Passed
Push — master ( 6aab01...0294bc )
by Aimeos
09:44
created

Standard   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 658
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 24
eloc 167
dl 0
loc 658
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getResourceType() 0 5 1
A __construct() 0 6 1
A getSearchAttributes() 0 22 1
A create() 0 4 1
A get() 0 3 1
A clear() 0 8 2
A search() 0 176 5
A filter() 0 25 2
A delete() 0 35 1
A createItemBase() 0 5 1
B saveItem() 0 161 7
A getSubManager() 0 3 1
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2012
6
 * @copyright Aimeos (aimeos.org), 2015-2022
7
 * @package MShop
8
 * @subpackage Coupon
9
 */
10
11
12
namespace Aimeos\MShop\Coupon\Manager;
13
14
15
/**
16
 * Default coupon manager interface for creating and handling coupons.
17
 *
18
 * @package MShop
19
 * @subpackage Coupon
20
 */
21
class Standard
22
	extends \Aimeos\MShop\Coupon\Manager\Base
23
	implements \Aimeos\MShop\Coupon\Manager\Iface, \Aimeos\MShop\Common\Manager\Factory\Iface
24
{
25
	private $searchConfig = array(
26
		'coupon.id' => array(
27
			'code' => 'coupon.id',
28
			'internalcode' => 'mcou."id"',
29
			'label' => 'ID',
30
			'type' => 'integer',
31
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_INT,
32
			'public' => false,
33
		),
34
		'coupon.siteid' => array(
35
			'code' => 'coupon.siteid',
36
			'internalcode' => 'mcou."siteid"',
37
			'label' => 'Site ID',
38
			'type' => 'string',
39
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
40
			'public' => false,
41
		),
42
		'coupon.label' => array(
43
			'code' => 'coupon.label',
44
			'internalcode' => 'mcou."label"',
45
			'label' => 'Label',
46
			'type' => 'string',
47
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
48
		),
49
		'coupon.provider' => array(
50
			'code' => 'coupon.provider',
51
			'internalcode' => 'mcou."provider"',
52
			'label' => 'Provider',
53
			'type' => 'string',
54
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
55
		),
56
		'coupon.datestart' => array(
57
			'code' => 'coupon.datestart',
58
			'internalcode' => 'mcou."start"',
59
			'label' => 'Start date/time',
60
			'type' => 'datetime',
61
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
62
		),
63
		'coupon.dateend' => array(
64
			'code' => 'coupon.dateend',
65
			'internalcode' => 'mcou."end"',
66
			'label' => 'End date/time',
67
			'type' => 'datetime',
68
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
69
		),
70
		'coupon.status' => array(
71
			'code' => 'coupon.status',
72
			'internalcode' => 'mcou."status"',
73
			'label' => 'Status',
74
			'type' => 'integer',
75
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_INT,
76
		),
77
		'coupon.config' => array(
78
			'code' => 'coupon.config',
79
			'internalcode' => 'mcou."config"',
80
			'label' => 'Configuration',
81
			'type' => 'string',
82
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
83
			'public' => false,
84
		),
85
		'coupon.ctime' => array(
86
			'code' => 'coupon.ctime',
87
			'internalcode' => 'mcou."ctime"',
88
			'label' => 'Create date/time',
89
			'type' => 'datetime',
90
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
91
			'public' => false,
92
		),
93
		'coupon.mtime' => array(
94
			'code' => 'coupon.mtime',
95
			'internalcode' => 'mcou."mtime"',
96
			'label' => 'Modification date/time',
97
			'type' => 'datetime',
98
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
99
			'public' => false,
100
		),
101
		'coupon.editor' => array(
102
			'code' => 'coupon.editor',
103
			'internalcode' => 'mcou."editor"',
104
			'label' => 'Editor',
105
			'type' => 'string',
106
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_STR,
107
			'public' => false,
108
		),
109
	);
110
111
	private $date;
112
113
114
	/**
115
	 * Initializes the object.
116
	 *
117
	 * @param \Aimeos\MShop\ContextIface $context Context object
118
	 */
119
	public function __construct( \Aimeos\MShop\ContextIface $context )
120
	{
121
		parent::__construct( $context );
122
		$this->setResourceName( 'db-coupon' );
123
124
		$this->date = $context->datetime();
125
	}
126
127
128
	/**
129
	 * Removes old entries from the storage.
130
	 *
131
	 * @param iterable $siteids List of IDs for sites whose entries should be deleted
132
	 * @return \Aimeos\MShop\Coupon\Manager\Iface Manager object for chaining method calls
133
	 */
134
	public function clear( iterable $siteids ) : \Aimeos\MShop\Common\Manager\Iface
135
	{
136
		$path = 'mshop/coupon/manager/submanagers';
137
		foreach( $this->context()->config()->get( $path, array( 'code' ) ) as $domain ) {
138
			$this->object()->getSubManager( $domain )->clear( $siteids );
139
		}
140
141
		return $this->clearBase( $siteids, 'mshop/coupon/manager/delete' );
142
	}
143
144
145
	/**
146
	 * Creates a new empty item instance
147
	 *
148
	 * @param array $values Values the item should be initialized with
149
	 * @return \Aimeos\MShop\Coupon\Item\Iface New coupon item object
150
	 */
151
	public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
152
	{
153
		$values['coupon.siteid'] = $this->context()->locale()->getSiteId();
154
		return $this->createItemBase( $values );
155
	}
156
157
158
	/**
159
	 * Returns the available manager types
160
	 *
161
	 * @param bool $withsub Return also the resource type of sub-managers if true
162
	 * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
163
	 */
164
	public function getResourceType( bool $withsub = true ) : array
165
	{
166
		$path = 'mshop/coupon/manager/submanagers';
167
168
		return $this->getResourceTypeBase( 'coupon', $path, array( 'code' ), $withsub );
169
	}
170
171
172
	/**
173
	 * Returns the attributes that can be used for searching.
174
	 *
175
	 * @param bool $withsub Return also attributes of sub-managers if true
176
	 * @return \Aimeos\Base\Criteria\Attribute\Iface[] List of search attribute items
177
	 */
178
	public function getSearchAttributes( bool $withsub = true ) : array
179
	{
180
		/** mshop/coupon/manager/submanagers
181
		 * List of manager names that can be instantiated by the coupon manager
182
		 *
183
		 * Managers provide a generic interface to the underlying storage.
184
		 * Each manager has or can have sub-managers caring about particular
185
		 * aspects. Each of these sub-managers can be instantiated by its
186
		 * parent manager using the getSubManager() method.
187
		 *
188
		 * The search keys from sub-managers can be normally used in the
189
		 * manager as well. It allows you to search for items of the manager
190
		 * using the search keys of the sub-managers to further limit the
191
		 * retrieved list of items.
192
		 *
193
		 * @param array List of sub-manager names
194
		 * @since 2014.03
195
		 * @category Developer
196
		 */
197
		$path = 'mshop/coupon/manager/submanagers';
198
199
		return $this->getSearchAttributesBase( $this->searchConfig, $path, array( 'code' ), $withsub );
200
	}
201
202
203
	/**
204
	 * Returns the coupons item specified by its ID.
205
	 *
206
	 * @param string $id Unique ID of the coupon item in the storage
207
	 * @param string[] $ref List of domains to fetch list items and referenced items for
208
	 * @param bool|null $default Add default criteria or NULL for relaxed default criteria
209
	 * @return \Aimeos\MShop\Coupon\Item\Iface Returns the coupon item of the given ID
210
	 * @throws \Aimeos\MShop\Exception If coupon couldn't be found
211
	 */
212
	public function get( string $id, array $ref = [], ?bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
213
	{
214
		return $this->getItemBase( 'coupon.id', $id, $ref, $default );
215
	}
216
217
218
	/**
219
	 * Saves a coupon item to the storage.
220
	 *
221
	 * @param \Aimeos\MShop\Coupon\Item\Iface $item Coupon implementing the coupon interface
222
	 * @param bool $fetch True if the new ID should be returned in the item
223
	 * @return \Aimeos\MShop\Coupon\Item\Iface $item Updated item including the generated ID
224
	 */
225
	public function saveItem( \Aimeos\MShop\Coupon\Item\Iface $item, bool $fetch = true ) : \Aimeos\MShop\Coupon\Item\Iface
226
	{
227
		if( !$item->isModified() ) {
228
			return $item;
229
		}
230
231
		$context = $this->context();
232
		$conn = $context->db( $this->getResourceName() );
233
234
			$id = $item->getId();
235
			$date = date( 'Y-m-d H:i:s' );
236
			$columns = $this->object()->getSaveAttributes();
237
238
			if( $id === null )
239
			{
240
				/** mshop/coupon/manager/insert/mysql
241
				 * Inserts a new coupon record into the database table
242
				 *
243
				 * @see mshop/coupon/manager/insert/ansi
244
				 */
245
246
				/** mshop/coupon/manager/insert/ansi
247
				 * Inserts a new coupon record into the database table
248
				 *
249
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
250
				 * the database and the newly created ID retrieved afterwards
251
				 * using the "newid" SQL statement.
252
				 *
253
				 * The SQL statement must be a string suitable for being used as
254
				 * prepared statement. It must include question marks for binding
255
				 * the values from the coupon item to the statement before they are
256
				 * sent to the database server. The number of question marks must
257
				 * be the same as the number of columns listed in the INSERT
258
				 * statement. The order of the columns must correspond to the
259
				 * order in the save() method, so the correct values are
260
				 * bound to the columns.
261
				 *
262
				 * The SQL statement should conform to the ANSI standard to be
263
				 * compatible with most relational database systems. This also
264
				 * includes using double quotes for table and column names.
265
				 *
266
				 * @param string SQL statement for inserting records
267
				 * @since 2014.03
268
				 * @category Developer
269
				 * @see mshop/coupon/manager/update/ansi
270
				 * @see mshop/coupon/manager/newid/ansi
271
				 * @see mshop/coupon/manager/delete/ansi
272
				 * @see mshop/coupon/manager/search/ansi
273
				 * @see mshop/coupon/manager/count/ansi
274
				 */
275
				$path = 'mshop/coupon/manager/insert';
276
				$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

276
				$sql = $this->addSqlColumns( array_keys( $columns ), /** @scrutinizer ignore-type */ $this->getSqlConfig( $path ) );
Loading history...
277
			}
278
			else
279
			{
280
				/** mshop/coupon/manager/update/mysql
281
				 * Updates an existing coupon record in the database
282
				 *
283
				 * @see mshop/coupon/manager/update/ansi
284
				 */
285
286
				/** mshop/coupon/manager/update/ansi
287
				 * Updates an existing coupon record in the database
288
				 *
289
				 * Items which already have an ID (i.e. the ID is not NULL) will
290
				 * be updated in the database.
291
				 *
292
				 * The SQL statement must be a string suitable for being used as
293
				 * prepared statement. It must include question marks for binding
294
				 * the values from the coupon item to the statement before they are
295
				 * sent to the database server. The order of the columns must
296
				 * correspond to the order in the save() method, so the
297
				 * correct values are bound to the columns.
298
				 *
299
				 * The SQL statement should conform to the ANSI standard to be
300
				 * compatible with most relational database systems. This also
301
				 * includes using double quotes for table and column names.
302
				 *
303
				 * @param string SQL statement for updating records
304
				 * @since 2014.03
305
				 * @category Developer
306
				 * @see mshop/coupon/manager/insert/ansi
307
				 * @see mshop/coupon/manager/newid/ansi
308
				 * @see mshop/coupon/manager/delete/ansi
309
				 * @see mshop/coupon/manager/search/ansi
310
				 * @see mshop/coupon/manager/count/ansi
311
				 */
312
				$path = 'mshop/coupon/manager/update';
313
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ), false );
314
			}
315
316
			$idx = 1;
317
			$stmt = $this->getCachedStatement( $conn, $path, $sql );
318
319
			foreach( $columns as $name => $entry ) {
320
				$stmt->bind( $idx++, $item->get( $name ), $entry->getInternalType() );
321
			}
322
323
			$stmt->bind( $idx++, $item->getLabel() );
324
			$stmt->bind( $idx++, $item->getProvider() );
325
			$stmt->bind( $idx++, json_encode( $item->getConfig() ) );
326
			$stmt->bind( $idx++, $item->getDateStart() );
327
			$stmt->bind( $idx++, $item->getDateEnd() );
328
			$stmt->bind( $idx++, $item->getStatus(), \Aimeos\Base\DB\Statement\Base::PARAM_INT );
329
			$stmt->bind( $idx++, $date ); // mtime
330
			$stmt->bind( $idx++, $context->editor() );
331
			$stmt->bind( $idx++, $context->locale()->getSiteId() );
332
333
			if( $id !== null ) {
334
				$stmt->bind( $idx, $id, \Aimeos\Base\DB\Statement\Base::PARAM_INT );
335
			} else {
336
				$stmt->bind( $idx, $date ); // ctime
337
			}
338
339
			$stmt->execute()->finish();
340
341
			if( $id === null && $fetch === true )
342
			{
343
				/** mshop/coupon/manager/newid/mysql
344
				 * Retrieves the ID generated by the database when inserting a new record
345
				 *
346
				 * @see mshop/coupon/manager/newid/ansi
347
				 */
348
349
				/** mshop/coupon/manager/newid/ansi
350
				 * Retrieves the ID generated by the database when inserting a new record
351
				 *
352
				 * As soon as a new record is inserted into the database table,
353
				 * the database server generates a new and unique identifier for
354
				 * that record. This ID can be used for retrieving, updating and
355
				 * deleting that specific record from the table again.
356
				 *
357
				 * For MySQL:
358
				 *  SELECT LAST_INSERT_ID()
359
				 * For PostgreSQL:
360
				 *  SELECT currval('seq_mcou_id')
361
				 * For SQL Server:
362
				 *  SELECT SCOPE_IDENTITY()
363
				 * For Oracle:
364
				 *  SELECT "seq_mcou_id".CURRVAL FROM DUAL
365
				 *
366
				 * There's no way to retrive the new ID by a SQL statements that
367
				 * fits for most database servers as they implement their own
368
				 * specific way.
369
				 *
370
				 * @param string SQL statement for retrieving the last inserted record ID
371
				 * @since 2014.03
372
				 * @category Developer
373
				 * @see mshop/coupon/manager/insert/ansi
374
				 * @see mshop/coupon/manager/update/ansi
375
				 * @see mshop/coupon/manager/delete/ansi
376
				 * @see mshop/coupon/manager/search/ansi
377
				 * @see mshop/coupon/manager/count/ansi
378
				 */
379
				$path = 'mshop/coupon/manager/newid';
380
				$id = $this->newId( $conn, $path );
381
			}
382
383
			$item->setId( $id );
384
385
		return $item;
386
	}
