Completed
Push — master ( 48019c...a8bfd3 )
by Aimeos
10:27
created

MShopAddDataAbstract::getAttributeItem()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 3
dl 0
loc 15
rs 9.2
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, 2014
6
 * @copyright Aimeos (aimeos.org), 2015-2016
7
 */
8
9
10
namespace Aimeos\MW\Setup\Task;
11
12
13
/**
14
 * Adds records to tables.
15
 */
16
class MShopAddDataAbstract extends \Aimeos\MW\Setup\Task\Base
17
{
18
	private $attributes;
19
20
21
	/**
22
	 * Initializes the object
23
	 *
24
	 * @param \Aimeos\MW\Setup\DBSchema\Iface $schema
25
	 * @param \Aimeos\MW\DB\Connection\Iface $conn
26
	 * @param \Aimeos\MShop\Context\Item\Iface|null $additional
27
	 * @throws \Aimeos\MW\Setup\Exception
28
	 */
29
	public function __construct( \Aimeos\MW\Setup\DBSchema\Iface $schema, \Aimeos\MW\DB\Connection\Iface $conn, $additional = null )
30
	{
31
		$iface = '\\Aimeos\\MShop\\Context\\Item\\Iface';
32
		if( !( $additional instanceof $iface ) ) {
33
			throw new \Aimeos\MW\Setup\Exception( sprintf( 'Additionally provided object is not of type "%1$s"', $iface ) );
34
		}
35
36
		parent::__construct( $schema, $conn, $additional );
37
	}
38
39
40
	/**
41
	 * Returns the list of task names which this task depends on.
42
	 *
43
	 * @return string[] List of task names
44
	 */
45
	public function getPreDependencies()
46
	{
47
		return array( 'TablesCreateMShop' );
48
	}
49
50
51
	/**
52
	 * Returns the list of task names which depends on this task.
53
	 *
54
	 * @return array List of task names
55
	 */
56
	public function getPostDependencies()
57
	{
58
		return [];
59
	}
60
61
62
	/**
63
	 * Executes the task for MySQL databases.
64
	 */
65
	protected function mysql()
66
	{
67
		// executed by tasks in sub-directories for specific sites
68
	}
69
70
71
	/**
72
	 * Adds the attributes to the given parent in the database.
73
	 *
74
	 * @param string $parentid ID of the parent item where the media should be associated to
75
	 * @param array $data Two dimensional associative list of attribute data
76
	 * @param string $domain Domain name the texts should be added to, e.g. 'catalog'
77
	 */
78
	protected function addAttributes( $parentid, array $data, $domain )
79
	{
80
		$context = $this->getContext();
81
		$attrManager = \Aimeos\MShop\Factory::createManager( $context, 'attribute' );
82
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
83
84
85
		$item = $attrManager->createItem();
86
		$item->setDomain( $domain );
87
88
		$listItem = $listManager->createItem();
89
		$listItem->setParentId( $parentid );
90
		$listItem->setDomain( 'attribute' );
91
92
93
		foreach( $data as $entry )
94
		{
95
			if( ( $attrItem = $this->getAttributeItem( $domain, $entry['type'], $entry['code'] ) ) === null )
96
			{
97
				$item->setId( null );
98
				$item->setTypeId( $this->getTypeId( 'attribute/type', $domain, $entry['type'] ) );
99
				$item->setCode( $entry['code'] );
100
				$item->setLabel( $entry['label'] );
101
				$item->setPosition( $entry['position'] );
102
				$item->setStatus( $entry['status'] );
103
104
				$attrManager->saveItem( $item );
105
				$id = $item->getId();
106
			}
107
			else
108
			{
109
				$id = $attrItem->getId();
110
			}
111
112
			$listItem->setId( null );
113
			$listItem->setTypeId( $this->getTypeId( $domain . '/lists/type', 'attribute', $entry['list-type'] ) );
114
			$listItem->setDateStart( $entry['list-start'] );
115
			$listItem->setDateEnd( $entry['list-end'] );
116
			$listItem->setConfig( $entry['list-config'] );
117
			$listItem->setPosition( $entry['list-position'] );
118
			$listItem->setStatus( $entry['list-status'] );
119
			$listItem->setRefId( $id );
120
121
			$listManager->saveItem( $listItem, false );
122
123
124
			if( isset( $entry['attribute'] ) ) {
125
				$this->addAttributes( $id, $entry['attribute'], 'attribute' );
126
			}
127
128
			if( isset( $entry['media'] ) ) {
129
				$this->addMedia( $id, $entry['media'], 'attribute' );
130
			}
131
132
			if( isset( $entry['price'] ) ) {
133
				$this->addPrices( $id, $entry['price'], 'attribute' );
134
			}
135
136
			if( isset( $entry['text'] ) ) {
137
				$this->addTexts( $id, $entry['text'], 'attribute' );
138
			}
139
		}
140
	}
141
142
143
	/**
144
	 * Adds the media to the given parent in the database.
145
	 *
146
	 * @param string $parentid ID of the parent item where the media should be associated to
147
	 * @param array $data Two dimensional associative list of media data
148
	 * @param string $domain Domain name the texts should be added to, e.g. 'catalog'
149
	 */
150
	protected function addMedia( $parentid, array $data, $domain )
151
	{
152
		$context = $this->getContext();
153
		$mediaManager = \Aimeos\MShop\Factory::createManager( $context, 'media' );
154
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
155
156
157
		$item = $mediaManager->createItem();
158
		$item->setDomain( $domain );
159
160
		$listItem = $listManager->createItem();
161
		$listItem->setParentId( $parentid );
162
		$listItem->setDomain( 'media' );
163
164
165
		foreach( $data as $entry )
166
		{
167
			$item->setId( null );
168
			$item->setTypeId( $this->getTypeId( 'media/type', $domain, $entry['type'] ) );
169
			$item->setLanguageId( $entry['languageid'] );
170
			$item->setMimetype( $entry['mimetype'] );
171
			$item->setPreview( $entry['preview'] );
172
			$item->setUrl( $entry['url'] );
173
			$item->setLabel( $entry['label'] );
174
			$item->setStatus( $entry['status'] );
175
176
			$mediaManager->saveItem( $item );
177
178
			$listItem->setId( null );
179
			$listItem->setTypeId( $this->getTypeId( $domain . '/lists/type', 'media', $entry['list-type'] ) );
180
			$listItem->setDateStart( $entry['list-start'] );
181
			$listItem->setDateEnd( $entry['list-end'] );
182
			$listItem->setConfig( $entry['list-config'] );
183
			$listItem->setPosition( $entry['list-position'] );
184
			$listItem->setStatus( $entry['list-status'] );
185
			$listItem->setRefId( $item->getId() );
186
187
			$listManager->saveItem( $listItem, false );
188
189
190
			if( isset( $entry['attribute'] ) ) {
191
				$this->addAttributes( $item->getId(), $entry['attribute'], 'media' );
192
			}
193
194
			if( isset( $entry['media'] ) ) {
195
				$this->addMedia( $item->getId(), $entry['media'], 'media' );
196
			}
197
198
			if( isset( $entry['price'] ) ) {
199
				$this->addPrices( $item->getId(), $entry['price'], 'media' );
200
			}
201
202
			if( isset( $entry['text'] ) ) {
203
				$this->addTexts( $item->getId(), $entry['text'], 'media' );
204
			}
205
		}
206
	}
207
208
209
	/**
210
	 * Adds the prices to the given parent in the database.
211
	 *
212
	 * @param string $parentid ID of the parent item where the media should be associated to
213
	 * @param array $data Two dimensional associative list of price data
214
	 * @param string $domain Domain name the texts should be added to, e.g. 'catalog'
215
	 */
216
	protected function addPrices( $parentid, array $data, $domain )
217
	{
218
		$context = $this->getContext();
219
		$mediaManager = \Aimeos\MShop\Factory::createManager( $context, 'price' );
220
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
221
222
223
		$item = $mediaManager->createItem();
224
		$item->setDomain( $domain );
225
226
		$listItem = $listManager->createItem();
227
		$listItem->setParentId( $parentid );
228
		$listItem->setDomain( 'price' );
229
230
231
		foreach( $data as $entry )
232
		{
233
			$item->setId( null );
234
			$item->setLabel( $entry['label'] );
235
			$item->setTypeId( $this->getTypeId( 'price/type', $domain, $entry['type'] ) );
236
			$item->setCurrencyId( $entry['currencyid'] );
237
			$item->setQuantity( $entry['quantity'] );
238
			$item->setValue( $entry['value'] );
239
			$item->setCosts( $entry['costs'] );
240
			$item->setRebate( $entry['rebate'] );
241
			$item->setTaxRate( $entry['taxrate'] );
242
			$item->setStatus( $entry['status'] );
243
244
			$mediaManager->saveItem( $item );
245
246
			$listItem->setId( null );
247
			$listItem->setTypeId( $this->getTypeId( $domain . '/lists/type', 'price', $entry['list-type'] ) );
248
			$listItem->setDateStart( $entry['list-start'] );
249
			$listItem->setDateEnd( $entry['list-end'] );
250
			$listItem->setConfig( $entry['list-config'] );
251
			$listItem->setPosition( $entry['list-position'] );
252
			$listItem->setStatus( $entry['list-status'] );
253
			$listItem->setRefId( $item->getId() );
254
255
			$listManager->saveItem( $listItem, false );
256
257
258
			if( isset( $entry['attribute'] ) ) {
259
				$this->addAttributes( $item->getId(), $entry['attribute'], 'price' );
260
			}
261
262
			if( isset( $entry['media'] ) ) {
263
				$this->addMedia( $item->getId(), $entry['media'], 'price' );
264
			}
265
266
			if( isset( $entry['price'] ) ) {
267
				$this->addPrices( $item->getId(), $entry['price'], 'price' );
268
			}
269
270
			if( isset( $entry['text'] ) ) {
271
				$this->addTexts( $item->getId(), $entry['text'], 'price' );
272
			}
273
		}
274
	}
275
276
277
	/**
278
	 * Adds the texts to the given parent in the database.
279
	 *
280
	 * @param string $parentid ID of the parent item where the media should be associated to
281
	 * @param array $data Two dimensional associative list text data
282
	 * @param string $domain Domain name the texts should be added to, e.g. 'catalog'
283
	 */
284
	protected function addTexts( $parentid, array $data, $domain )
285
	{
286
		$context = $this->getContext();
287
		$textManager = \Aimeos\MShop\Factory::createManager( $context, 'text' );
288
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
289
290
291
		$item = $textManager->createItem();
292
		$item->setDomain( $domain );
293
294
		$listItem = $listManager->createItem();
295
		$listItem->setParentId( $parentid );
296
		$listItem->setDomain( 'text' );
297
298
299
		foreach( $data as $entry )
300
		{
301
			$item->setId( null );
302
			$item->setTypeId( $this->getTypeId( 'text/type', $domain, $entry['type'] ) );
303
			$item->setLanguageId( $entry['languageid'] );
304
			$item->setContent( $entry['content'] );
305
			$item->setLabel( $entry['label'] );
306
			$item->setStatus( $entry['status'] );
307
308
			$textManager->saveItem( $item );
309
310
			$listItem->setId( null );
311
			$listItem->setTypeId( $this->getTypeId( $domain . '/lists/type', 'text', $entry['list-type'] ) );
312
			$listItem->setDateStart( $entry['list-start'] );
313
			$listItem->setDateEnd( $entry['list-end'] );
314
			$listItem->setConfig( $entry['list-config'] );
315
			$listItem->setPosition( $entry['list-position'] );
316
			$listItem->setStatus( $entry['list-status'] );
317
			$listItem->setRefId( $item->getId() );
318
319
			$listManager->saveItem( $listItem, false );
320
321
322
			if( isset( $entry['attribute'] ) ) {
323
				$this->addAttributes( $item->getId(), $entry['attribute'], 'text' );
324
			}
325
326
			if( isset( $entry['media'] ) ) {
327
				$this->addMedia( $item->getId(), $entry['media'], 'text' );
328
			}
329
330
			if( isset( $entry['price'] ) ) {
331
				$this->addPrices( $item->getId(), $entry['price'], 'text' );
332
			}
333
334
			if( isset( $entry['text'] ) ) {
335
				$this->addTexts( $item->getId(), $entry['text'], 'text' );
336
			}
337
		}
338
	}
339
340
341
	/**
342
	 * Adds the products to the given parent in the database.
343
	 *
344
	 * @param string $parentid ID of the parent item where the products should be associated to
345
	 * @param array $data Two dimensional associative list of product data
346
	 * @param string $domain Domain name the texts should be added to, e.g. 'catalog'
347
	 */
348
	protected function addProducts( $parentid, array $data, $domain )
349
	{
350
		$context = $this->getContext();
351
		$productManager = \Aimeos\MShop\Factory::createManager( $context, 'product' );
352
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
353
354
355
		$listItem = $listManager->createItem();
356
		$listItem->setParentId( $parentid );
357
		$listItem->setDomain( 'product' );
358
359
360
		$codes = [];
361
362
		foreach( $data as $entry ) {
363
			$codes[$entry['code']] = null;
364
		}
365
366
		$search = $productManager->createSearch();
367
		$search->setConditions( $search->compare( '==', 'product.code', array_keys( $codes ) ) );
368
		$products = $productManager->searchItems( $search );
369
370
		foreach( $products as $product ) {
371
			$codes[$product->getCode()] = $product->getId();
372
		}
373
374
375
		foreach( $data as $entry )
376
		{
377
			if( !isset( $codes[$entry['code']] ) ) {
378
				throw new \RuntimeException( sprintf( 'No product for code "%1$s" found', $entry['code'] ) );
379
			}
380
381
			$listItem->setId( null );
382
			$listItem->setTypeId( $this->getTypeId( $domain . '/lists/type', 'product', $entry['list-type'] ) );
383
			$listItem->setDateStart( $entry['list-start'] );
384
			$listItem->setDateEnd( $entry['list-end'] );
385
			$listItem->setConfig( $entry['list-config'] );
386
			$listItem->setPosition( $entry['list-position'] );
387
			$listItem->setStatus( $entry['list-status'] );
388
			$listItem->setRefId( $codes[$entry['code']] );
389
390
			$listManager->saveItem( $listItem, false );
391
		}
392
	}
393
394
395
	/**
396
	 * Adds stock levels to the given product in the database.
397
	 *
398
	 * @param string $productcode Code of the product item where the stock levels should be associated to
399
	 * @param array $data Two dimensional associative list of product stock data
400
	 */
401
	protected function addProductStock( $productcode, array $data )
402
	{
403
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'stock/type' );
404
405
		$types = [];
406
		foreach( $manager->searchItems( $manager->createSearch() ) as $id => $item ) {
407
			$types[$item->getCode()] = $id;
408
		}
409
410
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'stock' );
411
412
		$item = $manager->createItem();
