Passed
Push — master ( 3311dc...3c99d6 )
by Aimeos
05:26
created

Standard::createSearch()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 13
rs 10
c 0
b 0
f 0
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;
13
14
15
/**
16
 * Default order manager implementation.
17
 *
18
 * @package MShop
19
 * @subpackage Order
20
 */
21
class Standard
22
	extends \Aimeos\MShop\Common\Manager\Base
23
	implements \Aimeos\MShop\Order\Manager\Iface, \Aimeos\MShop\Common\Manager\Factory\Iface
24
{
25
	private $searchConfig = array(
26
		'order.id' => array(
27
			'code' => 'order.id',
28
			'internalcode' => 'mord."id"',
29
			'label' => 'Invoice ID',
30
			'type' => 'integer',
31
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
32
		),
33
		'order.siteid' => array(
34
			'code' => 'order.siteid',
35
			'internalcode' => 'mord."siteid"',
36
			'label' => 'Invoice site ID',
37
			'type' => 'integer',
38
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
39
			'public' => false,
40
		),
41
		'order.baseid' => array(
42
			'code' => 'order.baseid',
43
			'internalcode' => 'mord."baseid"',
44
			'label' => 'Invoice base ID',
45
			'type' => 'integer',
46
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
47
			'public' => false,
48
		),
49
		'order.datepayment' => array(
50
			'code' => 'order.datepayment',
51
			'internalcode' => 'mord."datepayment"',
52
			'label' => 'Purchase date',
53
			'type' => 'datetime',
54
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
55
		),
56
		'order.datedelivery' => array(
57
			'code' => 'order.datedelivery',
58
			'internalcode' => 'mord."datedelivery"',
59
			'label' => 'Delivery date',
60
			'type' => 'datetime',
61
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
62
		),
63
		'order.statusdelivery' => array(
64
			'code' => 'order.statusdelivery',
65
			'internalcode' => 'mord."statusdelivery"',
66
			'label' => 'Delivery status',
67
			'type' => 'integer',
68
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
69
		),
70
		'order.statuspayment' => array(
71
			'code' => 'order.statuspayment',
72
			'internalcode' => 'mord."statuspayment"',
73
			'label' => 'Payment status',
74
			'type' => 'integer',
75
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
76
		),
77
		'order.type' => array(
78
			'code' => 'order.type',
79
			'internalcode' => 'mord."type"',
80
			'label' => 'Invoice type',
81
			'type' => 'string',
82
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
83
		),
84
		'order.relatedid' => array(
85
			'code' => 'order.relatedid',
86
			'internalcode' => 'mord."relatedid"',
87
			'label' => 'Related invoice ID',
88
			'type' => 'integer',
89
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
90
		),
91
		'order.cdate' => array(
92
			'code' => 'order.cdate',
93
			'internalcode' => 'mord."cdate"',
94
			'label' => 'Create date',
95
			'type' => 'string',
96
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
97
			'public' => false,
98
		),
99
		'order.cmonth' => array(
100
			'code' => 'order.cmonth',
101
			'internalcode' => 'mord."cmonth"',
102
			'label' => 'Create month',
103
			'type' => 'string',
104
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
105
			'public' => false,
106
		),
107
		'order.cweek' => array(
108
			'code' => 'order.cweek',
109
			'internalcode' => 'mord."cweek"',
110
			'label' => 'Create week',
111
			'type' => 'string',
112
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
113
			'public' => false,
114
		),
115
		'order.cwday' => array(
116
			'code' => 'order.cwday',
117
			'internalcode' => 'mord."cwday"',
118
			'label' => 'Create weekday',
119
			'type' => 'string',
120
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
121
			'public' => false,
122
		),
123
		'order.chour' => array(
124
			'code' => 'order.chour',
125
			'internalcode' => 'mord."chour"',
126
			'label' => 'Create hour',
127
			'type' => 'string',
128
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
129
			'public' => false,
130
		),
131
		'order.ctime' => array(
132
			'code' => 'order.ctime',
133
			'internalcode' => 'mord."ctime"',
134
			'label' => 'Create date/time',
135
			'type' => 'datetime',
136
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
137
			'public' => false,
138
		),
139
		'order.mtime' => array(
140
			'code' => 'order.mtime',
141
			'internalcode' => 'mord."mtime"',
142
			'label' => 'Modify date/time',
143
			'type' => 'datetime',
144
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
145
			'public' => false,
146
		),
147
		'order.editor' => array(
148
			'code' => 'order.editor',
149
			'internalcode' => 'mord."editor"',
150
			'label' => 'Editor',
151
			'type' => 'string',
152
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
153
			'public' => false,
154
		),
155
		'order:status' => array(
156
			'code' => 'order:status()',
157
			'internalcode' => ':site AND mordst."type" = $1 AND mordst."value"',
158
			'label' => 'Order has status item, parameter(<type>)',
159
			'type' => 'string',
160
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
161
			'public' => false,
162
		),
163
		'order.containsStatus' => array(
164
			'code' => 'order.containsStatus()',
165
			'internalcode' => '( SELECT COUNT(mordst_cs."parentid")
166
				FROM "mshop_order_status" AS mordst_cs
167
				WHERE mord."id" = mordst_cs."parentid" AND :site
168
				AND mordst_cs."type" = $1 AND mordst_cs."value" IN ( $2 ) )',
169
			'label' => 'Number of order status items, parameter(<type>,<value>)',
170
			'type' => 'integer',
171
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
172
			'public' => false,
173
		),
174
	);
