Completed
Push — master ( 7f402b...a6068b )
by Aimeos
10:08
created

Standard::getPropertyItems()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 2
nop 1
dl 0
loc 20
rs 9.4285
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-2017
7
 * @package MShop
8
 * @subpackage Attribute
9
 */
10
11
12
namespace Aimeos\MShop\Attribute\Manager;
13
14
15
/**
16
 * Default attribute manager for creating and handling attributes.
17
 * @package MShop
18
 * @subpackage Attribute
19
 */
20
class Standard
21
	extends \Aimeos\MShop\Common\Manager\ListRef\Base
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
22
	implements \Aimeos\MShop\Attribute\Manager\Iface
23
{
24
	use \Aimeos\MShop\Common\Manager\PropertyRef\Traits;
25
26
27
	private $searchConfig = array(
28
		'attribute.id' => array(
29
			'code' => 'attribute.id',
30
			'internalcode' => 'matt."id"',
31
			'label' => 'ID',
32
			'type' => 'integer',
33
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
34
			'public' => false,
35
		),
36
		'attribute.siteid' => array(
37
			'code' => 'attribute.siteid',
38
			'internalcode' => 'matt."siteid"',
39
			'label' => 'Site ID',
40
			'type' => 'integer',
41
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
42
			'public' => false,
43
		),
44
		'attribute.typeid' => array(
45
			'code' => 'attribute.typeid',
46
			'internalcode' => 'matt."typeid"',
47
			'label' => 'Type',
48
			'type' => 'integer',
49
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
50
			'public' => false,
51
		),
52
		'attribute.label' => array(
53
			'code' => 'attribute.label',
54
			'internalcode' => 'matt."label"',
55
			'label' => 'Label',
56
			'type' => 'string',
57
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
58
		),
59
		'attribute.code' => array(
60
			'code' => 'attribute.code',
61
			'internalcode' => 'matt."code"',
62
			'label' => 'Code',
63
			'type' => 'string',
64
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
65
		),
66
		'attribute.domain' => array(
67
			'code' => 'attribute.domain',
68
			'internalcode' => 'matt."domain"',
69
			'label' => 'Domain',
70
			'type' => 'string',
71
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
72
		),
73
		'attribute.position' => array(
74
			'code' => 'attribute.position',
75
			'internalcode' => 'matt."pos"',
76
			'label' => 'Position',
77
			'type' => 'integer',
78
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
79
			'public' => false,
80
		),
81
		'attribute.status' => array(
82
			'code' => 'attribute.status',
83
			'internalcode' => 'matt."status"',
84
			'label' => 'Status',
85
			'type' => 'integer',
86
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
87
		),
88
		'attribute.ctime' => array(
89
			'code' => 'attribute.ctime',
90
			'internalcode' => 'matt."ctime"',
91
			'label' => 'Create date/time',
92
			'type' => 'datetime',
93
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
94
			'public' => false,
95
		),
96
		'attribute.mtime' => array(
97
			'code' => 'attribute.mtime',
98
			'internalcode' => 'matt."mtime"',
99
			'label' => 'Modification date/time',
100
			'type' => 'datetime',
101
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
102
			'public' => false,
103
		),
104
		'attribute.editor' => array(
105
			'code' => 'attribute.editor',
106
			'internalcode' => 'matt."editor"',
107
			'label' => 'Editor',
108
			'type' => 'string',
109
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
110
			'public' => false,
111
		),
112
	);
113
114
115
	/**
116
	 * Initializes the object.
117
	 *
118
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
119
	 */
120
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
121
	{
122
		parent::__construct( $context );
123
		$this->setResourceName( 'db-attribute' );
124
	}
125
126
127
	/**
128
	 * Removes old entries from the storage.
129
	 *
130
	 * @param integer[] $siteids List of IDs for sites whose entries should be deleted
131
	 */
132
	public function cleanup( array $siteids )
133
	{
134
		$path = 'mshop/attribute/manager/submanagers';
135
		foreach( $this->getContext()->getConfig()->get( $path, array( 'type', 'lists' ) ) as $domain ) {
136
			$this->getObject()->getSubManager( $domain )->cleanup( $siteids );
137
		}
138
139
		$this->cleanupBase( $siteids, 'mshop/attribute/manager/standard/delete' );
140
	}
141
142
143
	/**
144
	 * Returns the available manager types
145
	 *
146
	 * @param boolean $withsub Return also the resource type of sub-managers if true
147
	 * @return array Type of the manager and submanagers, subtypes are separated by slashes
148
	 */
149
	public function getResourceType( $withsub = true )
150
	{
151
		$path = 'mshop/attribute/manager/submanagers';
152
153
		return $this->getResourceTypeBase( 'attribute', $path, array( 'type', 'lists' ), $withsub );
154
	}
155
156
157
	/**
158
	 * Returns the attributes that can be used for searching.
159
	 *
160
	 * @param boolean $withsub Return also attributes of sub-managers if true
161
	 * @return array List of attribute items implementing \Aimeos\MW\Criteria\Attribute\Iface
162
	 */
163
	public function getSearchAttributes( $withsub = true )
164
	{
165
		/** mshop/attribute/manager/submanagers
166
		 * List of manager names that can be instantiated by the attribute manager
167
		 *
168
		 * Managers provide a generic interface to the underlying storage.
169
		 * Each manager has or can have sub-managers caring about particular
170
		 * aspects. Each of these sub-managers can be instantiated by its
171
		 * parent manager using the getSubManager() method.
172
		 *
173
		 * The search keys from sub-managers can be normally used in the
174
		 * manager as well. It allows you to search for items of the manager
175
		 * using the search keys of the sub-managers to further limit the
176
		 * retrieved list of items.
177
		 *
178
		 * @param array List of sub-manager names
179
		 * @since 2014.03
180
		 * @category Developer
181
		 */
182
		$path = 'mshop/attribute/manager/submanagers';
183
184
		return $this->getSearchAttributesBase( $this->searchConfig, $path, array( 'type', 'property', 'lists' ), $withsub );
185
	}
186
187
188
	/**
189
	 * Creates a new empty attribute item instance.
190
	 *
191
	 * @return \Aimeos\MShop\Attribute\Item\Iface Creates a blank Attribute item
192
	 */
193
	public function createItem()
194
	{
195
		$values = array( 'attribute.siteid' => $this->getContext()->getLocale()->getSiteId() );
196
		return $this->createItemBase( $values );
197
	}
198
199
200
	/**
201
	 * Returns the item specified by its code and domain/type if necessary
202
	 *
203
	 * @param string $code Code of the item
204
	 * @param string[] $ref List of domains to fetch list items and referenced items for
205
	 * @param string|null $domain Domain of the item if necessary to identify the item uniquely
206
	 * @param string|null $type Type code of the item if necessary to identify the item uniquely
207
	 * @param boolean $default True to add default criteria
208
	 * @return \Aimeos\MShop\Common\Item\Iface Item object
209
	 */
210
	public function findItem( $code, array $ref = [], $domain = null, $type = null, $default = false )
211
	{
212
		$find = array(
213
			'attribute.code' => $code,
214
			'attribute.domain' => $domain,
215
			'attribute.type.code' => $type,
216
			'attribute.type.domain' => $domain,
217
		);
218
		return $this->findItemBase( $find, $ref, $default );
219
	}
220
221
222
	/**
223
	 * Returns the attributes item specified by its ID.
224
	 *
225
	 * @param integer $id Unique ID of the attribute item in the storage
226
	 * @param string[] $ref List of domains to fetch list items and referenced items for
227
	 * @param boolean $default Add default criteria
228
	 * @return \Aimeos\MShop\Attribute\Item\Iface Returns the attribute item of the given id
229
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
230
	 */
231
	public function getItem( $id, array $ref = [], $default = false )
232
	{
233
		return $this->getItemBase( 'attribute.id', $id, $ref, $default );
234
	}
235
236
237
	/**
238
	 * Saves an attribute item to the storage.
239
	 *
240
	 * @param \Aimeos\MShop\Common\Item\Iface $item Attribute item
241
	 * @param boolean $fetch True if the new ID should be returned in the item
242
	 * @return \Aimeos\MShop\Common\Item\Iface $item Updated item including the generated ID
0 ignored issues
show
Documentation introduced by
Should the return type not be \Aimeos\MShop\Common\Item\ListRef\Iface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
243
	 * @throws \Aimeos\MShop\Attribute\Exception If Attribute couldn't be saved
244
	 */
245
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
246
	{
247
		$iface = '\\Aimeos\\MShop\\Attribute\\Item\\Iface';
248
		if( !( $item instanceof $iface ) ) {
249
			throw new \Aimeos\MShop\Attribute\Exception( sprintf( 'Object is not of required type "%1$s"', $iface ) );
250
		}
251
252
		if( !$item->isModified() )
253
		{
254
			$item = $this->savePropertyItems( $item, 'attribute' );
0 ignored issues
show
Documentation introduced by
$item is of type object<Aimeos\MShop\Common\Item\Iface>, but the function expects a object<Aimeos\MShop\Comm...Item\PropertyRef\Iface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
255
			return $this->saveRefItems( $item, 'attribute' );
0 ignored issues
show
Documentation introduced by
$item is of type object<Aimeos\MShop\Comm...Item\PropertyRef\Iface>, but the function expects a object<Aimeos\MShop\Common\Item\ListRef\Iface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
256
		}
257
258
		$context = $this->getContext();
259
260
		$dbm = $context->getDatabaseManager();
261
		$dbname = $this->getResourceName();
262
		$conn = $dbm->acquire( $dbname );
263
264
		try
265
		{
266
			$id = $item->getId();
267
			$date = date( 'Y-m-d H:i:s' );
268
269
			if( $id === null )
270
			{
271
				/** mshop/attribute/manager/standard/insert/mysql
272
				 * Inserts a new attribute record into the database table
273
				 *
274
				 * @see mshop/attribute/manager/standard/insert/ansi
275
				 */
276
277
				/** mshop/attribute/manager/standard/insert/ansi
278
				 * Inserts a new attribute record into the database table
279
				 *
280
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
281
				 * the database and the newly created ID retrieved afterwards
282
				 * using the "newid" SQL statement.
283
				 *
284
				 * The SQL statement must be a string suitable for being used as
285
				 * prepared statement. It must include question marks for binding
286
				 * the values from the attribute item to the statement before they are
287
				 * sent to the database server. The number of question marks must
288
				 * be the same as the number of columns listed in the INSERT
289
				 * statement. The order of the columns must correspond to the
290
				 * order in the saveItems() method, so the correct values are
291
				 * bound to the columns.
292
				 *
293
				 * The SQL statement should conform to the ANSI standard to be
294
				 * compatible with most relational database systems. This also
295
				 * includes using double quotes for table and column names.
296
				 *
297
				 * @param string SQL statement for inserting records
298
				 * @since 2014.03
299
				 * @category Developer
300
				 * @see mshop/attribute/manager/standard/update/ansi
301
				 * @see mshop/attribute/manager/standard/newid/ansi
302
				 * @see mshop/attribute/manager/standard/delete/ansi
303
				 * @see mshop/attribute/manager/standard/search/ansi
304
				 * @see mshop/attribute/manager/standard/count/ansi
305
				 */
306
				$path = 'mshop/attribute/manager/standard/insert';
307
			}
308
			else
309
			{
310
				/** mshop/attribute/manager/standard/update/mysql
311
				 * Updates an existing attribute record in the database
312
				 *
313
				 * @see mshop/attribute/manager/standard/update/ansi
314
				 */
315
316
				/** mshop/attribute/manager/standard/update/ansi
317
				 * Updates an existing attribute record in the database
318
				 *
319
				 * Items which already have an ID (i.e. the ID is not NULL) will
320
				 * be updated in the database.
321
				 *
322
				 * The SQL statement must be a string suitable for being used as
323
				 * prepared statement. It must include question marks for binding
324
				 * the values from the attribute item to the statement before they are
325
				 * sent to the database server. The order of the columns must
326
				 * correspond to the order in the saveItems() method, so the
327
				 * correct values are bound to the columns.
328
				 *
329
				 * The SQL statement should conform to the ANSI standard to be
330
				 * compatible with most relational database systems. This also
331
				 * includes using double quotes for table and column names.
332
				 *
333
				 * @param string SQL statement for updating records
334
				 * @since 2014.03
335
				 * @category Developer
336
				 * @see mshop/attribute/manager/standard/insert/ansi
337
				 * @see mshop/attribute/manager/standard/newid/ansi
338
				 * @see mshop/attribute/manager/standard/delete/ansi
339
				 * @see mshop/attribute/manager/standard/search/ansi
340
				 * @see mshop/attribute/manager/standard/count/ansi
341
				 */
342
				$path = 'mshop/attribute/manager/standard/update';
343
			}
344
345
			$stmt = $this->getCachedStatement( $conn, $path );
346
347
			$stmt->bind( 1, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
348
			$stmt->bind( 2, $item->getDomain() );
349
			$stmt->bind( 3, $item->getCode() );
350
			$stmt->bind( 4, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
351
			$stmt->bind( 5, $item->getPosition(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
352
			$stmt->bind( 6, $item->getLabel() );
353
			$stmt->bind( 7, $date ); // mtime
354
			$stmt->bind( 8, $context->getEditor() );
355
			$stmt->bind( 9, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
356
357
			if( $id !== null ) {
358
				$stmt->bind( 10, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
359
				$item->setId( $id );
360
			} else {
361
				$stmt->bind( 10, $date ); // ctime
362
			}
363
364
			$stmt->execute()->finish();
365
366
			if( $id === null && $fetch === true )
367
			{
368
				/** mshop/attribute/manager/standard/newid/mysql
369
				 * Retrieves the ID generated by the database when inserting a new record
370
				 *
371
				 * @see mshop/attribute/manager/standard/newid/ansi
372
				 */
373
374
				/** mshop/attribute/manager/standard/newid/ansi
375
				 * Retrieves the ID generated by the database when inserting a new record
376
				 *
377
				 * As soon as a new record is inserted into the database table,
378
				 * the database server generates a new and unique identifier for
379
				 * that record. This ID can be used for retrieving, updating and
380
				 * deleting that specific record from the table again.
381
				 *
382
				 * For MySQL:
383
				 *  SELECT LAST_INSERT_ID()
384
				 * For PostgreSQL:
385
				 *  SELECT currval('seq_matt_id')
386
				 * For SQL Server:
387
				 *  SELECT SCOPE_IDENTITY()
388
				 * For Oracle:
389
				 *  SELECT "seq_matt_id".CURRVAL FROM DUAL
390
				 *
391
				 * There's no way to retrive the new ID by a SQL statements that
392
				 * fits for most database servers as they implement their own
393
				 * specific way.
394
				 *
395
				 * @param string SQL statement for retrieving the last inserted record ID
396
				 * @since 2014.03
397
				 * @category Developer
398
				 * @see mshop/attribute/manager/standard/insert/ansi
399
				 * @see mshop/attribute/manager/standard/update/ansi
400
				 * @see mshop/attribute/manager/standard/delete/ansi
401
				 * @see mshop/attribute/manager/standard/search/ansi
402
				 * @see mshop/attribute/manager/standard/count/ansi
403
				 */
404
				$path = 'mshop/attribute/manager/standard/newid';
405
				$item->setId( $this->newId( $conn, $path ) );
406
			}
407
408
			$dbm->release( $conn, $dbname );
409
		}
410
		catch( \Exception $e )
411
		{
412
			$dbm->release( $conn, $dbname );
413
			throw $e;
414
		}
415
416
		$item = $this->savePropertyItems( $item, 'attribute' );
0 ignored issues
show
Documentation introduced by
$item is of type object<Aimeos\MShop\Common\Item\Iface>, but the function expects a object<Aimeos\MShop\Comm...Item\PropertyRef\Iface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
417
		return $this->saveRefItems( $item, 'attribute' );
0 ignored issues
show
Documentation introduced by
$item is of type object<Aimeos\MShop\Comm...Item\PropertyRef\Iface>, but the function expects a object<Aimeos\MShop\Common\Item\ListRef\Iface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
418
	}
419
420
421
	/**
422
	 * Removes multiple items specified by ids in the array.
423
	 *
424
	 * @param array $ids List of IDs
425
	 */
426
	public function deleteItems( array $ids )
427
	{
428
		/** mshop/attribute/manager/standard/delete/mysql
429
		 * Deletes the items matched by the given IDs from the database
430
		 *
431
		 * @see mshop/attribute/manager/standard/delete/ansi
432
		 */
433
434
		/** mshop/attribute/manager/standard/delete/ansi
435
		 * Deletes the items matched by the given IDs from the database
436
		 *
437
		 * Removes the records specified by the given IDs from the attribute database.
438
		 * The records must be from the site that is configured via the
439
		 * context item.
440
		 *
441
		 * The ":cond" placeholder is replaced by the name of the ID column and
442
		 * the given ID or list of IDs while the site ID is bound to the question
443
		 * mark.
444
		 *
445
		 * The SQL statement should conform to the ANSI standard to be
446
		 * compatible with most relational database systems. This also
447
		 * includes using double quotes for table and column names.
448
		 *
449
		 * @param string SQL statement for deleting items
450
		 * @since 2014.03
451
		 * @category Developer
452
		 * @see mshop/attribute/manager/standard/insert/ansi
453
		 * @see mshop/attribute/manager/standard/update/ansi
454
		 * @see mshop/attribute/manager/standard/newid/ansi
455
		 * @see mshop/attribute/manager/standard/search/ansi
456
		 * @see mshop/attribute/manager/standard/count/ansi
457
		 */
458
		$path = 'mshop/attribute/manager/standard/delete';
459
		$this->deleteItemsBase( $ids, $path );
460
	}
461
462
463
	/**
464
	 * Searches for attribute items based on the given criteria.
465
	 *
466
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
467
	 * @param string[] $ref List of domains to fetch list items and referenced items for
468
	 * @param integer|null &$total Number of items that are available in total
469
	 * @return array List of attribute items implementing \Aimeos\MShop\Attribute\Item\Iface
470
	 */
471
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
472
	{
473
		$map = $typeIds = [];
474
		$context = $this->getContext();
475
476
		$dbm = $context->getDatabaseManager();
477
		$dbname = $this->getResourceName();
478
		$conn = $dbm->acquire( $dbname );
479
480
		try
481
		{
482
			$required = array( 'attribute' );
483
484
			/** mshop/attribute/manager/sitemode
485
			 * Mode how items from levels below or above in the site tree are handled
486
			 *
487
			 * By default, only items from the current site are fetched from the
488
			 * storage. If the ai-sites extension is installed, you can create a
489
			 * tree of sites. Then, this setting allows you to define for the
490
			 * whole attribute domain if items from parent sites are inherited,
491
			 * sites from child sites are aggregated or both.
492
			 *
493
			 * Available constants for the site mode are:
494
			 * * 0 = only items from the current site
495
			 * * 1 = inherit items from parent sites
496
			 * * 2 = aggregate items from child sites
497
			 * * 3 = inherit and aggregate items at the same time
498
			 *
499
			 * You also need to set the mode in the locale manager
500
			 * (mshop/locale/manager/standard/sitelevel) to one of the constants.
501
			 * If you set it to the same value, it will work as described but you
502
			 * can also use different modes. For example, if inheritance and
503
			 * aggregation is configured the locale manager but only inheritance
504
			 * in the domain manager because aggregating items makes no sense in
505
			 * this domain, then items wil be only inherited. Thus, you have full
506
			 * control over inheritance and aggregation in each domain.
507
			 *
508
			 * @param integer Constant from Aimeos\MShop\Locale\Manager\Base class
509
			 * @category Developer
510
			 * @since 2018.01
511
			 * @see mshop/locale/manager/standard/sitelevel
512
			 */
513
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
514
			$level = $context->getConfig()->get( 'mshop/attribute/manager/sitemode', $level );
515
516
			/** mshop/attribute/manager/standard/search/mysql
517
			 * Retrieves the records matched by the given criteria in the database
518
			 *
519
			 * @see mshop/attribute/manager/standard/search/ansi
520
			 */
521
522
			/** mshop/attribute/manager/standard/search/ansi
523
			 * Retrieves the records matched by the given criteria in the database
524
			 *
525
			 * Fetches the records matched by the given criteria from the attribute
526
			 * database. The records must be from one of the sites that are
527
			 * configured via the context item. If the current site is part of
528
			 * a tree of sites, the SELECT statement can retrieve all records
529
			 * from the current site and the complete sub-tree of sites.
530
			 *
531
			 * As the records can normally be limited by criteria from sub-managers,
532
			 * their tables must be joined in the SQL context. This is done by
533
			 * using the "internaldeps" property from the definition of the ID
534
			 * column of the sub-managers. These internal dependencies specify
535
			 * the JOIN between the tables and the used columns for joining. The
536
			 * ":joins" placeholder is then replaced by the JOIN strings from
537
			 * the sub-managers.
538
			 *
539
			 * To limit the records matched, conditions can be added to the given
540
			 * criteria object. It can contain comparisons like column names that
541
			 * must match specific values which can be combined by AND, OR or NOT
542
			 * operators. The resulting string of SQL conditions replaces the
543
			 * ":cond" placeholder before the statement is sent to the database
544
			 * server.
545
			 *
546
			 * If the records that are retrieved should be ordered by one or more
547
			 * columns, the generated string of column / sort direction pairs
548
			 * replaces the ":order" placeholder. In case no ordering is required,
549
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
550
			 * markers is removed to speed up retrieving the records. Columns of
551
			 * sub-managers can also be used for ordering the result set but then
552
			 * no index can be used.
553
			 *
554
			 * The number of returned records can be limited and can start at any
555
			 * number between the begining and the end of the result set. For that
556
			 * the ":size" and ":start" placeholders are replaced by the
557
			 * corresponding values from the criteria object. The default values
558
			 * are 0 for the start and 100 for the size value.
559
			 *
560
			 * The SQL statement should conform to the ANSI standard to be
561
			 * compatible with most relational database systems. This also
562
			 * includes using double quotes for table and column names.
563
			 *
564
			 * @param string SQL statement for searching items
565
			 * @since 2014.03
566
			 * @category Developer
567
			 * @see mshop/attribute/manager/standard/insert/ansi
568
			 * @see mshop/attribute/manager/standard/update/ansi
569
			 * @see mshop/attribute/manager/standard/newid/ansi
570
			 * @see mshop/attribute/manager/standard/delete/ansi
571
			 * @see mshop/attribute/manager/standard/count/ansi
572
			 */
573
			$cfgPathSearch = 'mshop/attribute/manager/standard/search';
574
575
			/** mshop/attribute/manager/standard/count/mysql
576
			 * Counts the number of records matched by the given criteria in the database
577
			 *
578
			 * @see mshop/attribute/manager/standard/count/ansi
579
			 */
580
581
			/** mshop/attribute/manager/standard/count/ansi
582
			 * Counts the number of records matched by the given criteria in the database
583
			 *
584
			 * Counts all records matched by the given criteria from the attribute
585
			 * database. The records must be from one of the sites that are
586
			 * configured via the context item. If the current site is part of
587
			 * a tree of sites, the statement can count all records from the
588
			 * current site and the complete sub-tree of sites.
589
			 *
590
			 * As the records can normally be limited by criteria from sub-managers,
591
			 * their tables must be joined in the SQL context. This is done by
592
			 * using the "internaldeps" property from the definition of the ID
593
			 * column of the sub-managers. These internal dependencies specify
594
			 * the JOIN between the tables and the used columns for joining. The
595
			 * ":joins" placeholder is then replaced by the JOIN strings from
596
			 * the sub-managers.
597
			 *
598
			 * To limit the records matched, conditions can be added to the given
599
			 * criteria object. It can contain comparisons like column names that
600
			 * must match specific values which can be combined by AND, OR or NOT
601
			 * operators. The resulting string of SQL conditions replaces the
602
			 * ":cond" placeholder before the statement is sent to the database
603
			 * server.
604
			 *
605
			 * Both, the strings for ":joins" and for ":cond" are the same as for
606
			 * the "search" SQL statement.
607
			 *
608
			 * Contrary to the "search" statement, it doesn't return any records
609
			 * but instead the number of records that have been found. As counting
610
			 * thousands of records can be a long running task, the maximum number
611
			 * of counted records is limited for performance reasons.
612
			 *
613
			 * The SQL statement should conform to the ANSI standard to be
614
			 * compatible with most relational database systems. This also
615
			 * includes using double quotes for table and column names.
616
			 *
617
			 * @param string SQL statement for counting items
618
			 * @since 2014.03
619
			 * @category Developer
620
			 * @see mshop/attribute/manager/standard/insert/ansi
621
			 * @see mshop/attribute/manager/standard/update/ansi
622
			 * @see mshop/attribute/manager/standard/newid/ansi
623
			 * @see mshop/attribute/manager/standard/delete/ansi
624
			 * @see mshop/attribute/manager/standard/search/ansi
625
			 */
626
			$cfgPathCount = 'mshop/attribute/manager/standard/count';
627
628
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
629
630
			while( ( $row = $results->fetch() ) !== false )
631
			{
632
				$map[$row['attribute.id']] = $row;
633
				$typeIds[$row['attribute.typeid']] = null;
634
			}
635
636
			$dbm->release( $conn, $dbname );
637
		}
638
		catch( \Exception $e )
639
		{
640
			$dbm->release( $conn, $dbname );
641
			throw $e;
642
		}
643
644
		if( !empty( $typeIds ) )
645
		{
646
			$typeManager = $this->getObject()->getSubManager( 'type' );
647
			$typeSearch = $typeManager->createSearch();
648
			$typeSearch->setConditions( $typeSearch->compare( '==', 'attribute.type.id', array_keys( $typeIds ) ) );
649
			$typeSearch->setSlice( 0, $search->getSliceSize() );
650
			$typeItems = $typeManager->searchItems( $typeSearch );
651
652
			foreach( $map as $id => $row )
653
			{
654
				if( isset( $typeItems[$row['attribute.typeid']] ) )
655
				{
656
					$map[$id]['attribute.type'] = $typeItems[$row['attribute.typeid']]->getCode();
657
					$map[$id]['attribute.typename'] = $typeItems[$row['attribute.typeid']]->getName();
658
				}
659
			}
660
		}
661
662
		$propItems = $this->getPropertyItems( array_keys( $map ), 'attribute' );
663
664
		return $this->buildItems( $map, null, 'attribute', $propItems );
665
	}
666
667
668
	/**
669
	 * creates a search object and sets base criteria
670
	 *
671
	 * @param boolean $default
672
	 * @return \Aimeos\MW\Criteria\Iface
673
	 */
674
	public function createSearch( $default = false )
675
	{
676
		if( $default === true ) {
677
			return $this->createSearchBase( 'attribute' );
678
		}
679
680
		return parent::createSearch();
681
	}
682
683
684
	/**
685
	 * Returns a new manager for attribute extensions
686
	 *
687
	 * @param string $manager Name of the sub manager type in lower case
688
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
689
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g Type, List's etc.
690
	 */
691
	public function getSubManager( $manager, $name = null )
692
	{
693
		return $this->getSubManagerBase( 'attribute', $manager, $name );
694
	}
695
696
697
	/**
698
	 * Creates a new attribute item instance.
699
	 *
700
	 * @param array $values Associative list of key/value pairs
701
	 * @param array $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
702
	 * @param array $refItems List of items implementing \Aimeos\MShop\Text\Item\Iface
703
	 * @param array $propertyItems List of items implementing \Aimeos\MShop\Common\Item\Property\Iface
704
	 * @return \Aimeos\MShop\Attribute\Item\Iface New attribute item
705
	 */
706
	protected function createItemBase( array $values = [], array $listItems = [],
707
		array $refItems = [], array $propertyItems = [] )
708
	{
709
		return new \Aimeos\MShop\Attribute\Item\Standard( $values, $listItems, $refItems, $propertyItems );
710
	}
711
}
712