Skip to content
This repository has been archived by the owner on Jul 1, 2022. It is now read-only.

Commit

Permalink
Merge 9ff39ad into 0f73351
Browse files Browse the repository at this point in the history
  • Loading branch information
leandrogehlen committed Aug 26, 2018
2 parents 0f73351 + 9ff39ad commit 3a397c2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 51 deletions.
44 changes: 1 addition & 43 deletions src/SaveRelationsBehavior.php
Expand Up @@ -28,6 +28,7 @@ class SaveRelationsBehavior extends Behavior

public $relations = [];
public $useFormName = true;
public $autoStartTransaction = false;

private $_relations = [];
private $_oldRelationValue = []; // Store initial relations value
Expand Down Expand Up @@ -323,7 +324,6 @@ public function beforeValidate(ModelEvent $event)
*/
protected function saveRelatedRecords(BaseActiveRecord $model, ModelEvent $event)
{
$this->startTransactionForModel($model);
try {
foreach ($this->_relations as $relationName) {
if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...
Expand All @@ -343,38 +343,13 @@ protected function saveRelatedRecords(BaseActiveRecord $model, ModelEvent $event
}
} catch (Exception $e) {
Yii::warning(get_class($e) . ' was thrown while saving related records during beforeValidate event: ' . $e->getMessage(), __METHOD__);
$this->_rollback();
$model->addError($model->formName(), $e->getMessage());
$event->isValid = false; // Stop saving, something went wrong
return false;
}
return true;
}

/**
* @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
Expand Down Expand Up @@ -454,18 +429,6 @@ private function _prepareHasManyRelation(BaseActiveRecord $model, $relationName)
}
}

/**
* Rollback transaction if any
* @throws DbException
*/
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__);
}
}

/**
* Set relation foreign keys that point to owner primary key
* @param $relationName
Expand Down Expand Up @@ -521,7 +484,6 @@ public function afterSave()
}
} catch (Exception $e) {
Yii::warning(get_class($e) . ' was thrown while saving related records during afterSave event: ' . $e->getMessage(), __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.
Expand All @@ -530,9 +492,6 @@ public function afterSave()
}
$owner->refresh();
$this->_relationsSaveStarted = false;
if (($this->_transaction instanceof Transaction) && $this->_transaction->isActive) {
$this->_transaction->commit();
}
}
}

Expand Down Expand Up @@ -717,7 +676,6 @@ public function afterDelete()
}
} catch (Exception $e) {
Yii::warning(get_class($e) . ' was thrown while deleting related records during afterDelete event: ' . $e->getMessage(), __METHOD__);
$this->_rollback();
throw $e;
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/SaveRelationsTrait.php
Expand Up @@ -5,6 +5,9 @@
trait SaveRelationsTrait
{

/**
* Populates the relations with input data.
*/
public function load($data, $formName = null)
{
$loaded = parent::load($data, $formName);
Expand All @@ -13,4 +16,17 @@ public function load($data, $formName = null)
}
return $loaded;
}

/**
* Starts transaction if [autoStartTransaction] has been defined
*/
public function isTransactional($operation)
{
if ($this->hasProperty('autoStartTransaction')) {
return $this->autoStartTransaction;
}

return parent::isTransactional($operation);
}

}
25 changes: 17 additions & 8 deletions tests/SaveRelationsBehaviorTest.php
Expand Up @@ -17,6 +17,7 @@
use yii\base\Model;
use yii\db\Migration;
use yii\helpers\VarDumper;
use yii\db\ActiveRecord;

class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase
{
Expand Down Expand Up @@ -846,13 +847,8 @@ public function testSaveProjectWithCompanyWithUserShouldSucceed()
public function testLoadRelationNameAsDataKeyShouldSucceed()
{
$company = new Company([
'name' => 'NewSoft',
]);

$company->attachBehavior('saveRelations', [
'class' => SaveRelationsBehavior::className(),
'relations' => ['users'],
'useFormName' => false
'useFormName' => false,
'name' => 'NewSoft'
]);

$data = [
Expand All @@ -869,4 +865,17 @@ public function testLoadRelationNameAsDataKeyShouldSucceed()
$this->assertEquals('user1', $company->users[0]->username);
$this->assertEquals('user2', $company->users[1]->username);
}
}

public function testAutoStartTransaction()
{
$transactional;
$user = User::findOne(1);

$transactional = $user->isTransactional(ActiveRecord::OP_UPDATE);
$this->assertFalse($transactional);

$user->autoStartTransaction = true;
$transactional = $user->isTransactional(ActiveRecord::OP_UPDATE);
$this->assertTrue($transactional);
}
}

0 comments on commit 3a397c2

Please sign in to comment.