Completed
Push — master ( 6b3f15...fe5cb0 )
by Aimeos
09:22
created

Standard::findItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2017
7
 * @package MShop
8
 * @subpackage Locale
9
 */
10
11
12
namespace Aimeos\MShop\Locale\Manager\Language;
13
14
15
/**
16
 * Default implementation for managing languages.
17
 *
18
 * @package MShop
19
 * @subpackage Locale
20
 */
21
class Standard
22
	extends \Aimeos\MShop\Common\Manager\Base
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
23
	implements \Aimeos\MShop\Locale\Manager\Language\Iface
24
{
25
	private $searchConfig = array(
26
		'locale.language.id' => array(
27
			'code' => 'locale.language.id',
28
			'internalcode' => 'mlocla."id"',
29
			'internaldeps' => array( 'LEFT JOIN "mshop_locale_language" AS mlocla ON (mloc."langid" = mlocla."id")' ),
30
			'label' => 'Language ID',
31
			'type' => 'string',
32
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
33
			'public' => false,
34
		),
35
		'locale.language.siteid' => array(
36
			'code' => 'locale.language.siteid',
37
			'internalcode' => 'mlocla."siteid"',
38
			'label' => 'Language site ID',
39
			'type' => 'string',
40
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
41
			'public' => false,
42
		),
43
		'locale.language.label' => array(
44
			'code' => 'locale.language.label',
45
			'internalcode' => 'mlocla."label"',
46
			'label' => 'Language label',
47
			'type' => 'string',
48
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
49
		),
50
		'locale.language.code' => array(
51
			'code' => 'locale.language.code',
52
			'internalcode' => 'mlocla."id"',
53
			'label' => 'Language code',
54
			'type' => 'string',
55
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
56
		),
57
		'locale.language.status' => array(
58
			'code' => 'locale.language.status',
59
			'internalcode' => 'mlocla."status"',
60
			'label' => 'Language status',
61
			'type' => 'integer',
62
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
63
		),
64
		'locale.language.ctime' => array(
65
			'code' => 'locale.language.ctime',
66
			'internalcode' => 'mlocla."ctime"',
67
			'label' => 'Language create date/time',
68
			'type' => 'datetime',
69
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
70
			'public' => false,
71
		),
72
		'locale.language.mtime' => array(
73
			'code' => 'locale.language.mtime',
74
			'internalcode' => 'mlocla."mtime"',
75
			'label' => 'Language modify date/time',
76
			'type' => 'datetime',
77
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
78
			'public' => false,
79
		),
80
		'locale.language.editor' => array(
81
			'code' => 'locale.language.editor',
82
			'internalcode' => 'mlocla."editor"',
83
			'label' => 'Language editor',
84
			'type' => 'string',
85
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
86
			'public' => false,
87
		),
88
	);
89
90
91
	/**
92
	 * Initializes the object.
93
	 *
94
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
95
	 */
96
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
97
	{
98
		parent::__construct( $context );
99
		$this->setResourceName( 'db-locale' );
100
	}
101
102
103
	/**
104
	 * Creates a new language object.
105
	 *
106
	 * @return \Aimeos\MShop\Locale\Item\Language\Standard
107
	 */
108
	public function createItem()
109
	{
110
		try {
111
			$values = array( 'locale.language.siteid' => $this->getContext()->getLocale()->getSiteId() );
112
		} catch( \Exception $ex ) {
113
			$values = array( 'locale.language.siteid' => null );
114
		}
115
116
		return $this->createItemBase( $values );
117
	}
118
119
120
	/**
121
	 * Saves the language object to the storage.
122
	 *
123
	 * @param \Aimeos\MShop\Common\Item\Iface $item Language object
124
	 * @param boolean $fetch True if the new ID should be returned in the item
125
	 * @return \Aimeos\MShop\Common\Item\Iface $item Updated item including the generated ID
126
	 */
127
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
128
	{
129
		$iface = '\\Aimeos\\MShop\\Locale\\Item\\Language\\Iface';
130
		if( !( $item instanceof $iface ) ) {
131
			throw new \Aimeos\MShop\Locale\Exception( sprintf( 'Object is not of required type "%1$s"', $iface ) );
132
		}
133
134
		if( !$item->isModified() ) {
135
			return $item;
136
		}
137
138
		$context = $this->getContext();
139
140
		$dbm = $context->getDatabaseManager();
141
		$dbname = $this->getResourceName();
142
		$conn = $dbm->acquire( $dbname );
143
144
		try
145
		{
146
			$id = $item->getId();
147
			$date = date( 'Y-m-d H:i:s' );
148
149
			if( $id === null )
150
			{
151
				/** mshop/locale/manager/language/standard/insert/mysql
152
				 * Inserts a new language record into the database table
153
				 *
154
				 * @see mshop/locale/manager/language/standard/insert/ansi
155
				 */
156
157
				/** mshop/locale/manager/language/standard/insert/ansi
158
				 * Inserts a new language record into the database table
159
				 *
160
				 * The SQL statement must be a string suitable for being used as
161
				 * prepared statement. It must include question marks for binding
162
				 * the values from the language item to the statement before they are
163
				 * sent to the database server. The number of question marks must
164
				 * be the same as the number of columns listed in the INSERT
165
				 * statement. The order of the columns must correspond to the
166
				 * order in the saveItems() method, so the correct values are
167
				 * bound to the columns.
168
				 *
169
				 * The SQL statement should conform to the ANSI standard to be
170
				 * compatible with most relational database systems. This also
171
				 * includes using double quotes for table and column names.
172
				 *
173
				 * @param string SQL statement for inserting records
174
				 * @since 2014.03
175
				 * @category Developer
176
				 * @see mshop/locale/manager/language/standard/update/ansi
177
				 * @see mshop/locale/manager/language/standard/delete/ansi
178
				 * @see mshop/locale/manager/language/standard/search/ansi
179
				 * @see mshop/locale/manager/language/standard/count/ansi
180
				 */
181
				$path = 'mshop/locale/manager/language/standard/insert';
182
			}
183
			else
184
			{
185
				/** mshop/locale/manager/language/standard/update/mysql
186
				 * Updates an existing language record in the database
187
				 *
188
				 * @see mshop/locale/manager/language/standard/update/ansi
189
				 */
190
191
				/** mshop/locale/manager/language/standard/update/ansi
192
				 * Updates an existing language record in the database
193
				 *
194
				 * The SQL statement must be a string suitable for being used as
195
				 * prepared statement. It must include question marks for binding
196
				 * the values from the language item to the statement before they are
197
				 * sent to the database server. The order of the columns must
198
				 * correspond to the order in the saveItems() method, so the
199
				 * correct values are 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 updating records
206
				 * @since 2014.03
207
				 * @category Developer
208
				 * @see mshop/locale/manager/language/standard/insert/ansi
209
				 * @see mshop/locale/manager/language/standard/delete/ansi
210
				 * @see mshop/locale/manager/language/standard/search/ansi
211
				 * @see mshop/locale/manager/language/standard/count/ansi
212
				 */
213
				$path = 'mshop/locale/manager/language/standard/update';
214
			}
215
216
			$stmt = $this->getCachedStatement( $conn, $path );
217
218
			$stmt->bind( 1, $item->getLabel() );
219
			$stmt->bind( 2, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
220
			$stmt->bind( 3, $item->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
221
			$stmt->bind( 4, $date ); // mtime
222
			$stmt->bind( 5, $context->getEditor() );
223
			// code and ID are identical after saving and ID is the flag to detect updates or inserts
224
			$stmt->bind( 6, $item->getCode() );
225
226
			if( $id === null ) {
227
				$stmt->bind( 7, $date ); // ctime
228
			}
229
230
			$stmt->execute()->finish();
231
232
			$item->setId( $item->getCode() ); // set modified flag to false
233
234
			$dbm->release( $conn, $dbname );
235
		}
236
		catch( \Exception $e )
237
		{
238
			$dbm->release( $conn, $dbname );
239
			throw $e;
240
		}
241
242
		return $item;
243
	}
244
245
246
	/**
247
	 * Removes multiple items specified by ids in the array.
248
	 *
249
	 * @param array $ids List of IDs
250
	 */
251
	public function deleteItems( array $ids )
252
	{
253
		/** mshop/locale/manager/language/standard/delete/mysql
254
		 * Deletes the items matched by the given IDs from the database
255
		 *
256
		 * @see mshop/locale/manager/language/standard/delete/ansi
257
		 */
258
259
		/** mshop/locale/manager/language/standard/delete/ansi
260
		 * Deletes the items matched by the given IDs from the database
261
		 *
262
		 * Removes the language records specified by the given IDs from the
263
		 * locale database. The records must be from the site that is configured
264
		 * via the context item.
265
		 *
266
		 * The ":cond" placeholder is replaced by the name of the ID column and
267
		 * the given ID or list of IDs while the site ID is bound to the question
268
		 * mark.
269
		 *
270
		 * The SQL statement should conform to the ANSI standard to be
271
		 * compatible with most relational database systems. This also
272
		 * includes using double quotes for table and column names.
273
		 *
274
		 * @param string SQL statement for deleting items
275
		 * @since 2014.03
276
		 * @category Developer
277
		 * @see mshop/locale/manager/language/standard/insert/ansi
278
		 * @see mshop/locale/manager/language/standard/update/ansi
279
		 * @see mshop/locale/manager/language/standard/search/ansi
280
		 * @see mshop/locale/manager/language/standard/count/ansi
281
		 */
282
		$path = 'mshop/locale/manager/language/standard/delete';
283
		$this->deleteItemsBase( $ids, $path );
284
	}
285
286
287
	/**
288
	 * Create a Language object from a given Language ID/Key.
289
	 *
290
	 * @param string $id Language id to create the Language object
291
	 * @param string[] $ref List of domains to fetch list items and referenced items for
292
	 * @return \Aimeos\MShop\Locale\Item\Language\Iface Returns the language item of the given id
293
	 * @param boolean $default Add default criteria
294
	 * @throws \Aimeos\MW\DB\Exception If language object couldn't be fetched
295
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
296
	 */
297
	public function getItem( $id, array $ref = [], $default = false )
298
	{
299
		return $this->getItemBase( 'locale.language.id', $id, $ref, $default );
300
	}
301
302
303
	/**
304
	 * Returns the available manager types
305
	 *
306
	 * @param boolean $withsub Return also the resource type of sub-managers if true
307
	 * @return array Type of the manager and submanagers, subtypes are separated by slashes
308
	 */
309
	public function getResourceType( $withsub = true )
310
	{
311
		$path = 'mshop/locale/manager/language/submanagers';
312
313
		return $this->getResourceTypeBase( 'locale/language', $path, [], $withsub );
314
	}
315
316
317
	/**
318
	 * Returns the attributes that can be used for searching.
319
	 *
320
	 * @param boolean $withsub Return also attributes of sub-managers if true
321
	 * @return array List of attribute items implementing \Aimeos\MW\Criteria\Attribute\Iface
322
	 */
323
	public function getSearchAttributes( $withsub = true )
324
	{
325
		/** mshop/locale/manager/language/submanagers
326
		 * List of manager names that can be instantiated by the locale language manager
327
		 *
328
		 * Managers provide a generic interface to the underlying storage.
329
		 * Each manager has or can have sub-managers caring about particular
330
		 * aspects. Each of these sub-managers can be instantiated by its
331
		 * parent manager using the getSubManager() method.
332
		 *
333
		 * The search keys from sub-managers can be normally used in the
334
		 * manager as well. It allows you to search for items of the manager
335
		 * using the search keys of the sub-managers to further limit the
336
		 * retrieved list of items.
337
		 *
338
		 * @param array List of sub-manager names
339
		 * @since 2014.03
340
		 * @category Developer
341
		 */
342
		$path = 'mshop/locale/manager/language/submanagers';
343
344
		return $this->getSearchAttributesBase( $this->searchConfig, $path, [], $withsub );
345
	}
346
347
348
	/**
349
	 * Returns a new sub manager of the given type and name.
350
	 *
351
	 * @param string $manager Name of the sub manager type in lower case
352
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
353
	 * @return \Aimeos\MShop\Locale\Manager\Iface manager
354
	 */
355
	public function getSubManager( $manager, $name = null )
356
	{
357
		/** mshop/locale/manager/language/name
358
		 * Class name of the used locale language manager implementation
359
		 *
360
		 * Each default locale language manager can be replaced by an alternative imlementation.
361
		 * To use this implementation, you have to set the last part of the class
362
		 * name as configuration value so the manager factory knows which class it
363
		 * has to instantiate.
364
		 *
365
		 * For example, if the name of the default class is
366
		 *
367
		 *  \Aimeos\MShop\Locale\Manager\Language\Standard
368
		 *
369
		 * and you want to replace it with your own version named
370
		 *
371
		 *  \Aimeos\MShop\Locale\Manager\Language\Mylanguage
372
		 *
373
		 * then you have to set the this configuration option:
374
		 *
375
		 *  mshop/locale/manager/language/name = Mylanguage
376
		 *
377
		 * The value is the last part of your own class name and it's case sensitive,
378
		 * so take care that the configuration value is exactly named like the last
379
		 * part of the class name.
380
		 *
381
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
382
		 * characters are possible! You should always start the last part of the class
383
		 * name with an upper case character and continue only with lower case characters
384
		 * or numbers. Avoid chamel case names like "MyLanguage"!
385
		 *
386
		 * @param string Last part of the class name
387
		 * @since 2014.03
388
		 * @category Developer
389
		 */
390
391
		/** mshop/locale/manager/language/decorators/excludes
392
		 * Excludes decorators added by the "common" option from the locale language manager
393
		 *
394
		 * Decorators extend the functionality of a class by adding new aspects
395
		 * (e.g. log what is currently done), executing the methods of the underlying
396
		 * class only in certain conditions (e.g. only for logged in users) or
397
		 * modify what is returned to the caller.
398
		 *
399
		 * This option allows you to remove a decorator added via
400
		 * "mshop/common/manager/decorators/default" before they are wrapped
401
		 * around the locale language manager.
402
		 *
403
		 *  mshop/locale/manager/language/decorators/excludes = array( 'decorator1' )
404
		 *
405
		 * This would remove the decorator named "decorator1" from the list of
406
		 * common decorators ("\Aimeos\MShop\Common\Manager\Decorator\*") added via
407
		 * "mshop/common/manager/decorators/default" for the locale language manager.
408
		 *
409
		 * @param array List of decorator names
410
		 * @since 2014.03
411
		 * @category Developer
412
		 * @see mshop/common/manager/decorators/default
413
		 * @see mshop/locale/manager/language/decorators/global
414
		 * @see mshop/locale/manager/language/decorators/local
415
		 */
416
417
		/** mshop/locale/manager/language/decorators/global
418
		 * Adds a list of globally available decorators only to the locale language manager
419
		 *
420
		 * Decorators extend the functionality of a class by adding new aspects
421
		 * (e.g. log what is currently done), executing the methods of the underlying
422
		 * class only in certain conditions (e.g. only for logged in users) or
423
		 * modify what is returned to the caller.
424
		 *
425
		 * This option allows you to wrap global decorators
426
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the locale language manager.
427
		 *
428
		 *  mshop/locale/manager/language/decorators/global = array( 'decorator1' )
429
		 *
430
		 * This would add the decorator named "decorator1" defined by
431
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator1" only to the locale controller.
432
		 *
433
		 * @param array List of decorator names
434
		 * @since 2014.03
435
		 * @category Developer
436
		 * @see mshop/common/manager/decorators/default
437
		 * @see mshop/locale/manager/language/decorators/excludes
438
		 * @see mshop/locale/manager/language/decorators/local
439
		 */
440
441
		/** mshop/locale/manager/language/decorators/local
442
		 * Adds a list of local decorators only to the locale language manager
443
		 *
444
		 * Decorators extend the functionality of a class by adding new aspects
445
		 * (e.g. log what is currently done), executing the methods of the underlying
446
		 * class only in certain conditions (e.g. only for logged in users) or
447
		 * modify what is returned to the caller.
448
		 *
449
		 * This option allows you to wrap local decorators
450
		 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the locale language manager.
451
		 *
452
		 *  mshop/locale/manager/language/decorators/local = array( 'decorator2' )
453
		 *
454
		 * This would add the decorator named "decorator2" defined by
455
		 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator2" only to the locale
456
		 * controller.
457
		 *
458
		 * @param array List of decorator names
459
		 * @since 2014.03
460
		 * @category Developer
461
		 * @see mshop/common/manager/decorators/default
462
		 * @see mshop/locale/manager/language/decorators/excludes
463
		 * @see mshop/locale/manager/language/decorators/global
464
		 */
465
466
		return $this->getSubManagerBase( 'locale', 'language/' . $manager, $name );
467
	}
468
469
470
	/**
471
	 * Returns the item specified by its code and domain/type if necessary
472
	 *
473
	 * @param string $code Code of the item
474
	 * @param string[] $ref List of domains to fetch list items and referenced items for
475
	 * @param string|null $domain Domain of the item if necessary to identify the item uniquely
476
	 * @param string|null $type Type code of the item if necessary to identify the item uniquely
477
	 * @return \Aimeos\MShop\Common\Item\Iface Item object
478
	 */
479
	public function findItem( $code, array $ref = [], $domain = null, $type = null )
480
	{
481
		return $this->findItemBase( array( 'locale.language.id' => $code ), $ref );
482
	}
483
484
485
	/**
486
	 * Searches for language items matching the given criteria.
487
	 *
488
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
489
	 * @param string[] $ref List of domains to fetch list items and referenced items for
490
	 * @param integer|null &$total Number of items that are available in total
491
	 * @return array List of items implementing \Aimeos\MShop\Locale\Language\Item\Iface
492
	 */
493
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
494
	{
495
		$items = [];
496
		$context = $this->getContext();
497
498
		$dbm = $context->getDatabaseManager();
499
		$dbname = $this->getResourceName();
500
		$conn = $dbm->acquire( $dbname );
501
502
		try
503
		{
504
			$attributes = $this->getObject()->getSearchAttributes();
505
			$types = $this->getSearchTypes( $attributes );
506
			$translations = $this->getSearchTranslations( $attributes );
507
			$columns = $search->getColumnString( $search->getSortations(), $translations );
508
509
			$find = array( ':cond', ':order', ':columns', ':start', ':size' );
510
			$replace = array(
511
				$search->getConditionString( $types, $translations ),
512
				$search->getSortationString( $types, $translations ),
513
				( $columns ? ', ' . $columns : '' ),
514
				$search->getSliceStart(),
515
				$search->getSliceSize(),
516
			);
517
518
			/** mshop/locale/manager/language/standard/search/mysql
519
			 * Retrieves the records matched by the given criteria in the database
520
			 *
521
			 * @see mshop/locale/manager/language/standard/search/ansi
522
			 */
523
524
			/** mshop/locale/manager/language/standard/search/ansi
525
			 * Retrieves the records matched by the given criteria in the database
526
			 *
527
			 * Fetches the records matched by the given criteria from the attribute
528
			 * database. The records must be from one of the sites that are
529
			 * configured via the context item. If the current site is part of
530
			 * a tree of sites, the SELECT statement can retrieve all records
531
			 * from the current site and the complete sub-tree of sites.
532
			 *
533
			 * As the records can normally be limited by criteria from sub-managers,
534
			 * their tables must be joined in the SQL context. This is done by
535
			 * using the "internaldeps" property from the definition of the ID
536
			 * column of the sub-managers. These internal dependencies specify
537
			 * the JOIN between the tables and the used columns for joining. The
538
			 * ":joins" placeholder is then replaced by the JOIN strings from
539
			 * the sub-managers.
540
			 *
541
			 * To limit the records matched, conditions can be added to the given
542
			 * criteria object. It can contain comparisons like column names that
543
			 * must match specific values which can be combined by AND, OR or NOT
544
			 * operators. The resulting string of SQL conditions replaces the
545
			 * ":cond" placeholder before the statement is sent to the database
546
			 * server.
547
			 *
548
			 * If the records that are retrieved should be ordered by one or more
549
			 * columns, the generated string of column / sort direction pairs
550
			 * replaces the ":order" placeholder. In case no ordering is required,
551
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
552
			 * markers is removed to speed up retrieving the records. Columns of
553
			 * sub-managers can also be used for ordering the result set but then
554
			 * no index can be used.
555
			 *
556
			 * The number of returned records can be limited and can start at any
557
			 * number between the begining and the end of the result set. For that
558
			 * the ":size" and ":start" placeholders are replaced by the
559
			 * corresponding values from the criteria object. The default values
560
			 * are 0 for the start and 100 for the size value.
561
			 *
562
			 * The SQL statement should conform to the ANSI standard to be
563
			 * compatible with most relational database systems. This also
564
			 * includes using double quotes for table and column names.
565
			 *
566
			 * @param string SQL statement for searching items
567
			 * @since 2014.03
568
			 * @category Developer
569
			 * @see mshop/locale/manager/language/standard/insert/ansi
570
			 * @see mshop/locale/manager/language/standard/update/ansi
571
			 * @see mshop/locale/manager/language/standard/delete/ansi
572
			 * @see mshop/locale/manager/language/standard/count/ansi
573
			 */
574
			$path = 'mshop/locale/manager/language/standard/search';
575
576
			$sql = $this->getSqlConfig( $path );
577
			$results = $this->getSearchResults( $conn, str_replace( $find, $replace, $sql ) );
578
579
			try
580
			{
581
				while( ( $row = $results->fetch() ) !== false ) {
582
					$items[$row['locale.language.id']] = $this->createItemBase( $row );
583
				}
584
			}
585
			catch( \Exception $e )
586
			{
587
				$results->finish();
588
				throw $e;
589
			}
590
591
			if( $total !== null ) {
592
				$total = $this->getTotal( $conn, $find, $replace );
593
			}
594
595
			$dbm->release( $conn, $dbname );
596
		}
597
		catch( \Exception $e )
598
		{
599
			$dbm->release( $conn, $dbname );
600
			throw $e;
601
		}
602
603
		return $items;
604
	}
605
606
607
	/**
608
	 * Creates a search object and sets base criteria.
609
	 *
610
	 * @param boolean $default
611
	 * @return \Aimeos\MW\Criteria\Iface
612
	 */
613
	public function createSearch( $default = false )
614
	{
615
		if( $default === true ) {
616
			return $this->createSearchBase( 'locale.language' );
617
		}
618
619
		return parent::createSearch();
620
	}
621
622
623
	/**
624
	 * Returns the search results for the given SQL statement.
625
	 *
626
	 * @param \Aimeos\MW\DB\Connection\Iface $conn Database connection
627
	 * @param $sql SQL statement
628
	 * @return \Aimeos\MW\DB\Result\Iface Search result object
629
	 */
630
	protected function getSearchResults( \Aimeos\MW\DB\Connection\Iface $conn, $sql )
631
	{
632
		$statement = $conn->create( $sql );
633
		$this->getContext()->getLogger()->log( __METHOD__ . ': SQL statement: ' . $statement, \Aimeos\MW\Logger\Base::DEBUG );
634
635
		$results = $statement->execute();
636
637
		return $results;
638
	}
639
640
641
	/**
642
	 * Create new item object initialized with given parameters.
643
	 *
644
	 * @param array $data Associative list of item key/value pairs
645
	 * @return \Aimeos\MShop\Locale\Item\Language\Iface Language item
646
	 */
647
	protected function createItemBase( array $data = [] )
648
	{
649
		return new \Aimeos\MShop\Locale\Item\Language\Standard( $data );
650
	}
651
652
653
	/**
654
	 * Returns the total number of items found for the conditions
655
	 *
656
	 * @param \Aimeos\MW\DB\Connection\Iface $conn Database connection
657
	 * @param array $find List of markers that should be replaced in the SQL statement
658
	 * @param array $replace List of replacements for the markers in the SQL statement
659
	 * @throws \Aimeos\MShop\Locale\Exception If no total value was found
660
	 * @return integer Total number of found items
661
	 */
662
	protected function getTotal( \Aimeos\MW\DB\Connection\Iface $conn, array $find, array $replace )
663
	{
664
		/** mshop/locale/manager/language/standard/count/mysql
665
		 * Counts the number of records matched by the given criteria in the database
666
		 *
667
		 * @see mshop/locale/manager/language/standard/count/ansi
668
		 */
669
670
		/** mshop/locale/manager/language/standard/count/ansi
671
		 * Counts the number of records matched by the given criteria in the database
672
		 *
673
		 * Counts all records matched by the given criteria from the attribute
674
		 * database. The records must be from one of the sites that are
675
		 * configured via the context item. If the current site is part of
676
		 * a tree of sites, the statement can count all records from the
677
		 * current site and the complete sub-tree of sites.
678
		 *
679
		 * As the records can normally be limited by criteria from sub-managers,
680
		 * their tables must be joined in the SQL context. This is done by
681
		 * using the "internaldeps" property from the definition of the ID
682
		 * column of the sub-managers. These internal dependencies specify
683
		 * the JOIN between the tables and the used columns for joining. The
684
		 * ":joins" placeholder is then replaced by the JOIN strings from
685
		 * the sub-managers.
686
		 *
687
		 * To limit the records matched, conditions can be added to the given
688
		 * criteria object. It can contain comparisons like column names that
689
		 * must match specific values which can be combined by AND, OR or NOT
690
		 * operators. The resulting string of SQL conditions replaces the
691
		 * ":cond" placeholder before the statement is sent to the database
692
		 * server.
693
		 *
694
		 * Both, the strings for ":joins" and for ":cond" are the same as for
695
		 * the "search" SQL statement.
696
		 *
697
		 * Contrary to the "search" statement, it doesn't return any records
698
		 * but instead the number of records that have been found. As counting
699
		 * thousands of records can be a long running task, the maximum number
700
		 * of counted records is limited for performance reasons.
701
		 *
702
		 * The SQL statement should conform to the ANSI standard to be
703
		 * compatible with most relational database systems. This also
704
		 * includes using double quotes for table and column names.
705
		 *
706
		 * @param string SQL statement for counting items
707
		 * @since 2014.03
708
		 * @category Developer
709
		 * @see mshop/locale/manager/language/standard/insert/ansi
710
		 * @see mshop/locale/manager/language/standard/update/ansi
711
		 * @see mshop/locale/manager/language/standard/delete/ansi
712
		 * @see mshop/locale/manager/language/standard/search/ansi
713
		 */
714
		$path = 'mshop/locale/manager/language/standard/count';
715
716
		$sql = $this->getSqlConfig( $path );
717
		$results = $this->getSearchResults( $conn, str_replace( $find, $replace, $sql ) );
718
719
		$row = $results->fetch();
720
		$results->finish();
721
722
		if( $row === false ) {
723
			throw new \Aimeos\MShop\Locale\Exception( 'No total results value found' );
724
		}
725
726
		return $row['count'];
727
	}
728
}
729