Completed
Branch master (c3c77b)
by Aimeos
03:13
created

Standard::checkEntry()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 9
nc 4
nop 1
dl 0
loc 19
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2018
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
22
	implements \Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface
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
	private $types = [];
38
39
40
	/**
41
	 * Initializes the object
42
	 *
43
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
44
	 * @param array $mapping Associative list of field position in CSV as key and domain item key as value
45
	 * @param \Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface $object Decorated processor
46
	 */
47
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context, array $mapping,
48
		\Aimeos\Controller\Common\Product\Import\Csv\Processor\Iface $object = null )
49
	{
50
		parent::__construct( $context, $mapping, $object );
51
52
		/** controller/common/product/import/csv/processor/attribute/listtypes
53
		 * Names of the product list types for attributes that are updated or removed
54
		 *
55
		 * If you want to associate attribute items manually via the administration
56
		 * interface to products and don't want these to be touched during the
57
		 * import, you can specify the product list types for these attributes
58
		 * that shouldn't be updated or removed.
59
		 *
60
		 * @param array|null List of product list type names or null for all
61
		 * @since 2015.05
62
		 * @category Developer
63
		 * @category User
64
		 * @see controller/common/product/import/csv/domains
65
		 * @see controller/common/product/import/csv/processor/catalog/listtypes
66
		 * @see controller/common/product/import/csv/processor/media/listtypes
67
		 * @see controller/common/product/import/csv/processor/product/listtypes
68
		 * @see controller/common/product/import/csv/processor/price/listtypes
69
		 * @see controller/common/product/import/csv/processor/text/listtypes
70
		 */
71
		$key = 'controller/common/product/import/csv/processor/attribute/listtypes';
72
		$this->listTypes = $context->getConfig()->get( $key );
73
74
		if( $this->listTypes === null )
75
		{
76
			$this->listTypes = [];
77
			$manager = \Aimeos\MShop::create( $context, 'product/lists/type' );
78
79
			$search = $manager->createSearch()->setSlice( 0, 0x7fffffff );
80
			$search->setConditions( $search->compare( '==', 'product.lists.type.domain', 'attribute' ) );
81
82
			foreach( $manager->searchItems( $search ) as $item ) {
83
				$this->listTypes[$item->getCode()] = $item->getCode();
1 ignored issue
show
Bug introduced by
The method getCode() does not exist on Aimeos\MShop\Common\Item\Iface. It seems like you code against a sub-type of Aimeos\MShop\Common\Item\Iface such as Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Locale\Item\Site\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Order\Item\Base\Service\Iface or Aimeos\MShop\Customer\Item\Group\Iface or Aimeos\MShop\Order\Item\Base\Coupon\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Locale\Item\Language\Iface or Aimeos\MShop\Order\Item\...Service\Attribute\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Order\Item\...Product\Attribute\Iface or Aimeos\MShop\Coupon\Item\Code\Iface or Aimeos\MShop\Supplier\Item\Iface or Aimeos\MShop\Locale\Item\Currency\Iface or Aimeos\MShop\Attribute\Item\Standard or Aimeos\MShop\Catalog\Item\Standard or Aimeos\MShop\Customer\Item\Base or Aimeos\MShop\Customer\Item\Group\Standard or Aimeos\MShop\Common\Item\Type\Standard or Aimeos\MShop\Locale\Item\Site\Standard or Aimeos\MShop\Locale\Item\Currency\Standard or Aimeos\MShop\Locale\Item\Language\Standard or Aimeos\MShop\Order\Item\Base\Service\Base or Aimeos\MShop\Service\Item\Standard or Aimeos\MShop\Order\Item\Base\Coupon\Standard or Aimeos\MShop\Coupon\Item\Code\Standard or Aimeos\MShop\Order\Item\...vice\Attribute\Standard or Aimeos\MShop\Supplier\Item\Standard or Aimeos\MShop\Product\Item\Standard or Aimeos\MShop\Order\Item\...duct\Attribute\Standard or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Locale\Item\Language\Iface or Aimeos\MShop\Common\Item\Tree\Iface or Aimeos\MShop\Supplier\Item\Iface or Aimeos\MShop\Locale\Item\Currency\Iface or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Supplier\Item\Iface or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Customer\Item\Iface or Aimeos\MShop\Supplier\Item\Iface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
				$this->listTypes[$item->/** @scrutinizer ignore-call */ getCode()] = $item->getCode();
Loading history...
84
			}
85
		}
86
		else
87
		{
88
			$this->listTypes = array_flip( $this->listTypes );
89
		}
90
91
92
		$manager = \Aimeos\MShop::create( $context, 'attribute/type' );
93
94
		$search = $manager->createSearch()->setSlice( 0, 0x7fffffff );
95
		$search->setConditions( $search->compare( '==', 'attribute.type.domain', 'product' ) );
96
97
		foreach( $manager->searchItems( $search ) as $item ) {
98
			$this->types[$item->getCode()] = $item->getCode();
99
		}
100
101
102
		$this->cache = $this->getCache( 'attribute' );
103
	}
