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

Position::notify()   C

Complexity

Conditions 17
Paths 21

Size

Total Lines 64
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 40
c 0
b 0
f 0
nc 21
nop 2
dl 0
loc 64
rs 5.2166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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