Standard::bootstrapBase()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 17
rs 10
cc 4
nc 4
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2025
7
 * @package MShop
8
 * @subpackage Locale
9
 */
10
11
12
namespace Aimeos\MShop\Locale\Manager;
13
14
15
/**
16
 * Default locale manager implementation.
17
 *
18
 * @package MShop
19
 * @subpackage Locale
20
 */
21
class Standard
22
	extends \Aimeos\MShop\Locale\Manager\Base
23
	implements \Aimeos\MShop\Locale\Manager\Iface, \Aimeos\MShop\Common\Manager\Factory\Iface
24
{
25
	/** mshop/locale/manager/name
26
	 * Class name of the used locale manager implementation
27
	 *
28
	 * Each default manager can be replace by an alternative imlementation.
29
	 * To use this implementation, you have to set the last part of the class
30
	 * name as configuration value so the manager factory knows which class it
31
	 * has to instantiate.
32
	 *
33
	 * For example, if the name of the default class is
34
	 *
35
	 *  \Aimeos\MShop\Locale\Manager\Standard
36
	 *
37
	 * and you want to replace it with your own version named
38
	 *
39
	 *  \Aimeos\MShop\Locale\Manager\Mymanager
40
	 *
41
	 * then you have to set the this configuration option:
42
	 *
43
	 *  mshop/locale/manager/name = Mymanager
44
	 *
45
	 * The value is the last part of your own class name and it's case sensitive,
46
	 * so take care that the configuration value is exactly named like the last
47
	 * part of the class name.
48
	 *
49
	 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
50
	 * characters are possible! You should always start the last part of the class
51
	 * name with an upper case character and continue only with lower case characters
52
	 * or numbers. Avoid chamel case names like "MyManager"!
53
	 *
54
	 * @param string Last part of the class name
55
	 * @since 2014.03
56
	 */
57
58
	/** mshop/locale/manager/decorators/excludes
59
	 * Excludes decorators added by the "common" option from the locale manager
60
	 *
61
	 * Decorators extend the functionality of a class by adding new aspects
62
	 * (e.g. log what is currently done), executing the methods of the underlying
63
	 * class only in certain conditions (e.g. only for logged in users) or
64
	 * modify what is returned to the caller.
65
	 *
66
	 * This option allows you to remove a decorator added via
67
	 * "mshop/common/manager/decorators/default" before they are wrapped
68
	 * around the locale manager.
69
	 *
70
	 *  mshop/locale/manager/decorators/excludes = array( 'decorator1' )
71
	 *
72
	 * This would remove the decorator named "decorator1" from the list of
73
	 * common decorators ("\Aimeos\MShop\Common\Manager\Decorator\*") added via
74
	 * "mshop/common/manager/decorators/default" for the locale manager.
75
	 *
76
	 * @param array List of decorator names
77
	 * @since 2014.03
78
	 * @see mshop/common/manager/decorators/default
79
	 * @see mshop/locale/manager/decorators/global
80
	 * @see mshop/locale/manager/decorators/local
81
	 */
82
83
	/** mshop/locale/manager/decorators/global
84
	 * Adds a list of globally available decorators only to the locale manager
85
	 *
86
	 * Decorators extend the functionality of a class by adding new aspects
87
	 * (e.g. log what is currently done), executing the methods of the underlying
88
	 * class only in certain conditions (e.g. only for logged in users) or
89
	 * modify what is returned to the caller.
90
	 *
91
	 * This option allows you to wrap global decorators
92
	 * ("\Aimeos\MShop\Common\Manager\Decorator\*") around the locale manager.
93
	 *
94
	 *  mshop/locale/manager/decorators/global = array( 'decorator1' )
95
	 *
96
	 * This would add the decorator named "decorator1" defined by
97
	 * "\Aimeos\MShop\Common\Manager\Decorator\Decorator1" only to the locale
98
	 * manager.
99
	 *
100
	 * @param array List of decorator names
101
	 * @since 2014.03
102
	 * @see mshop/common/manager/decorators/default
103
	 * @see mshop/locale/manager/decorators/excludes
104
	 * @see mshop/locale/manager/decorators/local
105
	 */
106
107
	/** mshop/locale/manager/decorators/local
108
	 * Adds a list of local decorators only to the locale manager
109
	 *
110
	 * Decorators extend the functionality of a class by adding new aspects
111
	 * (e.g. log what is currently done), executing the methods of the underlying
112
	 * class only in certain conditions (e.g. only for logged in users) or
113
	 * modify what is returned to the caller.
114
	 *
115
	 * This option allows you to wrap local decorators
116
	 * ("\Aimeos\MShop\Locale\Manager\Decorator\*") around the locale manager.
117
	 *
118
	 *  mshop/locale/manager/decorators/local = array( 'decorator2' )
119
	 *
120
	 * This would add the decorator named "decorator2" defined by
121
	 * "\Aimeos\MShop\Locale\Manager\Decorator\Decorator2" only to the locale
122
	 * manager.
123
	 *
124
	 * @param array List of decorator names
125
	 * @since 2014.03
126
	 * @see mshop/common/manager/decorators/default
127
	 * @see mshop/locale/manager/decorators/excludes
128
	 * @see mshop/locale/manager/decorators/global
129
	 */
130
131
	/** mshop/locale/manager/resource
132
	 * Name of the database connection resource to use
133
	 *
134
	 * You can configure a different database connection for each data domain
135
	 * and if no such connection name exists, the "db" connection will be used.
136
	 * It's also possible to use the same database connection for different
137
	 * data domains by configuring the same connection name using this setting.
138
	 *
139
	 * @param string Database connection name
140
	 * @since 2023.04
141
	 */
142
143
	/** mshop/locale/manager/delete/mysql
144
	 * Deletes the items matched by the given IDs from the database
145
	 *
146
	 * @see mshop/locale/manager/delete/ansi
147
	 */
148
149
	/** mshop/locale/manager/delete/ansi
150
	 * Deletes the items matched by the given IDs from the database
151
	 *
152
	 * Removes the records specified by the given IDs from the locale database.
153
	 * The records must be from the site that is configured via the
154
	 * context item.
155
	 *
156
	 * The ":cond" placeholder is replaced by the name of the ID column and
157
	 * the given ID or list of IDs while the site ID is bound to the question
158
	 * mark.
159
	 *
160
	 * The SQL statement should conform to the ANSI standard to be
161
	 * compatible with most relational database systems. This also
162
	 * includes using double quotes for table and column names.
163
	 *
164
	 * @param string SQL statement for deleting items
165
	 * @since 2014.03
166
	 * @see mshop/locale/manager/insert/ansi
167
	 * @see mshop/locale/manager/update/ansi
168
	 * @see mshop/locale/manager/newid/ansi
169
	 * @see mshop/locale/manager/search/ansi
170
	 * @see mshop/locale/manager/count/ansi
171
	 */
172
173
174
	private array $searchConfig = [
175
		'locale.id' => [
176
			'label' => 'ID',
177
			'internalcode' => 'mloc."id"',
178
			'type' => 'int',
179
			'public' => false,
180
		],
181
		'locale.siteid' => [
182
			'label' => 'Site ID',
183
			'internalcode' => 'mloc."siteid"',
184
			'public' => false,
185
		],
186
		'locale.languageid' => [
187
			'label' => 'Language ID',
188
			'internalcode' => 'mloc."langid"',
189
		],
190
		'locale.currencyid' => [
191
			'label' => 'Currency ID',
192
			'internalcode' => 'mloc."currencyid"',
193
		],
194
		'locale.status' => [
195
			'label' => 'Status',
196
			'internalcode' => 'mloc."status"',
197
			'type' => 'int',
198
		],
199
		'locale.position' => [
200
			'label' => 'Position',
201
			'internalcode' => 'mloc."pos"',
202
			'type' => 'int',
203
		],
204
		'locale.ctime' => [
205
			'label' => 'Create date/time',
206
			'internalcode' => 'mloc."ctime"',
207
			'type' => 'datetime',
208
			'public' => false,
209
		],
210
		'locale.mtime' => [
211
			'label' => 'Modify date/time',
212
			'internalcode' => 'mloc."mtime"',
213
			'type' => 'datetime',
214
			'public' => false,
215
		],
216
		'locale.editor' => [
217
			'label' => 'Editor',
218
			'internalcode' => 'mloc."editor"',
219
			'public' => false,
220
		],
221
	];
222
223
224
	/**
225
	 * Returns the locale item for the given site code, language code and currency code.
226
	 *
227
	 * @param string $site Site code
228
	 * @param string $lang Language code (optional)
229
	 * @param string $currency Currency code (optional)
230
	 * @param bool $active Flag to get only active items (optional)
231
	 * @param int|null $level Constant from abstract class which site ID levels should be available (optional),
232
	 * 	based on config or value for SITE_PATH if null
233
	 * @param bool $bare Allow locale items with sites only
234
	 * @return \Aimeos\MShop\Locale\Item\Iface Locale item for the given parameters
235
	 * @throws \Aimeos\MShop\Locale\Exception If no locale item is found
236
	 */
237
	public function bootstrap( string $site, string $lang = '', string $currency = '', bool $active = true, ?int $level = null,
238
		bool $bare = false ) : \Aimeos\MShop\Locale\Item\Iface
239
	{
240
		$siteItem = $this->object()->getSubManager( 'site' )->find( $site );
241
242
		// allow enabled sites and sites under review
243
		if( $active && $siteItem->getStatus() < 1 && $siteItem->getStatus() !== -1 ) {
244
			throw new \Aimeos\MShop\Locale\Exception( 'Site not found' );
245
		}
246
247
		$siteId = $siteItem->getSiteId();
248
		$sites = [Base::SITE_ONE => $siteId];
249
250
		return $this->bootstrapBase( $site, $lang, $currency, $active, $siteItem, $siteId, $sites, $bare );
251
	}
252
253
254
	/**
255
	 * Creates a new empty item instance
256
	 *
257
	 * @param array $values Values the item should be initialized with
258
	 * @return \Aimeos\MShop\Locale\Item\Iface New locale item object
259
	 */
260
	public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
261
	{
262
		try {
263
			$values['locale.siteid'] = $values['locale.siteid'] ?? $this->context()->locale()->getSiteId();
264
		} catch( \Exception $e ) {} // if no locale item is available
265
266
		return $this->createItemBase( $values );
267
	}
268
269
270
	/**
271
	 * Creates a filter object.
272
	 *
273
	 * @param bool|null $default Add default criteria or NULL for relaxed default criteria
274
	 * @param bool $site TRUE for adding site criteria to limit items by the site of related items
275
	 * @return \Aimeos\Base\Criteria\Iface Returns the filter object
276
	 */
277
	public function filter( ?bool $default = false, bool $site = false ) : \Aimeos\Base\Criteria\Iface
278
	{
279
		return $this->filterBase( 'locale', $default );
280
	}
281
282
283
	/**
284
	 * Returns the attributes that can be used for searching.
285
	 *
286
	 * @param bool $withsub Return also attributes of sub-managers if true
287
	 * @return \Aimeos\Base\Criteria\Attribute\Iface[] List of search attribute items
288
	 */
289
	public function getSearchAttributes( bool $withsub = true ) : array
290
	{
291
		/** mshop/locale/manager/submanagers
292
		 * List of manager names that can be instantiated by the locale manager
293
		 *
294
		 * Managers provide a generic interface to the underlying storage.
295
		 * Each manager has or can have sub-managers caring about particular
296
		 * aspects. Each of these sub-managers can be instantiated by its
297
		 * parent manager using the getSubManager() method.
298
		 *
299
		 * The search keys from sub-managers can be normally used in the
300
		 * manager as well. It allows you to search for items of the manager
301
		 * using the search keys of the sub-managers to further limit the
302
		 * retrieved list of items.
303
		 *
304
		 * @param array List of sub-manager names
305
		 * @since 2014.03
306
		 */
307
		$path = 'mshop/locale/manager/submanagers';
308
		$default = ['language', 'currency', 'site'];
309
310
		return $this->getSearchAttributesBase( $this->searchConfig, $path, $default, $withsub );
311
	}
312
313
314
	/**
315
	 * Searches for all items matching the given critera.
316
	 *
317
	 * @param \Aimeos\Base\Criteria\Iface $search Criteria object with conditions, sortations, etc.
318
	 * @param string[] $ref List of domains to fetch list items and referenced items for
319
	 * @param int &$total Number of items that are available in total
320
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Locale\Item\Iface with ids as keys
321
	 */
322
	public function search( \Aimeos\Base\Criteria\Iface $search, array $ref = [], ?int &$total = null ) : \Aimeos\Map
323
	{
324
		$items = [];
325
		$level = \Aimeos\MShop\Locale\Manager\Base::SITE_PATH;
326
		$search = (clone $search)->add( $this->siteCondition( 'locale.siteid', $level ) );
327
328
		foreach( $this->searchEntries( $search, $ref, $total ) as $row )
329
		{
330
			if( $item = $this->applyFilter( $this->createItemBase( $row ) ) ) {
331
				$items[$row['locale.id']] = $item;
332
			}
333
		}
334
335
		return map( $items );
336
	}
337
338
339
	/**
340
	 * Returns the locale item for the given site code, language code and currency code.
341
	 *
342
	 * If the locale item is inherited from a parent site, the site ID of this locale item
343
	 * is changed to the site ID of the actual site. This ensures that items assigned to
344
	 * the same site as the site item are still used.
345
	 *
346
	 * @param string $site Site code
347
	 * @param string $lang Language code
348
	 * @param string $currency Currency code
349
	 * @param bool $active Flag to get only active items
350
	 * @param \Aimeos\MShop\Locale\Item\Site\Iface $siteItem Site item
351
	 * @param string $siteId Site ID
352
	 * @param array $sites Associative list of site constant as key and sites as values
353
	 * @param bool $bare Allow locale items with sites only
354
	 * @return \Aimeos\MShop\Locale\Item\Iface Locale item for the given parameters
355
	 * @throws \Aimeos\MShop\Locale\Exception If no locale item is found
356
	 */
357
	protected function bootstrapBase( string $site, string $lang, string $currency, bool $active,
358
		\Aimeos\MShop\Locale\Item\Site\Iface $siteItem, string $siteId, array $sites, bool $bare ) : \Aimeos\MShop\Locale\Item\Iface
359
	{
360
		if( $result = $this->bootstrapMatch( $siteId, $lang, $currency, $active, $siteItem, $sites ) ) {
361
			return $result;
362
		}
363
364
		if( $result = $this->bootstrapClosest( $siteId, $lang, $active, $siteItem, $sites ) ) {
365
			return $result;
366
		}
367
368
		if( $bare === true ) {
369
			return $this->createItemBase( ['locale.siteid' => $siteId], $siteItem, $sites );
370
		}
371
372
		$msg = $this->context()->translate( 'mshop', 'Locale item for site "%1$s" not found' );
373
		throw new \Aimeos\MShop\Locale\Exception( sprintf( $msg, $site ) );
374
	}
375
376
377
	/**
378
	 * Returns the matching locale item for the given site code, language code and currency code.
379
	 *
380
	 * If the locale item is inherited from a parent site, the site ID of this locale item
381
	 * is changed to the site ID of the actual site. This ensures that items assigned to
382
	 * the same site as the site item are still used.
383
	 *
384
	 * @param string $siteId Site ID
385
	 * @param string $lang Language code
386
	 * @param string $currency Currency code
387
	 * @param bool $active Flag to get only active items
388
	 * @param \Aimeos\MShop\Locale\Item\Site\Iface $siteItem Site item
389
	 * @param array $sites Associative list of site constant as key and sites as values
390
	 * @return \Aimeos\MShop\Locale\Item\Iface|null Locale item for the given parameters or null if no item was found
391
	 */
392
	private function bootstrapMatch( string $siteId, string $lang, string $currency, bool $active,
393
		\Aimeos\MShop\Locale\Item\Site\Iface $siteItem, array $sites ) : ?\Aimeos\MShop\Locale\Item\Iface
394
	{
395
		// Try to find exact match
396
		$search = $this->object()->filter( $active );
397
398
		$expr = array( $search->compare( '==', 'locale.siteid', $sites[Base::SITE_PATH] ?? $sites[Base::SITE_ONE] ) );
399
400
		if( !empty( $lang ) )
401
		{
402
			$langIds = strlen( $lang ) > 2 ? [$lang, substr( $lang, 0, 2 )] : [$lang];
403
			$expr[] = $search->compare( '==', 'locale.languageid', $langIds );
404
		}
405
406
		if( !empty( $currency ) ) {
407
			$expr[] = $search->compare( '==', 'locale.currencyid', $currency );
408
		}
409
410
		$expr[] = $search->getConditions();
411
412
413
		if( $active === true )
414
		{
415
			$expr[] = $search->compare( '>', 'locale.currency.status', 0 );
416
			$expr[] = $search->compare( '>', 'locale.language.status', 0 );
417
			$expr[] = $search->compare( '>', 'locale.site.status', 0 );
418
		}
419
420
		$search->setConditions( $search->and( $expr ) );
421
		$search->setSortations( array( $search->sort( '+', 'locale.position' ) ) );
422
		$result = $this->searchEntries( $search );
423
424
		// Try to find first item where site matches
425
		foreach( $result as $row )
426
		{
427
			if( $row['locale.siteid'] === $siteId ) {
428
				return $this->createItemBase( $row, $siteItem, $sites );
429
			}
430
		}
431
432
		if( ( $row = reset( $result ) ) !== false )
433
		{
434
			$row['locale.siteid'] = $siteId;
435
			return $this->createItemBase( $row, $siteItem, $sites );
436
		}
437
438
		return null;
439
	}
440
441
442
	/**
443
	 * Returns the locale item for the given site code, language code and currency code.
444
	 *
445
	 * If the locale item is inherited from a parent site, the site ID of this locale item
446
	 * is changed to the site ID of the actual site. This ensures that items assigned to
447
	 * the same site as the site item are still used.
448
	 *
449
	 * @param string $siteId Site ID
450
	 * @param string $lang Language code
451
	 * @param bool $active Flag to get only active items
452
	 * @param \Aimeos\MShop\Locale\Item\Site\Iface $siteItem Site item
453
	 * @param array $sites Associative list of site constant as key and sites as values
454
	 * @return \Aimeos\MShop\Locale\Item\Iface|null Locale item for the given parameters or null if no item was found
455
	 */
456
	private function bootstrapClosest( string $siteId, string $lang, bool $active,
457
		\Aimeos\MShop\Locale\Item\Site\Iface $siteItem, array $sites ) : ?\Aimeos\MShop\Locale\Item\Iface
458
	{
459
		// Try to find the best matching locale
460
		$search = $this->object()->filter( $active );
461
462
		$expr = array(
463
			$search->compare( '==', 'locale.siteid', $sites[Base::SITE_PATH] ?? $sites[Base::SITE_ONE] ),
464
			$search->getConditions()
465
		);
466
467
		if( $active === true )
468
		{
469
			$expr[] = $search->compare( '>', 'locale.currency.status', 0 );
470
			$expr[] = $search->compare( '>', 'locale.language.status', 0 );
471
			$expr[] = $search->compare( '>', 'locale.site.status', 0 );
472
		}
473
474
		$search->setConditions( $search->and( $expr ) );
475
		$search->setSortations( array( $search->sort( '+', 'locale.position' ) ) );
476
		$result = $this->searchEntries( $search );
477
478
		// Try to find first item where site and language matches
479
		foreach( $result as $row )
480
		{
481
			if( $row['locale.siteid'] === $siteId && $row['locale.languageid'] === $lang ) {
482
				return $this->createItemBase( $row, $siteItem, $sites );
483
			}
484
		}
485
486
		$short = strlen( $lang ) > 2 ? substr( $lang, 0, 2 ) : null;
487
488
		// Try to find first item where site and language without country matches
489
		if( $short )
490
		{
491
			foreach( $result as $row )
492
			{
493
				if( $row['locale.siteid'] === $siteId && $row['locale.languageid'] === $short ) {
494
					return $this->createItemBase( $row, $siteItem, $sites );
495
				}
496
			}
497
		}
498
499
		// Try to find first item where language matches
500
		foreach( $result as $row )
501
		{
502
			if( $row['locale.languageid'] === $lang )
503
			{
504
				$row['locale.siteid'] = $siteId;
505
				return $this->createItemBase( $row, $siteItem, $sites );
506
			}
507
		}
508
509
		// Try to find first item where language without country matches
510
		if( $short )
511
		{
512
			foreach( $result as $row )
513
			{
514
				if( $row['locale.siteid'] === $siteId && $row['locale.languageid'] === $short ) {
515
					return $this->createItemBase( $row, $siteItem, $sites );
516
				}
517
			}
518
		}
519
520
		// Try to find first item where site matches
521
		foreach( $result as $row )
522
		{
523
			if( $row['locale.siteid'] === $siteId ) {
524
				return $this->createItemBase( $row, $siteItem, $sites );
525
			}
526
		}
527
528
		// Return first item (no other match found)
529
		if( ( $row = reset( $result ) ) !== false )
530
		{
531
			$row['locale.siteid'] = $siteId;
532
			return $this->createItemBase( $row, $siteItem, $sites );
533
		}
534
535
		return null;
536
	}
537
538
539
	/**
540
	 * Instances a new locale item object.
541
	 *
542
	 * @param array $values Parameter to initialise the item
543
	 * @param \Aimeos\MShop\Locale\Item\Site\Iface|null $site Site item
544
	 * @param array $sites Associative list of site constant as key and sites as values
545
	 * @return \Aimeos\MShop\Locale\Item\Iface Locale item
546
	 */
547
	protected function createItemBase( array $values = [], ?\Aimeos\MShop\Locale\Item\Site\Iface $site = null,
548
		array $sites = [] ) : \Aimeos\MShop\Locale\Item\Iface
549
	{
550
		return new \Aimeos\MShop\Locale\Item\Standard( $values, $site, $sites );
551
	}
552
553
554
	/**
555
	 * Returns the site coditions for the search request
556
	 *
557
	 * @param string[] $keys Sorted list of criteria keys
558
	 * @param \Aimeos\Base\Criteria\Attribute\Iface[] $attributes Associative list of search keys and criteria attribute items as values
559
	 * @param int $sitelevel Site level constant from \Aimeos\MShop\Locale\Manager\Base
560
	 * @return \Aimeos\Base\Criteria\Expression\Iface[] List of search conditions
561
	 */
562
	protected function getSiteConditions( array $keys, array $attributes, int $sitelevel ) : array
563
	{
564
		return [];
565
	}
566
567
568
	/**
569
	 * Returns the prefix for the item properties and search keys.
570
	 *
571
	 * @return string Prefix for the item properties and search keys
572
	 */
573
	protected function prefix() : string
574
	{
575
		return 'locale.';
576
	}
577
578
579
	/**
580
	 * Adds or updates an item object.
581
	 *
582
	 * @param \Aimeos\MShop\Locale\Item\Iface $item Item object whose data should be saved
583
	 * @param bool $fetch True if the new ID should be returned in the item
584
	 * @return \Aimeos\MShop\Locale\Item\Iface $item Updated item including the generated ID
585
	 */
586
	protected function saveBase( \Aimeos\MShop\Common\Item\Iface $item, bool $fetch = true ) : \Aimeos\MShop\Common\Item\Iface
587
	{
588
		if( !$item->isModified() ) {
589
			return $item;
590
		}
591
592
		$context = $this->context();
593
		$conn = $context->db( $this->getResourceName() );
594
595
		$id = $item->getId();
596
		$columns = $this->object()->getSaveAttributes();
597
598
		if( $id === null )
599
		{
600
			/** mshop/locale/manager/insert/mysql
601
			 * Inserts a new locale record into the database table
602
			 *
603
			 * @see mshop/locale/manager/insert/ansi
604
			 */
605
606
			/** mshop/locale/manager/insert/ansi
607
			 * Inserts a new locale record into the database table
608
			 *
609
			 * Items with no ID yet (i.e. the ID is NULL) will be created in
610
			 * the database and the newly created ID retrieved afterwards
611
			 * using the "newid" SQL statement.
612
			 *
613
			 * The SQL statement must be a string suitable for being used as
614
			 * prepared statement. It must include question marks for binding
615
			 * the values from the locale item to the statement before they are
616
			 * sent to the database server. The number of question marks must
617
			 * be the same as the number of columns listed in the INSERT
618
			 * statement. The order of the columns must correspond to the
619
			 * order in the save() method, so the correct values are
620
			 * bound to the columns.
621
			 *
622
			 * The SQL statement should conform to the ANSI standard to be
623
			 * compatible with most relational database systems. This also
624
			 * includes using double quotes for table and column names.
625
			 *
626
			 * @param string SQL statement for inserting records
627
			 * @since 2014.03
628
			 * @see mshop/locale/manager/update/ansi
629
			 * @see mshop/locale/manager/newid/ansi
630
			 * @see mshop/locale/manager/delete/ansi
631
			 * @see mshop/locale/manager/search/ansi
632
			 * @see mshop/locale/manager/count/ansi
633
			 */
634
			$path = 'mshop/locale/manager/insert';
635
			$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ) );
0 ignored issues
show
Bug introduced by
It seems like $this->getSqlConfig($path) can also be of type array; however, parameter $sql of Aimeos\MShop\Common\Manager\Base::addSqlColumns() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

635
			$sql = $this->addSqlColumns( array_keys( $columns ), /** @scrutinizer ignore-type */ $this->getSqlConfig( $path ) );
Loading history...
636
		}
