Exemple #1
0
 /**
  * Stores a cleaned bean; i.e. only scalar values. This is the core of the store()
  * method. When all lists and embedded beans (parent objects) have been processed and
  * removed from the original bean the bean is passed to this method to be stored
  * in the database.
  *
  * @param OODBBean $bean the clean bean
  *
  * @return void
  */
 protected function storeBean(OODBBean $bean)
 {
     if ($bean->getMeta('changed')) {
         list($properties, $table) = $bean->getPropertiesAndType();
         $id = $properties['id'];
         unset($properties['id']);
         $updateValues = array();
         $k1 = 'property';
         $k2 = 'value';
         foreach ($properties as $key => $value) {
             $updateValues[] = array($k1 => $key, $k2 => $value);
         }
         $bean->id = $this->writer->updateRecord($table, $updateValues, $id);
         $bean->setMeta('changed', FALSE);
     }
     $bean->setMeta('tainted', FALSE);
 }
 /**
  * {@inheritdoc}
  */
 public function apply(OODBBean $bean, $eventName, array $options)
 {
     $fields = $options['events'][$eventName];
     $parts = array();
     foreach ($fields as $name) {
         $parts[] = $bean[$name];
     }
     $fieldName = $options['options']['fieldName'];
     if ($parts) {
         $bean->setMeta(sprintf('cast.%s', $fieldName), 'string');
         $bean->{$fieldName} = $this->sluggify(join(' ', $parts));
     }
 }
Exemple #3
0
 /**
  * Test meta data methods.
  *
  * @return void
  */
 public function testMetaData()
 {
     testpack('Test meta data');
     $bean = new 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 OODBBean();
     $bean->setMeta("meta.meta", "123");
     $bean2 = new OODBBean();
     asrt($bean2->getMeta("meta.meta"), NULL);
     $bean2->copyMetaFrom($bean);
     asrt($bean2->getMeta("meta.meta"), "123");
 }