175
176
177
	/**
178
	 * Creates the manager that will use the given context object.
179
	 *
180
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object with required objects
181
	 */
182
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
183
	{
184
		parent::__construct( $context );
185
		$this->setResourceName( 'db-order' );
186
187
188
		$sites = $context->getLocale()->getSiteSubTree();
189
		$this->replaceSiteMarker( $this->searchConfig['order:status'], 'mordst."siteid"', $sites, ':site' );
190
		$this->replaceSiteMarker( $this->searchConfig['order.containsStatus'], 'mordst_cs."siteid"', $sites, ':site' );
191
	}
192
193
194
	/**
195
	 * Counts the number items that are available for the values of the given key.
196
	 *
197
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria
198
	 * @param string $key Search key to aggregate items for
199
	 * @return integer[] List of the search keys as key and the number of counted items as value
200
	 * @todo 2018.01 Add optional parameters to interface
201
	 */
202
	public function aggregate( \Aimeos\MW\Criteria\Iface $search, $key, $value = null, $type = null )
203
	{
204
		/** mshop/order/manager/standard/aggregate/mysql
205
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
206
		 *
207
		 * @see mshop/order/manager/standard/aggregate/ansi
208
		 */
209
210
		/** mshop/order/manager/standard/aggregate/ansi
211
		 * Counts the number of records grouped by the values in the key column and matched by the given criteria
212
		 *
213
		 * Groups all records by the values in the key column and counts their
214
		 * occurence. The matched records can be limited by the given criteria
215
		 * from the order database. The records must be from one of the sites
216
		 * that are configured via the context item. If the current site is part
217
		 * of a tree of sites, the statement can count all records from the
218
		 * current site and the complete sub-tree of sites.
219
		 *
220
		 * As the records can normally be limited by criteria from sub-managers,
221
		 * their tables must be joined in the SQL context. This is done by
222
		 * using the "internaldeps" property from the definition of the ID
223
		 * column of the sub-managers. These internal dependencies specify
224
		 * the JOIN between the tables and the used columns for joining. The
225
		 * ":joins" placeholder is then replaced by the JOIN strings from
226
		 * the sub-managers.
227
		 *
228
		 * To limit the records matched, conditions can be added to the given
229
		 * criteria object. It can contain comparisons like column names that
230
		 * must match specific values which can be combined by AND, OR or NOT
231
		 * operators. The resulting string of SQL conditions replaces the
232
		 * ":cond" placeholder before the statement is sent to the database
233
		 * server.
234
		 *
235
		 * This statement doesn't return any records. Instead, it returns pairs
236
		 * of the different values found in the key column together with the
237
		 * number of records that have been found for that key values.
238
		 *
239
		 * The SQL statement should conform to the ANSI standard to be
240
		 * compatible with most relational database systems. This also
241
		 * includes using double quotes for table and column names.
242
		 *
243
		 * @param string SQL statement for aggregating order items
244
		 * @since 2014.09
245
		 * @category Developer
246
		 * @see mshop/order/manager/standard/insert/ansi
247
		 * @see mshop/order/manager/standard/update/ansi
248
		 * @see mshop/order/manager/standard/newid/ansi
249
		 * @see mshop/order/manager/standard/delete/ansi
250
		 * @see mshop/order/manager/standard/search/ansi
251
		 * @see mshop/order/manager/standard/count/ansi
252
		 */
253
254
		/** mshop/order/manager/standard/aggregateavg/mysql
255
		 * Computes the average of all values grouped by the key column and matched by the given criteria
256
		 *
257
		 * @param string SQL statement for aggregating the order items and computing the average value
258
		 * @since 2017.10
259
		 * @category Developer
260
		 * @see mshop/order/manager/standard/aggregateavg/ansi
261
		 * @see mshop/order/manager/standard/aggregate/mysql
262
		 */
263
264
		/** mshop/order/manager/standard/aggregateavg/ansi
265
		 * Computes the average of all values grouped by the key column and matched by the given criteria
266
		 *
267
		 * @param string SQL statement for aggregating the order items and computing the average value
268
		 * @since 2017.10
269
		 * @category Developer
270
		 * @see mshop/order/manager/standard/aggregate/ansi
271
		 */
272
273
		/** mshop/order/manager/standard/aggregatesum/mysql
274
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
275
		 *
276
		 * @param string SQL statement for aggregating the order items and computing the sum
277
		 * @since 2017.10
278
		 * @category Developer
279
		 * @see mshop/order/manager/standard/aggregatesum/ansi
280
		 * @see mshop/order/manager/standard/aggregate/mysql
281
		 */
282
283
		/** mshop/order/manager/standard/aggregatesum/ansi
284
		 * Computes the sum of all values grouped by the key column and matched by the given criteria
285
		 *
286
		 * @param string SQL statement for aggregating the order items and computing the sum
287
		 * @since 2017.10
288
		 * @category Developer
289
		 * @see mshop/order/manager/standard/aggregate/ansi
290
		 */
291
292
		$cfgkey = 'mshop/order/manager/standard/aggregate' . $type;
293
		return $this->aggregateBase( $search, $key, $cfgkey, array( 'order' ), $value );
294
	}
