public function save($runValidation = true)
 {
     if (!parent::save($runValidation)) {
         return false;
     }
     foreach ($this->deferredRelateBeans as $bean) {
         if ($this->linkType == RedBeanModel::LINK_TYPE_POLYMORPHIC) {
             if ($this->bean->id == null) {
                 ZurmoRedBean::store($this->bean);
             }
             $polyIdFieldName = strtolower($this->linkName) . '_id';
             $polyTypeFieldName = strtolower($this->linkName) . '_type';
             $bean->{$polyTypeFieldName} = $this->bean->getMeta('type');
             $bean->{$polyIdFieldName} = $this->bean->id;
         } else {
             ZurmoRedBeanLinkManager::link($bean, $this->bean, $this->resolveLinkNameForCasing());
         }
         ZurmoRedBean::store($bean);
     }
     $this->deferredRelateBeans = array();
     $relatedModelClassName = $this->relatedModelClassName;
     $tableName = $relatedModelClassName::getTableName();
     foreach ($this->deferredUnrelateBeans as $bean) {
         if (!$this->owns) {
             if ($this->linkType == RedBeanModel::LINK_TYPE_POLYMORPHIC) {
                 throw new NotSupportedException("Polymorphic relations can not be NOT_OWNED");
             }
             ZurmoRedBeanLinkManager::breakLink($bean, $tableName, $this->resolveLinkNameForCasing());
             ZurmoRedBean::store($bean);
         } else {
             ZurmoRedBean::trash($bean);
         }
     }
     $this->deferredUnrelatedBeans = array();
     foreach ($this->deferredUnrelatedModels as $model) {
         $event = new CModelEvent($model);
         $model->onRedBeanOneToManyRelatedModelsChange($event);
     }
     $this->deferredUnrelatedModels = array();
     return true;
 }
 public function save($runValidation = true)
 {
     if (!parent::save($runValidation)) {
         return false;
     }
     foreach ($this->deferredRelateBeans as $bean) {
         if ($this->linkType == RedBeanModel::LINK_TYPE_POLYMORPHIC) {
             if ($this->bean->id == null) {
                 R::store($this->bean);
             }
             $polyIdFieldName = strtolower($this->linkName) . '_id';
             $polyTypeFieldName = strtolower($this->linkName) . '_type';
             $bean->{$polyTypeFieldName} = $this->bean->getMeta('type');
             $bean->{$polyIdFieldName} = $this->bean->id;
             if (!RedBeanDatabase::isFrozen()) {
                 $tableName = RedBeanModel::getTableName($this->modelClassName);
                 RedBeanColumnTypeOptimizer::optimize($tableName, $polyIdFieldName, 'id');
             }
         } else {
             ZurmoRedBeanLinkManager::link($bean, $this->bean, $this->resolveLinkNameForCasing());
             if (!RedBeanDatabase::isFrozen()) {
                 $tableName = RedBeanModel::getTableName($this->modelClassName);
                 $columnName = RedBeanModel::getTableName($this->relatedModelClassName) . '_id';
                 $columnName = ZurmoRedBeanLinkManager::resolveColumnPrefix($this->resolveLinkNameForCasing()) . $columnName;
                 RedBeanColumnTypeOptimizer::optimize($tableName, $columnName, 'id');
             }
         }
         R::store($bean);
     }
     $this->deferredRelateBeans = array();
     $tableName = RedBeanModel::getTableName($this->relatedModelClassName);
     foreach ($this->deferredUnrelateBeans as $bean) {
         if (!$this->owns) {
             ZurmoRedBeanLinkManager::breakLink($bean, $tableName, $this->resolveLinkNameForCasing());
             R::store($bean);
         } else {
             R::trash($bean);
         }
     }
     $this->deferredUnrelateBeans = array();
     return true;
 }
예제 #3
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;
     }
 }
예제 #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;
     }
 }