Completed
Push — master ( 325f51...2c9b99 )
by Aimeos
12:01
created

Base::addListItem()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 6
nop 3
dl 0
loc 15
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2017
7
 * @package MShop
8
 * @subpackage Common
9
 */
10
11
12
namespace Aimeos\MShop\Common\Item\ListRef;
13
14
15
/**
16
 * Abstract class for items containing referenced list items.
17
 *
18
 * @package MShop
19
 * @subpackage Common
20
 */
21
abstract class Base extends \Aimeos\MShop\Common\Item\Base
22
{
23
	private $refItems;
24
	private $listItems;
25
	private $rmItems = [];
26
	private $prepared = false;
27
	private $max = 0;
28
29
30
	/**
31
	 * Initializes the item with the given values.
32
	 *
33
	 * @param string $prefix Prefix for the keys returned by toArray()
34
	 * @param array $values Associative list of key/value pairs of the item properties
35
	 * @param array $listItems Two dimensional associative list of domain / ID / list items that implement \Aimeos\MShop\Common\Item\Lists\Iface
36
	 * @param array $refItems Two dimensional associative list of domain / ID / domain items that implement \Aimeos\MShop\Common\Item\Iface
37
	 */
38
	public function __construct( $prefix, array $values = [], array $listItems = [], array $refItems = [] )
39
	{
40
		parent::__construct( $prefix, $values );
41
42
		$this->listItems = $listItems;
43
		$this->refItems = $refItems;
44
	}
45
46
47
	/**
48
	 * Adds a new or overwrite an existing list item which references the given domain item (created if it doesn't exist)
49
	 *
50
	 * @param string $domain Name of the domain (e.g. media, text, etc.)
51
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface $listItem List item referencing the new domain item
52
	 * @param \Aimeos\MShop\Common\Item\Iface|null $refItem New item added to the given domain or null if no item should be referenced
53
	 * @return \Aimeos\MShop\Common\Item\ListRef\Iface Self object for method chaining
54
	 */
55
	public function addListItem( $domain, \Aimeos\MShop\Common\Item\Lists\Iface $listItem, \Aimeos\MShop\Common\Item\Iface $refItem = null )
56
	{
57
		$id = $listItem->getId() ?: 'tmp-' . $this->max++;
58
		$this->listItems[$domain][$id] = $listItem->setDomain( $domain )->setRefItem( $refItem );
59
60
		if( $refItem !== null )
61
		{
62
			$id = $refItem->getId() ?: 'tmp-' . $this->max++;
63
			$listItem->setRefId( $id );
64
65
			$this->refItems[$domain][$id] = $refItem;
66
		}
67
68
		return $this;
69
	}
70
71
72
	/**
73
	 * Removes a list item which references the given domain item (removed as well if it exists)
74
	 *
75
	 * @param string $domain Name of the domain (e.g. media, text, etc.)
76
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface $listItem List item referencing the domain item
77
	 * @param \Aimeos\MShop\Common\Item\Iface|null $refItem Existing item removed from the given domain or null if item shouldn't be removed
78
	 * @return \Aimeos\MShop\Common\Item\ListRef\Iface Self object for method chaining
79
	 * @throws \Aimeos\MShop\Exception If given list item isn't found
80
	 */
81
	public function deleteListItem( $domain, \Aimeos\MShop\Common\Item\Lists\Iface $listItem, \Aimeos\MShop\Common\Item\Iface $refItem = null )
82
	{
83
		if( isset( $this->listItems[$domain] ) )
84
		{
85
			foreach( $this->listItems[$domain] as $key => $litem )
86
			{
87
				if( $litem === $listItem && $listItem->getDomain() === $domain )
88
				{
89
					$this->rmItems[] = $listItem->setRefItem( $refItem );
90
					unset( $this->listItems[$domain][$key] );
91
92
					return $this;
93
				}
94
			}
95
		}
96
97
		throw new \Aimeos\MShop\Exception( sprintf( 'List item for removal from domain "%1$s" not found', $domain ) );
98
	}
99
100
101
	/**
102
	 * Removes a list of list items which references their domain items (removed as well if it exists)
103
	 *
104
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface[] $items Existing list items
105
	 * @return \Aimeos\MShop\Common\Item\Iface Self object for method chaining
106
	 * @throws \Aimeos\MShop\Exception If an item isn't a list item or isn't found
107
	 */
108
	public function deleteListItems( array $items )
109
	{
110
		foreach( $items as $item )
111
		{
112
			if( !( $item instanceof \Aimeos\MShop\Common\Item\Lists\Iface ) ) {
113
				throw new \Aimeos\MShop\Exception( sprintf( 'Not a list item' ) );
114
			}
115
116
			$this->deleteListItem( $item->getDomain(), $item, $item->getRefItem() );
117
		}
118
119
		return $this;
120
	}
121
122
123
	/**
124
	 * Returns the deleted list items which include the domain items if available
125
	 *
126
	 * @return \Aimeos\MShop\Common\Item\Lists\Iface[] List items with referenced items attached (optional)
127
	 */
128
	public function getListItemsDeleted()
129
	{
130
		return $this->rmItems;
131
	}
132
133
134
	/**
135
	 * Returns the list item for the given reference ID, domain and list type
136
	 *
137
	 * @param string $domain Name of the domain (e.g. product, text, etc.)
138
	 * @param string $listtype Name of the list item type
139
	 * @param string $refId Unique ID of the referenced item
140
	 * @param boolean $active True to return only active items, false to return all
141
	 * @return \Aimeos\MShop\Common\Item\Lists\Iface|null Matching list item or null if none
142
	 */
143
	public function getListItem( $domain, $listtype, $refId, $active = true )
144
	{
145
		if( isset( $this->listItems[$domain] ) )
146
		{
147
			foreach( $this->listItems[$domain] as $listItem )
148
			{
149
				if( $listItem->getRefId() == $refId && $listItem->getType() === $listtype
150
					&& ( $active === false || $listItem->isAvailable() )
151
				) {
152
					return $listItem;
153
				}
154
			}
155
		}
156
	}
157
158
159
	/**
160
	 * Returns the list items attached, optionally filtered by domain and list type.
161
	 *
162
	 * The reference parameter in searchItems() must have been set accordingly
163
	 * to the requested domain to get the items. Otherwise, no items will be
164
	 * returned by this method.
165
	 *
166
	 * @param array|string|null $domain Name/Names of the domain (e.g. product, text, etc.) or null for all
167
	 * @param array|string|null $listtype Name/Names of the list item type or null for all
168
	 * @param array|string|null $type Name/Names of the item type or null for all
169
	 * @param boolean $active True to return only active items, false to return all
170
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
171
	 */
172
	public function getListItems( $domain = null, $listtype = null, $type = null, $active = true )
173
	{
174
		$result = [];
175
		$this->prepareListItems();
176
177
		$iface = '\\Aimeos\\MShop\\Common\\Item\\Typeid\\Iface';
178
		$listTypes = ( is_array( $listtype ) ? $listtype : array( $listtype ) );
179
		$types = ( is_array( $type ) ? $type : array( $type ) );
180
181
182
		foreach( $this->listItems as $dname => $list )
183
		{
184
			if( is_array( $domain ) && !in_array( $dname, $domain ) || $domain !== null && $dname !== $domain ) {
185
				continue;
186
			}
187
188
			foreach( $list as $id => $item )
189
			{
190
				if( $listtype && ( !($item instanceof $iface) || !in_array( $item->getType(), $listTypes ) ) ) {
191
					continue;
192
				}
193
194
				if( $type && ( !($item->getRefItem() instanceof $iface) || !in_array( $item->getRefItem()->getType(), $types ) ) ) {
195
					continue;
196
				}
197
198
				if( $active && !$item->isAvailable() ) {
199
					continue;
200
				}
201
202
				$result[$id] = $item;
203
			}
204
		}
205
206
		return $result;
207
	}
208
209
210
	/**
211
	 * Returns the product, text, etc. items filtered by domain and optionally by type and list type.
212
	 *
213
	 * The reference parameter in searchItems() must have been set accordingly
214
	 * to the requested domain to get the items. Otherwise, no items will be
215
	 * returned by this method.
216
	 *
217
	 * @param array|string|null $domain Name/Names of the domain (e.g. product, text, etc.) or null for all
218
	 * @param array|string|null $type Name/Names of the item type or null for all
219
	 * @param array|string|null $listtype Name/Names of the list item type or null for all
220
	 * @param boolean $active True to return only active items, false to return all
221
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Iface
222
	 */
223
	public function getRefItems( $domain = null, $type = null, $listtype = null, $active = true )
224
	{
225
		$list = [];
226
227
		foreach( $this->getListItems( $domain, $listtype, $type, $active ) as $listItem )
228
		{
229
			if( ( $refItem = $listItem->getRefItem() ) !== null && ( $active === false || $refItem->isAvailable() ) ) {
230
				$list[$listItem->getDomain()][$listItem->getRefId()] = $refItem;
231
			}
232
		}
233
234
		if( is_array( $domain ) || $domain === null ) {
235
			return $list;
236
		}
237
238
		if( isset( $list[$domain] ) ) {
239
			return $list[$domain];
240
		}
241
242
		return [];
243
	}
244
245
246
	/**
247
	 * Returns the label of the item.
248
	 * This method should be implemented in the derived class if a label column is available.
249
	 *
250
	 * @return string Label of the item
251
	 */
252
	public function getLabel()
253
	{
254
		return '';
255
	}
256
257
258
	/**
259
	 * Returns the localized text type of the item or the internal label if no name is available.
260
	 *
261
	 * @param string $type Text type to be returned
262
	 * @return string Specified text type or label of the item
263
	 */
264
	public function getName( $type = 'name' )
265
	{
266
		$items = $this->getRefItems( 'text', $type );
267
268
		if( ( $item = reset( $items ) ) !== false ) {
269
			return $item->getContent();
270
		}
271
272
		return $this->getLabel();
273
	}
274
275
276
	/**
277
	 * Compares the positions of two items for sorting.
278
	 *
279
	 * @param \Aimeos\MShop\Common\Item\Position\Iface $a First item
280
	 * @param \Aimeos\MShop\Common\Item\Position\Iface $b Second item
281
	 * @return integer -1 if position of $a < $b, 1 if position of $a > $b and 0 if both positions are equal
282
	 */
283
	protected function comparePosition( \Aimeos\MShop\Common\Item\Position\Iface $a, \Aimeos\MShop\Common\Item\Position\Iface $b )
284
	{
285
		if( $a->getPosition() === $b->getPosition() ) {
286
			return 0;
287
		}
288
289
		return ( $a->getPosition() < $b->getPosition() ) ? -1 : 1;
290
	}
291
292
293
	/**
294
	 * Sorts the list items according to their position value and attaches the referenced item
295
	 */
296
	protected function prepareListItems()
297
	{
298
		if( $this->prepared === true ) {
299
			return;
300
		}
301
302
		foreach( $this->listItems as $domain => $list )
303
		{
304
			foreach( $list as $listItem )
305
			{
306
				$refId = $listItem->getRefId();
307
308
				if( isset( $this->refItems[$domain][$refId] ) ) {
309
					$listItem->setRefItem( $this->refItems[$domain][$refId] );
310
				}
311
			}
312
313
			uasort( $this->listItems[$domain], array( $this, 'comparePosition' ) );
314
		}
315
316
		$this->prepared = true;
317
	}
318
}
319