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

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

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