637
		else
638
		{
639
			/** mshop/locale/manager/update/mysql
640
			 * Updates an existing locale record in the database
641
			 *
642
			 * @see mshop/locale/manager/update/ansi
643
			 */
644
645
			/** mshop/locale/manager/update/ansi
646
			 * Updates an existing locale record in the database
647
			 *
648
			 * Items which already have an ID (i.e. the ID is not NULL) will
649
			 * be updated in the database.
650
			 *
651
			 * The SQL statement must be a string suitable for being used as
652
			 * prepared statement. It must include question marks for binding
653
			 * the values from the locale item to the statement before they are
654
			 * sent to the database server. The order of the columns must
655
			 * correspond to the order in the save() method, so the
656
			 * correct values are bound to the columns.
657
			 *
658
			 * The SQL statement should conform to the ANSI standard to be
659
			 * compatible with most relational database systems. This also
660
			 * includes using double quotes for table and column names.
661
			 *
662
			 * @param string SQL statement for updating records
663
			 * @since 2014.03
664
			 * @see mshop/locale/manager/insert/ansi
665
			 * @see mshop/locale/manager/newid/ansi
666
			 * @see mshop/locale/manager/delete/ansi
667
			 * @see mshop/locale/manager/search/ansi
668
			 * @see mshop/locale/manager/count/ansi
669
			 */
670
			$path = 'mshop/locale/manager/update';
671
			$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ), false );
