Completed
Push — master ( 268cfa...1e6723 )
by Aimeos
02:55
created

Standard::checkEntry()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 8.2222
cc 7
eloc 6
nc 2
nop 1
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Common\Product\Import\Csv\Processor\Attribute;
12
13
14
/**
15
 * Attribute 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/attribute/name
25
	 * Name of the attribute processor implementation
26
	 *
27
	 * Use "Myname" if your class is named "\Aimeos\Controller\Common\Product\Import\Csv\Processor\Attribute\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/attribute/listtypes
52
		 * Names of the product list types for attributes that are updated or removed
53
		 *
54
		 * If you want to associate attribute items manually via the administration
55
		 * interface to products and don't want these to be touched during the
56
		 * import, you can specify the product list types for these attributes
57
		 * that shouldn't be updated or removed.
58
		 *
59
		 * @param array|null List of product list type names or null for all
60
		 * @since 2015.05
61
		 * @category Developer
62
		 * @category User
63
		 * @see controller/common/product/import/csv/domains
64
		 * @see controller/common/product/import/csv/processor/catalog/listtypes
65
		 * @see controller/common/product/import/csv/processor/media/listtypes
66
		 * @see controller/common/product/import/csv/processor/product/listtypes
67
		 * @see controller/common/product/import/csv/processor/price/listtypes
68
		 * @see controller/common/product/import/csv/processor/text/listtypes
69
		 */
70
		$this->listTypes = $context->getConfig()->get( 'controller/common/product/import/csv/processor/attribute/listtypes');
71
72
		$this->cache = $this->getCache( 'attribute' );
73
	}
74
75
76
	/**
77
	 * Saves the attribute related data to the storage
78
	 *
79
	 * @param \Aimeos\MShop\Product\Item\Iface $product Product item with associated items
80
	 * @param array $data List of CSV fields with position as key and data as value
81
	 * @return array List of data which hasn't been imported
82
	 */
83
	public function process( \Aimeos\MShop\Product\Item\Iface $product, array $data )
84
	{
85
		$context = $this->getContext();
86
		$manager = \Aimeos\MShop\Factory::createManager( $context, 'attribute' );
87
		$listManager = \Aimeos\MShop\Factory::createManager( $context, 'product/lists' );
88
		$separator = $context->getConfig()->get( 'controller/common/product/import/csv/separator', "\n" );
89
90
		$manager->begin();
91
92
		try
93
		{
94
			$pos = 0;
95
			$delete = array();
96
			$map = $this->getMappedChunk( $data );
97
			$listItems = $product->getListItems( 'attribute', $this->listTypes );
98
99
			foreach( $listItems as $listId => $listItem )
100
			{
101
				if( isset( $map[$pos] ) )
102
				{
103
					if( !isset( $map[$pos]['attribute.code'] ) || !isset( $map[$pos]['attribute.type'] ) )
104
					{
105
						unset( $map[$pos] );
106
						continue;
107
					}
108
109
					if( $this->checkMatch( $listItem, $map[$pos] ) === true )
110
					{
111
						$pos++;
112
						continue;
113
					}
114
				}
115
116
				$listItems[$listId] = null;
117
				$delete[] = $listId;
118
				$pos++;
119
			}
120
121
			$listManager->deleteItems( $delete );
122
123
			foreach( $map as $pos => $list )
124
			{
125
				if( $this->checkEntry( $list ) === false ) {
126
					continue;
127
				}
128
129
				$codes = explode( $separator, $list['attribute.code'] );
130
131
				foreach( $codes as $code )
132
				{
133
					$attrItem = $this->getAttributeItem( $code, $list['attribute.type'] );
134
					$attrItem->fromArray( $list );
135
					$attrItem->setCode( $code );
136
					$manager->saveItem( $attrItem );
137
138
					if( ( $listItem = array_shift( $listItems ) ) === null ) {
139
						$listItem = $listManager->createItem();
140
					}
141
142
					$typecode = $this->getValue( $list, 'product.lists.type', 'default' );
143
					$list['product.lists.typeid'] = $this->getTypeId( 'product/lists/type', 'attribute', $typecode );
144
					$list['product.lists.refid'] = $attrItem->getId();
145
					$list['product.lists.parentid'] = $product->getId();
146
					$list['product.lists.domain'] = 'attribute';
147
148
					$listItem->fromArray( $this->addListItemDefaults( $list, $pos ) );
149
					$listManager->saveItem( $listItem );
150
				}
151
			}
152
153
			$remaining = $this->getObject()->process( $product, $data );
154
155
			$manager->commit();
156
		}
157
		catch( \Exception $e )
158
		{
159
			$manager->rollback();
160
			throw $e;
161
		}
162
163
		return $remaining;
164
	}
165
166
167
	/**
168
	 * Checks if the entry from the mapped data is valid
169
	 *
170
	 * @param array $list Associative list of key/value pairs from the mapped data
171
	 * @return boolean True if the entry is valid, false if not
172
	 */
173
	protected function checkEntry( array $list )
174
	{
175
		if( !isset( $list['attribute.code'] ) || $list['attribute.code'] === '' || $list['attribute.type'] === ''
176
			|| isset( $list['product.lists.type'] ) && $this->listTypes !== null
177
			&& !in_array( $list['product.lists.type'], (array) $this->listTypes )
178
		) {
179
			return false;
180
		}
181
182
		return true;
183
	}
184
185
186
	/**
187
	 * Checks if the list item matches the values from the list
188
	 *
189
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface $listItem List item object
190
	 * @param array $list Associative list of key/value pairs from the mapped data
191
	 * @return boolean True if the list item matches the values in the list, false if not
192
	 */
193
	protected function checkMatch( \Aimeos\MShop\Common\Item\Lists\Iface $listItem, array $list )
194
	{
195
		$refItem = $listItem->getRefItem();
196
197
		if( $refItem !== null && $list['attribute.code'] === $refItem->getCode()
198
			&& $list['attribute.type'] === $refItem->getType()
199
			&& ( !isset( $list['product.lists.type'] ) || isset( $list['product.lists.type'] )
200
			&& $list['product.lists.type'] === $listItem->getType() )
201
		) {
202
			return true;
203
		}
204
205
		return false;
206
	}
207
208
209
	/**
210
	 * Returns the attribute item for the given code and type
211
	 *
212
	 * @param string $code Attribute code
213
	 * @param string $type Attribute type
214
	 * @return \Aimeos\MShop\Attribute\Item\Iface Attribute item object
215
	 */
216
	protected function getAttributeItem( $code, $type )
217
	{
218
		if( ( $item = $this->cache->get( $code, $type ) ) === null )
219
		{
220
			$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'attribute' );
221
222
			$item = $manager->createItem();
223
			$item->setTypeId( $this->getTypeId( 'attribute/type', 'product', $type ) );
224
			$item->setCode( $code );
225
			$item->setLabel( $type . ' ' . $code );
226
			$item->setStatus( 1 );
227
228
			$manager->saveItem( $item );
229
230
			$this->cache->set( $item );
231
		}
232
233
		return $item;
234
	}
235
}
236