387
388
389
	/**
390
	 * Removes multiple items.
391
	 *
392
	 * @param \Aimeos\MShop\Common\Item\Iface[]|string[] $itemIds List of item objects or IDs of the items
393
	 * @return \Aimeos\MShop\Coupon\Manager\Iface Manager object for chaining method calls
394
	 */
395
	public function delete( $itemIds ) : \Aimeos\MShop\Common\Manager\Iface
396
	{
397
		/** mshop/coupon/manager/delete/mysql
398
		 * Deletes the items matched by the given IDs from the database
399
		 *
400
		 * @see mshop/coupon/manager/delete/ansi
401
		 */
402
403
		/** mshop/coupon/manager/delete/ansi
404
		 * Deletes the items matched by the given IDs from the database
405
		 *
406
		 * Removes the records specified by the given IDs from the coupon database.
407
		 * The records must be from the site that is configured via the
408
		 * context item.
409
		 *
410
		 * The ":cond" placeholder is replaced by the name of the ID column and
411
		 * the given ID or list of IDs while the site ID is bound to the question
412
		 * mark.
413
		 *
414
		 * The SQL statement should conform to the ANSI standard to be
415
		 * compatible with most relational database systems. This also
416
		 * includes using double quotes for table and column names.
417
		 *
418
		 * @param string SQL statement for deleting items
419
		 * @since 2014.03
420
		 * @category Developer
421
		 * @see mshop/coupon/manager/insert/ansi
422
		 * @see mshop/coupon/manager/update/ansi
423
		 * @see mshop/coupon/manager/newid/ansi
424
		 * @see mshop/coupon/manager/search/ansi
425
		 * @see mshop/coupon/manager/count/ansi
426
		 */
427
		$path = 'mshop/coupon/manager/delete';
428
429
		return $this->deleteItemsBase( $itemIds, $path );
430
	}
