Esempio n. 1
0
 /**
  * Saves the model to the database. Models are only saved if they have been
  * modified and related models are saved before this model. If a related model
  * is modified and needs saving the deems the model to be modified and need
  * saving, which ensures that keys are updated.
  * Cyclic relationships are prevented from causing problems by the
  * save only proceeding to non-saved models.
  */
 public function save($runValidation = true, array $attributeNames = null)
 {
     if ($attributeNames !== null) {
         throw new NotSupportedException();
     }
     if ($this->isSaving) {
         return true;
     }
     $this->isSaving = true;
     try {
         if (!$runValidation || $this->validate()) {
             if ($this->beforeSave()) {
                 $beans = array_values($this->modelClassNameToBean);
                 $this->linkBeans();
                 // The breakLink/link is deferred until the save to avoid
                 // disconnecting or creating an empty row if the model was
                 // never actually saved.
                 foreach ($this->unlinkedRelationNames as $key => $relationName) {
                     $bean = $this->attributeNameToBeanAndClassName[$relationName][0];
                     $relationAndOwns = static::getRelationNameToRelationTypeModelClassNameAndOwnsForModel();
                     $relatedModelClassName = $relationAndOwns[$relationName][1];
                     $tempRelatedModelClassName = $relatedModelClassName;
                     self::resolveModelClassNameForClassesWithoutBeans($tempRelatedModelClassName);
                     $relatedTableName = self::getTableName($tempRelatedModelClassName);
                     $linkName = strtolower($relationName);
                     if ($linkName == strtolower($relatedModelClassName)) {
                         $linkName = null;
                     } elseif (static::getRelationType($relationName) == self::HAS_ONE && static::getRelationLinkType($relationName) == self::LINK_TYPE_SPECIFIC) {
                         $linkName = strtolower(static::getRelationLinkName($relationName));
                     }
                     ZurmoRedBeanLinkManager::breakLink($bean, $relatedTableName, $linkName);
                     //Check the $this->{$relationName} second in the if clause to avoid accidentially getting
                     //a relation to now save. //todo: this needs to be properly handled.
                     if (isset($this->unlinkedOwnedRelatedModelsToRemove[$relationName]) && $this->{$relationName} !== null) {
                         //Remove hasOne owned related models that are no longer needed because they have
                         //been replaced with another hasOne owned model.
                         if ($this->unlinkedOwnedRelatedModelsToRemove[$relationName]->id > 0) {
                             $this->unlinkedOwnedRelatedModelsToRemove[$relationName]->unrestrictedDelete();
                         }
                         unset($this->unlinkedOwnedRelatedModelsToRemove[$relationName]);
                     }
                     unset($this->unlinkedRelationNames[$key]);
                 }
                 assert('count($this->unlinkedRelationNames) == 0');
                 foreach ($this->relationNameToRelatedModel as $relationName => $relatedModel) {
                     $relationAndOwns = static::getRelationNameToRelationTypeModelClassNameAndOwnsForModel();
                     $relationType = $relationAndOwns[$relationName][0];
                     if (!in_array($relationType, array(self::HAS_ONE_BELONGS_TO, self::HAS_MANY_BELONGS_TO))) {
                         if ($relatedModel->isModified() || $this->isAttributeRequired($relationName)) {
                             //If the attribute is required, but already exists and has not been modified we do
                             //not have to worry about saving it.
                             if ($this->isSavableFromRelation && !($this->isAttributeRequired($relationName) && !$relatedModel->isModified() && $relatedModel->id > 0)) {
                                 if (!$relatedModel->save(false)) {
                                     $this->isSaving = false;
                                     return false;
                                 }
                             } elseif ($relatedModel->isModified()) {
                                 throw new NotSuportedException();
                             }
                         }
                     }
                     if ($relatedModel instanceof RedBeanModel) {
                         $bean = $this->attributeNameToBeanAndClassName[$relationName][0];
                         $relationAndOwns = static::getRelationNameToRelationTypeModelClassNameAndOwnsForModel();
                         $relatedModelClassName = $relationAndOwns[$relationName][1];
                         $linkName = strtolower($relationName);
                         if (strtolower($linkName) == strtolower($relatedModelClassName) || static::getRelationLinkType($relationName) == self::LINK_TYPE_ASSUMPTIVE) {
                             $linkName = null;
                         } elseif ($relationType == self::HAS_ONE && static::getRelationLinkType($relationName) == self::LINK_TYPE_SPECIFIC) {
                             $linkName = strtolower(static::getRelationLinkName($relationName));
                         } elseif ($relationType == RedBeanModel::HAS_MANY_BELONGS_TO || $relationType == RedBeanModel::HAS_ONE_BELONGS_TO) {
                             $label = 'Relations of type HAS_MANY_BELONGS_TO OR HAS_ONE_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}' => $linkName, '{relationModelClassName}' => $relatedModelClassName)));
                         }
                         //Needed to exclude HAS_ONE_BELONGS_TO because an additional column was being created
                         //on the wrong side.
                         if ($relationType != RedBeanModel::HAS_ONE_BELONGS_TO && ($relatedModel->isModified() || $relatedModel->id > 0 || $this->isAttributeRequired($relationName))) {
                             $relatedModel = $this->relationNameToRelatedModel[$relationName];
                             $relatedBean = $relatedModel->getClassBean($relatedModelClassName);
                             //Exclude HAS_MANY_BELONGS_TO because if the existing relation is unlinked, then
                             //this link should not be reactivated, because it will improperly create the bean
                             //in the database.
                             if (!($relationType == RedBeanModel::HAS_MANY_BELONGS_TO && $this->{$relationName}->id < 0)) {
                                 ZurmoRedBeanLinkManager::link($bean, $relatedBean, $linkName);
                             }
                             if (!RedBeanDatabase::isFrozen()) {
                                 $tableName = self::getTableName(static::getAttributeModelClassName($relationName));
                                 $columnName = self::getForeignKeyName(get_class($this), $relationName);
                                 RedBeanColumnTypeOptimizer::optimize($tableName, $columnName, 'id');
                             }
                         }
                     }
                 }
                 $baseModelClassName = null;
                 foreach ($this->modelClassNameToBean as $modelClassName => $bean) {
                     R::store($bean);
                     assert('$bean->id > 0');
                     if (!RedBeanDatabase::isFrozen()) {
                         static::resolveMixinsOnSaveForEnsuringColumnsAreCorrectlyFormed($baseModelClassName, $modelClassName);
                         $baseModelClassName = $modelClassName;
                     }
                 }
                 $this->modified = false;
                 $this->afterSave();
                 $calledModelClassName = get_called_class();
                 if ($calledModelClassName::isCacheable()) {
                     RedBeanModelsCache::cacheModel($this);
                 }
                 $this->isSaving = false;
                 return true;
             }
         }
         $this->isSaving = false;
         return false;
     } catch (Exception $e) {
         $this->isSaving = false;
         throw $e;
     }
 }