413
		$item->setProductCode( $productcode );
414
415
		foreach( $data as $entry )
416
		{
417
			$item->setId( null );
418
			$item->setDateBack( $entry['dateback'] );
419
			$item->setStockLevel( $entry['stocklevel'] );
420
			$item->setTypeId( $types[$entry['typeid']] );
421
422
			$manager->saveItem( $item, false );
423
		}
424
	}
425
426
427
	/**
428
	 * Returns the attribute for the given code, type and domain
429
	 *
430
	 * @param string $domain Domain the attribute belongs to
431
	 * @param string $type Attribute type
432
	 * @param string $code Attribute code
433
	 * @return \Aimeos\MShop\Attribute\Item\Iface|null Found attribute item or null if not available
434
	 */
435
	protected function getAttributeItem( $domain, $type, $code )
436
	{
437
		if( $this->attributes === null )
438
		{
439
			$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'attribute' );
440
441
			foreach( $manager->searchItems( $manager->createSearch() ) as $item ) {
442
				$this->attributes[$item->getDomain()][$item->getType()][$item->getCode()] = $item;
443
			}
444
		}
445
446
		if( isset( $this->attributes[$domain][$type][$code] ) ) {
447
			return $this->attributes[$domain][$type][$code];
448
		}
449
	}
450
451
452
	/**
453
	 * Returns the context.
454
	 *
455
	 * @return \Aimeos\MShop\Context\Item\Iface Context item
456
	 */
