Completed
Push — master ( 2e10c1...bb3077 )
by Aimeos
02:17
created

Base::getData()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 3
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2018
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Common\Catalog\Import\Csv;
12
13
14
/**
15
 * Common class for CSV catalog import job controllers and processors.
16
 *
17
 * @package Controller
18
 * @subpackage Common
19
 */
20
class Base
21
	extends \Aimeos\Controller\Jobs\Base
0 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
22
{
23
	private static $types = [];
24
25
26
	/**
27
	 * Converts the CSV field data using the available converter objects
28
	 *
29
	 * @param array $convlist Associative list of CSV field indexes and converter objects
30
	 * @param array $data Associative list of catalog codes and lists of CSV field indexes and their data
31
	 * @return array Associative list of CSV field indexes and their converted data
32
	 */
33
	protected function convertData( array $convlist, array $data )
34
	{
35
		foreach( $convlist as $idx => $converter )
36
		{
37
			foreach( $data as $code => $list )
38
			{
39
				if( isset( $list[$idx] ) ) {
40
					$data[$code][$idx] = $converter->translate( $list[$idx] );
41
				}
42
			}
43
		}
44
45
		return $data;
46
	}
47
48
49
	/**
50
	 * Returns the cache object for the given type
51
	 *
52
	 * @param string $type Type of the cached data
53
	 * @param string|null Name of the cache implementation
54
	 * @return \Aimeos\Controller\Common\Catalog\Import\Csv\Cache\Iface Cache object
55
	 */
56
	protected function getCache( $type, $name = null )
57
	{
58
		$context = $this->getContext();
59
		$config = $context->getConfig();
60
		$iface = '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Cache\\Iface';
61
62
		if( ctype_alnum( $type ) === false )
63
		{
64
			$classname = is_string($name) ? '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Cache\\' . $type : '<not a string>';
65
			throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Invalid characters in class name "%1$s"', $classname ) );
66
		}
67
68
		if( $name === null ) {
69
			$name = $config->get( 'controller/common/catalog/import/csv/cache/' . $type . '/name', 'Standard' );
70
		}
71
72
		if( ctype_alnum( $name ) === false )
73
		{
74
			$classname = is_string($name) ? '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Cache\\' . $type . '\\' . $name : '<not a string>';
75
			throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Invalid characters in class name "%1$s"', $classname ) );
76
		}
77
78
		$classname = '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Cache\\' . ucfirst( $type ) . '\\' . $name;
79
80
		if( class_exists( $classname ) === false ) {
81
			throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Class "%1$s" not found', $classname ) );
82
		}
83
84
		$object = new $classname( $context );
85
86
		if( !( $object instanceof $iface ) ) {
87
			throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Class "%1$s" does not implement interface "%2$s"', $classname, $iface ) );
88
		}
89
90
		return $object;
91
	}
92
93
94
	/**
95
	 * Returns the list of converter objects based on the given converter map
96
	 *
97
	 * @param array $convmap List of converter names for the values at the position in the CSV file
98
	 * @return array Associative list of positions and converter objects
99
	 */
100
	protected function getConverterList( array $convmap )
101
	{
102
		$convlist = [];
103
104
		foreach( $convmap as $idx => $name ) {
105
			$convlist[$idx] = \Aimeos\MW\Convert\Factory::createConverter( $name );
106
		}
107
108
		return $convlist;
109
	}
110
111
112
	/**
113
	 * Returns the rows from the CSV file up to the maximum count
114
	 *
115
	 * @param \Aimeos\MW\Container\Content\Iface $content CSV content object
116
	 * @param integer $maxcnt Maximum number of rows that should be retrieved at once
117
	 * @param integer $codePos Column position which contains the unique catalog code (starting from 0)
118
	 * @return array List of arrays with catalog codes as keys and list of values from the CSV file
119
	 */
120
	protected function getData( \Aimeos\MW\Container\Content\Iface $content, $maxcnt, $codePos )
121
	{
122
		$count = 0;
123
		$data = [];
124
125
		while( $content->valid() && $count++ < $maxcnt )
126
		{
127
			$row = $content->current();
128
			$data[ $row[$codePos] ] = $row;
129
			$content->next();
130
		}
131
132
		return $data;
133
	}
134
135
136
	/**
137
	 * Returns the default mapping for the CSV fields to the domain item keys
138
	 *
139
	 * Example:
140
	 *  'item' => array(
141
	 *  	0 => 'catalog.code', // e.g. unique EAN code
142
	 *		1 => 'catalog.parent', // Code of parent catalog node
143
	 *  	2 => 'catalog.label', // UTF-8 encoded text, also used as catalog name
144
	 *		3 => 'catalog.status', // If category should be shown in the frontend
145
	 *  ),
146
	 *  'text' => array(
147
	 *  	3 => 'text.type', // e.g. "short" for short description
148
	 *  	4 => 'text.content', // UTF-8 encoded text
149
	 *  ),
150
	 *  'media' => array(
151
	 *  	5 => 'media.url', // relative URL of the catalog image on the server
152
	 *  ),
153
	 *
154
	 * @return array Associative list of domains as keys ("item" is special for the catalog itself) and a list of
155
	 * 	positions and the domain item keys as values.
156
	 */
157
	protected function getDefaultMapping()
158
	{
159
		return array(
160
			'item' => array(
161
				0 => 'catalog.code',
162
				1 => 'catalog.parent',
163
				2 => 'catalog.label',
164
				3 => 'catalog.status',
165
			),
166
			'text' => array(
167
				4 => 'text.type',
168
				5 => 'text.content',
169
			),
170
			'media' => array(
171
				6 => 'media.url',
172
			),
173
		);
174
	}
175
176
177
	/**
178
	 * Returns the mapped data from the CSV line
179
	 *
180
	 * @param array $data List of CSV fields with position as key and domain item key as value (mapped data is removed)
181
	 * @param array $mapping List of domain item keys with the CSV field position as key
182
	 * @return array List of associative arrays containing the chunked properties
183
	 */
184
	protected function getMappedChunk( array &$data, array $mapping )
185
	{
186
		$idx = 0;
187
		$map = [];
188
189
		foreach( $mapping as $pos => $key )
190
		{
191
			if( isset( $map[$idx][$key] ) ) {
192
				$idx++;
193
			}
194
195
			if( isset( $data[$pos] ) )
196
			{
197
				$map[$idx][$key] = $data[$pos];
198
				unset( $data[$pos] );
199
			}
200
		}
201
202
		return $map;
203
	}
204
205
206
	/**
207
	 * Returns the processor object for saving the catalog related information
208
	 *
209
	 * @param array $mappings Associative list of processor types as keys and index/data mappings as values
210
	 * @return \Aimeos\Controller\Common\Catalog\Import\Csv\Processor\Iface Processor object
211
	 */
212
	protected function getProcessors( array $mappings )
213
	{
214
		$context = $this->getContext();
215
		$config = $context->getConfig();
216
		$iface = '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Processor\\Iface';
217
		$object = new \Aimeos\Controller\Common\Catalog\Import\Csv\Processor\Done( $context, [] );
218
219
		foreach( $mappings as $type => $mapping )
220
		{
221
			if( ctype_alnum( $type ) === false )
222
			{
223
				$classname = is_string($type) ? '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Processor\\' . $type : '<not a string>';
224
				throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Invalid characters in class name "%1$s"', $classname ) );
225
			}
226
227
			$name = $config->get( 'controller/common/catalog/import/csv/processor/' . $type . '/name', 'Standard' );
228
229
			if( ctype_alnum( $name ) === false )
230
			{
231
				$classname = is_string($name) ? '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Processor\\' . $type . '\\' . $name : '<not a string>';
232
				throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Invalid characters in class name "%1$s"', $classname ) );
233
			}
234
235
			$classname = '\\Aimeos\\Controller\\Common\\Catalog\\Import\\Csv\\Processor\\' . ucfirst( $type ) . '\\' . $name;
236
237
			if( class_exists( $classname ) === false ) {
238
				throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Class "%1$s" not found', $classname ) );
239
			}
240
241
			$object = new $classname( $context, $mapping, $object );
242
243
			if( !( $object instanceof $iface ) ) {
244
				throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'Class "%1$s" does not implement interface "%2$s"', $classname, $iface ) );
245
			}
246
		}
247
248
		return $object;
249
	}
250
251
252
	/**
253
	 * Returns the ID of the type item with the given code
254
	 *
255
	 * @param string $path Item/manager path separated by slashes, e.g. "catalog/lists/type"
256
	 * @param string $domain Domain the type items needs to be from
257
	 * @param string $code Unique code of the type item
258
	 * @return string Unique ID of the type item
259
	 */
260
	protected function getTypeId( $path, $domain, $code )
261
	{
262
		if( !isset( self::$types[$path][$domain] ) )
263
		{
264
			$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), $path );
265
			$key = str_replace( '/', '.', $path );
266
267
			$search = $manager->createSearch();
268
			$search->setConditions( $search->compare( '==', $key . '.domain', $domain ) );
269
270
			foreach( $manager->searchItems( $search ) as $id => $item ) {
271
				self::$types[$path][$domain][ $item->getCode() ] = $id;
272
			}
273
		}
274
275
		if( !isset( self::$types[$path][$domain][$code] ) ) {
276
			throw new \Aimeos\Controller\Jobs\Exception( sprintf( 'No type item for "%1$s/%2$s" in "%3$s" found', $domain, $code, $path ) );
277
		}
278
279
		return self::$types[$path][$domain][$code];
280
	}
281
}
282