@ -10,10 +10,10 @@ use yii\base\ModelEvent;
					 
			
		
	
		
			
				
					use yii\base\UnknownPropertyException;  
			
		
	
		
			
				
					use yii\db\ActiveQueryInterface;  
			
		
	
		
			
				
					use yii\db\BaseActiveRecord;  
			
		
	
		
			
				
					use Yii\db\Exception as DbException;  
			
		
	
		
			
				
					use yii\db\Transaction;  
			
		
	
		
			
				
					use yii\helpers\ArrayHelper;  
			
		
	
		
			
				
					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.  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -179,7 +179,7 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					            $fks = [];  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            // search PK  
			
		
	
		
			
				
					            foreach($modelClass::primaryKey() as $modelAttribute) {  
			
		
	
		
			
				
					            foreach  ($modelClass::primaryKey() as $modelAttribute) {  
			
		
	
		
			
				
					                if (array_key_exists($modelAttribute, $data) & &  !empty($data[$modelAttribute])) {  
			
		
	
		
			
				
					                    $fks[$modelAttribute] = $data[$modelAttribute];  
			
		
	
		
			
				
					                }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -287,10 +287,7 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        } 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__);  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					            $this->_rollback();  
			
		
	
		
			
				
					            $event->isValid = false; // Stop saving, something went wrong  
			
		
	
		
			
				
					            return false;  
			
		
	
		
			
				
					        }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -330,12 +327,7 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					            Yii::trace("Validating {$pettyRelationName} relation model using " . $relationModel->scenario . " scenario", __METHOD__);  
			
		
	
		
			
				
					            if (!$relationModel->validate()) {  
			
		
	
		
			
				
					                foreach ($relationModel->errors as $attributeErrors) {  
			
		
	
		
			
				
					                    foreach ($attributeErrors as $error) {  
			
		
	
		
			
				
					                        $model->addError($relationName, "{$pettyRelationName}: {$error}");  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    $event->isValid = false;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                $this->_addError($relationModel, $model, $relationName, $pettyRelationName);  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -352,6 +344,8 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					            $model = $this->owner;  
			
		
	
		
			
				
					            $this->_relationsSaveStarted = true;  
			
		
	
		
			
				
					            try {  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                foreach ($this->_relations as $relationName) {  
			
		
	
		
			
				
					                    if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...  
			
		
	
		
			
				
					                        Yii::trace("Linking {$relationName} relation", __METHOD__);  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -361,11 +355,15 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					                            $existingRecords = [];  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            /** @var BaseActiveRecord $relationModel */  
			
		
	
		
			
				
					                            foreach ($model->{$relationName} as $relationModel) {  
			
		
	
		
			
				
					                            foreach ($model->{$relationName} as $i => $ relationModel) {  
			
		
	
		
			
				
					                                if ($relationModel->isNewRecord) {  
			
		
	
		
			
				
					                                    if ($relation->via !== null) {  
			
		
	
		
			
				
					                                        if (!$relationModel->save()) {  
			
		
	
		
			
				
					                                            throw new Exception('Related model ' . $relationName . ' could not be saved (' . VarDumper::dumpAsString($relationModel->getErrors()) . ')');  
			
		
	
		
			
				
					                                        if ($relationModel->validate()) {  
			
		
	
		
			
				
					                                            $relationModel->save();  
			
		
	
		
			
				
					                                        } else {  
			
		
	
		
			
				
					                                            $pettyRelationName = Inflector::camel2words($relationName, true) . " #{$i}";  
			
		
	
		
			
				
					                                            $this->_addError($relationModel, $model, $relationName, $pettyRelationName);  
			
		
	
		
			
				
					                                            throw new DbException("Related record {$pettyRelationName} could not be saved.");  
			
		
	
		
			
				
					                                        }  
			
		
	
		
			
				
					                                    }  
			
		
	
		
			
				
					                                    $model->link($relationName, $relationModel);  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -373,8 +371,12 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					                                    $existingRecords[] = $relationModel;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                                if (count($relationModel->dirtyAttributes)) {  
			
		
	
		
			
				
					                                    if (!$relationModel->save()) {  
			
		
	
		
			
				
					                                        throw new Exception('Related model ' . $relationName . ' could not be saved (' . VarDumper::dumpAsString($relationModel->getErrors()) . ')');  
			
		
	
		
			
				
					                                    if ($relationModel->validate()) {  
			
		
	
		
			
				
					                                        $relationModel->save();  
			
		
	
		
			
				
					                                    } else {  
			
		
	
		
			
				
					                                        $pettyRelationName = Inflector::camel2words($relationName, true);  
			
		
	
		
			
				
					                                        $this->_addError($relationModel, $model, $relationName, $pettyRelationName);  
			
		
	
		
			
				
					                                        throw new DbException("Related record {$pettyRelationName} could not be saved.");  
			
		
	
		
			
				
					                                    }  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -409,11 +411,11 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					            } 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__);   
			
		
	
		
			
				
					                }   
			
		
	
		
			
				
					                $this->_rollback( );  
			
		
	
		
			
				
					                /***   
			
		
	
		
			
				
					                 * Sadly mandatory because the error occurred during afterSave event   
			
		
	
		
			
				
					                 * and we don't want the user/developper not to be aware of the issue.   
			
		
	
		
			
				
					                 ***/   
			
		
	
		
			
				
					                throw $e;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					            $model->refresh();  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -425,6 +427,26 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    /**  
			
		
	
		
			
				
					     * Populates relations with input data  
			
		
	
		
			
				
					     * @param array $data  
			
		
	
		
			
				
					     */  
			
		
	
		
			
				
					    public function loadRelations($data)  
			
		
	
		
			
				
					    {  
			
		
	
		
			
				
					        /** @var BaseActiveRecord $model */  
			
		
	
		
			
				
					        $model = $this->owner;  
			
		
	
		
			
				
					        foreach ($this->_relations as $relationName) {  
			
		
	
		
			
				
					            $relation = $model->getRelation($relationName);  
			
		
	
		
			
				
					            $modelClass = $relation->modelClass;  
			
		
	
		
			
				
					            /** @var BaseActiveRecord $relationalModel */  
			
		
	
		
			
				
					            $relationalModel = new $modelClass;  
			
		
	
		
			
				
					            $formName = $relationalModel->formName();  
			
		
	
		
			
				
					            if (array_key_exists($formName, $data)) {  
			
		
	
		
			
				
					                $model->{$relationName} = $data[$formName];  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    /**  
			
		
	
		
			
				
					     * Compute the difference between two set of records using primary keys "tokens"  
			
		
	
		
			
				
					     * @param BaseActiveRecord[] $initialRelations  
			
		
	
		
			
				
					     * @param BaseActiveRecord[] $updatedRelations  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -446,22 +468,27 @@ class SaveRelationsBehavior extends Behavior
					 
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    /**  
			
		
	
		
			
				
					     * Populates relations with input data  
			
		
	
		
			
				
					     * @param array $data  
			
		
	
		
			
				
					     * Attach errors to owner relational attributes  
			
		
	
		
			
				
					     * @param $relationModel  
			
		
	
		
			
				
					     * @param $owner  
			
		
	
		
			
				
					     * @param $relationName  
			
		
	
		
			
				
					     * @param $pettyRelationName  
			
		
	
		
			
				
					     * @return array  
			
		
	
		
			
				
					     */  
			
		
	
		
			
				
					    public function loadRelations($data)  
			
		
	
		
			
				
					    private function _addError($relationModel, $owner, $relationName, $pettyRelationName )  
			
		
	
		
			
				
					    {  
			
		
	
		
			
				
					        /** @var BaseActiveRecord $model */  
			
		
	
		
			
				
					        $model = $this->owner;  
			
		
	
		
			
				
					        foreach ($this->_relations as $relationName) {  
			
		
	
		
			
				
					            $relation = $model->getRelation($relationName);  
			
		
	
		
			
				
					            $modelClass = $relation->modelClass;  
			
		
	
		
			
				
					            /** @var BaseActiveRecord $relationalModel */  
			
		
	
		
			
				
					            $relationalModel = new $modelClass;  
			
		
	
		
			
				
					            $formName = $relationalModel->formName();  
			
		
	
		
			
				
					            if (array_key_exists($formName, $data)) {  
			
		
	
		
			
				
					                $model->{$relationName} = $data[$formName];  
			
		
	
		
			
				
					        foreach ($relationModel->errors as $attributeErrors) {  
			
		
	
		
			
				
					            foreach ($attributeErrors as $error) {  
			
		
	
		
			
				
					                $owner->addError($relationName, "{$pettyRelationName}: {$error}");  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    private function _rollback()  
			
		
	
		
			
				
					    {  
			
		
	
		
			
				
					        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__);  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					}