Typo3   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 481
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 20
eloc 100
c 5
b 0
f 0
dl 0
loc 481
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A clear() 0 9 2
A delete() 0 35 1
A __construct() 0 22 1
A createItemBase() 0 13 3
B saveItem() 0 155 7
A getSearchAttributes() 0 5 1
A getSubManager() 0 3 2
A getSaveAttributes() 0 3 1
A search() 0 108 2
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2025
6
 * @package MShop
7
 * @subpackage Group
8
 */
9
10
11
namespace Aimeos\MShop\Group\Manager;
12
13
14
/**
15
 * TYPO3 implementation of the group class
16
 *
17
 * @package MShop
18
 * @subpackage Group
19
 */
20
class Typo3
21
	extends \Aimeos\MShop\Group\Manager\Standard
22
{
23
	private array $searchConfig = array(
24
		'group.id' => array(
25
			'code' => 'group.id',
26
			'internalcode' => 'mgro."uid"',
27
			'label' => 'Group ID',
28
			'type' => 'int',
29
		),
30
		'group.code' => array(
31
			'code' => 'group.code',
32
			'internalcode' => 'mgro."title"',
33
			'label' => 'Group code',
34
			'type' => 'string',
35
		),
36
		'group.label' => array(
37
			'code' => 'group.label',
38
			'internalcode' => 'mgro."description"',
39
			'label' => 'Group label',
40
			'type' => 'string',
41
		),
42
		'group.ctime'=> array(
43
			'code' => 'group.ctime',
44
			'internalcode' => 'mgro."crdate"',
45
			'label' => 'Group creation time',
46
			'type' => 'datetime',
47
		),
48
		'group.mtime'=> array(
49
			'code' => 'group.mtime',
50
			'internalcode' => 'mgro."tstamp"',
51
			'label' => 'Group modification time',
52
			'type' => 'datetime',
53
		),
54
		'group.editor'=> array(
55
			'code' => 'group.editor',
56
			'internalcode' => '',
57
			'label' => 'Group editor',
58
			'type' => 'string',
59
		),
60
	);
61
62
	private array $plugins = [];
63
	private array $reverse = [];
64
	private int $pid;
65
66
67
	/**
68
	 * Initializes the group manager object
69
	 *
70
	 * @param \Aimeos\MShop\ContextIface $context Context object with required objects
71
	 */
72
	public function __construct( \Aimeos\MShop\ContextIface $context )
73
	{
74
		parent::__construct( $context );
75
76
		$plugin = new \Aimeos\Base\Criteria\Plugin\T3Datetime();
77
		$this->plugins['ctime'] = $this->reverse['crdate'] = $plugin;
78
		$this->plugins['mtime'] = $this->reverse['tstamp'] = $plugin;
79
80
		/** mshop/group/manager/typo3/pid-default
81
		 * Page ID the group records are assigned to
82
		 *
83
		 * In TYPO3, you can assign fe_group records to different sysfolders based
84
		 * on their page ID. These sysfolders can be use for user authorization and
85
		 * therefore, you need to assign the correct page ID to groups
86
		 * created or modified by the Aimeos admin backend.
87
		 *
88
		 * @param int TYPO3 page ID
89
		 * @since 2018.10
90
		 * @see mshop/customer/manager/typo3/pid-default
91
		 */
92
		$this->pid = (int) $context->config()->get( 'mshop/customer/manager/typo3/pid-default', 0 );
93
		$this->pid = (int) $context->config()->get( 'mshop/group/manager/typo3/pid-default', $this->pid );
94
	}
95
96
97
	/**
98
	 * Removes old entries from the database
99
	 *
100
	 * @param integer[] $siteids List of IDs for sites whose entries should be deleted
101
	 * @return \Aimeos\MShop\Common\Manager\Iface Same object for fluent interface
102
	 */
103
	public function clear( iterable $siteids ) : \Aimeos\MShop\Common\Manager\Iface
104
	{
105
		$path = 'mshop/group/manager/submanagers';
106
107
		foreach( $this->context()->config()->get( $path, [] ) as $domain ) {
108
			$this->object()->getSubManager( $domain )->clear( $siteids );
109
		}
110
111
		return $this;
112
	}
113
114
115
	/**
116
	 * Removes multiple items.
117
	 *
118
	 * @param \Aimeos\MShop\Common\Item\Iface[]|string[] $itemIds List of item objects or IDs of the items
119
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
120
	 */
121
	public function delete( $itemIds ) : \Aimeos\MShop\Common\Manager\Iface
122
	{
123
		/** mshop/group/manager/typo3/delete/mysql
124
		 * Deletes the items matched by the given IDs from the database
125
		 *
126
		 * @see mshop/group/manager/typo3/delete/ansi
127
		 */
128
129
		/** mshop/group/manager/typo3/delete/ansi
130
		 * Deletes the items matched by the given IDs from the database
131
		 *
132
		 * Removes the records specified by the given IDs from the group
133
		 * database. The records must be from the site that is configured via the
134
		 * context item.
135
		 *
136
		 * The ":cond" placeholder is replaced by the name of the ID column and
137
		 * the given ID or list of IDs while the site ID is bound to the question
138
		 * mark.
139
		 *
140
		 * The SQL statement should conform to the ANSI standard to be
141
		 * compatible with most relational database systems. This also
142
		 * includes using double quotes for table and column names.
143
		 *
144
		 * @param string SQL statement for deleting items
145
		 * @since 2015.08
146
		 * @category Developer
147
		 * @see mshop/group/manager/typo3/insert/ansi
148
		 * @see mshop/group/manager/typo3/update/ansi
149
		 * @see mshop/group/manager/typo3/newid/ansi
150
		 * @see mshop/group/manager/typo3/search/ansi
151
		 * @see mshop/group/manager/typo3/count/ansi
152
		 */
153
		$path = 'mshop/group/manager/typo3/delete';
154
155
		return $this->deleteItemsBase( $itemIds, $path, false, 'uid' );
156
	}
157
158
159
	/**
160
	 * Returns the additional column/search definitions
161
	 *
162
	 * @return array Associative list of column names as keys and items implementing \Aimeos\Base\Criteria\Attribute\Iface
163
	 */
164
	public function getSaveAttributes() : array
165
	{
166
		return [];
167
	}
168
169
170
	/**
171
	 * Returns the attributes that can be used for searching
172
	 *
173
	 * @param bool $withsub Return attributes of sub-managers too if true
174
	 * @return array List of attribute items implementing \Aimeos\Base\Criteria\Attribute\Iface
175
	 */
176
	public function getSearchAttributes( bool $withsub = true ) : array
177
	{
178
		$path = 'mshop/group/manager/submanagers';
179
180
		return $this->getSearchAttributesBase( $this->searchConfig, $path, [], $withsub );
181
	}
182
183
184
	/**
185
	 * Returns a new manager for group extensions
186
	 *
187
	 * @param string $manager Name of the sub manager type in lower case
188
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
189
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions
190
	 */
191
	public function getSubManager( string $manager, ?string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
192
	{
193
		return $this->getSubManagerBase( 'group/group', $manager, ( $name === null ? 'Typo3' : $name ) );
194
	}
195
196
197
	/**
198
	 * Inserts a new or updates an existing group item
199
	 *
200
	 * @param \Aimeos\MShop\Group\Item\Iface $item Group item
201
	 * @param boolean $fetch True if the new ID should be returned in the item
202
	 * @return \Aimeos\MShop\Group\Item\Iface $item Updated item including the generated ID
203
	 */
204
	protected function saveItem( \Aimeos\MShop\Group\Item\Iface $item, bool $fetch = true ) : \Aimeos\MShop\Group\Item\Iface
205
	{
206
		if( !$item->isModified() ) {
207
			return $item;
208
		}
209
210
		$context = $this->context();
211
		$conn = $context->db( $this->getResourceName() );
212
		$time = date_create_from_format( 'Y-m-d H:i:s', $context->datetime() )->getTimestamp();
213
214
		$id = $item->getId();
215
		$columns = $this->object()->getSaveAttributes();
216
217
		if( $id === null )
218
		{
219
			/** mshop/group/manager/typo3/insert/mysql
220
			 * Inserts a new group record into the database table
221
			 *
222
			 * @see mshop/group/manager/typo3/insert/ansi
223
			 */
224
225
			/** mshop/group/manager/typo3/insert/ansi
226
			 * Inserts a new group record into the database table
227
			 *
228
			 * Items with no ID yet (i.e. the ID is NULL) will be created in
229
			 * the database and the newly created ID retrieved afterwards
230
			 * using the "newid" SQL statement.
231
			 *
232
			 * The SQL statement must be a string suitable for being used as
233
			 * prepared statement. It must include question marks for binding
234
			 * the values from the group item to the statement before
235
			 * they are sent to the database server. The number of question
236
			 * marks must be the same as the number of columns listed in the
237
			 * INSERT statement. The order of the columns must correspond to
238
			 * the order in the save() method, so the correct values are
239
			 * bound to the columns.
240
			 *
241
			 * The SQL statement should conform to the ANSI standard to be
242
			 * compatible with most relational database systems. This also
243
			 * includes using double quotes for table and column names.
244
			 *
245
			 * @param string SQL statement for inserting records
246
			 * @since 2015.08
247
			 * @category Developer
248
			 * @see mshop/group/manager/typo3/update/ansi
249
			 * @see mshop/group/manager/typo3/newid/ansi
250
			 * @see mshop/group/manager/typo3/delete/ansi
251
			 * @see mshop/group/manager/typo3/search/ansi
252
			 * @see mshop/group/manager/typo3/count/ansi
253
			 */
254
			$path = 'mshop/group/manager/typo3/insert';
255
			$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

255
			$sql = $this->addSqlColumns( array_keys( $columns ), /** @scrutinizer ignore-type */ $this->getSqlConfig( $path ) );
Loading history...
256
		}
257
		else
258
		{
259
			/** mshop/group/manager/typo3/update/mysql
260
			 * Updates an existing group record in the database
261
			 *
262
			 * @see mshop/group/manager/typo3/update/ansi
263
			 */
264
265
			/** mshop/group/manager/typo3/update/ansi
266
			 * Updates an existing group record in the database
267
			 *
268
			 * Items which already have an ID (i.e. the ID is not NULL) will
269
			 * be updated in the database.
270
			 *
271
			 * The SQL statement must be a string suitable for being used as
272
			 * prepared statement. It must include question marks for binding
273
			 * the values from the group item to the statement before
274
			 * they are sent to the database server. The order of the columns
275
			 * must correspond to the order in the save() method, so the
276
			 * correct values are bound to the columns.
277
			 *
278
			 * The SQL statement should conform to the ANSI standard to be
279
			 * compatible with most relational database systems. This also
280
			 * includes using double quotes for table and column names.
281
			 *
282
			 * @param string SQL statement for updating records
283
			 * @since 2015.08
284
			 * @category Developer
285
			 * @see mshop/group/manager/typo3/insert/ansi
286
			 * @see mshop/group/manager/typo3/newid/ansi
287
			 * @see mshop/group/manager/typo3/delete/ansi
288
			 * @see mshop/group/manager/typo3/search/ansi
289
			 * @see mshop/group/manager/typo3/count/ansi
290
			 */
291
			$path = 'mshop/group/manager/typo3/update';
292
			$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ), false );
293
		}
294
295
		$idx = 1;
296
		$stmt = $this->getCachedStatement( $conn, $path, $sql );
297
298
		foreach( $columns as $name => $entry ) {
299
			$stmt->bind( $idx++, $item->get( $name ), \Aimeos\Base\Criteria\SQL::type( $entry->getType() ) );
300
		}
301
302
		$stmt->bind( $idx++, $this->pid, \Aimeos\Base\DB\Statement\Base::PARAM_INT );
303
		$stmt->bind( $idx++, $item->getCode() );
304
		$stmt->bind( $idx++, $item->getLabel() );
305
		$stmt->bind( $idx++, $time, \Aimeos\Base\DB\Statement\Base::PARAM_INT ); // mtime
306
307
		if( $id !== null ) {
308
			$stmt->bind( $idx++, $id, \Aimeos\Base\DB\Statement\Base::PARAM_INT );
309
			$item->setId( $id );
310
		} else {
311
			$stmt->bind( $idx++, $time, \Aimeos\Base\DB\Statement\Base::PARAM_INT ); // ctime
312
		}
313
314
		$stmt->execute()->finish();
315
316
		if( $id === null && $fetch === true )
317
		{
318
			/** mshop/group/manager/typo3/newid/mysql
319
			 * Retrieves the ID generated by the database when inserting a new record
320
			 *
321
			 * @see mshop/group/manager/typo3/newid/ansi
322
			 */
323
324
			/** mshop/group/manager/typo3/newid/ansi
325
			 * Retrieves the ID generated by the database when inserting a new record
326
			 *
327
			 * As soon as a new record is inserted into the database table,
328
			 * the database server generates a new and unique identifier for
329
			 * that record. This ID can be used for retrieving, updating and
330
			 * deleting that specific record from the table again.
331
			 *
332
			 * For MySQL:
333
			 *  SELECT LAST_INSERT_ID()
334
			 * For PostgreSQL:
335
			 *  SELECT currval('seq_mcus_id')
336
			 * For SQL Server:
337
			 *  SELECT SCOPE_IDENTITY()
338
			 * For Oracle:
339
			 *  SELECT "seq_mcus_id".CURRVAL FROM DUAL
340
			 *
341
			 * There's no way to retrive the new ID by a SQL statements that
342
			 * fits for most database servers as they implement their own
343
			 * specific way.
344
			 *
345
			 * @param string SQL statement for retrieving the last inserted record ID
346
			 * @since 2015.08
347
			 * @category Developer
348
			 * @see mshop/group/manager/typo3/insert/ansi
349
			 * @see mshop/group/manager/typo3/update/ansi
350
			 * @see mshop/group/manager/typo3/delete/ansi
351
			 * @see mshop/group/manager/typo3/search/ansi
352
			 * @see mshop/group/manager/typo3/count/ansi
353
			 */
354
			$path = 'mshop/group/manager/typo3/newid';
355
			$item->setId( $this->newId( $conn, $path ) );
356
		}
357
358
		return $item;
359
	}
