Passed
Push — master ( 022b5e...74faaa )
by Aimeos
04:45
created

Standard::createItemBase()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 8
dl 0
loc 6
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2020
7
 * @package MShop
8
 * @subpackage Order
9
 */
10
11
12
namespace Aimeos\MShop\Order\Manager\Base;
13
14
15
/**
16
 * Default implementation for order base manager.
17
 *
18
 * @package MShop
19
 * @subpackage Order
20
 */
21
class Standard extends Base
22
	implements \Aimeos\MShop\Order\Manager\Base\Iface, \Aimeos\MShop\Common\Manager\Factory\Iface
23
{
24
	private $searchConfig = array(
25
		'order.base.id' => array(
26
			'code' => 'order.base.id',
27
			'internalcode' => 'mordba."id"',
28
			'internaldeps' => array( 'LEFT JOIN "mshop_order_base" AS mordba ON ( mord."baseid" = mordba."id" )' ),
29
			'label' => 'Order ID',
30
			'type' => 'integer',
31
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
32
			'public' => false,
33
		),
34
		'order.base.siteid' => array(
35
			'code' => 'order.base.siteid',
36
			'internalcode' => 'mordba."siteid"',
37
			'label' => 'Order site ID',
38
			'type' => 'string',
39
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
40
			'public' => false,
41
		),
42
		'order.base.sitecode' => array(
43
			'code' => 'order.base.sitecode',
44
			'internalcode' => 'mordba."sitecode"',
45
			'label' => 'Order site code',
46
			'type' => 'string',
47
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
48
			'public' => false,
49
		),
50
		'order.base.customerid' => array(
51
			'code' => 'order.base.customerid',
52
			'internalcode' => 'mordba."customerid"',
53
			'label' => 'Order customer ID',
54
			'type' => 'string',
55
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
56
		),
57
		'order.base.customerref' => array(
58
			'code' => 'order.base.customerref',
59
			'internalcode' => 'mordba."customerref"',
60
			'label' => 'Order customer reference',
61
			'type' => 'string',
62
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
63
		),
64
		'order.base.languageid' => array(
65
			'code' => 'order.base.languageid',
66
			'internalcode' => 'mordba."langid"',
67
			'label' => 'Order language code',
68
			'type' => 'string',
69
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
70
		),
71
		'order.base.currencyid' => array(
72
			'code' => 'order.base.currencyid',
73
			'internalcode' => 'mordba."currencyid"',
74
			'label' => 'Order currencyid code',
75
			'type' => 'string',
76
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
77
		),
78
		'order.base.price' => array(
79
			'code' => 'order.base.price',
80
			'internalcode' => 'mordba."price"',
81
			'label' => 'Order price amount',
82
			'type' => 'string',
83
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
84
		),
85
		'order.base.costs' => array(
86
			'code' => 'order.base.costs',
87
			'internalcode' => 'mordba."costs"',
88
			'label' => 'Order shipping amount',
89
			'type' => 'string',
90
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
91
		),
92
		'order.base.rebate' => array(
93
			'code' => 'order.base.rebate',
94
			'internalcode' => 'mordba."rebate"',
95
			'label' => 'Order rebate amount',
96
			'type' => 'string',
97
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
98
		),
99
		'order.base.taxvalue' => array(
100
			'code' => 'order.base.taxvalue',
101
			'internalcode' => 'mordba."tax"',
102
			'label' => 'Order tax amount',
103
			'type' => 'string',
104
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
105
		),
106
		'order.base.taxflag' => array(
107
			'code' => 'order.base.taxflag',
108
			'internalcode' => 'mordba."taxflag"',
109
			'label' => 'Order tax flag (0=net, 1=gross)',
110
			'type' => 'string',
111
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
112
		),
113
		'order.base.comment' => array(
114
			'code' => 'order.base.comment',
115
			'internalcode' => 'mordba."comment"',
116
			'label' => 'Order comment',
117
			'type' => 'string',
118
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
119
		),
120
		'order.base.ctime' => array(
121
			'code' => 'order.base.ctime',
122
			'internalcode' => 'mordba."ctime"',
123
			'label' => 'Order create date/time',
124
			'type' => 'datetime',
125
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
126
			'public' => false,
127
		),
128
		'order.base.mtime' => array(
129
			'code' => 'order.base.mtime',
130
			'internalcode' => 'mordba."mtime"',
131
			'label' => 'Order modify date/time',
132
			'type' => 'datetime',
133
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
134
			'public' => false,
135
		),
136
		'order.base.editor' => array(
137
			'code' => 'order.base.editor',
138
			'internalcode' => 'mordba."editor"',
139
			'label' => 'Order editor',
140
			'type' => 'string',
141
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
142
			'public' => false,
143
		),
144
	);
145
146
147
	/**
148
	 * Initializes the object.
149
	 *
150
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
151
	 */
152
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
153
	{
154
		parent::__construct( $context );
155
		$this->setResourceName( 'db-order' );
156
	}
157
158
159
	/**
160
	 * Counts the number items that are available for the values of the given key.
161
	 *
162
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria
163
	 * @param string $key Search key to aggregate items for
164
	 * @param string|null $value Search key for aggregating the value column
165
	 * @param string|null $type Type of the aggregation, empty string for count or "sum" or "avg" (average)
166
	 * @return \Aimeos\Map List of the search keys as key and the number of counted items as value
167
	 */
168
	public function aggregate( \Aimeos\MW\Criteria\Iface $search, string $key, string $value = null, string $type = null ) : \Aimeos\Map
169
	{
170
		/** mshop/order/manager/base/standard/aggregate/mysql
171
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
172
		 *
173
		 * @see mshop/order/manager/base/standard/aggregate/ansi
174
		 */
175
176
		/** mshop/order/manager/base/standard/aggregate/ansi
177
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
178
		 *
179
		 * Groups all records by the values in the key column and counts their
180
		 * occurence. The matched records can be limited by the given criteria
181
		 * from the order database. The records must be from one of the sites
182
		 * that are configured via the context item. If the current site is part
183
		 * of a tree of sites, the statement can count all records from the
184
		 * current site and the complete sub-tree of sites.
185
		 *
186
		 * As the records can normally be limited by criteria from sub-managers,
187
		 * their tables must be joined in the SQL context. This is done by
188
		 * using the "internaldeps" property from the definition of the ID
189
		 * column of the sub-managers. These internal dependencies specify
190
		 * the JOIN between the tables and the used columns for joining. The
191
		 * ":joins" placeholder is then replaced by the JOIN strings from
192
		 * the sub-managers.
193
		 *
194
		 * To limit the records matched, conditions can be added to the given
195
		 * criteria object. It can contain comparisons like column names that
196
		 * must match specific values which can be combined by AND, OR or NOT
197
		 * operators. The resulting string of SQL conditions replaces the
198
		 * ":cond" placeholder before the statement is sent to the database
199
		 * server.
200
		 *
201
		 * This statement doesn't return any records. Instead, it returns pairs
202
		 * of the different values found in the key column together with the
203
		 * number of records that have been found for that key values.
204
		 *
205
		 * The SQL statement should conform to the ANSI standard to be
206
		 * compatible with most relational database systems. This also
207
		 * includes using double quotes for table and column names.
208
		 *
209
		 * @param string SQL statement for aggregating order items
210
		 * @since 2014.09
211
		 * @category Developer
212
		 * @see mshop/order/manager/base/standard/insert/ansi
213
		 * @see mshop/order/manager/base/standard/update/ansi
214
		 * @see mshop/order/manager/base/standard/newid/ansi
215
		 * @see mshop/order/manager/base/standard/delete/ansi
216
		 * @see mshop/order/manager/base/standard/search/ansi
217
		 * @see mshop/order/manager/base/standard/count/ansi
218
		 */
219
220
		/** mshop/order/manager/base/standard/aggregateavg/mysql
221
		 * Computes the average of all values grouped by the key column and matched by the given criteria
222
		 *
223
		 * @param string SQL statement for aggregating the order base items and computing the average value
224
		 * @since 2017.10
225
		 * @category Developer
226
		 * @see mshop/order/manager/base/standard/aggregateavg/ansi
227
		 * @see mshop/order/manager/base/standard/aggregate/mysql
228
		 */
229
230
		/** mshop/order/manager/base/standard/aggregateavg/ansi
231
		 * Computes the average of all values grouped by the key column and matched by the given criteria
232
		 *
233
		 * @param string SQL statement for aggregating the order base items and computing the average value
234
		 * @since 2017.10
235
		 * @category Developer
236
		 * @see mshop/order/manager/base/standard/aggregate/ansi
237
		 */
238
239
		/** mshop/order/manager/base/standard/aggregatesum/mysql
240
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
241
		 *
242
		 * @param string SQL statement for aggregating the order base items and computing the sum
243
		 * @since 2017.10
244
		 * @category Developer
245
		 * @see mshop/order/manager/base/standard/aggregatesum/ansi
246
		 * @see mshop/order/manager/base/standard/aggregate/mysql
247
		 */
248
249
		/** mshop/order/manager/base/standard/aggregatesum/ansi
250
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
251
		 *
252
		 * @param string SQL statement for aggregating the order base items and computing the sum
253
		 * @since 2017.10
254
		 * @category Developer
255
		 * @see mshop/order/manager/base/standard/aggregate/ansi
256
		 */
257
258
		$cfgkey = 'mshop/order/manager/base/standard/aggregate' . $type;
259
		return $this->aggregateBase( $search, $key, $cfgkey, array( 'order.base' ), $value );
260
	}
261
262
263
	/**
264
	 * Removes old entries from the storage.
265
	 *
266
	 * @param string[] $siteids List of IDs for sites whose entries should be deleted
267
	 * @return \Aimeos\MShop\Order\Manager\Base\Iface Manager object for chaining method calls
268
	 */
269
	public function clear( array $siteids ) : \Aimeos\MShop\Common\Manager\Iface
270
	{
271
		$path = 'mshop/order/manager/base/submanagers';
272
		$default = array( 'address', 'coupon', 'product', 'service' );
273
274
		foreach( $this->getContext()->getConfig()->get( $path, $default ) as $domain ) {
275
			$this->getObject()->getSubManager( $domain )->clear( $siteids );
276
		}
277
278
		return $this->clearBase( $siteids, 'mshop/order/manager/base/standard/delete' );
279
	}
280
281
282
	/**
283
	 * Creates a new empty item instance
284
	 *
285
	 * @param array $values Values the item should be initialized with
286
	 * @return \Aimeos\MShop\Order\Item\Base\Iface New order base item object
287
	 */
288
	public function createItem( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
289
	{
290
		$context = $this->getContext();
291
		$locale = $context->getLocale();
292
293
		$values['order.base.siteid'] = $locale->getSiteId();
294
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
295
296
		$base = $this->createItemBase( $priceManager->createItem(), clone $locale, $values );
297
298
		\Aimeos\MShop::create( $context, 'plugin' )->register( $base, 'order' );
299
300
		return $base;
301
	}
302
303
304
	/**
305
	 * Creates a search critera object
306
	 *
307
	 * @param bool $default Add default criteria (optional)
308
	 * @param bool $site TRUE to add site criteria to show orders with available products only
309
	 * @return \Aimeos\MW\Criteria\Iface New search criteria object
310
	 */
311
	public function createSearch( bool $default = false, bool $site = false ) : \Aimeos\MW\Criteria\Iface
312
	{
313
		$search = parent::createSearch( $default );
314
		$context = $this->getContext();
315
316
		if( $default === true )
317
		{
318
			$search->setConditions( $search->combine( '&&', [
319
				$search->compare( '==', 'order.base.customerid', $context->getUserId() ),
320
				$search->getConditions(),
321
			] ) );
322
		}
323
324
		if( $site === true )
325
		{
326
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
327
			$search->setConditions( $search->combine( '&&', [
328
				$this->getSiteCondition( $search, 'order.base.product.siteid', $level ),
329
				$search->getConditions()
330
			] ) );
331
		}
332
333
		return $search;
334
	}
335
336
337
	/**
338
	 * Removes multiple items.
339
	 *
340
	 * @param \Aimeos\MShop\Common\Item\Iface[]|string[] $itemIds List of item objects or IDs of the items
341
	 * @return \Aimeos\MShop\Order\Manager\Base\Iface Manager object for chaining method calls
342
	 */
343
	public function deleteItems( array $itemIds ) : \Aimeos\MShop\Common\Manager\Iface
344
	{
345
		/** mshop/order/manager/base/standard/delete/mysql
346
		 * Deletes the items matched by the given IDs from the database
347
		 *
348
		 * @see mshop/order/manager/base/standard/delete/ansi
349
		 */
350
351
		/** mshop/order/manager/base/standard/delete/ansi
352
		 * Deletes the items matched by the given IDs from the database
353
		 *
354
		 * Removes the records specified by the given IDs from the order database.
355
		 * The records must be from the site that is configured via the
356
		 * context item.
357
		 *
358
		 * The ":cond" placeholder is replaced by the name of the ID column and
359
		 * the given ID or list of IDs while the site ID is bound to the question
360
		 * mark.
361
		 *
362
		 * The SQL statement should conform to the ANSI standard to be
363
		 * compatible with most relational database systems. This also
364
		 * includes using double quotes for table and column names.
365
		 *
366
		 * @param string SQL statement for deleting items
367
		 * @since 2014.03
368
		 * @category Developer
369
		 * @see mshop/order/manager/base/standard/insert/ansi
370
		 * @see mshop/order/manager/base/standard/update/ansi
371
		 * @see mshop/order/manager/base/standard/newid/ansi
372
		 * @see mshop/order/manager/base/standard/search/ansi
373
		 * @see mshop/order/manager/base/standard/count/ansi
374
		 */
375
		$path = 'mshop/order/manager/base/standard/delete';
376
377
		return $this->deleteItemsBase( $itemIds, $path );
378
	}
379
380
381
	/**
382
	 * Returns the order base item specified by the given ID.
383
	 *
384
	 * @param string $id Unique id of the order base
385
	 * @param string[] $ref List of domains to fetch list items and referenced items for
386
	 * @param bool $default Add default criteria
387
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Returns Order base item of the given id
388
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
389
	 */
390
	public function getItem( string $id, array $ref = [], bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
391
	{
392
		return $this->getItemBase( 'order.base.id', $id, $ref, $default );
393
	}
394
395
396
	/**
397
	 * Returns the available manager types
398
	 *
399
	 * @param bool $withsub Return also the resource type of sub-managers if true
400
	 * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
401
	 */
402
	public function getResourceType( bool $withsub = true ) : array
403
	{
404
		$path = 'mshop/order/manager/base/submanagers';
405
		return $this->getResourceTypeBase( 'order/base', $path, ['address', 'coupon', 'product', 'service'], $withsub );
406
	}
407
408
409
	/**
410
	 * Returns the attributes that can be used for searching.
411
	 *
412
	 * @param bool $withsub Return also attributes of sub-managers if true
413
	 * @return \Aimeos\MW\Criteria\Attribute\Iface[] List of search attribute items
414
	 */
415
	public function getSearchAttributes( bool $withsub = true ) : array
416
	{
417
		/** mshop/order/manager/base/submanagers
418
		 * List of manager names that can be instantiated by the order base manager
419
		 *
420
		 * Managers provide a generic interface to the underlying storage.
421
		 * Each manager has or can have sub-managers caring about particular
422
		 * aspects. Each of these sub-managers can be instantiated by its
423
		 * parent manager using the getSubManager() method.
424
		 *
425
		 * The search keys from sub-managers can be normally used in the
426
		 * manager as well. It allows you to search for items of the manager
427
		 * using the search keys of the sub-managers to further limit the
428
		 * retrieved list of items.
429
		 *
430
		 * @param array List of sub-manager names
431
		 * @since 2014.03
432
		 * @category Developer
433
		 */
434
		$path = 'mshop/order/manager/base/submanagers';
435
		$default = array( 'address', 'coupon', 'product', 'service' );
436
437
		return $this->getSearchAttributesBase( $this->searchConfig, $path, $default, $withsub );
438
	}
439
440
441
	/**
442
	 * Returns a new manager for order base extensions.
443
	 *
444
	 * @param string $manager Name of the sub manager type in lower case
445
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
446
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g address, coupon, product, service, etc.
447
	 */
448
	public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
449
	{
450
		/** mshop/order/manager/base/name
451
		 * Class name of the used order base manager implementation
452
		 *
453
		 * Each default order base manager can be replaced by an alternative imlementation.
454
		 * To use this implementation, you have to set the last part of the class
455
		 * name as configuration value so the manager factory knows which class it
456
		 * has to instantiate.
457
		 *
458
		 * For example, if the name of the default class is
459
		 *
460
		 *  \Aimeos\MShop\Order\Manager\Base\Standard
461
		 *
462
		 * and you want to replace it with your own version named
463
		 *
464
		 *  \Aimeos\MShop\Order\Manager\Base\Mybase
465
		 *
466
		 * then you have to set the this configuration option:
467
		 *
468
		 *  mshop/order/manager/base/name = Mybase
469
		 *
470
		 * The value is the last part of your own class name and it's case sensitive,
471
		 * so take care that the configuration value is exactly named like the last
472
		 * part of the class name.
473
		 *
474
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
475
		 * characters are possible! You should always start the last part of the class
476
		 * name with an upper case character and continue only with lower case characters
477
		 * or numbers. Avoid chamel case names like "MyBase"!
478
		 *
479
		 * @param string Last part of the class name
480
		 * @since 2014.03
481
		 * @category Developer
482
		 */
483
484
		/** mshop/order/manager/base/decorators/excludes
485
		 * Excludes decorators added by the "common" option from the order base manager
486
		 *
487
		 * Decorators extend the functionality of a class by adding new aspects
488
		 * (e.g. log what is currently done), executing the methods of the underlying
489
		 * class only in certain conditions (e.g. only for logged in users) or
490
		 * modify what is returned to the caller.
491
		 *
492
		 * This option allows you to remove a decorator added via
493
		 * "mshop/common/manager/decorators/default" before they are wrapped
494
		 * around the order base manager.
495
		 *
496
		 *  mshop/order/manager/base/decorators/excludes = array( 'decorator1' )
497
		 *
498
		 * This would remove the decorator named "decorator1" from the list of
499
		 * common decorators ("\Aimeos\MShop\Common\Manager\Decorator\*") added via
500
		 * "mshop/common/manager/decorators/default" for the order base manager.
501
		 *
502
		 * @param array List of decorator names
503
		 * @since 2014.03
504
		 * @category Developer
505
		 * @see mshop/common/manager/decorators/default
506
		 * @see mshop/order/manager/base/decorators/global
507
		 * @see mshop/order/manager/base/decorators/local
508
		 */
509
510
		/** mshop/order/manager/base/decorators/global
511
		 * Adds a list of globally available decorators only to the order base manager
512
		 *
513
		 * Decorators extend the functionality of a class by adding new aspects
514
		 * (e.g. log what is currently done), executing the methods of the underlying
515
		 * class only in certain conditions (e.g. only for logged in users) or
516
		 * modify what is returned to the caller.
517
		 *
518
		 * This option allows you to wrap global decorators
519
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the order base
520
		 * manager.
521
		 *
522
		 *  mshop/order/manager/base/decorators/global = array( 'decorator1' )
523
		 *
524
		 * This would add the decorator named "decorator1" defined by
525
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator1" only to the order
526
		 * base manager.
527
		 *
528
		 * @param array List of decorator names
529
		 * @since 2014.03
530
		 * @category Developer
531
		 * @see mshop/common/manager/decorators/default
532
		 * @see mshop/order/manager/base/decorators/excludes
533
		 * @see mshop/order/manager/base/decorators/local
534
		 */
535
536
		/** mshop/order/manager/base/decorators/local
537
		 * Adds a list of local decorators only to the order base manager
538
		 *
539
		 * Decorators extend the functionality of a class by adding new aspects
540
		 * (e.g. log what is currently done), executing the methods of the underlying
541
		 * class only in certain conditions (e.g. only for logged in users) or
542
		 * modify what is returned to the caller.
543
		 *
544
		 * This option allows you to wrap local decorators
545
		 * ("\Aimeos\MShop\Order\Manager\Base\Decorator\*") around the order base
546
		 * manager.
547
		 *
548
		 *  mshop/order/manager/base/decorators/local = array( 'decorator2' )
549
		 *
550
		 * This would add the decorator named "decorator2" defined by
551
		 * "\Aimeos\MShop\Order\Manager\Base\Decorator\Decorator2" only to the
552
		 * order base manager.
553
		 *
554
		 * @param array List of decorator names
555
		 * @since 2014.03
556
		 * @category Developer
557
		 * @see mshop/common/manager/decorators/default
558
		 * @see mshop/order/manager/base/decorators/excludes
559
		 * @see mshop/order/manager/base/decorators/global
560
		 */
561
562
		return $this->getSubManagerBase( 'order', 'base/' . $manager, $name );
563
	}
564
565
566
	/**
567
	 * Adds or updates an order base item in the storage.
568
	 *
569
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $item Order base object (sub-items are not saved)
570
	 * @param bool $fetch True if the new ID should be returned in the item
571
	 * @return \Aimeos\MShop\Order\Item\Base\Iface $item Updated item including the generated ID
572
	 */
573
	public function saveItem( \Aimeos\MShop\Order\Item\Base\Iface $item, bool $fetch = true ) : \Aimeos\MShop\Order\Item\Base\Iface
574
	{
575
		if( !$item->isModified() && !$item->getLocale()->isModified() ) {
576
			return $item;
577
		}
578
579
		$context = $this->getContext();
580
581
		$dbm = $context->getDatabaseManager();
582
		$dbname = $this->getResourceName();
583
		$conn = $dbm->acquire( $dbname );
584
585
		try
586
		{
587
			$id = $item->getId();
588
			$date = date( 'Y-m-d H:i:s' );
589
			$columns = $this->getObject()->getSaveAttributes();
590
591
			if( $id === null )
592
			{
593
				/** mshop/order/manager/base/standard/insert/mysql
594
				 * Inserts a new order record into the database table
595
				 *
596
				 * @see mshop/order/manager/base/standard/insert/ansi
597
				 */
598
599
				/** mshop/order/manager/base/standard/insert/ansi
600
				 * Inserts a new order record into the database table
601
				 *
602
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
603
				 * the database and the newly created ID retrieved afterwards
604
				 * using the "newid" SQL statement.
605
				 *
606
				 * The SQL statement must be a string suitable for being used as
607
				 * prepared statement. It must include question marks for binding
608
				 * the values from the order item to the statement before they are
609
				 * sent to the database server. The number of question marks must
610
				 * be the same as the number of columns listed in the INSERT
611
				 * statement. The order of the columns must correspond to the
612
				 * order in the saveItems() method, so the correct values are
613
				 * bound to the columns.
614
				 *
615
				 * The SQL statement should conform to the ANSI standard to be
616
				 * compatible with most relational database systems. This also
617
				 * includes using double quotes for table and column names.
618
				 *
619
				 * @param string SQL statement for inserting records
620
				 * @since 2014.03
621
				 * @category Developer
622
				 * @see mshop/order/manager/base/standard/update/ansi
623
				 * @see mshop/order/manager/base/standard/newid/ansi
624
				 * @see mshop/order/manager/base/standard/delete/ansi
625
				 * @see mshop/order/manager/base/standard/search/ansi
626
				 * @see mshop/order/manager/base/standard/count/ansi
627
				 */
628
				$path = 'mshop/order/manager/base/standard/insert';
629
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ) );
0 ignored issues
show
Bug introduced by
It seems like $this->getSqlConfig($path) can also be of type array; however, parameter $sql of Aimeos\MShop\Common\Manager\Base::addSqlColumns() does only seem to accept string, 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

629
				$sql = $this->addSqlColumns( array_keys( $columns ), /** @scrutinizer ignore-type */ $this->getSqlConfig( $path ) );
Loading history...
630
			}
631
			else
632
			{
633
				/** mshop/order/manager/base/standard/update/mysql
634
				 * Updates an existing order record in the database
635
				 *
636
				 * @see mshop/order/manager/base/standard/update/ansi
637
				 */
638
639
				/** mshop/order/manager/base/standard/update/ansi
640
				 * Updates an existing order record in the database
641
				 *
642
				 * Items which already have an ID (i.e. the ID is not NULL) will
643
				 * be updated in the database.
644
				 *
645
				 * The SQL statement must be a string suitable for being used as
646
				 * prepared statement. It must include question marks for binding
647
				 * the values from the order item to the statement before they are
648
				 * sent to the database server. The order of the columns must
649
				 * correspond to the order in the saveItems() method, so the
650
				 * correct values are bound to the columns.
651
				 *
652
				 * The SQL statement should conform to the ANSI standard to be
653
				 * compatible with most relational database systems. This also
654
				 * includes using double quotes for table and column names.
655
				 *
656
				 * @param string SQL statement for updating records
657
				 * @since 2014.03
658
				 * @category Developer
659
				 * @see mshop/order/manager/base/standard/insert/ansi
660
				 * @see mshop/order/manager/base/standard/newid/ansi
661
				 * @see mshop/order/manager/base/standard/delete/ansi
662
				 * @see mshop/order/manager/base/standard/search/ansi
663
				 * @see mshop/order/manager/base/standard/count/ansi
664
				 */
665
				$path = 'mshop/order/manager/base/standard/update';
666
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ), false );
667
			}
668
669
			$priceItem = $item->getPrice();
670
			$localeItem = $context->getLocale();
671
672
			$idx = 1;
673
			$stmt = $this->getCachedStatement( $conn, $path, $sql );
674
675
			foreach( $columns as $name => $entry ) {
676
				$stmt->bind( $idx++, $item->get( $name ), $entry->getInternalType() );
677
			}
678
679
			$stmt->bind( $idx++, $item->getCustomerId() );
680
			$stmt->bind( $idx++, $localeItem->getSiteItem()->getCode() );
681
			$stmt->bind( $idx++, $item->getLocale()->getLanguageId() );
682
			$stmt->bind( $idx++, $priceItem->getCurrencyId() );
683
			$stmt->bind( $idx++, $priceItem->getValue() );
684
			$stmt->bind( $idx++, $priceItem->getCosts() );
685
			$stmt->bind( $idx++, $priceItem->getRebate() );
686
			$stmt->bind( $idx++, $priceItem->getTaxValue() );
687
			$stmt->bind( $idx++, $priceItem->getTaxFlag(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
688
			$stmt->bind( $idx++, $item->getCustomerReference() );
689
			$stmt->bind( $idx++, $item->getComment() );
690
			$stmt->bind( $idx++, $date ); // mtime
691
			$stmt->bind( $idx++, $context->getEditor() );
692
			$stmt->bind( $idx++, $localeItem->getSiteId() );
693
694
			if( $id !== null ) {
695
				$stmt->bind( $idx++, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
696
			} else {
697
				$stmt->bind( $idx++, $date ); // ctime
698
			}
699
700
			$stmt->execute()->finish();
701
702
			if( $id === null && $fetch === true )
703
			{
704
				/** mshop/order/manager/base/standard/newid/mysql
705
				 * Retrieves the ID generated by the database when inserting a new record
706
				 *
707
				 * @see mshop/order/manager/base/standard/newid/ansi
708
				 */
709
710
				/** mshop/order/manager/base/standard/newid/ansi
711
				 * Retrieves the ID generated by the database when inserting a new record
712
				 *
713
				 * As soon as a new record is inserted into the database table,
714
				 * the database server generates a new and unique identifier for
715
				 * that record. This ID can be used for retrieving, updating and
716
				 * deleting that specific record from the table again.
717
				 *
718
				 * For MySQL:
719
				 *  SELECT LAST_INSERT_ID()
720
				 * For PostgreSQL:
721
				 *  SELECT currval('seq_mord_id')
722
				 * For SQL Server:
723
				 *  SELECT SCOPE_IDENTITY()
724
				 * For Oracle:
725
				 *  SELECT "seq_mord_id".CURRVAL FROM DUAL
726
				 *
727
				 * There's no way to retrive the new ID by a SQL statements that
728
				 * fits for most database servers as they implement their own
729
				 * specific way.
730
				 *
731
				 * @param string SQL statement for retrieving the last inserted record ID
732
				 * @since 2014.03
733
				 * @category Developer
734
				 * @see mshop/order/manager/base/standard/insert/ansi
735
				 * @see mshop/order/manager/base/standard/update/ansi
736
				 * @see mshop/order/manager/base/standard/delete/ansi
737
				 * @see mshop/order/manager/base/standard/search/ansi
738
				 * @see mshop/order/manager/base/standard/count/ansi
739
				 */
740
				$path = 'mshop/order/manager/base/standard/newid';
741
				$id = $this->newId( $conn, $path );
742
			}
743
744
			$item->setId( $id );
745
746
			$dbm->release( $conn, $dbname );
747
		}
748
		catch( \Exception $e )
749
		{
750
			$dbm->release( $conn, $dbname );
751
			throw $e;
752
		}
753
754
		return $item;
755
	}
756
757
758
	/**
759
	 * Search for orders based on the given criteria.
760
	 *
761
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
762
	 * @param string[] $ref List of domains to fetch list items and referenced items for, e.g.
763
	 *	"order/base/address", "order/base/coupon", "order/base/product", "order/base/service"
764
	 * @param int|null &$total Number of items that are available in total
765
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Order\Item\Base\Iface with ids as keys
766
	 */
767
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], int &$total = null ) : \Aimeos\Map
768
	{
769
		$context = $this->getContext();
770
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
771
		$localeManager = \Aimeos\MShop::create( $context, 'locale' );
772
773
		$dbm = $context->getDatabaseManager();
774
		$dbname = $this->getResourceName();
775
		$conn = $dbm->acquire( $dbname );
776
777
		$map = $items = $custItems = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $items is dead and can be removed.
Loading history...
778
779
		try
780
		{
781
			$required = array( 'order.base' );
782
783
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
784
			$level = $context->getConfig()->get( 'mshop/order/manager/sitemode', $level );
785
786
			/** mshop/order/manager/base/standard/search/mysql
787
			 * Retrieves the records matched by the given criteria in the database
788
			 *
789
			 * @see mshop/order/manager/base/standard/search/ansi
790
			 */
791
792
			/** mshop/order/manager/base/standard/search/ansi
793
			 * Retrieves the records matched by the given criteria in the database
794
			 *
795
			 * Fetches the records matched by the given criteria from the order
796
			 * database. The records must be from one of the sites that are
797
			 * configured via the context item. If the current site is part of
798
			 * a tree of sites, the SELECT statement can retrieve all records
799
			 * from the current site and the complete sub-tree of sites.
800
			 *
801
			 * As the records can normally be limited by criteria from sub-managers,
802
			 * their tables must be joined in the SQL context. This is done by
803
			 * using the "internaldeps" property from the definition of the ID
804
			 * column of the sub-managers. These internal dependencies specify
805
			 * the JOIN between the tables and the used columns for joining. The
806
			 * ":joins" placeholder is then replaced by the JOIN strings from
807
			 * the sub-managers.
808
			 *
809
			 * To limit the records matched, conditions can be added to the given
810
			 * criteria object. It can contain comparisons like column names that
811
			 * must match specific values which can be combined by AND, OR or NOT
812
			 * operators. The resulting string of SQL conditions replaces the
813
			 * ":cond" placeholder before the statement is sent to the database
814
			 * server.
815
			 *
816
			 * If the records that are retrieved should be ordered by one or more
817
			 * columns, the generated string of column / sort direction pairs
818
			 * replaces the ":order" placeholder. In case no ordering is required,
819
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
820
			 * markers is removed to speed up retrieving the records. Columns of
821
			 * sub-managers can also be used for ordering the result set but then
822
			 * no index can be used.
823
			 *
824
			 * The number of returned records can be limited and can start at any
825
			 * number between the begining and the end of the result set. For that
826
			 * the ":size" and ":start" placeholders are replaced by the
827
			 * corresponding values from the criteria object. The default values
828
			 * are 0 for the start and 100 for the size value.
829
			 *
830
			 * The SQL statement should conform to the ANSI standard to be
831
			 * compatible with most relational database systems. This also
832
			 * includes using double quotes for table and column names.
833
			 *
834
			 * @param string SQL statement for searching items
835
			 * @since 2014.03
836
			 * @category Developer
837
			 * @see mshop/order/manager/base/standard/insert/ansi
838
			 * @see mshop/order/manager/base/standard/update/ansi
839
			 * @see mshop/order/manager/base/standard/newid/ansi
840
			 * @see mshop/order/manager/base/standard/delete/ansi
841
			 * @see mshop/order/manager/base/standard/count/ansi
842
			 */
843
			$cfgPathSearch = 'mshop/order/manager/base/standard/search';
844
845
			/** mshop/order/manager/base/standard/count/mysql
846
			 * Counts the number of records matched by the given criteria in the database
847
			 *
848
			 * @see mshop/order/manager/base/standard/count/ansi
849
			 */
850
851
			/** mshop/order/manager/base/standard/count/ansi
852
			 * Counts the number of records matched by the given criteria in the database
853
			 *
854
			 * Counts all records matched by the given criteria from the order
855
			 * database. The records must be from one of the sites that are
856
			 * configured via the context item. If the current site is part of
857
			 * a tree of sites, the statement can count all records from the
858
			 * current site and the complete sub-tree of sites.
859
			 *
860
			 * As the records can normally be limited by criteria from sub-managers,
861
			 * their tables must be joined in the SQL context. This is done by
862
			 * using the "internaldeps" property from the definition of the ID
863
			 * column of the sub-managers. These internal dependencies specify
864
			 * the JOIN between the tables and the used columns for joining. The
865
			 * ":joins" placeholder is then replaced by the JOIN strings from
866
			 * the sub-managers.
867
			 *
868
			 * To limit the records matched, conditions can be added to the given
869
			 * criteria object. It can contain comparisons like column names that
870
			 * must match specific values which can be combined by AND, OR or NOT
871
			 * operators. The resulting string of SQL conditions replaces the
872
			 * ":cond" placeholder before the statement is sent to the database
873
			 * server.
874
			 *
875
			 * Both, the strings for ":joins" and for ":cond" are the same as for
876
			 * the "search" SQL statement.
877
			 *
878
			 * Contrary to the "search" statement, it doesn't return any records
879
			 * but instead the number of records that have been found. As counting
880
			 * thousands of records can be a long running task, the maximum number
881
			 * of counted records is limited for performance reasons.
882
			 *
883
			 * The SQL statement should conform to the ANSI standard to be
884
			 * compatible with most relational database systems. This also
885
			 * includes using double quotes for table and column names.
886
			 *
887
			 * @param string SQL statement for counting items
888
			 * @since 2014.03
889
			 * @category Developer
890
			 * @see mshop/order/manager/base/standard/insert/ansi
891
			 * @see mshop/order/manager/base/standard/update/ansi
892
			 * @see mshop/order/manager/base/standard/newid/ansi
893
			 * @see mshop/order/manager/base/standard/delete/ansi
894
			 * @see mshop/order/manager/base/standard/search/ansi
895
			 */
896
			$cfgPathCount = 'mshop/order/manager/base/standard/count';
897
898
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount,
899
				$required, $total, $level );
900
901
			while( ( $row = $results->fetch() ) !== null ) {
902
				$map[$row['order.base.id']] = $row;
903
			}
904
905
			$dbm->release( $conn, $dbname );
906
		}
