Skip to content

Commit ee8de6a

Browse files
committed
Wrote tests (closes #1), fixed sort double processing (fixes #11), tests related bug fixes, refactoring
1 parent cbe8415 commit ee8de6a

17 files changed

+672
-24
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/vendor
2+
composer.lock
3+
4+
/tests/_output
5+
/tests/unit/UnitTester.php

behaviors/BaseSortableBehavior.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use yii\base\Behavior;
66
use yii\base\InvalidConfigException;
77
use yii\base\InvalidParamException;
8-
use yii\db\ActiveRecord;
98

109
/**
1110
* @property \yii\db\ActiveRecord $model

behaviors/numerical/BaseNumericalSortableBehavior.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ abstract class BaseNumericalSortableBehavior extends BaseSortableBehavior
1818
*/
1919
protected $_intervalSize;
2020

21+
/**
22+
* @var boolean
23+
*/
24+
protected $_isSortProcessed = false;
25+
2126

2227
/**
2328
* @param integer $position
@@ -45,31 +50,37 @@ public function events()
4550
public function modelInit()
4651
{
4752
$this->_oldModel = clone $this->model;
53+
$this->_isSortProcessed = false;
4854
}
4955

5056
public function afterFind()
5157
{
52-
$this->_oldModel = clone $this->model;
58+
$this->modelInit();
5359
}
5460

5561
public function beforeInsert()
5662
{
57-
$this->isSortable() ? $this->addSort() : $this->resetSort();
63+
$this->processSort();
5864
}
5965

6066
public function afterInsert()
6167
{
62-
$this->processSortableDiff(true);
68+
$this->processSort(true);
69+
$this->modelInit();
6370
}
6471

6572
public function beforeUpdate()
6673
{
67-
$this->processSortableDiff();
74+
$this->processSort();
75+
76+
if ($this->isScopeChanged()) {
77+
$this->addSort();
78+
}
6879
}
6980

7081
public function afterUpdate()
7182
{
72-
$this->processSortableDiff(true);
83+
$this->processSort(true);
7384
}
7485

7586
/**
@@ -198,18 +209,24 @@ protected function updateSort()
198209
/**
199210
* @param boolean $updateSort
200211
*/
201-
protected function processSortableDiff($updateSort = false)
212+
protected function processSort($updateSort = false)
202213
{
203-
$sortableDiff = $this->getSortableDiff();
204-
if ($sortableDiff === true) {
214+
if ($this->_isSortProcessed) {
215+
return;
216+
}
217+
218+
$isSortable = $this->model->isNewRecord ? $this->isSortable() : $this->getSortableDiff();
219+
if ($isSortable === true) {
205220
$this->addSort();
206-
} elseif ($sortableDiff === false) {
221+
} elseif ($isSortable === false) {
207222
$this->resetSort();
208223
}
209224

210-
if ($sortableDiff !== null && $updateSort) {
225+
if ($isSortable !== null && $updateSort) {
211226
$this->updateSort();
212227
}
228+
229+
$this->_isSortProcessed = true;
213230
}
214231

215232
/**

behaviors/numerical/ContinuousNumericalSortableBehavior.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,22 @@ public function beforeUpdate()
3535
{
3636
parent::beforeUpdate();
3737

38-
if ($this->isScopeChanged()) {
39-
$this->addSort();
40-
$this->_reindexOldModel = true;
41-
} else {
42-
$this->_reindexOldModel = false;
43-
}
38+
$this->_reindexOldModel = $this->isScopeChanged() ? true : false;
4439
}
4540

4641
public function afterUpdate()
4742
{
4843
parent::afterUpdate();
4944

50-
if ($this->getSortableDiff() === false) {
45+
if (!$this->getSort()) {
5146
$this->reindexAfterDelete();
5247
}
5348

5449
if ($this->_reindexOldModel) {
55-
$this->_oldModel->reindexAfterDelete();
50+
$this->_oldModel->reindexAfterDelete(true);
5651
}
52+
53+
$this->modelInit();
5754
}
5855

5956
public function afterDelete()
@@ -106,9 +103,12 @@ public function moveToPosition($position)
106103
$this->model->updateAttributes([$this->sortAttribute => $position]);
107104
}
108105

109-
public function reindexAfterDelete()
106+
/**
107+
* @param boolean $useCurrentSort
108+
*/
109+
public function reindexAfterDelete($useCurrentSort = false)
110110
{
111-
$sort = $this->_oldModel->getSort();
111+
$sort = $useCurrentSort ? $this->model->getSort() : $this->_oldModel->getSort();
112112

113113
$models = $this->query
114114
->andWhere(['>', $this->sortAttribute, $sort])

behaviors/numerical/IntervalNumericalSortableBehavior.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,18 @@ public function afterFind()
3535
{
3636
parent::afterFind();
3737

38-
if (!self::$_positionsMap) {
39-
$this->initPositionsMap();
38+
if (!isset(self::$_positionsMap[$this->getPositionMapKey()])) {
39+
$this->fillPositionsMap();
4040
}
4141
}
4242

43+
public function afterUpdate()
44+
{
45+
parent::afterUpdate();
46+
47+
$this->modelInit();
48+
}
49+
4350
/**
4451
* @inheritdoc
4552
*/
@@ -82,6 +89,14 @@ public function setIntervalSize($value)
8289
$this->_intervalSize = $value;
8390
}
8491

92+
/**
93+
* @return \yii\db\ActiveQuery
94+
*/
95+
protected function getQuery()
96+
{
97+
return parent::getQuery()->select(null);
98+
}
99+
85100
/**
86101
* @inheritdoc
87102
*/
@@ -109,7 +124,7 @@ protected function prependAdded()
109124
$this->setSort($sort);
110125
}
111126

112-
protected function initPositionsMap()
127+
protected function fillPositionsMap()
113128
{
114129
$elements = $this->query
115130
->select($this->model->primaryKey())

codeception.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
actor: Tester
2+
paths:
3+
tests: tests
4+
log: tests/_output
5+
data: tests/_data
6+
helpers: tests/_support
7+
settings:
8+
bootstrap: _bootstrap.php
9+
colors: true
10+
memory_limit: 1024M
11+
modules:
12+
config:
13+
Db:
14+
dsn: 'sqlite:tests/_output/temp.db'
15+
user: ''
16+
password: ''
17+
dump: tests/_data/dump.sql

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
"yiisoft/yii2": "*",
2323
"yiisoft/yii2-jui": "*"
2424
},
25+
"require-dev": {
26+
"yiisoft/yii2-codeception": "~2.0"
27+
},
2528
"autoload": {
2629
"psr-4": {
2730
"arogachev\\sortable\\": ""

tests/_bootstrap.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
defined('YII_DEBUG') or define('YII_DEBUG', true);
3+
defined('YII_ENV') or define('YII_ENV', 'dev');
4+
require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'autoload.php']);
5+
require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'yiisoft', 'yii2', 'Yii.php']);
6+
Yii::setAlias('@tests', __DIR__);
7+
Yii::setAlias('@data', __DIR__ . DIRECTORY_SEPARATOR . '_data');

tests/_data/ContinuousQuestion.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace data;
4+
5+
use arogachev\sortable\behaviors\numerical\ContinuousNumericalSortableBehavior;
6+
use Yii;
7+
use yii\db\ActiveRecord;
8+
use yii\helpers\ArrayHelper;
9+
10+
/**
11+
* @property integer $id
12+
* @property integer $test_id
13+
* @property integer $sort
14+
* @property string $content
15+
* @property integer $is_active
16+
*/
17+
class ContinuousQuestion extends ActiveRecord
18+
{
19+
/**
20+
* @inheritdoc
21+
*/
22+
public function behaviors()
23+
{
24+
return [
25+
'sort' => [
26+
'class' => ContinuousNumericalSortableBehavior::className(),
27+
'scope' => function () {
28+
return ContinuousQuestion::find()->where(['test_id' => $this->test_id]);
29+
},
30+
'sortableCondition' => [
31+
'is_active' => 1,
32+
],
33+
]
34+
];
35+
}
36+
37+
/**
38+
* @inheritdoc
39+
*/
40+
public static function tableName()
41+
{
42+
return 'continuous_questions';
43+
}
44+
45+
/**
46+
* @inheritdoc
47+
*/
48+
public function rules()
49+
{
50+
return [
51+
['is_active', 'default', 'value' => 1],
52+
];
53+
}
54+
55+
/**
56+
* @return array
57+
*/
58+
public function getOtherQuestionsSort()
59+
{
60+
$questions = static::find()
61+
->where(['test_id' => $this->test_id])
62+
->andWhere(['<>', 'id', $this->id])
63+
->orderBy(['id' => SORT_ASC])
64+
->all();
65+
66+
return ArrayHelper::getColumn($questions, 'sort');
67+
}
68+
}

tests/_data/IntervalQuestion.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace data;
4+
5+
use arogachev\sortable\behaviors\numerical\IntervalNumericalSortableBehavior;
6+
use Yii;
7+
use yii\db\ActiveRecord;
8+
use yii\helpers\ArrayHelper;
9+
10+
/**
11+
* @property integer $id
12+
* @property integer $test_id
13+
* @property integer $sort
14+
* @property string $content
15+
* @property integer $is_active
16+
*/
17+
class IntervalQuestion extends ActiveRecord
18+
{
19+
/**
20+
* @inheritdoc
21+
*/
22+
public function behaviors()
23+
{
24+
return [
25+
'sort' => [
26+
'class' => IntervalNumericalSortableBehavior::className(),
27+
'scope' => function () {
28+
return IntervalQuestion::find()->where(['test_id' => $this->test_id]);
29+
},
30+
'sortableCondition' => [
31+
'is_active' => 1,
32+
],
33+
]
34+
];
35+
}
36+
37+
/**
38+
* @inheritdoc
39+
*/
40+
public static function tableName()
41+
{
42+
return 'interval_questions';
43+
}
44+
45+
/**
46+
* @inheritdoc
47+
*/
48+
public function rules()
49+
{
50+
return [
51+
['is_active', 'default', 'value' => 1],
52+
];
53+
}
54+
55+
/**
56+
* @return array
57+
*/
58+
public function getOtherQuestionsSort()
59+
{
60+
$questions = static::find()
61+
->where(['test_id' => $this->test_id])
62+
->andWhere(['<>', 'id', $this->id])
63+
->orderBy(['id' => SORT_ASC])
64+
->all();
65+
66+
return ArrayHelper::getColumn($questions, 'sort');
67+
}
68+
}

0 commit comments

Comments
 (0)