/** * 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); } }
/** * Dispenses a OODBBean * @param string $type * @return RedBean_OODBBean $bean */ public function dispense($type) { $bean = new RedBean_OODBBean(); $bean->setMeta("type", $type); $bean->id = 0; $this->signal("dispense", $bean); $this->check($bean); return $bean; }
/** * Dispenses a new bean (a RedBean_OODBBean Bean Object) * of the specified type. Always * use this function to get an empty bean object. Never * instantiate a RedBean_OODBBean yourself because it needs * to be configured before you can use it with RedBean. This * function applies the appropriate initialization / * configuration for you. * @param string $type * @return RedBean_OODBBean $bean */ public function dispense($type) { $bean = new RedBean_OODBBean(); $bean->setMeta("type", $type); $idfield = $this->writer->getIDField($bean->getMeta("type")); $bean->{$idfield} = 0; $this->signal("dispense", $bean); $this->check($bean); return $bean; }
/** * 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"); }
/** * Associates two beans with eachother. This method connects two beans with eachother, just * like the other associate() method in the Association Manager. The difference is however * that this method accepts a base bean, this bean will be used as the basis of the * association record in the link table. You can thus add additional properties and * even foreign keys. * * @param RedBean_OODBBean $bean1 bean 1 * @param RedBean_OODBBean $bean2 bean 2 * @param RedBean_OODBBean $bbean base bean for association record * * @return void */ 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); }
/** * Used for mixins. */ protected function mapAndCacheMetadataAndSetHints($modelClassName, RedBean_OODBBean $bean) { assert('is_string($modelClassName)'); assert('$modelClassName != ""'); $metadata = $this->getMetadata(); if (isset($metadata[$modelClassName])) { $hints = array(); if (isset($metadata[$modelClassName]['members'])) { foreach ($metadata[$modelClassName]['members'] as $memberName) { $this->attributeNameToBeanAndClassName[$memberName] = array($bean, $modelClassName); //$this->attributeNamesNotBelongsToOrManyMany[] = $memberName; if (substr($memberName, -2) == 'Id') { $columnName = strtolower($memberName); $hints[$columnName] = 'id'; } } } if (isset($metadata[$modelClassName]['relations'])) { foreach ($metadata[$modelClassName]['relations'] as $relationName => $relationTypeModelClassNameAndOwns) { assert('in_array(count($relationTypeModelClassNameAndOwns), array(2, 3, 4, 5))'); $relationType = $relationTypeModelClassNameAndOwns[0]; $relationModelClassName = $relationTypeModelClassNameAndOwns[1]; if ($relationType == self::HAS_MANY_BELONGS_TO && strtolower($relationName) != strtolower($relationModelClassName)) { $label = 'Relations of type HAS_MANY_BELONGS_TO must have the relation name ' . 'the same as the related model class name. Relation: {relationName} ' . 'Relation model class name: {relationModelClassName}'; throw new NotSupportedException(Zurmo::t('Core', $label, array('{relationName}' => $relationName, '{relationModelClassName}' => $relationModelClassName))); } if (count($relationTypeModelClassNameAndOwns) >= 3 && $relationTypeModelClassNameAndOwns[2] == self::OWNED) { $owns = true; } else { $owns = false; } // $linkType = null; // $relationLinkName = null; // self::resolveLinkTypeAndRelationLinkName($relationTypeModelClassNameAndOwns, $linkType, // $relationLinkName); assert('in_array($relationType, array(self::HAS_ONE_BELONGS_TO, self::HAS_MANY_BELONGS_TO, ' . 'self::HAS_ONE, self::HAS_MANY, self::MANY_MANY))'); $this->attributeNameToBeanAndClassName[$relationName] = array($bean, $modelClassName); /** $this->relationNameToRelationTypeModelClassNameAndOwns[$relationName] = array($relationType, $relationModelClassName, $owns, $linkType, $relationLinkName); * **/ if (!in_array($relationType, array(self::HAS_ONE_BELONGS_TO, self::HAS_MANY_BELONGS_TO, self::MANY_MANY))) { //$this->attributeNamesNotBelongsToOrManyMany[] = $relationName; } } } // Add model validators. Parent validators are already applied. if (isset($metadata[$modelClassName]['rules'])) { foreach ($metadata[$modelClassName]['rules'] as $validatorMetadata) { assert('isset($validatorMetadata[0])'); assert('isset($validatorMetadata[1])'); $attributeName = $validatorMetadata[0]; // Each rule in RedBeanModel must specify one attribute name. // This was just better style, now it is mandatory. assert('strpos($attributeName, " ") === false'); $validatorName = $validatorMetadata[1]; $validatorParameters = array_slice($validatorMetadata, 2); if (isset(CValidator::$builtInValidators[$validatorName])) { $validatorName = CValidator::$builtInValidators[$validatorName]; } if (isset(self::$yiiValidatorsToRedBeanValidators[$validatorName])) { $validatorName = self::$yiiValidatorsToRedBeanValidators[$validatorName]; } $validator = CValidator::createValidator($validatorName, $this, $attributeName, $validatorParameters); switch ($validatorName) { case 'RedBeanModelTypeValidator': case 'TypeValidator': $columnName = strtolower($attributeName); if (array_key_exists($columnName, $hints)) { unset($hints[$columnName]); } if (in_array($validator->type, array('date', 'datetime', 'blob', 'longblob', 'string', 'text', 'longtext'))) { $hints[$columnName] = $validator->type; } break; case 'CBooleanValidator': $columnName = strtolower($attributeName); $hints[$columnName] = 'boolean'; break; case 'RedBeanModelUniqueValidator': if (!static::isRelation($attributeName)) { $bean->setMeta("buildcommand.unique", array(array($attributeName))); } else { $relationAndOwns = static::getRelationNameToRelationTypeModelClassNameAndOwnsForModel(); $relatedModelClassName = $relationAndOwns[$attributeName][1]; $relatedModelTableName = self::getTableName($relatedModelClassName); $columnName = strtolower($attributeName); if ($columnName != $relatedModelTableName) { $columnName .= '_' . $relatedModelTableName; } $columnName .= '_id'; $bean->setMeta("buildcommand.unique", array(array($columnName))); } break; } $this->validators[] = $validator; } // Check if we need to update string type to long string type, based on validators. if (isset($metadata[$modelClassName]['members'])) { foreach ($metadata[$modelClassName]['members'] as $memberName) { $allValidators = $this->getValidators($memberName); if (!empty($allValidators)) { foreach ($allValidators as $validator) { if ((get_class($validator) == 'RedBeanModelTypeValidator' || get_class($validator) == 'TypeValidator') && $validator->type == 'string') { $columnName = strtolower($validator->attributes[0]); if (count($allValidators) > 1) { $haveCStringValidator = false; foreach ($allValidators as $innerValidator) { if (get_class($innerValidator) == 'CStringValidator' && isset($innerValidator->max) && $innerValidator->max > 0) { if ($innerValidator->max > 65535) { $hints[$columnName] = 'longtext'; } elseif ($innerValidator->max < 255) { $hints[$columnName] = "string({$innerValidator->max})"; } else { $hints[$columnName] = 'text'; } } if (get_class($innerValidator) == 'CStringValidator') { $haveCStringValidator = true; } } if (!$haveCStringValidator) { $hints[$columnName] = 'text'; } } else { $hints[$columnName] = 'text'; } } } } } } } $bean->setMeta('hint', $hints); } }
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); asrt(isset($arr["__info"]), false); $arr = $bean->export(true); asrt(isset($arr["__info"]), true); asrt($arr["a"], 1); asrt($arr["b"], 2); //Test observer testpack("UNIT TEST Observer Mechanism "); $observable = new ObservableMock(); $observer = new ObserverMock();
/** * Associates a pair of beans. This method associates two beans, no matter * what types. Accepts a base bean that contains data for the linking record. * This method is used by associate. This method also accepts a base bean to be used * as the template for the link record in the database. * * @param RedBean_OODBBean $bean1 first bean * @param RedBean_OODBBean $bean2 second bean * @param RedBean_OODBBean $bean base bean (association record) * * @throws Exception|RedBean_Exception_SQL * * @return mixed */ protected function associateBeans(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, RedBean_OODBBean $bean) { $property1 = $bean1->getMeta('type') . '_id'; $property2 = $bean2->getMeta('type') . '_id'; if ($property1 == $property2) { $property2 = $bean2->getMeta('type') . '2_id'; } //add a build command for Unique Indexes $bean->setMeta('buildcommand.unique', array(array($property1, $property2))); //add a build command for Single Column Index (to improve performance in case unqiue cant be used) $indexName1 = 'index_for_' . $bean->getMeta('type') . '_' . $property1; $indexName2 = 'index_for_' . $bean->getMeta('type') . '_' . $property2; $bean->setMeta('buildcommand.indexes', array($property1 => $indexName1, $property2 => $indexName2)); $this->oodb->store($bean1); $this->oodb->store($bean2); $bean->setMeta("cast.{$property1}", "id"); $bean->setMeta("cast.{$property2}", "id"); $bean->{$property1} = $bean1->id; $bean->{$property2} = $bean2->id; $results = array(); try { $id = $this->oodb->store($bean); //On creation, add constraints.... if (!$this->oodb->isFrozen() && $bean->getMeta('buildreport.flags.created')) { $bean->setMeta('buildreport.flags.created', 0); if (!$this->oodb->isFrozen()) { $this->writer->addConstraintForTypes($bean1->getMeta('type'), $bean2->getMeta('type')); } } $results[] = $id; } catch (RedBean_Exception_SQL $exception) { if (!$this->writer->sqlStateIn($exception->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) { throw $exception; } } return $results; }
/** * Converts an embedded bean to an ID, removed the bean property and * stores the bean in the embedded beans array. * * @param array $embeddedBeans destination array for embedded bean * @param RedBean_OODBBean $bean target bean * @param string $property property that contains the embedded bean * @param RedBean_OODBBean $value embedded bean itself */ private function processEmbeddedBean(&$embeddedBeans, $bean, $property, RedBean_OODBBean $value) { $linkField = $property . '_id'; $bean->{$linkField} = $this->prepareEmbeddedBean($value); $bean->setMeta('cast.' . $linkField, 'id'); $embeddedBeans[$linkField] = $value; $bean->removeProperty($property); }
/** * For Preloader: adds the IDs of your input beans to the nested beans, otherwise * we dont know how to pass them to the each-function later on. * * @param RedBean_OODBBean $nestedBean nested bean * @param array $addInputIDs input ids * * @return void */ private function addInputBeanIDsToBean($nestedBean, $addInputIDs) { $currentInputBeanIDs = $nestedBean->getMeta('sys.input-bean-id'); if (!is_array($currentInputBeanIDs)) { $currentInputBeanIDs = array(); } foreach ($addInputIDs as $addInputID) { $currentInputBeanIDs[$addInputID] = $addInputID; } $nestedBean->setMeta('sys.input-bean-id', $currentInputBeanIDs); }
/** * ExportAll. * * @return void */ public function testExportAll() { testpack('Test exportAll'); $redbean = R::$redbean; $bean = new RedBean_OODBBean(); $bean->import(array("a" => 1, "b" => 2)); $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); asrt(isset($arr["__info"]), FALSE); $arr = $bean->export(TRUE); asrt(isset($arr["__info"]), TRUE); asrt($arr["a"], 1); asrt($arr["b"], 2); $exportBean = $redbean->dispense("abean"); $exportBean->setMeta("metaitem.bla", 1); $exportedBean = $exportBean->export(TRUE); asrt($exportedBean["__info"]["metaitem.bla"], 1); asrt($exportedBean["__info"]["type"], "abean"); // Can we determine whether a bean is empty? testpack('test $bean->isEmpty() function'); $bean = R::dispense('bean'); asrt($bean->isEmpty(), TRUE); asrt(count($bean) > 0, TRUE); $bean->property = 1; asrt($bean->isEmpty(), FALSE); asrt(count($bean) > 0, TRUE); $bean->property = 0; asrt($bean->isEmpty(), TRUE); asrt(count($bean) > 0, TRUE); $bean->property = FALSE; asrt($bean->isEmpty(), TRUE); asrt(count($bean) > 0, TRUE); $bean->property = NULL; asrt($bean->isEmpty(), TRUE); asrt(count($bean) > 0, TRUE); unset($bean->property); asrt($bean->isEmpty(), TRUE); asrt(count($bean) > 0, TRUE); // Export bug I found $object = R::graph(json_decode('{"type":"bandmember","name":"Duke","ownInstrument":[{"type":"instrument","name":"Piano"}]}', TRUE)); $a = R::exportAll($object); pass(); asrt(isset($a[0]), TRUE); asrt((int) $a[0]['id'], 0); asrt($a[0]['name'], 'Duke'); asrt($a[0]['ownInstrument'][0]['name'], 'Piano'); R::nuke(); $v = R::dispense('village'); $b = R::dispense('building'); $v->name = 'a'; $b->name = 'b'; $v->ownBuilding[] = $b; $id = R::store($v); $a = R::exportAll($v); asrt($a[0]['name'], 'a'); asrt($a[0]['ownBuilding'][0]['name'], 'b'); $v = R::load('village', $id); $b2 = R::dispense('building'); $b2->name = 'c'; $v->ownBuilding[] = $b2; $a = R::exportAll($v); asrt($a[0]['name'], 'a'); asrt($a[0]['ownBuilding'][0]['name'], 'b'); asrt(count($a[0]['ownBuilding']), 2); list($r1, $r2) = R::dispense('army', 2); $r1->name = '1'; $r2->name = '2'; $v->sharedArmy[] = $r2; $a = R::exportAll($v); asrt(count($a[0]['sharedArmy']), 1); R::store($v); $v = R::load('village', $id); $a = R::exportAll($v); asrt(count($a[0]['sharedArmy']), 1); asrt($a[0]['name'], 'a'); asrt($a[0]['ownBuilding'][0]['name'], 'b'); asrt(count($a[0]['ownBuilding']), 2); $v->sharedArmy[] = $r1; $a = R::exportAll($v); asrt(count($a[0]['sharedArmy']), 2); $v = R::load('village', $id); $a = R::exportAll($v); asrt(count($a[0]['sharedArmy']), 1); $v->sharedArmy[] = $r1; R::store($v); $v = R::load('village', $id); $a = R::exportAll($v); asrt(count($a[0]['sharedArmy']), 2); }
/** * Dispenses a new bean (a RedBean_OODBBean Bean Object) * of the specified type. Always * use this function to get an empty bean object. Never * instantiate a RedBean_OODBBean yourself because it needs * to be configured before you can use it with RedBean. This * function applies the appropriate initialization / * configuration for you. * @param string $type * @return RedBean_OODBBean $bean */ public function dispense($type) { $this->signal("before_dispense", $type); $bean = new RedBean_OODBBean(); $bean->setBeanHelper($this->beanhelper); $bean->setMeta("type", $type); $idfield = $this->writer->getIDField($bean->getMeta("type")); $bean->setMeta("sys.idfield", $idfield); //$bean->setMeta("sys.oodb",$this); $bean->{$idfield} = 0; if (!$this->isFrozen) { $this->check($bean); } $bean->setMeta("tainted", true); $this->signal("dispense", $bean); return $bean; }
/** * Associates a pair of beans. This method associates two beans, no matter * what types. * * @param RedBean_OODBBean $bean1 first bean * @param RedBean_OODBBean $bean2 second bean * @param RedBean_OODBBean $bean base bean * * @return mixed $id either the link ID or null */ protected function associateBeans(RedBean_OODBBean $bean1, RedBean_OODBBean $bean2, RedBean_OODBBean $bean) { $idfield1 = $this->writer->getIDField($bean1->getMeta("type")); $idfield2 = $this->writer->getIDField($bean2->getMeta("type")); $property1 = $bean1->getMeta("type") . "_id"; $property2 = $bean2->getMeta("type") . "_id"; if ($property1 == $property2) { $property2 = $bean2->getMeta("type") . "2_id"; } //add a build command for Unique Indexes $bean->setMeta("buildcommand.unique", array(array($property1, $property2))); //add a build command for Single Column Index (to improve performance in case unqiue cant be used) $indexName1 = "index_for_" . $bean->getMeta("type") . "_" . $property1; $indexName2 = "index_for_" . $bean->getMeta("type") . "_" . $property2; $bean->setMeta("buildcommand.indexes", array($property1 => $indexName1, $property2 => $indexName2)); $this->oodb->store($bean1); $this->oodb->store($bean2); $bean->setMeta("assoc." . $bean1->getMeta("type"), $bean1); $bean->setMeta("assoc." . $bean2->getMeta("type"), $bean2); $bean->setMeta("cast.{$property1}", "id"); $bean->setMeta("cast.{$property2}", "id"); $bean->{$property1} = $bean1->{$idfield1}; $bean->{$property2} = $bean2->{$idfield2}; try { $id = $this->oodb->store($bean); //On creation, add constraints.... if ($this->flagUseConstraints && !$this->oodb->isFrozen() && $bean->getMeta("buildreport.flags.created")) { $bean->setMeta("buildreport.flags.created", 0); if (!$this->oodb->isFrozen()) { $this->writer->addConstraint($bean1, $bean2); } } return $id; } catch (RedBean_Exception_SQL $e) { if (!$this->writer->sqlStateIn($e->getSQLState(), array(RedBean_QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) { throw $e; } } }