Esempio n. 2
0
 public function testMixedInPersonInUser()
 {
     $user = new User();
     $user->username = '******';
     $user->lastName = 'Dude';
     $this->assertTrue($user->save());
     $this->assertTrue($user->isAttribute('id'));
     // From RedBeanModel.
     $this->assertTrue($user->isAttribute('createdDateTime'));
     // From Item.
     $this->assertTrue($user->isAttribute('firstName'));
     // From Person.
     $this->assertTrue($user->isAttribute('username'));
     // From User.
     $this->assertTrue($user->isRelation('createdByUser'));
     // From Item.
     $this->assertTrue($user->isRelation('rights'));
     // From Permitable.
     $this->assertTrue($user->isRelation('title'));
     // From Person.
     $this->assertTrue($user->isRelation('manager'));
     // From User.
     unset($user);
     $user = User::getByUsername('dude');
     $this->assertTrue($user->isAttribute('id'));
     // From RedBeanModel.
     $this->assertTrue($user->isAttribute('createdDateTime'));
     // From Item.
     $this->assertTrue($user->isAttribute('firstName'));
     // From Person.
     $this->assertTrue($user->isAttribute('username'));
     // From User.
     $this->assertTrue($user->isRelation('createdByUser'));
     // From Item.
     $this->assertTrue($user->isRelation('rights'));
     // From Permitable.
     $this->assertTrue($user->isRelation('title'));
     // From Person.
     $this->assertTrue($user->isRelation('manager'));
     // From User.
     RedBeanModelsCache::cacheModel($user);
     $modelIdentifier = $user->getModelIdentifier();
     unset($user);
     RedBeanModelsCache::forgetAll(true);
     // Forget it at the php level.
     RedBeansCache::forgetAll();
     if (MEMCACHE_ON) {
         $user = RedBeanModelsCache::getModel($modelIdentifier);
         $this->assertTrue($user->isAttribute('id'));
         // From RedBeanModel.
         $this->assertTrue($user->isAttribute('createdDateTime'));
         // From Item.
         $this->assertTrue($user->isAttribute('firstName'));
         // From Person.
         $this->assertTrue($user->isAttribute('username'));
         // From User.
         $this->assertTrue($user->isRelation('createdByUser'));
         // From Item.
         $this->assertTrue($user->isRelation('rights'));
         // From Permitable.
         $this->assertTrue($user->isRelation('title'));
         // From Person.
         $this->assertTrue($user->isRelation('manager'));
         // From User.
     }
 }
 public function testFileContentModelNotBeingCached()
 {
     $fileContent = new FileContent();
     $fileContent->content = str_repeat('a', 1000);
     $this->assertTrue($fileContent->save());
     $modelIdentifier = $fileContent->getModelIdentifier();
     RedBeanModelsCache::cacheModel($fileContent);
     try {
         RedBeanModelsCache::getModel($modelIdentifier);
     } catch (NotFoundException $e) {
         $this->fail('NotFoundException exception is thrown.');
     }
     $prefix = RedBeanModelsCache::getCachePrefix($modelIdentifier, RedBeanModelsCache::$cacheType);
     $cachedData = false;
     if (isset(Yii::app()->cache)) {
         $cachedData = Yii::app()->cache->get($prefix . $modelIdentifier);
     }
     $this->assertFalse($cachedData);
 }
