Test Failed
Push — master ( 894c40...e5d2d2 )
by Julien
11:34
created

Position::getRawSql()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Model\Behavior;
13
14
use Phalcon\Db\RawValue;
15
use Phalcon\Mvc\Model\Behavior;
16
use Phalcon\Mvc\ModelInterface;
17
use Phalcon\Text;
18
use Zemit\Mvc\Model;
19
20
class Position extends Behavior
21
{
22
    use SkippableTrait;
23
    
24
    public bool $progress = false;
25
    
26
    public function setField(string $field): void
27
    {
28
        $this->options['field'] = $field;
29
    }
30
    
31
    public function getField(): string
32
    {
33
        return $this->options['field'];
34
    }
35
    
36
    public function setRawSql(bool $rawSql): void
37
    {
38
        $this->options['rawSql'] = $rawSql;
39
    }
40
    
41
    public function getRawSql(): bool
42
    {
43
        return $this->options['rawSql'];
44
    }
45
    
46
    public function setProgress(bool $progress): void
47
    {
48
        $this->progress = $progress;
49
    }
50
    
51
    public function getProgress(): bool
52
    {
53
        return $this->progress;
54
    }
55
    
56
    public function __construct(array $options = [])
57
    {
58
        parent::__construct($options);
59
        $this->setField($options['field'] ?? 'position');
60
        $this->setRawSql($options['rawSql'] ?? true);
61
    }
62
    
63
    /**
64
     * @return mixed
65
     */
66
    public function notify(string $type, ModelInterface $model)
67
    {
68
        if (!$this->isEnabled()) {
69
            return;
70
        }
71
        
72
        assert($model instanceof Model);
73
        
74
        $positionField = $this->getField();
75
        $rawSql = $this->getRawSql();
76
        
77
        switch ($type) {
78
            case 'beforeValidation':
79
                // if position field is empty, force current max(position)+1
80
                $lastPosition = $model::findFirst(['order' => $positionField . ' DESC']);
81
                if ($lastPosition && assert($lastPosition instanceof $model)) {
82
                    $position = (int)$lastPosition->getAttribute($positionField);
0 ignored issues
show
Bug introduced by
The method getAttribute() does not exist on Phalcon\Mvc\ModelInterface. It seems like you code against a sub-type of Phalcon\Mvc\ModelInterface such as Phalcon\Mvc\Model or Zemit\Models\Setting or Zemit\Models\Category or Zemit\Models\Audit or Zemit\Models\UserGroup or Zemit\Models\User or Zemit\Models\Field or Zemit\Models\Page or Zemit\Models\Log or Zemit\Models\File or Zemit\Models\Role or Zemit\Models\GroupRole or Zemit\Models\Template or Zemit\Models\AuditDetail or Zemit\Models\UserType or Zemit\Models\Post or Zemit\Models\PostCategory or Zemit\Models\Session or Zemit\Models\TranslateField or Zemit\Models\GroupType or Zemit\Models\Translate or Zemit\Models\Email or Zemit\Models\Data or Zemit\Models\Group or Zemit\Models\Lang or Zemit\Models\EmailFile or Zemit\Models\TranslateTable or Zemit\Models\SiteLang or Zemit\Models\UserRole or Zemit\Models\Flag or Zemit\Models\Menu or Zemit\Models\Site or Zemit\Models\Type or Zemit\Models\Channel or Zemit\Models\Meta. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
                    $position = (int)$lastPosition->/** @scrutinizer ignore-call */ getAttribute($positionField);
Loading history...
83
                    $model->setAttribute($positionField, $position + 1);
84
                }
85
                break;
86
            
87
            case 'afterSave':
88
                if (!$this->getProgress() && $model->hasSnapshotData() && $model->hasUpdated($positionField)) {
89
                    $this->setProgress(true);
90
                    
91
                    $snapshot = $model->getOldSnapshotData() ?: $model->getSnapshotData();
92
                    $modelPosition = $model->getAttribute($positionField);
93
                    $modelPrimaryKeys = $model->getPrimaryKeysValues();
94
                    
95
                    if (!($modelPosition instanceof RawValue)) {
96
                        $uField = Text::uncamelize($positionField); // @todo use columnMap
97
                        $updatePositionQuery = null;
98
                        
99
                        if ($snapshot[$positionField] > $modelPosition) {
100
                            $updatePositionQuery = $rawSql
101
                                ? 'UPDATE `' . $model->getSource() . '` SET `' . $uField . '` = `' . $uField . '`+1 WHERE `' . $uField . '` >= :position and `' . $uField . '` < :oldPosition and `' . $idField . '` <> :id'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $idField seems to be never defined.
Loading history...
102
                                : 'UPDATE [' . get_class($model) . '] SET [' . $positionField . '] = [' . $positionField . ']+1 WHERE [' . $positionField . '] >= ?1 and [' . $positionField . '] < ?2 and [' . $idField . '] <> ?0';
103
                        }
104
                        elseif ($snapshot[$positionField] < $modelPosition) {
105
                            $updatePositionQuery = $rawSql
106
                                ? 'UPDATE `' . $model->getSource() . '` SET `' . $uField . '` = `' . $uField . '`-1 WHERE `' . $uField . '` > :oldPosition and `' . $uField . '` <= :position and `' . $idField . '` <> :id'
107
                                : 'UPDATE [' . get_class($model) . '] SET [' . $positionField . '] = [' . $positionField . ']-1 WHERE [' . $positionField . '] > ?2 and [' . $positionField . '] <= ?1 and [' . $idField . '] <> ?0';
108
                        }
109
                        
110
                        if (!empty($updatePositionQuery)) {
111
                            if ($rawSql) {
112
                                $model->getWriteConnection()->query($updatePositionQuery, [
113
                                    'primaryKeys' => $modelPrimaryKeys,
114
                                    'position' => $modelPosition,
115
                                    'oldPosition' => $snapshot[$positionField],
116
                                ]);
117
                            }
118
                            else {
119
                                $model->getModelsManager()->executeQuery($updatePositionQuery, [$modelId, $modelPosition, $snapshot[$positionField]]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $modelId does not exist. Did you maybe mean $model?
Loading history...
120
                            }
121
                        }
122
                    }
123
                    
124
                    $this->setProgress(false);
125
                }
126
                break;
127
        }
128
        
129
        return true;
130
    }
131
}
132