Completed
Push — master ( a3e1ac...484d40 )
by Aimeos
02:36
created

Standard   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 9
dl 0
loc 165
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 36 1
B process() 0 52 7
B checkEntry() 0 10 6
A deleteListItems() 0 15 1
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2016
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Common\Product\Import\Csv\Processor\Product;
12
13
14
/**
15
 * Product processor for CSV imports
16
 *
17
 * @package Controller
18
 * @subpackage Common
19
 */
20
class Standard
21
	extends \Aimeos\Controller\Common\Product\Import\Csv\Processor\Base
0 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
22
	implements \Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
23
{
24
	/** controller/common/product/import/csv/processor/product/name
25
	 * Name of the product processor implementation
26
	 *
27
	 * Use "Myname" if your class is named "\Aimeos\Controller\Common\Product\Import\Csv\Processor\Product\Myname".
28
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
29
	 *
30
	 * @param string Last part of the processor class name
31
	 * @since 2015.10
32
	 * @category Developer
33
	 */
34
35
	private $cache;
36
	private $listTypes;
37
38
39
	/**
40
	 * Initializes the object
41
	 *
42
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
43
	 * @param array $mapping Associative list of field position in CSV as key and domain item key as value
44
	 * @param \Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface $object Decorated processor
45
	 */
46
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context, array $mapping,
47
		\Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface $object = null )
48
	{
49
		parent::__construct( $context, $mapping, $object );
50
51
		/** controller/common/product/import/csv/processor/product/listtypes
52
		 * Names of the product list types that are updated or removed
53
		 *
54
		 * Aimeos offers associated items like "bought together" products that
55
		 * are automatically generated by other job controllers. These relations
56
		 * shouldn't normally be overwritten or deleted by default during the
57
		 * import and this confiuration option enables you to specify the list
58
		 * types that should be updated or removed if not available in the import
59
		 * file.
60
		 *
61
		 * Contrary, if you don't generate any relations automatically in the
62
		 * shop and want to import those relations too, you can set the option
63
		 * to null to update all associated items.
64
		 *
65
		 * @param array|null List of product list type names or null for all
66
		 * @since 2015.05
67
		 * @category Developer
68
		 * @category User
69
		 * @see controller/common/product/import/csv/domains
70
		 * @see controller/common/product/import/csv/processor/attribute/listtypes
71
		 * @see controller/common/product/import/csv/processor/catalog/listtypes
72
		 * @see controller/common/product/import/csv/processor/media/listtypes
73
		 * @see controller/common/product/import/csv/processor/price/listtypes
74
		 * @see controller/common/product/import/csv/processor/text/listtypes
75
		 */
76
		$default = array( 'default', 'suggestion' );
77
		$key = 'controller/common/product/import/csv/processor/product/listtypes';
78
		$this->listTypes = $context->getConfig()->get( $key, $default );
79
80
		$this->cache = $this->getCache( 'product' );
81
	}
82
83
84
	/**
85
	 * Saves the product related data to the storage
86
	 *
87
	 * @param \Aimeos\MShop\Product\Item\Iface $product Product item with associated items
88
	 * @param array $data List of CSV fields with position as key and data as value
89
	 * @return array List of data which hasn't been imported
90
	 */
91
	public function process( \Aimeos\MShop\Product\Item\Iface $product, array $data )
92
	{
93
		$context = $this->getContext();
94
		$manager = \Aimeos\MShop\Factory::createManager( $context, 'product' );
95
		$separator = $context->getConfig()->get( 'controller/common/product/import/csv/separator', "\n" );
96
97
		$this->cache->set( $product );
98
99
		$manager->begin();
100
101
		try
102
		{
103
			$types = array();
104
105
			foreach( $this->getMappedChunk( $data ) as $list )
106
			{
107
				if( $this->checkEntry( $list ) === false ) {
108
					continue;
109
				}
110
111
				$listMap = array();
112
				$type = ( isset( $list['product.lists.type'] ) ? $list['product.lists.type'] : 'default' );
113
				$types[] = $type;
114
115
				foreach( explode( $separator, $list['product.code'] ) as $code )
116
				{
117
					if( ( $prodid = $this->cache->get( $code ) ) === null )
118
					{
119
						$msg = 'No product for code "%1$s" available when importing product with code "%2$s"';
120
						throw new \Aimeos\Controller\Jobs\Exception( sprintf( $msg, $code, $product->getCode() ) );
121
					}
122
123
					$listMap[$prodid] = $list;
124
				}
125
126
				$manager->updateListItems( $product, $listMap, 'product', $type );
127
			}
128
129
			$this->deleteListItems( $product->getId(), $types );
130
131
			$remaining = $this->getObject()->process( $product, $data );
132
133
			$manager->commit();
134
		}
135
		catch( \Exception $e )
136
		{
137
			$manager->rollback();
138
			throw $e;
139
		}
140
141
		return $remaining;
142
	}
143
144
145
	/**
146
	 * Checks if an entry can be used for updating a media item
147
	 *
148
	 * @param array $list Associative list of key/value pairs from the mapping
149
	 * @return boolean True if valid, false if not
150
	 */
151
	protected function checkEntry( array $list )
152
	{
153
		if( !isset( $list['product.code'] ) || $list['product.code'] === '' || isset( $list['product.lists.type'] )
154
			&& $this->listTypes !== null && !in_array( $list['product.lists.type'], (array) $this->listTypes )
155
		) {
156
			return false;
157
		}
158
159
		return true;
160
	}
161
162
163
	/**
164
	 * Deletes all list items whose types aren't in the given list
165
	 *
166
	 * @param string $prodId Unique product ID
167
	 * @param array $types List of types that have been updated
168
	 */
169
	protected function deleteListItems( $prodId, array $types )
170
	{
171
		$codes = array_diff( $this->listTypes, $types );
172
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'product/lists' );
173
174
		$search = $manager->createSearch();
175
		$expr = array(
176
			$search->compare( '==', 'product.lists.parentid', $prodId ),
177
			$search->compare( '==', 'product.lists.domain', 'product' ),
178
			$search->compare( '==', 'product.lists.type.code', $codes ),
179
		);
180
		$search->setConditions( $search->combine( '&&', $expr ) );
181
182
		$manager->deleteItems( array_keys( $manager->searchItems( $search ) ) );
183
	}
184
}
185