Passed
Push — master ( 8f9d50...fd98c8 )
by Aimeos
18:27 queued 04:20
created

Standard::getSupplierItem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 17
rs 9.9666
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), 2020-2025
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Supplier;
12
13
14
/**
15
 * Supplier processor for CSV imports
16
 *
17
 * @package Controller
18
 * @subpackage Common
19
 */
20
class Standard
21
	extends \Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Base
22
	implements \Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Iface
23
{
24
	/** controller/jobs/product/import/csv/processor/supplier/name
25
	 * Name of the supplier processor implementation
26
	 *
27
	 * Use "Myname" if your class is named "\Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Supplier\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 2020.07
32
	 */
33
34
	private \Aimeos\Controller\Jobs\Common\Product\Import\Csv\Cache\Supplier\Standard $cache;
35
	private ?array $listTypes = null;
36
37
38
	/**
39
	 * Initializes the object
40
	 *
41
	 * @param \Aimeos\MShop\ContextIface $context Context object
42
	 * @param array $mapping Associative list of field position in CSV as key and domain item key as value
43
	 * @param \Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Iface $object Decorated processor
44
	 */
45
	public function __construct( \Aimeos\MShop\ContextIface $context, array $mapping,
46
		?\Aimeos\Controller\Jobs\Common\Product\Import\Csv\Processor\Iface $object = null )
47
	{
48
		parent::__construct( $context, $mapping, $object );
49
50
		$config = $context->config();
51
52
		/** controller/jobs/product/import/csv/supplier/listtypes
53
		 * Names of the supplier list types that are updated or removed
54
		 *
55
		 * Aimeos offers associated items like "bought together" suppliers that
56
		 * are automatically generated by other job controllers. These relations
57
		 * shouldn't normally be overwritten or deleted by default during the
58
		 * import and this confiuration option enables you to specify the list
59
		 * types that should be updated or removed if not available in the import
60
		 * file.
61
		 *
62
		 * Contrary, if you don't generate any relations automatically in the
63
		 * shop and want to import those relations too, you can set the option
64
		 * to null to update all associated items.
65
		 *
66
		 * @param array|null List of supplier list type names or null for all
67
		 * @since 2020.07
68
		 * @see controller/jobs/product/import/csv/domains
69
		 * @see controller/jobs/product/import/csv/separator
70
		 * @see controller/jobs/product/import/csv/attribute/listtypes
71
		 * @see controller/jobs/product/import/csv/catalog/listtypes
72
		 * @see controller/jobs/product/import/csv/media/listtypes
73
		 * @see controller/jobs/product/import/csv/price/listtypes
74
		 * @see controller/jobs/product/import/csv/product/listtypes
75
		 * @see controller/jobs/product/import/csv/text/listtypes
76
		 */
77
		$default = $config->get( 'controller/jobs/product/import/csv/processor/supplier/listtypes', ['default', 'promotion'] );
78
		$this->listTypes = $config->get( 'controller/jobs/product/import/csv/supplier/listtypes', $default );
79
80
		if( $this->listTypes === null )
81
		{
82
			$this->listTypes = [];
83
			$manager = \Aimeos\MShop::create( $context, 'product/lists/type' );
84
			$search = $manager->filter()->slice( 0, 0x7fffffff );
85
86
			foreach( $manager->search( $search ) as $item ) {
87
				$this->listTypes[$item->getCode()] = $item->getCode();
88
			}
89
		}
90
		else
91
		{
92
			$this->listTypes = array_combine( $this->listTypes, $this->listTypes );
93
		}
94
95
		$this->cache = $this->getCache( 'supplier' );
96
	}
97
98
99
	/**
100
	 * Saves the supplier related data to the storage
101
	 *
102
	 * @param \Aimeos\MShop\Product\Item\Iface $product Product item with associated items
103
	 * @param array $data List of CSV fields with position as key and data as value
104
	 * @return array List of data which has not been imported
105
	 */
106
	public function process( \Aimeos\MShop\Product\Item\Iface $product, array $data ) : array
107
	{
108
		$context = $this->context();
109
		$logger = $context->logger();
110
111
		$manager = \Aimeos\MShop::create( $context, 'product' );
112
		$separator = $context->config()->get( 'controller/jobs/product/import/csv/separator', "\n" );
113
114
		$listItems = $product->getListItems( 'supplier', $this->listTypes, null, false );
115
		$pos = 0;
116
117
		foreach( $this->getMappedChunk( $data, $this->getMapping() ) as $list )
118
		{
119
			if( $this->checkEntry( $list ) === false ) {
120
				continue;
121
			}
122
123
			$listConfig = $this->getListConfig( trim( $this->val( $list, 'product.lists.config', '' ) ) );
124
			$listtype = trim( $this->val( $list, 'product.lists.type', 'default' ) );
125
			$this->addType( 'product/lists/type', 'supplier', $listtype );
126
127
			$codes = explode( $separator, trim( $this->val( $list, 'supplier.code', '' ) ) );
128
			unset( $list['supplier.code'] );
129
130
			foreach( $codes as $code )
131
			{
132
				$code = trim( $code );
133
134
				if( ( $supItem = $this->cache->get( $code ) ) === null )
135
				{
136
					$msg = 'No supplier for code "%1$s" available when importing product with code "%2$s"';
137
					$logger->warning( sprintf( $msg, $code, $product->getCode() ), 'import/csv/product' );
138
					continue;
139
				}
140
141
				if( ( $listItem = $product->getListItem( 'supplier', $listtype, $supItem->getId() ) ) === null ) {
0 ignored issues
show
Bug introduced by
It seems like $supItem->getId() can also be of type null; however, parameter $refId of Aimeos\MShop\Common\Item...ef\Iface::getListItem() 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

141
				if( ( $listItem = $product->getListItem( 'supplier', $listtype, /** @scrutinizer ignore-type */ $supItem->getId() ) ) === null ) {
Loading history...
142
					$listItem = $manager->createListItem()->setType( $listtype );
0 ignored issues
show
Bug introduced by
The method createListItem() does not exist on Aimeos\MShop\Common\Manager\Iface. Did you maybe mean create()? ( Ignorable by Annotation )

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

142
					$listItem = $manager->/** @scrutinizer ignore-call */ createListItem()->setType( $listtype );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
143
				} else {
144
					unset( $listItems[$listItem->getId()] );
145
				}
146
147
				$listItem = $listItem->fromArray( $list )->setConfig( $listConfig )->setPosition( $pos++ );
148
				$supItem = $supItem->fromArray( $list )->setCode( $code );
149
				$product->addListItem( 'supplier', $listItem, $supItem );
150
			}
151
		}
152
153
		$product->deleteListItems( $listItems );
154
155
		return $this->object()->process( $product, $data );
156
	}
157
158
159
	/**
160
	 * Checks if an entry can be used for updating a media item
161
	 *
162
	 * @param array $list Associative list of key/value pairs from the mapping
163
	 * @return bool True if valid, false if not
164
	 */
165
	protected function checkEntry( array $list ) : bool
166
	{
167
		if( $this->val( $list, 'supplier.code' ) === null ) {
168
			return false;
169
		}
170
171
		if( ( $type = trim( $this->val( $list, 'product.lists.type', 'default' ) ) ) && !isset( $this->listTypes[$type] ) )
172
		{
173
			$msg = sprintf( 'Invalid type "%1$s" (%2$s)', $type, 'product list' );
174
			throw new \Aimeos\Controller\Jobs\Exception( $msg );
175
		}
176
177
		return true;
178
	}
179
}
180