907
		catch( \Exception $e )
908
		{
909
			$dbm->release( $conn, $dbname );
910
			throw $e;
911
		}
912
913
		if( ( isset( $ref['customer'] ) || in_array( 'customer', $ref ) )
914
			&& !( $ids = map( $map )->col( 'order.base.customerid' )->filter() )->empty()
915
		) {
916
			$manager = \Aimeos\MShop::create( $context, 'customer' );
917
			$search = $manager->createSearch()->setSlice( 0, count( $ids ) );
918
			$search->setConditions( $search->compare( '==', 'customer.id', $ids ) );
919
			$custItems = $manager->searchItems( $search, $ref );
920
		}
921
922
		foreach( $map as $id => $row )
923
		{
924
			$price = $priceManager->createItem();
925
			$price->setCurrencyId( $row['order.base.currencyid'] );
926
			$price->setValue( $row['order.base.price'] );
927
			$price->setCosts( $row['order.base.costs'] );
928
			$price->setRebate( $row['order.base.rebate'] );
929
			$price->setTaxValue( $row['order.base.taxvalue'] );
930
			$price->setTaxFlag( $row['order.base.taxflag'] );
931
932
			// you may need the site object! take care!
933
			$localeItem = $localeManager->createItem();
934
			$localeItem->setLanguageId( $row['order.base.languageid'] );
935
			$localeItem->setCurrencyId( $row['order.base.currencyid'] );
936
			$localeItem->setSiteId( $row['order.base.siteid'] );
937
938
			$map[$id] = [$price, $localeItem, $row, $custItems[$row['order.base.customerid'] ?? null] ?? null];
939
		}