457
	protected function getContext()
458
	{
459
		return $this->additional;
460
	}
461
462
463
	/**
464
	 * Returns the type ID for the given type and domain found by the manager
465
	 *
466
	 * @param string $name Manager name like 'catalog/lists/type'
467
	 * @param string $domain Domain of the type item we are looking for, e.g. 'text'
468
	 * @param string $type Type code of the item we are looking for, e.g. 'default'
469
	 * @return string Type ID
470
	 */
471
	protected function getTypeId( $name, $domain, $type )
472
	{
473
		$key = str_replace( '/', '.', $name );
474
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), $name );
475
476
		$search = $manager->createSearch();
477
		$expr = array(
478
			$search->compare( '==', $key . '.domain', $domain ),
479
			$search->compare( '==', $key . '.code', $type ),
480
		);
481
		$search->setConditions( $search->combine( '&&', $expr ) );
482
483
		$result = $manager->searchItems( $search );
484
485
		if( ( $item = reset( $result ) ) === false ) {
486
			throw new \RuntimeException( sprintf( 'No type item found for "%1$s/%2$s" using "%3$s"', $domain, $type, $name ) );
487
		}
488
489
		return $item->getId();
490
	}
491
492
493
	/**
494
	 * Deletes the demo items from the given parent ID in the database.
495
	 *
496
	 * @param string $parentid ID of the parent item where the associated items should be removed from
497
	 * @param string $name Name of the list manager, e.g. 'catalog/lists'
498
	 * @param string $domain Name of the domain the items are associated to, e.g. 'catalog'
499
	 * @param string $refdomain Name of the domain to remove the items from, e.g. 'text'
500
	 */
