Completed
Push — master ( 262d71...f4720a )
by Nekrasov
02:40
created

ElementQuery::fromSectionWithCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Arrilot\BitrixModels\Queries;
4
5
use Arrilot\BitrixModels\Collection;
6
use CIBlock;
7
use Exception;
8
9
/**
10
 * @method ElementQuery sortByDate(string $sort = 'desc')
11
 */
12
class ElementQuery extends BaseQuery
13
{
14
    /**
15
     * CIblock object or test double.
16
     *
17
     * @var object.
18
     */
19
    public static $cIblockObject;
20
21
    /**
22
     * Query sort.
23
     *
24
     * @var array
25
     */
26
    public $sort = ['SORT' => 'ASC'];
27
28
    /**
29
     * Query group by.
30
     *
31
     * @var array
32
     */
33
    public $groupBy = false;
34
35
    /**
36
     * Iblock id.
37
     *
38
     * @var int
39
     */
40
    protected $iblockId;
41
42
    /**
43
     * List of standard entity fields.
44
     *
45
     * @var array
46
     */
47
    protected $standardFields = [
48
        'ID',
49
        'TIMESTAMP_X',
50
        'TIMESTAMP_X_UNIX',
51
        'MODIFIED_BY',
52
        'DATE_CREATE',
53
        'DATE_CREATE_UNIX',
54
        'CREATED_BY',
55
        'IBLOCK_ID',
56
        'IBLOCK_SECTION_ID',
57
        'ACTIVE',
58
        'ACTIVE_FROM',
59
        'ACTIVE_TO',
60
        'SORT',
61
        'NAME',
62
        'PREVIEW_PICTURE',
63
        'PREVIEW_TEXT',
64
        'PREVIEW_TEXT_TYPE',
65
        'DETAIL_PICTURE',
66
        'DETAIL_TEXT',
67
        'DETAIL_TEXT_TYPE',
68
        'SEARCHABLE_CONTENT',
69
        'IN_SECTIONS',
70
        'SHOW_COUNTER',
71
        'SHOW_COUNTER_START',
72
        'CODE',
73
        'TAGS',
74
        'XML_ID',
75
        'EXTERNAL_ID',
76
        'TMP_ID',
77
        'CREATED_USER_NAME',
78
        'DETAIL_PAGE_URL',
79
        'LIST_PAGE_URL',
80
        'CREATED_DATE',
81
    ];
82
83
    /**
84
     * Method that is used to fetch getList results.
85
     * Available values: 'getNext' or 'getNextElement'.
86
     *
87
     * @var string
88
     */
89
    protected $fetchUsing = 'getNextElement';
90
91
    /**
92
     * Constructor.
93
     *
94
     * @param object $bxObject
95
     * @param string $modelName
96
     */
97
    public function __construct($bxObject, $modelName)
98
    {
99
        static::instantiateCIblockObject();
100
101
        parent::__construct($bxObject, $modelName);
102
103
        $this->iblockId = $modelName::iblockId();
104
        $this->fetchUsing = $modelName::$fetchUsing;
105
    }
106
107
    /**
108
     * Instantiate bitrix entity object.
109
     *
110
     * @throws Exception
111
     *
112
     * @return object
113
     */
114
    public static function instantiateCIblockObject()
115
    {
116
        if (static::$cIblockObject) {
117
            return static::$cIblockObject;
118
        }
119
120
        if (class_exists('CIblock')) {
121
            return static::$cIblockObject = new CIblock();
122
        }
123
124
        throw new Exception('CIblock object initialization failed');
125
    }
126
127
    /**
128
     * Setter for groupBy.
129
     *
130
     * @param $value
131
     *
132
     * @return $this
133
     */
134
    public function groupBy($value)
135
    {
136
        $this->groupBy = $value;
137
138
        return $this;
139
    }
140
141
    /**
142
     * Setter for fetchUsing.
143
     *
144
     * @param string $fetchUsing
145
     *
146
     * @return $this
147
     */
148
    public function fetchUsing($fetchUsing)
149
    {
150
        $this->fetchUsing = $fetchUsing;
151
152
        return $this;
153
    }
154
155
    /**
156
     * Get list of items.
157
     *
158
     * @return Collection
159
     */
160
    public function getList()
161
    {
162
        if ($this->queryShouldBeStopped) {
163
            return new Collection();
164
        }
165
166
        $items = [];
167
168
        $rsItems = $this->bxObject->getList(
169
            $this->sort,
170
            $this->normalizeFilter(),
171
            $this->groupBy,
172
            $this->navigation,
173
            $this->normalizeSelect()
174
        );
175
176
        if ($this->shouldBeFetchedUsingGetNext()) {
177
            while ($arItem = $rsItems->getNext()) {
178
                $this->addItemToResultsUsingKeyBy($items, new $this->modelName($arItem['ID'], $arItem));
179
            }
180
        } else {
181
            while ($obItem = $rsItems->getNextElement()) {
182
                $arItem = $obItem->getFields();
183
                if ($this->propsMustBeSelected()) {
184
                    $arItem['PROPERTIES'] = $obItem->getProperties();
185
                    $this->normalizePropertyResultFormat($arItem);
186
                }
187
188
                $this->addItemToResultsUsingKeyBy($items, new $this->modelName($arItem['ID'], $arItem));
189
            }
190
        }
191
192
        return new Collection($items);
193
    }
194
195
    /**
196
     * Get count of elements that match $filter.
197
     *
198
     * @return int
199
     */
200
    public function count()
201
    {
202
        if ($this->queryShouldBeStopped) {
203
            return 0;
204
        }
205
206
        return (int) $this->bxObject->getList(false, $this->normalizeFilter(), []);
207
    }
208
209
    /**
210
     * Normalize properties's format converting it to 'PROPERTY_"CODE"_VALUE'.
211
     *
212
     * @param array $fields
213
     *
214
     * @return null
215
     */
216
    protected function normalizePropertyResultFormat(&$fields)
217
    {
218
        if (empty($fields['PROPERTIES'])) {
219
            return;
220
        }
221
222
        foreach ($fields['PROPERTIES'] as $code => $prop) {
223
            $fields['PROPERTY_'.$code.'_VALUE'] = $prop['VALUE'];
224
            $fields['~PROPERTY_'.$code.'_VALUE'] = $prop['~VALUE'];
225
            $fields['PROPERTY_'.$code.'_DESCRIPTION'] = $prop['DESCRIPTION'];
226
            $fields['~PROPERTY_'.$code.'_DESCRIPTION'] = $prop['~DESCRIPTION'];
227
            $fields['PROPERTY_'.$code.'_VALUE_ID'] = $prop['PROPERTY_VALUE_ID'];
228
            if (isset($prop['VALUE_ENUM_ID'])) {
229
                $fields['PROPERTY_'.$code.'_ENUM_ID'] = $prop['VALUE_ENUM_ID'];
230
            }
231
        }
232
    }
233
234
    /**
235
     * Normalize filter before sending it to getList.
236
     * This prevents some inconsistency.
237
     *
238
     * @return array
239
     */
240
    protected function normalizeFilter()
241
    {
242
        $this->filter['IBLOCK_ID'] = $this->iblockId;
243
244
        return $this->filter;
245
    }
246
247
    /**
248
     * Normalize select before sending it to getList.
249
     * This prevents some inconsistency.
250
     *
251
     * @return array
252
     */
253 View Code Duplication
    protected function normalizeSelect()
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...
254
    {
255
        if ($this->fieldsMustBeSelected()) {
256
            $this->select = array_merge($this->standardFields, $this->select);
257
        }
258
259
        if ($this->propsMustBeSelected() && $this->shouldBeFetchedUsingGetNext()) {
260
            $this->addAllPropsToSelect();
261
        }
262
263
        $this->select[] = 'ID';
264
        $this->select[] = 'IBLOCK_ID';
265
266
        return $this->clearSelectArray();
267
    }
268
269
    /**
270
     * Add all iblock property codes to select.
271
     *
272
     * return null
273
     */
274
    protected function addAllPropsToSelect()
275
    {
276
        $this->select[] = 'ID';
277
        $this->select[] = 'IBLOCK_ID';
278
279
        $rsProps = static::$cIblockObject->getProperties($this->iblockId);
280
        while ($prop = $rsProps->fetch()) {
281
            $this->select[] = 'PROPERTY_'.$prop['CODE'];
282
        }
283
    }
284
285
    /**
286
     * Determine if we should fetch using GetNext() method.
287
     *
288
     * @return bool
289
     */
290
    protected function shouldBeFetchedUsingGetNext()
291
    {
292
        return $this->fetchUsing === 'getNext' || $this->fetchUsing === 'GetNext';
293
    }
294
}
295