940
941
		return $this->buildItems( $map, $ref );
942
	}
943
944
945
	/**
946
	 * Creates a new basket containing the items from the order excluding the coupons.
947
	 * If the last parameter is ture, the items will be marked as new and
948
	 * modified so an additional order is stored when the basket is saved.
949
	 *
950
	 * @param string $id Base ID of the order to load
951
	 * @param int $parts Bitmap of the basket parts that should be loaded
952
	 * @param bool $fresh Create a new basket by copying the existing one and remove IDs
953
	 * @param bool $default True to use default criteria, false for no limitation
954
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Basket including all items
955
	 */
956
	public function load( string $id, int $parts = \Aimeos\MShop\Order\Item\Base\Base::PARTS_ALL, bool $fresh = false,
957
		bool $default = false ) : \Aimeos\MShop\Order\Item\Base\Iface
958
	{
959
		$search = $this->getObject()->createSearch( $default );
960
		$expr = [
961
			$search->compare( '==', 'order.base.id', $id ),
962
			$search->getConditions(),
963
		];
964
		$search->setConditions( $search->combine( '&&', $expr ) );
965
966
		$context = $this->getContext();
967
		$dbm = $context->getDatabaseManager();
968
		$dbname = $this->getResourceName();
969
		$conn = $dbm->acquire( $dbname );
970
971
		try
972
		{
973
			$sitelevel = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
974
			$sitelevel = $context->getConfig()->get( 'mshop/order/manager/sitemode', $sitelevel );
975
976
			$cfgPathSearch = 'mshop/order/manager/base/standard/search';
977
			$cfgPathCount = 'mshop/order/manager/base/standard/count';
978
			$required = array( 'order.base' );
979
			$total = null;
980
981
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $sitelevel );
982
983
			if( ( $row = $results->fetch() ) === null ) {
984
				throw new \Aimeos\MShop\Order\Exception( sprintf( 'Order base item with order ID "%1$s" not found', $id ) );
985
			}
986
			$results->finish();
987
988
			$dbm->release( $conn, $dbname );
989
		}
