Test Failed
Branch v5 (12d602)
by Alexey
04:51
created

OptionsParser::getWarehouses()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 5
Ratio 29.41 %

Importance

Changes 0
Metric Value
cc 7
eloc 12
nc 4
nop 1
dl 5
loc 17
rs 8.2222
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Helper for module methods
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2016 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
12
namespace Ecommerce;
13
14
class OptionsParser extends \InjiObject {
15
16
    public static function parse($options = [], $forCount = false) {
17
        $selectOptions = self::getDefault($options);
18
19
        //parse order options
20
        self::order($options, $selectOptions);
21
22
        //joined offers
23
        $selectOptions['join'][] = [Item\Offer::table(), Item::index() . ' = ' . Item\Offer::colPrefix() . Item::index(), 'inner'];
24
25
        //joined prices, check price configs
26
        $comparision = Item\Offer::index() . ' = ' . Item\Offer\Price::colPrefix() . Item\Offer::index();
27
        if (empty(\App::$cur->Ecommerce->config['show_zero_price'])) {
28
            $comparision .= ' and ' . Item\Offer\Price::colPrefix() . 'price>0';
29
        }
30
        if (!empty(\App::$cur->Ecommerce->config['available_price_types'])) {
31
            $comparision .= ' and ' . Item\Offer\Price::colPrefix() . 'item_offer_price_type_id in (' . implode(',', \App::$cur->Ecommerce->config['available_price_types']) . ')';
32
        }
33
        $selectOptions['join'][] = [Item\Offer\Price::table(), $comparision,
34
            empty(\App::$cur->Ecommerce->config['show_without_price']) ? 'inner' : 'left'];
35
36
        //join item types
37
        $selectOptions['join'][] = [
38
            Item\Offer\Price\Type::table(), Item\Offer\Price::colPrefix() . Item\Offer\Price\Type::index() . ' = ' . Item\Offer\Price\Type::index()
39
        ];
40
41
        //add filter for item type user roles by current user role
42
        $selectOptions['where'][] = [
43
            [Item\Offer\Price\Type::index(), null, 'is'],
44
            [
45
                [Item\Offer\Price\Type::colPrefix() . 'roles', '', '=', 'OR'],
46
                [Item\Offer\Price\Type::colPrefix() . 'roles', '%|' . \Users\User::$cur->role_id . '|%', 'LIKE', 'OR'],
47
            ],
48
        ];
49
50
        //add custom preset filters from config on where
51
        self::presetFilters($selectOptions);
52
53
        //parse filters
54
        self::filters($options, $selectOptions);
55
56
        //categories paths
57
        self::categories($options, $selectOptions);
58
59
        //search
60
        self::search($options, $selectOptions);
61
62
        self::warehouse($selectOptions);
63
        if ($forCount) {
64
            $selectOptions['distinct'] = \Ecommerce\Item::index();
65
        } else {
66
            $selectOptions['group'] = Item::index();
67
        }
68
        if (isset($options['array'])) {
69
            $selectOptions['array'] = $options['array'];
70
        }
71
72
        return $selectOptions;
73
    }
74
75
    public static function getDefault(&$options) {
76
        $selectOptions = [
77
            'where' => !empty($options['where']) ? $options['where'] : [],
78
            'distinct' => false,
79
            'join' => [],
80
            'order' => [],
81
            'start' => isset($options['start']) ? (int) $options['start'] : 0,
82
            'key' => isset($options['key']) ? $options['key'] : null,
83
            'limit' => !empty($options['count']) ? (int) $options['count'] : 0,
84
        ];
85
86
        //only not deleted items
87
        $selectOptions['where'][] = ['deleted', 0];
88
89
        //check config of view items without images
90
        if (empty(\App::$cur->Ecommerce->config['view_empty_image'])) {
91
            $selectOptions['where'][] = ['image_file_id', 0, '!='];
92
        }
93
94
        return $selectOptions;
95
    }
96
97
    public static function order(&$options, &$selectOptions) {
98
        if (empty($options['sort']) || !is_array($options['sort'])) {
99
            return;
100
        }
101
        foreach ($options['sort'] as $col => $direction) {
102
            $direction = strtolower($direction) == 'desc' ? 'desc' : 'asc';
103
            switch ($col) {
104
                case 'price':
105
                    $selectOptions['order'][] = [Item\Offer\Price::colPrefix() . 'price', $direction];
106
                    break;
107
                case 'new':
108
                    $selectOptions['order'][] = ['date_create', $direction];
109
                    break;
110
                case 'isset':
111
                    $warehouseIds = self::getWarehouses('order');
112
                    $selectOptions['order'][] = [
113
                        '(
114
          (SELECT COALESCE(sum(`' . Item\Offer\Warehouse::colPrefix() . 'count`),0) 
115
            FROM ' . \App::$cur->db->table_prefix . Item\Offer\Warehouse::table() . ' iciw 
116
            WHERE iciw.' . Item\Offer\Warehouse::colPrefix() . Item\Offer::index() . ' = ' . Item\Offer::index() . '
117
                ' . ($warehouseIds ? ' AND iciw.' . Item\Offer\Warehouse::colPrefix() . Warehouse::index() . ' IN(' . implode(',', $warehouseIds) . ')' : '') . '
118
            )
119
          -
120
          (SELECT COALESCE(sum(' . Warehouse\Block::colPrefix() . 'count) ,0)
121
            FROM ' . \App::$cur->db->table_prefix . Warehouse\Block::table() . ' iewb
122
            inner JOIN ' . \App::$cur->db->table_prefix . Cart::table() . ' icc ON icc.' . Cart::index() . ' = iewb.' . Warehouse\Block::colPrefix() . Cart::index() . ' AND (
123
                (`' . Cart::colPrefix() . 'warehouse_block` = 1 and `' . Cart::colPrefix() . 'cart_status_id` in(2,3,6)) ||
124
                (`' . Cart::colPrefix() . Cart\Status::index() . '` in(0,1) and `' . Cart::colPrefix() . 'date_last_activ` >=subdate(now(),INTERVAL 30 MINUTE))
125
            )
126
            WHERE iewb.' . Warehouse\Block::colPrefix() . Item\Offer::index() . ' = ' . Item\Offer::index() . ')
127
          )', $direction
128
                    ];
129
                    break;
130
                case 'name':
131
                case 'sales':
132
                case 'weight':
133
                    $selectOptions['order'][] = [$col, $direction];
134
            }
135
        }
136
        $selectOptions['order'][] = ['offers:prices:type:weight', 'ASC'];
137
    }