Exemple #4
0
 /**
  * Normally the check() method is always called indirectly when
  * dealing with beans. This test ensures we can call check()
  * directly. Even though frozen repositories do not rely on
  * bean checking to improve performance the method should still
  * offer the same functionality when called directly.
  *
  * @return void
  */
 public function testCheckDirectly()
 {
     $bean = new OODBBean();
     $bean->id = 0;
     $bean->setMeta('type', 'book');
     R::getRedBean()->check($bean);
     $bean->setMeta('type', '.');
     try {
         R::getRedBean()->check($bean);
         fail();
     } catch (\Exception $e) {
         pass();
     }
     //check should remain the same even if frozen repo is used, method is public after all!
     //we dont want to break the API!
     R::freeze(TRUE);
     try {
         R::getRedBean()->check($bean);
         fail();
     } catch (\Exception $e) {
         pass();
     }
     R::freeze(FALSE);
 }
 /**
  * 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 OODBBean $bean1 first bean
  * @param OODBBean $bean2 second bean
  * @param OODBBean $bean  base bean (association record)
  *
  * @return mixed
  */
 protected function associateBeans(OODBBean $bean1, OODBBean $bean2, OODBBean $bean)
 {
     $type = $bean->getMeta('type');
     $property1 = $bean1->getMeta('type') . '_id';
     $property2 = $bean2->getMeta('type') . '_id';
     if ($property1 == $property2) {
         $property2 = $bean2->getMeta('type') . '2_id';
     }
     $this->oodb->store($bean1);
     $this->oodb->store($bean2);
     $bean->setMeta("cast.{$property1}", "id");
     $bean->setMeta("cast.{$property2}", "id");
     $bean->setMeta('sys.buildcommand.unique', array($property1, $property2));
     $bean->{$property1} = $bean1->id;
     $bean->{$property2} = $bean2->id;
     $results = array();
     try {
         $id = $this->oodb->store($bean);
         $results[] = $id;
     } catch (SQLException $exception) {
         if (!$this->writer->sqlStateIn($exception->getSQLState(), array(QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) {
             throw $exception;
         }
     }
     return $results;
 }
Exemple #6
0
 /**
  * Modifies the table to fit the bean data.
  * Given a property and a value and the bean, this method will
  * adjust the table structure to fit the requirements of the property and value.
  * This may include adding a new column or widening an existing column to hold a larger
  * or different kind of value. This method employs the writer to adjust the table
  * structure in the database. Schema updates are recorded in meta properties of the bean.
  *
  * This method will also apply indexes, unique constraints and foreign keys.
  *
  * @param OODBBean $bean     bean to get cast data from and store meta in
  * @param string   $property property to store
  * @param mixed    $value    value to store
  *
  * @return void
  */
 private function modifySchema(OODBBean $bean, $property, $value)
 {
     $doFKStuff = FALSE;
     $table = $bean->getMeta('type');
     $columns = $this->writer->getColumns($table);
     $columnNoQ = $this->writer->esc($property, TRUE);
     if (!$this->oodb->isChilled($bean->getMeta('type'))) {
         if ($bean->getMeta("cast.{$property}", -1) !== -1) {
             //check for explicitly specified types
             $cast = $bean->getMeta("cast.{$property}");
             $typeno = $this->getTypeFromCast($cast);
         } else {
             $cast = FALSE;
             $typeno = $this->writer->scanType($value, TRUE);
         }
         if (isset($columns[$this->writer->esc($property, TRUE)])) {
             //Is this property represented in the table ?
             if (!$cast) {
                 //rescan without taking into account special types >80
                 $typeno = $this->writer->scanType($value, FALSE);
             }
             $sqlt = $this->writer->code($columns[$this->writer->esc($property, TRUE)]);
             if ($typeno > $sqlt) {
                 //no, we have to widen the database column type
                 $this->writer->widenColumn($table, $property, $typeno);
                 $bean->setMeta('buildreport.flags.widen', TRUE);
                 $doFKStuff = TRUE;
             }
         } else {
             $this->writer->addColumn($table, $property, $typeno);
             $bean->setMeta('buildreport.flags.addcolumn', TRUE);
             $doFKStuff = TRUE;
         }
         if ($doFKStuff) {
             if (strrpos($columnNoQ, '_id') === strlen($columnNoQ) - 3) {
                 $destinationColumnNoQ = substr($columnNoQ, 0, strlen($columnNoQ) - 3);
                 $indexName = "index_foreignkey_{$table}_{$destinationColumnNoQ}";
                 $this->writer->addIndex($table, $indexName, $columnNoQ);
                 $typeof = $bean->getMeta("sys.typeof.{$destinationColumnNoQ}", $destinationColumnNoQ);
                 $isLink = $bean->getMeta('sys.buildcommand.unique', FALSE);
                 //Make FK CASCADING if part of exclusive list (dependson=typeof) or if link bean
                 $isDep = $bean->moveMeta('sys.buildcommand.fkdependson') === $typeof || is_array($isLink);
                 $result = $this->writer->addFK($table, $typeof, $columnNoQ, 'id', $isDep);
                 //If this is a link bean and all unique columns have been added already, then apply unique constraint
                 if (is_array($isLink) && !count(array_diff($isLink, array_keys($this->writer->getColumns($table))))) {
                     $this->writer->addUniqueConstraint($table, $bean->moveMeta('sys.buildcommand.unique'));
                     $bean->setMeta("sys.typeof.{$destinationColumnNoQ}", NULL);
                 }
             }
         }
     }
 }
 /**
  * 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 OODBBean $bean1 first bean
  * @param OODBBean $bean2 second bean
  * @param OODBBean $bean  base bean (association record)
  *
  * @throws\Exception|SQL
  *
  * @return mixed
  */
 protected function associateBeans(OODBBean $bean1, OODBBean $bean2, OODBBean $bean)
 {
     $property1 = $bean1->getMeta('type') . '_id';
     $property2 = $bean2->getMeta('type') . '_id';
     if ($property1 == $property2) {
         $property2 = $bean2->getMeta('type') . '2_id';
     }
     //Dont mess with other tables, only add the unique constraint if:
     //1. the table exists (otherwise we cant inspect it)
     //2. the table only contains N-M fields: ID, N-ID, M-ID.
     $unique = array($property1, $property2);
     $type = $bean->getMeta('type');
     $tables = $this->writer->getTables();
     if (in_array($type, $tables) && !$this->oodb->isChilled($type)) {
         $columns = $this->writer->getColumns($type);
         if (count($columns) === 3 && isset($columns['id']) && isset($columns[$property1]) && isset($columns[$property2])) {
             $bean->setMeta('buildcommand.unique', array($unique));
         }
     }
     //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 (SQL $exception) {
         if (!$this->writer->sqlStateIn($exception->getSQLState(), array(QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION))) {
             throw $exception;
         }
     }
     return $results;
 }
Exemple #8
0
 /**
  * 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 OODBBean $bean          target bean
  * @param string           $property      property that contains the embedded bean
  * @param OODBBean $value         embedded bean itself
  */
 protected function processEmbeddedBean(&$embeddedBeans, $bean, $property, OODBBean $value)
 {
     $linkField = $property . '_id';
     $id = $this->prepareEmbeddedBean($value);
     if ($bean->{$linkField} != $id) {
         $bean->{$linkField} = $id;
     }
     $bean->setMeta('cast.' . $linkField, 'id');
     $embeddedBeans[$linkField] = $value;
     unset($bean->{$property});
 }
Exemple #9
0
 /**
  * ExportAll.
  *
  * @return void
  */
 public function testExportAll()
 {
     testpack('Test exportAll');
     $redbean = R::getRedBean();
     $bean = new 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
     $bandmember = R::dispense('bandmember');
     $bandmember->name = 'Duke';
     $instrument = R::dispense('instrument');
     $instrument->name = 'Piano';
     $bandmember->ownInstrument[] = $instrument;
     $a = R::exportAll($bandmember);
     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);
 }
