Passed
Push — master ( c46287...9f1c00 )
by Aimeos
05:19
created

Methods::initMethods()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2023
6
 * @package MShop
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\MShop\Common\Manager;
12
13
14
/**
15
 * Method trait for managers
16
 *
17
 * @package MShop
18
 * @subpackage Common
19
 */
20
trait Methods
21
{
22
	private ?\Aimeos\MShop\Common\Manager\Iface $object = null;
23
	private array $filterFcn = [];
24
	private string $domain;
25
	private string $subpath;
26
27
28
	/**
29
	 * Returns the alias of the used table
30
	 *
31
	 * @return string Table alias e.g. "mprolity"
32
	 */
33
	abstract protected function alias() : string;
34
35
36
	/**
37
	 * Adds a filter callback for an item type
38
	 *
39
	 * @param string $iface Interface name of the item to apply the filter to
40
	 * @param \Closure $fcn Anonymous function receiving the item to check as first parameter
41
	 */
42
	public function addFilter( string $iface, \Closure $fcn )
43
	{
44
		if( !isset( $this->filterFcn[$iface] ) ) {
45
			$this->filterFcn[$iface] = [];
46
		}
47
48
		$this->filterFcn[$iface][] = $fcn;
49
	}
50
51
52
	/**
53
	 * Returns the class names of the manager and used decorators.
54
	 *
55
	 * @return array List of class names
56
	 */
57
	public function classes() : array
58
	{
59
		return [get_class( $this )];
60
	}
61
62
63
	/**
64
	 * Removes old entries from the storage
65
	 *
66
	 * @param iterable $siteids List of IDs for sites whose entries should be deleted
67
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
68
	 */
69
	public function clear( iterable $siteids ) : \Aimeos\MShop\Common\Manager\Iface
70
	{
71
		return $this;
72
	}
73
74
75
	/**
76
	 * Creates a new empty item instance
77
	 *
78
	 * @param array $values Values the item should be initialized with
79
	 * @return \Aimeos\MShop\Attribute\Item\Iface New attribute item object
80
	 */
81
	public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
82
	{
83
		return new \Aimeos\MShop\Common\Item\Base( $this->prefix(), $values );
84
	}
85
86
87
	/**
88
	 * Creates a new cursor based on the filter criteria
89
	 *
90
	 * @param \Aimeos\Base\Criteria\Iface $filter Criteria object with conditions, sortations, etc.
91
	 * @return \Aimeos\MShop\Common\Cursor\Iface Cursor object
92
	 */
93
	public function cursor( \Aimeos\Base\Criteria\Iface $filter ) : \Aimeos\MShop\Common\Cursor\Iface
94
	{
95
		return new \Aimeos\MShop\Common\Cursor\Standard( $filter );
96
	}
97
98
99
	/**
100
	 * Deletes one or more items.
101
	 *
102
	 * @param \Aimeos\MShop\Common\Item\Iface|\Aimeos\Map|array|string $items Item object, ID or a list of them
103
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
104
	 */
105
	public function delete( $items ) : \Aimeos\MShop\Common\Manager\Iface
106
	{
107
		return $this;
108
	}
109
110
111
	/**
112
	 * Creates a filter object.
113
	 *
114
	 * @param bool|null $default Add default criteria or NULL for relaxed default criteria
115
	 * @param bool $site TRUE for adding site criteria to limit items by the site of related items
116
	 * @return \Aimeos\Base\Criteria\Iface Returns the filter object
117
	 */
118
	public function filter( ?bool $default = false, bool $site = false ) : \Aimeos\Base\Criteria\Iface
119
	{
120
		throw new \LogicException( 'Not implemented' );
121
	}
122
123
124
	/**
125
	 * Returns the item specified by its ID
126
	 *
127
	 * @param string $id Id of item
128
	 * @param string[] $ref List of domains to fetch list items and referenced items for
129
	 * @param bool|null $default Add default criteria or NULL for relaxed default criteria
130
	 * @return \Aimeos\MShop\Common\Item\Iface Item object
131
	 */
132
	public function get( string $id, array $ref = [], ?bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
133
	{
134
		throw new \LogicException( 'Not implemented' );
135
	}
136
137
138
	/**
139
	 * Returns the available manager types
140
	 *
141
	 * @param bool $withsub Return also the resource type of sub-managers if true
142
	 * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
143
	 */
144
	public function getResourceType( bool $withsub = true ) : array
145
	{
146
		return [$this->getManagerPath()];
147
	}
148
149
150
	/**
151
	 * Returns the additional column/search definitions
152
	 *
153
	 * @return array Associative list of column names as keys and items implementing \Aimeos\Base\Criteria\Attribute\Iface
154
	 */
155
	public function getSaveAttributes() : array
156
	{
157
		return [];
158
	}
159
160
161
	/**
162
	 * Returns the attributes that can be used for searching.
163
	 *
164
	 * @param bool $withsub Return also attributes of sub-managers if true
165
	 * @return \Aimeos\Base\Criteria\Attribute\Iface[] List of attribute items
166
	 */
167
	public function getSearchAttributes( bool $withsub = true ) : array
168
	{
169
		return [];
170
	}
171
172
173
	/**
174
	 * Returns a new manager for attribute extensions
175
	 *
176
	 * @param string $manager Name of the sub manager type in lower case
177
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
178
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g Type, List's etc.
179
	 */
180
	public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
181
	{
182
		throw new \LogicException( 'Not implemented' );
183
	}
184
185
186
	/**
187
	 * Iterates over all matched items and returns the found ones
188
	 *
189
	 * @param \Aimeos\MShop\Common\Cursor\Iface $cursor Cursor object with filter, domains and cursor
190
	 * @param string[] $ref List of domains whose items should be fetched too
191
	 * @return \Aimeos\Map|null List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
192
	 */
193
	public function iterate( \Aimeos\MShop\Common\Cursor\Iface $cursor, array $ref = [] ) : ?\Aimeos\Map
194
	{
195
		return null;
196
	}
197
198
199
	/**
200
	 * Adds or updates an item object or a list of them.
201
	 *
202
	 * @param \Aimeos\MShop\Common\Item\Iface[]|\Aimeos\MShop\Common\Item\Iface $items Item or list of items whose data should be saved
203
	 * @param bool $fetch True if the new ID should be returned in the item
204
	 * @return \Aimeos\MShop\Common\Item\Iface[]|\Aimeos\MShop\Common\Item\Iface Saved item or items
205
	 */
206
	public function save( $items, bool $fetch = true )
207
	{
208
		return $items;
209
	}
210
211
212
	/**
213
	 * Searches for all items matching the given critera.
214
	 *
215
	 * @param \Aimeos\Base\Criteria\Iface $filter Criteria object with conditions, sortations, etc.
216
	 * @param string[] $ref List of domains to fetch list items and referenced items for
217
	 * @param int &$total Number of items that are available in total
218
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
219
	 */
220
	public function search( \Aimeos\Base\Criteria\Iface $filter, array $ref = [], int &$total = null ) : \Aimeos\Map
221
	{
222
		return map();
223
	}
224
225
226
	/**
227
	 * Injects the reference of the outmost object
228
	 *
229
	 * @param \Aimeos\MShop\Common\Manager\Iface $object Reference to the outmost manager or decorator
230
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
231
	 */
232
	public function setObject( \Aimeos\MShop\Common\Manager\Iface $object ) : \Aimeos\MShop\Common\Manager\Iface
233
	{
234
		$this->object = $object;
235
		return $this;
236
	}
237
238
239
	/**
240
	 * Starts a database transaction on the connection identified by the given name
241
	 *
242
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
243
	 */
244
	public function begin() : \Aimeos\MShop\Common\Manager\Iface
245
	{
246
		return $this;
247
	}
248
249
250
	/**
251
	 * Commits the running database transaction on the connection identified by the given name
252
	 *
253
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
254
	 */
255
	public function commit() : \Aimeos\MShop\Common\Manager\Iface
256
	{
257
		return $this;
258
	}
259
260
261
	/**
262
	 * Rolls back the running database transaction on the connection identified by the given name
263
	 *
264
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
265
	 */
266
	public function rollback() : \Aimeos\MShop\Common\Manager\Iface
267
	{
268
		return $this;
269
	}
270
271
272
	/**
273
	 * Applies the filters for the item type to the item
274
	 *
275
	 * @param object $item Item to apply the filter to
276
	 * @return object|null Object if the item should be used, null if not
277
	 */
278
	protected function applyFilter( $item )
279
	{
280
		foreach( $this->filterFcn as $iface => $fcnList )
281
		{
282
			if( is_object( $item ) && $item instanceof $iface )
283
			{
284
				foreach( $fcnList as $fcn )
285
				{
286
					if( $fcn( $item ) === null ) {
287
						return null;
288
					}
289
				}
290
			}
291
		}
292
293
		return $item;
294
	}
295
296
297
	/**
298
	 * Creates the criteria attribute items from the list of entries
299
	 *
300
	 * @param array $list Associative array of code as key and array with properties as values
301
	 * @return \Aimeos\Base\Criteria\Attribute\Standard[] List of criteria attribute items
302
	 */
303
	protected function createAttributes( array $list ) : array
304
	{
305
		$attr = [];
306
307
		foreach( $list as $key => $fields )
308
		{
309
			$fields['code'] = $fields['code'] ?? $key;
310
			$fields['internalcode'] = $fields['internalcode'] ?? $key;
311
			$attr[$key] = new \Aimeos\Base\Criteria\Attribute\Standard( $fields );
312
		}
313
314
		return $attr;
315
	}
316
317
318
	/**
319
	 * Returns the full configuration key for the passed last part
320
	 *
321
	 * @param string $name Configuration last part
322
	 * @return string Full configuration key
323
	 */
324
	protected function getConfigKey( string $name ) : string
325
	{
326
		$subPath = $this->getSubPath();
327
		return 'mshop/' . $this->getDomain() . '/manager/' . ( $subPath ? $subPath . '/' : '' ) . $name;
328
	}
329
330
331
	/**
332
	 * Returns the manager domain
333
	 *
334
	 * @return string Manager domain e.g. "product"
335
	 */
336
	protected function getDomain() : string
337
	{
338
		if( !isset( $this->domain ) ) {
339
			$this->initMethods();
340
		}
341
342
		return $this->domain;
343
	}
344
345
346
	/**
347
	 * Returns the manager path
348
	 *
349
	 * @return string Manager path e.g. "product/lists/type"
350
	 */
351
	protected function getManagerPath() : string
352
	{
353
		$subPath = $this->getSubPath();
354
		return $this->getDomain() . ( $subPath ? '/' . $subPath : '' );
355
	}
356
357
358
	/**
359
	 * Returns the prefix for the item properties and search keys.
360
	 *
361
	 * @return string Prefix for the item properties and search keys
362
	 */
363
	protected function prefix() : string
364
	{
365
		return '';
366
	}
367
368
369
	/**
370
	 * Returns the attribute helper functions for searching defined by the manager.
371
	 *
372
	 * @param \Aimeos\Base\Criteria\Attribute\Iface[] $attributes List of search attribute items
373
	 * @return array Associative array of attribute code and helper function
374
	 */
375
	protected function getSearchFunctions( array $attributes ) : array
376
	{
377
		$list = [];
378
		$iface = \Aimeos\Base\Criteria\Attribute\Iface::class;
379
380
		foreach( $attributes as $key => $item )
381
		{
382
			if( $item instanceof $iface ) {
383
				$list[$item->getCode()] = $item->getFunction();
384
			} else if( isset( $item['code'] ) ) {
385
				$list[$item['code']] = $item['function'] ?? null;
386
			} else {
387
				throw new \Aimeos\MShop\Exception( sprintf( 'Invalid attribute at position "%1$d"', $key ) );
388
			}
389
		}
390
391
		return $list;
392
	}
393
394
395
	/**
396
	 * Returns the item search key for the passed name
397
	 *
398
	 * @return string Item prefix e.g. "product.lists.type.id"
399
	 */
400
	protected function getSearchKey( string $name = '' ) : string
401
	{
402
		$subPath = $this->getSubPath();
403
		return $this->getDomain() . ( $subPath ? '.' . $subPath : '' ) . ( $name ? '.' . $name : '' );
404
	}
405
406
407
	/**
408
	 * Returns the attribute translations for searching defined by the manager.
409
	 *
410
	 * @param \Aimeos\Base\Criteria\Attribute\Iface[] $attributes List of search attribute items
411
	 * @return array Associative array of attribute code and internal attribute code
412
	 */
413
	protected function getSearchTranslations( array $attributes ) : array
414
	{
415
		$translations = [];
416
		$alias = $this->alias();
417
		$iface = \Aimeos\Base\Criteria\Attribute\Iface::class;
0 ignored issues
show
Unused Code introduced by
The assignment to $iface is dead and can be removed.
Loading history...
418
419
		foreach( $attributes as $key => $item )
420
		{
421
			if( $alias && strpos( $item->getInternalCode(), '"' ) === false ) {
0 ignored issues
show
Bug introduced by
It seems like $item->getInternalCode() can also be of type array; however, parameter $haystack of strpos() 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

421
			if( $alias && strpos( /** @scrutinizer ignore-type */ $item->getInternalCode(), '"' ) === false ) {
Loading history...
422
				$translations[$item->getCode()] = $alias . '."' . $item->getInternalCode() . '"';
0 ignored issues
show
Bug introduced by
Are you sure $item->getInternalCode() of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

422
				$translations[$item->getCode()] = $alias . '."' . /** @scrutinizer ignore-type */ $item->getInternalCode() . '"';
Loading history...
423
			} else {
424
				$translations[$item->getCode()] = $item->getInternalCode();
425
			}
426
		}
427
428
		return $translations;
429
	}
430
431
432
	/**
433
	 * Returns the attribute types for searching defined by the manager.
434
	 *
435
	 * @param \Aimeos\Base\Criteria\Attribute\Iface[] $attributes List of search attribute items
436
	 * @return array Associative array of attribute code and internal attribute type
437
	 */
438
	protected function getSearchTypes( array $attributes ) : array
439
	{
440
		$types = [];
441
		$iface = \Aimeos\Base\Criteria\Attribute\Iface::class;
442
443
		foreach( $attributes as $key => $item )
444
		{
445
			if( $item instanceof $iface ) {
446
				$types[$item->getCode()] = $item->getInternalType();
447
			} else if( isset( $item['code'] ) ) {
448
				$types[$item['code']] = $item['internaltype'];
449
			} else {
450
				throw new \Aimeos\MShop\Exception( sprintf( 'Invalid attribute at position "%1$d"', $key ) );
451
			}
452
		}
453
454
		return $types;
455
	}
456
457
458
	/**
459
	 * Returns the manager domain sub-path
460
	 *
461
	 * @return string Manager domain sub-path e.g. "lists/type"
462
	 */
463
	protected function getSubPath() : string
464
	{
465
		if( !isset( $this->subpath ) ) {
466
			$this->initMethods();
467
		}
468
469
		return $this->subpath;
470
	}
471
472
473
	/**
474
	 * Returns the name of the used table
475
	 *
476
	 * @return string Table name e.g. "mshop_product_lists_type"
477
	 */
478
	protected function getTable() : string
479
	{
480
		$subPath = $this->getSubPath();
481
		return 'mshop_' . $this->getDomain() . ( $subPath ? '_' . str_replace( '/', '_', $subPath ) : '' );
482
	}
483
484
485
	/**
486
	 * Initializes the trait
487
	 */
488
	protected function initMethods()
489
	{
490
		$parts = explode( '\\', strtolower( current( $this->classes() ) ) );
491
		array_shift( $parts ); array_shift( $parts ); // remove "Aimeos\MShop"
492
		array_pop( $parts );
493
494
		$this->domain = array_shift( $parts ) ?: '';
495
		array_shift( $parts ); // remove "manager"
496
		$this->subpath = join( '/', $parts );
497
	}
498
499
500
	/**
501
	 * Returns the outmost decorator of the decorator stack
502
	 *
503
	 * @return \Aimeos\MShop\Common\Manager\Iface Outmost decorator object
504
	 */
505
	protected function object() : \Aimeos\MShop\Common\Manager\Iface
506
	{
507
		return $this->object ?? $this;
508
	}
509
}
510