1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* TechDivision\Import\Product\UrlRewrite\Observers\UrlRewriteObserver |
5
|
|
|
* |
6
|
|
|
* NOTICE OF LICENSE |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the Open Software License (OSL 3.0) |
9
|
|
|
* that is available through the world-wide-web at this URL: |
10
|
|
|
* http://opensource.org/licenses/osl-3.0.php |
11
|
|
|
* |
12
|
|
|
* PHP version 5 |
13
|
|
|
* |
14
|
|
|
* @author Tim Wagner <[email protected]> |
15
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
16
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
17
|
|
|
* @link https://github.com/techdivision/import-product-url-rewrite |
18
|
|
|
* @link http://www.techdivision.com |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace TechDivision\Import\Product\UrlRewrite\Observers; |
22
|
|
|
|
23
|
|
|
use TechDivision\Import\Utils\StoreViewCodes; |
24
|
|
|
use TechDivision\Import\Product\UrlRewrite\Utils\ColumnKeys; |
25
|
|
|
use TechDivision\Import\Product\UrlRewrite\Utils\MemberNames; |
26
|
|
|
use TechDivision\Import\Product\Utils\VisibilityKeys; |
27
|
|
|
use TechDivision\Import\Product\Utils\CoreConfigDataKeys; |
28
|
|
|
use TechDivision\Import\Product\Observers\AbstractProductImportObserver; |
29
|
|
|
use TechDivision\Import\Product\UrlRewrite\Services\ProductUrlRewriteProcessorInterface; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Observer that creates/updates the product's URL rewrites. |
33
|
|
|
* |
34
|
|
|
* @author Tim Wagner <[email protected]> |
35
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
36
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
37
|
|
|
* @link https://github.com/techdivision/import-product-url-rewrite |
38
|
|
|
* @link http://www.techdivision.com |
39
|
|
|
*/ |
40
|
|
|
class UrlRewriteObserver extends AbstractProductImportObserver |
41
|
|
|
{ |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* The entity type to load the URL rewrites for. |
45
|
|
|
* |
46
|
|
|
* @var string |
47
|
|
|
*/ |
48
|
|
|
const ENTITY_TYPE = 'product'; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* The key for the category in the metadata. |
52
|
|
|
* |
53
|
|
|
* @var string |
54
|
|
|
*/ |
55
|
|
|
const CATEGORY_ID = 'category_id'; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* The URL key from the CSV file column that has to be processed by the observer. |
59
|
|
|
* |
60
|
|
|
* @var string |
61
|
|
|
*/ |
62
|
|
|
protected $urlKey; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* The actual category ID to process. |
66
|
|
|
* |
67
|
|
|
* @var integer |
68
|
|
|
*/ |
69
|
|
|
protected $categoryId; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* The actual entity ID to process. |
73
|
|
|
* |
74
|
|
|
* @var integer |
75
|
|
|
*/ |
76
|
|
|
protected $entityId; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* The ID of the recently created URL rewrite. |
80
|
|
|
* |
81
|
|
|
* @var integer |
82
|
|
|
*/ |
83
|
|
|
protected $urlRewriteId; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* The array with the URL rewrites that has to be created. |
87
|
|
|
* |
88
|
|
|
* @var array |
89
|
|
|
*/ |
90
|
|
|
protected $urlRewrites = array(); |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* The array with the category IDs related with the product. |
94
|
|
|
* |
95
|
|
|
* @var array |
96
|
|
|
*/ |
97
|
|
|
protected $productCategoryIds = array(); |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* The product bunch processor instance. |
101
|
|
|
* |
102
|
|
|
* @var \TechDivision\Import\Product\UrlRewrite\Services\ProductUrlRewriteProcessorInterface |
103
|
|
|
*/ |
104
|
|
|
protected $productUrlRewriteProcessor; |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Initialize the observer with the passed product URL rewrite processor instance. |
108
|
|
|
* |
109
|
|
|
* @param \TechDivision\Import\Product\UrlRewrite\Services\ProductUrlRewriteProcessorInterface $productUrlRewriteProcessor The product URL rewrite processor instance |
110
|
|
|
*/ |
111
|
|
|
public function __construct(ProductUrlRewriteProcessorInterface $productUrlRewriteProcessor) |
112
|
|
|
{ |
113
|
|
|
$this->productUrlRewriteProcessor = $productUrlRewriteProcessor; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Return's the product bunch processor instance. |
118
|
|
|
* |
119
|
|
|
* @return \TechDivision\Import\Product\Services\ProductBunchProcessorInterface The product bunch processor instance |
120
|
|
|
*/ |
121
|
|
|
protected function getProductUrlRewriteProcessor() |
122
|
|
|
{ |
123
|
|
|
return $this->productUrlRewriteProcessor; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Process the observer's business logic. |
128
|
|
|
* |
129
|
|
|
* @return void |
130
|
|
|
*/ |
131
|
|
|
protected function process() |
132
|
|
|
{ |
133
|
|
|
|
134
|
|
|
// initialize the store view code |
135
|
|
|
$this->getSubject()->prepareStoreViewCode(); |
136
|
|
|
|
137
|
|
|
// load the SKU |
138
|
|
|
$sku = $this->getValue($this->getPrimaryKeyColumnName()); |
139
|
|
|
|
140
|
|
|
// load the store view - if no store view has been set we use the admin store view as default |
141
|
|
|
$storeViewCode = $this->getSubject()->getStoreViewCode(StoreViewCodes::ADMIN); |
142
|
|
|
|
143
|
|
|
// only map the visibility of the product with the default store view |
144
|
|
|
if (!$this->hasBeenProcessed($sku)) { |
145
|
|
|
$this->addEntityIdVisibilityIdMapping($this->getValue(ColumnKeys::VISIBILITY)); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
// query whether or not we're in the admin store view |
149
|
|
|
if ($storeViewCode === StoreViewCodes::ADMIN) { |
150
|
|
|
// stop processing as we don't want to create URL rewrites for the admin store view |
151
|
|
|
return; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// query whether or not the row has already been processed |
155
|
|
|
if ($this->storeViewHasBeenProcessed($sku, $storeViewCode)) { |
156
|
|
|
// log a message |
157
|
|
|
$this->getSubject() |
158
|
|
|
->getSystemLogger() |
159
|
|
|
->warning( |
160
|
|
|
sprintf( |
161
|
|
|
'URL rewrites for SKU "%s" + store view code "%s" has already been processed', |
162
|
|
|
$sku, |
163
|
|
|
$storeViewCode |
164
|
|
|
) |
165
|
|
|
); |
166
|
|
|
|
167
|
|
|
// return immediately |
168
|
|
|
return; |
169
|
|
|
}; |
170
|
|
|
|
171
|
|
|
// try to load the URL key, return immediately if not possible |
172
|
|
|
if ($this->hasValue(ColumnKeys::URL_KEY)) { |
173
|
|
|
$this->urlKey = $urlKey = $this->getValue(ColumnKeys::URL_KEY); |
174
|
|
|
} else { |
175
|
|
|
return; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
// prepare the URL rewrites |
179
|
|
|
$this->prepareUrlRewrites(); |
180
|
|
|
|
181
|
|
|
// do NOT create new URL rewrites, if the product is NOT visible (any more), BUT |
182
|
|
|
// handle existing URL rewrites, e. g. to remove and clean up the URL rewrites |
183
|
|
|
if ($this->isNotVisible()) { |
184
|
|
|
return; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
// iterate over the categories and create the URL rewrites |
188
|
|
|
foreach ($this->urlRewrites as $categoryId => $urlRewrite) { |
189
|
|
|
// initialize and persist the URL rewrite |
190
|
|
|
if ($urlRewrite = $this->initializeUrlRewrite($urlRewrite)) { |
191
|
|
|
// initialize URL rewrite and catagory ID |
192
|
|
|
$this->categoryId = $categoryId; |
|
|
|
|
193
|
|
|
$this->entityId = $urlRewrite[MemberNames::ENTITY_ID]; |
194
|
|
|
|
195
|
|
|
try { |
196
|
|
|
// persist the URL rewrite |
197
|
|
|
$this->urlRewriteId = $this->persistUrlRewrite($urlRewrite); |
|
|
|
|
198
|
|
|
|
199
|
|
|
// initialize and persist the URL rewrite product => category relation |
200
|
|
|
$urlRewriteProductCategory = $this->initializeUrlRewriteProductCategory( |
201
|
|
|
$this->prepareUrlRewriteProductCategoryAttributes() |
202
|
|
|
); |
203
|
|
|
|
204
|
|
|
// persist the URL rewrite product category relation |
205
|
|
|
$this->persistUrlRewriteProductCategory($urlRewriteProductCategory); |
206
|
|
|
|
207
|
|
|
} catch (\Exception $e) { |
208
|
|
|
// query whether or not debug mode has been enabled |
209
|
|
|
if ($this->getSubject()->isDebugMode()) { |
210
|
|
|
$this->getSubject()->getSystemLogger()->warning($this->getSubject()->appendExceptionSuffix($e->getMessage())); |
|
|
|
|
211
|
|
|
} else { |
212
|
|
|
throw $e; |
213
|
|
|
} |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
// if changed, e. g. the request path of the URL rewrite has been suffixed with a |
219
|
|
|
// number because another one with the same request path for an other entity and |
220
|
|
|
// a different store view already exists, then override the old URL key with the |
221
|
|
|
// new generated one |
222
|
|
|
if ($urlKey !== $this->urlKey) { |
223
|
|
|
$this->setValue(ColumnKeys::URL_KEY, $this->urlKey); |
224
|
|
|
} |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Initialize the category product with the passed attributes and returns an instance. |
229
|
|
|
* |
230
|
|
|
* @param array $attr The category product attributes |
231
|
|
|
* |
232
|
|
|
* @return array The initialized category product |
233
|
|
|
*/ |
234
|
|
|
protected function initializeUrlRewrite(array $attr) |
235
|
|
|
{ |
236
|
|
|
return $attr; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Initialize the URL rewrite product => category relation with the passed attributes |
241
|
|
|
* and returns an instance. |
242
|
|
|
* |
243
|
|
|
* @param array $attr The URL rewrite product => category relation attributes |
244
|
|
|
* |
245
|
|
|
* @return array The initialized URL rewrite product => category relation |
246
|
|
|
*/ |
247
|
|
|
protected function initializeUrlRewriteProductCategory($attr) |
248
|
|
|
{ |
249
|
|
|
return $attr; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Prepare's the URL rewrites that has to be created/updated. |
254
|
|
|
* |
255
|
|
|
* @return void |
256
|
|
|
*/ |
257
|
|
|
protected function prepareUrlRewrites() |
258
|
|
|
{ |
259
|
|
|
|
260
|
|
|
// (re-)initialize the array for the URL rewrites and the product category IDs |
261
|
|
|
$this->urlRewrites = array(); |
262
|
|
|
$this->productCategoryIds = array(); |
263
|
|
|
|
264
|
|
|
// load the root category, because we need that to create the default product URL rewrite |
265
|
|
|
$rootCategory = $this->getRootCategory(); |
266
|
|
|
|
267
|
|
|
// query whether or not categories has to be used as product URL suffix |
268
|
|
|
if ($this->getSubject()->getCoreConfigData(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_USE_CATEGORIES, false)) { |
269
|
|
|
// if yes, add the category IDs of the products |
270
|
|
|
foreach ($this->getProductCategoryIds() as $categoryId => $entityId) { |
271
|
|
|
$this->resolveCategoryIds($categoryId, $entityId, true); |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
// at least, add the root category ID to the category => product relations |
276
|
|
|
$this->productCategoryIds[$rootCategory[MemberNames::ENTITY_ID]] = $this->getSubject()->getLastEntityId(); |
|
|
|
|
277
|
|
|
|
278
|
|
|
// prepare the URL rewrites |
279
|
|
|
foreach ($this->productCategoryIds as $categoryId => $entityId) { |
280
|
|
|
// set category/entity ID |
281
|
|
|
$this->entityId = $entityId; |
282
|
|
|
$this->categoryId = $categoryId; |
283
|
|
|
|
284
|
|
|
// prepare the attributes for each URL rewrite |
285
|
|
|
$this->urlRewrites[$categoryId] = $this->prepareAttributes(); |
286
|
|
|
} |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* Resolve's the parent categories of the category with the passed ID and relate's |
291
|
|
|
* it with the product with the passed ID, if the category is top level OR has the |
292
|
|
|
* anchor flag set. |
293
|
|
|
* |
294
|
|
|
* @param integer $categoryId The ID of the category to resolve the parents |
295
|
|
|
* @param integer $entityId The ID of the product entity to relate the category with |
296
|
|
|
* @param boolean $topLevel TRUE if the passed category has top level, else FALSE |
297
|
|
|
* |
298
|
|
|
* @return void |
299
|
|
|
*/ |
300
|
|
|
protected function resolveCategoryIds($categoryId, $entityId, $topLevel = false) |
301
|
|
|
{ |
302
|
|
|
|
303
|
|
|
// return immediately if this is the absolute root node |
304
|
|
|
if ((integer) $categoryId === 1) { |
305
|
|
|
return; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
// load the data of the category with the passed ID |
309
|
|
|
$category = $this->getCategory($categoryId); |
310
|
|
|
|
311
|
|
|
// query whether or not the product has already been related |
312
|
|
|
if (!isset($this->productCategoryIds[$categoryId])) { |
313
|
|
|
if ($topLevel) { |
314
|
|
|
// relate it, if the category is top level |
315
|
|
|
$this->productCategoryIds[$categoryId] = $entityId; |
316
|
|
|
} elseif ((integer) $category[MemberNames::IS_ANCHOR] === 1) { |
317
|
|
|
// also relate it, if the category is not top level, but has the anchor flag set |
318
|
|
|
$this->productCategoryIds[$categoryId] = $entityId; |
319
|
|
|
} else { |
320
|
|
|
$this->getSubject() |
321
|
|
|
->getSystemLogger() |
322
|
|
|
->debug(sprintf('Don\'t create URL rewrite for category "%s" because of missing anchor flag', $category[MemberNames::PATH])); |
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
// load the root category |
327
|
|
|
$rootCategory = $this->getRootCategory(); |
328
|
|
|
|
329
|
|
|
// try to resolve the parent category IDs |
330
|
|
|
if ($rootCategory[MemberNames::ENTITY_ID] !== ($parentId = $category[MemberNames::PARENT_ID])) { |
331
|
|
|
$this->resolveCategoryIds($parentId, $entityId, false); |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Prepare the attributes of the entity that has to be persisted. |
337
|
|
|
* |
338
|
|
|
* @return array The prepared attributes |
339
|
|
|
*/ |
340
|
|
|
protected function prepareAttributes() |
341
|
|
|
{ |
342
|
|
|
|
343
|
|
|
// load the store ID to use |
344
|
|
|
$storeId = $this->getSubject()->getRowStoreId(); |
|
|
|
|
345
|
|
|
|
346
|
|
|
// load the category to create the URL rewrite for |
347
|
|
|
$category = $this->getCategory($this->categoryId); |
348
|
|
|
|
349
|
|
|
// initialize the values |
350
|
|
|
$requestPath = $this->prepareRequestPath($category); |
351
|
|
|
$targetPath = $this->prepareTargetPath($category); |
352
|
|
|
$metadata = serialize($this->prepareMetadata($category)); |
353
|
|
|
|
354
|
|
|
// return the prepared URL rewrite |
355
|
|
|
return $this->initializeEntity( |
356
|
|
|
array( |
357
|
|
|
MemberNames::ENTITY_TYPE => UrlRewriteObserver::ENTITY_TYPE, |
358
|
|
|
MemberNames::ENTITY_ID => $this->entityId, |
359
|
|
|
MemberNames::REQUEST_PATH => $requestPath, |
360
|
|
|
MemberNames::TARGET_PATH => $targetPath, |
361
|
|
|
MemberNames::REDIRECT_TYPE => 0, |
362
|
|
|
MemberNames::STORE_ID => $storeId, |
363
|
|
|
MemberNames::DESCRIPTION => null, |
364
|
|
|
MemberNames::IS_AUTOGENERATED => 1, |
365
|
|
|
MemberNames::METADATA => $metadata |
366
|
|
|
) |
367
|
|
|
); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Prepare's the URL rewrite product => category relation attributes. |
372
|
|
|
* |
373
|
|
|
* @return array The prepared attributes |
374
|
|
|
*/ |
375
|
|
|
protected function prepareUrlRewriteProductCategoryAttributes() |
376
|
|
|
{ |
377
|
|
|
|
378
|
|
|
// return the prepared product |
379
|
|
|
return $this->initializeEntity( |
380
|
|
|
array( |
381
|
|
|
MemberNames::PRODUCT_ID => $this->entityId, |
382
|
|
|
MemberNames::CATEGORY_ID => $this->categoryId, |
383
|
|
|
MemberNames::URL_REWRITE_ID => $this->urlRewriteId |
384
|
|
|
) |
385
|
|
|
); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Prepare's the target path for a URL rewrite. |
390
|
|
|
* |
391
|
|
|
* @param array $category The categroy with the URL path |
392
|
|
|
* |
393
|
|
|
* @return string The target path |
394
|
|
|
*/ |
395
|
|
|
protected function prepareTargetPath(array $category) |
396
|
|
|
{ |
397
|
|
|
|
398
|
|
|
// load the actual entity ID |
399
|
|
|
$lastEntityId = $this->getLastEntityId(); |
|
|
|
|
400
|
|
|
|
401
|
|
|
// query whether or not, the category is the root category |
402
|
|
|
if ($this->isRootCategory($category)) { |
403
|
|
|
$targetPath = sprintf('catalog/product/view/id/%d', $lastEntityId); |
404
|
|
|
} else { |
405
|
|
|
$targetPath = sprintf('catalog/product/view/id/%d/category/%d', $lastEntityId, $category[MemberNames::ENTITY_ID]); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
// return the target path |
409
|
|
|
return $targetPath; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Prepare's the request path for a URL rewrite or the target path for a 301 redirect. |
414
|
|
|
* |
415
|
|
|
* @param array $category The categroy with the URL path |
416
|
|
|
* |
417
|
|
|
* @return string The request path |
418
|
|
|
* @throws \RuntimeException Is thrown, if the passed category has no or an empty value for attribute "url_path" |
419
|
|
|
*/ |
420
|
|
|
protected function prepareRequestPath(array $category) |
421
|
|
|
{ |
422
|
|
|
|
423
|
|
|
// load the product URL suffix to use |
424
|
|
|
$urlSuffix = $this->getCoreConfigData(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'); |
|
|
|
|
425
|
|
|
|
426
|
|
|
// query whether or not, the category is the root category |
427
|
|
|
if ($this->isRootCategory($category)) { |
428
|
|
|
return sprintf('%s%s', $this->urlKey, $urlSuffix); |
429
|
|
|
} else { |
430
|
|
|
// query whether or not the category's "url_path" attribute, necessary to create a valid "request_path", is available |
431
|
|
|
if (isset($category[MemberNames::URL_PATH]) && $category[MemberNames::URL_PATH]) { |
432
|
|
|
return sprintf('%s/%s%s', $category[MemberNames::URL_PATH], $this->urlKey, $urlSuffix); |
433
|
|
|
} |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
// throw an exception if the category's "url_path" attribute is NOT available |
437
|
|
|
throw new \RuntimeException( |
438
|
|
|
sprintf( |
439
|
|
|
'Can\'t find mandatory attribute "%s" for category ID "%d", necessary to build a valid "request_path"', |
440
|
|
|
MemberNames::URL_PATH, |
441
|
|
|
$category[MemberNames::ENTITY_ID] |
442
|
|
|
) |
443
|
|
|
); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Prepare's the URL rewrite's metadata with the passed category values. |
448
|
|
|
* |
449
|
|
|
* @param array $category The category used for preparation |
450
|
|
|
* |
451
|
|
|
* @return array The metadata |
452
|
|
|
*/ |
453
|
|
|
protected function prepareMetadata(array $category) |
454
|
|
|
{ |
455
|
|
|
|
456
|
|
|
// initialize the metadata |
457
|
|
|
$metadata = array(); |
458
|
|
|
|
459
|
|
|
// query whether or not, the passed category IS the root category |
460
|
|
|
if ($this->isRootCategory($category)) { |
461
|
|
|
return $metadata; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
// if not, set the category ID in the metadata |
465
|
|
|
$metadata[UrlRewriteObserver::CATEGORY_ID] = $category[MemberNames::ENTITY_ID]; |
466
|
|
|
|
467
|
|
|
// return the metadata |
468
|
|
|
return $metadata; |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Query whether or not the actual entity is visible or not. |
473
|
|
|
* |
474
|
|
|
* @return boolean TRUE if the entity is NOT visible, else FALSE |
475
|
|
|
*/ |
476
|
|
|
protected function isNotVisible() |
477
|
|
|
{ |
478
|
|
|
return $this->getEntityIdVisibilityIdMapping() === VisibilityKeys::VISIBILITY_NOT_VISIBLE; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* Return's the visibility for the passed entity ID, if it already has been mapped. The mapping will be created |
483
|
|
|
* by calling <code>\TechDivision\Import\Product\Subjects\BunchSubject::getVisibilityIdByValue</code> which will |
484
|
|
|
* be done by the <code>\TechDivision\Import\Product\Callbacks\VisibilityCallback</code>. |
485
|
|
|
* |
486
|
|
|
* @return integer The visibility ID |
487
|
|
|
* @throws \Exception Is thrown, if the entity ID has not been mapped |
488
|
|
|
* @see \TechDivision\Import\Product\Subjects\BunchSubject::getVisibilityIdByValue() |
489
|
|
|
*/ |
490
|
|
|
protected function getEntityIdVisibilityIdMapping() |
491
|
|
|
{ |
492
|
|
|
return $this->getSubject()->getEntityIdVisibilityIdMapping(); |
|
|
|
|
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Return's the root category for the actual view store. |
497
|
|
|
* |
498
|
|
|
* @return array The store's root category |
499
|
|
|
* @throws \Exception Is thrown if the root category for the passed store code is NOT available |
500
|
|
|
*/ |
501
|
|
|
protected function getRootCategory() |
502
|
|
|
{ |
503
|
|
|
return $this->getSubject()->getRootCategory(); |
|
|
|
|
504
|
|
|
} |
505
|
|
|
|
506
|
|
|
/** |
507
|
|
|
* Return's TRUE if the passed category IS the root category, else FALSE. |
508
|
|
|
* |
509
|
|
|
* @param array $category The category to query |
510
|
|
|
* |
511
|
|
|
* @return boolean TRUE if the passed category IS the root category |
512
|
|
|
*/ |
513
|
|
|
protected function isRootCategory(array $category) |
514
|
|
|
{ |
515
|
|
|
|
516
|
|
|
// load the root category |
517
|
|
|
$rootCategory = $this->getRootCategory(); |
518
|
|
|
|
519
|
|
|
// compare the entity IDs and return the result |
520
|
|
|
return $rootCategory[MemberNames::ENTITY_ID] === $category[MemberNames::ENTITY_ID]; |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* Return's the list with category IDs the product is related with. |
525
|
|
|
* |
526
|
|
|
* @return array The product's category IDs |
527
|
|
|
*/ |
528
|
|
|
protected function getProductCategoryIds() |
529
|
|
|
{ |
530
|
|
|
return $this->getSubject()->getProductCategoryIds(); |
|
|
|
|
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
/** |
534
|
|
|
* Return's the category with the passed ID. |
535
|
|
|
* |
536
|
|
|
* @param integer $categoryId The ID of the category to return |
537
|
|
|
* |
538
|
|
|
* @return array The category data |
539
|
|
|
*/ |
540
|
|
|
protected function getCategory($categoryId) |
541
|
|
|
{ |
542
|
|
|
return $this->getSubject()->getCategory($categoryId); |
|
|
|
|
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
/** |
546
|
|
|
* Persist's the URL rewrite with the passed data. |
547
|
|
|
* |
548
|
|
|
* @param array $row The URL rewrite to persist |
549
|
|
|
* |
550
|
|
|
* @return string The ID of the persisted entity |
551
|
|
|
*/ |
552
|
|
|
protected function persistUrlRewrite($row) |
553
|
|
|
{ |
554
|
|
|
return $this->getProductUrlRewriteProcessor()->persistUrlRewrite($row); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
/** |
558
|
|
|
* Persist's the URL rewrite product => category relation with the passed data. |
559
|
|
|
* |
560
|
|
|
* @param array $row The URL rewrite product => category relation to persist |
561
|
|
|
* |
562
|
|
|
* @return void |
563
|
|
|
*/ |
564
|
|
|
protected function persistUrlRewriteProductCategory($row) |
565
|
|
|
{ |
566
|
|
|
return $this->getProductUrlRewriteProcessor()->persistUrlRewriteProductCategory($row); |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* Return's the column name that contains the primary key. |
571
|
|
|
* |
572
|
|
|
* @return string the column name that contains the primary key |
573
|
|
|
*/ |
574
|
|
|
protected function getPrimaryKeyColumnName() |
575
|
|
|
{ |
576
|
|
|
return ColumnKeys::SKU; |
577
|
|
|
} |
578
|
|
|
|
579
|
|
|
/** |
580
|
|
|
* Queries whether or not the passed SKU and store view code has already been processed. |
581
|
|
|
* |
582
|
|
|
* @param string $sku The SKU to check been processed |
583
|
|
|
* @param string $storeViewCode The store view code to check been processed |
584
|
|
|
* |
585
|
|
|
* @return boolean TRUE if the SKU and store view code has been processed, else FALSE |
586
|
|
|
*/ |
587
|
|
|
protected function storeViewHasBeenProcessed($sku, $storeViewCode) |
588
|
|
|
{ |
589
|
|
|
return $this->getSubject()->storeViewHasBeenProcessed($sku, $storeViewCode); |
|
|
|
|
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Add the entity ID => visibility mapping for the actual entity ID. |
594
|
|
|
* |
595
|
|
|
* @param string $visibility The visibility of the actual entity to map |
596
|
|
|
* |
597
|
|
|
* @return void |
598
|
|
|
*/ |
599
|
|
|
protected function addEntityIdVisibilityIdMapping($visibility) |
600
|
|
|
{ |
601
|
|
|
$this->getSubject()->addEntityIdVisibilityIdMapping($visibility); |
|
|
|
|
602
|
|
|
} |
603
|
|
|
} |
604
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.