Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Test Failed
Push — allow-customization-of-reorder... ( 60c105 )
by Pedro
30:53
created

Reorder::updateTreeOrder()   C

Complexity

Conditions 13
Paths 1

Size

Total Lines 67
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 5 Features 1
Metric Value
cc 13
eloc 35
c 12
b 5
f 1
nc 1
nop 1
dl 0
loc 67
rs 6.6166

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
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Illuminate\Support\Facades\DB;
6
7
/**
8
 * Properties and methods for the Reorder operation.
9
 */
10
trait Reorder
11
{
12
    /**
13
     * Change the order and parents of the given elements, according to the NestedSortable AJAX call.
14
     *
15
     * @param  array  $request  The entire request from the NestedSortable AJAX Call.
16
     * @return int The number of items whose position in the tree has been changed.
17
     */
18
    public function updateTreeOrder($request)
19
    {
20
        $primaryKey = $this->model->getKeyName();
21
22
        $columns = $this->getOperationSetting('reorderColumnNames');
0 ignored issues
show
Bug introduced by
It seems like getOperationSetting() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

22
        /** @scrutinizer ignore-call */ 
23
        $columns = $this->getOperationSetting('reorderColumnNames');
Loading history...
23
24
        // we use the upsert method that should update the values of the matching ids.
25
        // it has the drawback of creating new entries when the id is not found
26
        // for that reason we get a list of all the ids and filter the ones
27
        // sent in the request that are not in the database
28
        $itemKeys = $this->model->query()->select($primaryKey)->get()->pluck($primaryKey);
29
30
        // filter the items that are not in the database and map the request
31
        $reorderItems = collect($request)->filter(function ($item) use ($itemKeys) {
0 ignored issues
show
Bug introduced by
$request of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

31
        $reorderItems = collect(/** @scrutinizer ignore-type */ $request)->filter(function ($item) use ($itemKeys) {
Loading history...
32
            return $item['item_id'] !== '' && $item['item_id'] !== null && $itemKeys->contains($item['item_id']);
33
        })->map(function ($item) use ($primaryKey, $columns) {
34
            $item[$primaryKey] = $item['item_id'];
35
            $item[$columns['parent_id']] = empty($item['parent_id']) ? null : $item['parent_id'];
36
            $item[$columns['depth']] = empty($item['depth']) ? null : (int) $item['depth'];
37
            $item[$columns['lft']] = empty($item['left']) ? null : (int) $item['left'];
38
            $item[$columns['rgt']] = empty($item['right']) ? null : (int) $item['right'];
39
            
40
            // unset mapped items properties.
41
            if($columns['parent_id'] !== 'parent_id') { unset($item['parent_id']); };
42
            if($columns['depth'] !== 'depth') { unset($item['depth']); }
43
            if($columns['lft'] !== 'left') { unset($item['left']); }
44
            if($columns['rgt'] !== 'right') { unset($item['right']); }
45
            
46
            // unset the item_id property
47
            unset($item['item_id']);
48
49
            return $item;
50
        })->toArray();
51
52
        $sentIds = array_column($reorderItems, $primaryKey);
53
54
        $itemKeys = $itemKeys->filter(function ($id) use ($sentIds) {
55
            return in_array($id, $sentIds);
56
        });
57
58
        // wrap the queries in a transaction to avoid partial updates
59
        DB::connection($this->model->getConnectionName())->transaction(function () use ($reorderItems, $primaryKey, $itemKeys, $columns) {
60
            // create a string of ?,?,?,? to use as bind placeholders for item keys
61
            $reorderItemsBindString = implode(',', array_fill(0, count($reorderItems), '?'));
62
63
            // each of this properties will be updated using a single query with a CASE statement
64
            // this ensures that only 4 queries are run, no matter how many items are reordered
65
            foreach (array_values($columns) as $column) {
66
                $query = '';
67
                $bindings = [];
68
                $query .= "UPDATE {$this->model->getTable()} SET {$column} = CASE ";
69
                foreach ($reorderItems as $item) {
70
                    $query .= "WHEN {$primaryKey} = ? THEN ? ";
71
                    $bindings[] = $item[$primaryKey];
72
                    $bindings[] = $item[$column];
73
                }
74
                // add the bind placeholders for the item keys at the end the array of bindings
75
                array_push($bindings, ...$itemKeys->toArray());
76
77
                // add the where clause to the query to help match the items
78
                $query .= "ELSE {$column} END WHERE {$primaryKey} IN ({$reorderItemsBindString})";
79
80
                DB::connection($this->model->getConnectionName())->statement($query, $bindings);
81
            }
82
        });
83
84
        return count($reorderItems);
85
    }
86
87
    /**
88
     * Enable the Reorder functionality in the CRUD Panel for users that have the been given access to 'reorder' using:
89
     * $this->crud->allowAccess('reorder');.
90
     *
91
     * @param  string  $label  Column name that will be shown on the labels.
92
     * @param  int  $max_level  Maximum hierarchy level to which the elements can be nested (1 = no nesting, just reordering).
93
     */
94
    public function enableReorder($label = 'name', $max_level = 1)
95
    {
96
        $this->setOperationSetting('enabled', true);
0 ignored issues
show
Bug introduced by
It seems like setOperationSetting() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

96
        $this->/** @scrutinizer ignore-call */ 
97
               setOperationSetting('enabled', true);
Loading history...
97
        $this->setOperationSetting('label', $label);
98
        $this->setOperationSetting('max_level', $max_level);
99
    }
100
101
    /**
102
     * Disable the Reorder functionality in the CRUD Panel for all users.
103
     */
104
    public function disableReorder()
105
    {
106
        $this->setOperationSetting('enabled', false);
107
    }
108
109
    /**
110
     * Check if the Reorder functionality is enabled or not.
111
     *
112
     * @return bool
113
     */
114
    public function isReorderEnabled()
115
    {
116
        return $this->getOperationSetting('enabled');
117
    }
118
}
119