431
432
433
	/**
434
	 * Searchs for coupon items based on the given criteria.
435
	 *
436
	 * @param \Aimeos\Base\Criteria\Iface $search Search criteria object
437
	 * @param string[] $ref List of domains to fetch list items and referenced items for
438
	 * @param int|null &$total Number of items that are available in total
439
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Coupon\Item\Iface with ids as keys
440
	 */
441
	public function search( \Aimeos\Base\Criteria\Iface $search, array $ref = [], int &$total = null ) : \Aimeos\Map
442
	{
443
		$context = $this->context();
444
		$conn = $context->db( $this->getResourceName() );
445
		$items = [];
446
447
			$required = array( 'coupon' );
448
449
			/** mshop/coupon/manager/sitemode
450
			 * Mode how items from levels below or above in the site tree are handled
451
			 *
452
			 * By default, only items from the current site are fetched from the
453
			 * storage. If the ai-sites extension is installed, you can create a
454
			 * tree of sites. Then, this setting allows you to define for the
455
			 * whole coupon domain if items from parent sites are inherited,
456
			 * sites from child sites are aggregated or both.
457
			 *
458
			 * Available constants for the site mode are:
459
			 * * 0 = only items from the current site
460
			 * * 1 = inherit items from parent sites
461
			 * * 2 = aggregate items from child sites
462
			 * * 3 = inherit and aggregate items at the same time
463
			 *
464
			 * You also need to set the mode in the locale manager
465
			 * (mshop/locale/manager/sitelevel) to one of the constants.
466
			 * If you set it to the same value, it will work as described but you
467
			 * can also use different modes. For example, if inheritance and
468
			 * aggregation is configured the locale manager but only inheritance
469
			 * in the domain manager because aggregating items makes no sense in
470
			 * this domain, then items wil be only inherited. Thus, you have full
471
			 * control over inheritance and aggregation in each domain.
472
			 *
473
			 * @param int Constant from Aimeos\MShop\Locale\Manager\Base class
474
			 * @category Developer
475
			 * @since 2018.01
476
			 * @see mshop/locale/manager/sitelevel
477
			 */
478
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_PATH;
479
			$level = $context->config()->get( 'mshop/coupon/manager/sitemode', $level );
480
481
			/** mshop/coupon/manager/search/mysql
482
			 * Retrieves the records matched by the given criteria in the database
483
			 *
484
			 * @see mshop/coupon/manager/search/ansi
485
			 */
486
487
			/** mshop/coupon/manager/search/ansi
488
			 * Retrieves the records matched by the given criteria in the database
489
			 *
490
			 * Fetches the records matched by the given criteria from the coupon
491
			 * database. The records must be from one of the sites that are
492
			 * configured via the context item. If the current site is part of
493
			 * a tree of sites, the SELECT statement can retrieve all records
494
			 * from the current site and the complete sub-tree of sites.
495
			 *
496
			 * As the records can normally be limited by criteria from sub-managers,
497
			 * their tables must be joined in the SQL context. This is done by
498
			 * using the "internaldeps" property from the definition of the ID
499
			 * column of the sub-managers. These internal dependencies specify
500
			 * the JOIN between the tables and the used columns for joining. The
501
			 * ":joins" placeholder is then replaced by the JOIN strings from
502
			 * the sub-managers.
503
			 *
504
			 * To limit the records matched, conditions can be added to the given
505
			 * criteria object. It can contain comparisons like column names that
506
			 * must match specific values which can be combined by AND, OR or NOT
507
			 * operators. The resulting string of SQL conditions replaces the
508
			 * ":cond" placeholder before the statement is sent to the database
509
			 * server.
510
			 *
511
			 * If the records that are retrieved should be ordered by one or more
512
			 * columns, the generated string of column / sort direction pairs
513
			 * replaces the ":order" placeholder. In case no ordering is required,
514
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
515
			 * markers is removed to speed up retrieving the records. Columns of
516
			 * sub-managers can also be used for ordering the result set but then
517
			 * no index can be used.
518
			 *
519
			 * The number of returned records can be limited and can start at any
520
			 * number between the begining and the end of the result set. For that
521
			 * the ":size" and ":start" placeholders are replaced by the
522
			 * corresponding values from the criteria object. The default values
523
			 * are 0 for the start and 100 for the size value.
524
			 *
525
			 * The SQL statement should conform to the ANSI standard to be
526
			 * compatible with most relational database systems. This also
527
			 * includes using double quotes for table and column names.
528
			 *
529
			 * @param string SQL statement for searching items
530
			 * @since 2014.03
531
			 * @category Developer
532
			 * @see mshop/coupon/manager/insert/ansi
533
			 * @see mshop/coupon/manager/update/ansi
534
			 * @see mshop/coupon/manager/newid/ansi
535
			 * @see mshop/coupon/manager/delete/ansi
536
			 * @see mshop/coupon/manager/count/ansi
537
			 */
538
			$cfgPathSearch = 'mshop/coupon/manager/search';
539
540
			/** mshop/coupon/manager/count/mysql
541
			 * Counts the number of records matched by the given criteria in the database
542
			 *
543
			 * @see mshop/coupon/manager/count/ansi
544
			 */
545
546
			/** mshop/coupon/manager/count/ansi
547
			 * Counts the number of records matched by the given criteria in the database
548
			 *
549
			 * Counts all records matched by the given criteria from the coupon
550
			 * database. The records must be from one of the sites that are
551
			 * configured via the context item. If the current site is part of
552
			 * a tree of sites, the statement can count all records from the
553
			 * current site and the complete sub-tree of sites.
554
			 *
555
			 * As the records can normally be limited by criteria from sub-managers,
556
			 * their tables must be joined in the SQL context. This is done by
557
			 * using the "internaldeps" property from the definition of the ID
558
			 * column of the sub-managers. These internal dependencies specify
559
			 * the JOIN between the tables and the used columns for joining. The
560
			 * ":joins" placeholder is then replaced by the JOIN strings from
561
			 * the sub-managers.
562
			 *
563
			 * To limit the records matched, conditions can be added to the given
564
			 * criteria object. It can contain comparisons like column names that
565
			 * must match specific values which can be combined by AND, OR or NOT
566
			 * operators. The resulting string of SQL conditions replaces the
567
			 * ":cond" placeholder before the statement is sent to the database
568
			 * server.
569
			 *
570
			 * Both, the strings for ":joins" and for ":cond" are the same as for
571
			 * the "search" SQL statement.
572
			 *
573
			 * Contrary to the "search" statement, it doesn't return any records
574
			 * but instead the number of records that have been found. As counting
575
			 * thousands of records can be a long running task, the maximum number
576
			 * of counted records is limited for performance reasons.
577
			 *
578
			 * The SQL statement should conform to the ANSI standard to be
579
			 * compatible with most relational database systems. This also
580
			 * includes using double quotes for table and column names.
581
			 *
582
			 * @param string SQL statement for counting items
583
			 * @since 2014.03
584
			 * @category Developer
585
			 * @see mshop/coupon/manager/insert/ansi
586
			 * @see mshop/coupon/manager/update/ansi
587
			 * @see mshop/coupon/manager/newid/ansi
588
			 * @see mshop/coupon/manager/delete/ansi
589
			 * @see mshop/coupon/manager/search/ansi
590
			 */
591
			$cfgPathCount = 'mshop/coupon/manager/count';
592
593
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
594
595
			try
596
			{
597
				while( ( $row = $results->fetch() ) !== null )
598
				{
599
					if( ( $row['coupon.config'] = json_decode( $config = $row['coupon.config'], true ) ) === null )
600
					{
601
						$msg = sprintf( 'Invalid JSON as result of search for ID "%2$s" in "%1$s": %3$s', 'mshop_coupon.config', $row['id'], $config );
602
						$context->logger()->warning( $msg, 'core/coupon' );
603
					}
604
605
					if( $item = $this->applyFilter( $this->createItemBase( $row ) ) ) {
606
						$items[$row['coupon.id']] = $item;
607
					}
608
				}
609
			}
610
			catch( \Exception $e )
611
			{
612
				$results->finish();
613
				throw $e;
614
			}
615
616
		return map( $items );
617
	}
