Completed
Push — master ( 2cd00f...8db945 )
by Aimeos
17:36
created

Base::saveRefItems()   F

Complexity

Conditions 12
Paths 1164

Size

Total Lines 74
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 35
nc 1164
nop 2
dl 0
loc 74
rs 2.2446
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2014
6
 * @copyright Aimeos (aimeos.org), 2015-2017
7
 * @package MShop
8
 * @subpackage Common
9
 */
10
11
12
namespace Aimeos\MShop\Common\Manager\ListRef;
13
14
15
/**
16
 * Abstract class for managers working with referenced list items.
17
 *
18
 * @package MShop
19
 * @subpackage Common
20
 */
21
abstract class Base
22
	extends \Aimeos\MShop\Common\Manager\Base
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
23
	implements \Aimeos\MShop\Common\Manager\ListRef\Iface
24
{
25
	private $typeIds = [];
26
27
	/**
28
	 * Updates the list items to the referenced items for the given domain and type
29
	 *
30
	 * @param \Aimeos\MShop\Common\Item\ListRef\Iface $item Item including references to other domain items
31
	 * @param array $map Associative list of reference ID as key and list of list item properties as key/value pairs
32
	 * @param string $domain Domain name of the referenced items
33
	 * @param string $type List type for the referenced items
34
	 */
35
	public function updateListItems( \Aimeos\MShop\Common\Item\ListRef\Iface $item, array $map, $domain, $type )
36
	{
37
		$listManager =  $this->getObject()->getSubManager( 'lists' );
38
39
		if( !isset( $this->typeIds[$domain][$type] ) )
40
		{
41
			$typeManager = $listManager->getSubManager( 'type' );
42
			$this->typeIds[$domain][$type] = $typeManager->findItem( $type, [], $domain )->getId();
43
		}
44
45
		$listItem = $listManager->createItem();
46
		$listItem->setTypeId( $this->typeIds[$domain][$type] );
47
		$listItem->setParentId( $item->getId() );
48
		$listItem->setDomain( $domain );
49
		$listItem->setStatus( 1 );
50
51
		$pos = 0;
52
		$listRef = $ids = [];
53
		$listItems = $item->getListItems( $domain, $type );
54
55
		foreach( $listItems as $id => $listItem ) {
56
			$listRef[$listItem->getRefId()] = $id;
57
		}
58
59
		foreach( $map as $id => $values )
60
		{
61
			$copy = $listItem;
62
63
			if( !isset( $listRef[$id] ) )
64
			{
65
				$copy->setId( null );
66
				$copy->setRefId( $id );
67
			}
68
			else
69
			{
70
				$copy = $listItems[$listRef[$id]];
71
				$ids[] = $listRef[$id];
72
			}
73
74
			if( is_array( $values ) ) {
75
				$copy->fromArray( $values );
76
			}
77
78
			$copy->setPosition( $pos++ );
79
			$listManager->saveItem( $copy, false );
80
		}
81
82
		$listManager->deleteItems( array_diff( $listRef, $ids ) );
83
	}
84
85
86
	/**
87
	 * Creates a new item for the specific manager.
88
	 *
89
	 * @param array $values Associative list of key/value pairs
90
	 * @param array $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
91
	 * @param array $refItems List of items implementing \Aimeos\MShop\Common\Item\Iface
92
	 * @return \Aimeos\MShop\Common\Item\Iface New item
93
	 */
94
	abstract protected function createItemBase( array $values = [], array $listItems = [], array $refItems = [] );
95
96
97
	/**
98
	 * Creates the items with address item, list items and referenced items.
99
	 *
100
	 * @param array $map Associative list of IDs as keys and the associative array of values
101
	 * @param array|null $domains List of domains to fetch list items and referenced items for or null for all
102
	 * @param string $prefix Domain prefix
103
	 * @param array $local Associative list of IDs as keys and the associative array of items as values
104
	 * @param array $local2 Associative list of IDs as keys and the associative array of items as values
105
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Iface
106
	 */
107
	protected function buildItems( array $map, $domains, $prefix, array $local = [], array $local2 = [] )
108
	{
109
		$items = $listItemMap = $refItemMap = $refIdMap = [];
110
111
		if( $domains === null || count( $domains ) > 0 )
112
		{
113
			$listItems = $this->getListItems( array_keys( $map ), $domains, $prefix );
114
115
			foreach( $listItems as $listItem )
116
			{
117
				$domain = $listItem->getDomain();
118
				$parentid = $listItem->getParentId();
119
120
				$listItemMap[$parentid][$domain][$listItem->getId()] = $listItem;
121
				$refIdMap[$domain][$listItem->getRefId()][] = $parentid;
122
			}
123
124
			$refItemMap = $this->getRefItems( $refIdMap );
125
		}
126
127
		foreach( $map as $id => $values )
128
		{
129
			$listItems = [];
130
			if( isset( $listItemMap[$id] ) ) {
131
				$listItems = $listItemMap[$id];
132
			}
133
134
			$refItems = [];
135
			if( isset( $refItemMap[$id] ) ) {
136
				$refItems = $refItemMap[$id];
137
			}
138
139
			$localItems = [];
140
			if( isset( $local[$id] ) ) {
141
				$localItems = $local[$id];
142
			}
143
144
			$localItems2 = [];
145
			if( isset( $local2[$id] ) ) {
146
				$localItems2 = $local2[$id];
147
			}
148
149
			$items[$id] = $this->createItemBase( $values, $listItems, $refItems, $localItems, $localItems2 );
0 ignored issues
show
Unused Code introduced by
The call to Base::createItemBase() has too many arguments starting with $localItems.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
150
		}
151
152
		return $items;
153
	}
154
155
156
	/**
157
	 * Returns the list items that belong to the given IDs.
158
	 *
159
	 * @param array $ids List of IDs
160
	 * @param array|null $domains List of domain names whose referenced items should be attached or null for all
161
	 * @param string $prefix Domain prefix
162
	 * @return array List of items implementing \Aimeos\MShop\Common\Lists\Item\Iface
163
	 */
164
	protected function getListItems( array $ids, $domains, $prefix )
165
	{
166
		$manager = $this->getObject()->getSubManager( 'lists' );
167
168
		$search = $manager->createSearch();
169
170
		$expr = [ $search->compare( '==', $prefix . '.lists.parentid', $ids ) ];
171
172
		if( $domains !== null ) {
173
			$expr[] = $search->compare( '==', $prefix . '.lists.domain', $domains );
174
		}
175
176
		$search->setConditions( $search->combine( '&&', $expr ) );
177
		$search->setSlice( 0, 0x7fffffff );
178
179
		return $manager->searchItems( $search );
180
	}
181
182
183
	/**
184
	 * Returns the referenced items for the given IDs.
185
	 *
186
	 * @param array $refIdMap Associative list of domain/ref-ID/parent-item-ID key/value pairs
187
	 * @return array Associative list of parent-item-ID/domain/items key/value pairs
188
	 */
189
	protected function getRefItems( array $refIdMap )
190
	{
191
		$items = [];
192
		$context = $this->getContext();
193
194
		foreach( $refIdMap as $domain => $list )
195
		{
196
			try
197
			{
198
				$manager = \Aimeos\MShop\Factory::createManager( $context, $domain );
199
200
				$search = $manager->createSearch();
201
				$search->setConditions( $search->compare( '==', str_replace( '/', '.', $domain ) . '.id', array_keys( $list ) ) );
202
				$search->setSlice( 0, 0x7fffffff );
203
204
				foreach( $manager->searchItems( $search ) as $id => $item )
205
				{
206
					foreach( $list[$id] as $parentId ) {
207
						$items[$parentId][$domain][$id] = $item;
208
					}
209
				}
210
			}
211
			catch( \Aimeos\MShop\Exception $e )
212
			{
213
				$logger = $context->getLogger();
214
				$logger->log( sprintf( 'Item referenced in domain "%1$s" not found: %2$s', $domain, $e->getMessage() ) );
215
				$logger->log( $e->getTraceAsString() );
216
			}
217
		}
218
219
		return $items;
220
	}
221
222
223
	/**
224
	 * Adds new, updates existing and deletes removed referenced items
225
	 *
226
	 * @param \Aimeos\MShop\Common\Item\ListRef\Iface $item Item with referenced items
227
	 * @param string $domain Domain of the calling manager
228
	 * @return \Aimeos\MShop\Common\Item\ListRef\Iface $item with updated referenced items
229
	 */
230
	protected function saveRefItems( \Aimeos\MShop\Common\Item\ListRef\Iface $item, $domain )
231
	{
232
		$context = $this->getContext();
233
		$rmListIds = $rmIds = $refManager = [];
234
		$listManager = \Aimeos\MShop\Factory::createManager( $context, $domain . '/lists' );
235
236
237
		foreach( $item->getListItemsDeleted() as $listItem )
238
		{
239
			$rmListIds[] = $listItem->getId();
240
241
			if( ( $refItem = $listItem->getRefItem() ) !== null ) {
242
				$rmIds[$listItem->getDomain()][] = $refItem->getId();
243
			}
244
		}
245
246
247
		try
248
		{
249
			foreach( $rmIds as $refDomain => $ids )
250
			{
251
				$refManager[$refDomain] = \Aimeos\MShop\Factory::createManager( $context, $refDomain );
252
				$refManager[$refDomain]->begin();
253
254
				$refManager[$refDomain]->deleteItems( $ids );
255
			}
256
257
			$listManager->deleteItems( $rmListIds );
258
259
260
			foreach( $item->getListItems( null, null, null, false ) as $listItem )
261
			{
262
				if( ( $refItem = $listItem->getRefItem() ) !== null )
263
				{
264
					if( $refItem instanceof \Aimeos\MShop\Common\Item\Domain\Iface ) {
265
						$refItem->setDomain( $domain );
266
					}
267
268
					$refDomain = $listItem->getDomain();
269
270
					if( !isset( $refManager[$refDomain] ) )
271
					{
272
						$refManager[$refDomain] = \Aimeos\MShop\Factory::createManager( $context, $refDomain );
273
						$refManager[$refDomain]->begin();
274
					}
275
276
					$refItem = $refManager[$refDomain]->saveItem( $refItem );
277
					$listItem->setRefId( $refItem->getId() );
278
				}
279
280
				if( $listItem->getParentId() != $item->getId() ) {
281
					$listItem->setId( null ); //create new list item if copied
282
				}
283
284
				$listItem->setParentId( $item->getId() );
285
				$listManager->saveItem( $listItem );
286
			}
287
288
289
			foreach( $refManager as $manager ) {
290
				$manager->commit();
291
			}
292
		}
293
		catch( \Exception $e )
294
		{
295
			foreach( $refManager as $manager ) {
296
				$manager->rollback();
297
			}
298
299
			throw $e;
300
		}
301
302
		return $item;
303
	}
304
}
305