990
		catch( \Exception $e )
991
		{
992
			$dbm->release( $conn, $dbname );
993
			throw $e;
994
		}
995
996
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
997
		$localeManager = \Aimeos\MShop::create( $context, 'locale' );
998
999
		$price = $priceManager->createItem( [
1000
			'price.currencyid' => $row['order.base.currencyid'],
1001
			'price.value' => $row['order.base.price'],
1002
			'price.costs' => $row['order.base.costs'],
1003
			'price.rebate' => $row['order.base.rebate'],
1004
			'price.taxflag' => $row['order.base.taxflag'],
1005
			'price.taxvalue' => $row['order.base.taxvalue'],
1006
		] );
1007
1008
		// you may need the site object! take care!
1009
		$localeItem = $localeManager->createItem( [
1010
			'locale.languageid' => $row['order.base.languageid'],
1011
			'locale.currencyid' => $row['order.base.currencyid'],
1012
			'locale.siteid' => $row['order.base.siteid'],
1013
		] );
1014
1015
		if( $fresh === false ) {
1016
			$basket = $this->loadItems( $id, $price, $localeItem, $row, $parts );
1017
		} else {
1018
			$basket = $this->loadFresh( $id, $price, $localeItem, $row, $parts );
1019
		}
1020
1021
		$pluginManager = \Aimeos\MShop::create( $this->getContext(), 'plugin' );
