/** * Throws an exception if information in the bean has been changed * by another process or bean. * @param string $event * @param RedBean_OODBBean $item */ public function onEvent($event, $item) { $id = $item->id; if (!(int) $id) { $event = "open"; } $type = $item->getMeta("type"); if ($event == "open") { if (isset($this->stash[$id])) { $insertid = $this->stash[$id]; unset($this->stash[$id]); return $insertid; } $insertid = $this->writer->insertRecord("__log", array("action", "tbl", "itemid"), array(array(1, $type, $id))); $item->setMeta("opened", $insertid); //echo "<br>opened: ".print_r($item, 1); } if ($event == "update" || $event == "delete") { if ($item->getMeta("opened")) { $oldid = $item->getMeta("opened"); } else { $oldid = 0; } $newid = $this->writer->checkChanges($type, $id, $oldid); $item->setMeta("opened", $newid); } }
/** * Ensures that given an association between * $bean1 and $bean2, * if one of them gets trashed the association will be * automatically removed. * @param RedBean_OODBBean $bean1 * @param RedBean_OODBBean $bean2 * @return boolean $addedFKS */ public static function addConstraint(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, $dontCache = false) { //Fetch the toolbox $toolbox = RedBean_Setup::getToolBox(); RedBean_CompatManager::scanDirect($toolbox, array(RedBean_CompatManager::C_SYSTEM_MYSQL => "5")); //Create an association manager $association = new RedBean_AssociationManager($toolbox); $writer = $toolbox->getWriter(); $oodb = $toolbox->getRedBean(); $adapter = $toolbox->getDatabaseAdapter(); //Frozen? Then we may not alter the schema! if ($oodb->isFrozen()) { return false; } //$adapter->getDatabase()->setDebugMode(1); $table1 = $bean1->getMeta("type"); $table2 = $bean2->getMeta("type"); $table = $association->getTable(array($table1, $table2)); $idfield1 = $writer->getIDField($bean1->getMeta("type")); $idfield2 = $writer->getIDField($bean2->getMeta("type")); $bean = $oodb->dispense($table); $property1 = $bean1->getMeta("type") . "_id"; $property2 = $bean2->getMeta("type") . "_id"; if ($property1 == $property2) { $property2 = $bean2->getMeta("type") . "2_id"; } $table = $adapter->escape($table); $table1 = $adapter->escape($table1); $table2 = $adapter->escape($table2); $property1 = $adapter->escape($property1); $property2 = $adapter->escape($property2); //In Cache? Then we dont need to bother if (isset(self::$fkcache[$table])) { return false; } $db = $adapter->getCell("select database()"); $fks = $adapter->getCell("\n\t\t\tSELECT count(*)\n\t\t\tFROM information_schema.KEY_COLUMN_USAGE\n\t\t\tWHERE TABLE_SCHEMA ='{$db}' AND TABLE_NAME ='{$table}' AND\n\t\t\tCONSTRAINT_NAME <>'PRIMARY' AND REFERENCED_TABLE_NAME is not null\n\t\t"); //already foreign keys added in this association table if ($fks > 0) { return false; } //add the table to the cache, so we dont have to fire the fk query all the time. if (!$dontCache) { self::$fkcache[$table] = true; } $columns = $writer->getColumns($table); if ($writer->code($columns[$property1]) !== RedBean_QueryWriter_MySQL::C_DATATYPE_UINT32) { $writer->widenColumn($table, $property1, RedBean_QueryWriter_MySQL::C_DATATYPE_UINT32); } if ($writer->code($columns[$property2]) !== RedBean_QueryWriter_MySQL::C_DATATYPE_UINT32) { $writer->widenColumn($table, $property2, RedBean_QueryWriter_MySQL::C_DATATYPE_UINT32); } $sql = "\n\t\t\tALTER TABLE " . $writer->noKW($table) . "\n\t\t\tADD FOREIGN KEY({$property1}) references {$table1}(id) ON DELETE CASCADE;\n\n\t\t"; $adapter->exec($sql); $sql = "\n\t\t\tALTER TABLE " . $writer->noKW($table) . "\n\t\t\tADD FOREIGN KEY({$property2}) references {$table2}(id) ON DELETE CASCADE\n\t\t"; $adapter->exec($sql); return true; }
/** * * @param RedBean_OODBBean $parent * @return array $childObjects */ public function children(RedBean_OODBBean $parent) { try { $ids = $this->adapter->getCol("SELECT id FROM\n\t\t\t`" . $parent->getMeta("type") . "`\n\t\t\tWHERE `" . $this->property . "` = " . intval($parent->id) . "\n\t\t"); } catch (RedBean_Exception_SQL $e) { return array(); } return $this->oodb->batch($parent->getMeta("type"), $ids); }
/** * Returns all the nodes that have been attached to the specified * parent node. * @param RedBean_OODBBean $parent * @return array $childObjects */ public function children(RedBean_OODBBean $parent) { $idfield = $this->writer->getIDField($parent->getMeta("type")); try { $ids = $this->writer->selectByCrit($idfield, $parent->getMeta("type"), $this->property, intval($parent->{$idfield})); } catch (RedBean_Exception_SQL $e) { return array(); } return $this->oodb->batch($parent->getMeta("type"), $ids); }
public static function getKeys(RedBean_OODBBean $bean, $typeName) { $fieldName = self::getLinkField($typeName); $id = (int) $bean->{$fieldName}; $ids = R::getCol("select id from {$typeName} where " . $bean->getMeta("type") . "_id" . " = {$bean->id}"); return $ids; }
/** * Does an optimization cycle for each UPDATE event * @param string $event * @param RedBean_OODBBean $bean */ public function onEvent($event, $bean) { try { if ($event == "update") { $arr = $bean->export(); unset($arr["id"]); if (count($arr) == 0) { return; } $table = $this->adapter->escape($bean->getMeta("type")); $columns = array_keys($arr); $column = $this->adapter->escape($columns[array_rand($columns)]); $value = $arr[$column]; $type = $this->writer->scanType($value); $fields = $this->writer->getColumns($table); if (!in_array($column, array_keys($fields))) { return; } $typeInField = $this->writer->code($fields[$column]); if ($type < $typeInField) { $type = $this->writer->typeno_sqltype[$type]; $this->adapter->exec("alter table `{$table}` add __test " . $type); $this->adapter->exec("update `{$table}` set __test=`{$column}`"); $diff = $this->adapter->getCell("select\n\t\t\t\t\t\t\tcount(*) as df from `{$table}` where\n\t\t\t\t\t\t\tstrcmp(`{$column}`,__test) != 0"); if (!$diff) { $this->adapter->exec("alter table `{$table}` change `{$column}` `{$column}` " . $type); } $this->adapter->exec("alter table `{$table}` drop __test"); } } } catch (RedBean_Exception_SQL $e) { //optimizer might make mistakes, dont care.. } }
public static function getKeys(RedBean_OODBBean $bean, $typeName, $name = null) { $fieldName = self::getLinkField($typeName, $name); $id = (int) $bean->{$fieldName}; $columnPrefix = self::resolveColumnPrefix($name); $columnName = $columnPrefix . $bean->getMeta("type") . '_id'; $ids = ZurmoRedBean::getCol("select id from {$typeName} where " . $columnName . " = {$bean->id}"); return $ids; }
/** * Checks whether a bean is valid * @param RedBean_OODBBean $bean */ public function check(RedBean_OODBBean $bean) { //Is all meta information present? if (!isset($bean->id) || !$bean->getMeta("type")) { throw new RedBean_Exception_Security("Bean has incomplete Meta Information"); } //Pattern of allowed characters $pattern = '/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]/'; //Does the type contain invalid characters? if (preg_match($pattern, $bean->getMeta("type"))) { throw new RedBean_Exception_Security("Bean Type is invalid"); } //Are the properties and values valid? foreach ($bean as $prop => $value) { if (is_array($value) || is_object($value) || strlen($prop) < 1 || preg_match($pattern, $prop)) { throw new RedBean_Exception_Security("Invalid Bean: property {$prop} "); } } }
/** * Does an optimization cycle for each UPDATE event. * @param string $event * @param RedBean_OODBBean $bean */ public function onEvent($event, $bean) { try { if ($event == "update") { $arr = $bean->export(); unset($arr["id"]); if (count($arr) == 0) { return; } $table = $this->adapter->escape($bean->getMeta("type")); $columns = array_keys($arr); //Select a random column for optimization. $column = $this->adapter->escape($columns[array_rand($columns)]); $value = $arr[$column]; $type = $this->writer->scanType($value); $fields = $this->writer->getColumns($table); if (!in_array($column, array_keys($fields))) { return; } $typeInField = $this->writer->code($fields[$column]); //Is the type too wide? if ($type < $typeInField) { try { @$this->adapter->exec("alter table " . $this->writer->noKW($table) . " drop __test"); } catch (Exception $e) { } //Try to re-fit the entire column; by testing it. $type = $this->writer->typeno_sqltype[$type]; //Add a test column. @$this->adapter->exec("alter table " . $this->writer->noKW($table) . " add __test " . $type); //Copy the values and see if there are differences. @$this->adapter->exec("update " . $this->writer->noKW($table) . " set __test=" . $this->writer->noKW($column) . ""); $rows = $this->adapter->get("select " . $this->writer->noKW($column) . " as a, __test as b from " . $this->writer->noKW($table)); $diff = 0; foreach ($rows as $row) { $diff += $row["a"] != $row["b"]; } if (!$diff) { //No differences; shrink column. @$this->adapter->exec("alter table " . $this->writer->noKW($table) . " change " . $this->writer->noKW($column) . " " . $this->writer->noKW($column) . " " . $type); } //Throw away test column; we don't need it anymore! @$this->adapter->exec("alter table " . $this->writer->noKW($table) . " drop __test"); } else { $this->MySQLSpecificColumns($table, $column, $fields[$column], $value); } } } catch (RedBean_Exception_SQL $e) { //optimizer might make mistakes, don't care. //echo $e->getMessage()."<br>"; } }
/** * Test meta data methods. * * @return void */ public function testMetaData() { testpack('Test meta data'); $bean = new RedBean_OODBBean(); $bean->setMeta("this.is.a.custom.metaproperty", "yes"); asrt($bean->getMeta("this.is.a.custom.metaproperty"), "yes"); asrt($bean->getMeta("nonexistant"), NULL); asrt($bean->getMeta("nonexistant", "abc"), "abc"); asrt($bean->getMeta("nonexistant.nested"), NULL); asrt($bean->getMeta("nonexistant,nested", "abc"), "abc"); $bean->setMeta("test.two", "second"); asrt($bean->getMeta("test.two"), "second"); $bean->setMeta("another.little.property", "yes"); asrt($bean->getMeta("another.little.property"), "yes"); asrt($bean->getMeta("test.two"), "second"); // Copy Metadata $bean = new RedBean_OODBBean(); $bean->setMeta("meta.meta", "123"); $bean2 = new RedBean_OODBBean(); asrt($bean2->getMeta("meta.meta"), NULL); $bean2->copyMetaFrom($bean); asrt($bean2->getMeta("meta.meta"), "123"); }
/** * * @param RedBean_OODBBean $parent * @return array $childObjects */ public function children(RedBean_OODBBean $parent) { $idfield = $this->writer->getIDField($parent->getMeta("type")); try { /* $ids = $this->adapter->getCol("SELECT `".$idfield."` FROM `".$parent->getMeta("type")."` WHERE `".$this->property."` = ".intval( $parent->$idfield )." "); */ /* $ids = $this->adapter->getCol($this->writer->buildSimpleQuery( "select",array($idfield),$parent->getMeta("type"), array("name"=>$this->property, "value"=>intval($parent->$idfield), "operator"=>"=","structure"=>"") )); */ $ids = $this->writer->selectByCrit($idfield, $parent->getMeta("type"), $this->property, intval($parent->{$idfield})); } catch (RedBean_Exception_SQL $e) { return array(); } return $this->oodb->batch($parent->getMeta("type"), $ids); }
/** * Loads the Bean internally * @param integer $id */ public function find($id) { $this->bean = $this->redbean->load($this->bean->getMeta("type"), (int) $id); }
/** * Removes a bean from the database. * This function will remove the specified RedBean_OODBBean * Bean Object from the database. * @throws RedBean_Exception_Security $exception * @param RedBean_OODBBean $bean */ public function trash(RedBean_OODBBean $bean) { $idfield = $this->writer->getIDField($bean->getMeta("type")); $this->signal("delete", $bean); $this->check($bean); try { $this->writer->deleteRecord($bean->getMeta("type"), $bean->{$idfield}); } catch (RedBean_Exception_SQL $e) { if ($e->getSQLState() != "42S02" && $e->getSQLState() != "42S22") { throw $e; } } }
/** * Adds a constraint. If one of the beans gets trashed * the other, related bean should be removed as well. * * @param RedBean_OODBBean $bean1 first bean * @param RedBean_OODBBean $bean2 second bean * @param bool $dontCache by default we use a cache, TRUE = NO CACHING (optional) * * @return void */ public function addConstraint(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, $dontCache = false) { $table1 = $bean1->getMeta("type"); $table2 = $bean2->getMeta("type"); $writer = $this; $adapter = $this->adapter; $table = $this->getAssocTableFormat(array($table1, $table2)); $idfield1 = $writer->getIDField($bean1->getMeta("type")); $idfield2 = $writer->getIDField($bean2->getMeta("type")); $property1 = $bean1->getMeta("type") . "_id"; $property2 = $bean2->getMeta("type") . "_id"; if ($property1 == $property2) { $property2 = $bean2->getMeta("type") . "2_id"; } $table = $adapter->escape($table); $table1 = $adapter->escape($table1); $table2 = $adapter->escape($table2); $property1 = $adapter->escape($property1); $property2 = $adapter->escape($property2); //In Cache? Then we dont need to bother $fkCode = "fk" . md5($table . $property1 . $property2); if (isset($this->fkcache[$fkCode])) { return false; } //Dispatch to right method try { return $this->constrain($table, $table1, $table2, $property1, $property2, $dontCache); } catch (RedBean_Exception_SQL $e) { if (!$writer->sqlStateIn($e->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, RedBean_QueryWriter::C_SQLSTATE_NO_SUCH_TABLE))) { throw $e; } } return false; }
public function extAssociate(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, RedBean_OODBBean $baseBean) { $table = $this->getTable(array($bean1->getMeta("type"), $bean2->getMeta("type"))); $baseBean->setMeta("type", $table); return $this->associateBeans($bean1, $bean2, $baseBean); }
public function insertOrUpdateRedBean(RedBean_OODBBean $oModel) { $writer = $this->getRedBeanWriter(); $type = $oModel->getMeta("type"); $idfield = $writer->getIDField($type); $idvalue = $oModel->{$idfield}; FlexiLogger::info(__METHOD__, "trying: " . $type . ": " . $oModel->{$idfield}); if (empty($idvalue)) { //if empty, just insert as usual return $this->insertRedBean($oModel); } else { //checking if update $bean = $this->getRedBeanModel($type, $idvalue); if ($bean != null && $bean !== false && $bean->{$idfield} == $idvalue) { // is existing record FlexiLogger::debug(__METHOD__, "Found record for " . $type . ":" . $idvalue); return $this->storeRedBean($oModel); } else { //cannot find record, time to insert, but with specified id return $this->insertRedBean($oModel); } } }
/** * 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; }
/** * Creates a 1 to Many Association * If the association fails it throws an exception. * @throws RedBean_Exception_SQL $failedToEnforce1toN * @param RedBean_OODBBean $bean1 * @param RedBean_OODBBean $bean2 * @return RedBean_AssociationManager $chainable */ public function set1toNAssoc(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2) { $type = $bean1->getMeta("type"); $this->clearRelations($bean2, $type); $this->associate($bean1, $bean2); if (count($this->related($bean2, $type)) === 1) { return $this; } else { throw new RedBean_Exception_SQL("Failed to enforce 1toN Relation for {$type} "); } }
/** * Counts the number of beans of a specific type * @param RedBean_OODBBean $bean * @return integer $count */ public function numberOf(RedBean_OODBBean $bean) { $type = $this->adapter->escape($bean->getMeta("type")); return (int) $this->adapter->getCell("SELECT count(*) FROM `{$type}`"); }
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; }
/** * @deprecated Use addContraintForTypes instead. * * @param RedBean_OODBBean $bean1 bean * @param RedBean_OODBBean $bean2 bean * * @return void */ public function addConstraint(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2) { $this->addConstraintForTypes($bean1->getMeta('type'), $bean2->getMeta('type')); }
$bean->setMeta("arr", array(1, 2)); asrt(is_array($bean->getMeta("arr")), true); asrt($bean->getMeta("nonexistant"), NULL); asrt($bean->getMeta("nonexistant", "abc"), "abc"); asrt($bean->getMeta("nonexistant.nested"), NULL); asrt($bean->getMeta("nonexistant,nested", "abc"), "abc"); $bean->setMeta("test.two", "second"); asrt($bean->getMeta("test.two"), "second"); $bean->setMeta("another.little.property", "yes"); asrt($bean->getMeta("another.little.property"), "yes"); asrt($bean->getMeta("test.two"), "second"); testpack("UNIT TEST RedBean OODBBean: copyMeta"); $bean = new RedBean_OODBBean(); $bean->setMeta("meta.meta", "123"); $bean2 = new RedBean_OODBBean(); asrt($bean2->getMeta("meta.meta"), NULL); $bean2->copyMetaFrom($bean); asrt($bean2->getMeta("meta.meta"), "123"); testpack("UNIT TEST RedBean OODBBean: import"); $bean = new RedBean_OODBBean(); $bean->import(array("a" => 1, "b" => 2)); asrt($bean->a, 1); asrt($bean->b, 2); testpack("UNIT TEST RedBean OODBBean: export"); $bean->setMeta("justametaproperty", "hellothere"); $arr = $bean->export(); asrt(is_array($arr), true); asrt(isset($arr["a"]), true); asrt(isset($arr["b"]), true); asrt($arr["a"], 1); asrt($arr["b"], 2);
/** * Given two beans this function returns TRUE if they are associated using a * many-to-many association, FALSE otherwise. * * @throws RedBean_Exception_SQL * * @param RedBean_OODBBean $bean1 bean * @param RedBean_OODBBean $bean2 bean * * @return boolean */ public function areRelated(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2) { try { $row = $this->writer->queryRecordLink($bean1->getMeta('type'), $bean2->getMeta('type'), $bean1->id, $bean2->id); return (bool) $row; } catch (RedBean_Exception_SQL $exception) { $this->handleException($exception); return FALSE; } }
/** * Checks whether a RedBean_OODBBean bean is valid. * If the type is not valid or the ID is not valid it will * throw an exception: RedBean_Exception_Security. * * @param RedBean_OODBBean $bean the bean that needs to be checked * * @return void * * @throws RedBean_Exception_Security $exception */ public function check(RedBean_OODBBean $bean) { //Is all meta information present? if (!isset($bean->id)) { throw new RedBean_Exception_Security('Bean has incomplete Meta Information id '); } if (!$bean->getMeta('type')) { throw new RedBean_Exception_Security('Bean has incomplete Meta Information II'); } //Pattern of allowed characters $pattern = '/[^a-z0-9_]/i'; //Does the type contain invalid characters? if (preg_match($pattern, $bean->getMeta('type'))) { throw new RedBean_Exception_Security('Bean Type is invalid'); } //Are the properties and values valid? foreach ($bean as $prop => $value) { if (is_array($value) || is_object($value)) { throw new RedBean_Exception_Security("Invalid Bean value: property {$prop}"); } else { if (strlen($prop) < 1 || preg_match($pattern, $prop)) { throw new RedBean_Exception_Security("Invalid Bean property: property {$prop}"); } } } }
/** * Returns the ID of the Model. */ public function getID() { $idField = $this->tools->getWriter()->getIDField($this->bean->getMeta("type")); return $this->bean->{$idField}; }
/** * Makes a copy of a bean. This method copies the bean and * adds the specified associations. * * For instance: R::copy( $book, "author,library" ); * * Duplicates the $book bean and copies the association links * author and library as well. Note that only many-to-many * associations can be copied. Also note that no author or library * beans are copied, only the connections or references to these * beans. * * @param RedBean_OODBBean $bean * @param string $associatedBeanTypesStr * @return array $copiedBean */ public static function copy($bean, $associatedBeanTypesStr) { $type = $bean->getMeta("type"); $copy = R::dispense($type); $copy->import($bean->export()); $copy->copyMetaFrom($bean); $copy->id = 0; R::store($copy); $associatedBeanTypes = explode(",", $associatedBeanTypesStr); foreach ($associatedBeanTypes as $associatedBeanType) { $assocBeans = R::related($bean, $associatedBeanType); foreach ($assocBeans as $assocBean) { R::associate($copy, $assocBean); } } $copy->setMeta("original", $bean); 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; }
/** * @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; }
/** * Creates a 1 to Many Association * @param RedBean_OODBBean $bean1 * @param RedBean_OODBBean $bean2 */ public function set1toNAssoc(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2) { $this->clearRelations($bean2, $bean1->getMeta("type")); $this->associate($bean1, $bean2); }
/** * 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; }