360
361
362
	/**
363
	 * Returns the item objects matched by the given search criteria.
364
	 *
365
	 * @param \Aimeos\Base\Criteria\Iface $search Search criteria object
366
	 * @param array $ref List of domain items that should be fetched too
367
	 * @param int|null &$total Number of items that are available in total
368
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Group\Item\Iface
369
	 * @throws \Aimeos\MShop\Exception If retrieving items failed
370
	 */
371
	public function search( \Aimeos\Base\Criteria\Iface $search, array $ref = [], ?int &$total = null ) : \Aimeos\Map
372
	{
373
		$map = [];
374
		$context = $this->context();
375
		$conn = $context->db( $this->getResourceName() );
376
377
			$required = array( 'group' );
378
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
379
380
			/** mshop/group/manager/typo3/search
381
			 * Retrieves the records matched by the given criteria in the database
382
			 *
383
			 * Fetches the records matched by the given criteria from the group
384
			 * database. The records must be from one of the sites that are
385
			 * configured via the context item. If the current site is part of
386
			 * a tree of sites, the SELECT statement can retrieve all records
387
			 * from the current site and the complete sub-tree of sites.
388
			 *
389
			 * As the records can normally be limited by criteria from sub-managers,
390
			 * their tables must be joined in the SQL context. This is done by
391
			 * using the "internaldeps" property from the definition of the ID
392
			 * column of the sub-managers. These internal dependencies specify
393
			 * the JOIN between the tables and the used columns for joining. The
394
			 * ":joins" placeholder is then replaced by the JOIN strings from
395
			 * the sub-managers.
396
			 *
397
			 * To limit the records matched, conditions can be added to the given
398
			 * criteria object. It can contain comparisons like column names that
399
			 * must match specific values which can be combined by AND, OR or NOT
400
			 * operators. The resulting string of SQL conditions replaces the
401
			 * ":cond" placeholder before the statement is sent to the database
402
			 * server.
403
			 *
404
			 * If the records that are retrieved should be ordered by one or more
405
			 * columns, the generated string of column / sort direction pairs
406
			 * replaces the ":order" placeholder. In case no ordering is required,
407
			 * the complete ORDER BY part including the "\/*-orderby*\/...\/*orderby-*\/"
408
			 * markers is removed to speed up retrieving the records. Columns of
409
			 * sub-managers can also be used for ordering the result set but then
410
			 * no index can be used.
411
			 *
412
			 * The number of returned records can be limited and can start at any
413
			 * number between the begining and the end of the result set. For that
414
			 * the ":size" and ":start" placeholders are replaced by the
415
			 * corresponding values from the criteria object. The default values
416
			 * are 0 for the start and 100 for the size value.
417
			 *
418
			 * The SQL statement should conform to the ANSI standard to be
419
			 * compatible with most relational database systems. This also
420
			 * includes using double quotes for table and column names.
421
			 *
422
			 * @param string SQL statement for searching items
423
			 * @since 2015.08
424
			 * @category Developer
425
			 * @see mshop/group/manager/typo3/count
426
			 */
427
			$cfgPathSearch = 'mshop/group/manager/typo3/search';
428
429
			/** mshop/group/manager/typo3/count
430
			 * Counts the number of records matched by the given criteria in the database
431
			 *
432
			 * Counts all records matched by the given criteria from the group
433
			 * database. The records must be from one of the sites that are
434
			 * configured via the context item. If the current site is part of
435
			 * a tree of sites, the statement can count all records from the
436
			 * current site and the complete sub-tree of sites.
437
			 *
438
			 * As the records can normally be limited by criteria from sub-managers,
439
			 * their tables must be joined in the SQL context. This is done by
440
			 * using the "internaldeps" property from the definition of the ID
441
			 * column of the sub-managers. These internal dependencies specify
442
			 * the JOIN between the tables and the used columns for joining. The
443
			 * ":joins" placeholder is then replaced by the JOIN strings from
444
			 * the sub-managers.
445
			 *
446
			 * To limit the records matched, conditions can be added to the given
447
			 * criteria object. It can contain comparisons like column names that
448
			 * must match specific values which can be combined by AND, OR or NOT
449
			 * operators. The resulting string of SQL conditions replaces the
450
			 * ":cond" placeholder before the statement is sent to the database
451
			 * server.
452
			 *
453
			 * Both, the strings for ":joins" and for ":cond" are the same as for
454
			 * the "search" SQL statement.
455
			 *
456
			 * Contrary to the "search" statement, it doesn't return any records
457
			 * but instead the number of records that have been found. As counting
458
			 * thousands of records can be a long running task, the maximum number
459
			 * of counted records is limited for performance reasons.
460
			 *
461
			 * The SQL statement should conform to the ANSI standard to be
462
			 * compatible with most relational database systems. This also
463
			 * includes using double quotes for table and column names.
464
			 *
465
			 * @param string SQL statement for counting items
466
			 * @since 2015.08
467
			 * @category Developer
468
			 * @see mshop/group/manager/typo3/search
469
			 */
470
			$cfgPathCount = 'mshop/group/manager/typo3/count';
471
472
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
473
474
			while( $row = $results->fetch() ) {
475
				$map[(string) $row['group.id']] = $this->createItemBase( $row );
476
			}
477
478
		return map( $map );
479
	}
480
481
482
	/**
483
	 * Creates a new group item.
484
	 *
485
	 * @param array $values List of attributes for group item
486
	 * @return \Aimeos\MShop\Group\Item\Iface New group item
487
	 */
488
	protected function createItemBase( array $values = [] ) : \Aimeos\MShop\Group\Item\Iface
489
	{
490
		$values['group.siteid'] = $this->context()->locale()->getSiteId();
491
492
		if( array_key_exists( 'group.mtime', $values ) ) {
493
			$values['group.mtime'] = $this->reverse['tstamp']->reverse( $values['group.mtime'] );
494
		}
495
496
		if( array_key_exists( 'group.ctime', $values ) ) {
497
			$values['group.ctime'] = $this->reverse['crdate']->reverse( $values['group.ctime'] );
498
		}
499
500
		return new \Aimeos\MShop\Group\Item\Standard( 'group.', $values );
501
	}
502
}
503