672
		}
673
674
		$idx = 1;
675
		$stmt = $this->getCachedStatement( $conn, $path, $sql );
676
		$siteIds = explode( '.', trim( $item->getSiteId(), '.' ) );
677
678
		foreach( $columns as $name => $entry ) {
679
			$stmt->bind( $idx++, $item->get( $name ), \Aimeos\Base\Criteria\SQL::type( $entry->getType() ) );
680
		}
681
682
		$stmt->bind( $idx++, $item->getLanguageId() );
683
		$stmt->bind( $idx++, $item->getCurrencyId() );
684
		$stmt->bind( $idx++, $item->getPosition(), \Aimeos\Base\DB\Statement\Base::PARAM_INT );
685
		$stmt->bind( $idx++, $item->getStatus(), \Aimeos\Base\DB\Statement\Base::PARAM_INT );
686
		$stmt->bind( $idx++, $context->datetime() ); // mtime
687
		$stmt->bind( $idx++, $context->editor() );
688
		$stmt->bind( $idx++, end( $siteIds ), \Aimeos\Base\DB\Statement\Base::PARAM_INT );
689
		$stmt->bind( $idx++, $context->locale()->getSiteId() );
690
691
		if( $id !== null ) {
692
			$stmt->bind( $idx++, $id, \Aimeos\Base\DB\Statement\Base::PARAM_INT );
693
		} else {
694
			$stmt->bind( $idx++, $context->datetime() ); // ctime
695
		}