295
296
297
	/**
298
	 * Removes old entries from the storage.
299
	 *
300
	 * @param string[] $siteids List of IDs for sites whose entries should be deleted
301
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
302
	 */
303
	public function cleanup( array $siteids )
304
	{
305
		$path = 'mshop/order/manager/submanagers';
306
		foreach( $this->getContext()->getConfig()->get( $path, array( 'status', 'base' ) ) as $domain ) {
307
			$this->getObject()->getSubManager( $domain )->cleanup( $siteids );
308
		}
309
310
		return $this->cleanupBase( $siteids, 'mshop/order/manager/standard/delete' );
311
	}
312
313
314
	/**
315
	 * Creates a new empty item instance
316
	 *
317
	 * @param array $values Values the item should be initialized with
318
	 * @return \Aimeos\MShop\Order\Item\Iface New order item object
319
	 */
320
	public function createItem( array $values = [] )
321
	{
322
		$values['order.siteid'] = $this->getContext()->getLocale()->getSiteId();
323
		return $this->createItemBase( $values );
324
	}
325
326
327
	/**
328
	 * Creates a search critera object
329
	 *
330
	 * @param boolean $default Add default criteria (optional)
331
	 * @return \Aimeos\MW\Criteria\Iface New search criteria object
332
	 */
333
	public function createSearch( $default = false )
334
	{
335
		$search = parent::createSearch();
336
337
		if( $default === true )
338
		{
339
			$search->setConditions( $search->combine( '&&', [
340
				$search->compare( '==', 'order.base.customerid', $this->getContext()->getUserId() ),
341
				$search->getConditions()
342
			] ) );
343
		}
344
345
		return $search;
346
	}
347
348
349
	/**
350
	 * Creates a one-time order in the storage from the given invoice object.
351
	 *
352
	 * @param \Aimeos\MShop\Order\Item\Iface $item Order item with necessary values
353
	 * @param boolean $fetch True if the new ID should be returned in the item
354
	 * @return \Aimeos\MShop\Order\Item\Iface $item Updated item including the generated ID
355
	 */
