Total Complexity | 48 |
Total Lines | 441 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like Base often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Base, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | abstract class Base extends \Aimeos\MShop\Common\Manager\Base |
||
22 | { |
||
23 | /** |
||
24 | * Unlock basket. |
||
25 | * Disable the lock for the serialized basket in the session so |
||
26 | * modifications of the basket content are allowed again. Note that the |
||
27 | * locks are advisory locks that can't be enforced if code doesn't care |
||
28 | * about the lock. |
||
29 | */ |
||
30 | const LOCK_DISABLE = 0; |
||
31 | |||
32 | /** |
||
33 | * Lock basket. |
||
34 | * Enable the lock for the serialized basket in the session so |
||
35 | * modifications of the basket content are not allowed any more. Note that |
||
36 | * the locks are advisory locks that can't be enforced if code doesn't care |
||
37 | * about the lock. |
||
38 | */ |
||
39 | const LOCK_ENABLE = 1; |
||
40 | |||
41 | |||
42 | /** |
||
43 | * Returns a new and empty order item (shopping basket). |
||
44 | * |
||
45 | * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00) |
||
46 | * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency |
||
47 | * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID |
||
48 | * @param \Aimeos\MShop\Order\Item\Product\Iface[] $products List of ordered product items |
||
49 | * @param \Aimeos\MShop\Order\Item\Address\Iface[] $addresses List of order address items |
||
50 | * @param \Aimeos\MShop\Order\Item\Service\Iface[] $services List of order serviceitems |
||
51 | * @param \Aimeos\MShop\Order\Item\Product\Iface[] $coupons Associative list of coupon codes as keys and items as values |
||
52 | * @param \Aimeos\MShop\Customer\Item\Iface|null $custItem Customer item object if requested |
||
53 | * @return \Aimeos\MShop\Order\Item\Iface Order object |
||
54 | */ |
||
55 | abstract protected function createItemBase( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale, |
||
56 | array $values = [], array $products = [], array $addresses = [], array $services = [], array $coupons = [], |
||
57 | ?\Aimeos\MShop\Customer\Item\Iface $custItem = null ) : \Aimeos\MShop\Order\Item\Iface; |
||
58 | |||
59 | |||
60 | /** |
||
61 | * Returns the current basket of the customer. |
||
62 | * |
||
63 | * @param string $type Basket type if a customer can have more than one basket |
||
64 | * @return \Aimeos\MShop\Order\Item\Iface Shopping basket |
||
65 | */ |
||
66 | public function getSession( string $type = 'default' ) : \Aimeos\MShop\Order\Item\Iface |
||
67 | { |
||
68 | $context = $this->context(); |
||
69 | $token = $context->token(); |
||
70 | $locale = $context->locale(); |
||
71 | $currency = $locale->getCurrencyId(); |
||
72 | $language = $locale->getLanguageId(); |
||
73 | $sitecode = $locale->getSiteItem()->getCode(); |
||
74 | |||
75 | $key = $token . '-' . $sitecode . '-' . $language . '-' . $currency . '-' . $type; |
||
76 | |||
77 | try |
||
78 | { |
||
79 | if( ( $order = \Aimeos\MShop::create( $context, 'order/basket' )->get( $key )->getItem() ) === null ) { |
||
80 | return $this->object()->create(); |
||
81 | } |
||
82 | |||
83 | \Aimeos\MShop::create( $context, 'plugin' )->register( $order, 'order' ); |
||
84 | } |
||
85 | catch( \Exception $e ) |
||
86 | { |
||
87 | return $this->object()->create(); |
||
88 | } |
||
89 | |||
90 | return $order; |
||
91 | } |
||
92 | |||
93 | |||
94 | /** |
||
95 | * Returns the current lock status of the basket. |
||
96 | * |
||
97 | * @param string $type Basket type if a customer can have more than one basket |
||
98 | * @return int Lock status (@see \Aimeos\MShop\Order\Manager\Base) |
||
99 | */ |
||
100 | public function getSessionLock( string $type = 'default' ) : int |
||
101 | { |
||
102 | $context = $this->context(); |
||
103 | $session = $context->session(); |
||
104 | $locale = $context->locale(); |
||
105 | $currency = $locale->getCurrencyId(); |
||
106 | $language = $locale->getLanguageId(); |
||
107 | $sitecode = $locale->getSiteItem()->getCode(); |
||
108 | $key = 'aimeos/basket/lock-' . $sitecode . '-' . $language . '-' . $currency . '-' . strval( $type ); |
||
109 | |||
110 | if( ( $value = $session->get( $key ) ) !== null ) { |
||
111 | return (int) $value; |
||
112 | } |
||
113 | |||
114 | return \Aimeos\MShop\Order\Manager\Base::LOCK_DISABLE; |
||
115 | } |
||
116 | |||
117 | |||
118 | /** |
||
119 | * Saves the current shopping basket of the customer. |
||
120 | * |
||
121 | * @param \Aimeos\MShop\Order\Item\Iface $order Shopping basket |
||
122 | * @param string $type Order type if a customer can have more than one order at once |
||
123 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
124 | */ |
||
125 | public function setSession( \Aimeos\MShop\Order\Item\Iface $order, string $type = 'default' ) : \Aimeos\MShop\Order\Manager\Iface |
||
126 | { |
||
127 | $context = $this->context(); |
||
128 | $token = $context->token(); |
||
129 | $locale = $context->locale(); |
||
130 | $currency = $locale->getCurrencyId(); |
||
131 | $language = $locale->getLanguageId(); |
||
132 | $sitecode = $locale->getSiteItem()->getCode(); |
||
133 | |||
134 | $key = $token . '-' . $sitecode . '-' . $language . '-' . $currency . '-' . strval( $type ); |
||
135 | |||
136 | $session = $context->session(); |
||
137 | |||
138 | $list = $session->get( 'aimeos/basket/list', [] ); |
||
139 | $list[$key] = $key; |
||
140 | |||
141 | $session->set( 'aimeos/basket/list', $list ); |
||
142 | |||
143 | $manager = \Aimeos\MShop::create( $context, 'order/basket' ); |
||
144 | $manager->save( $manager->create()->setId( $key )->setCustomerId( $context->user() )->setItem( clone $order ) ); |
||
145 | |||
146 | return $this; |
||
147 | } |
||
148 | |||
149 | |||
150 | /** |
||
151 | * Locks or unlocks the session by setting the lock value. |
||
152 | * The lock is a cooperative lock and you have to check the lock value before you proceed. |
||
153 | * |
||
154 | * @param int $lock Lock value (@see \Aimeos\MShop\Order\Manager\Base) |
||
155 | * @param string $type Order type if a customer can have more than one order at once |
||
156 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
157 | */ |
||
158 | public function setSessionLock( int $lock, string $type = 'default' ) : \Aimeos\MShop\Order\Manager\Iface |
||
159 | { |
||
160 | $this->checkLock( $lock ); |
||
161 | |||
162 | $context = $this->context(); |
||
163 | $session = $context->session(); |
||
164 | $locale = $context->locale(); |
||
165 | $currency = $locale->getCurrencyId(); |
||
166 | $language = $locale->getLanguageId(); |
||
167 | $sitecode = $locale->getSiteItem()->getCode(); |
||
168 | $key = 'aimeos/basket/lock-' . $sitecode . '-' . $language . '-' . $currency . '-' . strval( $type ); |
||
169 | |||
170 | $session->set( $key, strval( $lock ) ); |
||
171 | |||
172 | return $this; |
||
173 | } |
||
174 | |||
175 | |||
176 | /** |
||
177 | * Checks if the lock value is a valid constant. |
||
178 | * |
||
179 | * @param int $value Lock constant |
||
180 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
181 | * @throws \Aimeos\MShop\Order\Exception If given value is invalid |
||
182 | */ |
||
183 | protected function checkLock( int $value ) : \Aimeos\MShop\Order\Manager\Iface |
||
194 | } |
||
195 | |||
196 | |||
197 | /** |
||
198 | * Returns the address item map for the given order IDs |
||
199 | * |
||
200 | * @param string[] $ids List of order IDs |
||
201 | * @return array Multi-dimensional associative list of order IDs as keys and order address type/item pairs as values |
||
202 | */ |
||
203 | protected function getAddresses( array $ids ) : array |
||
204 | { |
||
205 | $items = []; |
||
206 | $manager = $this->object()->getSubManager( 'address' ); |
||
207 | |||
208 | $criteria = $manager->filter()->slice( 0, 0x7fffffff ); |
||
209 | $criteria->setConditions( $criteria->compare( '==', 'order.address.parentid', $ids ) ); |
||
210 | |||
211 | foreach( $manager->search( $criteria ) as $item ) { |
||
212 | $items[$item->getParentId()][] = $item; |
||
213 | } |
||
214 | |||
215 | return $items; |
||
216 | } |
||
217 | |||
218 | |||
219 | /** |
||
220 | * Returns the coupon map for the given order IDs |
||
221 | * |
||
222 | * @param string[] $ids List of order IDs |
||
223 | * @param array $products Associative list of IDs and order product ID/item pairs as values |
||
224 | * @return array Multi-dimensional associative list of order IDs as keys and coupons with product items as values |
||
225 | */ |
||
226 | protected function getCoupons( array $ids, array $products = [] ) : array |
||
227 | { |
||
228 | $map = $productMap = []; |
||
229 | $manager = $this->object()->getSubManager( 'coupon' ); |
||
230 | |||
231 | foreach( $products as $id => $list ) |
||
232 | { |
||
233 | if( !isset( $productMap[$id] ) ) { |
||
234 | $productMap[$id] = []; |
||
235 | } |
||
236 | |||
237 | foreach( $list as $key => $product ) { |
||
238 | $productMap[$id][$product->getId()] = $product; |
||
239 | } |
||
240 | } |
||
241 | |||
242 | $criteria = $manager->filter()->slice( 0, 0x7fffffff ); |
||
243 | $criteria->setConditions( $criteria->compare( '==', 'order.coupon.parentid', $ids ) ); |
||
244 | |||
245 | foreach( $manager->search( $criteria ) as $item ) |
||
246 | { |
||
247 | if( !isset( $map[$item->getParentId()][$item->getCode()] ) ) { |
||
248 | $map[$item->getParentId()][$item->getCode()] = []; |
||
249 | } |
||
250 | |||
251 | if( $item->getProductId() !== null && isset( $productMap[$item->getParentId()][$item->getProductId()] ) ) { |
||
252 | $map[$item->getParentId()][$item->getCode()][] = $productMap[$item->getParentId()][$item->getProductId()]; |
||
253 | } |
||
254 | } |
||
255 | |||
256 | return $map; |
||
257 | } |
||
258 | |||
259 | |||
260 | /** |
||
261 | * Retrieves the ordered products from the storage. |
||
262 | * |
||
263 | * @param string[] $ids List of order IDs |
||
264 | * @return array Multi-dimensional associative list of order IDs as keys and order product |
||
265 | * IDs/items pairs in reversed order as values |
||
266 | */ |
||
267 | protected function getProducts( array $ids ) : array |
||
268 | { |
||
269 | $map = $attributes = $subProducts = []; |
||
270 | $manager = $this->object()->getSubManager( 'product' ); |
||
271 | $attrManager = $manager->getSubManager( 'attribute' ); |
||
272 | |||
273 | $criteria = $manager->filter()->slice( 0, 0x7fffffff ); |
||
274 | $criteria->setConditions( $criteria->compare( '==', 'order.product.parentid', $ids ) ); |
||
275 | $items = $manager->search( $criteria )->reverse(); |
||
276 | |||
277 | $search = $attrManager->filter()->slice( 0, 0x7fffffff ); |
||
278 | $search->setConditions( $search->compare( '==', 'order.product.attribute.parentid', $items->keys()->toArray() ) ); |
||
279 | |||
280 | foreach( $attrManager->search( $search ) as $id => $attribute ) { |
||
281 | $attributes[$attribute->getParentId()][$id] = $attribute; |
||
282 | } |
||
283 | |||
284 | foreach( $items as $id => $item ) |
||
285 | { |
||
286 | if( isset( $attributes[$id] ) ) { |
||
287 | $item->setAttributeItems( $attributes[$id] ); |
||
288 | } |
||
289 | |||
290 | if( $item->getOrderProductId() === null ) |
||
291 | { |
||
292 | ksort( $subProducts ); // bring the array into the right order because it's reversed |
||
293 | $item->setProducts( $subProducts ); |
||
294 | $map[$item->getParentId()][$item->getPosition()] = $item; |
||
295 | |||
296 | $subProducts = []; |
||
297 | } |
||
298 | else |
||
299 | { // in case it's a sub-product |
||
300 | $subProducts[$item->getPosition()] = $item; |
||
301 | } |
||
302 | } |
||
303 | |||
304 | foreach( $map as $key => $list ) { |
||
305 | ksort( $map[$key] ); |
||
306 | } |
||
307 | |||
308 | return $map; |
||
309 | } |
||
310 | |||
311 | |||
312 | /** |
||
313 | * Retrieves the order services from the storage. |
||
314 | * |
||
315 | * @param string[] $ids List of order IDs |
||
316 | * @return array Multi-dimensional associative list of order IDs as keys and service type/items pairs as values |
||
317 | */ |
||
318 | protected function getServices( array $ids ) : array |
||
331 | } |
||
332 | |||
333 | |||
334 | /** |
||
335 | * Saves the addresses of the order to the storage. |
||
336 | * |
||
337 | * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing address items |
||
338 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
339 | */ |
||
340 | protected function saveAddresses( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface |
||
341 | { |
||
342 | $addresses = $basket->getAddresses()->flat( 1 ); |
||
343 | |||
344 | foreach( $addresses as $address ) |
||
345 | { |
||
346 | if( $address->getParentId() != $basket->getId() ) { |
||
347 | $address->setId( null ); // create new item if copied |
||
348 | } |
||
349 | |||
350 | $address->setParentId( $basket->getId() ); |
||
351 | } |
||
352 | |||
353 | $this->object()->getSubManager( 'address' )->save( $addresses ); |
||
354 | |||
355 | return $this; |
||
356 | } |
||
357 | |||
358 | |||
359 | /** |
||
360 | * Saves the coupons of the order to the storage. |
||
361 | * |
||
362 | * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing coupon items |
||
363 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
364 | */ |
||
365 | protected function saveCoupons( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface |
||
394 | } |
||
395 | |||
396 | |||
397 | /** |
||
398 | * Saves the ordered products to the storage. |
||
399 | * |
||
400 | * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing ordered products or bundles |
||
401 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
402 | */ |
||
403 | protected function saveProducts( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface |
||
437 | } |
||
438 | |||
439 | |||
440 | /** |
||
441 | * Saves the services of the order to the storage. |
||
442 | * |
||
443 | * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing service items |
||
444 | * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls |
||
445 | */ |
||
446 | protected function saveServices( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface |
||
462 | } |
||
463 | } |
||
464 |