Completed
Push — development ( cfd391...deed4d )
by Andrij
12:03
created

modules/exchange/classes/Categories.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace exchange\classes;
4
5
use CMSFactory\ModuleSettings;
6
use core\models\Route;
7
use core\models\RouteQuery;
8
use Propel\Runtime\Exception\PropelException;
9
10
/**
11
 *
12
 *
13
 *
14
 * @author kolia
15
 */
16
final class Categories extends ExchangeBase
17
{
18
19
    /**
20
     *
21
     * @var array
22
     */
23
    private $categoriesNames = [];
24
25
    /**
26
     * Parsed categories from XML to one-dimension array
27
     * @var array
28
     */
29
    private $categoriesXml = [];
30
31
    /**
32
     *
33
     * @var array
34
     */
35
    private $existing = [];
36
37
    /**
38
     *
39
     */
40
    private $externalIds;
41
42
    /**
43
     *
44
     * @var array
45
     */
46
    private $new = [];
47
48
    /**
49
     * Check if category exists (by external id) (helper)
50
     * @param string $externalId
51
     * @param boolean $returnCategoryId if TRUE, then method will return id of category
52
     * @return boolean|int FALSE if category is new, TRUE otherwise
53
     */
54
    public function categoryExists2($externalId, $returnCategoryId = FALSE) {
55
56
        if (null === $this->externalIds) {
57
            $this->externalIds = [];
58
            foreach ($this->categories as $categoryId => $categoryData) {
59
                if (!empty($categoryData['external_id'])) {
60
                    $this->externalIds[$categoryData['external_id']] = $categoryId;
61
                }
62
            }
63
        }
64
        $exists = isset($this->externalIds[$externalId]);
65
        if ($exists == TRUE) {
66
            return $returnCategoryId !== TRUE ? TRUE : $this->externalIds[$externalId];
67
        }
68
        return FALSE;
69
    }
70
71
    /**
72
     * Starting import of the categories
73
     * @return boolean|array FALSE|array(count of inserted, count of deleted)
74
     * @throws \Exception
75
     */
76
    protected function import_() {
77
78
        // getting categories names for checking fr unique names
79
        $categoriesI18n = $this->db
80
            ->where('locale', \MY_Controller::getCurrentLocale())
81
            ->get('shop_category_i18n')
82
            ->result_array();
83
84
        /** @var array $categoriesI18n */
85
        foreach ($categoriesI18n as $category) {
86
            array_push($this->categoriesNames, $category['name']);
87
        }
88
        // creating one-dimention array of categories
89
        $this->processCategories($this->importData);
90
91
        // inserting
92
        $insertCount = count($this->new);
93
        if ($insertCount > 0) {
94
            $dbArray = $this->getPreparedData($this->new);
95
            $this->insertBatch('shop_category', $dbArray);
96
            $this->dataLoad->getNewData('categories');
97
            $i18nData = $this->getI18nData($this->new);
98
            $this->insertBatch('shop_category_i18n', $i18nData);
99
        }
100
101
        $ignoreExisting = ModuleSettings::ofModule('exchange')->get('ignore_existing');
102
        // updating
103
        $updateCount = count($this->existing);
104
        if ($updateCount > 0 && !isset($ignoreExisting['categories'])) {
105
            $dbArray = $this->getPreparedData($this->existing);
106
            $this->updateBatch('shop_category', $dbArray, 'external_id');
107
            $this->dataLoad->getNewData('categories');
108
            $i18nData = $this->getI18nData($this->existing);
109
            $this->updateBatch('shop_category_i18n', $i18nData, 'id');
110
        }
111
112
        $pathsAndParents = $this->getPathsAndParents();
113
        $this->updateBatch('shop_category', $pathsAndParents, 'id');
114
115
        $this->dataLoad->getNewData('categories');
116
    }
117
118
    /**
119
     * Creates one-dimension array with categories from XML-file
120
     * (method is filling  $categories, $new and $existing arrays of class instance)
121
     * @param \SimpleXMLElement $categories
122
     * @param string $parent (default null) external id of parent if there is
123
     */
124
    private function processCategories(\SimpleXMLElement $categories, $parent = NULL) {
125
        foreach ($categories as $category) {
126
            $externalId = (string) $category->Ид;
127
128
            // splitting on those which need to be updated and new (by external id)
129
            if (FALSE == $this->categoryExists($externalId)) {
130
                $this->new[] = $externalId;
131
                $name = $this->getCategoryName((string) $category->Наименование);
132
            } else {
133
                $this->existing[] = $externalId;
134
                $name = (string) $category->Наименование;
135
            }
136
137
            $this->categoriesXml[$externalId] = [
138
                                                 'name'               => $name,
139
                                                 'active'             => (string) $category->Статус === 'Удален' ? 0 : 1,
140
                                                 'external_id'        => $externalId,
141
                                                 'parent_external_id' => $parent === null ? 0 : $parent,
142
                                                ];
143
144
            if (isset($category->Группы)) {
145
                $this->processCategories($category->Группы->Группа, $externalId);
146
            }
147
        }
148
149
    }
150
151
    /**
152
     * Check if category exists (by external id) (helper)
153
     * @param string $externalId
154
     * @return boolean FALSE if category is new, FALSE otherwise
155
     */
156
    public function categoryExists($externalId) {
157
158
        foreach ($this->categories as $categoryId => $categoryData) {
159
            if ($externalId == $categoryData['external_id']) {
160
                return TRUE;
161
            }
162
        }
163
        return FALSE;
164
    }
165
166
    /**
167
     * @param string $name
168
     * @return string
169
     */
170
    private function getCategoryName($name) {
171
172
        $nameTemp = $name;
173
        $i = 1;
174
        while (in_array($nameTemp, $this->categoriesNames, true)) {
175
            $nameTemp = $name . ' ' . $i++;
176
        }
177
        array_push($this->categoriesNames, $nameTemp);
178
        return $nameTemp;
179
    }
180
181
    /**
182
     * Prepare array for DB insert/update query
183
     * (returns array ready to inserting in database)
184
     * @param array $categoriesExternalIds
185
     * @return array
186
     */
187
    private function getPreparedData(array $categoriesExternalIds) {
188
189
        $dbArray = [];
190
        foreach ($categoriesExternalIds as $externalId) {
191
            // fitment of category url (might be busy)
192
            // preparing array for insert
193
            $dbArray[] = [
194
                          'external_id' => $externalId,
195
                          'active'      => $this->categoriesXml[$externalId]['active'],
196
                         ];
197
        }
198
        return $dbArray;
199
    }
200
201
    /**
202
     * @param array $categoriesExternalIds
203
     * @return array
204
     */
205
    private function getI18nData($categoriesExternalIds) {
206
207
        $i18n = [];
208
        foreach ($this->categories as $categoryId => $categoryData) {
209
            if (in_array($categoryData['external_id'], $categoriesExternalIds, true)) {
210
                $i18n[] = [
211
                           'id'     => $categoryData['id'],
212
                           'locale' => $this->locale,
213
                           'name'   => $this->categoriesXml[$categoryData['external_id']]['name'],
214
                          ];
215
            }
216
        }
217
        return $i18n;
218
    }
219
220
    /**
221
     * Filling parent ids of
222
     * @return array
223
     */
224
    private function getPathsAndParents() {
225
        $categoriesExternalIds = array_merge($this->new, $this->existing);
226
        // UPDATING INSERTED CATEGORIES (add parent ids & full path)
227
        $this->dataLoad->getNewData('categories'); // getting categories form db again
228
        // getting only categories which was inserted
229
        $categories = [];
230
        // "parent data" is in $this->categories (db),
231
        foreach ($this->categories as $categoryId => $categoryData) {
232
            if (in_array($categoryData['external_id'], $categoriesExternalIds, true)) {
233
                $categories[$categoryData['id']] = [
234
                                                    'id'          => $categoryData['id'],
235
                                                    'parent_id'   => $this->getParentIdDb($categoryData['external_id']),
236
                                                    'external_id' => $categoryData['external_id'],
237
                                                   ];
238
            }
239
        }
240
241
        // creating id-paths and url-paths of each category
242
        foreach ($categories as $categoryId => $categoryData) {
243
            $currentPathIds = [];
244
245
            $neededCid = $categoryData['parent_id'];
246
247
            while ($neededCid != 0) {
248
                $currentPathIds[] = $neededCid;
249
                $neededCid = $categories[$neededCid]['parent_id'];
250
            }
251
252
            $parentUrl = RouteQuery::create()->filterByEntityId($categoryData['parent_id'])->filterByType(Route::TYPE_SHOP_CATEGORY)->findOne();
253
            try{
0 ignored issues
show
Expected 1 space after TRY keyword; 0 found
Loading history...
254
255
                        $route = new RouteQuery();
256
                        $route->filterByParentUrl($parentUrl ? $parentUrl->getFullUrl() : '');
257
                        $route->filterByUrl(translit_url($this->categoriesXml[$categoryData['external_id']]['name']));
258
                        $route->findByType(Route::TYPE_SHOP_CATEGORY);
259
                        $route->filterByEntityId($categoryData['id']);
260
                        $route->findOneOrCreate()->save();
261
262
            }catch (PropelException $exp){
263
                dd($exp);
0 ignored issues
show
The use of function dd() is forbidden
Loading history...
264
            }
265
            $categories[$categoryId]['route_id'] = $route->findOne()->getId();
266
            $categories[$categoryId]['full_path_ids'] = serialize(array_reverse($currentPathIds));
267
        }
268
269
        return $categories;
270
    }
271
272
    /**
273
     * Returning DB id of category by external_id (helper)
274
     * @param string $externalId
275
     * @return int|boolean id (DB primary key) of category|FALSE
276
     */
277
    private function getParentIdDb($externalId) {
278
279
        $parentExternalId = $this->categoriesXml[$externalId]['parent_external_id'];
280
        if ((string) $parentExternalId == '0') {
281
            return 0;
282
        }
283
        foreach ($this->categories as $categoryData) {
284
            if ($parentExternalId == $categoryData['external_id']) {
285
                return $categoryData['id'];
286
            }
287
        }
288
        return 0;
289
    }
290
291
}