1022
		$pluginManager->register( $basket, 'order' );
1023
1024
		return $basket;
1025
	}
1026
1027
1028
	/**
1029
	 * Saves the complete basket to the storage including the items attached.
1030
	 *
1031
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket object containing all information
1032
	 * @param int $parts Bitmap of the basket parts that should be stored
1033
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Stored order basket
1034
	 */
1035
	public function store( \Aimeos\MShop\Order\Item\Base\Iface $basket,
1036
		int $parts = \Aimeos\MShop\Order\Item\Base\Base::PARTS_ALL ) : \Aimeos\MShop\Order\Item\Base\Iface
1037
	{
1038
		$basket = $this->getObject()->saveItem( $basket );
1039
1040
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT
1041
			|| $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_COUPON
1042
		) {
1043
			$this->storeProducts( $basket );
1044
		}
1045
1046
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_COUPON ) {
1047
			$this->storeCoupons( $basket );
1048
		}
1049
1050
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_ADDRESS ) {
1051
			$this->storeAddresses( $basket );
1052
		}
1053
1054
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_SERVICE ) {
1055
			$this->storeServices( $basket );
1056
		}
1057
1058
		return $basket;
1059
	}
1060
1061
1062
	/**
1063
	 * Creates the order base item objects from the map and adds the referenced items
1064
	 *
1065
	 * @param array $map Associative list of order base IDs as keys and list of price/locale/row as values
1066
	 * @param string[] $ref Domain items that should be added as well, e.g.
1067
	 *	"order/base/address", "order/base/coupon", "order/base/product", "order/base/service"
1068
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Order\Item\Base\Iface with IDs as keys
1069
	 */
