Completed
Push — development ( 67765c...7029e6 )
by Andrij
18:12
created

Properties::makei18n()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 1
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace exchange\classes;
4
5
use CMSFactory\ModuleSettings;
6
7
/**
8
 *
9
 *
10
 * @author kolia
11
 */
12
class Properties extends ExchangeBase
13
{
0 ignored issues
show
introduced by
Opening brace of a class must be on the same line as the definition
Loading history...
14
15
    const PROPTYPE_NUM = 0;
16
    const PROPTYPE_SPR = 1;
17
18
    /**
19
     *
20
     * @var string
21
     */
22
    protected $brandIdentif = NULL;
23
24
    /**
25
     *
26
     * @var array [[id => name],...]
27
     */
28
    protected $brandIdsToNames = [];
29
30
    /**
31
     *
32
     * @var array (property_external_id => id)
33
     */
34
    protected $brands = [];
35
36
    /**
37
     * For the properties with type "Справочник"
38
     * @var array
39
     */
40
    public $dictionaryProperties = [];
41
42
    /**
43
     * External ids of existing properties
44
     * @var array
45
     */
46
    protected $existing = [];
47
48
    /**
49
     * External ids of new properties
50
     * @var array
51
     */
52
    protected $new = [];
53
54
    /**
55
     *
56
     * @var array
57
     */
58
    protected $propertiesData = [];
59
60
    public function getBrandIdByExId($externalId = NULL) {
61
62
        if ($externalId == NULL) {
63
            return $this->brands;
64
        }
65
66
        if (array_key_exists($externalId, $this->brands)) {
67
            return $this->brands[$externalId];
68
        }
69
70
        return FALSE;
71
    }
72
73
    /**
74
     * Отримання ід бренду по його назві.
75
     * Даний метод викликається із Products
76
     * Якщо бренд не існує, то він буде створений (правда це трошки трошки не продуктивно,
77
     * бо краще було б зв’язувати по exId, але це буде не універсально, бо зараз
78
     * бренд ід береться із властивостей - шоби не рухати більше ніж треба коду в модулі)
79
     * @param string $brandName
80
     * @return null|int
81
     */
82
    public function getBrandIdByName($brandName) {
83
84
        if (!is_string($brandName) || !isset($brandName[0])) {
85
            return null;
86
        }
87
88
        $brandName = trim($brandName);
89
        $brandId = array_search($brandName, $this->brandIdsToNames);
90
        if (false != $brandId && is_numeric($brandId)) {
91
            return $brandId;
92
        }
93
94
        // creating brand
95
        $this->db->insert(
96
            'shop_brands',
97
            [
98
             'url'     => translit_url($brandName),
99
             'created' => time(),
100
             'updated' => time(),
101
            ]
102
        );
103
104
        if ($this->db->_error_message()) {
105
            return null;
106
        }
107
108
        $brandId = $this->db->insert_id();
109
110
        $this->db->insert(
111
            'shop_brands_i18n',
112
            [
113
             'id'     => $brandId,
114
             'locale' => $this->locale,
115
             'name'   => $brandName,
116
            ]
117
        );
118
119
        if ($this->db->_error_message()) {
120
            $this->db->delete('shop_brands', ['id' => $brandId], 1);
121
            return null;
122
        }
123
124
        $this->brandIdsToNames[$brandId] = $brandName;
125
126
        return $brandId;
127
    }
128
129
    /**
130
     * Returns property identificator of brand
131
     * @return string
132
     */
133
    public function getBrandIdentif() {
134
135
        return $this->brandIdentif;
136
    }
137
138
    public function setBrandIdentif($brandIdentif) {
139
140
        $this->brandIdentif = $brandIdentif;
141
        return $this;
142
    }
143
144
    /**
0 ignored issues
show
introduced by
Doc comment is empty
Loading history...
145
     *
146
     */
147
    protected function import_() {
148
149
        \CI::$APP->load->helper('translit');
150
151
        // preparing data array for insert, splitting on new and existing properties
152
        $this->processProperties();
153
154
        if (count($this->new) > 0) {
155
            $this->insert();
156
        }
157
158
        $ignoreExisting = ModuleSettings::ofModule('exchange')->get('ignore_existing');
159
        if (count($this->existing) > 0 && !isset($ignoreExisting['properties'])) {
160
            $this->update();
161
        }
162
163
        if (count($this->brands) > 0) {
164
            $this->insertBrands();
165
        }
166
167
        $this->dataLoad->getNewData('properties');
168
169
        $this->loadBrandsNames();
170
171
        $this->processPropertiesValues();
172
    }
173
174
    /**
175
     * Parsing properties. Separation on new and existing.
176
     * Preparing arrays (insert & update) for db
177
     */
178
    protected function processProperties() {
179
        foreach ($this->importData as $property) {
180
            $propertyData = [];
0 ignored issues
show
Unused Code introduced by
$propertyData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
181
            $externalId = (string) $property->Ид;
182
            $name = (string) $property->Наименование;
183
184
            if ($name == $this->brandIdentif & $this->brandIdentif !== NULL) {
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: ($name == $this->brandId...->brandIdentif !== NULL, Probably Intended Meaning: $name == ($this->brandId...>brandIdentif !== NULL)

When comparing the result of a bit operation, we suggest to add explicit parenthesis and not to rely on PHP’s built-in operator precedence to ensure the code behaves as intended and to make it more readable.

Let’s take a look at these examples:

// Returns always int(0).
return 0 === $foo & 4;
return (0 === $foo) & 4;

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
185
                $this->brandIdentif = $externalId;
186
            }
187
188
            $propertyData = ['external_id' => $externalId];
189
190
            $this->propertiesData[$externalId]['name'] = $name;
191
192
            $propertyData['csv_name'] = str_replace(['-', '_', "'"], '', translit_url($property->Наименование));
193
194
            // type ("Справочник"|"Число")
195
            $type = (string) $property->ТипЗначений === 'Справочник' ? self::PROPTYPE_SPR : self::PROPTYPE_NUM;
196
            $this->propertiesData[$externalId]['type'] = $type;
197
            if ($type == self::PROPTYPE_SPR) {
198
                // getting all possible values
199
                $values = [];
200
                foreach ($property->ВариантыЗначений->Справочник as $propValue) {
201
                    $values[(string) $propValue->ИдЗначения] = (string) $propValue->Значение;
202
                }
203
                $this->dictionaryProperties[$externalId] = $values;
204
205
                if ($this->brandIdentif == $externalId) {
206
                    $this->brands = $values;
207
                }
208
            }
209
210
            // main_property
211
            $propertyData['main_property'] = (string) $property->Обязательное === 'true' ? 1 : 0;
212
213
            // checking if property is "multivalue"
214
            if ((string) $property->Множественное === 'true' || $type === self::PROPTYPE_SPR) {
215
                $propertyData['multiple'] = 1;
216
            } else {
217
                $propertyData['multiple'] = 0;
218
            }
219
220
            // status of property (active or disabled)
221
            $active = (string) $property->ИспользованиеСвойства === 'true';
222
            if ($active === TRUE || count($property->ИспользованиеСвойства) === 0) {
223
                $propertyData['active'] = 1;
224
            } else {
225
                $propertyData['active'] = 0;
226
            }
227
228
            // separation on new and existing
229
            if (!$this->propertyExists($externalId)) {
230
                // adding default property values
231
                $propertyData['show_in_compare'] = 0;
232
                $propertyData['show_on_site'] = 1;
233
                $propertyData['show_in_filter'] = 0;
234
235
                $this->new[$externalId] = $propertyData;
236
            } else {
237
                $this->existing[$externalId] = $propertyData;
238
            }
239
        }
240
    }
241
242
    /**
243
     * Checks if property exists by external id
244
     * @param string $externalId
245
     * @return boolean
246
     */
247
    protected function propertyExists($externalId) {
248
249
        foreach ($this->properties as $propertyData) {
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist. Did you mean dictionaryProperties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
250
            if ($propertyData['external_id'] == $externalId) {
251
                return TRUE;
252
            }
253
        }
254
        return FALSE;
255
    }
256
257
    /**
0 ignored issues
show
introduced by
Doc comment is empty
Loading history...
258
     *
259
     */
260
    protected function insert() {
261
262
        $this->insertBatch('shop_product_properties', $this->new);
263
        // getting updated data from DB
264
        $this->dataLoad->getNewData('properties');
265
266
        // preparing data for `i18n` and `mod_exchange`
267
        $i18n = $this->makei18n('new');
268
        $this->insertBatch('shop_product_properties_i18n', $i18n);
269
    }
270
271
    private function makei18n($type = 'existing') {
272
273
        $i18n = [];
274
        $modExchange = [];
0 ignored issues
show
Unused Code introduced by
$modExchange is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
275
        foreach ($this->properties as $propertyData) {
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist. Did you mean dictionaryProperties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
276
            $exId = $propertyData['external_id'];
277
            if (array_key_exists($exId, $this->$type)) {
278
                $arr = [];
0 ignored issues
show
Unused Code introduced by
$arr is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
279
280
                $i18n[] = [
281
                           'id'     => $propertyData['id'],
282
                           'name'   => $this->propertiesData[$exId]['name'],
283
                           'locale' => $this->locale,
284
                          ];
285
286
            }
287
        }
288
        return $i18n;
289
    }
290
291
    /**
292
     *
293
     * @throws \Exception
0 ignored issues
show
introduced by
Comment missing or not on the next line for @throws tag in function comment
Loading history...
294
     */
295
    protected function update() {
296
297
        $this->updateBatch('shop_product_properties', $this->existing, 'external_id');
298
        // preparing data for `i18n` and `mod_exchange`
299
        // preparing data for `i18n`
300
        $i18n = $this->makei18n();
301
302
        $this->updateBatch('shop_product_properties_i18n', $i18n, 'id');
303
    }
304
305
    /**
306
     * Inserting new brands,
307
     * forming array with all new brands
308
     */
309
    protected function insertBrands() {
310
311
        // getting existing brands
312
        $result = $this->db
313
            ->select(['id', 'name'])
314
            ->get('shop_brands_i18n')
315
            ->result_array();
316
317
        $existingBrands = [];
318
        foreach ($result as $brandData) {
319
            $existingBrands[strtolower($brandData['name'])] = $brandData['id'];
320
        }
321
322
        // inserting new brands
323
        $newBrands = [];
324
        $referensForI18n = [];
325
        foreach ($this->brands as $externalId => $brandName) {
326
            $name_ = strtolower($brandName);
327
            if (array_key_exists($name_, $existingBrands)) { // brand exist
0 ignored issues
show
introduced by
There should be no white space after an opening "{"
Loading history...
328
                $this->brands[$externalId] = $existingBrands[$name_];
329
            } else {
330
                $url = translit_url($brandName);
331
                $referensForI18n[$url] = $externalId;
332
                $newBrands[] = ['url' => $url];
333
            }
334
        }
335
336
        // those witch will be needed for products
337
        if (count($newBrands) > 0) {
338
            $this->insertBatch('shop_brands', $newBrands);
339
            $result = $this->db
340
                ->select(['id', 'url'])
341
                ->get('shop_brands')
342
                ->result_array();
343
344
            $newBrandsI18n = [];
345
            foreach ($result as $brandData) {
346
                if (array_key_exists($brandData['url'], $referensForI18n)) {
347
                    $newBrandsI18n[] = [
348
                                        'id'     => $brandData['id'],
349
                                        'name'   => $this->brands[$referensForI18n[$brandData['url']]],
350
                                        'locale' => $this->locale,
351
                                       ];
352
                    $this->brands[$referensForI18n[$brandData['url']]] = $brandData['id'];
353
                }
354
            }
355
356
            $this->insertBatch('shop_brands_i18n', $newBrandsI18n);
357
        }
358
    }
359
360
    protected function loadBrandsNames() {
361
362
        $result = $this->db
363
            ->select(['shop_brands.id', 'shop_brands_i18n.name'])
364
            ->from('shop_brands')
365
            ->join('shop_brands_i18n', sprintf("shop_brands.id=shop_brands_i18n.id AND shop_brands_i18n.locale='%s'", $this->locale))
366
            ->get();
367
368
        if (!$result) {
369
            return;
370
        }
371
        $result = $result->result_array();
372
373
        foreach ($result as $brandData) {
374
            $this->brandIdsToNames[$brandData['id']] = $brandData['name'];
375
        }
376
    }
377
378
    private function processPropertiesValues() {
379
        foreach ($this->properties as $property) {
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist. Did you mean dictionaryProperties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
380
381
            if(array_key_exists($property['external_id'], $this->dictionaryProperties)) {
0 ignored issues
show
introduced by
Expected "if (...) {\n"; found "if(...) {\n"
Loading history...
382
                foreach ($this->dictionaryProperties[$property['external_id']] as $key => $values) {
383
384
                    $prop = \SPropertyValueQuery::create()
385
                        ->useI18nQuery(\MY_Controller::getCurrentLocale())
386
                        ->filterByValue($values)
387
                        ->endUse()
388
                        ->filterByPropertyId($property['id'])
389
                        ->findOne();
390
391
                    if($prop === null) {
0 ignored issues
show
introduced by
Expected "if (...) {\n"; found "if(...) {\n"
Loading history...
392
                        $prop = new \SPropertyValue();
393
                        $prop->setLocale(\MY_Controller::getCurrentLocale());
394
                        $prop->setValue($values);
395
                        $prop->setPropertyId($property['id']);
396
                        $prop->save();
397
                    }
398
                }
399
            }
400
        }
401
    }
402
403
}