138
139
    public static function presetFilters(&$selectOptions) {
140
        if (empty(\App::$cur->Ecommerce->config['view_filter'])) {
141
            return;
142
        }
143
        if (!empty(\App::$cur->Ecommerce->config['view_filter']['options'])) {
144
            foreach (\App::$cur->Ecommerce->config['view_filter']['options'] as $optionId => $optionValue) {
145
                $selectOptions['join'][] = [Item\Param::table(), Item::index() . ' = ' . 'option' . $optionId . '.' . Item\Param::colPrefix() . Item::index() . ' AND ' .
146
                    'option' . $optionId . '.' . Item\Param::colPrefix() . Item\Option::index() . ' = "' . (int) $optionId . '" AND ' .
147
                    'option' . $optionId . '.' . Item\Param::colPrefix() . 'value = "' . (int) $optionValue . '"',
148
                    'inner', 'option' . $optionId];
149
            }
150
        }
151
    }
152
153
    public static function filters(&$options, &$selectOptions) {
154
        if (empty($options['filters'])) {
155
            return;
156
        }
157
        foreach ($options['filters'] as $col => $filter) {
158
            switch ($col) {
159
                case 'best':
160
                    if ($filter) {
161
                        $selectOptions['where'][] = ['best', 1];
162
                    }
163
                    break;
164
                case 'badge':
165
                    $selectOptions['where'][] = ['item_badge_id', (int) $filter];
166
                    break;
167
                case 'price':
168
                    $colName = Item\Offer\Price::colPrefix() . 'price';
169 View Code Duplication
                    if (!empty($filter['min'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
170
                        $selectOptions['where'][] = [$colName, (float) $filter['min'], '>='];
171
                    }
172 View Code Duplication
                    if (!empty($filter['max'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
173
                        $selectOptions['where'][] = [$colName, (float) $filter['max'], '<='];
174
                    }
175
                    break;
176
                case 'options':
177
                case 'offerOptions':
178
                    if ($col == 'offerOptions') {
179
                        $paramPrefix = Item\Offer\Param::colPrefix();
180
                        $itemIndex = Item\Offer::index();
181
                        $optionIndex = Item\Offer\Option::index();
182
                        $table = Item\Offer\Param::table();
183
                    } else {
184
                        $paramPrefix = Item\Param::colPrefix();
185
                        $itemIndex = Item::index();
186
                        $optionIndex = Item\Option::index();
187
                        $table = Item\Param::table();
188
                    }
189
                    if ($filter) {
190
                        foreach ($filter as $optionId => $optionValue) {
191
                            $optionId = (int) $optionId;
192
                            if (is_array($optionValue)) {
193
                                $optionValueArr = [];
194
                                foreach ($optionValue as $val) {
195
                                    $optionValueArr[] = \App::$cur->db->connection->pdo->quote($val);
196
                                }
197
                                $qstr = 'IN (' . implode(',', $optionValueArr) . ')';
198
                            } else {
199
                                $qstr = '= ' . \App::$cur->db->connection->pdo->quote($optionValue);
200
                            }
201
                            $selectOptions['join'][] = [$table, $itemIndex . ' = ' . 'option' . $optionId . '.' . $paramPrefix . $itemIndex . ' AND ' .
202
                                'option' . $optionId . '.' . $paramPrefix . $optionIndex . ' = "' . (int) $optionId . '" AND ' .
203
                                'option' . $optionId . '.' . $paramPrefix . 'value ' . $qstr . '',
204
                                'inner', 'option' . $optionId];
205
                        }
206
                    }
207
            }
208
        }
209
    }
210
211
    public static function categories(&$options, &$selectOptions) {
212
        if (empty($options['parent'])) {
213
            return;
214
        }
215
        if (is_array($options['parent']) || strpos($options['parent'], ',') !== false) {
216
            $list = is_array($options['parent']) ? $options['parent'] : explode(',', $options['parent']);
217
            $first = true;
218
            $where = [];
219
            foreach ($list as $categoryId) {
220
                if (!$categoryId) {
221
                    continue;
222
                }
223
                $category = Category::get($categoryId);
224
                $where[] = ['tree_path', $category->tree_path . (int) $categoryId . '/%', 'LIKE', $first ? 'AND' : 'OR'];
225
                $first = false;
226
            }
227
            $selectOptions['where'][] = $where;
228
        } else {
229
            $category = Category::get($options['parent']);
230
            if ($category) {
231
                $selectOptions['where'][] = ['tree_path', $category->tree_path . (int) $options['parent'] . '/%', 'LIKE'];
232
            }
233
        }
234
    }
235
236
    public static function search(&$options, &$selectOptions) {
237
        if (empty($options['search'])) {
238
            return;
239
        }
240
        $searchStr = preg_replace('![^A-zА-я0-9 ]!iSu', ' ', $options['search']);
241
        $searchArr = [];
242
        foreach (explode(' ', $searchStr) as $part) {
243
            $part = trim($part);
244
            if ($part && strlen($part) > 2) {
245
                $searchArr[] = ['search_index', '%' . $part . '%', 'LIKE'];
246
            }
247
        }
248
        if (!empty($searchArr)) {
249
            $selectOptions['where'][] = $searchArr;
250
        }
251
    }
252
253
    public static function warehouse(&$selectOptions) {
254
        if (!empty(\App::$cur->Ecommerce->config['view_empty_warehouse'])) {
255
            return;
256
        }
257
        $warehouseIds = self::getWarehouses();
258
259
        $selectOptions['where'][] = [
260
            '(
261
          (SELECT COALESCE(sum(`' . Item\Offer\Warehouse::colPrefix() . 'count`),0) 
262
            FROM ' . \App::$cur->db->table_prefix . Item\Offer\Warehouse::table() . ' iciw 
263
            WHERE iciw.' . Item\Offer\Warehouse::colPrefix() . Item\Offer::index() . ' = ' . Item\Offer::index() . '
264
                ' . ($warehouseIds ? ' AND iciw.' . Item\Offer\Warehouse::colPrefix() . Warehouse::index() . ' IN(' . implode(',', $warehouseIds) . ')' : '') . '
265
            )
266
          -
267
          (SELECT COALESCE(sum(' . Warehouse\Block::colPrefix() . 'count) ,0)
268
            FROM ' . \App::$cur->db->table_prefix . Warehouse\Block::table() . ' iewb
269
            inner JOIN ' . \App::$cur->db->table_prefix . Cart::table() . ' icc ON icc.' . Cart::index() . ' = iewb.' . Warehouse\Block::colPrefix() . Cart::index() . ' AND (
270
                (`' . Cart::colPrefix() . 'warehouse_block` = 1 and `' . Cart::colPrefix() . 'cart_status_id` in(2,3,6)) ||
271
                (`' . Cart::colPrefix() . Cart\Status::index() . '` in(0,1) and `' . Cart::colPrefix() . 'date_last_activ` >=subdate(now(),INTERVAL 30 MINUTE))
272
            )
273
            WHERE iewb.' . Warehouse\Block::colPrefix() . Item\Offer::index() . ' = ' . Item\Offer::index() . ')
274
          )',
275
            0,
276
            '>'
277
        ];
278
    }
279
280
    public static function getWarehouses($type = 'all') {
281
        if ($type === 'order') {
282
            $warehouses = Warehouse::getList(['where' => ['type', 'order']]);
283
            return array_keys($warehouses);
284
        }
285
        if (!\App::$cur->geography || !\Geography\City::$cur) {
286
            return [];
287
        }
288
        $warehouseIds = [];
289
        $warehouses = \Geography\City\Data::get([['code', 'warehouses'], ['city_id', \Geography\City::$cur->id]]);
290 View Code Duplication
        if ($warehouses && $warehouses->data) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
291
            foreach (explode(',', $warehouses->data) as $id) {
292
                $warehouseIds[$id] = $id;
293
            }
294
        }
295
        return $warehouseIds;
296
    }
297
}