618
619
620
	/**
621
	 * Returns a new sub manager of the given type and name.
622
	 *
623
	 * @param string $manager Name of the sub manager type in lower case
624
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
625
	 * @return \Aimeos\MShop\Common\Manager\Iface Sub manager
626
	 */
627
	public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
628
	{
629
		return $this->getSubManagerBase( 'coupon', $manager, $name );
630
	}
631
632
633
	/**
634
	 * Creates a filter object.
635
	 *
636
	 * @param bool|null $default Add default criteria or NULL for relaxed default criteria
637
	 * @param bool $site TRUE for adding site criteria to limit items by the site of related items
638
	 * @return \Aimeos\Base\Criteria\Iface Returns the filter object
639
	 */
640
	public function filter( ?bool $default = false, bool $site = false ) : \Aimeos\Base\Criteria\Iface
641
	{
642
		if( $default !== false )
643
		{
644
			$object = $this->filterBase( 'coupon', $default );
645
646
			$expr = [];
647
			$expr[] = $object->getConditions();
648
649
			$temp = [];
650
			$temp[] = $object->compare( '==', 'coupon.datestart', null );
651
			$temp[] = $object->compare( '<=', 'coupon.datestart', $this->date );
652
			$expr[] = $object->or( $temp );
653
654
			$temp = [];
655
			$temp[] = $object->compare( '==', 'coupon.dateend', null );
656
			$temp[] = $object->compare( '>=', 'coupon.dateend', $this->date );
657
			$expr[] = $object->or( $temp );
658
659
			$object->setConditions( $object->and( $expr ) );
660
661
			return $object;
662
		}
663
664
		return parent::filter();
665
	}
666
667
668
	/**
669
	 * Creates a new coupon item instance
670
	 *
671
	 * @param array $values Values of the coupon item from the storage
672
	 * @return \Aimeos\MShop\Coupon\Item\Iface Returns a new created coupon item instance
673
	 */
674
	protected function createItemBase( array $values = [] ) : \Aimeos\MShop\Coupon\Item\Iface
675
	{
676
		$values['.date'] = $this->date;
677
678
		return new \Aimeos\MShop\Coupon\Item\Standard( $values );
679
	}
680
}
681