1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* TechDivision\Import\Product\Observers\UrlRewriteUpdateObserver |
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 |
18
|
|
|
* @link http://www.techdivision.com |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace TechDivision\Import\Product\Observers; |
22
|
|
|
|
23
|
|
|
use TechDivision\Import\Product\Utils\MemberNames; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Observer that creates/updates the product's URL rewrites. |
27
|
|
|
* |
28
|
|
|
* @author Tim Wagner <[email protected]> |
29
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
30
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
31
|
|
|
* @link https://github.com/techdivision/import-product |
32
|
|
|
* @link http://www.techdivision.com |
33
|
|
|
*/ |
34
|
|
|
class UrlRewriteUpdateObserver extends UrlRewriteObserver |
35
|
|
|
{ |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Array with the existing URL rewrites of the actual product. |
39
|
|
|
* |
40
|
|
|
* @var array |
41
|
|
|
*/ |
42
|
|
|
protected $existingUrlRewrites = array(); |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Return's the URL rewrite for the passed store ID and request path. |
46
|
|
|
* |
47
|
|
|
* @param integer $storeId The store ID to return the URL rewrite for |
48
|
|
|
* @param string $requestPath The request path to return the URL rewrite for |
49
|
|
|
* |
50
|
|
|
* @return array|null The URL rewrite |
51
|
|
|
*/ |
52
|
1 |
|
protected function getExistingUrlRewrite($storeId, $requestPath) |
53
|
|
|
{ |
54
|
1 |
|
if (isset($this->existingUrlRewrites[$storeId][$requestPath])) { |
55
|
|
|
return $this->existingUrlRewrites[$storeId][$requestPath]; |
56
|
|
|
} |
57
|
1 |
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Remove's the passed URL rewrite from the existing one's. |
61
|
|
|
* |
62
|
|
|
* @param array $urlRewrite The URL rewrite to remove |
63
|
|
|
* |
64
|
|
|
* @return void |
65
|
|
|
*/ |
66
|
|
|
protected function removeExistingUrlRewrite(array $urlRewrite) |
67
|
|
|
{ |
68
|
|
|
|
69
|
|
|
// load store ID and request path |
70
|
|
|
$storeId = (integer) $urlRewrite[MemberNames::STORE_ID]; |
71
|
|
|
$requestPath = $urlRewrite[MemberNames::REQUEST_PATH]; |
72
|
|
|
|
73
|
|
|
// query whether or not the URL rewrite exists and remove it, if available |
74
|
|
|
if (isset($this->existingUrlRewrites[$storeId][$requestPath])) { |
75
|
|
|
unset($this->existingUrlRewrites[$storeId][$requestPath]); |
76
|
|
|
} |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Process the observer's business logic. |
81
|
|
|
* |
82
|
|
|
* @return void |
83
|
|
|
* @see \TechDivision\Import\Product\Observers\UrlRewriteObserver::process() |
84
|
|
|
*/ |
85
|
1 |
|
protected function process() |
86
|
|
|
{ |
87
|
|
|
|
88
|
|
|
// process the new URL rewrites first |
89
|
1 |
|
parent::process(); |
90
|
|
|
|
91
|
|
|
// load the root category |
92
|
1 |
|
$rootCategory = $this->getRootCategory(); |
93
|
|
|
|
94
|
|
|
// create redirect URL rewrites for the existing URL rewrites |
95
|
1 |
|
foreach ($this->existingUrlRewrites as $existingUrlRewrites) { |
96
|
1 |
|
foreach ($existingUrlRewrites as $existingUrlRewrite) { |
97
|
|
|
// if the URL rewrite has been created manually |
98
|
1 |
|
if ((integer) $existingUrlRewrite[MemberNames::IS_AUTOGENERATED] === 0) { |
99
|
|
|
// do NOT create another redirect |
100
|
|
|
continue; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
// if the URL rewrite already IS a redirect |
104
|
1 |
|
if ((integer) $existingUrlRewrite[MemberNames::REDIRECT_TYPE] !== 0) { |
105
|
|
|
// do NOT create another redirect |
106
|
|
|
continue; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
// load the metadata from the existing URL rewrite |
110
|
1 |
|
$metadata = $this->getMetadata($existingUrlRewrite); |
111
|
|
|
|
112
|
|
|
// initialize the category with the root category |
113
|
1 |
|
$category = $rootCategory; |
114
|
|
|
|
115
|
|
|
// query whether or not, the existing URL rewrite has been replaced |
116
|
1 |
|
if (isset($this->urlRewrites[$metadata['category_id']])) { |
117
|
|
|
// if yes, load the category of the original one |
118
|
1 |
|
$category = $this->getCategory($metadata['category_id']); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
// load target path/metadata for the actual category |
122
|
1 |
|
$targetPath = $this->prepareRequestPath($category); |
123
|
1 |
|
$metadata = serialize($this->prepareMetadata($category)); |
124
|
|
|
|
125
|
|
|
// override data witht rhe root category information |
126
|
|
|
$attr = array( |
127
|
1 |
|
MemberNames::REDIRECT_TYPE => 301, |
128
|
1 |
|
MemberNames::METADATA => $metadata, |
129
|
1 |
|
MemberNames::TARGET_PATH => $targetPath, |
130
|
|
|
); |
131
|
|
|
|
132
|
|
|
// merge and return the prepared URL rewrite |
133
|
1 |
|
$existingUrlRewrite = $this->mergeEntity($existingUrlRewrite, $attr); |
134
|
|
|
|
135
|
|
|
// create the URL rewrite |
136
|
1 |
|
$this->persistUrlRewrite($existingUrlRewrite); |
137
|
|
|
} |
138
|
|
|
} |
139
|
1 |
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Prepare's the URL rewrites that has to be created/updated. |
143
|
|
|
* |
144
|
|
|
* @return void |
145
|
|
|
* @see \TechDivision\Import\Product\Observers\UrlRewriteObserver::prepareUrlRewrites() |
146
|
|
|
*/ |
147
|
1 |
|
protected function prepareUrlRewrites() |
148
|
|
|
{ |
149
|
|
|
|
150
|
|
|
// prepare the new URL rewrites first |
151
|
1 |
|
parent::prepareUrlRewrites(); |
152
|
|
|
|
153
|
|
|
// (re-)initialize the array for the existing URL rewrites |
154
|
1 |
|
$this->existingUrlRewrites = array(); |
155
|
|
|
|
156
|
|
|
// load primary key and entity type |
157
|
1 |
|
$pk = $this->getPrimaryKey(); |
158
|
1 |
|
$entityType = UrlRewriteObserver::ENTITY_TYPE; |
159
|
|
|
|
160
|
|
|
// load the existing URL rewrites of the actual entity |
161
|
1 |
|
$existingUrlRewrites = $this->getUrlRewritesByEntityTypeAndEntityId($entityType, $pk); |
162
|
|
|
|
163
|
|
|
// prepare the existing URL rewrites to improve searching them by store ID/request path |
164
|
1 |
|
foreach ($existingUrlRewrites as $existingUrlRewrite) { |
165
|
|
|
// load store ID and request path from the existing URL rewrite |
166
|
1 |
|
$storeId = (integer) $existingUrlRewrite[MemberNames::STORE_ID]; |
167
|
1 |
|
$requestPath = $existingUrlRewrite[MemberNames::REQUEST_PATH]; |
168
|
|
|
|
169
|
|
|
// append the URL rewrite with its store ID/request path |
170
|
1 |
|
$this->existingUrlRewrites[$storeId][$requestPath] = $existingUrlRewrite; |
171
|
|
|
} |
172
|
1 |
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Initialize the category product with the passed attributes and returns an instance. |
176
|
|
|
* |
177
|
|
|
* @param array $attr The category product attributes |
178
|
|
|
* |
179
|
|
|
* @return array The initialized category product |
180
|
|
|
*/ |
181
|
1 |
|
protected function initializeUrlRewrite(array $attr) |
182
|
|
|
{ |
183
|
|
|
|
184
|
|
|
// load store ID and request path |
185
|
1 |
|
$storeId = $attr[MemberNames::STORE_ID]; |
186
|
1 |
|
$requestPath = $attr[MemberNames::REQUEST_PATH]; |
187
|
|
|
|
188
|
|
|
// try to load the URL rewrite for the store ID and request path |
189
|
1 |
|
if ($urlRewrite = $this->getExistingUrlRewrite($storeId, $requestPath)) { |
190
|
|
|
// if a URL rewrite has been found, do NOT create a redirect |
191
|
|
|
$this->removeExistingUrlRewrite($urlRewrite); |
192
|
|
|
|
193
|
|
|
// if the found URL rewrite has been created manually |
194
|
|
|
if ((integer) $urlRewrite[MemberNames::IS_AUTOGENERATED] === 0) { |
195
|
|
|
// do NOT update it nor create a another redirect |
196
|
|
|
return false; |
|
|
|
|
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
// if the found URL rewrite has been autogenerated, then update it |
200
|
|
|
return $this->mergeEntity($urlRewrite, $attr); |
201
|
|
|
|
|
|
|
|
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
// simple return the attributes |
205
|
1 |
|
return $attr; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Return's the unserialized metadata of the passed URL rewrite. If the |
210
|
|
|
* metadata doesn't contain a category ID, the category ID of the root |
211
|
|
|
* category will be added. |
212
|
|
|
* |
213
|
|
|
* @param array $urlRewrite The URL rewrite to return the metadata for |
214
|
|
|
* |
215
|
|
|
* @return array The metadata of the passed URL rewrite |
216
|
|
|
*/ |
217
|
1 |
|
protected function getMetadata($urlRewrite) |
218
|
|
|
{ |
219
|
|
|
|
220
|
|
|
// initialize the array with the metaddata |
221
|
1 |
|
$metadata = array(); |
222
|
|
|
|
223
|
|
|
// try to unserialize the metadata from the passed URL rewrite |
224
|
1 |
|
if (isset($urlRewrite[MemberNames::METADATA])) { |
225
|
1 |
|
$metadata = unserialize($urlRewrite[MemberNames::METADATA]); |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
// query whether or not a category ID has been found |
229
|
1 |
|
if (isset($metadata['category_id'])) { |
230
|
|
|
// if yes, return the metadata |
231
|
1 |
|
return $metadata; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
// if not, append the ID of the root category |
235
|
1 |
|
$rootCategory = $this->getRootCategory(); |
236
|
1 |
|
$metadata['category_id'] = $rootCategory[MemberNames::ENTITY_ID]; |
237
|
|
|
|
238
|
|
|
// and return the metadata |
239
|
1 |
|
return $metadata; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Return's the URL rewrites for the passed URL entity type and ID. |
244
|
|
|
* |
245
|
|
|
* @param string $entityType The entity type to load the URL rewrites for |
246
|
|
|
* @param integer $entityId The entity ID to laod the rewrites for |
247
|
|
|
* |
248
|
|
|
* @return array The URL rewrites |
249
|
|
|
*/ |
250
|
1 |
|
protected function getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId) |
251
|
|
|
{ |
252
|
1 |
|
return $this->getSubject()->getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId); |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.