@ -13,6 +13,7 @@ use yii\db\BaseActiveRecord; 
			
		
	
		
		
			
				
					
					use yii\db\Transaction; use yii\db\Transaction;  
			
		
	
		
		
			
				
					
					use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;  
			
		
	
		
		
			
				
					
					use yii\helpers\Inflector; use yii\helpers\Inflector;  
			
		
	
		
		
			
				
					
					use yii\helpers\VarDumper;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					/** /**  
			
		
	
		
		
			
				
					
					 * This Active Record Behavior allows to validate and save the Model relations when the save() method is invoked.  * This Active Record Behavior allows to validate and save the Model relations when the save() method is invoked.  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -29,12 +30,13 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					    private $_transaction;     private $_transaction;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    private $_relationsScenario = [];     private $_relationsScenario = [];  
			
		
	
		
		
			
				
					
					    private $_relationsCascadeDelete = []; 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    //private $_relationsCascadeDelete = []; //TODO  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    public function init()     public function init()  
			
		
	
		
		
			
				
					
					    {     {  
			
		
	
		
		
			
				
					
					        parent::init();         parent::init();  
			
		
	
		
		
			
				
					
					        $allowedProperties = ['scenario', 'cascadeDelete' ];         $allowedProperties = ['scenario'];  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        foreach ($this->relations as $key => $value) {         foreach ($this->relations as $key => $value) {  
			
		
	
		
		
			
				
					
					            if (is_int($key)) {             if (is_int($key)) {  
			
		
	
		
		
			
				
					
					                $this->_relations[] = $value;                 $this->_relations[] = $value;  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -102,7 +104,15 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					        if (in_array($name, $this->_relations)) {         if (in_array($name, $this->_relations)) {  
			
		
	
		
		
			
				
					
					            Yii::trace("Setting {$name} relation value", __METHOD__);             Yii::trace("Setting {$name} relation value", __METHOD__);  
			
		
	
		
		
			
				
					
					            if (!isset($this->_oldRelationValue[$name])) {             if (!isset($this->_oldRelationValue[$name])) {  
			
		
	
		
		
			
				
					
					                $this->_oldRelationValue[$name] = $this->owner->{$name};                 if ($this->owner->isNewRecord) {  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                    if ($this->owner->getRelation($name)->multiple === true) {  
			
		
	
		
		
			
				
					
					                        $this->_oldRelationValue[$name] = [];  
			
		
	
		
		
			
				
					
					                    } else {  
			
		
	
		
		
			
				
					
					                        $this->_oldRelationValue[$name] = null;  
			
		
	
		
		
			
				
					
					                    }  
			
		
	
		
		
			
				
					
					                } else {  
			
		
	
		
		
			
				
					
					                    $this->_oldRelationValue[$name] = $this->owner->{$name};  
			
		
	
		
		
			
				
					
					                }  
			
		
	
		
		
			
				
					
					            }             }  
			
		
	
		
		
			
				
					
					            if ($this->owner->getRelation($name)->multiple === true) {             if ($this->owner->getRelation($name)->multiple === true) {  
			
		
	
		
		
			
				
					
					                $this->setMultipleRelation($name, $value);                 $this->setMultipleRelation($name, $value);  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -174,8 +184,7 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					                    $fks[$modelAttribute] = $data[$modelAttribute];                     $fks[$modelAttribute] = $data[$modelAttribute];  
			
		
	
		
		
			
				
					
					                }                 }  
			
		
	
		
		
			
				
					
					            }             }  
			
		
	
		
		
			
				
					
					
            if (empty($fks)) {  
			
				
				
			
		
	
		
		
			
				
					
					            if (!$fks) {  
			
		
	
		
		
	
		
		
			
				
					
					                // Get the right link definition                 // Get the right link definition  
			
		
	
		
		
			
				
					
					                if ($relation->via instanceof BaseActiveRecord) {                 if ($relation->via instanceof BaseActiveRecord) {  
			
		
	
		
		
			
				
					
					                    $viaQuery = $relation->via;                     $viaQuery = $relation->via;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -186,7 +195,6 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					                } else {                 } else {  
			
		
	
		
		
			
				
					
					                    $link = $relation->link;                     $link = $relation->link;  
			
		
	
		
		
			
				
					
					                }                 }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					                foreach ($link as $relatedAttribute => $modelAttribute) {                 foreach ($link as $relatedAttribute => $modelAttribute) {  
			
		
	
		
		
			
				
					
					                    if (array_key_exists($modelAttribute, $data) & &  !empty($data[$modelAttribute])) {                     if (array_key_exists($modelAttribute, $data) & &  !empty($data[$modelAttribute])) {  
			
		
	
		
		
			
				
					
					                        $fks[$modelAttribute] = $data[$modelAttribute];                         $fks[$modelAttribute] = $data[$modelAttribute];  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -317,9 +325,9 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					        /** @var BaseActiveRecord $model */         /** @var BaseActiveRecord $model */  
			
		
	
		
		
			
				
					
					        $model = $this->owner;         $model = $this->owner;  
			
		
	
		
		
			
				
					
					        if (!is_null($relationModel) & &  ($relationModel->isNewRecord || count($relationModel->getDirtyAttributes()))) {         if (!is_null($relationModel) & &  ($relationModel->isNewRecord || count($relationModel->getDirtyAttributes()))) {  
			
		
	
		
		
			
				
					
					//            if (key_exists($relationModel , $this->_relationsScenario)) {            if (key_exists($relationName , $this->_relationsScenario)) { 
			
				
				
			
		
	
		
		
			
				
					
					//                 $relationModel->setScenario($this->_relationsScenario[$relationModel ]);                $relationModel->setScenario($this->_relationsScenario[$relationName ]);  
			
				
				
			
		
	
		
		
			
				
					
					//             }            }  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					            Yii::trace("Validating {$pettyRelationName} relation model using " . $relationModel->scenario . " scenario", __METHOD__);             Yii::trace("Validating {$pettyRelationName} relation model using " . $relationModel->scenario . " scenario", __METHOD__);  
			
		
	
		
		
			
				
					
					            if (!$relationModel->validate()) {             if (!$relationModel->validate()) {  
			
		
	
		
		
			
				
					
					                foreach ($relationModel->errors as $attributeErrors) {                 foreach ($relationModel->errors as $attributeErrors) {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -343,56 +351,70 @@ class SaveRelationsBehavior extends Behavior 
			
		
	
		
		
			
				
					
					            /** @var BaseActiveRecord $model */             /** @var BaseActiveRecord $model */  
			
		
	
		
		
			
				
					
					            $model = $this->owner;             $model = $this->owner;  
			
		
	
		
		
			
				
					
					            $this->_relationsSaveStarted = true;             $this->_relationsSaveStarted = true;  
			
		
	
		
		
			
				
					
					            foreach ($this->_relations as $relationName) {             try {  
			
				
				
			
		
	
		
		
			
				
					
					                if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...                 foreach ($this->_relations as $relationName) {  
			
				
				
			
		
	
		
		
			
				
					
					                    Yii::trace("Linking {$relationName} relation", __METHOD__);                     if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...  
			
				
				
			
		
	
		
		
			
				
					
					                    $relation = $model->getRelation($relationName);                         Yii::trace("Linking {$relationName} relation", __METHOD__);  
			
				
				
			
		
	
		
		
			
				
					
					                    if ($relation->multiple === true) { // Has many relation                         $relation = $model->getRelation($relationName);  
			
				
				
			
		
	
		
		
			
				
					
					                        // Process new relations                         if ($relation->multiple === true) { // Has many relation  
			
				
				
			
		
	
		
		
			
				
					
					                        $existingRecords = [];                             // Process new relations  
			
				
				
			
		
	
		
		
			
				
					
					                        /** @var BaseActiveRecord $relationModel */                             $existingRecords = [];  
			
				
				
			
		
	
		
		
			
				
					
					                        foreach ($model->{$relationName} as $relationModel) { 
 
			
				
				
			
		
	
		
		
			
				
					
					                            if ($relationModel->isNewRecord) {                             /** @var BaseActiveRecord $relationModel */  
			
				
				
			
		
	
		
		
			
				
					
					                                if ($relation->via !== null) {                             foreach ($model->{$relationName} as $relationModel) {  
			
				
				
			
		
	
		
		
			
				
					
					                                    $relationModel->save(false);                                 if ($relationModel->isNewRecord) {  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					                                    if ($relation->via !== null) {  
			
		
	
		
		
			
				
					
					                                        if (!$relationModel->save()) {  
			
		
	
		
		
			
				
					
					                                            throw new Exception('Related model ' . $relationName . ' could not be saved (' . VarDumper::dumpAsString($relationModel->getErrors()) . ')');  
			
		
	
		
		
			
				
					
					                                        }  
			
		
	
		
		
			
				
					
					                                    }  
			
		
	
		
		
			
				
					
					                                    $model->link($relationName, $relationModel);  
			
		
	
		
		
			
				
					
					                                } else {  
			
		
	
		
		
			
				
					
					                                    $existingRecords[] = $relationModel;  
			
		
	
		
		
			
				
					
					                                }  
			
		
	
		
		
			
				
					
					                                if (count($relationModel->dirtyAttributes)) {  
			
		
	
		
		
			
				
					
					                                    if (!$relationModel->save()) {  
			
		
	
		
		
			
				
					
					                                        throw new Exception('Related model ' . $relationName . ' could not be saved (' . VarDumper::dumpAsString($relationModel->getErrors()) . ')');  
			
		
	
		
		
			
				
					
					                                    }  
			
		
	
		
		
			
				
					
					                                }                                 }  
			
		
	
		
		
			
				
					
					                                $model->link($relationName, $relationModel);  
			
		
	
		
		
			
				
					
					                            } else {  
			
		
	
		
		
			
				
					
					                                $existingRecords[] = $relationModel;  
			
		
	
		
		
			
				
					
					                            }                             }  
			
		
	
		
		
			
				
					
					                            if (count($relationModel->dirtyAttributes)) {                             // Process existing added and deleted relations  
			
				
				
			
		
	
		
		
			
				
					
					                                $relationModel->save(false);                             list($addedPks, $deletedPks) = $this->_computePkDiff($this->_oldRelationValue[$relationName], $existingRecords);  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					                            // Deleted relations  
			
		
	
		
		
			
				
					
					                            $initialModels = ArrayHelper::index($this->_oldRelationValue[$relationName], function (BaseActiveRecord $model) {  
			
		
	
		
		
			
				
					
					                                return implode("-", $model->getPrimaryKey(true));  
			
		
	
		
		
			
				
					
					                            });  
			
		
	
		
		
			
				
					
					                            foreach ($deletedPks as $key) {  
			
		
	
		
		
			
				
					
					                                $model->unlink($relationName, $initialModels[$key], true);  
			
		
	
		
		
			
				
					
					                            }                             }  
			
		
	
		
		
			
				
					
					                        }                             // Added relations  
			
				
				
			
		
	
		
		
			
				
					
					                        // Process existing added and deleted relations                             $actualModels = ArrayHelper::index($model->{$relationName}, function (BaseActiveRecord $model) {  
			
				
				
			
		
	
		
		
			
				
					
					                        list($addedPks, $deletedPks) = $this->_computePkDiff($this->_oldRelationValue[$relationName], $existingRecords);                                 return implode("-", $model->getPrimaryKey(true));  
			
				
				
			
		
	
		
		
			
				
					
					                        // Deleted relations                             });  
			
				
				
			
		
	
		
		
			
				
					
					                        $initialModels = ArrayHelper::index($this->_oldRelationValue[$relationName], function (BaseActiveRecord $model) {                             foreach ($addedPks as $key) {  
			
				
				
			
		
	
		
		
			
				
					
					                            return implode("-", $model->getPrimaryKey(true));                                 $model->link($relationName, $actualModels[$key]);  
			
				
				
			
		
	
		
		
			
				
					
					                        });                             }  
			
				
				
			
		
	
		
		
			
				
					
					                        foreach ($deletedPks as $key) {                         } else { // Has one relation  
			
				
				
			
		
	
		
		
			
				
					
					                            $model->unlink($relationName, $initialModels[$key], true);                             if ($this->_oldRelationValue[$relationName] !== $model->{$relationName}) {  
			
				
				
			
		
	
		
		
			
				
					
					                        }                                 if ($model->{$relationName} instanceof BaseActiveRecord) {  
			
				
				
			
		
	
		
		
			
				
					
					                        // Added relations                                     $model->link($relationName, $model->{$relationName});  
			
				
				
			
		
	
		
		
			
				
					
					                        $actualModels = ArrayHelper::index($model->{$relationName}, function (BaseActiveRecord $model) {                                 } else {  
			
				
				
			
		
	
		
		
			
				
					
					                            return implode("-", $model->getPrimaryKey(true));                                     if ($this->_oldRelationValue[$relationName] instanceof BaseActiveRecord) {  
			
				
				
			
		
	
		
		
			
				
					
					                        });                                         $model->unlink($relationName, $this->_oldRelationValue[$relationName]);  
			
				
				
			
		
	
		
		
			
				
					
					                        foreach ($addedPks as $key) {                                     }  
			
				
				
			
		
	
		
		
			
				
					
					                            $model->link($relationName, $actualModels[$key]);  
			
		
	
		
		
			
				
					
					                        }  
			
		
	
		
		
			
				
					
					                    } else { // Has one relation  
			
		
	
		
		
			
				
					
					                        if ($this->_oldRelationValue[$relationName] !== $model->{$relationName}) {  
			
		
	
		
		
			
				
					
					                            if ($model->{$relationName} instanceof BaseActiveRecord) {  
			
		
	
		
		
			
				
					
					                                $model->link($relationName, $model->{$relationName});  
			
		
	
		
		
			
				
					
					                            } else {  
			
		
	
		
		
			
				
					
					                                if ($this->_oldRelationValue[$relationName] instanceof BaseActiveRecord) {  
			
		
	
		
		
			
				
					
					                                    $model->unlink($relationName, $this->_oldRelationValue[$relationName]);  
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					                                }                                 }  
			
		
	
		
		
			
				
					
					                            }                             }  
			
		
	
		
		
			
				
					
					                        }                         }  
			
		
	
		
		
			
				
					
					                        unset($this->_oldRelationValue[$relationName]);  
			
		
	
		
		
			
				
					
					                    }                     }  
			
		
	
		
		
			
				
					
					                    unset($this->_oldRelationValue[$relationName]);  
			
		
	
		
		
			
				
					
					                }                 }  
			
		
	
		
		
			
				
					
					            } catch (Exception $e) {  
			
		
	
		
		
			
				
					
					                Yii::warning(get_class($e) . " was thrown during the saving of related records : " . $e->getMessage(), __METHOD__);  
			
		
	
		
		
			
				
					
					                if (($this->_transaction instanceof Transaction) & &  $this->_transaction->isActive) {  
			
		
	
		
		
			
				
					
					                    $this->_transaction->rollBack(); // If anything goes wrong, transaction will be rolled back  
			
		
	
		
		
			
				
					
					                    Yii::info("Rolling back", __METHOD__);  
			
		
	
		
		
			
				
					
					                }  
			
		
	
		
		
			
				
					
					                throw $e;  
			
		
	
		
		
			
				
					
					            }             }  
			
		
	
		
		
			
				
					
					            $model->refresh();             $model->refresh();  
			
		
	
		
		
			
				
					
					            $this->_relationsSaveStarted = false;             $this->_relationsSaveStarted = false;