/** * Tests whether getID never produces a notice. * * @return void */ public function testGetIDShouldNeverPrintNotice() { set_error_handler(function ($err, $errStr) { die('>>>>FAIL :' . $err . ' ' . $errStr); }); $bean = new RedBean_OODBBean(); $bean->getID(); restore_error_handler(); pass(); }
/** * Makes a copy of a bean. This method makes a deep copy * of the bean.The copy will have the following features. * - All beans in own-lists will be duplicated as well * - All references to shared beans will be copied but not the shared beans themselves * - All references to parent objects (_id fields) will be copied but not the parents themselves * In most cases this is the desired scenario for copying beans. * This function uses a trail-array to prevent infinite recursion, if a recursive bean is found * (i.e. one that already has been processed) the ID of the bean will be returned. * This should not happen though. * * Note: * This function does a reflectional database query so it may be slow. * * @param RedBean_OODBBean $bean bean to be copied * @param array $trail for internal usage, pass array() * @param boolean $pid for internal usage * * @return array $copiedBean the duplicated bean */ protected function duplicate($bean, $trail = array(), $pid = false) { $type = $bean->getMeta('type'); $key = $type . $bean->getID(); if (isset($trail[$key])) { return $bean; } $trail[$key] = $bean; $copy = $this->redbean->dispense($type); $copy->import($bean->getProperties()); $copy->id = 0; $tables = $this->toolbox->getWriter()->getTables(); foreach ($tables as $table) { if (strpos($table, '_') !== false || $table == $type) { continue; } $owned = 'own' . ucfirst($table); $shared = 'shared' . ucfirst($table); if ($beans = $bean->{$owned}) { $copy->{$owned} = array(); foreach ($beans as $subBean) { array_push($copy->{$owned}, $this->duplicate($subBean, $trail, $pid)); } } $copy->setMeta('sys.shadow.' . $owned, null); if ($beans = $bean->{$shared}) { $copy->{$shared} = array(); foreach ($beans as $subBean) { array_push($copy->{$shared}, $subBean); } } $copy->setMeta('sys.shadow.' . $shared, null); } if ($pid) { $copy->id = $bean->id; } return $copy; }
/** * Generates a key from the bean type and its ID and determines if the bean * occurs in the trail, if not the bean will be added to the trail. * Returns TRUE if the bean occurs in the trail and FALSE otherwise. * * @param array $trail list of former beans * @param RedBean_OODBBean $bean currently selected bean * * @return boolean */ private function inTrailOrAdd(&$trail, RedBean_OODBBean $bean) { $type = $bean->getMeta('type'); $key = $type . $bean->getID(); if (isset($trail[$key])) { return TRUE; } $trail[$key] = $bean; return FALSE; }
public function areRelated(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2) { if (!$bean1->getID() || !$bean2->getID()) { return false; } $table = $this->getTable(array($bean1->getMeta("type"), $bean2->getMeta("type"))); $idfield1 = $this->writer->getIDField($bean1->getMeta("type")); $idfield2 = $this->writer->getIDField($bean2->getMeta("type")); $type = $bean1->getMeta("type"); if ($type == $bean2->getMeta("type")) { $type .= "2"; $cross = 1; } else { $cross = 0; } $property1 = $type . "_id"; $property2 = $bean2->getMeta("type") . "_id"; $value1 = (int) $bean1->{$idfield1}; $value2 = (int) $bean2->{$idfield2}; try { $rows = $this->writer->selectRecord($table, array($property1 => array($value1), $property2 => array($value2)), null); if ($cross) { $rows2 = $this->writer->selectRecord($table, array($property2 => array($value1), $property1 => array($value2)), null); $rows = array_merge($rows, $rows2); } } catch (RedBean_Exception_SQL $e) { if (!$this->writer->sqlStateIn($e->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_TABLE))) { throw $e; } return false; } return count($rows) > 0; }
/** * @see RedBean_DuplicationManager::dup * * @param RedBean_OODBBean $bean bean to be copied * @param array $trail trail to prevent infinite loops * @param boolean $pid preserve IDs * * @return array $copiedBean the duplicated bean */ protected function duplicate($bean, $trail = array(), $pid = false) { $type = $bean->getMeta('type'); $key = $type . $bean->getID(); if (isset($trail[$key])) { return $bean; } $trail[$key] = $bean; $copy = $this->redbean->dispense($type); $copy->importFrom($bean); $copy->id = 0; $tables = $this->tables; foreach ($tables as $table) { if (is_array($this->filters) && count($this->filters) && !in_array($table, $this->filters)) { continue; } if ($table == $type) { continue; } $owned = 'own' . ucfirst($table); $shared = 'shared' . ucfirst($table); if ($this->hasSharedList($type, $table)) { if ($beans = $bean->{$shared}) { $copy->{$shared} = array(); foreach ($beans as $subBean) { array_push($copy->{$shared}, $subBean); } } } elseif ($this->hasOwnList($type, $table)) { if ($beans = $bean->{$owned}) { $copy->{$owned} = array(); foreach ($beans as $subBean) { array_push($copy->{$owned}, $this->duplicate($subBean, $trail, $pid)); } } $copy->setMeta('sys.shadow.' . $owned, null); } $copy->setMeta('sys.shadow.' . $shared, null); } if ($pid) { $copy->id = $bean->id; } return $copy; }
public function exportBean(RedBean_OODBBean $bean) { $bid = $bean->getMeta('type') . '-' . $bean->getID(); if (isset($this->recurCheck[$bid])) { return null; } $this->recurCheck[$bid] = $bid; $export = $bean->export(); foreach ($export as $key => $value) { if (strpos($key, '_id') !== false) { $sub = str_replace('_id', '', $key); $subBean = $bean->{$sub}; if ($subBean) { $export[$sub] = $this->export($subBean, false); } } } $type = $bean->getMeta('type'); $linkField = $type . '_id'; foreach ($this->tables as $table => $cols) { if (strpos($table, '_') === false) { if (in_array($linkField, array_keys($cols))) { $field = 'own' . ucfirst($table); $export[$field] = self::export($bean->{$field}, false); } } } foreach ($this->tables as $table => $cols) { if (strpos($table, '_') !== false) { $parts = explode('_', $table); if (is_array($parts) && in_array($type, $parts)) { $other = $parts[0]; if ($other == $type) { $other = $parts[1]; } $field = 'shared' . ucfirst($other); $export[$field] = self::export($bean->{$field}, false); } } } return $export; }
/** * Exports a single bean * * @param RedBean_OODBBean $bean Bean to be exported * * @return array|NULL $array Array export of bean */ public function exportBean(RedBean_OODBBean $bean) { $bid = $bean->getMeta('type') . '-' . $bean->getID(); if (isset($this->recurCheck[$bid])) { return NULL; } $this->recurCheck[$bid] = $bid; $export = $bean->export(); foreach ($export as $key => $value) { $this->extractParentBean($export, $bean, $key, $value); } foreach ($this->tables as $table => $cols) { //get all ownProperties $this->extractOwnList($export, $bean, $table, $cols); } foreach ($this->tables as $table => $cols) { //get all sharedProperties $this->extractSharedList($export, $bean, $table); } return $export; }
/** * Stores a bean in the database. This function takes a * RedBean_OODBBean Bean Object $bean and stores it * in the database. If the database schema is not compatible * with this bean and RedBean runs in fluid mode the schema * will be altered to store the bean correctly. * If the database schema is not compatible with this bean and * RedBean runs in frozen mode it will throw an exception. * This function returns the primary key ID of the inserted * bean. * * @throws RedBean_Exception_Security $exception * @param RedBean_OODBBean $bean bean to store * * @return integer $newid */ public function store(RedBean_OODBBean $bean) { $processLists = false; foreach ($bean as $k => $v) { if (is_array($v) || is_object($v)) { $processLists = true; break; } } if (!$processLists && !$bean->getMeta('tainted')) { return $bean->getID(); } $this->signal("update", $bean); if ($processLists) { //Define groups $sharedAdditions = $sharedTrashcan = $sharedresidue = $sharedItems = array(); $ownAdditions = $ownTrashcan = $ownresidue = array(); $tmpCollectionStore = array(); $embeddedBeans = array(); foreach ($bean as $p => $v) { if ($v instanceof RedBean_OODBBean) { $embtype = $v->getMeta('type'); $idfield = $this->writer->getIDField($embtype); if (!$v->{$idfield} || $v->getMeta('tainted')) { $this->store($v); } $beanID = $v->{$idfield}; $linkField = $p . '_id'; $bean->{$linkField} = $beanID; $bean->setMeta('cast.' . $linkField, 'id'); $embeddedBeans[$linkField] = $v; $tmpCollectionStore[$p] = $bean->{$p}; $bean->removeProperty($p); } if (is_array($v)) { $originals = $bean->getMeta('sys.shadow.' . $p); if (!$originals) { $originals = array(); } if (strpos($p, 'own') === 0) { list($ownAdditions, $ownTrashcan, $ownresidue) = $this->processGroups($originals, $v, $ownAdditions, $ownTrashcan, $ownresidue); $bean->removeProperty($p); } elseif (strpos($p, 'shared') === 0) { list($sharedAdditions, $sharedTrashcan, $sharedresidue) = $this->processGroups($originals, $v, $sharedAdditions, $sharedTrashcan, $sharedresidue); $bean->removeProperty($p); } else { } } } } if (!$this->isFrozen) { $this->check($bean); } //what table does it want $table = $bean->getMeta("type"); $idfield = $this->writer->getIDField($table); if ($bean->getMeta('tainted')) { //Does table exist? If not, create if (!$this->isFrozen && !$this->tableExists($table)) { $this->writer->createTable($table); $bean->setMeta("buildreport.flags.created", true); } if (!$this->isFrozen) { $columns = $this->writer->getColumns($table); } //does the table fit? $insertvalues = array(); $insertcolumns = array(); $updatevalues = array(); foreach ($bean as $p => $v) { if ($p != $idfield) { if (!$this->isFrozen) { //Does the user want to specify the type? if ($bean->getMeta("cast.{$p}", -1) !== -1) { $cast = $bean->getMeta("cast.{$p}"); if ($cast == "string") { $typeno = $this->writer->scanType("STRING"); } elseif ($cast == "id") { $typeno = $this->writer->getTypeForID(); } else { throw new RedBean_Exception("Invalid Cast"); } } else { //What kind of property are we dealing with? $typeno = $this->writer->scanType($v); } //Is this property represented in the table? if (isset($columns[$p])) { //yes it is, does it still fit? $sqlt = $this->writer->code($columns[$p]); if ($typeno > $sqlt) { //no, we have to widen the database column type $this->writer->widenColumn($table, $p, $typeno); $bean->setMeta("buildreport.flags.widen", true); } } else { //no it is not $this->writer->addColumn($table, $p, $typeno); $bean->setMeta("buildreport.flags.addcolumn", true); //@todo: move build commands here... more practical $this->processBuildCommands($table, $p, $bean); } } //Okay, now we are sure that the property value will fit $insertvalues[] = $v; $insertcolumns[] = $p; $updatevalues[] = array("property" => $p, "value" => $v); } } if (!$this->isFrozen && ($uniques = $bean->getMeta("buildcommand.unique"))) { foreach ($uniques as $unique) { $this->writer->addUniqueIndex($table, $unique); } } $rs = $this->writer->updateRecord($table, $updatevalues, $bean->{$idfield}); $bean->{$idfield} = $rs; $bean->setMeta("tainted", false); } if ($processLists) { foreach ($embeddedBeans as $linkField => $embeddedBean) { if (!$this->isFrozen) { $this->writer->addIndex($bean->getMeta('type'), 'index_foreignkey_' . $embeddedBean->getMeta('type'), $linkField); $this->writer->addFK($bean->getMeta('type'), $embeddedBean->getMeta('type'), $linkField, $this->writer->getIDField($embeddedBean->getMeta('type'))); } } $myFieldLink = $bean->getMeta('type') . '_id'; //Handle related beans foreach ($ownTrashcan as $trash) { if ($trash instanceof RedBean_OODBBean) { $trash->{$myFieldLink} = null; $this->store($trash); } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } foreach ($ownAdditions as $addition) { if ($addition instanceof RedBean_OODBBean) { $addition->{$myFieldLink} = $bean->{$idfield}; $addition->setMeta('cast.' . $myFieldLink, 'id'); $this->store($addition); if (!$this->isFrozen) { $this->writer->addIndex($addition->getMeta('type'), 'index_foreignkey_' . $bean->getMeta('type'), $myFieldLink); $this->writer->addFK($addition->getMeta('type'), $bean->getMeta('type'), $myFieldLink, $idfield); } } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } foreach ($ownresidue as $residue) { if ($residue instanceof RedBean_OODBBean) { if ($residue->getMeta('tainted')) { $this->store($residue); } } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } foreach ($sharedTrashcan as $trash) { if ($trash instanceof RedBean_OODBBean) { $this->assocManager->unassociate($trash, $bean); } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } foreach ($sharedAdditions as $addition) { if ($addition instanceof RedBean_OODBBean) { $this->assocManager->associate($addition, $bean); } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } foreach ($sharedresidue as $residue) { if ($residue instanceof RedBean_OODBBean) { $this->store($residue); } else { throw new RedBean_Exception_Security('Array may only contain RedBean_OODBBeans'); } } } $this->signal("after_update", $bean); return (int) $bean->{$idfield}; }