Passed
Push — master ( 29d5f6...586595 )
by Aimeos
04:48
created

lib/mshoplib/src/MShop/Tag/Manager/Standard.php (1 issue)

Labels
Severity
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 Tag
9
 */
10
11
12
namespace Aimeos\MShop\Tag\Manager;
13
14
15
/**
16
 * Default tag manager implementation.
17
 *
18
 * @package MShop
19
 * @subpackage Tag
20
 */
21
class Standard
22
	extends \Aimeos\MShop\Common\Manager\Base
23
	implements \Aimeos\MShop\Tag\Manager\Iface, \Aimeos\MShop\Common\Manager\Factory\Iface
24
{
25
	private $searchConfig = array(
26
		'tag.id' => array(
27
			'code' => 'tag.id',
28
			'internalcode' => 'mtag."id"',
29
			'label' => 'ID',
30
			'type' => 'integer',
31
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
32
		),
33
		'tag.siteid' => array(
34
			'code' => 'tag.siteid',
35
			'internalcode' => 'mtag."siteid"',
36
			'label' => 'Site ID',
37
			'type' => 'integer',
38
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
39
			'public' => false,
40
		),
41
		'tag.typeid' => array(
42
			'code' => 'tag.typeid',
43
			'internalcode' => 'mtag."typeid"',
44
			'label' => 'Type id',
45
			'type' => 'integer',
46
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
47
			'public' => false,
48
		),
49
		'tag.label' => array(
50
			'code' => 'tag.label',
51
			'internalcode' => 'mtag."label"',
52
			'label' => 'Label',
53
			'type' => 'string',
54
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
55
		),
56
		'tag.domain' => array(
57
			'code' => 'tag.domain',
58
			'internalcode' => 'mtag."domain"',
59
			'label' => 'Domain',
60
			'type' => 'string',
61
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
62
		),
63
		'tag.languageid' => array(
64
			'code' => 'tag.languageid',
65
			'internalcode' => 'mtag."langid"',
66
			'label' => 'Language id',
67
			'type' => 'string',
68
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
69
		),
70
		'tag.ctime' => array(
71
			'code' => 'tag.ctime',
72
			'internalcode' => 'mtag."ctime"',
73
			'label' => 'Creation date/time',
74
			'type' => 'datetime',
75
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
76
			'public' => false,
77
		),
78
		'tag.mtime' => array(
79
			'code' => 'tag.mtime',
80
			'internalcode' => 'mtag."mtime"',
81
			'label' => 'Modify date/time',
82
			'type' => 'datetime',
83
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
84
			'public' => false,
85
		),
86
		'tag.editor' => array(
87
			'code' => 'tag.editor',
88
			'internalcode' => 'mtag."editor"',
89
			'label' => 'Editor',
90
			'type' => 'string',
91
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
92
			'public' => false,
93
		),
94
	);
95
96
	private $languageId;
97
98
99
	/**
100
	 * Initializes the object.
101
	 *
102
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
103
	 */
104
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
105
	{
106
		parent::__construct( $context );
107
		$this->setResourceName( 'db-tag' );
108
109
		$this->languageId = $context->getLocale()->getLanguageId();
110
	}
111
112
113
	/**
114
	 * Removes old entries from the storage.
115
	 *
116
	 * @param integer[] $siteids List of IDs for sites whose entries should be deleted
117
	 */
118
	public function cleanup( array $siteids )
119
	{
120
		$path = 'mshop/tag/manager/submanagers';
121
		foreach( $this->getContext()->getConfig()->get( $path, array( 'type' ) ) as $domain ) {
122
			$this->getObject()->getSubManager( $domain )->cleanup( $siteids );
123
		}
124
125
		$this->cleanupBase( $siteids, 'mshop/tag/manager/standard/delete' );
126
	}
127
128
129
	/**
130
	 * Creates a new empty item instance
131
	 *
132
	 * @param string|null Type the item should be created with
133
	 * @param string|null Domain of the type the item should be created with
134
	 * @param array $values Values the item should be initialized with
135
	 * @return \Aimeos\MShop\Tag\Item\Iface New tag item object
136
	 */
137
	public function createItem( $type = null, $domain = null, array $values = [] )
138
	{
139
		$values['tag.siteid'] = $this->getContext()->getLocale()->getSiteId();
140
141
		if( $type !== null )
142
		{
143
			$values['tag.typeid'] = $this->getTypeId( $type, $domain );
144
			$values['tag.type'] = $type;
145
		}
146
147
		return $this->createItemBase( $values );
148
	}
149
150
151
	/**
152
	 * Inserts the new tag items for tag item
153
	 *
154
	 * @param \Aimeos\MShop\Tag\Item\Iface $item Tag item which should be saved
155
	 * @param boolean $fetch True if the new ID should be returned in the item
156
	 * @return \Aimeos\MShop\Common\Item\Iface $item Updated item including the generated ID
157
	 */
158
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
159
	{
160
		self::checkClass( '\\Aimeos\\MShop\\Tag\\Item\\Iface', $item );
161
162
		if( !$item->isModified() ) {
163
			return $item;
164
		}
165
166
		$context = $this->getContext();
167
168
		$dbm = $context->getDatabaseManager();
169
		$dbname = $this->getResourceName();
170
		$conn = $dbm->acquire( $dbname );
171
172
		try
173
		{
174
			$id = $item->getId();
175
			$date = date( 'Y-m-d H:i:s' );
176
177
			if( $id === null )
178
			{
179
				/** mshop/tag/manager/standard/insert/mysql
180
				 * Inserts a new tag tag record into the database table
181
				 *
182
				 * @see mshop/tag/manager/standard/insert/ansi
183
				 */
184
185
				/** mshop/tag/manager/standard/insert/ansi
186
				 * Inserts a new tag tag record into the database table
187
				 *
188
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
189
				 * the database and the newly created ID retrieved afterwards
190
				 * using the "newid" SQL statement.
191
				 *
192
				 * The SQL statement must be a string suitable for being used as
193
				 * prepared statement. It must include question marks for binding
194
				 * the values from the tag tag item to the statement before they are
195
				 * sent to the database server. The number of question marks must
196
				 * be the same as the number of columns listed in the INSERT
197
				 * statement. The order of the columns must correspond to the
198
				 * order in the saveItems() method, so the correct values are
199
				 * bound to the columns.
200
				 *
201
				 * The SQL statement should conform to the ANSI standard to be
202
				 * compatible with most relational database systems. This also
203
				 * includes using double quotes for table and column names.
204
				 *
205
				 * @param string SQL statement for inserting records
206
				 * @since 2015.12
207
				 * @category Developer
208
				 * @see mshop/tag/manager/standard/update/ansi
209
				 * @see mshop/tag/manager/standard/newid/ansi
210
				 * @see mshop/tag/manager/standard/delete/ansi
211
				 * @see mshop/tag/manager/standard/search/ansi
212
				 * @see mshop/tag/manager/standard/count/ansi
213
				 */
214
				$path = 'mshop/tag/manager/standard/insert';
215
			}
216
			else
217
			{
218
				/** mshop/tag/manager/standard/update/mysql
219
				 * Updates an existing tag tag record in the database
220
				 *
221
				 * @see mshop/tag/manager/standard/update/ansi
222
				 */
223
224
				/** mshop/tag/manager/standard/update/ansi
225
				 * Updates an existing tag tag record in the database
226
				 *
227
				 * Items which already have an ID (i.e. the ID is not NULL) will
228
				 * be updated in the database.
229
				 *
230
				 * The SQL statement must be a string suitable for being used as
231
				 * prepared statement. It must include question marks for binding
232
				 * the values from the tag tag item to the statement before they are
233
				 * sent to the database server. The order of the columns must
234
				 * correspond to the order in the saveItems() method, so the
235
				 * correct values are bound to the columns.
236
				 *
237
				 * The SQL statement should conform to the ANSI standard to be
238
				 * compatible with most relational database systems. This also
239
				 * includes using double quotes for table and column names.
240
				 *
241
				 * @param string SQL statement for updating records
242
				 * @since 2015.12
243
				 * @category Developer
244
				 * @see mshop/tag/manager/standard/insert/ansi
245
				 * @see mshop/tag/manager/standard/newid/ansi
246
				 * @see mshop/tag/manager/standard/delete/ansi
247
				 * @see mshop/tag/manager/standard/search/ansi
248
				 * @see mshop/tag/manager/standard/count/ansi
249
				 */
250
				$path = 'mshop/tag/manager/standard/update';
251
			}
252
253
			$stmt = $this->getCachedStatement( $conn, $path );
254
255
			$stmt->bind( 1, $item->getLanguageId() );
256
			$stmt->bind( 2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
257
			$stmt->bind( 3, $item->getDomain() );
258
			$stmt->bind( 4, $item->getLabel() );
1 ignored issue
show
The method getLabel() does not exist on Aimeos\MShop\Common\Item\Iface. It seems like you code against a sub-type of Aimeos\MShop\Common\Item\Iface such as Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Locale\Item\Site\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Text\Item\Iface or Aimeos\MShop\Customer\Item\Group\Iface or Aimeos\MShop\Media\Item\Iface or Aimeos\MShop\Coupon\Item\Iface or Aimeos\MAdmin\Job\Item\Iface or Aimeos\MShop\Tag\Item\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Locale\Item\Language\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Supplier\Item\Iface or Aimeos\MShop\Locale\Item\Currency\Iface or Aimeos\MShop\Attribute\Item\Standard or Aimeos\MShop\Catalog\Item\Standard or Aimeos\MShop\Customer\Item\Base or Aimeos\MShop\Plugin\Item\Standard or Aimeos\MShop\Tag\Item\Standard or Aimeos\MShop\Customer\Item\Group\Standard or Aimeos\MShop\Media\Item\Standard or Aimeos\MAdmin\Job\Item\Standard or Aimeos\MShop\Common\Item\Type\Standard or Aimeos\MShop\Locale\Item\Site\Standard or Aimeos\MShop\Locale\Item\Currency\Standard or Aimeos\MShop\Text\Item\Standard or Aimeos\MShop\Locale\Item\Language\Standard or Aimeos\MShop\Service\Item\Standard or Aimeos\MShop\Common\Item\ListRef\Base or Aimeos\MShop\Price\Item\Base or Aimeos\MShop\Supplier\Item\Standard or Aimeos\MShop\Coupon\Item\Standard or Aimeos\MShop\Product\Item\Standard or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Text\Item\Iface or Aimeos\MShop\Media\Item\Iface or Aimeos\MShop\Coupon\Item\Iface or Aimeos\MAdmin\Job\Item\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Locale\Item\Language\Iface or Aimeos\MShop\Common\Item\Tree\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Supplier\Item\Iface or Aimeos\MShop\Locale\Item\Currency\Iface or Aimeos\MShop\Price\Item\Base or Aimeos\MShop\Price\Item\Base. ( Ignorable by Annotation )

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

258
			$stmt->bind( 4, $item->/** @scrutinizer ignore-call */ getLabel() );
Loading history...
259
			$stmt->bind( 5, $date ); //mtime
260
			$stmt->bind( 6, $context->getEditor() );
261
			$stmt->bind( 7, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
262
263
			if( $id !== null ) {
264
				$stmt->bind( 8, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
265
				$item->setId( $id ); //is not modified anymore
266
			} else {
267
				$stmt->bind( 8, $date ); //ctime
268
			}
269
270
			$stmt->execute()->finish();
271
272
			if( $id === null && $fetch === true )
273
			{
274
				/** mshop/tag/manager/standard/newid/mysql
275
				 * Retrieves the ID generated by the database when inserting a new record
276
				 *
277
				 * @see mshop/tag/manager/standard/newid/ansi
278
				 */
279
280
				/** mshop/tag/manager/standard/newid/ansi
281
				 * Retrieves the ID generated by the database when inserting a new record
282
				 *
283
				 * As soon as a new record is inserted into the database table,
284
				 * the database server generates a new and unique identifier for
285
				 * that record. This ID can be used for retrieving, updating and
286
				 * deleting that specific record from the table again.
287
				 *
288
				 * For MySQL:
289
				 *  SELECT LAST_INSERT_ID()
290
				 * For PostgreSQL:
291
				 *  SELECT currval('seq_mtag_id')
292
				 * For SQL Server:
293
				 *  SELECT SCOPE_IDENTITY()
294
				 * For Oracle:
295
				 *  SELECT "seq_mtag_id".CURRVAL FROM DUAL
296
				 *
297
				 * There's no way to retrive the new ID by a SQL statements that
298
				 * fits for most database servers as they implement their own
299
				 * specific way.
300
				 *
301
				 * @param string SQL statement for retrieving the last inserted record ID
302
				 * @since 2015.12
303
				 * @category Developer
304
				 * @see mshop/tag/manager/standard/insert/ansi
305
				 * @see mshop/tag/manager/standard/update/ansi
306
				 * @see mshop/tag/manager/standard/delete/ansi
307
				 * @see mshop/tag/manager/standard/search/ansi
308
				 * @see mshop/tag/manager/standard/count/ansi
309
				 */
310
				$path = 'mshop/tag/manager/standard/newid';
311
				$item->setId( $this->newId( $conn, $path ) );
312
			}
313
314
			$dbm->release( $conn, $dbname );
315
		}
316
		catch( \Exception $e )
317
		{
318
			$dbm->release( $conn, $dbname );
319
			throw $e;
320
		}
321
322
		return $item;
323
	}
324
325
326
	/**
327
	 * Removes multiple items specified by ids in the array.
328
	 *
329
	 * @param array $ids List of IDs
330
	 */
331
	public function deleteItems( array $ids )
332
	{
333
		/** mshop/tag/manager/standard/delete/mysql
334
		 * Deletes the items matched by the given IDs from the database
335
		 *
336
		 * @see mshop/tag/manager/standard/delete/ansi
337
		 */
338
339
		/** mshop/tag/manager/standard/delete/ansi
340
		 * Deletes the items matched by the given IDs from the database
341
		 *
342
		 * Removes the records specified by the given IDs from the tag database.
343
		 * The records must be from the site that is configured via the
344
		 * context item.
345
		 *
346
		 * The ":cond" placeholder is replaced by the name of the ID column and
347
		 * the given ID or list of IDs while the site ID is bound to the question
348
		 * mark.
349
		 *
350
		 * The SQL statement should conform to the ANSI standard to be
351
		 * compatible with most relational database systems. This also
352
		 * includes using double quotes for table and column names.
353
		 *
354
		 * @param string SQL statement for deleting items
355
		 * @since 2015.12
356
		 * @category Developer
357
		 * @see mshop/tag/manager/standard/insert/ansi
358
		 * @see mshop/tag/manager/standard/update/ansi
359
		 * @see mshop/tag/manager/standard/newid/ansi
360
		 * @see mshop/tag/manager/standard/search/ansi
361
		 * @see mshop/tag/manager/standard/count/ansi
362
		 */
363
		$path = 'mshop/tag/manager/standard/delete';
364
		$this->deleteItemsBase( $ids, $path );
365
	}
366
367
368
	/**
369
	 * Returns tag tag item with given Id.
370
	 *
371
	 * @param integer $id Id of the tag tag item
372
	 * @param string[] $ref List of domains to fetch list items and referenced items for
373
	 * @param boolean $default Add default criteria
374
	 * @return \Aimeos\MShop\Tag\Item\Iface Returns the tag tag item of the given id
375
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
376
	 */
377
	public function getItem( $id, array $ref = [], $default = false )
378
	{
379
		return $this->getItemBase( 'tag.id', $id, $ref, $default );
380
	}
381
382
383
	/**
384
	 * Returns the available manager types
385
	 *
386
	 * @param boolean $withsub Return also the resource type of sub-managers if true
387
	 * @return array Type of the manager and submanagers, subtypes are separated by slashes
388
	 */
389
	public function getResourceType( $withsub = true )
390
	{
391
		$path = 'mshop/tag/manager/submanagers';
392
393
		return $this->getResourceTypeBase( 'tag', $path, array( 'type' ), $withsub );
394
	}
395
396
397
	/**
398
	 * Returns the attributes that can be used for searching.
399
	 *
400
	 * @param boolean $withsub Return also attributes of sub-managers if true
401
	 * @return array Returns a list of attribtes implementing \Aimeos\MW\Criteria\Attribute\Iface
402
	 */
403
	public function getSearchAttributes( $withsub = true )
404
	{
405
		/** mshop/tag/manager/submanagers
406
		 * List of manager names that can be instantiated by the tag tag manager
407
		 *
408
		 * Managers provide a generic interface to the underlying storage.
409
		 * Each manager has or can have sub-managers caring about particular
410
		 * aspects. Each of these sub-managers can be instantiated by its
411
		 * parent manager using the getSubManager() method.
412
		 *
413
		 * The search keys from sub-managers can be normally used in the
414
		 * manager as well. It allows you to search for items of the manager
415
		 * using the search keys of the sub-managers to further limit the
416
		 * retrieved list of items.
417
		 *
418
		 * @param array List of sub-manager names
419
		 * @since 2015.12
420
		 * @category Developer
421
		 */
422
		$path = 'mshop/tag/manager/submanagers';
423
424
		return $this->getSearchAttributesBase( $this->searchConfig, $path, array( 'type' ), $withsub );
425
	}
426
427
428
	/**
429
	 * Search for all tag items based on the given critera.
430
	 *
431
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
432
	 * @param string[] $ref List of domains to fetch list items and referenced items for
433
	 * @param integer|null &$total Number of items that are available in total
434
	 * @return array List of tag items implementing \Aimeos\MShop\Tag\Item\Iface
435
	 */
436
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
437
	{
438
		$items = $map = $typeIds = [];
439
		$context = $this->getContext();
440
441
		$dbm = $context->getDatabaseManager();
442
		$dbname = $this->getResourceName();
443
		$conn = $dbm->acquire( $dbname );
444
445
		try
446
		{
447
			$required = array( 'tag' );
448
449
			/** mshop/tag/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 tag 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/standard/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 integer Constant from Aimeos\MShop\Locale\Manager\Base class
474
			 * @category Developer
475
			 * @since 2018.01
476
			 * @see mshop/locale/manager/standard/sitelevel
477
			 */
478
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
479
			$level = $context->getConfig()->get( 'mshop/tag/manager/sitemode', $level );
480
481
			/** mshop/tag/manager/standard/search/mysql
482
			 * Retrieves the records matched by the given criteria in the database
483
			 *
484
			 * @see mshop/tag/manager/standard/search/ansi
485
			 */
486
487
			/** mshop/tag/manager/standard/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 tag
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 2015.12
531
			 * @category Developer
532
			 * @see mshop/tag/manager/standard/insert/ansi
533
			 * @see mshop/tag/manager/standard/update/ansi
534
			 * @see mshop/tag/manager/standard/newid/ansi
535
			 * @see mshop/tag/manager/standard/delete/ansi
536
			 * @see mshop/tag/manager/standard/count/ansi
537
			 */
538
			$cfgPathSearch = 'mshop/tag/manager/standard/search';
539
540
			/** mshop/tag/manager/standard/count/mysql
541
			 * Counts the number of records matched by the given criteria in the database
542
			 *
543
			 * @see mshop/tag/manager/standard/count/ansi
544
			 */
545
546
			/** mshop/tag/manager/standard/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 tag
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 2015.12
584
			 * @category Developer
585
			 * @see mshop/tag/manager/standard/insert/ansi
586
			 * @see mshop/tag/manager/standard/update/ansi
587
			 * @see mshop/tag/manager/standard/newid/ansi
588
			 * @see mshop/tag/manager/standard/delete/ansi
589
			 * @see mshop/tag/manager/standard/search/ansi
590
			 */
591
			$cfgPathCount = 'mshop/tag/manager/standard/count';
592
593
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
594
			while( ( $row = $results->fetch() ) !== false )
595
			{
596
				$map[$row['tag.id']] = $row;
597
				$typeIds[$row['tag.typeid']] = null;
598
			}
599
600
			$dbm->release( $conn, $dbname );
601
		}
602
		catch( \Exception $e )
603
		{
604
			$dbm->release( $conn, $dbname );
605
			throw $e;
606
		}
607
608
		if( !empty( $typeIds ) )
609
		{
610
			$typeManager = $this->getObject()->getSubManager( 'type' );
611
			$typeSearch = $typeManager->createSearch();
612
			$typeSearch->setConditions( $typeSearch->compare( '==', 'tag.type.id', array_keys( $typeIds ) ) );
613
			$typeSearch->setSlice( 0, $search->getSliceSize() );
614
			$typeItems = $typeManager->searchItems( $typeSearch );
615
616
			foreach( $map as $id => $row )
617
			{
618
				if( isset( $typeItems[$row['tag.typeid']] ) )
619
				{
620
					$row['tag.type'] = $typeItems[$row['tag.typeid']]->getCode();
621
					$row['tag.typename'] = $typeItems[$row['tag.typeid']]->getName();
622
				}
623
624
				$items[$id] = $this->createItemBase( $row );
625
			}
626
		}
627
628
		return $items;
629
	}
630
631
632
	/**
633
	 * Returns a new manager for tag extensions
634
	 *
635
	 * @param string $manager Name of the sub manager type in lower case
636
	 * @param string|null $name Name of the implementation, will be from
637
	 * configuration (or Default) if null
638
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g tag types, tag lists etc.
639
	 */
640
	public function getSubManager( $manager, $name = null )
641
	{
642
		/** mshop/tag/manager/name
643
		 * Class name of the used tag tag manager implementation
644
		 *
645
		 * Each default tag tag manager can be replaced by an alternative imlementation.
646
		 * To use this implementation, you have to set the last part of the class
647
		 * name as configuration value so the manager factory knows which class it
648
		 * has to instantiate.
649
		 *
650
		 * For example, if the name of the default class is
651
		 *
652
		 *  \Aimeos\MShop\Tag\Manager\Standard
653
		 *
654
		 * and you want to replace it with your own version named
655
		 *
656
		 *  \Aimeos\MShop\Tag\Manager\Mytag
657
		 *
658
		 * then you have to set the this configuration option:
659
		 *
660
		 *  mshop/tag/manager/name = Mytag
661
		 *
662
		 * The value is the last part of your own class name and it's case sensitive,
663
		 * so take care that the configuration value is exactly named like the last
664
		 * part of the class name.
665
		 *
666
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
667
		 * characters are possible! You should always start the last part of the class
668
		 * name with an upper case character and continue only with lower case characters
669
		 * or numbers. Avoid chamel case names like "MyTag"!
670
		 *
671
		 * @param string Last part of the class name
672
		 * @since 2015.12
673
		 * @category Developer
674
		 */
675
676
		/** mshop/tag/manager/decorators/excludes
677
		 * Excludes decorators added by the "common" option from the tag tag manager
678
		 *
679
		 * Decorators extend the functionality of a class by adding new aspects
680
		 * (e.g. log what is currently done), executing the methods of the underlying
681
		 * class only in certain conditions (e.g. only for logged in users) or
682
		 * modify what is returned to the caller.
683
		 *
684
		 * This option allows you to remove a decorator added via
685
		 * "mshop/common/manager/decorators/default" before they are wrapped
686
		 * around the tag tag manager.
687
		 *
688
		 *  mshop/tag/manager/decorators/excludes = array( 'decorator1' )
689
		 *
690
		 * This would remove the decorator named "decorator1" from the list of
691
		 * common decorators ("\Aimeos\MShop\Common\Manager\Decorator\*") added via
692
		 * "mshop/common/manager/decorators/default" for the tag tag manager.
693
		 *
694
		 * @param array List of decorator names
695
		 * @since 2015.12
696
		 * @category Developer
697
		 * @see mshop/common/manager/decorators/default
698
		 * @see mshop/tag/manager/decorators/global
699
		 * @see mshop/tag/manager/decorators/local
700
		 */
701
702
		/** mshop/tag/manager/decorators/global
703
		 * Adds a list of globally available decorators only to the tag tag manager
704
		 *
705
		 * Decorators extend the functionality of a class by adding new aspects
706
		 * (e.g. log what is currently done), executing the methods of the underlying
707
		 * class only in certain conditions (e.g. only for logged in users) or
708
		 * modify what is returned to the caller.
709
		 *
710
		 * This option allows you to wrap global decorators
711
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the tag tag manager.
712
		 *
713
		 *  mshop/tag/manager/decorators/global = array( 'decorator1' )
714
		 *
715
		 * This would add the decorator named "decorator1" defined by
716
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator1" only to the tag controller.
717
		 *
718
		 * @param array List of decorator names
719
		 * @since 2015.12
720
		 * @category Developer
721
		 * @see mshop/common/manager/decorators/default
722
		 * @see mshop/tag/manager/decorators/excludes
723
		 * @see mshop/tag/manager/decorators/local
724
		 */
725
726
		/** mshop/tag/manager/decorators/local
727
		 * Adds a list of local decorators only to the tag tag manager
728
		 *
729
		 * Decorators extend the functionality of a class by adding new aspects
730
		 * (e.g. log what is currently done), executing the methods of the underlying
731
		 * class only in certain conditions (e.g. only for logged in users) or
732
		 * modify what is returned to the caller.
733
		 *
734
		 * This option allows you to wrap local decorators
735
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the tag tag manager.
736
		 *
737
		 *  mshop/tag/manager/decorators/local = array( 'decorator2' )
738
		 *
739
		 * This would add the decorator named "decorator2" defined by
740
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator2" only to the tag
741
		 * controller.
742
		 *
743
		 * @param array List of decorator names
744
		 * @since 2015.12
745
		 * @category Developer
746
		 * @see mshop/common/manager/decorators/default
747
		 * @see mshop/tag/manager/decorators/excludes
748
		 * @see mshop/tag/manager/decorators/global
749
		 */
750
751
		return $this->getSubManagerBase( 'tag', '' . $manager, $name );
752
	}
753
754
755
	/**
756
	 * Creates new tag item object.
757
	 *
758
	 * @see \Aimeos\MShop\Tag\Item\Standard Default tag item
759
	 * @param array $values Possible optional array keys can be given: id, typeid, langid, type, label
760
	 * @return \Aimeos\MShop\Tag\Item\Standard New tag item object
761
	 */
762
	protected function createItemBase( array $values = [] )
763
	{
764
		$values['languageid'] = $this->languageId;
765
766
		return new \Aimeos\MShop\Tag\Item\Standard( $values );
767
	}
768
}
769