class Widget extends MyObject
{
public $price;
public $quantity;
public function __construct($data = null)
{
$this->useTags = true;
$this->commentsEnabled = true;
parent::__construct($data, 'widgets');
$this->fullTextFields[] = 'name';
$this->fullTextFields[] = 'description';
$this->likeFields[] = 'name';
}
public function getPagesXml()
{
$xml = parent::getPagesXml();
$xml .= <<
XML;
return $xml;
}
public function initComponentsPage()
{
#$this->doCachePage = true;
parent::initViewPage();
$this->kids = $this->getComponents(true);
}
public function drawComponentsPage()
{
if (count($this->kids))
{
?>
Part
Unit Price
Total
foreach ($this->kids AS $kid): ?>
$total = $kid->total(); ?>
$all += $total; ?>
= $kid->getName(true)?>
$price = $kid->price(); ?>
if ($price && $kid->quantity): ?>
= $kid->quantity ?> @ = $price ?>
else: ?>
= $kid->getLink(".addsupplier?id=$kid->id", "add one")?>
endif ?>
= $total ?>
endforeach ?>
Total:
=$all?>
}
else
echo 'No components needed.
';
}
public function initUniquePartsPage()
{
#$this->doCachePage = true;
if ($this->params('type') == 'json')
parent::initJSONPage();
else
parent::initViewPage();
$this->parts = array();
$this->determineUniqueParts($this->parts);
}
public function determineUniqueParts(&$parts)
{
if ($this->isRawPart())
$this->addUnique($parts);
$kids = $this->getComponents();
if (count($kids))
foreach ($kids AS $kid){
$kid->determineUniqueParts($parts);
}
}
public function isRawPart(){
$sup = $this->getSuppliers();
if (count($sup)){
$this->suppliers = $sup;
return true;
}
}
public function addUnique(&$parts)
{
if(!$parts[$this->id])
$parts[$this->id] = &$this;
$parts[$this->id]->tot_quantity += $this->quantity;
}
public function drawUniquePartsPage()
{
$data = array();
foreach ($this->parts AS $part){
$data[$part->id] = $part->tot_quantity;
}
arsort($data);
foreach ($data as $key => $qty)
$names[$key] = $this->parts[$key]->getName();
asort($names);
if ($this->params('type') == 'json')
echo JSON::encode($data);
else
{
?>
Qty
Part
Links
foreach ($names AS $key => $name){
$qty = $data[$key];
echo "
$qty
" . $this->parts[$key]->getName(false) . "
Wiki - " . $this->parts[$key]->getLink(".view?id=$this->id", "Parts DB") . "
";
}
echo "" . count($data) . " Unique Parts ";
echo "" . array_sum($data) . " Total Parts ";
echo "
";
$form = $this->createGeoSupplierForm();
$form->drawIfNeeded();
}
}
public function createGeoSupplierForm()
{
$form = new Form();
$form->action = "http://" . $_SERVER['HTTP_HOST'] . $this->getUrl(".bomsuppliers?id=$this->id&bjtemplate=blank");
$form->add('CountryField', 'country', array(
'required' => true,
'title' => 'Find Suppliers in: '
));
$form->addSubmit('Go!');
return $form;
}
public function initBOMSuppliersPage()
{
parent::initViewPage();
$this->parts = array();
$this->determineUniqueParts($this->parts);
$this->pageTitle = $_POST['country'][0] . " Suppliers for " . $this->getName();
}
public function drawBOMSuppliersPage()
{
$data = array();
foreach ($this->parts AS $part){
$data[$part->id] = $part->tot_quantity;
}
arsort($data);
foreach ($data as $key => $qty)
$names[$key] = $this->parts[$key]->getName();
asort($names);
?>
foreach ($names AS $key => $name){
$qty = $data[$key];
echo "
$qty
" . $this->parts[$key]->getName() . "
Wiki - " . $this->parts[$key]->getLink(".view?id=$this->id", "Parts DB") . "
";
?>
}
echo " Unique Parts:" . count($data) . " Total Parts:" . array_sum($data) . " ";
echo "
";
}
public function initBillofMaterialsPage()
{
parent::initViewPage();
$this->needsJs("/js/dtree/dtree.js");
$this->needsCSS("/js/dtree/dtree.css");
$this->pageTitle = "Bill of Materials - " . $this->getName();
}
public function drawBillofMaterialsPage()
{
?>
Welcome, this page is where you can generate a bill of materials for any component in the project.
To make this as easy and interactive as possible, on this page you'll be able to choose from a variety of
options to create your parts list. Then you will be able to print it for future reference.
Directions:
Select Desired Parts (some parts have alternative parts that may be cheaper / easier to aquire for you)
Select Country (some suppliers only ship to certain countries or are cheaper for a certain country)
Select Suppliers (you will save money by going through fewer suppliers)
Generate List (we will then generate you a parts list which you can print off or save)
Loading...
}
public function total()
{
return $this->quantity * $this->price();
}
public function price()
{
$rs = dbQuery("
SELECT sp.id, s.name
FROM supplier_parts sp
INNER JOIN suppliers s
ON sp.supplier_id = s.id
WHERE sp.widget_id = '$this->id'
ORDER BY sp.price ASC
LIMIT 1");
$ar = mysql_fetch_assoc($rs);
$ob = new SupplierPart($ar['id']);
$ob->supplier = $ar['name'];
if ($ob->price)
return $ob->price;
else
{
$kids = $this->getComponents();
if (count($kids)){
foreach ($kids AS $kid)
$total += $kid->price() * $kid->quantity;
return $total;
}
else
return null;
}
}
public function getBestSuppliers()
{
}
public function getSuppliers()
{
$om = new SupplierParts();
return $om->search(array(
"widget_id" => $this->id
));
}
public function getAlternatives()
{
$om = new Widgets();
return $om->search(array(
"alternative" => $this->id
));
}
public function getComponents($full = false)
{
$rs = dbQuery("
SELECT w2w.quantity, w2w.unit, w.*
FROM widgets w
INNER JOIN widgets_to_widgets w2w
ON w.id = w2w.child_id
WHERE w2w.parent_id = '$this->id'
ORDER BY w.name
");
while ($ar = mysql_fetch_assoc($rs))
{
$ob = new Widget($ar['id']);
$ob->quantity = $ar['quantity'];
$ob->unit = $ar['unit'];
if ($full)
$ob->kids = $ob->getComponents($full);
$kids[] = $ob;
}
return $kids;
}
public function delete()
{
dbExecute("
DELETE FROM widgets_to_widgets
WHERE parent_id = '$this->id' OR child_id = '$this->id'
");
dbExecute("
DELETE FROM widgets_to_alternatives
WHERE widget_id = '$this->id' OR alternative_id = '$this->id'
");
$steps = new Steps();
$rs = $steps->search(array(
'widget_id' => $this->id
));
foreach ($rs As $ob)
$ob->delete();
parent::delete();
}
public function initPublishPage()
{
parent::initEditPage();
$this->pageTitle = 'Publish Widget - ' . $this->getName();
}
public function initSetQtyPage()
{
parent::initEditPage();
$this->setTemplate(new BlankTemplate());
}
public function drawSetQtyPage()
{
$qty = $this->params("qty");
$unit = $this->params("unit");
$parent_id = $this->id;
$child_id = $this->params('part_id');
dbQuery("
UPDATE widgets_to_widgets SET
quantity = '$qty',
unit = '$unit'
WHERE parent_id = '$parent_id'
AND child_id = '$child_id'
");
echo $qty;
}
public function drawPublishPage()
{
$this->publish();
echo "You widget '" . $this->getName(true) . "' has been published.";
}
public function publish()
{
$this->is_published = true;
$this->save();
$kids = $this->getComponents(false);
if (count($kids)){
foreach ($kids AS $kid){
$kid->publish();
}
}
}
public function initEditStepsPage()
{
parent::initEditPage();
$this->pageTitle = 'Edit Steps - ' . $this->getName();
}
public function drawEditStepsPage()
{
$links[] = $this->getLink(".view?id=$this->id", "Back to " . $this->getName());
$links[] = $this->getLink("step.edit?widget_id=$this->id", "Add New Step");
$this->drawPageNavigation($links);
echo "Click name and drag to re-order steps. The first step image will be the widget image. ";
$steps = new Steps();
$rs = $steps->search(array(
'widget_id' => $this->id
));
if (count($rs))
{
?>
foreach ($rs AS $ob)
{
echo "id\">";
echo $ob->getName(false);
echo " " . $ob->getLink(".view?id=$ob->id", "view");
echo " " . $ob->getLink(".edit?id=$ob->id", "edit");
echo " " . $ob->getLink(".editimages?id=$ob->id", "images");
echo " " . $ob->getLink(".delete?id=$ob->id", "delete");
echo " ";
}
?>
}
else
echo "No Steps Found.
";
}
public function initEditPartsPage()
{
parent::initEditPage();
$this->pageTitle = 'Edit Parts - ' . $this->getName();
}
public function drawEditPartsPage()
{
$links[] = $this->getLink(".view?id=$this->id", "Back to " . $this->getName());
$links[] = $this->getLink(".addpart?id=$this->id&type=child", "Add Component");
$links[] = $this->getLink(".addsupplier?id=$this->id", "Add Supplier");
$links[] = $this->getLink(".addpart?id=$this->id&type=alternative", "Add Alternative Part");
$this->drawPageNavigation($links);
$rs = $this->getComponents();
echo "
Child Parts ";
if (count($rs))
{
?>
}
else
echo "No Parts Found. ";
echo "
";
$rs = $this->getAlternatives();
echo "
Alternative Parts ";
if (count($rs))
{
echo "";
foreach ($rs AS $ob)
{
echo "";
echo $ob->getName(false);
echo " ";
if ($ob->canView())
echo " " . $ob->getLink(".view?id=$ob->id", "view");
if ($ob->canEdit())
echo " " . $ob->getLink(".edit?id=$ob->id", "edit");
if ($this->canEdit())
echo " " . $ob->getLink(".removepart?id=$this->id&part_id=$ob->id&type=alternative", "remove");
echo " ";
}
echo "
";
}
else
echo "No Parts Found. ";
echo "";
}
public function initEditSuppliersPage()
{
parent::initEditPage();
$this->pageTitle = 'Edit Suppliers - ' . $this->getName();
}
public function drawEditSuppliersPage()
{
$links[] = $this->getLink(".view?id=$this->id", "Back to " . $this->getName());
$links[] = $this->getLink(".addsupplier?id=$this->id", "Add Supplier");
$links[] = $this->getLink(".addpart?id=$this->id&type=child", "Add Component");
$this->drawPageNavigation($links);
$parts = new SupplierParts();
$rs = $parts->search(array(
'widget_id' => $this->id
));
echo "
Suppliers ";
if (count($rs))
{
echo "";
foreach ($rs AS $ob)
{
$supplier = new Supplier($ob->supplier_id);
echo "";
echo $supplier->getName(false);
echo " ($ob->price)";
echo " ";
if ($ob->canView())
echo " " . $ob->getLink(".view?id=$ob->id", "view");
if ($ob->canEdit())
echo " " . $ob->getLink(".edit?id=$ob->id", "edit");
if ($this->canEdit())
echo " " . $ob->getLink(".delete?id=$ob->id", "remove");
echo " ";
}
echo "
";
}
else
echo "No Suppliers Found. ";
echo "";
}
public function initAddSupplierPage()
{
parent::initEditPage();
$this->pageTitle = 'Add Supplier to ' . $this->getName();
}
public function drawAddSupplierPage()
{
global $me;
$form = $this->createAddSupplierForm();
if ($form->isSubmitted())
{
$form->validate();
if (!$form->hasError())
{
$supplierId = (int)$form->getData('supplier_id');
//did we get the part?
if ($supplierId)
$supplier = new Supplier($supplierId);
//either create a new one, also double check its real.
if (!$supplierId || $supplier->name != $_POST['supplier_id_search'])
{
$newSupplier = true;
//set up our stuff
$supplier = new Supplier();
$supplier->name = dbEscape($_POST['supplier_id_search']);
$supplier->user_id = $me->id;
$supplier->add_date = date("Y-m-d H:i:s");
$supplier->edit_date = date("Y-m-d H:i:s");
$supplier->save();
}
//make sure we have a supplier id.
if ($supplier->id)
{
//create the part entry
$part = new SupplierPart();
$part->user_id = $me->id;
$part->supplier_id = $supplier->id;
$part->widget_id = $this->id;
$part->add_date = date("Y-m-d H:i:s");
$part->edit_date = date("Y-m-d H:i:s");
$part->price_date = date("Y-m-d H:i:s");
$part->price = $form->getData('price');
$part->detail_link = $form->getData('detail_link');
$part->approved = 1;
$part->save();
if ($newSupplier)
Util::redirect($supplier->getUrl(".edit?id=$supplier->id"));
else
Util ::redirect($this->getUrl(".editsuppliers?id=$this->id"));
}
else
throw new PageError("Something went wrong.");
}
}
$form->drawIfNeeded();
}
public function createAddSupplierForm()
{
$form = new Form();
$form->action = $this->getUrl(".addsupplier?id=$this->id");
$form->add('AutoCompleteIdField', 'supplier_id', array(
'width' => '85%',
'title' => 'Supplier Name',
'lookupUrl' => $this->getUrl("suppliers.search?output=autocomplete")
));
$form->add('TextField', 'detail_link', array(
'title' => 'Detail / Buy URL',
'width' => '85%'
));
$form->add('TextField', 'price', array(
));
$form->addSubmit('Add Supplier');
return $form;
}
public function initAddPartPage()
{
parent::initEditPage();
$this->pageTitle = 'Add Part to ' . $this->getName();
}
public function drawAddPartPage()
{
global $me;
$form = $this->createAddPartForm($this->params('type'));
if ($form->isSubmitted())
{
$form->validate();
$partId = (int)$form->getData('part_id');
//did we get the part?
if ($partId)
$part = new Widget($partId);
//nope, create it.
else
{
//set up our stuff
$part = new Widget();
$part->user_id = $me->id;
$part->name = dbEscape($_POST['part_id_search']);
$part->add_date = date("Y-m-d H:i:s");
$part->edit_date = date("Y-m-d H:i:s");
$part->save();
}
if ($part->id == $this->id)
$form->setError('part', "The widget cannot have a part that is itself");
if (!$form->hasError())
{
//make sure we have a part id.
if ($part->id)
{
if ($this->params('type') == 'child')
$this->addChildPart($part->id, $form->getData('quantity'), $form->getData('units'), $form->getData('notes'));
else
$this->addAlternativePart($part->id, $form->getData('notes'));
Util::redirect($this->getUrl(".editparts?id=$this->id"));
}
else
throw new PageError("Something went wrong.");
}
}
$form->drawIfNeeded();
}
public function createAddPartForm($type)
{
$form = new Form();
$form->action = $this->getUrl(".addpart?id=$this->id&type=$type");
$form->add('AutoCompleteIdField', 'part_id', array(
'width' => '100%',
'title' => 'Part Name',
'lookupUrl' => $this->getUrl("widgets.search?output=autocomplete")
));
if ($type == 'child')
{
$form->add('TextField', 'quantity', array(
'required' => true,
'width' => '40px'
));
$form->add('TextField', 'units', array(
'width' => '100px',
'title' => 'Units (item, cc, mm, oz, etc.)'
));
$form->add('TextareaField', 'notes', array(
'width' => '100%',
'height' => '80px',
'title' => 'Notes'
));
$form->addSubmit('Add Child Part');
}
else
{
$form->add('TextareaField', 'notes', array(
'width' => '100%',
'height' => '80px',
'title' => 'Notes'
));
$form->addSubmit('Add Alternative Part');
}
return $form;
}
public function initRemovePartPage()
{
parent::initEditPage();
$this->pageTitle = 'Remove Part From ' . $this->getName();
}
public function drawRemovePartPage()
{
if ($this->params('type') == 'child')
$this->removeChildPart($this->params('part_id'));
else
$this->removeAlternativePart($this->params('part_id'));
Util::redirect($this->getUrl(".editparts?id=$this->id"));
}
public function addChildPart($id, $quantity, $unit, $notes = '')
{
$quantity = (int)$quantity;
$unit = dbEscape($unit);
$notes = dbEscape($notes);
dbExecute("
INSERT INTO widgets_to_widgets
(parent_id, child_id, quantity, unit, notes)
VALUES
('$this->id', '$id', '$quantity', '$unit', '$notes')
");
}
public function addAlternativePart($id, $notes = '')
{
$notes = dbEscape($notes);
dbExecute("
INSERT INTO widgets_to_alternatives
(widget_id, alternative_id, notes)
VALUES
('$this->id', '$id', '$notes')
");
}
public function removeChildPart($id)
{
dbExecute("
DELETE FROM widgets_to_widgets
WHERE parent_id = '$this->id'
AND child_id = '$id'
");
}
public function removeAlternativePart($id)
{
dbExecute("
DELETE FROM widgets_to_alternatives
WHERE widget_id = '$this->id'
AND alternative_id = '$id'
");
}
public function getCreateFieldsArray()
{
$data = parent::getCreateFieldsArray();
$data['name'] = "name varchar(255) default '' not null";
$data['description'] = "description text default '' not null";
$data['image_id'] = 'image_id int(11) default 0 not null';
$data['is_published'] = 'is_published tinyint(1) default 0 not null';
$data['website'] = "website varchar(255) default '' not null";
$data['svn_repository'] = "svn_repository varchar(255) default '' not null";
return $data;
}
public function getCreateIndexesArray()
{
$data = parent::getCreateIndexesArray();
$data['image_id'] = 'key(image_id)';
return $data;
}
public function editFormAddFields($form)
{
global $me;
if ($this->id)
$form->add('CheckboxField', 'is_published', array('label' => 'Is Published?'));
if ($me->isAdmin())
$form->add('CheckBoxField', 'featured', array('label' => 'Is Featured?'));
$form->add('CheckboxField', 'can_be_fabricated', array('label' => 'Can it be fabricated?'));
$form->add('TextField', 'name', array(
'required' => true,
'width' => '100%',
));
$form->add('TextAreaField', 'description', array(
'width' => '100%',
'height' => '150px'
));
$form->add('TextField', 'website', array(
'width' => '100%',
));
$form->add('TextField', 'svn_repository', array(
'width' => '100%',
'title' => 'SVN Url'
));
$form->add('TextField', 'flickr_set_id', array(
'width' => '100%',
'title' => 'Flickr SetID or Set URL'
));
$form->add('TextField', 'video_link', array(
'width' => '100%',
'title' => 'Vimeo video URL / ID (YouTube works too)'
));
$this->tags->addTagFields($form);
if ($this->id)
$form->addSubmit('Save Widget');
else
$form->addSubmit('Add Widget');
}
public function getName($link = false)
{
return parent::getName($link, $this->name);
}
public function initViewPage()
{
parent::initViewPage();
if (!$this->isPublished())
$this->addStatus("This widget is not published. getUrl(".publish?id=$this->id") . "\"
onclick=\"return Widget.publish($this->id)\">Publish Now! "
);
ob_start();
?>
Meta Data
Creator: =$this->creator->getName(true);?>
Added: =Time::formatRelative($this->add_date, false);?>
Updated: =Time::formatRelative($this->edit_date, false);?>
Links
if ($this->website)
echo "website\">Part Homepage ";
if ($this->svn_repository)
echo "svn_repository\">SVN Repository ";
echo "";
?> -->
//show what stuff we're part of...
$this->parts = new Widgets();
$rs = $this->parts->search(array(
'child_id' => $this->id
));
if (count($rs))
{
echo "
I am part of: ";
foreach ($rs AS $ob)
$data[] = $ob->getName(true);
echo implode(", ", $data);
echo "";
}
//draw my tags
$this->tagFactory();
$tags = $this->tags->getTags();
if (count($tags))
echo "
Tags (" . $this->tags->getLink(".main", "popular") . ") " . $this->tags->getTagList($tags) . "";
$this->SidebarData = ob_get_contents();
ob_end_clean();
}
public function getWikiUrl()
{
if ($this->wiki_url == '')
return "http://objects.reprap.org/mediawiki/index.php/" . preg_replace('/\W/', '', $this->getName());
else
return $this->wiki_url;
}
public function drawViewPage()
{
if ($this->canEdit())
{
$links[] = $this->getLink(".edit?id=$this->id", "Edit Part");
$links[] = $this->getLink(".editparts?id=$this->id", "Edit Components");
$links[] = $this->getLink(".editsuppliers?id=$this->id", "Edit Suppliers");
$links[] = $this->getLink(".delete?id=$this->id", "Delete Part");
}
if (count($links))
$this->drawPageNavigation($links);
$wiki = "Wiki ";
$comps = $this->getComponents();
$suppliers = $this->getSuppliers();
$alts = $this->getAlternatives();
?>
=$this->getLink(".uniqueparts?id=$this->id", "View Bill of Materials (Parts List)")?>
=Linkify::bbcode($this->description)?>
}
public function getMediaEmbedMarkup()
{
if (preg_match("/vimeo\.com/", $this->media_link))
return $this->getVimeoEmbed($this->media_link);
else if (preg_match("/youtube\.com/", $this->media_link))
return $this->getYouTubeEmbed($this->media_link);
else if (preg_match("/flickr\.com/", $this->media_link))
return $this->getFlickrEmbed($this->media_link);
}
public function getFlickrEmbed($link){
if (preg_match("/\d{4,}/", $link, $matches))
return "";
}
public function getVimeoEmbed($link){
if (preg_match("/[0-9]{3,}/", $link, $matches))
return " ";
}
public function getYouTubeEmbed($link){
if (preg_match("/[0-9a-zA-Z]{3,}$/", $link, $matches))
return ' ';
}
public function drawRow()
{
?>
=$this->getName(true)?>
if (!$this->isPublished()): ?>
-- Not Published!
endif ?>
}
public function initJSONPage()
{
$this->doCachePage = true;
parent::initJSONPage();
}
public function initXMLPage()
{
$this->doCachePage = true;
parent::initXMLPage();
}
public function initPHPPage()
{
$this->doCachePage = true;
parent::initPHPPage();
}
public function isPublished()
{
return (bool)$this->is_published;
}
public function getPublicData()
{
$data = parent::getPublicData();
//load some basic stuff.
$data['name'] = $this->getName();
$data['description'] = Linkify::bbcode($this->description);
$data['is_published'] = $this->is_published;
$data['website'] = $this->website;
$datap['svn_repository'] = $this->svn_repository;
$data['can_be_fabricated'] = $this->can_be_fabricated;
$data['featured'] = $this->featured;
$data['media_link'] = $this->media_link;
$data['media_embed'] = $this->getMediaEmbedMarkup();
$kids = $this->getComponents(false);
if (count($kids)){
foreach ($kids AS $kid)
$data['components'][] = $kid->getPublicData();
}
$kids = $this->getSuppliers(false);
if (count($kids)){
foreach ($kids AS $kid)
$data['suppliers'][] = $kid->getPublicData();
}
/*
$alts = $this->getAlternatives();
if (count($alts)){
foreach ($alts AS $alt){
$data['alternatives'][] = $alt->getPublicData();
}
}
*/
return $data;
}
public function getRssItem()
{
$item = parent::getRssItem();
$item->title = $this->getName(true);
$item->description = Linkify::bbcode($this->description);
return $item;
}
public function getCreateTableSql()
{
$sql = parent::getCreateTableSql();
$sql .= "
CREATE TABLE widgets_to_widgets
(
parent_id int(11) default 0 not null,
child_id int(11) default 0 not null,
quantity int(11) default 0 not null,
key(parent_id),
key(child_id)
);
CREATE TABLE widgets_to_alternatives
(
widget_id int(11) default 0 not null,
alternative_id int(11) default 0 not null,
key(widget_id),
key(alternative_id)
);
";
return $sql;
}
}
class WidgetThread extends BaseThread
{
function __construct($contentId = null)
{
parent::__construct($contentId, 'Widget');
}
}
class WidgetComment Extends BaseComment
{
function __construct($data = null)
{
parent::__construct($data, 'widget');
}
}
?>