Passed
Push — master ( 8f16ed...3311dc )
by Aimeos
10:04
created

mshoplib/src/MShop/Order/Manager/Base/Standard.php (6 issues)

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-2018
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' => 'integer',
39
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
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.languageid' => array(
58
			'code' => 'order.base.languageid',
59
			'internalcode' => 'mordba."langid"',
60
			'label' => 'Order language code',
61
			'type' => 'string',
62
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
63
		),
64
		'order.base.currencyid' => array(
65
			'code' => 'order.base.currencyid',
66
			'internalcode' => 'mordba."currencyid"',
67
			'label' => 'Order currencyid code',
68
			'type' => 'string',
69
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
70
		),
71
		'order.base.price' => array(
72
			'code' => 'order.base.price',
73
			'internalcode' => 'mordba."price"',
74
			'label' => 'Order price amount',
75
			'type' => 'string',
76
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
77
		),
78
		'order.base.costs' => array(
79
			'code' => 'order.base.costs',
80
			'internalcode' => 'mordba."costs"',
81
			'label' => 'Order shipping amount',
82
			'type' => 'string',
83
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
84
		),
85
		'order.base.rebate' => array(
86
			'code' => 'order.base.rebate',
87
			'internalcode' => 'mordba."rebate"',
88
			'label' => 'Order rebate amount',
89
			'type' => 'string',
90
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
91
		),
92
		'order.base.taxvalue' => array(
93
			'code' => 'order.base.taxvalue',
94
			'internalcode' => 'mordba."tax"',
95
			'label' => 'Order tax amount',
96
			'type' => 'string',
97
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
98
		),
99
		'order.base.taxflag' => array(
100
			'code' => 'order.base.taxflag',
101
			'internalcode' => 'mordba."taxflag"',
102
			'label' => 'Order tax flag (0=net, 1=gross)',
103
			'type' => 'string',
104
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
105
		),
106
		'order.base.comment' => array(
107
			'code' => 'order.base.comment',
108
			'internalcode' => 'mordba."comment"',
109
			'label' => 'Order comment',
110
			'type' => 'string',
111
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
112
		),
