Passed
Push — master ( 70aa88...10de15 )
by Aimeos
03:08
created

Typo3::delete()   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 1
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), 2014-2020
7
 * @package MShop
8
 * @subpackage Customer
9
 */
10
11
12
namespace Aimeos\MShop\Customer\Manager;
13
14
15
/**
16
 * Typo3 implementation of the customer class.
17
 *
18
 * @package MShop
19
 * @subpackage Customer
20
 */
21
class Typo3
22
	extends \Aimeos\MShop\Customer\Manager\Standard
23
{
24
	private $searchConfig = array(
25
		'customer.id' => array(
26
			'label' => 'Customer ID',
27
			'code' => 'customer.id',
28
			'internalcode' => 't3feu."uid"',
29
			'type' => 'integer',
30
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT,
31
			'public' => false,
32
		),
33
		'customer.siteid' => array(
34
			'code' => 'customer.siteid',
35
			'internalcode' => 't3feu."siteid"',
36
			'label' => 'Customer site ID',
37
			'type'=> 'string',
38
			'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR,
39
			'public' => false,
40
		),
41
		'customer.code' => array(
42
			'label' => 'Customer username',
43
			'code' => 'customer.code',
44
			'internalcode' => 't3feu."username"',
45
			'type' => 'string',
46
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR
47
		),
48
		'customer.label' => array(
49
			'label' => 'Customer name',
50
			'code' => 'customer.label',
51
			'internalcode' => 't3feu."name"',
52
			'type' => 'string',
53
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR
54
		),
55
		'customer.salutation' => array(
56
			'label' => 'Customer salutation',
57
			'code' => 'customer.salutation',
58
			'internalcode' => 't3feu."gender"',
59
			'type' => 'string',
60
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
61
		),
62
		'customer.company'=> array(
63
			'label' => 'Customer company',
64
			'code' => 'customer.company',
65
			'internalcode' => 't3feu."company"',
66
			'type' => 'string',
67
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
68
		),
69
		'customer.vatid'=> array(
70
			'label' => 'Customer VAT ID',
71
			'code' => 'customer.vatid',
72
			'internalcode' => 't3feu."vatid"',
73
			'type' => 'string',
74
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
75
		),
76
		'customer.title' => array(
77
			'label' => 'Customer title',
78
			'code' => 'customer.title',
79
			'internalcode' => 't3feu."title"',
80
			'type' => 'string',
81
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
82
		),
83
		'customer.firstname' => array(
84
			'label' => 'Customer firstname',
85
			'code' => 'customer.firstname',
86
			'internalcode' => 't3feu."first_name"',
87
			'type' => 'string',
88
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
89
		),
90
		'customer.lastname' => array(
91
			'label' => 'Customer lastname',
92
			'code' => 'customer.lastname',
93
			'internalcode' => 't3feu."last_name"',
94
			'type' => 'string',
95
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
96
		),
97
		'customer.address1' => array(
98
			'label' => 'Customer address part one',
99
			'code' => 'customer.address1',
100
			'internalcode' => 't3feu."address"',
101
			'type' => 'string',
102
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
103
		),
104
		'customer.address2' => array(
105
			'label' => 'Customer address part two',
106
			'code' => 'customer.address2',
107
			'internalcode' => 't3feu."address"',
108
			'type' => 'string',
109
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
110
		),
111
		'customer.address3' => array(
112
			'label' => 'Customer address part three',
113
			'code' => 'customer.address3',
114
			'internalcode' => 't3feu."address"',
115
			'type' => 'string',
116
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
117
		),
118
		'customer.postal' => array(
119
			'label' => 'Customer postal',
120
			'code' => 'customer.postal',
121
			'internalcode' => 't3feu."zip"',
122
			'type' => 'string',
123
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
124
		),
125
		'customer.city' => array(
126
			'label' => 'Customer city',
127
			'code' => 'customer.city',
128
			'internalcode' => 't3feu."city"',
129
			'type' => 'string',
130
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
131
		),
132
		'customer.state' => array(
133
			'label' => 'Customer state',
134
			'code' => 'customer.state',
135
			'internalcode' => 't3feu."zone"',
136
			'type' => 'string',
137
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
138
		),
139
		'customer.languageid' => array(
140
			'label' => 'Customer language',
141
			'code' => 'customer.languageid',
142
			'internalcode' => 't3feu."language"',
143
			'type' => 'string',
144
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
145
		),
146
		'customer.countryid' => array(
147
			'label' => 'Customer country',
148
			'code' => 'customer.countryid',
149
			'internalcode' => 'tsc."cn_iso_2"',
150
			'type' => 'string',
151
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
152
		),
153
		'customer.telephone' => array(
154
			'label' => 'Customer telephone',
155
			'code' => 'customer.telephone',
156
			'internalcode' => 't3feu."telephone"',
157
			'type' => 'string',
158
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
159
		),
160
		'customer.email' => array(
161
			'label' => 'Customer email',
162
			'code' => 'customer.email',
163
			'internalcode' => 't3feu."email"',
164
			'type' => 'string',
165
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
166
		),
167
		'customer.telefax' => array(
168
			'label' => 'Customer telefax',
169
			'code' => 'customer.telefax',
170
			'internalcode' => 't3feu."fax"',
171
			'type' => 'string',
172
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
173
		),
174
		'customer.website' => array(
175
			'label' => 'Customer website',
176
			'code' => 'customer.website',
177
			'internalcode' => 't3feu."www"',
178
			'type' => 'string',
179
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
180
		),
181
		'customer.longitude' => array(
182
			'label' => 'Customer longitude',
183
			'code' => 'customer.longitude',
184
			'internalcode' => 't3feu."longitude"',
185
			'type' => 'float',
186
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT,
187
		),
188
		'customer.latitude' => array(
189
			'label' => 'Customer latitude',
190
			'code' => 'customer.latitude',
191
			'internalcode' => 't3feu."latitude"',
192
			'type' => 'float',
193
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT,
194
		),
195
		'customer.birthday' => array(
196
			'label' => 'Customer birthday',
197
			'code' => 'customer.birthday',
198
			'internalcode' => 't3feu."date_of_birth"',
199
			'type' => 'date',
200
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
201
		),
202
		'customer.password'=> array(
203
			'label' => 'Customer password',
204
			'code' => 'customer.password',
205
			'internalcode' => 't3feu."password"',
206
			'type' => 'string',
207
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
208
		),
209
		'customer.status'=> array(
210
			'label' => 'Customer status',
211
			'code' => 'customer.status',
212
			'internalcode' => 't3feu."disable"',
213
			'type' => 'integer',
214
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_INT
215
		),
216
		'customer.dateverified'=> array(
217
			'label' => 'Customer verification date',
218
			'code' => 'customer.dateverified',
219
			'internalcode' => 't3feu."vdate"',
220
			'type' => 'date',
221
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
222
		),
223
		'customer.ctime'=> array(
224
			'label' => 'Customer creation time',
225
			'code' => 'customer.ctime',
226
			'internalcode' => 't3feu."crdate"',
227
			'type' => 'datetime',
228
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
229
		),
230
		'customer.mtime'=> array(
231
			'label' => 'Customer modification time',
232
			'code' => 'customer.mtime',
233
			'internalcode' => 't3feu."tstamp"',
234
			'type' => 'datetime',
235
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
236
		),
237
		// not available
238
		'customer.editor'=> array(
239
			'label' => 'Customer editor',
240
			'code' => 'customer.editor',
241
			'internalcode' => null,
242
			'type' => 'string',
243
			'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_STR,
244
		),
245
		'customer:has' => array(
246
			'code' => 'customer:has()',
247
			'internalcode' => ':site AND :key AND t3feuli."id"',
248
			'internaldeps' => ['LEFT JOIN "fe_users_list" AS t3feuli ON ( t3feuli."parentid" = t3feu."uid" )'],
249
			'label' => 'Customer has list item, parameter(<domain>[,<list type>[,<reference ID>)]]',
250
			'type' => 'null',
251
			'internaltype' => 'null',
252
			'public' => false,
253
		),
254
		'customer:prop' => array(
255
			'code' => 'customer:prop()',
256
			'internalcode' => ':site AND :key AND t3feupr."id"',
257
			'internaldeps' => ['LEFT JOIN "fe_users_property" AS t3feupr ON ( t3feupr."parentid" = t3feu."uid" )'],
258
			'label' => 'Customer has property item, parameter(<property type>[,<language code>[,<property value>]])',
259
			'type' => 'null',
260
			'internaltype' => 'null',
261
			'public' => false,
262
		),
263
	);
264
265
266
	private $plugins = [];
267
	private $reverse = [];
268
	private $helper;
269
	private $pid;
270
271
272
273
	/**
274
	 * Initializes a new customer manager object using the given context object.
275
	 *
276
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object with required objects
277
	 */
278
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
279
	{
280
		parent::__construct( $context );
281
282
		$plugin = new \Aimeos\MW\Criteria\Plugin\T3Salutation();
283
		$this->plugins['customer.salutation'] = $this->reverse['gender'] = $plugin;
284
285
		$plugin = new \Aimeos\MW\Criteria\Plugin\T3Status();
286
		$this->plugins['customer.status'] = $this->reverse['disable'] = $plugin;
287
288
		$plugin = new \Aimeos\MW\Criteria\Plugin\T3Date();
289
		$this->plugins['customer.birthday'] = $this->reverse['date_of_birth'] = $plugin;
290
291
		$plugin = new \Aimeos\MW\Criteria\Plugin\T3Datetime();
292
		$this->plugins['customer.ctime'] = $this->reverse['crdate'] = $plugin;
293
		$this->plugins['customer.mtime'] = $this->reverse['tstamp'] = $plugin;
294
295
		$this->pid = $context->getConfig()->get( 'mshop/customer/manager/typo3/pid-default', 0 );
296
297
298
		$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
299
		$level = $context->getConfig()->get( 'mshop/customer/manager/sitemode', $level );
300
301
302
		$this->searchConfig['customer:has']['function'] = function( &$source, array $params ) use ( $level ) {
303
304
			array_walk_recursive( $params, function( &$v ) {
305
				$v = trim( $v, '\'' );
306
			} );
307
308
			$keys = [];
309
			$params[1] = isset( $params[1] ) ? $params[1] : '';
310
			$params[2] = isset( $params[2] ) ? $params[2] : '';
311
312
			foreach( (array) $params[1] as $type ) {
313
				foreach( (array) $params[2] as $id ) {
314
					$keys[] = $params[0] . '|' . ( $type ? $type . '|' : '' ) . $id;
315
				}
316
			}
317
318
			$sitestr = $this->getSiteString( 't3feuli."siteid"', $level );
319
			$keystr = $this->toExpression( 't3feuli."key"', $keys, $params[2] !== '' ? '==' : '=~' );
320
			$source = str_replace( [':site', ':key'], [$sitestr, $keystr], $source );
321
322
			return $params;
323
		};
324
325
326
		$this->searchConfig['customer:prop']['function'] = function( &$source, array $params ) use ( $level ) {
327
328
			array_walk_recursive( $params, function( &$v ) {
329
				$v = trim( $v, '\'' );
330
			} );
331
332
			$keys = [];
333
			$params[1] = array_key_exists( 1, $params ) ? $params[1] : '';
334
			$params[2] = isset( $params[2] ) ? $params[2] : '';
335
336
			foreach( (array) $params[1] as $lang ) {
337
				foreach( (array) $params[2] as $id ) {
338
					$keys[] = $params[0] . '|' . ( $lang ? $lang . '|' : '' ) . ( $id !== '' ?  md5( $id ) : '' );
339
				}
340
			}
341
342
			$sitestr = $this->getSiteString( 't3feupr."siteid"', $level );
343
			$keystr = $this->toExpression( 't3feupr."key"', $keys, $params[2] !== '' ? '==' : '=~' );
344
			$source = str_replace( [':site', ':key'], [$sitestr, $keystr], $source );
345
346
			return $params;
347
		};
348
	}
349
350
351
	/**
352
	 * Removes old entries from the storage.
353
	 *
354
	 * @param string[] $siteids List of IDs for sites whose entries should be deleted
355
	 * @return \Aimeos\MShop\Common\Manager\Iface Same object for fluent interface
356
	 */
357
	public function clear( array $siteids ) : \Aimeos\MShop\Common\Manager\Iface
358
	{
359
		$path = 'mshop/customer/manager/submanagers';
360
		$default = ['address', 'group', 'lists', 'property'];
361
362
		foreach( $this->getContext()->getConfig()->get( $path, $default ) as $domain ) {
363
			$this->getObject()->getSubManager( $domain )->clear( $siteids );
364
		}
365
366
		return $this->clearBase( $siteids, 'mshop/customer/manager/typo3/delete' );
367
	}
368
369
370
	/**
371
	 * Creates a new empty item instance
372
	 *
373
	 * @param array $values Values the item should be initialized with
374
	 * @return \Aimeos\MShop\Customer\Item\Iface New site item object
375
	 */
376
	public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
377
	{
378
		$values['customer.siteid'] = $this->getContext()->getLocale()->getSiteId();
379
		return $this->createItemBase( $values );
380
	}
381
382
383
	/**
384
	 * Removes multiple items.
385
	 *
386
	 * @param \Aimeos\MShop\Common\Item\Iface[]|string[] $itemIds List of item objects or IDs of the items
387
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
388
	 */
389
	public function delete( $itemIds ) : \Aimeos\MShop\Common\Manager\Iface
390
	{
391
		$path = 'mshop/customer/manager/typo3/delete';
392
		return $this->deleteItemsBase( $itemIds, $path, true, 'uid' )->deleteRefItems( $itemIds );
393
	}
394
395
396
	/**
397
	 * Returns the list attributes that can be used for searching.
398
	 *
399
	 * @param bool $withsub Return also attributes of sub-managers if true
400
	 * @return array List of attribute items implementing \Aimeos\MW\Criteria\Attribute\Iface
401
	 */
402
	public function getSearchAttributes( bool $withsub = true ) : array
403
	{
404
		$path = 'mshop/customer/manager/submanagers';
405
		return $this->getSearchAttributesBase( $this->searchConfig, $path, ['address'], $withsub );
406
	}
407
408
409
	/**
410
	 * Saves a customer item object.
411
	 *
412
	 * @param \Aimeos\MShop\Customer\Item\Iface $item Customer item object
413
	 * @param bool $fetch True if the new ID should be returned in the item
414
	 * @return \Aimeos\MShop\Customer\Item\Iface $item Updated item including the generated ID
415
	 */
416
	public function saveItem( \Aimeos\MShop\Customer\Item\Iface $item, bool $fetch = true ) : \Aimeos\MShop\Customer\Item\Iface
417
	{
418
		if( !$item->isModified() )
419
		{
420
			$item = $this->savePropertyItems( $item, 'customer' );
421
			$item = $this->saveAddressItems( $item, 'customer' );
422
			return $this->saveListItems( $item, 'customer' );
423
		}
424
425
		$context = $this->getContext();
426
		$dbm = $context->getDatabaseManager();
427
		$dbname = $this->getResourceName();
428
		$conn = $dbm->acquire( $dbname );
429
430
		try
431
		{
432
			$id = $item->getId();
433
			$billingAddress = $item->getPaymentAddress();
434
			$columns = $this->getObject()->getSaveAttributes();
435
436
			if( $id === null )
437
			{
438
				/** mshop/customer/manager/typo3/insert
439
				 * Inserts a new customer record into the database table
440
				 *
441
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
442
				 * the database and the newly created ID retrieved afterwards
443
				 * using the "newid" SQL statement.
444
				 *
445
				 * The SQL statement must be a string suitable for being used as
446
				 * prepared statement. It must include question marks for binding
447
				 * the values from the customer item to the statement before they are
448
				 * sent to the database server. The number of question marks must
449
				 * be the same as the number of columns listed in the INSERT
450
				 * statement. The order of the columns must correspond to the
451
				 * order in the saveItems() method, so the correct values are
452
				 * bound to the columns.
453
				 *
454
				 * The SQL statement should conform to the ANSI standard to be
455
				 * compatible with most relational database systems. This also
456
				 * includes using double quotes for table and column names.
457
				 *
458
				 * @param string SQL statement for inserting records
459
				 * @since 2014.03
460
				 * @category Developer
461
				 * @see mshop/customer/manager/typo3/update
462
				 * @see mshop/customer/manager/typo3/newid
463
				 * @see mshop/customer/manager/typo3/delete
464
				 * @see mshop/customer/manager/typo3/search
465
				 * @see mshop/customer/manager/typo3/count
466
				 */
467
				$path = 'mshop/customer/manager/typo3/insert';
468
				$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

468
				$sql = $this->addSqlColumns( array_keys( $columns ), /** @scrutinizer ignore-type */ $this->getSqlConfig( $path ) );
Loading history...
469
			}
470
			else
471
			{
472
				/** mshop/customer/manager/typo3/update
473
				 * Updates an existing customer record in the database
474
				 *
475
				 * Items which already have an ID (i.e. the ID is not NULL) will
476
				 * be updated in the database.
477
				 *
478
				 * The SQL statement must be a string suitable for being used as
479
				 * prepared statement. It must include question marks for binding
480
				 * the values from the customer item to the statement before they are
481
				 * sent to the database server. The order of the columns must
482
				 * correspond to the order in the saveItems() method, so the
483
				 * correct values are bound to the columns.
484
				 *
485
				 * The SQL statement should conform to the ANSI standard to be
486
				 * compatible with most relational database systems. This also
487
				 * includes using double quotes for table and column names.
488
				 *
489
				 * @param string SQL statement for updating records
490
				 * @since 2014.03
491
				 * @category Developer
492
				 * @see mshop/customer/manager/typo3/insert
493
				 * @see mshop/customer/manager/typo3/newid
494
				 * @see mshop/customer/manager/typo3/delete
495
				 * @see mshop/customer/manager/typo3/search
496
				 * @see mshop/customer/manager/typo3/count
497
				 */
498
				$path = 'mshop/customer/manager/typo3/update';
499
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path ), false );
500
			}
501
502
			$address = $billingAddress->getAddress1();
503
504
			if( ( $part = $billingAddress->getAddress2() ) != '' ) {
505
				$address .= ' ' . $part;
506
			}
507
508
			if( ( $part = $billingAddress->getAddress3() ) != '' ) {
509
				$address .= ' ' . $part;
510
			}
511
512
			$idx = 1;
513
			$stmt = $this->getCachedStatement( $conn, $path, $sql );
514
515
			foreach( $columns as $name => $entry ) {
516
				$stmt->bind( $idx++, $item->get( $name ), $entry->getInternalType() );
517
			}
518
519
			// TYPO3 fe_users.static_info_country is a three letter ISO code instead a two letter one
520
			$stmt->bind( $idx++, $item->getLabel() );
521
			$stmt->bind( $idx++, $item->getCode() );
522
			$stmt->bind( $idx++, $this->plugins['customer.salutation']->translate( $billingAddress->getSalutation() ), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
523
			$stmt->bind( $idx++, $billingAddress->getCompany() );
524
			$stmt->bind( $idx++, $billingAddress->getVatID() );
525
			$stmt->bind( $idx++, $billingAddress->getTitle() );
526
			$stmt->bind( $idx++, $billingAddress->getFirstname() );
527
			$stmt->bind( $idx++, $billingAddress->getLastname() );
528
			$stmt->bind( $idx++, $address );
529
			$stmt->bind( $idx++, $billingAddress->getPostal() );
530
			$stmt->bind( $idx++, $billingAddress->getCity() );
531
			$stmt->bind( $idx++, $billingAddress->getState() );
532
			$stmt->bind( $idx++, $billingAddress->getLanguageId() );
533
			$stmt->bind( $idx++, $billingAddress->getTelephone() );
534
			$stmt->bind( $idx++, $billingAddress->getEmail() );
535
			$stmt->bind( $idx++, $billingAddress->getTelefax() );
536
			$stmt->bind( $idx++, $billingAddress->getWebsite() );
537
			$stmt->bind( $idx++, $billingAddress->getLongitude(), \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT );
538
			$stmt->bind( $idx++, $billingAddress->getLatitude(), \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT );
539
			$stmt->bind( $idx++, $this->plugins['customer.birthday']->translate( $billingAddress->getBirthday() ), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
540
			$stmt->bind( $idx++, $this->plugins['customer.status']->translate( $item->getStatus() ), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
541
			$stmt->bind( $idx++, $item->getPassword() );
542
			$stmt->bind( $idx++, time(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); // Modification time
543
			$stmt->bind( $idx++, $billingAddress->getCountryId() );
544
			$stmt->bind( $idx++, implode( ',', $item->getGroups() ) );
545
			$stmt->bind( $idx++, $this->pid, \Aimeos\MW\DB\Statement\Base::PARAM_INT ); // TYPO3 PID value
546
			$stmt->bind( $idx++, $context->getLocale()->getSiteId() );
547
548
			if( $id !== null ) {
549
				$stmt->bind( $idx, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
550
				$item->setId( $id );
551
			} else {
552
				$stmt->bind( $idx, time(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); // Creation time
553
			}
554
555
			$stmt->execute()->finish();
556
557
			if( $id === null && $fetch === true )
558
			{
559
				/** mshop/customer/manager/typo3/newid
560
				 * Retrieves the ID generated by the database when inserting a new record
561
				 *
562
				 * As soon as a new record is inserted into the database table,
563
				 * the database server generates a new and unique identifier for
564
				 * that record. This ID can be used for retrieving, updating and
565
				 * deleting that specific record from the table again.
566
				 *
567
				 * For MySQL:
568
				 *  SELECT LAST_INSERT_ID()
569
				 * For PostgreSQL:
570
				 *  SELECT currval('seq_mcus_id')
571
				 * For SQL Server:
572
				 *  SELECT SCOPE_IDENTITY()
573
				 * For Oracle:
574
				 *  SELECT "seq_mcus_id".CURRVAL FROM DUAL
575
				 *
576
				 * There's no way to retrive the new ID by a SQL statements that
577
				 * fits for most database servers as they implement their own
578
				 * specific way.
579
				 *
580
				 * @param string SQL statement for retrieving the last inserted record ID
581
				 * @since 2014.03
582
				 * @category Developer
583
				 * @see mshop/customer/manager/typo3/insert
584
				 * @see mshop/customer/manager/typo3/update
585
				 * @see mshop/customer/manager/typo3/delete
586
				 * @see mshop/customer/manager/typo3/search
587
				 * @see mshop/customer/manager/typo3/count
588
				 */
589
				$path = 'mshop/customer/manager/typo3/newid';
590
				$item->setId( $this->newId( $conn, $path ) );
591
			}
592
593
			$dbm->release( $conn, $dbname );
594
		}
595
		catch( \Exception $e )
596
		{
597
			$dbm->release( $conn, $dbname );
598
			throw $e;
599
		}
600
601
		$item = $this->savePropertyItems( $item, 'customer' );
602
		$item = $this->saveAddressItems( $item, 'customer' );
603
		return $this->saveListItems( $item, 'customer' );
604
	}
605
606
607
	/**
608
	 * Returns the item objects matched by the given search criteria.
609
	 *
610
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
611
	 * @param int|null &$total Number of items that are available in total
612
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Customer\Item\Iface
613
	 * @throws \Aimeos\MShop\Customer\Exception If creating items failed
614
	 */
615
	public function search( \Aimeos\MW\Criteria\Iface $search, array $ref = [], int &$total = null ) : \Aimeos\Map
616
	{
617
		$dbm = $this->getContext()->getDatabaseManager();
618
		$dbname = $this->getResourceName();
619
		$conn = $dbm->acquire( $dbname );
620
		$map = [];
621
622
		try
623
		{
624
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
625
			$cfgPathSearch = 'mshop/customer/manager/typo3/search';
626
			$cfgPathCount = 'mshop/customer/manager/typo3/count';
627
			$required = array( 'customer' );
628
629
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level, $this->plugins );
630
631
			while( ( $row = $results->fetch() ) !== null ) {
632
				$map[(string) $row['customer.id']] = $row;
633
			}
634
635
			$dbm->release( $conn, $dbname );
636
		}
637
		catch( \Exception $e )
638
		{
639
			$dbm->release( $conn, $dbname );
640
			throw $e;
641
		}
642
643
		$addrItems = [];
644
		if( in_array( 'customer/address', $ref, true ) ) {
645
			$addrItems = $this->getAddressItems( array_keys( $map ), 'customer' );
646
		}
647
648
		$propItems = []; $name = 'customer/property';
649
		if( isset( $ref[$name] ) || in_array( $name, $ref, true ) )
650
		{
651
			$propTypes = isset( $ref[$name] ) && is_array( $ref[$name] ) ? $ref[$name] : null;
652
			$propItems = $this->getPropertyItems( array_keys( $map ), 'customer', $propTypes );
653
		}
654
655
		return $this->buildItems( $map, $ref, 'customer', $addrItems, $propItems );
656
	}
657
658
659
	/**
660
	 * Returns a new manager for customer extensions
661
	 *
662
	 * @param string $manager Name of the sub manager type in lower case
663
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
664
	 * @return mixed Manager for different extensions, e.g stock, tags, locations, etc.
665
	 */
666
	public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
667
	{
668
		return $this->getSubManagerBase( 'customer', $manager, ( $name === null ? 'Typo3' : $name ) );
669
	}
670
671
672
	/**
673
	 * Creates a new customer item.
674
	 *
675
	 * @param array $values List of attributes for customer item
676
	 * @param \Aimeos\MShop\Common\Lists\Item\Iface[] $listItems List of list items
677
	 * @param \Aimeos\MShop\Common\Item\Iface[] $refItems List of referenced items
678
	 * @param \Aimeos\MShop\Common\Item\Address\Iface[] $addrItems List of referenced address items
679
	 * @param \Aimeos\MShop\Common\Item\Property\Iface[] $propItems List of property items
680
	 * @return \Aimeos\MShop\Customer\Item\Iface New customer item
681
	 */
682
	protected function createItemBase( array $values = [], array $listItems = [], array $refItems = [],
683
		array $addrItems = [], array $propItems = [] ) : \Aimeos\MShop\Common\Item\Iface
684
	{
685
		$helper = $this->getPasswordHelper();
686
		$values['customer.siteid'] = $this->getContext()->getLocale()->getSiteId();
687
688
		if( array_key_exists( 'date_of_birth', $values ) ) {
689
			$values['customer.birthday'] = $this->reverse['date_of_birth']->reverse( $values['date_of_birth'] );
690
		}
691
692
		if( array_key_exists( 'gender', $values ) ) {
693
			$values['customer.salutation'] = $this->reverse['gender']->reverse( $values['gender'] );
694
		}
695
696
		if( array_key_exists( 'disable', $values ) ) {
697
			$values['customer.status'] = $this->reverse['disable']->reverse( $values['disable'] );
698
		}
699
700
		if( array_key_exists( 'tstamp', $values ) ) {
701
			$values['customer.mtime'] = $this->reverse['tstamp']->reverse( $values['tstamp'] );
702
		}
703
704
		if( array_key_exists( 'crdate', $values ) ) {
705
			$values['customer.ctime'] = $this->reverse['crdate']->reverse( $values['crdate'] );
706
		}
707
708
		if( array_key_exists( 'groups', $values ) && $values['groups'] !== '' ) {
709
			$values['customer.groups'] = explode( ',', $values['groups'] );
710
		}
711
712
713
		$address = new \Aimeos\MShop\Common\Item\Address\Simple( 'customer.', $values );
714
715
		return new \Aimeos\MShop\Customer\Item\Standard(
716
			$address, $values, $listItems, $refItems, $addrItems, $propItems, $helper
717
		);
718
	}
719
720
721
	/**
722
	 * Returns a password helper object based on the configuration.
723
	 *
724
	 * @return \Aimeos\MShop\Common\Helper\Password\Iface Password helper object
725
	 * @throws \Aimeos\MShop\Exception If the name is invalid or the class isn't found
726
	 */
727
	protected function getPasswordHelper() : \Aimeos\MShop\Common\Helper\Password\Iface
728
	{
729
		if( $this->helper ) {
730
			return $this->helper;
731
		}
732
733
		$classname = \Aimeos\MShop\Common\Helper\Password\Typo3::class;
734
735
		if( class_exists( $classname ) === false ) {
736
			throw new \Aimeos\MShop\Exception( sprintf( 'Class "%1$s" not available', $classname ) );
737
		}
738
739
		$context = $this->getContext();
740
		$object = ( method_exists( $context, 'getHasherTypo3' ) ? $context->getHasherTypo3() : null );
741
742
		$helper = new $classname( array( 'object' => $object ) );
743
744
		return $this->helper = self::checkClass( \Aimeos\MShop\Common\Helper\Password\Iface::class, $helper );
745
	}
746
}
747