Passed
Push — master ( a59ecb...8091ff )
by Aimeos
23:24 queued 18:06
created

Base::saveServices()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 16
rs 10
cc 3
nc 3
nop 1
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2023
7
 * @package MShop
8
 * @subpackage Order
9
 */
10
11
12
namespace Aimeos\MShop\Order\Manager;
13
14
15
/**
16
 * Basic methods and constants for order items (shopping basket).
17
 *
18
 * @package MShop
19
 * @subpackage Order
20
 */
21
abstract class Base extends \Aimeos\MShop\Common\Manager\Base
22
{
23
	/**
24
	 * Returns a new and empty order item (shopping basket).
25
	 *
26
	 * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00)
27
	 * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency
28
	 * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID
29
	 * @param \Aimeos\MShop\Order\Item\Product\Iface[] $products List of ordered product items
30
	 * @param \Aimeos\MShop\Order\Item\Address\Iface[] $addresses List of order address items
31
	 * @param \Aimeos\MShop\Order\Item\Service\Iface[] $services List of order serviceitems
32
	 * @param \Aimeos\MShop\Order\Item\Product\Iface[] $coupons Associative list of coupon codes as keys and items as values
33
	 * @param \Aimeos\MShop\Customer\Item\Iface|null $custItem Customer item object if requested
34
	 * @return \Aimeos\MShop\Order\Item\Iface Order object
35
	 */
36
	abstract protected function createItemBase( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale,
37
		array $values = [], array $products = [], array $addresses = [], array $services = [], array $coupons = [],
38
		?\Aimeos\MShop\Customer\Item\Iface $custItem = null ) : \Aimeos\MShop\Order\Item\Iface;
39
40
41
	/**
42
	 * Returns the address item map for the given order IDs
43
	 *
44
	 * @param string[] $ids List of order IDs
45
	 * @param array $ref List of referenced domains that should be fetched too
46
	 * @return array Multi-dimensional associative list of order IDs as keys and order address type/item pairs as values
47
	 */
48
	protected function getAddresses( array $ids, array $ref ) : array
49
	{
50
		$items = [];
51
		$manager = $this->object()->getSubManager( 'address' );
52
53
		$criteria = $manager->filter()->slice( 0, 0x7fffffff );
54
		$criteria->setConditions( $criteria->compare( '==', 'order.address.parentid', $ids ) );
55
56
		foreach( $manager->search( $criteria, $ref ) as $item ) {
57
			$items[$item->getParentId()][] = $item;
58
		}
59
60
		return $items;
61
	}
62
63
64
	/**
65
	 * Returns the coupon map for the given order IDs
66
	 *
67
	 * @param string[] $ids List of order IDs
68
	 * @param array $products Associative list of IDs and order product ID/item pairs as values
69
	 * @return array Multi-dimensional associative list of order IDs as keys and coupons with product items as values
70
	 */
71
	protected function getCoupons( array $ids, array $products = [] ) : array
72
	{
73
		$map = $productMap = [];
74
		$manager = $this->object()->getSubManager( 'coupon' );
75
76
		foreach( $products as $id => $list )
77
		{
78
			if( !isset( $productMap[$id] ) ) {
79
				$productMap[$id] = [];
80
			}
81
82
			foreach( $list as $key => $product ) {
83
				$productMap[$id][$product->getId()] = $product;
84
			}
85
		}
86
87
		$criteria = $manager->filter()->slice( 0, 0x7fffffff );
88
		$criteria->setConditions( $criteria->compare( '==', 'order.coupon.parentid', $ids ) );
89
90
		foreach( $manager->search( $criteria ) as $item )
91
		{
92
			if( !isset( $map[$item->getParentId()][$item->getCode()] ) ) {
93
				$map[$item->getParentId()][$item->getCode()] = [];
94
			}
95
96
			if( $item->getProductId() !== null && isset( $productMap[$item->getParentId()][$item->getProductId()] ) ) {
97
				$map[$item->getParentId()][$item->getCode()][] = $productMap[$item->getParentId()][$item->getProductId()];
98
			}
99
		}
100
101
		return $map;
102
	}
103
104
105
	/**
106
	 * Retrieves the ordered products from the storage.
107
	 *
108
	 * @param string[] $ids List of order IDs
109
	 * @param array $ref List of referenced domains that should be fetched too
110
	 * @return array Multi-dimensional associative list of order IDs as keys and order product
111
	 *	IDs/items pairs in reversed order as values
112
	 */
113
	protected function getProducts( array $ids, array $ref ) : array
114
	{
115
		$map = $attributes = $subProducts = [];
116
		$manager = $this->object()->getSubManager( 'product' );
117
		$attrManager = $manager->getSubManager( 'attribute' );
118
119
		$criteria = $manager->filter()->slice( 0, 0x7fffffff );
120
		$criteria->setConditions( $criteria->compare( '==', 'order.product.parentid', $ids ) );
121
		$items = $manager->search( $criteria, $ref )->reverse();
122
123
		$search = $attrManager->filter()->slice( 0, 0x7fffffff );
124
		$search->setConditions( $search->compare( '==', 'order.product.attribute.parentid', $items->keys()->toArray() ) );
125
126
		foreach( $attrManager->search( $search, $ref ) as $id => $attribute ) {
127
			$attributes[$attribute->getParentId()][$id] = $attribute;
128
		}
129
130
		foreach( $items as $id => $item )
131
		{
132
			if( isset( $attributes[$id] ) ) {
133
				$item->setAttributeItems( $attributes[$id] );
134
			}
135
136
			if( $item->getOrderProductId() === null )
137
			{
138
				ksort( $subProducts ); // bring the array into the right order because it's reversed
139
				$item->setProducts( $subProducts );
140
				$map[$item->getParentId()][$item->getPosition()] = $item;
141
142
				$subProducts = [];
143
			}
144
			else
145
			{	// in case it's a sub-product
146
				$subProducts[$item->getPosition()] = $item;
147
			}
148
		}
149
150
		foreach( $map as $key => $list ) {
151
			ksort( $map[$key] );
152
		}
153
154
		return $map;
155
	}
156
157
158
	/**
159
	 * Retrieves the order services from the storage.
160
	 *
161
	 * @param string[] $ids List of order IDs
162
	 * @param array $ref List of referenced domains that should be fetched too
163
	 * @return array Multi-dimensional associative list of order IDs as keys and service type/items pairs as values
164
	 */
165
	protected function getServices( array $ids, array $ref ) : array
166
	{
167
		$map = [];
168
		$manager = $this->object()->getSubManager( 'service' );
169
170
		$criteria = $manager->filter()->slice( 0, 0x7fffffff );
171
		$criteria->setConditions( $criteria->compare( '==', 'order.service.parentid', $ids ) );
172
173
		foreach( $manager->search( $criteria, $ref ) as $item ) {
174
			$map[$item->getParentId()][] = $item;
175
		}
176
177
		return $map;
178
	}
179
180
181
	/**
182
	 * Saves the addresses of the order to the storage.
183
	 *
184
	 * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing address items
185
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
186
	 */
187
	protected function saveAddresses( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
188
	{
189
		$addresses = $basket->getAddresses()->flat( 1 );
190
191
		foreach( $addresses as $address )
192
		{
193
			if( $address->getParentId() != $basket->getId() ) {
194
				$address->setId( null ); // create new item if copied
195
			}
196
197
			$address->setParentId( $basket->getId() );
198
		}
199
200
		$this->object()->getSubManager( 'address' )->save( $addresses );
201
202
		return $this;
203
	}
204
205
206
	/**
207
	 * Saves the coupons of the order to the storage.
208
	 *
209
	 * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing coupon items
210
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
211
	 */
212
	protected function saveCoupons( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
213
	{
214
		$manager = $this->object()->getSubManager( 'coupon' );
215
		$filter = $manager->filter()->add( 'order.coupon.parentid', '==', $basket->getId() )->slice( 0, 0x7fffffff );
216
		$items = $manager->search( $filter )->groupBy( 'order.coupon.code' );
217
218
		foreach( $basket->getCoupons() as $code => $products )
219
		{
220
			if( empty( $products ) )
221
			{
222
				$item = !empty( $items[$code] ) ? current( $items[$code] ) : $manager->create()->setParentId( $basket->getId() );
0 ignored issues
show
Bug introduced by
It seems like $items[$code] can also be of type null; however, parameter $array of current() does only seem to accept array|object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
				$item = !empty( $items[$code] ) ? current( /** @scrutinizer ignore-type */ $items[$code] ) : $manager->create()->setParentId( $basket->getId() );
Loading history...
223
				$manager->save( $item->setCode( $code ) );
224
				continue;
225
			}
226
227
			foreach( $products as $product )
228
			{
229
				foreach( $items[$code] ?? [] as $prodItem )
230
				{
231
					if( $product->getId() === $prodItem->getId() ) {
232
						continue 2;
233
					}
234
				}
235
236
				$manager->save( $manager->create()->setParentId( $basket->getId() )->setCode( $code )->setProductId( $product->getId() ) );
237
			}
238
		}
239
240
		return $this;
241
	}
242
243
244
	/**
245
	 * Saves the ordered products to the storage.
246
	 *
247
	 * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing ordered products or bundles
248
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
249
	 */
250
	protected function saveProducts( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
251
	{
252
		$products = $basket->getProducts();
253
		$pos = (int) $products->merge( $products->getProducts()->flat( 1 ) )->max( 'order.product.position' );
254
255
		foreach( $products as $product )
256
		{
257
			if( $product->getParentId() != $basket->getId() ) {
258
				$product->setId( null ); // create new item if copied
259
			}
260
261
			if( !$product->getPosition() ) {
262
				$product->setPosition( ++$pos );
263
			}
264
265
			$product->setParentId( $basket->getId() );
266
267
			foreach( $product->getProducts() as $subProduct )
268
			{
269
				if( $subProduct->getParentId() != $basket->getId() ) {
270
					$subProduct->setId( null ); // create new item if copied
271
				}
272
273
				if( !$subProduct->getPosition() ) {
274
					$subProduct->setPosition( ++$pos );
275
				}
276
277
				$subProduct->setParentId( $basket->getId() );
278
			}
279
		}
280
281
		$this->object()->getSubManager( 'product' )->save( $products );
282
283
		return $this;
284
	}
285
286
287
	/**
288
	 * Saves the services of the order to the storage.
289
	 *
290
	 * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing service items
291
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
292
	 */
293
	protected function saveServices( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
294
	{
295
		$services = $basket->getServices()->flat( 1 );
296
297
		foreach( $services as $service )
298
		{
299
			if( $service->getParentId() != $basket->getId() ) {
300
				$service->setId( null ); // create new item if copied
301
			}
302
303
			$service->setParentId( $basket->getId() );
304
		}
305
306
		$this->object()->getSubManager( 'service' )->save( $services );
307
308
		return $this;
309
	}
310
}
311