Completed
Pull Request — master (#12)
by
unknown
01:23
created

HLQuery::groupBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Arrilot\BitrixModels\Queries;
4
5
6
use Arrilot\BitrixModels\Models\HLModel;
7
use Illuminate\Support\Collection;
8
use LogicException;
9
10
class HLQuery extends BaseQuery
11
{
12
    public $keyBy = 'ID';
13
14
    /**
15
     * Query sort.
16
     *
17
     * @var array
18
     */
19
    public $select = false;
20
    public $sort = ['ID' => 'ASC'];
21
    public $limit;
22
    public $page;
23
    public $ttl = 0;
24
25
    /**
26
     * Query group by.
27
     *
28
     * @var array
29
     */
30
    public $groupBy = false;
31
32
    /**
33
     * Iblock id.
34
     *
35
     * @var int
36
     */
37
    protected $tableName;
38
39
    /**
40
     * Constructor.
41
     *
42
     * @param object $bxObject
43
     * @param string $modelName
44
     */
45
    public function __construct($bxObject, $modelName)
46
    {
47
        parent::__construct($bxObject, $modelName);
48
49
        $this->tableName = $modelName::tableName();
50
    }
51
52
    /**
53
     * Setter for groupBy.
54
     *
55
     * @param $value
56
     *
57
     * @return $this
58
     */
59
    public function groupBy($value)
60
    {
61
        $this->groupBy = $value;
62
63
        return $this;
64
    }
65
66
    public function limit($value)
67
    {
68
        $this->limit = $value;
69
70
        return $this;
71
    }
72
73
    public function page($num)
74
    {
75
        $this->page = $num;
76
77
        return $this;
78
    }
79
80
    public function cache($ttl)
81
    {
82
        $this->ttl = (int) $ttl;
83
84
        return $this;
85
    }
86
87
    /**
88
     * Get list of items.
89
     *
90
     * @return Collection
91
     */
92
    public function getList()
93
    {
94
        if ($this->queryShouldBeStopped) {
95
            return new Collection();
96
        }
97
98
        $items = [];
99
100
101
        $params = [
102
            'filter' => $this->normalizeFilter(),
103
            'order' => $this->sort,
104
            'select' => $this->normalizeSelect(),
105
            //'cache' => ['ttl' => 3600],
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
106
        ];
107
108
        if ($this->groupBy) $params['group'] = $this->groupBy;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->groupBy of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
109
        if ($this->limit) $params['limit'] = $this->limit;
110
        if ($this->ttl) $params['cache'] = ['ttl' => $this->ttl];
111
        if ($this->page && $this->limit) $params['offset'] = $this->page * $this->limit;
112
113
        $rsItems = $this->bxObject::getList($params);
114
        while ($arItem = $rsItems->fetch()) {
115
            $this->addItemToResultsUsingKeyBy($items, new $this->modelName($arItem['ID'], $arItem));
116
        }
117
118
        return new Collection($items);
119
    }
120
121 View Code Duplication
    protected function addItemToResultsUsingKeyBy(&$results, HLModel $object)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
    {
123
        $item = $object->fields;
124
125
        if (!isset($item[$this->keyBy])) {
126
            throw new LogicException("Field {$this->keyBy} is not found in object");
127
        }
128
129
        $keyByValue = $item[$this->keyBy];
130
131
        if (!isset($results[$keyByValue])) {
132
            $results[$keyByValue] = $object;
133
        } else {
134
            $oldFields = $results[$keyByValue]->fields;
135
            foreach ($oldFields as $field => $oldValue) {
136
                // пропускаем служебные поля.
137
                if (in_array($field, ['_were_multiplied', 'PROPERTIES'])) {
138
                    continue;
139
                }
140
141
                $alreadyMultiplied = !empty($oldFields['_were_multiplied'][$field]);
142
143
                // мультиплицируем только несовпадающие значения полей
144
                $newValue = $item[$field];
145
                if ($oldValue !== $newValue) {
146
                    // если еще не мультиплицировали поле, то его надо превратить в массив.
147
                    if (!$alreadyMultiplied) {
148
                        $oldFields[$field] = [
149
                            $oldFields[$field]
150
                        ];
151
                        $oldFields['_were_multiplied'][$field] = true;
152
                    }
153
154
                    // добавляем новое значению поле если такого еще нет.
155
                    if (empty($oldFields[$field]) || (is_array($oldFields[$field]) && !in_array($newValue, $oldFields[$field]))) {
156
                        $oldFields[$field][] = $newValue;
157
                    }
158
                }
159
            }
160
161
            $results[$keyByValue]->fields = $oldFields;
162
        }
163
    }
164
165
    /**
166
     * Get count of elements that match $filter.
167
     *
168
     * @return int
169
     */
170
    public function count()
171
    {
172
        if ($this->queryShouldBeStopped) {
173
            return 0;
174
        }
175
176
        return (int) $this->bxObject->getCount($this->normalizeFilter());
177
    }
178
179
    /**
180
     * Normalize filter before sending it to getList.
181
     * This prevents some inconsistency.
182
     *
183
     * @return array
184
     */
185
    protected function normalizeFilter()
186
    {
187
        return $this->filter;
188
    }
189
190
    /**
191
     * Normalize select before sending it to getList.
192
     * This prevents some inconsistency.
193
     *
194
     * @return array
195
     */
196
    protected function normalizeSelect()
197
    {
198
        return ( !$this->select || empty($this->select) ) ? ['*'] : $this->select;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->select of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
199
    }
200
}