696
697
		$stmt->execute()->finish();
698
699
		if( $id === null && $fetch === true )
700
		{
701
			/** mshop/locale/manager/newid/mysql
702
			 * Retrieves the ID generated by the database when inserting a new record
703
			 *
704
			 * @see mshop/locale/manager/newid/ansi
705
			 */
706
707
			/** mshop/locale/manager/newid/ansi
708
			 * Retrieves the ID generated by the database when inserting a new record
709
			 *
710
			 * As soon as a new record is inserted into the database table,
711
			 * the database server generates a new and unique identifier for
712
			 * that record. This ID can be used for retrieving, updating and
713
			 * deleting that specific record from the table again.
714
			 *
715
			 * For MySQL:
716
			 *  SELECT LAST_INSERT_ID()
717
			 * For PostgreSQL:
718
			 *  SELECT currval('seq_mloc_id')
719
			 * For SQL Server:
720
			 *  SELECT SCOPE_IDENTITY()
721
			 * For Oracle:
722
			 *  SELECT "seq_mloc_id".CURRVAL FROM DUAL
723
			 *
724
			 * There's no way to retrive the new ID by a SQL statements that
725
			 * fits for most database servers as they implement their own
726
			 * specific way.
727
			 *
728
			 * @param string SQL statement for retrieving the last inserted record ID
729
			 * @since 2014.03
730
			 * @see mshop/locale/manager/insert/ansi
731
			 * @see mshop/locale/manager/update/ansi
732
			 * @see mshop/locale/manager/delete/ansi
733
			 * @see mshop/locale/manager/search/ansi
734
			 * @see mshop/locale/manager/count/ansi
735
			 */
736
			$path = 'mshop/locale/manager/newid';
737
			$id = $this->newId( $conn, $path );
738
		}