1070
	protected function buildItems( array $map, array $ref ) : \Aimeos\Map
1071
	{
1072
		$items = [];
1073
		$baseIds = array_keys( $map );
1074
		$addressMap = $couponMap = $productMap = $serviceMap = [];
1075
1076
		if( in_array( 'order/base/address', $ref ) ) {
1077
			$addressMap = $this->getAddresses( $baseIds );
1078
		}
1079
1080
		if( in_array( 'order/base/product', $ref ) ) {
1081
			$productMap = $this->getProducts( $baseIds );
1082
		}
1083
1084
		if( in_array( 'order/base/coupon', $ref ) ) {
1085
			$couponMap = $this->getCoupons( $baseIds, false, $productMap );
1086
		}
1087
1088
		if( in_array( 'order/base/service', $ref ) ) {
1089
			$serviceMap = $this->getServices( $baseIds );
1090
		}
1091
1092
		foreach( $map as $id => $list )
1093
		{
1094
			list( $price, $locale, $row, $custItem ) = $list;
1095
1096
			$addresses = $addressMap[$id] ?? [];
1097
			$coupons = $couponMap[$id] ?? [];
1098
			$products = $productMap[$id] ?? [];
1099
			$services = $serviceMap[$id] ?? [];
1100
1101
			$item = $this->createItemBase( $price, $locale, $row, $products, $addresses, $services, $coupons, $custItem );
1102
1103
			if( $item = $this->applyFilter( $item ) ) {
1104
				$items[$id] = $item;
1105
			}
1106
		}
1107
1108
		return map( $items );
1109
	}
1110
1111
1112
	/**
1113
	 * Returns a new and empty order base item (shopping basket).
1114
	 *
1115
	 * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00)
1116
	 * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency
1117
	 * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID
1118
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $products List of ordered product items
1119
	 * @param \Aimeos\MShop\Order\Item\Base\Address\Iface[] $addresses List of order address items
1120
	 * @param \Aimeos\MShop\Order\Item\Base\Service\Iface[] $services List of order serviceitems
1121
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $coupons Associative list of coupon codes as keys and items as values
1122
	 * @param \Aimeos\MShop\Customer\Item\Iface|null $custItem Customer item object if requested
1123
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base object
1124
	 */
1125
	protected function createItemBase( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale,
1126
		array $values = [], array $products = [], array $addresses = [], array $services = [], array $coupons = [],
1127
		?\Aimeos\MShop\Customer\Item\Iface $custItem = null ) : \Aimeos\MShop\Order\Item\Base\Iface
1128
	{
1129
		return new \Aimeos\MShop\Order\Item\Base\Standard( $price, $locale,
1130
			$values, $products, $addresses, $services, $coupons, $custItem );
1131
	}
1132
}
1133