104
105
106
	/**
107
	 * Saves the attribute related data to the storage
108
	 *
109
	 * @param \Aimeos\MShop\Product\Item\Iface $product Product item with associated items
110
	 * @param array $data List of CSV fields with position as key and data as value
111
	 * @return array List of data which hasn't been imported
112
	 */
113
	public function process( \Aimeos\MShop\Product\Item\Iface $product, array $data )
114
	{
115
		$context = $this->getContext();
116
		$listManager = \Aimeos\MShop::create( $context, 'product/lists' );
117
		$separator = $context->getConfig()->get( 'controller/common/product/import/csv/separator', "\n" );
118
119
		$listMap = [];
120
		$map = $this->getMappedChunk( $data, $this->getMapping() );
121
		$listItems = $product->getListItems( 'attribute', $this->listTypes );
122
123
		foreach( $listItems as $listItem )
124
		{
125
			if( ( $refItem = $listItem->getRefItem() ) !== null ) {
126
				$listMap[ $refItem->getCode() ][ $listItem->getType() ] = $listItem;
127
			}
128
		}
129
130
		foreach( $map as $pos => $list )
131
		{
132
			if( $this->checkEntry( $list ) === false ) {
133
				continue;
134
			}
135
136
			$codes = explode( $separator, $this->getValue( $list, 'attribute.code', '' ) );
137
138
			foreach( $codes as $code )
139
			{
140
				$code = trim( $code );
141
				$listtype = $this->getValue( $list, 'product.lists.type', 'default' );
142
143
				if( isset( $listMap[$code][$listtype] ) )
144
				{
145
					$listItem = $listMap[$code][$listtype];
146
					unset( $listItems[ $listItem->getId() ] );
147
				}
148
				else
149
				{
150
					$listItem = $listManager->createItem()->setType( $listtype );
151
				}
152
153
				$listItem = $listItem->setPosition( $pos )->fromArray( $list );
154
155
				$attrItem = $this->getAttributeItem( $code, $this->getValue( $list, 'attribute.type' ) );
156
				$attrItem = $attrItem->setCode( $code )->fromArray( $list );
157
158
				$product->addListItem( 'attribute', $listItem, $attrItem );
159
			}
160
		}
161
162
		$product->deleteListItems( $listItems );
163
164
		return $this->getObject()->process( $product, $data );
165
	}
166
167
168
	/**
169
	 * Checks if the entry from the mapped data is valid
170
	 *
171
	 * @param array $list Associative list of key/value pairs from the mapped data
172
	 * @return boolean True if the entry is valid, false if not
173
	 */
174
	protected function checkEntry( array $list )
175
	{
176
		if( $this->getValue( $list, 'attribute.code' ) === null ) {
177
			return false;
178
		}
179
180
		if( ( $type = $this->getValue( $list, 'product.lists.type' ) ) && !isset( $this->listTypes[$type] ) )
181
		{
182
			$msg = sprintf( 'Invalid type "%1$s" (%2$s)', $type, 'product list' );
183
			throw new \Aimeos\Controller\Common\Exception( $msg );
184
		}
185
186
		if( ( $type = $this->getValue( $list, 'attribute.type' ) ) && !isset( $this->types[$type] ) )
187
		{
188
			$msg = sprintf( 'Invalid type "%1$s" (%2$s)', $type, 'attribute' );
189
			throw new \Aimeos\Controller\Common\Exception( $msg );
190
		}
191
192
		return true;
193
	}
194
195
196
	/**
197
	 * Returns the attribute item for the given code and type
198
	 *
199
	 * @param string $code Attribute code
200
	 * @param string $type Attribute type
201
	 * @return \Aimeos\MShop\Attribute\Item\Iface Attribute item object
202
	 */
203
	protected function getAttributeItem( $code, $type )
204
	{
205
		if( ( $item = $this->cache->get( $code, $type ) ) === null )
206
		{
207
			$manager = \Aimeos\MShop::create( $this->getContext(), 'attribute' );
208
209
			$item = $manager->createItem();
210
			$item->setType( $type );
211
			$item->setDomain( 'product' );
212
			$item->setLabel( $code );
213
			$item->setCode( $code );
214
			$item->setStatus( 1 );
215
216
			$item = $manager->saveItem( $item );
217
218
			$this->cache->set( $item );
219
		}
220
221
		return $item;
222
	}
223
}
224