739
740
		$item->setId( $id );
741
742
		return $item;
743
	}
744
745
746
	/**
747
	 * Searches for all items matching the given critera.
748
	 *
749
	 * @param \Aimeos\Base\Criteria\Iface $search Criteria object with conditions, sortations, etc.
750
	 * @param string[] $ref List of domains to fetch list items and referenced items for
751
	 * @param int &$total Number of items that are available in total
752
	 * @return array Associative list of key/value pairs
753
	 */
754
	protected function searchEntries( \Aimeos\Base\Criteria\Iface $search, array $ref = [], ?int &$total = null ) : array
755
	{
756
		$map = [];
757
		$context = $this->context();
758
		$conn = $context->db( $this->getResourceName() );
759
760
		$required = ['locale'];
761
762
		/** mshop/locale/manager/search/mysql
763
		 * Retrieves the records matched by the given criteria in the database
764
		 *
765
		 * @see mshop/locale/manager/search/ansi
766
		 */
767
768
		/** mshop/locale/manager/search/ansi
769
		 * Retrieves the records matched by the given criteria in the database
770
		 *
771
		 * Fetches the records matched by the given criteria from the locale
772
		 * database. The records must be from one of the sites that are
773
		 * configured via the context item. If the current site is part of
774
		 * a tree of sites, the SELECT statement can retrieve all records
775
		 * from the current site and the complete sub-tree of sites.
776
		 *
777
		 * To limit the records matched, conditions can be added to the given
778
		 * criteria object. It can contain comparisons like column names that
779
		 * must match specific values which can be combined by AND, OR or NOT
780
		 * operators. The resulting string of SQL conditions replaces the
781
		 * ":cond" placeholder before the statement is sent to the database
782
		 * server.
783
		 *
784
		 * If the records that are retrieved should be ordered by one or more
785
		 * columns, the generated string of column / sort direction pairs
786
		 * replaces the ":order" placeholder. Columns of
787
		 * sub-managers can also be used for ordering the result set but then
788
		 * no index can be used.
789
		 *
790
		 * The number of returned records can be limited and can start at any
791
		 * number between the begining and the end of the result set. For that
792
		 * the ":size" and ":start" placeholders are replaced by the
793
		 * corresponding values from the criteria object. The default values
794
		 * are 0 for the start and 100 for the size value.
795
		 *
796
		 * The SQL statement should conform to the ANSI standard to be
797
		 * compatible with most relational database systems. This also
798
		 * includes using double quotes for table and column names.
799
		 *
800
		 * @param string SQL statement for searching items
801
		 * @since 2014.03
802
		 * @see mshop/locale/manager/insert/ansi
803
		 * @see mshop/locale/manager/update/ansi
804
		 * @see mshop/locale/manager/newid/ansi
805
		 * @see mshop/locale/manager/delete/ansi
806
		 * @see mshop/locale/manager/count/ansi
807
		 */
808
		$cfgPathSearch = 'mshop/locale/manager/search';
809
810
		/** mshop/locale/manager/count/mysql
811
		 * Counts the number of records matched by the given criteria in the database
812
		 *
813
		 * @see mshop/locale/manager/count/ansi
814
		 */
815
816
		/** mshop/locale/manager/count/ansi
817
		 * Counts the number of records matched by the given criteria in the database
818
		 *
819
		 * Counts all records matched by the given criteria from the locale
820
		 * database. The records must be from one of the sites that are
821
		 * configured via the context item. If the current site is part of
822
		 * a tree of sites, the statement can count all records from the
823
		 * current site and the complete sub-tree of sites.
824
		 *
825
		 * To limit the records matched, conditions can be added to the given
826
		 * criteria object. It can contain comparisons like column names that
827
		 * must match specific values which can be combined by AND, OR or NOT
828
		 * operators. The resulting string of SQL conditions replaces the
829
		 * ":cond" placeholder before the statement is sent to the database
830
		 * server.
831
		 *
832
		 * Both, the strings for ":joins" and for ":cond" are the same as for
833
		 * the "search" SQL statement.
834
		 *
835
		 * Contrary to the "search" statement, it doesn't return any records
836
		 * but instead the number of records that have been found. As counting
837
		 * thousands of records can be a long running task, the maximum number
838
		 * of counted records is limited for performance reasons.
839
		 *
840
		 * The SQL statement should conform to the ANSI standard to be
841
		 * compatible with most relational database systems. This also
842
		 * includes using double quotes for table and column names.
843
		 *
844
		 * @param string SQL statement for counting items
845
		 * @since 2014.03
846
		 * @see mshop/locale/manager/insert/ansi
847
		 * @see mshop/locale/manager/update/ansi
848
		 * @see mshop/locale/manager/newid/ansi
849
		 * @see mshop/locale/manager/delete/ansi
850
		 * @see mshop/locale/manager/search/ansi
851
		 */
852
		$cfgPathCount = 'mshop/locale/manager/count';
853
854
		$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total );
855
856
		while( $row = $results->fetch() ) {
857
			$map[$row['locale.id']] = $row;
858
		}
859
860
		return $map;
861
	}
862
}
863