501
	protected function removeItems( $parentid, $name, $domain, $refdomain )
502
	{
503
		$context = $this->getContext();
504
		$key = str_replace( '/', '.', $name );
505
506
		$manager = \Aimeos\MShop\Factory::createManager( $context, $refdomain );
507
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $name );
508
509
510
		$search = $manager->createSearch();
511
		$expr = array(
512
			$search->compare( '==', $refdomain . '.domain', $domain ),
513
			$search->compare( '=~', $refdomain . '.label', 'Demo' ),
514
		);
515
		$search->setConditions( $search->combine( '&&', $expr ) );
516
517
		$ids = array_keys( $manager->searchItems( $search ) );
518
		$manager->deleteItems( $ids );
519
520
521
		$search = $listManager->createSearch();
522
		$expr = array(
523
			$search->compare( '==', $key . '.parentid', $parentid ),
524
			$search->compare( '==', $key . '.domain', $refdomain ),
525
			$search->compare( '==', $key . '.refid', $ids ),
526
		);
527
		$search->setConditions( $search->combine( '&&', $expr ) );
528
529
		$listIds = array_keys( $listManager->searchItems( $search ) );
530
		$listManager->deleteItems( $listIds );
531
	}
532
533
534
	/**
535
	 * Deletes the references to non-existent or demo items in the database.
536
	 *
537
	 * @param string $parentid ID of the parent item where the associated items should be removed from
538
	 * @param string $name Name of the list manager, e.g. 'catalog/lists'
539
	 * @param string $refdomain Name of the domain to remove the items from, e.g. 'product'
540
	 */
