|
|
@ -40,6 +40,9 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
private $_relationsSaveStarted = false; |
|
|
|
private $_relationsSaveStarted = false; |
|
|
|
private $_transaction; |
|
|
|
private $_transaction; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @var BaseActiveRecord[] $_savedHasOneModels */ |
|
|
|
|
|
|
|
private $_savedHasOneModels = []; |
|
|
|
|
|
|
|
|
|
|
|
private $_relationsScenario = []; |
|
|
|
private $_relationsScenario = []; |
|
|
|
private $_relationsExtraColumns = []; |
|
|
|
private $_relationsExtraColumns = []; |
|
|
|
private $_relationsCascadeDelete = []; |
|
|
|
private $_relationsCascadeDelete = []; |
|
|
@ -315,8 +318,9 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* For each related model, try to save it first. |
|
|
|
* Prepare each related model (validate or save if needed). |
|
|
|
* This is done during the before validation process to be able to set the related foreign keys. |
|
|
|
* This is done during the before validation process to be able |
|
|
|
|
|
|
|
* to set the related foreign keys for newly created has one records. |
|
|
|
* @param BaseActiveRecord $model |
|
|
|
* @param BaseActiveRecord $model |
|
|
|
* @param ModelEvent $event |
|
|
|
* @param ModelEvent $event |
|
|
|
* @return bool |
|
|
|
* @return bool |
|
|
@ -354,30 +358,6 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* @param BaseActiveRecord $model |
|
|
|
* @param BaseActiveRecord $model |
|
|
|
*/ |
|
|
|
|
|
|
|
protected function startTransactionForModel(BaseActiveRecord $model) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if ($this->isModelTransactional($model) && is_null($model->getDb()->transaction)) { |
|
|
|
|
|
|
|
$this->_transaction = $model->getDb()->beginTransaction(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @param BaseActiveRecord $model |
|
|
|
|
|
|
|
* @return bool |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected function isModelTransactional(BaseActiveRecord $model) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (method_exists($model, 'isTransactional')) { |
|
|
|
|
|
|
|
return ($model->isNewRecord && $model->isTransactional($model::OP_INSERT)) |
|
|
|
|
|
|
|
|| (!$model->isNewRecord && $model->isTransactional($model::OP_UPDATE)) |
|
|
|
|
|
|
|
|| $model->isTransactional($model::OP_ALL); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @param BaseActiveRecord $model |
|
|
|
|
|
|
|
* @param ModelEvent $event |
|
|
|
* @param ModelEvent $event |
|
|
|
* @param $relationName |
|
|
|
* @param $relationName |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -393,8 +373,9 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
// Save Has one relation new record |
|
|
|
// Save Has one relation new record |
|
|
|
if ($event->isValid && (count($model->dirtyAttributes) || $model->{$relationName}->isNewRecord)) { |
|
|
|
if ($event->isValid && (count($model->dirtyAttributes) || $model->{$relationName}->isNewRecord)) { |
|
|
|
Yii::debug('Saving ' . self::prettyRelationName($relationName) . ' relation model', __METHOD__); |
|
|
|
Yii::debug('Saving ' . self::prettyRelationName($relationName) . ' relation model', __METHOD__); |
|
|
|
$this->startTransactionForModel($model); |
|
|
|
if ($model->{$relationName}->save()) { |
|
|
|
$model->{$relationName}->save(); |
|
|
|
$this->_savedHasOneModels[] = $model->{$relationName}; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -457,15 +438,15 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Rollback transaction if any |
|
|
|
* Delete newly created Has one models if any |
|
|
|
* @throws DbException |
|
|
|
* @throws DbException |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private function _rollback() |
|
|
|
private function _rollback() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (($this->_transaction instanceof Transaction) && $this->_transaction->isActive) { |
|
|
|
foreach ($this->_savedHasOneModels as $savedHasOneModel) { |
|
|
|
$this->_transaction->rollBack(); // If anything goes wrong, transaction will be rolled back |
|
|
|
$savedHasOneModel->delete(); |
|
|
|
Yii::info('Rolling back', __METHOD__); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$this->_savedHasOneModels = []; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -728,18 +709,13 @@ class SaveRelationsBehavior extends Behavior |
|
|
|
/** |
|
|
|
/** |
|
|
|
* Populates relations with input data |
|
|
|
* Populates relations with input data |
|
|
|
* @param array $data |
|
|
|
* @param array $data |
|
|
|
|
|
|
|
* @throws InvalidConfigException |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public function loadRelations($data) |
|
|
|
public function loadRelations($data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/** @var BaseActiveRecord $owner */ |
|
|
|
/** @var BaseActiveRecord $owner */ |
|
|
|
$owner = $this->owner; |
|
|
|
$owner = $this->owner; |
|
|
|
foreach ($this->_relations as $relationName) { |
|
|
|
foreach ($this->_relations as $relationName) { |
|
|
|
// /** @var ActiveQuery $relation */ |
|
|
|
|
|
|
|
// $relation = $owner->getRelation($relationName); |
|
|
|
|
|
|
|
// $modelClass = $relation->modelClass; |
|
|
|
|
|
|
|
// /** @var ActiveQuery $relationalModel */ |
|
|
|
|
|
|
|
// $relationalModel = new $modelClass; |
|
|
|
|
|
|
|
//$keyName = ($this->relationKeyName === self::RELATION_KEY_FORMNAME ? $relationalModel->formName() : $relationName); |
|
|
|
|
|
|
|
$keyName = $this->_getRelationKeyName($relationName); |
|
|
|
$keyName = $this->_getRelationKeyName($relationName); |
|
|
|
if (array_key_exists($keyName, $data)) { |
|
|
|
if (array_key_exists($keyName, $data)) { |
|
|
|
$owner->{$relationName} = $data[$keyName]; |
|
|
|
$owner->{$relationName} = $data[$keyName]; |
|
|
|