From 53d56d6b978c102562277e260a3d5e5646d6ad87 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Sun, 21 Aug 2016 01:22:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B7=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D0=B8=D1=87=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B0=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/behaviors/PrimaryKeyValueBehavior.php | 61 ++++++++++++++++ common/models/EmailActivation.php | 29 ++------ .../behaviors/PrimaryKeyValueBehaviorTest.php | 70 +++++++++++++++++++ .../unit/models/EmailActivationTest.php | 26 ------- 4 files changed, 138 insertions(+), 48 deletions(-) create mode 100644 common/behaviors/PrimaryKeyValueBehavior.php create mode 100644 tests/codeception/common/unit/behaviors/PrimaryKeyValueBehaviorTest.php diff --git a/common/behaviors/PrimaryKeyValueBehavior.php b/common/behaviors/PrimaryKeyValueBehavior.php new file mode 100644 index 0000000..1c73999 --- /dev/null +++ b/common/behaviors/PrimaryKeyValueBehavior.php @@ -0,0 +1,61 @@ + 'setPrimaryKeyValue', + ]; + } + + public function setPrimaryKeyValue() : bool { + $owner = $this->owner; + if ($owner->getPrimaryKey() === null) { + do { + $key = $this->generateValue(); + } while ($this->isValueExists($key)); + + $owner->{$this->getPrimaryKeyName()} = $key; + } + + return true; + } + + protected function generateValue() : string { + return (string)call_user_func($this->value); + } + + protected function isValueExists(string $key) : bool { + return $this->owner->find()->andWhere([$this->getPrimaryKeyName() => $key])->exists(); + } + + protected function getPrimaryKeyName() : string { + $owner = $this->owner; + $primaryKeys = $owner->primaryKey(); + if (!isset($primaryKeys[0])) { + throw new InvalidConfigException('"' . get_class($owner) . '" must have a primary key.'); + } elseif (count($primaryKeys) > 1) { + throw new InvalidConfigException('Current behavior don\'t support models with more then one primary key.'); + } + + /** @noinspection PhpIncompatibleReturnTypeInspection да как бы оно всё нормально, но шторм мне не верит */ + return $primaryKeys[0]; + } + +} diff --git a/common/models/EmailActivation.php b/common/models/EmailActivation.php index 7f27407..0b53bf7 100644 --- a/common/models/EmailActivation.php +++ b/common/models/EmailActivation.php @@ -3,6 +3,7 @@ namespace common\models; use common\behaviors\DataBehavior; use common\behaviors\EmailActivationExpirationBehavior; +use common\behaviors\PrimaryKeyValueBehavior; use common\components\UserFriendlyRandomKey; use yii\base\InvalidConfigException; use yii\behaviors\TimestampBehavior; @@ -42,6 +43,12 @@ class EmailActivation extends ActiveRecord { 'class' => TimestampBehavior::class, 'updatedAtAttribute' => false, ], + [ + 'class' => PrimaryKeyValueBehavior::class, + 'value' => function() { + return UserFriendlyRandomKey::make(); + }, + ], 'expirationBehavior' => [ 'class' => EmailActivationExpirationBehavior::class, 'repeatTimeout' => 5 * 60, // 5m @@ -84,26 +91,4 @@ class EmailActivation extends ActiveRecord { ]; } - public function beforeSave($insert) { - if (!parent::beforeSave($insert)) { - return false; - } - - if ($this->key === null) { - do { - $this->key = $this->generateKey(); - } while ($this->isKeyExists($this->key)); - } - - return true; - } - - protected function generateKey() : string { - return UserFriendlyRandomKey::make(); - } - - protected function isKeyExists(string $key) : bool { - return self::find()->andWhere(['key' => $key])->exists(); - } - } diff --git a/tests/codeception/common/unit/behaviors/PrimaryKeyValueBehaviorTest.php b/tests/codeception/common/unit/behaviors/PrimaryKeyValueBehaviorTest.php new file mode 100644 index 0000000..7852ac5 --- /dev/null +++ b/tests/codeception/common/unit/behaviors/PrimaryKeyValueBehaviorTest.php @@ -0,0 +1,70 @@ +specify('method should generate value for primary key field on call', function() { + $model = new DummyModel(); + /** @var PrimaryKeyValueBehavior|\PHPUnit_Framework_MockObject_MockObject $behavior */ + $behavior = $this->getMockBuilder(PrimaryKeyValueBehavior::class) + ->setMethods(['isValueExists']) + ->setConstructorArgs([[ + 'value' => function() { + return 'mock'; + }, + ]]) + ->getMock(); + + $behavior->expects($this->once()) + ->method('isValueExists') + ->will($this->returnValue(false)); + + $model->attachBehavior('primary-key-value-behavior', $behavior); + $behavior->setPrimaryKeyValue(); + expect($model->id)->equals('mock'); + }); + + $this->specify('method should repeat value generation if generated value duplicate with exists', function() { + $model = new DummyModel(); + /** @var PrimaryKeyValueBehavior|\PHPUnit_Framework_MockObject_MockObject $behavior */ + $behavior = $this->getMockBuilder(PrimaryKeyValueBehavior::class) + ->setMethods(['isValueExists', 'generateValue']) + ->setConstructorArgs([[ + 'value' => function() { + return 'this was mocked, but let be passed'; + }, + ]]) + ->getMock(); + + $behavior->expects($this->exactly(3)) + ->method('generateValue') + ->will($this->onConsecutiveCalls('1', '2', '3')); + + $behavior->expects($this->exactly(3)) + ->method('isValueExists') + ->will($this->onConsecutiveCalls(true, true, false)); + + $model->attachBehavior('primary-key-value-behavior', $behavior); + $behavior->setPrimaryKeyValue(); + expect($model->id)->equals('3'); + }); + } + +} + +class DummyModel extends ActiveRecord { + + public $id; + + public static function primaryKey() { + return ['id']; + } + +} diff --git a/tests/codeception/common/unit/models/EmailActivationTest.php b/tests/codeception/common/unit/models/EmailActivationTest.php index c48bf5a..d604e1f 100644 --- a/tests/codeception/common/unit/models/EmailActivationTest.php +++ b/tests/codeception/common/unit/models/EmailActivationTest.php @@ -28,30 +28,4 @@ class EmailActivationTest extends DbTestCase { }); } - public function testBeforeSave() { - $this->specify('method should generate value for key field if it empty', function() { - $model = new EmailActivation(); - $model->beforeSave(true); - expect($model->key)->notNull(); - }); - - $this->specify('method should repeat code generation if code duplicate with exists', function() { - /** @var EmailActivation|\PHPUnit_Framework_MockObject_MockObject $model */ - $model = $this->getMockBuilder(EmailActivation::class) - ->setMethods(['generateKey', 'isKeyExists']) - ->getMock(); - - $model->expects($this->exactly(3)) - ->method('generateKey') - ->will($this->onConsecutiveCalls('1', '2', '3')); - - $model->expects($this->exactly(3)) - ->method('isKeyExists') - ->will($this->onConsecutiveCalls(true, true, false)); - - $model->beforeSave(true); - expect($model->key)->equals('3'); - }); - } - }