Passed
Push — master ( f5900b...04f158 )
by Aimeos
04:26
created

Base::getMappedChunk()   B

Complexity

Conditions 8
Paths 17

Size

Total Lines 29
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 13
nc 17
nop 2
dl 0
loc 29
rs 8.4444
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), 2018-2025
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Jobs\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
22
{
23
	/**
24
	 * Returns the cache object for the given type
25
	 *
26
	 * @param string $type Type of the cached data
27
	 * @param string|null $name Name of the cache implementation
28
	 * @return \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Cache\Iface Cache object
29
	 * @throws \LogicException If class can't be instantiated
30
	 */
31
	protected function getCache( string $type, $name = null ) : \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Cache\Iface
32
	{
33
		$context = $this->context();
34
		$config = $context->config();
35
36
		if( ctype_alnum( $type ) === false ) {
37
			throw new \LogicException( sprintf( 'Invalid characters in class name "%1$s"', $type ), 400 );
38
		}
39
40
		if( $name === null ) {
41
			$name = $config->get( 'controller/jobs/catalog/import/csv/cache/' . $type . '/name', 'Standard' );
42
		}
43
44
		if( ctype_alnum( $name ) === false ) {
45
			throw new \LogicException( sprintf( 'Invalid characters in class name "%1$s"', $name ), 400 );
46
		}
47
48
		$classname = '\\Aimeos\\Controller\\Jobs\\Common\\Catalog\\Import\\Csv\\Cache\\' . ucfirst( $type ) . '\\' . $name;
49
		$interface = \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Cache\Iface::class;
50
51
		return \Aimeos\Utils::create( $classname, [$context], $interface );
52
	}
53
54
55
	/**
56
	 * Returns the rows from the CSV file up to the maximum count
57
	 *
58
	 * @param resource $fh File handle to CSV file
59
	 * @param int $maxcnt Maximum number of rows that should be retrieved at once
60
	 * @param int $codePos Column position which contains the unique product code (starting from 0)
61
	 * @return array List of arrays with product codes as keys and list of values from the CSV file
62
	 */
63
	protected function getData( $fh, int $maxcnt, int $codePos ) : array
64
	{
65
		$data = [];
66
		$count = 0;
67
68
		while( $count++ < $maxcnt && ( $row = fgetcsv( $fh, null, ',', '"', '' ) ) !== false ) {
69
			$data[$row[$codePos]] = $row;
70
		}
71
72
		return $data;
73
	}
74
75
76
	/**
77
	 * Returns the default mapping for the CSV fields to the domain item keys
78
	 *
79
	 * Example:
80
	 *  'item' => array(
81
	 *  	0 => 'catalog.code', // e.g. unique EAN code
82
	 *		1 => 'catalog.parent', // Code of parent catalog node
83
	 *  	2 => 'catalog.label', // UTF-8 encoded text, also used as catalog name
84
	 *		3 => 'catalog.status', // If category should be shown in the frontend
85
	 *  ),
86
	 *  'text' => array(
87
	 *  	3 => 'text.type', // e.g. "short" for short description
88
	 *  	4 => 'text.content', // UTF-8 encoded text
89
	 *  ),
90
	 *  'media' => array(
91
	 *  	5 => 'media.url', // relative URL of the catalog image on the server
92
	 *  ),
93
	 *
94
	 * @return array Associative list of domains as keys ("item" is special for the catalog itself) and a list of
95
	 * 	positions and the domain item keys as values.
96
	 */
97
	protected function getDefaultMapping() : array
98
	{
99
		return array(
100
			'item' => array(
101
				0 => 'catalog.code',
102
				1 => 'catalog.parent',
103
				2 => 'catalog.label',
104
				3 => 'catalog.status',
105
			),
106
			'text' => array(
107
				4 => 'text.type',
108
				5 => 'text.content',
109
			),
110
			'media' => array(
111
				6 => 'media.url',
112
			),
113
		);
114
	}
115
116
117
	/**
118
	 * Returns the configuration for the given string
119
	 *
120
	 * @param string $value Configuration string
121
	 * @return array Configuration settings
122
	 */
123
	protected function getListConfig( string $value ) : array
124
	{
125
		$config = [];
126
127
		foreach( array_filter( explode( "\n", $value ) ) as $line )
128
		{
129
			list( $key, $val ) = explode( ':', $line );
130
			$config[$key] = $val;
131
		}
132
133
		return $config;
134
	}
135
136
137
	/**
138
	 * Returns the mapped data from the CSV line
139
	 *
140
	 * @param array $data List of CSV fields with position as key and domain item key as value (mapped data is removed)
141
	 * @param array $mapping List of domain item keys with the CSV field position as key
142
	 * @return array List of associative arrays containing the chunked properties
143
	 */
144
	protected function getMappedChunk( array &$data, array $mapping ) : array
145
	{
146
		$idx = 0;
147
		$map = [];
148
149
		foreach( $mapping as $pos => $key )
150
		{
151
			$code = is_array( $key ) ? $key['_'] : $key;
152
153
			if( isset( $map[$idx][$code] ) ) {
154
				$idx++;
155
			}
156
157
			if( is_array( $key ) )
158
			{
159
				foreach( $key as $name => $val )
160
				{
161
					if( $name !== '_' ) {
162
						$map[$idx][$name] = $val;
163
					}
164
				}
165
			}
166
167
			if( isset( $data[$pos] ) ) {
168
				$map[$idx][$code] = $data[$pos];
169
			}
170
		}
171
172
		return $map;
173
	}
174
175
176
	/**
177
	 * Returns the processor object for saving the catalog related information
178
	 *
179
	 * @param array $mappings Associative list of processor types as keys and index/data mappings as values
180
	 * @return \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Processor\Iface Processor object
181
	 * @throws \LogicException If class can't be instantiated
182
	 */
183
	protected function getProcessors( array $mappings ) : \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Processor\Iface
184
	{
185
		unset( $mappings['item'] );
186
187
		$context = $this->context();
188
		$config = $context->config();
189
190
		$interface = \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Processor\Iface::class;
191
		$object = new \Aimeos\Controller\Jobs\Common\Catalog\Import\Csv\Processor\Done( $context, [] );
192
193
		foreach( $mappings as $type => $mapping )
194
		{
195
			if( ctype_alnum( $type ) === false ) {
196
				throw new \LogicException( sprintf( 'Invalid characters in class name "%1$s"', $type ), 400 );
197
			}
198
199
			$name = $config->get( 'controller/jobs/catalog/import/csv/processor/' . $type . '/name', 'Standard' );
200
201
			if( ctype_alnum( $name ) === false ) {
202
				throw new \LogicException( sprintf( 'Invalid characters in class name "%1$s"', $name ), 400 );
203
			}
204
205
			$classname = '\\Aimeos\\Controller\\Jobs\\Common\\Catalog\\Import\\Csv\\Processor\\' . ucfirst( $type ) . '\\' . $name;
206
207
			$object = \Aimeos\Utils::create( $classname, [$context, $mapping, $object], $interface );
208
		}
209
210
		return $object;
211
	}
212
}
213