Exemple #10
0
 /**
  * Molds the table to fit the bean data.
  * Given a property and a value and the bean, this method will
  * adjust the table structure to fit the requirements of the property and value.
  * This may include adding a new column or widening an existing column to hold a larger
  * or different kind of value. This method employs the writer to adjust the table
  * structure in the database. Schema updates are recorded in meta properties of the bean.
  *
  * @param OODBBean $bean     bean to get cast data from and store meta in
  * @param string           $property property to store
  * @param mixed            $value    value to store
  *
  * @return void
  */
 private function moldTable(OODBBean $bean, $property, $value)
 {
     $table = $bean->getMeta('type');
     $columns = $this->writer->getColumns($table);
     if (!$this->oodb->isChilled($bean->getMeta('type'))) {
         if ($bean->getMeta("cast.{$property}", -1) !== -1) {
             //check for explicitly specified types
             $cast = $bean->getMeta("cast.{$property}");
             $typeno = $this->getTypeFromCast($cast);
         } else {
             $cast = FALSE;
             $typeno = $this->writer->scanType($value, TRUE);
         }
         if (isset($columns[$this->writer->esc($property, TRUE)])) {
             //Is this property represented in the table ?
             if (!$cast) {
                 //rescan without taking into account special types >80
                 $typeno = $this->writer->scanType($value, FALSE);
             }
             $sqlt = $this->writer->code($columns[$this->writer->esc($property, TRUE)]);
             if ($typeno > $sqlt) {
                 //no, we have to widen the database column type
                 $this->writer->widenColumn($table, $property, $typeno);
                 $bean->setMeta('buildreport.flags.widen', TRUE);
             }
         } else {
             $this->writer->addColumn($table, $property, $typeno);
             $bean->setMeta('buildreport.flags.addcolumn', TRUE);
             $this->processBuildCommands($table, $property, $bean);
         }
     }
 }