541
	protected function removeListItems( $parentid, $name, $refdomain )
542
	{
543
		$start = 0;
544
		$context = $this->getContext();
545
		$key = str_replace( '/', '.', $name );
546
547
		$manager = \Aimeos\MShop\Factory::createManager( $context, $refdomain );
548
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $name );
549
550
551
		$search = $listManager->createSearch();
552
		$expr = array(
553
			$search->compare( '==', $key . '.parentid', $parentid ),
554
			$search->compare( '==', $key . '.domain', $refdomain ),
555
		);
556
		$search->setConditions( $search->combine( '&&', $expr ) );
557
558
		do
559
		{
560
			$refIds = $listIds = $map = [];
561
			$result = $listManager->searchItems( $search );
562
563
			foreach( $result as $id => $listItem )
564
			{
565
				$refIds[] = $listItem->getRefId();
566
				$map[$listItem->getRefId()][] = $id;
567
			}
568
569
570
			$search = $manager->createSearch();
571
			$search->setConditions( $search->compare( '==', $refdomain . '.id', $refIds ) );
572
			$ids = array_keys( $manager->searchItems( $search ) );
573
574
			foreach( array_diff( $refIds, $ids ) as $refId ) {
575
				$listIds = array_merge( $listIds, $map[$refId] );
576
			}
577
578
			$listManager->deleteItems( $listIds );
579
580
581
			$count = count( $result );
582
			$start += $count;
583
			$search->setSlice( $start );
584
		}
585
		while( $count == $search->getSliceSize() );
586
587
588
		$search = $manager->createSearch();
589
		$search->setConditions( $search->compare( '=~', $refdomain . '.label', 'Demo' ) );
590
		$ids = array_keys( $manager->searchItems( $search ) );
591
592
		$search = $listManager->createSearch();
593
		$expr = array(
594
			$search->compare( '==', $key . '.parentid', $parentid ),
595
			$search->compare( '==', $key . '.refid', $ids ),
596
			$search->compare( '==', $key . '.domain', $refdomain ),
597
		);
598
		$search->setConditions( $search->combine( '&&', $expr ) );
599
600
		$listManager->deleteItems( array_keys( $listManager->searchItems( $search ) ) );
601
	}
602
603
604
	/**
605
	 * Starts a new transation
606
	 */
607
	protected function txBegin()
608
	{
609
		$dbm = $this->additional->getDatabaseManager();
610
611
		$conn = $dbm->acquire();
612
		$conn->begin();
613
		$dbm->release( $conn );
614
	}
615
616
617
	/**
618
	 * Commits an existing transaction
619
	 */
620
	protected function txCommit()
621
	{
622
		$dbm = $this->additional->getDatabaseManager();
623
624
		$conn = $dbm->acquire();
625
		$conn->commit();
626
		$dbm->release( $conn );
627
	}
628
}