/** * 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; }
/** * @see BeanHelper::getModelForBean */ public function getModelForBean(OODBBean $bean) { $model = $bean->getMeta('type'); $prefix = defined('REDBEAN_MODEL_PREFIX') ? REDBEAN_MODEL_PREFIX : '\\Model_'; if (strpos($model, '_') !== FALSE) { $modelParts = explode('_', $model); $modelName = ''; foreach ($modelParts as $part) { $modelName .= ucfirst($part); } $modelName = $prefix . $modelName; if (!class_exists($modelName)) { //second try $modelName = $prefix . ucfirst($model); if (!class_exists($modelName)) { return NULL; } } } else { $modelName = $prefix . ucfirst($model); if (!class_exists($modelName)) { return NULL; } } $obj = self::factory($modelName); $obj->loadBean($bean); return $obj; }
/** * Save bean to database */ public function save() { foreach ($this->_bean->getProperties() as $prop => &$propValue) { if (substr($prop, 0, 3) === 'own') { $propsToUpdate = []; foreach ($propValue as $subValue) { if ($subValue instanceof BaseModel) { $subValue = $subValue->getBean(); $propsToUpdate[] = $subValue; } } $this->__set($prop, $propsToUpdate); } if (substr($prop, 0, 6) === 'shared') { $propsToUpdate = []; foreach ($propValue as $subValue) { if ($subValue instanceof BaseModel) { $subValue = $subValue->getBean(); $propsToUpdate[] = $subValue; } } $this->__set($prop, $propsToUpdate); } } if ($this->_timestamps) { $this->_bean->{'updated_at'} = Carbon::now(); } R::store($this->_bean); }
public function getModelForBean(OODBBean $bean) { $model = $bean->getMeta("type"); $prefix = $this->defaultNamespace; $typeMap = $this->typeMap; if (isset($typeMap[$model])) { $modelName = $typeMap[$model]; } else { if (strpos($model, '_') !== FALSE) { $modelParts = explode('_', $model); $modelName = ''; foreach ($modelParts as $part) { $modelName .= ucfirst($part); } $modelName = $prefix . $modelName; if (!class_exists($modelName)) { //second try $modelName = $prefix . ucfirst($model); if (!class_exists($modelName)) { return NULL; } } } else { $modelName = $prefix . ucfirst($model); if (!class_exists($modelName)) { return NULL; } } } $obj = self::factory($modelName); $obj->loadBean($bean); return $obj; }
private function exportApplicationForm(OODBBean $bean) { $appForm = $bean->export(); $appForm['items'] = array_map(function ($itemBean) { return array_merge($itemBean->export(), ['lab' => $itemBean->lab->name, 'itemcategory' => $itemBean->itemcategory->name]); }, $bean->ownApplicationformitemList); return $appForm; }
/** * Tests whether getID never produces a notice. * * @return void */ public function testGetIDShouldNeverPrintNotice() { set_error_handler(function ($err, $errStr) { die('>>>>FAIL :' . $err . ' ' . $errStr); }); $bean = new OODBBean(); $bean->getID(); restore_error_handler(); pass(); }
/** * {@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)); } }
public function getModelForBean(\RedBeanPHP\OODBBean $bean) { $prefix = '\\Model_'; $model = $bean->getMeta('type'); $modelName = $prefix . $this->underscoreToCamelCase($model); if (!class_exists($modelName)) { return null; } $model = new $modelName(); if ($model instanceof \Box\InjectionAwareInterface) { $model->setDi($this->di); } $model->loadBean($bean); return $model; }
public static function validate(\RedBeanPHP\OODBBean $bean) { $data = $bean->export(); $model = $bean->box() !== null ? $bean->box() : null; if (!$model) { throw new ModelValidation_Exception('This bean does not have a model!'); } $rules = isset($model::$rules) ? $model::$rules : null; if (!$rules) { throw new ModelValidation_Exception('This bean does not have any established rules!'); } $validations = []; $filters = []; $labels = []; $messages = []; foreach ($rules as $field => $rule) { if (isset($rule['filter'])) { $filters[$field] = $rule['filter']; } if (isset($rule['label'])) { $labels[$field] = $rule['label']; } if (isset($rule['validation'])) { $validations[$field] = $rule['validation']; } if (isset($rule['message'])) { $field = isset($rule['label']) ? $rule['label'] : ucwords(str_replace(array('_', '-'), chr(32), $field)); $messages[$field] = $rule['message']; } } $gump = new \GUMP(); if (!empty($filters)) { $gump->filter_rules($filters); } if (!empty($validations)) { $gump->validation_rules($validations); } if (!empty($labels)) { $gump->set_field_names($labels); } $validated_data = $gump->run($data); if ($validated_data === false) { return self::default2custom_errors($gump->get_errors_array(), $messages); } else { $bean->import($validated_data); return true; } }
/** * * @param \RedBeanPHP\OODBBean $old_object * @param \RedBeanPHP\OODBBean $new_object * @param type $message */ public static function create($old_object, $new_object, $message, $entity = false) { //Determine the current user $audit = R::dispense('audit'); $audit->message = $message; $audit->date_logged = date('Y-m-d H:i:s'); $audit->table = $new_object ? $new_object->getMeta('type') : null; $audit->entity = $entity ? $entity : $audit->table; $aidit->tableId = $new_object ? $new_object->id : $old_object->id; $audit->old_obj = serialize($old_object); $audit->new_obj = serialize($new_object); $audit->user = G()->get_user(); R::store($audit); // $user->ownAudit[] = $audit; // R::store($user); Admin_Alert::add_message($message . ' <a href="' . ADMIN_URL . "package/audit/changes/{$audit->id}" . '">View Change</a>'); }
/** Function to insert new Event * @param array $eventData containg to be inserted for event * @param \RedBeanPHP\OODBBean $user user who is creating the event * @retrun boolean * **/ public function insertEvent(array $eventData, \RedBeanPHP\OODBBean $user) { try { //check if event with same name is already associated with user $associatedRow = $user->withCondition('event_name = ? LIMIT 1', array($eventData['event_name']))->ownEventsList; if (!$associatedRow) { $event = $this->_redbeans->dispense('events'); foreach ($eventData as $column => $data) { $event->{$column} = $data; } $user->ownEventsList[] = $event; return $this->_redbeans->store($user); } else { throw new \Exception('Cannot insert event with same name'); } } catch (\Exception $e) { return false; } return false; }
/** * Returns all beans that have been tagged with one or more * of the specified tags. * * Tag list can be either an array with tag names or a comma separated list * of tag names. * * @param string $beanType type of bean you are looking for * @param array|string $tagList list of tags to match * * @return array */ public function tagged($beanType, $tagList) { $tags = $this->extractTagsIfNeeded($tagList); $collection = array(); $tags = $this->redbean->find('tag', array('title' => $tags)); $list = 'shared' . ucfirst($beanType); if (is_array($tags) && count($tags) > 0) { foreach ($tags as $tag) { $collection += $tag->{$list}; } } return $collection; }
/** * 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"); }
/** * 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); }
/** * Stores a bean and its lists in one run. * * @param OODBBean $bean * * @return void */ protected function processLists(OODBBean $bean) { $sharedAdditions = $sharedTrashcan = $sharedresidue = $sharedItems = $ownAdditions = $ownTrashcan = $ownresidue = $embeddedBeans = array(); //Define groups foreach ($bean as $property => $value) { $value = $value instanceof SimpleModel ? $value->unbox() : $value; if ($value instanceof OODBBean) { $this->processEmbeddedBean($embeddedBeans, $bean, $property, $value); } elseif (is_array($value)) { $originals = $bean->getMeta('sys.shadow.' . $property, array()); $bean->setMeta('sys.shadow.' . $property, NULL); //clear shadow if (strpos($property, 'own') === 0) { list($ownAdditions, $ownTrashcan, $ownresidue) = $this->processGroups($originals, $value, $ownAdditions, $ownTrashcan, $ownresidue); $listName = lcfirst(substr($property, 3)); if ($bean->getMeta('sys.exclusive-' . $listName)) { OODBBean::setMetaAll($ownTrashcan, 'sys.garbage', TRUE); } unset($bean->{$property}); } elseif (strpos($property, 'shared') === 0) { list($sharedAdditions, $sharedTrashcan, $sharedresidue) = $this->processGroups($originals, $value, $sharedAdditions, $sharedTrashcan, $sharedresidue); unset($bean->{$property}); } } } $this->storeBean($bean); $this->addForeignKeysForParentBeans($bean, $embeddedBeans); $this->processTrashcan($bean, $ownTrashcan); $this->processAdditions($bean, $ownAdditions); $this->processResidue($ownresidue); $this->processSharedTrashcan($bean, $sharedTrashcan); $this->processSharedAdditions($bean, $sharedAdditions); $this->processSharedResidue($bean, $sharedresidue); }
/** * 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')) { $this->check($bean); $table = $bean->getMeta('type'); $this->createTableIfNotExists($bean, $table); $updateValues = array(); foreach ($bean as $property => $value) { if ($property !== 'id') { $this->modifySchema($bean, $property, $value); } if ($property !== 'id') { $updateValues[] = array('property' => $property, 'value' => $value); } } $bean->id = $this->writer->updateRecord($table, $updateValues, $bean->id); $bean->setMeta('changed', FALSE); } $bean->setMeta('tainted', FALSE); }
/** * Returns all beans that have been tagged with ALL of the tags given. * * Tag list can be either an array with tag names or a comma separated list * of tag names. * * @param string $beanType type of bean you are looking for * @param array|string $tagList list of tags to match * * @return array */ public function taggedAll($beanType, $tagList, $sql = '', $bindings = array()) { $tags = $this->extractTagsIfNeeded($tagList); $records = $this->toolbox->getWriter()->queryTagged($beanType, $tags, TRUE, $sql, $bindings); return $this->redbean->convertToBeans($beanType, $records); }
/** * Returns a model for a bean based on its type. * * @param OODBBean $bean * * @return object */ public function getModelForBean(\RedBeanPHP\OODBBean $bean) { if ($bean->getMeta('type') === 'meal') { $model = new Model_Soup(); $model->loadBean($bean); return $model; } else { return parent::getModelForBean($bean); } }
/** * Test error handling options FUSE. */ public function testModelErrorHandling() { $test = R::dispense('feed'); $test->nonExistantMethod(); pass(); $old = R::setErrorHandlingFUSE(OODBBean::C_ERR_LOG); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], FALSE); asrt($old[1], NULL); $test->nonExistantMethod(); //we cant really test this... :( pass(); $old = R::setErrorHandlingFUSE(OODBBean::C_ERR_NOTICE); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_LOG); asrt($old[1], NULL); set_error_handler(function ($error, $str) { asrt($str, 'FUSE: method does not exist in model: nonExistantMethod'); }, E_USER_NOTICE); $test->nonExistantMethod(); restore_error_handler(); $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_WARN); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_NOTICE); asrt($old[1], NULL); set_error_handler(function ($error, $str) { asrt($str, 'FUSE: method does not exist in model: nonExistantMethod'); }, E_USER_WARNING); $test->nonExistantMethod(); restore_error_handler(); $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_FATAL); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_WARN); asrt($old[1], NULL); set_error_handler(function ($error, $str) { asrt($str, 'FUSE: method does not exist in model: nonExistantMethod'); }, E_USER_ERROR); $test->nonExistantMethod(); restore_error_handler(); $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_EXCEPTION); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_FATAL); asrt($old[1], NULL); try { $test->nonExistantMethod(); fail(); } catch (\Exception $e) { pass(); } global $test_bean; $test_bean = $test; global $has_executed_error_func_fuse; $has_executed_error_func_fuse = FALSE; $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_FUNC, function ($info) { global $has_executed_error_func_fuse; global $test_bean; $has_executed_error_func_fuse = TRUE; asrt(is_array($info), TRUE); asrt($info['method'], 'nonExistantMethod'); asrt(json_encode($info['bean']->export()), json_encode($test_bean->export())); asrt($info['message'], 'FUSE: method does not exist in model: nonExistantMethod'); }); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_EXCEPTION); asrt($old[1], NULL); $test->nonExistantMethod(); asrt($has_executed_error_func_fuse, TRUE); $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_IGNORE); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_FUNC); asrt(is_callable($old[1]), TRUE); $old = OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_IGNORE); asrt(is_array($old), TRUE); asrt(count($old), 2); asrt($old[0], OODBBean::C_ERR_IGNORE); asrt($old[1], NULL); try { OODBBean::setErrorHandlingFUSE(900); fail(); } catch (\Exception $e) { pass(); asrt($e->getMessage(), 'Invalid error mode selected'); } try { OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_FUNC, 'hello'); fail(); } catch (\Exception $e) { pass(); asrt($e->getMessage(), 'Invalid error handler'); } OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_EXCEPTION); //make sure ignore FUSE events $test = R::dispense('feed'); R::store($test); $test = $test->fresh(); R::trash($test); pass(); OODBBean::setErrorHandlingFUSE(OODBBean::C_ERR_IGNORE); }
/** * 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 OODBBean $bean currently selected bean * * @return boolean */ private function inTrailOrAdd(&$trail, OODBBean $bean) { $type = $bean->getMeta('type'); $key = $type . $bean->getID(); if (isset($trail[$key])) { return TRUE; } $trail[$key] = $bean; return FALSE; }
/** * Test unboxing * * @param OODBBean $bean */ private function giveMeBean(OODBBean $bean) { asrt($bean instanceof OODBBean, TRUE); asrt('A bit too salty', $bean->taste()); asrt('tomato', $bean->flavour); }
/** * 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); }
/** * Test import from and tainted. * * @return void */ public function testImportFromAndTainted() { testpack('Test importFrom() and Tainted'); $bean = R::dispense('bean'); R::store($bean); $bean->name = 'abc'; asrt($bean->getMeta('tainted'), TRUE); R::store($bean); asrt($bean->getMeta('tainted'), FALSE); $copy = R::dispense('bean'); R::store($copy); $copy = R::load('bean', $copy->id); asrt($copy->getMeta('tainted'), FALSE); $copy->import(array('name' => 'xyz')); asrt($copy->getMeta('tainted'), TRUE); $copy->setMeta('tainted', FALSE); asrt($copy->getMeta('tainted'), FALSE); $copy->importFrom($bean); asrt($copy->getMeta('tainted'), TRUE); testpack('Test basic import() feature.'); $bean = new OODBBean(); $bean->import(array("a" => 1, "b" => 2)); asrt($bean->a, 1); asrt($bean->b, 2); $bean->import(array("a" => 3, "b" => 4), "a,b"); asrt($bean->a, 3); asrt($bean->b, 4); $bean->import(array("a" => 5, "b" => 6), " a , b "); asrt($bean->a, 5); asrt($bean->b, 6); $bean->import(array("a" => 1, "b" => 2)); testpack('Test inject() feature.'); $coffee = R::dispense('coffee'); $coffee->id = 2; $coffee->liquid = 'black'; $cup = R::dispense('cup'); $cup->color = 'green'; // Pour coffee in cup $cup->inject($coffee); // Do we still have our own property? asrt($cup->color, 'green'); // Did we pour the liquid in the cup? asrt($cup->liquid, 'black'); // Id should not be transferred asrt($cup->id, 0); }
/** * Alias for setAutoResolve() method on OODBBean. * Enables or disables auto-resolving fetch types. * Auto-resolving aliased parent beans is convenient but can * be slower and can create infinite recursion if you * used aliases to break cyclic relations in your domain. * * @param boolean $automatic TRUE to enable automatic resolving aliased parents * * @return void */ public static function setAutoResolve($automatic = TRUE) { OODBBean::setAutoResolve((bool) $automatic); }
/** * Part of the store() functionality. * Handles all new additions after the bean has been saved. * Stores addition bean in own-list, extracts the id and * adds a foreign key. Also adds a constraint in case the type is * in the dependent list. * * @param OODBBean $bean bean * @param array $ownAdditions list of addition beans in own-list * * @return void * * @throws Security */ protected function processAdditions($bean, $ownAdditions) { $beanType = $bean->getMeta('type'); $cachedIndex = array(); foreach ($ownAdditions as $addition) { if ($addition instanceof OODBBean) { $myFieldLink = $beanType . '_id'; $alias = $bean->getMeta('sys.alias.' . $addition->getMeta('type')); if ($alias) { $myFieldLink = $alias . '_id'; } $addition->{$myFieldLink} = $bean->id; $addition->setMeta('cast.' . $myFieldLink, 'id'); $this->store($addition); } else { throw new RedException('Array may only contain OODBBeans'); } } }
/** * Emulates legacy function for use with older tests. */ function set1toNAssoc($a, \RedBeanPHP\OODBBean $bean1, \RedBeanPHP\OODBBean $bean2) { $type = $bean1->getMeta("type"); $a->clearRelations($bean2, $type); $a->associate($bean1, $bean2); if (count($a->related($bean2, $type)) === 1) { // return $this; } else { throw new \RedBeanPHP\RedException\SQL("Failed to enforce 1-N Relation for {$type} "); } }
/** * Injects the properties of another bean but keeps the original ID. * Just like import() but keeps the original ID. * Chainable. * * @param OODBBean $otherBean the bean whose properties you would like to copy * * @return OODBBean */ public function inject(OODBBean $otherBean) { $myID = $this->properties['id']; $this->import($otherBean->export()); $this->id = $myID; return $this; }
/** * Checks whether a OODBBean bean is valid. * If the type is not valid or the ID is not valid it will * throw an exception: Security. * * @param OODBBean $bean the bean that needs to be checked * * @return void * * @throws Security $exception */ public function check(OODBBean $bean) { //Is all meta information present? if (!isset($bean->id)) { throw new RedException('Bean has incomplete Meta Information id '); } if (!$bean->getMeta('type')) { throw new RedException('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 RedException('Bean Type is invalid'); } //Are the properties and values valid? foreach ($bean as $prop => $value) { if (is_array($value) || is_object($value)) { throw new RedException("Invalid Bean value: property {$prop}"); } else { if (strlen($prop) < 1 || preg_match($pattern, $prop)) { throw new RedException("Invalid Bean property: property {$prop}"); } } } }
/** * 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; }
/** * Insert or Update a bean * * @param OODBBean $bean * @param $data array * @return Result */ private function saveBean($bean, $data) { // Handle File Field that may not in the $data, because Filename always go into $_FILES. foreach ($_FILES as $fieldName => $file) { $data[$fieldName] = $file["name"]; } // Store Showing fields only $fields = $this->getShowFields(); foreach ($fields as $field) { // Check is unique if ($field->isUnique()) { // Try to find duplicate beans $fieldName = $field->getName(); $duplicateBeans = R::find($bean->getMeta('type'), " {$fieldName} = ? ", [$data[$field->getName()]]); if (count($duplicateBeans) > 0) { $validateResult = "Email 已存在!"; } } if ($field->getFieldRelation() == Field::MANY_TO_MANY) { // 1. Many to many // http://www.redbeanphp.com/many_to_many $keyName = "shared" . ucfirst($field->getName()) . "List"; // Clear the current list (tableB_tableA) try { $tableName = $this->getTableName() . "_" . $field->getName(); $idName = $this->getTableName() . "_id"; R::exec("DELETE FROM {$tableName} WHERE {$idName} = ?", [$bean->id]); } catch (\Exception $ex) { } // Clear the current list (tableA_tableB) try { $tableName = $field->getName() . "_" . $this->getTableName(); $idName = $this->getTableName() . "_id"; R::exec("DELETE FROM {$tableName} WHERE {$idName} = ?", [$bean->id]); } catch (\Exception $ex) { } // If User have checked a value in checkbox if (isset($data[$field->getName()])) { $valueList = $data[$field->getName()]; $slots = R::genSlots($valueList); $relatedBeans = R::find($field->getName(), " id IN ({$slots})", $valueList); foreach ($relatedBeans as $relatedBean) { $bean->{$keyName}[] = $relatedBean; } } } else { if ($field->getFieldRelation() == Field::ONE_TO_MANY) { // TODO One to many } else { if (!$field->isStorable()) { // 2. If not storable, skip continue; } elseif ($field->getFieldRelation() == Field::NORMAL) { // 3.Normal data field $value = $field->getStoreValue($data); if ($value == LouisCRUD::NULL) { $value = null; } // Validate the value if ($field->isStorable()) { $validateResult = $field->validate($value, $data); } else { // TODO: check non-storable? $validateResult = true; } // If validate failed, return result object. if ($validateResult !== true) { $result = new Result(); $result->id = @$bean->id; $result->msg = $validateResult; $result->fieldName = $field->getName(); $result->class = "callout-danger"; return $result; } // Set the value to the current bean directly $bean->{$field->getName()} = $value; } } } } // Store // TODO: Return result object $id = R::store($bean); $result = new Result(); $result->id = $id; return $result; }