Browse Source

Preparing for enhancements #3, #5 and #15 to be able to set per relation properties

tags/1.3.0
Alban Jubert 7 years ago
parent
commit
30377e1054
  1. 39
      src/SaveRelationsBehavior.php
  2. 4
      tests/models/Link.php
  3. 2
      tests/models/Project.php

39
src/SaveRelationsBehavior.php

@ -7,6 +7,7 @@ use Yii;
use yii\base\Behavior; use yii\base\Behavior;
use yii\base\Exception; use yii\base\Exception;
use yii\base\ModelEvent; use yii\base\ModelEvent;
use yii\base\UnknownPropertyException;
use yii\db\ActiveQueryInterface; use yii\db\ActiveQueryInterface;
use yii\db\BaseActiveRecord; use yii\db\BaseActiveRecord;
use yii\db\Transaction; use yii\db\Transaction;
@ -22,10 +23,36 @@ class SaveRelationsBehavior extends Behavior
{ {
public $relations = []; public $relations = [];
private $_relations = [];
private $_oldRelationValue = []; private $_oldRelationValue = [];
private $_relationsSaveStarted = false; private $_relationsSaveStarted = false;
private $_transaction; private $_transaction;
private $_relationsScenario = [];
private $_relationsCascadeDelete = [];
public function init()
{
parent::init();
$allowedProperties = ['scenario', 'cascadeDelete'];
foreach ($this->relations as $key => $value) {
if (is_int($key)) {
$this->_relations[] = $value;
} else {
$this->_relations[] = $key;
if (is_array($value)) {
foreach ($value as $propertyKey => $propertyValue) {
if (in_array($propertyKey, $allowedProperties)) {
$this->{'_relations' . ucfirst($propertyKey)}[$key] = $propertyValue;
} else {
throw new UnknownPropertyException('The relation property named ' . $propertyKey . ' is not supported');
}
}
}
}
}
}
public function events() public function events()
{ {
return [ return [
@ -58,7 +85,7 @@ class SaveRelationsBehavior extends Behavior
public function canSetProperty($name, $checkVars = true) public function canSetProperty($name, $checkVars = true)
{ {
$getter = 'get' . $name; $getter = 'get' . $name;
if (in_array($name, $this->relations) && method_exists($this->owner, $getter) && $this->owner->$getter() instanceof ActiveQueryInterface) { if (in_array($name, $this->_relations) && method_exists($this->owner, $getter) && $this->owner->$getter() instanceof ActiveQueryInterface) {
return true; return true;
} }
return parent::canSetProperty($name, $checkVars); return parent::canSetProperty($name, $checkVars);
@ -72,7 +99,7 @@ class SaveRelationsBehavior extends Behavior
*/ */
public function __set($name, $value) public function __set($name, $value)
{ {
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}; $this->_oldRelationValue[$name] = $this->owner->{$name};
@ -187,7 +214,7 @@ class SaveRelationsBehavior extends Behavior
$model = $this->owner; $model = $this->owner;
if ($this->saveRelatedRecords($model, $event)) { if ($this->saveRelatedRecords($model, $event)) {
// If relation is has_one, try to set related model attributes // If relation is has_one, try to set related model attributes
foreach ($this->relations as $relationName) { foreach ($this->_relations as $relationName) {
if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing... if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...
$relation = $model->getRelation($relationName); $relation = $model->getRelation($relationName);
if ($relation->multiple === false && !empty($model->{$relationName})) { if ($relation->multiple === false && !empty($model->{$relationName})) {
@ -219,7 +246,7 @@ class SaveRelationsBehavior extends Behavior
$this->_transaction = $model->getDb()->beginTransaction(); $this->_transaction = $model->getDb()->beginTransaction();
} }
try { try {
foreach ($this->relations as $relationName) { foreach ($this->_relations as $relationName) {
if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing... if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...
$relation = $model->getRelation($relationName); $relation = $model->getRelation($relationName);
if (!empty($model->{$relationName})) { if (!empty($model->{$relationName})) {
@ -302,7 +329,7 @@ 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) { foreach ($this->_relations as $relationName) {
if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing... if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...
Yii::trace("Linking {$relationName} relation", __METHOD__); Yii::trace("Linking {$relationName} relation", __METHOD__);
$relation = $model->getRelation($relationName); $relation = $model->getRelation($relationName);
@ -390,7 +417,7 @@ class SaveRelationsBehavior extends Behavior
{ {
/** @var BaseActiveRecord $model */ /** @var BaseActiveRecord $model */
$model = $this->owner; $model = $this->owner;
foreach ($this->relations as $relationName) { foreach ($this->_relations as $relationName) {
$relation = $model->getRelation($relationName); $relation = $model->getRelation($relationName);
$modelClass = $relation->modelClass; $modelClass = $relation->modelClass;
/** @var BaseActiveRecord $relationalModel */ /** @var BaseActiveRecord $relationalModel */

4
tests/models/Link.php

@ -6,6 +6,10 @@ use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior;
class Link extends \yii\db\ActiveRecord class Link extends \yii\db\ActiveRecord
{ {
const SCENARIO_FIRST = 'first';
const SCENARIO_SECOND = 'second';
/** /**
* @inheritdoc * @inheritdoc
*/ */

2
tests/models/Project.php

@ -22,7 +22,7 @@ class Project extends \yii\db\ActiveRecord
return [ return [
'saveRelations' => [ 'saveRelations' => [
'class' => SaveRelationsBehavior::className(), 'class' => SaveRelationsBehavior::className(),
'relations' => ['company', 'users', 'links'] 'relations' => ['company', 'users', 'links' => ['scenario' => Link::SCENARIO_FIRST]]
], ],
]; ];
} }

Loading…
Cancel
Save