Esempio n. 4
0
 /**
  * Saves the model to the database. Models are only saved if they have been
  * modified and related models are saved before this model. If a related model
  * is modified and needs saving the deems the model to be modified and need
  * saving, which ensures that keys are updated.
  * Cyclic relationships are prevented from causing problems by the
  * save only proceeding to non-saved models.
  */
 public function save($runValidation = true, array $attributeNames = null)
 {
     if ($attributeNames !== null) {
         throw new NotSupportedException();
     }
     if ($this->isSaving) {
         return true;
     }
     $this->isSaving = true;
     try {
         if (!$runValidation || $this->validate()) {
             if ($this->beforeSave()) {
                 $beans = array_values($this->modelClassNameToBean);
                 $this->linkBeans();
                 // The breakLink/link is deferred until the save to avoid
                 // disconnecting or creating an empty row if the model was
                 // never actually saved.
                 foreach ($this->unlinkedRelationNames as $key => $relationName) {
                     $bean = $this->attributeNameToBeanAndClassName[$relationName][0];
                     $relatedModelClassName = $this->relationNameToRelationTypeModelClassNameAndOwns[$relationName][1];
                     $relatedTableName = self::getTableName($relatedModelClassName);
                     $linkName = strtolower($relationName);
                     if ($linkName == strtolower($relatedModelClassName)) {
                         $linkName = null;
                     }
                     ZurmoRedBeanLinkManager::breakLink($bean, $relatedTableName, $linkName);
                     unset($this->unlinkedRelationNames[$key]);
                 }
                 assert('count($this->unlinkedRelationNames) == 0');
                 foreach ($this->relationNameToRelatedModel as $relationName => $relatedModel) {
                     $relationType = $this->relationNameToRelationTypeModelClassNameAndOwns[$relationName][0];
                     if (!in_array($relationType, array(self::HAS_ONE_BELONGS_TO, self::HAS_MANY_BELONGS_TO))) {
                         if ($relatedModel->isModified() || $this->isAttributeRequired($relationName)) {
                             //If the attribute is required, but already exists and has not been modified we do
                             //not have to worry about saving it.
                             if ($this->isSavableFromRelation && !($this->isAttributeRequired($relationName) && !$relatedModel->isModified() && $relatedModel->id > 0)) {
                                 if (!$relatedModel->save(false)) {
                                     $this->isSaving = false;
                                     return false;
                                 }
                             } elseif ($relatedModel->isModified()) {
                                 throw new NotSuportedException();
                             }
                         }
                     }
                     if ($relatedModel instanceof RedBeanModel) {
                         $bean = $this->attributeNameToBeanAndClassName[$relationName][0];
                         $relatedModelClassName = $this->relationNameToRelationTypeModelClassNameAndOwns[$relationName][1];
                         $linkName = strtolower($relationName);
                         if (strtolower($linkName) == strtolower($relatedModelClassName)) {
                             $linkName = null;
                         } elseif ($relationType == RedBeanModel::HAS_MANY_BELONGS_TO || $relationType == RedBeanModel::HAS_ONE_BELONGS_TO) {
                             $label = 'Relations of type HAS_MANY_BELONGS_TO OR HAS_ONE_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(Yii::t('Default', $label, array('{relationName}' => $linkName, '{relationModelClassName}' => $relatedModelClassName)));
                         }
                         //Needed to exclude HAS_ONE_BELONGS_TO because an additional column was being created
                         //on the wrong side.
                         if ($relationType != RedBeanModel::HAS_ONE_BELONGS_TO && ($relatedModel->isModified() || $relatedModel->id > 0 || $this->isAttributeRequired($relationName))) {
                             $relatedModel = $this->relationNameToRelatedModel[$relationName];
                             $relatedBean = $relatedModel->getClassBean($relatedModelClassName);
                             ZurmoRedBeanLinkManager::link($bean, $relatedBean, $linkName);
                             if (!RedBeanDatabase::isFrozen()) {
                                 $tableName = self::getTableName($this->getAttributeModelClassName($relationName));
                                 $columnName = self::getForeignKeyName(get_class($this), $relationName);
                                 RedBeanColumnTypeOptimizer::optimize($tableName, $columnName, 'id');
                             }
                         }
                     }
                 }
                 $baseModelClassName = null;
                 foreach ($this->modelClassNameToBean as $modelClassName => $bean) {
                     R::store($bean);
                     assert('$bean->id > 0');
                     if (!RedBeanDatabase::isFrozen()) {
                         static::resolveMixinsOnSaveForEnsuringColumnsAreCorrectlyFormed($baseModelClassName, $modelClassName);
                         $baseModelClassName = $modelClassName;
                     }
                 }
                 $this->modified = false;
                 $this->afterSave();
                 RedBeanModelsCache::cacheModel($this);
                 $this->isSaving = false;
                 return true;
             }
         }
         $this->isSaving = false;
         return false;
     } catch (Exception $e) {
         $this->isSaving = false;
         throw $e;
     }
 }