356
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
357
	{
358
		self::checkClass( \Aimeos\MShop\Order\Item\Iface::class, $item );
359
360
		if( $item->getBaseId() === null ) {
361
			throw new \Aimeos\MShop\Order\Exception( 'Required order base ID is missing' );
362
		}
363
364
		if( !$item->isModified() ) {
365
			return $item;
366
		}
367
368
		$context = $this->getContext();
369
370
		$dbm = $context->getDatabaseManager();
371
		$dbname = $this->getResourceName();
372
		$conn = $dbm->acquire( $dbname );
373
374
		try
375
		{
376
			$id = $item->getId();
377
			$date = date( 'Y-m-d H:i:s' );
378
379
			if( $id === null )
380
			{
381
				/** mshop/order/manager/standard/insert/mysql
382
				 * Inserts a new order record into the database table
383
				 *
384
				 * @see mshop/order/manager/standard/insert/ansi
385
				 */
386
387
				/** mshop/order/manager/standard/insert/ansi
388
				 * Inserts a new order record into the database table
389
				 *
390
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
391
				 * the database and the newly created ID retrieved afterwards
392
				 * using the "newid" SQL statement.
393
				 *
394
				 * The SQL statement must be a string suitable for being used as
395
				 * prepared statement. It must include question marks for binding
396
				 * the values from the order item to the statement before they are
397
				 * sent to the database server. The number of question marks must
398
				 * be the same as the number of columns listed in the INSERT
399
				 * statement. The order of the columns must correspond to the
400
				 * order in the saveItems() method, so the correct values are
401
				 * bound to the columns.
402
				 *
403
				 * The SQL statement should conform to the ANSI standard to be
404
				 * compatible with most relational database systems. This also
405
				 * includes using double quotes for table and column names.
406
				 *
407
				 * @param string SQL statement for inserting records
408
				 * @since 2014.03
409
				 * @category Developer
410
				 * @see mshop/order/manager/standard/update/ansi
411
				 * @see mshop/order/manager/standard/newid/ansi
412
				 * @see mshop/order/manager/standard/delete/ansi
413
				 * @see mshop/order/manager/standard/search/ansi
414
				 * @see mshop/order/manager/standard/count/ansi
415
				 */
416
				$path = 'mshop/order/manager/standard/insert';
417
			}
418
			else
419
			{
420
				/** mshop/order/manager/standard/update/mysql
421
				 * Updates an existing order record in the database
422
				 *
423
				 * @see mshop/order/manager/standard/update/ansi
424
				 */
425
426
				/** mshop/order/manager/standard/update/ansi
427
				 * Updates an existing order record in the database
428
				 *
429
				 * Items which already have an ID (i.e. the ID is not NULL) will
430
				 * be updated in the database.
431
				 *
432
				 * The SQL statement must be a string suitable for being used as
433
				 * prepared statement. It must include question marks for binding
434
				 * the values from the order item to the statement before they are
435
				 * sent to the database server. The order of the columns must
436
				 * correspond to the order in the saveItems() method, so the
437
				 * correct values are bound to the columns.
438
				 *
439
				 * The SQL statement should conform to the ANSI standard to be
440
				 * compatible with most relational database systems. This also
441
				 * includes using double quotes for table and column names.
442
				 *
443
				 * @param string SQL statement for updating records
444
				 * @since 2014.03
445
				 * @category Developer
446
				 * @see mshop/order/manager/standard/insert/ansi
447
				 * @see mshop/order/manager/standard/newid/ansi
448
				 * @see mshop/order/manager/standard/delete/ansi
449
				 * @see mshop/order/manager/standard/search/ansi
450
				 * @see mshop/order/manager/standard/count/ansi
451
				 */
452
				$path = 'mshop/order/manager/standard/update';
453
			}
454
455
			$stmt = $this->getCachedStatement( $conn, $path );
456
457
			$stmt->bind( 1, $item->getBaseId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
458
			$stmt->bind( 2, $item->getType() );
459
			$stmt->bind( 3, $item->getDatePayment() );
460
			$stmt->bind( 4, $item->getDateDelivery() );
461
			$stmt->bind( 5, $item->getDeliveryStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
462
			$stmt->bind( 6, $item->getPaymentStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
463
			$stmt->bind( 7, $item->getRelatedId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
464
			$stmt->bind( 8, $date ); // mtime
465
			$stmt->bind( 9, $context->getEditor() );
466
			$stmt->bind( 10, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
467
468
			if( $id !== null ) {
469
				$stmt->bind( 11, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
470
				$item->setId( $id ); // is not modified anymore
471
			} else {
472
				$stmt->bind( 11, $date ); // ctime
473
				$stmt->bind( 12, date( 'Y-m-d' ) ); // cdate
474
				$stmt->bind( 13, date( 'Y-m' ) ); // cmonth
475
				$stmt->bind( 14, date( 'Y-W' ) ); // cweek
476
				$stmt->bind( 15, date( 'w' ) ); // cwday
477
				$stmt->bind( 16, date( 'H' ) ); // chour
478
			}
479
480
			$stmt->execute()->finish();
481
482
			if( $id === null && $fetch === true )
483
			{
484
				/** mshop/order/manager/standard/newid/mysql
485
				 * Retrieves the ID generated by the database when inserting a new record
486
				 *
487
				 * @see mshop/order/manager/standard/newid/ansi
488
				 */
489
490
				/** mshop/order/manager/standard/newid/ansi
491
				 * Retrieves the ID generated by the database when inserting a new record
492
				 *
493
				 * As soon as a new record is inserted into the database table,
494
				 * the database server generates a new and unique identifier for
495
				 * that record. This ID can be used for retrieving, updating and
496
				 * deleting that specific record from the table again.
497
				 *
498
				 * For MySQL:
499
				 *  SELECT LAST_INSERT_ID()
500
				 * For PostgreSQL:
501
				 *  SELECT currval('seq_mord_id')
502
				 * For SQL Server:
503
				 *  SELECT SCOPE_IDENTITY()
504
				 * For Oracle:
505
				 *  SELECT "seq_mord_id".CURRVAL FROM DUAL
506
				 *
507
				 * There's no way to retrive the new ID by a SQL statements that
508
				 * fits for most database servers as they implement their own
509
				 * specific way.
510
				 *
511
				 * @param string SQL statement for retrieving the last inserted record ID
512
				 * @since 2014.03
513
				 * @category Developer
514
				 * @see mshop/order/manager/standard/insert/ansi
515
				 * @see mshop/order/manager/standard/update/ansi
516
				 * @see mshop/order/manager/standard/delete/ansi
517
				 * @see mshop/order/manager/standard/search/ansi
518
				 * @see mshop/order/manager/standard/count/ansi
519
				 */
520
				$path = 'mshop/order/manager/standard/newid';
521
				$item->setId( $this->newId( $conn, $path ) );
522
			}
523
524
			$dbm->release( $conn, $dbname );
525
		}
526
		catch( \Exception $e )
527
		{
528
			$dbm->release( $conn, $dbname );
529
			throw $e;
530
		}
531
532
533
		$this->addStatus( $item );
534
535
		return $item;
536
	}
537
538
539
	/**
540
	 * Returns an order invoice item built from database values.
541
	 *
542
	 * @param string $id Unique id of the order invoice
543
	 * @param string[] $ref List of domains to fetch list items and referenced items for
544
	 * @param boolean $default Add default criteria
545
	 * @return \Aimeos\MShop\Order\Item\Iface Returns order invoice item of the given id
546
	 * @throws \Aimeos\MShop\Order\Exception If item couldn't be found
547
	 */
548
	public function getItem( $id, array $ref = [], $default = false )
549
	{
550
		return $this->getItemBase( 'order.id', $id, $ref, $default );
551
	}
552
553
554
	/**
555
	 * Removes multiple items specified by ids in the array.
556
	 *
557
	 * @param string[] $ids List of IDs
558
	 * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
559
	 */
560
	public function deleteItems( array $ids )
561
	{
562
		/** mshop/order/manager/standard/delete/mysql
563
		 * Deletes the items matched by the given IDs from the database
564
		 *
565
		 * @see mshop/order/manager/standard/delete/ansi
566
		 */
567
568
		/** mshop/order/manager/standard/delete/ansi
569
		 * Deletes the items matched by the given IDs from the database
570
		 *
571
		 * Removes the records specified by the given IDs from the order database.
572
		 * The records must be from the site that is configured via the
573
		 * context item.
574
		 *
575
		 * The ":cond" placeholder is replaced by the name of the ID column and
576
		 * the given ID or list of IDs while the site ID is bound to the question
577
		 * mark.
578
		 *
579
		 * The SQL statement should conform to the ANSI standard to be
580
		 * compatible with most relational database systems. This also
581
		 * includes using double quotes for table and column names.
582
		 *
583
		 * @param string SQL statement for deleting items
584
		 * @since 2014.03
585
		 * @category Developer
586
		 * @see mshop/order/manager/standard/insert/ansi
587
		 * @see mshop/order/manager/standard/update/ansi
588
		 * @see mshop/order/manager/standard/newid/ansi
589
		 * @see mshop/order/manager/standard/search/ansi
590
		 * @see mshop/order/manager/standard/count/ansi
591
		 */
592
		$path = 'mshop/order/manager/standard/delete';
593
594
		return $this->deleteItemsBase( $ids, $path );
595
	}
596
597
598
	/**
599
	 * Returns the available manager types
600
	 *
601
	 * @param boolean $withsub Return also the resource type of sub-managers if true
602
	 * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
603
	 */
604
	public function getResourceType( $withsub = true )
605
	{
606
		$path = 'mshop/order/manager/submanagers';
607
		return $this->getResourceTypeBase( 'order', $path, array( 'base', 'status' ), $withsub );
608
	}
609
610
611
	/**
612
	 * Returns the attributes that can be used for searching.
613
	 *
614
	 * @param boolean $withsub Return also attributes of sub-managers if true
615
	 * @return \Aimeos\MW\Criteria\Attribute\Iface[] List of search attribute items
616
	 */
617
	public function getSearchAttributes( $withsub = true )
618
	{
619
		/** mshop/order/manager/submanagers
620
		 * List of manager names that can be instantiated by the order manager
621
		 *
622
		 * Managers provide a generic interface to the underlying storage.
623
		 * Each manager has or can have sub-managers caring about particular
624
		 * aspects. Each of these sub-managers can be instantiated by its
625
		 * parent manager using the getSubManager() method.
626
		 *
627
		 * The search keys from sub-managers can be normally used in the
628
		 * manager as well. It allows you to search for items of the manager
629
		 * using the search keys of the sub-managers to further limit the
630
		 * retrieved list of items.
631
		 *
632
		 * @param array List of sub-manager names
633
		 * @since 2014.03
634
		 * @category Developer
635
		 */
636
		$path = 'mshop/order/manager/submanagers';
637
		$default = array( 'base', 'status' );
638
639
		return $this->getSearchAttributesBase( $this->searchConfig, $path, $default, $withsub );
640
	}
641
642
643
	/**
644
	 * Searches for orders based on the given criteria.
645
	 *
646
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
647
	 * @param string[] $ref List of domains to fetch list items and referenced items for
648
	 * @param integer|null &$total Number of items that are available in total
649
	 * @return \Aimeos\MShop\Order\Item\Iface[] List of order items
650
	 */
651
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
652
	{
653
		$context = $this->getContext();
654
655
		$dbm = $context->getDatabaseManager();
656
		$dbname = $this->getResourceName();
657
		$conn = $dbm->acquire( $dbname );
658
659
		$items = [];
660
661
		try
662
		{
663
			$required = array( 'order' );
664
665
			/** mshop/order/manager/sitemode
666
			 * Mode how items from levels below or above in the site tree are handled
667
			 *
668
			 * By default, only items from the current site are fetched from the
669
			 * storage. If the ai-sites extension is installed, you can create a
670
			 * tree of sites. Then, this setting allows you to define for the
671
			 * whole order domain if items from parent sites are inherited,
672
			 * sites from child sites are aggregated or both.
673
			 *
674
			 * Available constants for the site mode are:
675
			 * * 0 = only items from the current site
676
			 * * 1 = inherit items from parent sites
677
			 * * 2 = aggregate items from child sites
678
			 * * 3 = inherit and aggregate items at the same time
679
			 *
680
			 * You also need to set the mode in the locale manager
681
			 * (mshop/locale/manager/standard/sitelevel) to one of the constants.
682
			 * If you set it to the same value, it will work as described but you
683
			 * can also use different modes. For example, if inheritance and
684
			 * aggregation is configured the locale manager but only inheritance
685
			 * in the domain manager because aggregating items makes no sense in
686
			 * this domain, then items wil be only inherited. Thus, you have full
687
			 * control over inheritance and aggregation in each domain.
688
			 *
689
			 * @param integer Constant from Aimeos\MShop\Locale\Manager\Base class
690
			 * @category Developer
691
			 * @since 2018.01
692
			 * @see mshop/locale/manager/standard/sitelevel
693
			 */
694
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
695
			$level = $context->getConfig()->get( 'mshop/order/manager/sitemode', $level );
696
697
			/** mshop/order/manager/standard/search/mysql
698
			 * Retrieves the records matched by the given criteria in the database
699
			 *
700
			 * @see mshop/order/manager/standard/search/ansi
701
			 */
702
703
			/** mshop/order/manager/standard/search/ansi
704
			 * Retrieves the records matched by the given criteria in the database
705
			 *
706
			 * Fetches the records matched by the given criteria from the order
707
			 * database. The records must be from one of the sites that are
708
			 * configured via the context item. If the current site is part of
709
			 * a tree of sites, the SELECT statement can retrieve all records
710
			 * from the current site and the complete sub-tree of sites.
711
			 *
712
			 * As the records can normally be limited by criteria from sub-managers,
713
			 * their tables must be joined in the SQL context. This is done by
714
			 * using the "internaldeps" property from the definition of the ID
715
			 * column of the sub-managers. These internal dependencies specify
716
			 * the JOIN between the tables and the used columns for joining. The
717
			 * ":joins" placeholder is then replaced by the JOIN strings from
718
			 * the sub-managers.
719
			 *
720
			 * To limit the records matched, conditions can be added to the given
721
			 * criteria object. It can contain comparisons like column names that
722
			 * must match specific values which can be combined by AND, OR or NOT
723
			 * operators. The resulting string of SQL conditions replaces the
724
			 * ":cond" placeholder before the statement is sent to the database
725
			 * server.
726
			 *
727
			 * If the records that are retrieved should be ordered by one or more
728
			 * columns, the generated string of column / sort direction pairs
729
			 * replaces the ":order" placeholder. In case no ordering is required,
730
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
731
			 * markers is removed to speed up retrieving the records. Columns of
732
			 * sub-managers can also be used for ordering the result set but then
733
			 * no index can be used.
734
			 *
735
			 * The number of returned records can be limited and can start at any
736
			 * number between the begining and the end of the result set. For that
737
			 * the ":size" and ":start" placeholders are replaced by the
738
			 * corresponding values from the criteria object. The default values
739
			 * are 0 for the start and 100 for the size value.
740
			 *
741
			 * The SQL statement should conform to the ANSI standard to be
742
			 * compatible with most relational database systems. This also
743
			 * includes using double quotes for table and column names.
744
			 *
745
			 * @param string SQL statement for searching items
746
			 * @since 2014.03
747
			 * @category Developer
748
			 * @see mshop/order/manager/standard/insert/ansi
749
			 * @see mshop/order/manager/standard/update/ansi
750
			 * @see mshop/order/manager/standard/newid/ansi
751
			 * @see mshop/order/manager/standard/delete/ansi
752
			 * @see mshop/order/manager/standard/count/ansi
753
			 */
754
			$cfgPathSearch = 'mshop/order/manager/standard/search';
755
756
			/** mshop/order/manager/standard/count/mysql
757
			 * Counts the number of records matched by the given criteria in the database
758
			 *
759
			 * @see mshop/order/manager/standard/count/ansi
760
			 */
761
762
			/** mshop/order/manager/standard/count/ansi
763
			 * Counts the number of records matched by the given criteria in the database
764
			 *
765
			 * Counts all records matched by the given criteria from the order
766
			 * database. The records must be from one of the sites that are
767
			 * configured via the context item. If the current site is part of
768
			 * a tree of sites, the statement can count all records from the
769
			 * current site and the complete sub-tree of sites.
770
			 *
771
			 * As the records can normally be limited by criteria from sub-managers,
772
			 * their tables must be joined in the SQL context. This is done by
773
			 * using the "internaldeps" property from the definition of the ID
774
			 * column of the sub-managers. These internal dependencies specify
775
			 * the JOIN between the tables and the used columns for joining. The
776
			 * ":joins" placeholder is then replaced by the JOIN strings from
777
			 * the sub-managers.
778
			 *
779
			 * To limit the records matched, conditions can be added to the given
780
			 * criteria object. It can contain comparisons like column names that
781
			 * must match specific values which can be combined by AND, OR or NOT
782
			 * operators. The resulting string of SQL conditions replaces the
783
			 * ":cond" placeholder before the statement is sent to the database
784
			 * server.
785
			 *
786
			 * Both, the strings for ":joins" and for ":cond" are the same as for
787
			 * the "search" SQL statement.
788
			 *
789
			 * Contrary to the "search" statement, it doesn't return any records
790
			 * but instead the number of records that have been found. As counting
791
			 * thousands of records can be a long running task, the maximum number
792
			 * of counted records is limited for performance reasons.
793
			 *
794
			 * The SQL statement should conform to the ANSI standard to be
795
			 * compatible with most relational database systems. This also
796
			 * includes using double quotes for table and column names.
797
			 *
798
			 * @param string SQL statement for counting items
799
			 * @since 2014.03
800
			 * @category Developer
801
			 * @see mshop/order/manager/standard/insert/ansi
802
			 * @see mshop/order/manager/standard/update/ansi
803
			 * @see mshop/order/manager/standard/newid/ansi
804
			 * @see mshop/order/manager/standard/delete/ansi
805
			 * @see mshop/order/manager/standard/search/ansi
806
			 */
807
			$cfgPathCount = 'mshop/order/manager/standard/count';
808
809
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount,
810
				$required, $total, $level );
811
812
			try
813
			{
814
				while( ( $row = $results->fetch() ) !== false ) {
815
					$items[$row['order.id']] = $this->createItemBase( $row );
816
				}
817
			}
818
			catch( \Exception $e )
819
			{
820
				$results->finish();
821
				throw $e;
822
			}
823
824
			$dbm->release( $conn, $dbname );
825
		}
826
		catch( \Exception $e )
827
		{
828
			$dbm->release( $conn, $dbname );
829
			throw $e;
830
		}
831
832
		return $items;
833
	}
834
835
836
	/**
837
	 * Returns a new manager for order extensions
838
	 *
839
	 * @param string $manager Name of the sub manager type in lower case
840
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
841
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g base, etc.
842
	 */
843
	public function getSubManager( $manager, $name = null )
844
	{
845
		return $this->getSubManagerBase( 'order', $manager, $name );
846
	}
847
848
849
	/**
850
	 * Adds the new payment and delivery values to the order status log.
851
	 *
852
	 * @param \Aimeos\MShop\Order\Item\Iface $item Order item object
853
	 */
854
	protected function addStatus( \Aimeos\MShop\Order\Item\Iface $item )
855
	{
856
		$statusManager = \Aimeos\MShop::create( $this->getContext(), 'order/status' );
857
858
		$statusItem = $statusManager->createItem();
859
		$statusItem->setParentId( $item->getId() );
0 ignored issues
show
Bug introduced by
The method setParentId() 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

859
		$statusItem->/** @scrutinizer ignore-call */ 
860
               setParentId( $item->getId() );

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...
860
861
		if( $item->getPaymentStatus() != $item->oldPaymentStatus )
0 ignored issues
show
Bug Best Practice introduced by
The property oldPaymentStatus does not exist on Aimeos\MShop\Order\Item\Iface. Since you implemented __get, consider adding a @property annotation.
Loading history...
862
		{
863
			$statusItem->setId( null );
864
			$statusItem->setType( \Aimeos\MShop\Order\Item\Status\Base::STATUS_PAYMENT );
865
			$statusItem->setValue( $item->getPaymentStatus() );
0 ignored issues
show
Bug introduced by
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

865
			$statusItem->/** @scrutinizer ignore-call */ 
866
                setValue( $item->getPaymentStatus() );

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...
866
867
			$statusManager->saveItem( $statusItem, false );
868
		}
869
870
		if( $item->getDeliveryStatus() != $item->oldDeliveryStatus )
0 ignored issues
show
Bug Best Practice introduced by
The property oldDeliveryStatus does not exist on Aimeos\MShop\Order\Item\Iface. Since you implemented __get, consider adding a @property annotation.
Loading history...
871
		{
872
			$statusItem->setId( null );
873
			$statusItem->setType( \Aimeos\MShop\Order\Item\Status\Base::STATUS_DELIVERY );
874
			$statusItem->setValue( $item->getDeliveryStatus() );
875
876
			$statusManager->saveItem( $statusItem, false );
877
		}
878
	}
879
880
881
	/**
882
	 * Creates a new order item.
883
	 *
884
	 * @param array $values List of attributes for order item
885
	 * @return \Aimeos\MShop\Order\Item\Iface New order item
886
	 */
887
	protected function createItemBase( array $values = [] )
888
	{
889
		return new \Aimeos\MShop\Order\Item\Standard( $values );
890
	}
891
}
892