113
		'order.base.status' => array(
114
			'code' => 'order.base.status',
115
			'internalcode' => 'mordba."status"',
116
			'label' => 'Order subscription status',
117
			'type' => 'integer',
118
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
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
	 * @return integer[] List of the search keys as key and the number of counted items as value
165
	 * @todo 2018.01 Add optional parameters to interface
166
	 */
167
	public function aggregate( \Aimeos\MW\Criteria\Iface $search, $key, $value = null, $type = null )
168
	{
169
		/** mshop/order/manager/base/standard/aggregate/mysql
170
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
171
		 *
172
		 * @see mshop/order/manager/base/standard/aggregate/ansi
173
		 */
174
175
		/** mshop/order/manager/base/standard/aggregate/ansi
176
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
177
		 *
178
		 * Groups all records by the values in the key column and counts their
179
		 * occurence. The matched records can be limited by the given criteria
180
		 * from the order database. The records must be from one of the sites
181
		 * that are configured via the context item. If the current site is part
182
		 * of a tree of sites, the statement can count all records from the
183
		 * current site and the complete sub-tree of sites.
184
		 *
185
		 * As the records can normally be limited by criteria from sub-managers,
186
		 * their tables must be joined in the SQL context. This is done by
187
		 * using the "internaldeps" property from the definition of the ID
188
		 * column of the sub-managers. These internal dependencies specify
189
		 * the JOIN between the tables and the used columns for joining. The
190
		 * ":joins" placeholder is then replaced by the JOIN strings from
191
		 * the sub-managers.
192
		 *
193
		 * To limit the records matched, conditions can be added to the given
194
		 * criteria object. It can contain comparisons like column names that
195
		 * must match specific values which can be combined by AND, OR or NOT
196
		 * operators. The resulting string of SQL conditions replaces the
197
		 * ":cond" placeholder before the statement is sent to the database
198
		 * server.
199
		 *
200
		 * This statement doesn't return any records. Instead, it returns pairs
201
		 * of the different values found in the key column together with the
202
		 * number of records that have been found for that key values.
203
		 *
204
		 * The SQL statement should conform to the ANSI standard to be
205
		 * compatible with most relational database systems. This also
206
		 * includes using double quotes for table and column names.
207
		 *
208
		 * @param string SQL statement for aggregating order items
209
		 * @since 2014.09
210
		 * @category Developer
211
		 * @see mshop/order/manager/base/standard/insert/ansi
212
		 * @see mshop/order/manager/base/standard/update/ansi
213
		 * @see mshop/order/manager/base/standard/newid/ansi
214
		 * @see mshop/order/manager/base/standard/delete/ansi
215
		 * @see mshop/order/manager/base/standard/search/ansi
216
		 * @see mshop/order/manager/base/standard/count/ansi
217
		 */
218
219
		/** mshop/order/manager/base/standard/aggregateavg/mysql
220
		 * Computes the average of all values grouped by the key column and matched by the given criteria
221
		 *
222
		 * @param string SQL statement for aggregating the order base items and computing the average value
223
		 * @since 2017.10
224
		 * @category Developer
225
		 * @see mshop/order/manager/base/standard/aggregateavg/ansi
226
		 * @see mshop/order/manager/base/standard/aggregate/mysql
227
		 */
228
229
		/** mshop/order/manager/base/standard/aggregateavg/ansi
230
		 * Computes the average of all values grouped by the key column and matched by the given criteria
231
		 *
232
		 * @param string SQL statement for aggregating the order base items and computing the average value
233
		 * @since 2017.10
234
		 * @category Developer
235
		 * @see mshop/order/manager/base/standard/aggregate/ansi
236
		 */
237
238
		/** mshop/order/manager/base/standard/aggregatesum/mysql
239
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
240
		 *
241
		 * @param string SQL statement for aggregating the order base items and computing the sum
242
		 * @since 2017.10
243
		 * @category Developer
244
		 * @see mshop/order/manager/base/standard/aggregatesum/ansi
245
		 * @see mshop/order/manager/base/standard/aggregate/mysql
246
		 */
247
248
		/** mshop/order/manager/base/standard/aggregatesum/ansi
249
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
250
		 *
251
		 * @param string SQL statement for aggregating the order base items and computing the sum
252
		 * @since 2017.10
253
		 * @category Developer
254
		 * @see mshop/order/manager/base/standard/aggregate/ansi
255
		 */
256
257
		$cfgkey = 'mshop/order/manager/base/standard/aggregate' . $type;
258
		return $this->aggregateBase( $search, $key, $cfgkey, array( 'order.base' ), $value );
259
	}
260
261
262
	/**
263
	 * Removes old entries from the storage.
264
	 *
265
	 * @param string[] $siteids List of IDs for sites whose entries should be deleted
266
	 * @return \Aimeos\MShop\Order\Manager\Base\Iface Manager object for chaining method calls
267
	 */
268
	public function cleanup( array $siteids )
269
	{
270
		$path = 'mshop/order/manager/base/submanagers';
271
		$default = array( 'address', 'coupon', 'product', 'service' );
272
273
		foreach( $this->getContext()->getConfig()->get( $path, $default ) as $domain ) {
274
			$this->getObject()->getSubManager( $domain )->cleanup( $siteids );
275
		}
276
277
		return $this->cleanupBase( $siteids, 'mshop/order/manager/base/standard/delete' );
278
	}
279
280
281
	/**
282
	 * Creates a new empty item instance
283
	 *
284
	 * @param array $values Values the item should be initialized with
285
	 * @return \Aimeos\MShop\Order\Item\Base\Iface New order base item object
286
	 */
287
	public function createItem( array $values = [] )
288
	{
289
		$context = $this->getContext();
290
		$locale = $context->getLocale();
291
292
		$values['order.base.siteid'] = $locale->getSiteId();
293
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
294
295
		$base = $this->createItemBase( $priceManager->createItem(), clone $locale, $values );
296
297
		\Aimeos\MShop::create( $context, 'plugin' )->register( $base, 'order' );
298
299
		return $base;
300
	}
301
302
303
	/**
304
	 * Creates a search critera object
305
	 *
306
	 * @param boolean $default Add default criteria (optional)
307
	 * @return \Aimeos\MW\Criteria\Iface New search criteria object
308
	 */
309
	public function createSearch( $default = false )
310
	{
311
		$search = parent::createSearch( $default );
312
313
		if( $default !== false )
314
		{
315
			$userId = $this->getContext()->getUserId();
316
			$expr = [
317
				$search->compare( '==', 'order.base.customerid', $userId ),
318
				$search->getConditions(),
319
			];
320
			$search->setConditions( $search->combine( '&&', $expr ) );
321
		}
322
323
		return $search;
324
	}
325
326
327
	/**
328
	 * Removes multiple items specified by ids in the array.
329
	 *
330
	 * @param string[] $ids List of IDs
331
	 * @return \Aimeos\MShop\Order\Manager\Base\Iface Manager object for chaining method calls
332
	 */
333
	public function deleteItems( array $ids )
334
	{
335
		/** mshop/order/manager/base/standard/delete/mysql
336
		 * Deletes the items matched by the given IDs from the database
337
		 *
338
		 * @see mshop/order/manager/base/standard/delete/ansi
339
		 */
340
341
		/** mshop/order/manager/base/standard/delete/ansi
342
		 * Deletes the items matched by the given IDs from the database
343
		 *
344
		 * Removes the records specified by the given IDs from the order database.
345
		 * The records must be from the site that is configured via the
346
		 * context item.
347
		 *
348
		 * The ":cond" placeholder is replaced by the name of the ID column and
349
		 * the given ID or list of IDs while the site ID is bound to the question
350
		 * mark.
351
		 *
352
		 * The SQL statement should conform to the ANSI standard to be
353
		 * compatible with most relational database systems. This also
354
		 * includes using double quotes for table and column names.
355
		 *
356
		 * @param string SQL statement for deleting items
357
		 * @since 2014.03
358
		 * @category Developer
359
		 * @see mshop/order/manager/base/standard/insert/ansi
360
		 * @see mshop/order/manager/base/standard/update/ansi
361
		 * @see mshop/order/manager/base/standard/newid/ansi
362
		 * @see mshop/order/manager/base/standard/search/ansi
363
		 * @see mshop/order/manager/base/standard/count/ansi
364
		 */
365
		$path = 'mshop/order/manager/base/standard/delete';
366
367
		return $this->deleteItemsBase( $ids, $path );
368
	}
369
370
371
	/**
372
	 * Returns the order base item specified by the given ID.
373
	 *
374
	 * @param string $id Unique id of the order base
375
	 * @param string[] $ref List of domains to fetch list items and referenced items for
376
	 * @param boolean $default Add default criteria
377
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Returns Order base item of the given id
378
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
379
	 */
380
	public function getItem( $id, array $ref = [], $default = false )
381
	{
382
		return $this->getItemBase( 'order.base.id', $id, $ref, $default );
383
	}
384
385
386
	/**
387
	 * Returns the available manager types
388
	 *
389
	 * @param boolean $withsub Return also the resource type of sub-managers if true
390
	 * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
391
	 */
392
	public function getResourceType( $withsub = true )
393
	{
394
		$path = 'mshop/order/manager/base/submanagers';
395
		return $this->getResourceTypeBase( 'order/base', $path, ['address', 'coupon', 'product', 'service'], $withsub );
396
	}
397
398
399
	/**
400
	 * Returns the attributes that can be used for searching.
401
	 *
402
	 * @param boolean $withsub Return also attributes of sub-managers if true
403
	 * @return \Aimeos\MW\Criteria\Attribute\Iface[] List of search attribute items
404
	 */
405
	public function getSearchAttributes( $withsub = true )
406
	{
407
		/** mshop/order/manager/base/submanagers
408
		 * List of manager names that can be instantiated by the order base manager
409
		 *
410
		 * Managers provide a generic interface to the underlying storage.
411
		 * Each manager has or can have sub-managers caring about particular
412
		 * aspects. Each of these sub-managers can be instantiated by its
413
		 * parent manager using the getSubManager() method.
414
		 *
415
		 * The search keys from sub-managers can be normally used in the
416
		 * manager as well. It allows you to search for items of the manager
417
		 * using the search keys of the sub-managers to further limit the
418
		 * retrieved list of items.
419
		 *
420
		 * @param array List of sub-manager names
421
		 * @since 2014.03
422
		 * @category Developer
423
		 */
424
		$path = 'mshop/order/manager/base/submanagers';
425
		$default = array( 'address', 'coupon', 'product', 'service' );
426
427
		return $this->getSearchAttributesBase( $this->searchConfig, $path, $default, $withsub );
428
	}
429
430
431
	/**
432
	 * Returns a new manager for order base extensions.
433
	 *
434
	 * @param string $manager Name of the sub manager type in lower case
435
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
436
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g address, coupon, product, service, etc.
437
	 */
438
	public function getSubManager( $manager, $name = null )
439
	{
440
		/** mshop/order/manager/base/name
441
		 * Class name of the used order base manager implementation
442
		 *
443
		 * Each default order base manager can be replaced by an alternative imlementation.
444
		 * To use this implementation, you have to set the last part of the class
445
		 * name as configuration value so the manager factory knows which class it
446
		 * has to instantiate.
447
		 *
448
		 * For example, if the name of the default class is
449
		 *
450
		 *  \Aimeos\MShop\Order\Manager\Base\Standard
451
		 *
452
		 * and you want to replace it with your own version named
453
		 *
454
		 *  \Aimeos\MShop\Order\Manager\Base\Mybase
455
		 *
456
		 * then you have to set the this configuration option:
457
		 *
458
		 *  mshop/order/manager/base/name = Mybase
459
		 *
460
		 * The value is the last part of your own class name and it's case sensitive,
461
		 * so take care that the configuration value is exactly named like the last
462
		 * part of the class name.
463
		 *
464
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
465
		 * characters are possible! You should always start the last part of the class
466
		 * name with an upper case character and continue only with lower case characters
467
		 * or numbers. Avoid chamel case names like "MyBase"!
468
		 *
469
		 * @param string Last part of the class name
470
		 * @since 2014.03
471
		 * @category Developer
472
		 */
473
474
		/** mshop/order/manager/base/decorators/excludes
475
		 * Excludes decorators added by the "common" option from the order base manager
476
		 *
477
		 * Decorators extend the functionality of a class by adding new aspects
478
		 * (e.g. log what is currently done), executing the methods of the underlying
479
		 * class only in certain conditions (e.g. only for logged in users) or
480
		 * modify what is returned to the caller.
481
		 *
482
		 * This option allows you to remove a decorator added via
483
		 * "mshop/common/manager/decorators/default" before they are wrapped
484
		 * around the order base manager.
485
		 *
486
		 *  mshop/order/manager/base/decorators/excludes = array( 'decorator1' )
487
		 *
488
		 * This would remove the decorator named "decorator1" from the list of
489
		 * common decorators ("\Aimeos\MShop\Common\Manager\Decorator\*") added via
490
		 * "mshop/common/manager/decorators/default" for the order base manager.
491
		 *
492
		 * @param array List of decorator names
493
		 * @since 2014.03
494
		 * @category Developer
495
		 * @see mshop/common/manager/decorators/default
496
		 * @see mshop/order/manager/base/decorators/global
497
		 * @see mshop/order/manager/base/decorators/local
498
		 */
499
500
		/** mshop/order/manager/base/decorators/global
501
		 * Adds a list of globally available decorators only to the order base manager
502
		 *
503
		 * Decorators extend the functionality of a class by adding new aspects
504
		 * (e.g. log what is currently done), executing the methods of the underlying
505
		 * class only in certain conditions (e.g. only for logged in users) or
506
		 * modify what is returned to the caller.
507
		 *
508
		 * This option allows you to wrap global decorators
509
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the order base
510
		 * manager.
511
		 *
512
		 *  mshop/order/manager/base/decorators/global = array( 'decorator1' )
513
		 *
514
		 * This would add the decorator named "decorator1" defined by
515
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator1" only to the order
516
		 * base manager.
517
		 *
518
		 * @param array List of decorator names
519
		 * @since 2014.03
520
		 * @category Developer
521
		 * @see mshop/common/manager/decorators/default
522
		 * @see mshop/order/manager/base/decorators/excludes
523
		 * @see mshop/order/manager/base/decorators/local
524
		 */
525
526
		/** mshop/order/manager/base/decorators/local
527
		 * Adds a list of local decorators only to the order base manager
528
		 *
529
		 * Decorators extend the functionality of a class by adding new aspects
530
		 * (e.g. log what is currently done), executing the methods of the underlying
531
		 * class only in certain conditions (e.g. only for logged in users) or
532
		 * modify what is returned to the caller.
533
		 *
534
		 * This option allows you to wrap local decorators
535
		 * ("\Aimeos\MShop\Order\Manager\Base\Decorator\*") around the order base
536
		 * manager.
537
		 *
538
		 *  mshop/order/manager/base/decorators/local = array( 'decorator2' )
539
		 *
540
		 * This would add the decorator named "decorator2" defined by
541
		 * "\Aimeos\MShop\Order\Manager\Base\Decorator\Decorator2" only to the
542
		 * order base manager.
543
		 *
544
		 * @param array List of decorator names
545
		 * @since 2014.03
546
		 * @category Developer
547
		 * @see mshop/common/manager/decorators/default
548
		 * @see mshop/order/manager/base/decorators/excludes
549
		 * @see mshop/order/manager/base/decorators/global
550
		 */
551
552
		return $this->getSubManagerBase( 'order', 'base/' . $manager, $name );
553
	}
554
555
556
	/**
557
	 * Adds or updates an order base item in the storage.
558
	 *
559
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $item Order base object (sub-items are not saved)
560
	 * @param boolean $fetch True if the new ID should be returned in the item
561
	 * @return \Aimeos\MShop\Order\Item\Base\Iface $item Updated item including the generated ID
562
	 */
563
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
564
	{
565
		self::checkClass( \Aimeos\MShop\Order\Item\Base\Iface::class, $item );
566
567
		if( !$item->isModified() && !$item->getLocale()->isModified() ) {
568
			return $item;
569
		}
570
571
		$context = $this->getContext();
572
573
		$dbm = $context->getDatabaseManager();
574
		$dbname = $this->getResourceName();
575
		$conn = $dbm->acquire( $dbname );
576
577
		try
578
		{
579
			$id = $item->getId();
580
			$date = date( 'Y-m-d H:i:s' );
581
582
			if( $id === null )
583
			{
584
				/** mshop/order/manager/base/standard/insert/mysql
585
				 * Inserts a new order record into the database table
586
				 *
587
				 * @see mshop/order/manager/base/standard/insert/ansi
588
				 */
589
590
				/** mshop/order/manager/base/standard/insert/ansi
591
				 * Inserts a new order record into the database table
592
				 *
593
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
594
				 * the database and the newly created ID retrieved afterwards
595
				 * using the "newid" SQL statement.
596
				 *
597
				 * The SQL statement must be a string suitable for being used as
598
				 * prepared statement. It must include question marks for binding
599
				 * the values from the order item to the statement before they are
600
				 * sent to the database server. The number of question marks must
601
				 * be the same as the number of columns listed in the INSERT
602
				 * statement. The order of the columns must correspond to the
603
				 * order in the saveItems() method, so the correct values are
604
				 * bound to the columns.
605
				 *
606
				 * The SQL statement should conform to the ANSI standard to be
607
				 * compatible with most relational database systems. This also
608
				 * includes using double quotes for table and column names.
609
				 *
610
				 * @param string SQL statement for inserting records
611
				 * @since 2014.03
612
				 * @category Developer
613
				 * @see mshop/order/manager/base/standard/update/ansi
614
				 * @see mshop/order/manager/base/standard/newid/ansi
615
				 * @see mshop/order/manager/base/standard/delete/ansi
616
				 * @see mshop/order/manager/base/standard/search/ansi
617
				 * @see mshop/order/manager/base/standard/count/ansi
618
				 */
619
				$path = 'mshop/order/manager/base/standard/insert';
620
			}
621
			else
622
			{
623
				/** mshop/order/manager/base/standard/update/mysql
624
				 * Updates an existing order record in the database
625
				 *
626
				 * @see mshop/order/manager/base/standard/update/ansi
627
				 */
628
629
				/** mshop/order/manager/base/standard/update/ansi
630
				 * Updates an existing order record in the database
631
				 *
632
				 * Items which already have an ID (i.e. the ID is not NULL) will
633
				 * be updated in the database.
634
				 *
635
				 * The SQL statement must be a string suitable for being used as
636
				 * prepared statement. It must include question marks for binding
637
				 * the values from the order item to the statement before they are
638
				 * sent to the database server. The order of the columns must
639
				 * correspond to the order in the saveItems() method, so the
640
				 * correct values are bound to the columns.
641
				 *
642
				 * The SQL statement should conform to the ANSI standard to be
643
				 * compatible with most relational database systems. This also
644
				 * includes using double quotes for table and column names.
645
				 *
646
				 * @param string SQL statement for updating records
647
				 * @since 2014.03
648
				 * @category Developer
649
				 * @see mshop/order/manager/base/standard/insert/ansi
650
				 * @see mshop/order/manager/base/standard/newid/ansi
651
				 * @see mshop/order/manager/base/standard/delete/ansi
652
				 * @see mshop/order/manager/base/standard/search/ansi
653
				 * @see mshop/order/manager/base/standard/count/ansi
654
				 */
655
				$path = 'mshop/order/manager/base/standard/update';
656
			}
657
658
			$priceItem = $item->getPrice();
659
			$localeItem = $context->getLocale();
660
661
			$stmt = $this->getCachedStatement( $conn, $path );
662
663
			$stmt->bind( 1, $item->getCustomerId() );
664
			$stmt->bind( 2, $localeItem->getSite()->getCode() );
665
			$stmt->bind( 3, $item->getLocale()->getLanguageId() );
666
			$stmt->bind( 4, $priceItem->getCurrencyId() );
667
			$stmt->bind( 5, $priceItem->getValue() );
668
			$stmt->bind( 6, $priceItem->getCosts() );
669
			$stmt->bind( 7, $priceItem->getRebate() );
670
			$stmt->bind( 8, $priceItem->getTaxValue() );
671
			$stmt->bind( 9, $priceItem->getTaxFlag(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
672
			$stmt->bind( 10, $item->getComment() );
673
			$stmt->bind( 11, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
674
			$stmt->bind( 12, $date ); // mtime
675
			$stmt->bind( 13, $context->getEditor() );
676
			$stmt->bind( 14, $localeItem->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
677
678
			if( $id !== null ) {
679
				$stmt->bind( 15, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
680
				$item->setId( $id );
681
			} else {
682
				$stmt->bind( 15, $date ); // ctime
683
			}
684
685
			$stmt->execute()->finish();
686
687
			if( $id === null && $fetch === true )
688
			{
689
				/** mshop/order/manager/base/standard/newid/mysql
690
				 * Retrieves the ID generated by the database when inserting a new record
691
				 *
692
				 * @see mshop/order/manager/base/standard/newid/ansi
693
				 */
694
695
				/** mshop/order/manager/base/standard/newid/ansi
696
				 * Retrieves the ID generated by the database when inserting a new record
697
				 *
698
				 * As soon as a new record is inserted into the database table,
699
				 * the database server generates a new and unique identifier for
700
				 * that record. This ID can be used for retrieving, updating and
701
				 * deleting that specific record from the table again.
702
				 *
703
				 * For MySQL:
704
				 *  SELECT LAST_INSERT_ID()
705
				 * For PostgreSQL:
706
				 *  SELECT currval('seq_mord_id')
707
				 * For SQL Server:
708
				 *  SELECT SCOPE_IDENTITY()
709
				 * For Oracle:
710
				 *  SELECT "seq_mord_id".CURRVAL FROM DUAL
711
				 *
712
				 * There's no way to retrive the new ID by a SQL statements that
713
				 * fits for most database servers as they implement their own
714
				 * specific way.
715
				 *
716
				 * @param string SQL statement for retrieving the last inserted record ID
717
				 * @since 2014.03
718
				 * @category Developer
719
				 * @see mshop/order/manager/base/standard/insert/ansi
720
				 * @see mshop/order/manager/base/standard/update/ansi
721
				 * @see mshop/order/manager/base/standard/delete/ansi
722
				 * @see mshop/order/manager/base/standard/search/ansi
723
				 * @see mshop/order/manager/base/standard/count/ansi
724
				 */
725
				$path = 'mshop/order/manager/base/standard/newid';
726
				$item->setId( $this->newId( $conn, $path ) );
727
			}
728
729
			$dbm->release( $conn, $dbname );
730
		}
731
		catch( \Exception $e )
732
		{
733
			$dbm->release( $conn, $dbname );
734
			throw $e;
735
		}
736
737
		return $item;
738
	}
739
740
741
	/**
742
	 * Search for orders based on the given criteria.
743
	 *
744
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
745
	 * @param string[] $ref List of domains to fetch list items and referenced items for, e.g.
746
	 *	"order/base/address", "order/base/coupon", "order/base/product", "order/base/service"
747
	 * @param integer|null &$total Number of items that are available in total
748
	 * @return array List of items implementing \Aimeos\MShop\Order\Item\Base\Iface
749
	 */
750
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
751
	{
752
		$map = [];
753
754
		$context = $this->getContext();
755
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
756
		$localeManager = \Aimeos\MShop::create( $context, 'locale' );
757
758
		$dbm = $context->getDatabaseManager();
759
		$dbname = $this->getResourceName();
760
		$conn = $dbm->acquire( $dbname );
761
762
		try
763
		{
764
			$required = array( 'order.base' );
765
766
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
767
			$level = $context->getConfig()->get( 'mshop/order/manager/sitemode', $level );
768
769
			/** mshop/order/manager/base/standard/search/mysql
770
			 * Retrieves the records matched by the given criteria in the database
771
			 *
772
			 * @see mshop/order/manager/base/standard/search/ansi
773
			 */
774
775
			/** mshop/order/manager/base/standard/search/ansi
776
			 * Retrieves the records matched by the given criteria in the database
777
			 *
778
			 * Fetches the records matched by the given criteria from the order
779
			 * database. The records must be from one of the sites that are
780
			 * configured via the context item. If the current site is part of
781
			 * a tree of sites, the SELECT statement can retrieve all records
782
			 * from the current site and the complete sub-tree of sites.
783
			 *
784
			 * As the records can normally be limited by criteria from sub-managers,
785
			 * their tables must be joined in the SQL context. This is done by
786
			 * using the "internaldeps" property from the definition of the ID
787
			 * column of the sub-managers. These internal dependencies specify
788
			 * the JOIN between the tables and the used columns for joining. The
789
			 * ":joins" placeholder is then replaced by the JOIN strings from
790
			 * the sub-managers.
791
			 *
792
			 * To limit the records matched, conditions can be added to the given
793
			 * criteria object. It can contain comparisons like column names that
794
			 * must match specific values which can be combined by AND, OR or NOT
795
			 * operators. The resulting string of SQL conditions replaces the
796
			 * ":cond" placeholder before the statement is sent to the database
797
			 * server.
798
			 *
799
			 * If the records that are retrieved should be ordered by one or more
800
			 * columns, the generated string of column / sort direction pairs
801
			 * replaces the ":order" placeholder. In case no ordering is required,
802
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
803
			 * markers is removed to speed up retrieving the records. Columns of
804
			 * sub-managers can also be used for ordering the result set but then
805
			 * no index can be used.
806
			 *
807
			 * The number of returned records can be limited and can start at any
808
			 * number between the begining and the end of the result set. For that
809
			 * the ":size" and ":start" placeholders are replaced by the
810
			 * corresponding values from the criteria object. The default values
811
			 * are 0 for the start and 100 for the size value.
812
			 *
813
			 * The SQL statement should conform to the ANSI standard to be
814
			 * compatible with most relational database systems. This also
815
			 * includes using double quotes for table and column names.
816
			 *
817
			 * @param string SQL statement for searching items
818
			 * @since 2014.03
819
			 * @category Developer
820
			 * @see mshop/order/manager/base/standard/insert/ansi
821
			 * @see mshop/order/manager/base/standard/update/ansi
822
			 * @see mshop/order/manager/base/standard/newid/ansi
823
			 * @see mshop/order/manager/base/standard/delete/ansi
824
			 * @see mshop/order/manager/base/standard/count/ansi
825
			 */
826
			$cfgPathSearch = 'mshop/order/manager/base/standard/search';
827
828
			/** mshop/order/manager/base/standard/count/mysql
829
			 * Counts the number of records matched by the given criteria in the database
830
			 *
831
			 * @see mshop/order/manager/base/standard/count/ansi
832
			 */
833
834
			/** mshop/order/manager/base/standard/count/ansi
835
			 * Counts the number of records matched by the given criteria in the database
836
			 *
837
			 * Counts all records matched by the given criteria from the order
838
			 * database. The records must be from one of the sites that are
839
			 * configured via the context item. If the current site is part of
840
			 * a tree of sites, the statement can count all records from the
841
			 * current site and the complete sub-tree of sites.
842
			 *
843
			 * As the records can normally be limited by criteria from sub-managers,
844
			 * their tables must be joined in the SQL context. This is done by
845
			 * using the "internaldeps" property from the definition of the ID
846
			 * column of the sub-managers. These internal dependencies specify
847
			 * the JOIN between the tables and the used columns for joining. The
848
			 * ":joins" placeholder is then replaced by the JOIN strings from
849
			 * the sub-managers.
850
			 *
851
			 * To limit the records matched, conditions can be added to the given
852
			 * criteria object. It can contain comparisons like column names that
853
			 * must match specific values which can be combined by AND, OR or NOT
854
			 * operators. The resulting string of SQL conditions replaces the
855
			 * ":cond" placeholder before the statement is sent to the database
856
			 * server.
857
			 *
858
			 * Both, the strings for ":joins" and for ":cond" are the same as for
859
			 * the "search" SQL statement.
860
			 *
861
			 * Contrary to the "search" statement, it doesn't return any records
862
			 * but instead the number of records that have been found. As counting
863
			 * thousands of records can be a long running task, the maximum number
864
			 * of counted records is limited for performance reasons.
865
			 *
866
			 * The SQL statement should conform to the ANSI standard to be
867
			 * compatible with most relational database systems. This also
868
			 * includes using double quotes for table and column names.
869
			 *
870
			 * @param string SQL statement for counting items
871
			 * @since 2014.03
872
			 * @category Developer
873
			 * @see mshop/order/manager/base/standard/insert/ansi
874
			 * @see mshop/order/manager/base/standard/update/ansi
875
			 * @see mshop/order/manager/base/standard/newid/ansi
876
			 * @see mshop/order/manager/base/standard/delete/ansi
877
			 * @see mshop/order/manager/base/standard/search/ansi
878
			 */
879
			$cfgPathCount = 'mshop/order/manager/base/standard/count';
880
881
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount,
882
				$required, $total, $level );
883
884
			while( ( $row = $results->fetch() ) !== false )
885
			{
886
				$price = $priceManager->createItem();
887
				$price->setCurrencyId( $row['order.base.currencyid'] );
0 ignored issues
show
The method setCurrencyId() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

887
				$price->/** @scrutinizer ignore-call */ 
888
            setCurrencyId( $row['order.base.currencyid'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
888
				$price->setValue( $row['order.base.price'] );
0 ignored issues
show
The method setValue() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

888
				$price->/** @scrutinizer ignore-call */ 
889
            setValue( $row['order.base.price'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
889
				$price->setCosts( $row['order.base.costs'] );
0 ignored issues
show
The method setCosts() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

889
				$price->/** @scrutinizer ignore-call */ 
890
            setCosts( $row['order.base.costs'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
890
				$price->setRebate( $row['order.base.rebate'] );
0 ignored issues
show
The method setRebate() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

890
				$price->/** @scrutinizer ignore-call */ 
891
            setRebate( $row['order.base.rebate'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
891
				$price->setTaxValue( $row['order.base.taxvalue'] );
892
				$price->setTaxFlag( $row['order.base.taxflag'] );
893
894
				// you may need the site object! take care!
895
				$localeItem = $localeManager->createItem();
896
				$localeItem->setLanguageId( $row['order.base.languageid'] );
0 ignored issues
show
The method setLanguageId() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

896
				$localeItem->/** @scrutinizer ignore-call */ 
897
                 setLanguageId( $row['order.base.languageid'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
897
				$localeItem->setCurrencyId( $row['order.base.currencyid'] );
898
				$localeItem->setSiteId( $row['order.base.siteid'] );
0 ignored issues
show
The method setSiteId() does not exist on Aimeos\MShop\Attribute\Item\Iface. ( Ignorable by Annotation )

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

898
				$localeItem->/** @scrutinizer ignore-call */ 
899
                 setSiteId( $row['order.base.siteid'] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
899
900
				$map[$row['order.base.id']] = [$price, $localeItem, $row];
901
			}
902
903
			$dbm->release( $conn, $dbname );
904
		}
905
		catch( \Exception $e )
906
		{
907
			$dbm->release( $conn, $dbname );
908
			throw $e;
909
		}
910
911
		return $this->buildItems( $map, $ref );
912
	}
913
914
915
	/**
916
	 * Creates a new basket containing the items from the order excluding the coupons.
917
	 * If the last parameter is ture, the items will be marked as new and
918
	 * modified so an additional order is stored when the basket is saved.
919
	 *
920
	 * @param string $id Base ID of the order to load
921
	 * @param integer $parts Bitmap of the basket parts that should be loaded
922
	 * @param boolean $fresh Create a new basket by copying the existing one and remove IDs
923
	 * @param boolean $default True to use default criteria, false for no limitation
924
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Basket including all items
925
	 */
926
	public function load( $id, $parts = \Aimeos\MShop\Order\Item\Base\Base::PARTS_ALL, $fresh = false, $default = false )
927
	{
928
		$search = $this->getObject()->createSearch( $default );
929
		$expr = [
930
			$search->compare( '==', 'order.base.id', $id ),
931
			$search->getConditions(),
932
		];
933
		$search->setConditions( $search->combine( '&&', $expr ) );
934
935
		$context = $this->getContext();
936
		$dbm = $context->getDatabaseManager();
937
		$dbname = $this->getResourceName();
938
		$conn = $dbm->acquire( $dbname );
939
940
		try
941
		{
942
			$sitelevel = \Aimeos\MShop\Locale\Manager\Base::SITE_SUBTREE;
943
			$cfgPathSearch = 'mshop/order/manager/base/standard/search';
944
			$cfgPathCount = 'mshop/order/manager/base/standard/count';
945
			$required = array( 'order.base' );
946
			$total = null;
947
948
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $sitelevel );
949
950
			if( ( $row = $results->fetch() ) === false ) {
951
				throw new \Aimeos\MShop\Order\Exception( sprintf( 'Order base item with order ID "%1$s" not found', $id ) );
952
			}
953
			$results->finish();
954
955
			$dbm->release( $conn, $dbname );
956
		}
957
		catch( \Exception $e )
958
		{
959
			$dbm->release( $conn, $dbname );
960
			throw $e;
961
		}
962
963
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
964
		$localeManager = \Aimeos\MShop::create( $context, 'locale' );
965
966
		$price = $priceManager->createItem();
967
		$price->setCurrencyId( $row['order.base.currencyid'] );
968
		$price->setValue( $row['order.base.price'] );
969
		$price->setCosts( $row['order.base.costs'] );
970
		$price->setRebate( $row['order.base.rebate'] );
971
		$price->setTaxFlag( $row['order.base.taxflag'] );
972
		$price->setTaxValue( $row['order.base.taxvalue'] );
973
974
		// you may need the site object! take care!
975
		$localeItem = $localeManager->createItem();
976
		$localeItem->setLanguageId( $row['order.base.languageid'] );
977
		$localeItem->setCurrencyId( $row['order.base.currencyid'] );
978
		$localeItem->setSiteId( $row['order.base.siteid'] );
979
980
		if( $fresh === false ) {
981
			$basket = $this->loadItems( $id, $price, $localeItem, $row, $parts );
982
		} else {
983
			$basket = $this->loadFresh( $id, $price, $localeItem, $row, $parts );
984
		}
985
986
		$pluginManager = \Aimeos\MShop::create( $this->getContext(), 'plugin' );
987
		$pluginManager->register( $basket, 'order' );
988
989
		return $basket;
990
	}
991
992
993
	/**
994
	 * Saves the complete basket to the storage including the items attached.
995
	 *
996
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket object containing all information
997
	 * @param integer $parts Bitmap of the basket parts that should be stored
998
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Stored order basket
999
	 */
1000
	public function store( \Aimeos\MShop\Order\Item\Base\Iface $basket, $parts = \Aimeos\MShop\Order\Item\Base\Base::PARTS_ALL )
1001
	{
1002
		$basket = $this->getObject()->saveItem( $basket );
1003
1004
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT
1005
			|| $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_COUPON
1006
		) {
1007
			$this->storeProducts( $basket );
1008
		}
1009
1010
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_COUPON ) {
1011
			$this->storeCoupons( $basket );
1012
		}
1013
1014
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_ADDRESS ) {
1015
			$this->storeAddresses( $basket );
1016
		}
1017
1018
		if( $parts & \Aimeos\MShop\Order\Item\Base\Base::PARTS_SERVICE ) {
1019
			$this->storeServices( $basket );
1020
		}
1021
1022
		return $basket;
1023
	}
1024
1025
1026
	/**
1027
	 * Creates the order base item objects from the map and adds the referenced items
1028
	 *
1029
	 * @param array $map Associative list of order base IDs as keys and list of price/locale/row as values
1030
	 * @param string[] $ref Domain items that should be added as well, e.g.
1031
	 *	"order/base/address", "order/base/coupon", "order/base/product", "order/base/service"
1032
	 * @return \Aimeos\MShop\Order\Item\Base\Iface[] Associative list of order base IDs as keys and items as values
1033
	 */
1034
	protected function buildItems( array $map, array $ref )
1035
	{
1036
		$items = [];
1037
		$baseIds = array_keys( $map );
1038
		$addressMap = $couponMap = $productMap = $serviceMap = [];
1039
1040
		if( in_array( 'order/base/address', $ref ) ) {
1041
			$addressMap = $this->getAddresses( $baseIds );
1042
		}
1043
1044
		if( in_array( 'order/base/product', $ref ) ) {
1045
			$productMap = $this->getProducts( $baseIds );
1046
		}
1047
1048
		if( in_array( 'order/base/coupon', $ref ) ) {
1049
			$couponMap = $this->getCoupons( $baseIds, false, $productMap );
1050
		}
1051
1052
		if( in_array( 'order/base/service', $ref ) ) {
1053
			$serviceMap = $this->getServices( $baseIds );
1054
		}
1055
1056
		foreach( $map as $id => $list )
1057
		{
1058
			list( $price, $locale, $row ) = $list;
1059
			$addresses = $coupons = $products = $services = [];
1060
1061
			if( isset( $addressMap[$id] ) ) {
1062
				$addresses = $addressMap[$id];
1063
			}
1064
1065
			if( isset( $couponMap[$id] ) ) {
1066
				$coupons = $couponMap[$id];
1067
			}
1068
1069
			if( isset( $productMap[$id] ) ) {
1070
				$products = $productMap[$id];
1071
			}
1072
1073
			if( isset( $serviceMap[$id] ) ) {
1074
				$services = $serviceMap[$id];
1075
			}
1076
1077
			$items[$id] = $this->createItemBase( $price, $locale, $row, $products, $addresses, $services, $coupons );
1078
		}
1079
1080
		return $items;
1081
	}
1082
1083
1084
	/**
1085
	 * Returns a new and empty order base item (shopping basket).
1086
	 *
1087
	 * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00)
1088
	 * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency
1089
	 * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID
1090
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $products List of ordered product items
1091
	 * @param \Aimeos\MShop\Order\Item\Base\Address\Iface[] $addresses List of order address items
1092
	 * @param \Aimeos\MShop\Order\Item\Base\Service\Iface[] $services List of order serviceitems
1093
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $coupons Associative list of coupon codes as keys and items as values
1094
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base object
1095
	 */
1096
	protected function createItemBase( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale,
1097
		array $values = [], array $products = [], array $addresses = [],
1098
		array $services = [], array $coupons = [] )
1099
	{
1100
		return new \Aimeos\MShop\Order\Item\Base\Standard( $price, $locale,
1101
			$values, $products, $addresses, $services, $coupons );
1102
	}
1103
}
1104