Traits::deleteRefItems()   B
last analyzed

Complexity

Conditions 7
Paths 11

Size

Total Lines 26
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 11
c 2
b 0
f 0
dl 0
loc 26
rs 8.8333
cc 7
nc 11
nop 1
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2025
6
 * @package MShop
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\MShop\Common\Manager\ListsRef;
12
13
14
/**
15
 * Trait for managers working with referenced list items
16
 *
17
 * @package MShop
18
 * @subpackage Common
19
 */
20
trait Traits
21
{
22
	/**
23
	 * Returns the context object.
24
	 *
25
	 * @return \Aimeos\MShop\ContextIface Context object
26
	 */
27
	abstract protected function context() : \Aimeos\MShop\ContextIface;
28
29
	/**
30
	 * Returns the domain of the manager
31
	 *
32
	 * @return string Domain of the manager
33
	 */
34
	abstract protected function domain() : string;
35
36
	/**
37
	 * Returns the outmost decorator of the decorator stack
38
	 *
39
	 * @return \Aimeos\MShop\Common\Manager\Iface Outmost decorator object
40
	 */
41
	abstract protected function object() : \Aimeos\MShop\Common\Manager\Iface;
42
43
44
	/**
45
	 * Creates a new lists item object
46
	 *
47
	 * @param array $values Values the item should be initialized with
48
	 * @return \Aimeos\MShop\Common\Item\Lists\Iface New list items object
49
	 */
50
	public function createListItem( array $values = [] ) : \Aimeos\MShop\Common\Item\Lists\Iface
51
	{
52
		$domain = $this->domain();
53
		$context = $this->context();
54
55
		$values['.date'] = $context->datetime();
56
		$values[$domain . '.lists.siteid'] = $values[$domain . '.lists.siteid'] ?? $context->locale()->getSiteId();
57
58
		return new \Aimeos\MShop\Common\Item\Lists\Standard( $domain . '.lists.', $values );
59
	}
60
61
62
	/**
63
	 * Removes the items referenced by the given list items.
64
	 *
65
	 * @param \Aimeos\MShop\Common\Item\ListsRef\Iface[]|\Aimeos\Map|array $items List of items with deleted list items
66
	 * @return \Aimeos\MShop\Common\Manager\ListsRef\Iface Manager object for method chaining
67
	 */
68
	protected function deleteRefItems( $items ) : \Aimeos\MShop\Common\Manager\ListsRef\Iface
69
	{
70
		if( ( $items = map( $items ) )->isEmpty() ) {
71
			return $this;
72
		}
73
74
		$map = [];
75
76
		foreach( $items as $item )
77
		{
78
			if( $item instanceof \Aimeos\MShop\Common\Item\ListsRef\Iface )
79
			{
80
				foreach( $item->getListItemsDeleted() as $listItem )
81
				{
82
					if( $listItem->getRefItem() ) {
83
						$map[$listItem->getDomain()][] = $listItem->getRefId();
84
					}
85
				}
86
			}
87
		}
88
89
		foreach( $map as $domain => $ids ) {
90
			\Aimeos\MShop::create( $this->context(), $domain )->begin()->delete( $ids )->commit();
91
		}
92
93
		return $this;
94
	}
95
96
97
	/**
98
	 * Returns the list items that belong to the given parent item IDs.
99
	 *
100
	 * @param string[] $parentIds List of parent item IDs
101
	 * @param string[] $ref List of domain names whose referenced items should be attached
102
	 * @param string $domain Domain prefix
103
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface with IDs as keys
104
	 */
105
	protected function getListItems( array $parentIds, array $ref, string $domain ) : array
106
	{
107
		if( empty( $ref ) ) {
108
			return [];
109
		}
110
111
		$manager = $this->object()->getSubManager( 'lists' );
112
		$search = $manager->filter()->slice( 0, 0x7fffffff );
113
114
		$list = [];
115
		$len = strlen( $domain );
116
		$expr = [$search->compare( '==', $domain . '.lists.parentid', $parentIds )];
117
118
		foreach( $ref as $key => $type )
119
		{
120
			if( is_array( $type ) )
121
			{
122
				$key = !strncmp( $key, $domain . '/', $len + 1 ) ? [$key, substr( $key, $len + 1 )] : $key; // remove prefix
123
124
				$list[] = $search->and( [
125
					$search->compare( '==', $domain . '.lists.domain', $key ),
126
					$search->compare( '==', $domain . '.lists.type', $type ),
127
				] );
128
			}
129
			else
130
			{
131
				$type = !strncmp( $type, $domain . '/', $len + 1 ) ? [$type, substr( $type, $len + 1 )] : $type; // remove prefix
132
				$list[] = $search->compare( '==', $domain . '.lists.domain', $type );
133
			}
134
		}
135
136
		if( !empty( $list ) ) {
137
			$expr[] = $search->or( $list );
138
		}
139
140
		return $manager->search( $search->add( $search->and( $expr ) ), $ref )
141
			->uasort( fn( $a, $b ) => $a->getPosition() <=> $b->getPosition() )
142
			->all();
143
	}
144
145
146
	/**
147
	 * Adds new, updates existing and deletes removed list items and referenced items if available
148
	 *
149
	 * @param \Aimeos\MShop\Common\Item\ListsRef\Iface $item Item with referenced items
150
	 * @param string $domain Domain of the calling manager
151
	 * @param bool $fetch True if the new ID should be returned in the item
152
	 * @return \Aimeos\MShop\Common\Item\ListsRef\Iface $item with updated referenced items
153
	 */
154
	protected function saveListItems( \Aimeos\MShop\Common\Item\ListsRef\Iface $item, string $domain,
155
		bool $fetch = true ) : \Aimeos\MShop\Common\Item\ListsRef\Iface
156
	{
157
		$context = $this->context();
158
		$rmListItems = $rmItems = $refManager = [];
159
		$listManager = $this->object()->getSubManager( 'lists' );
160
161
162
		foreach( $item->getListItemsDeleted() as $listItem )
163
		{
164
			$rmListItems[] = $listItem;
165
166
			if( ( $refItem = $listItem->getRefItem() ) !== null ) {
167
				$rmItems[$listItem->getDomain()][] = $refItem->getId();
168
			}
169
		}
170
171
172
		try
173
		{
174
			foreach( $rmItems as $refDomain => $list )
175
			{
176
				$refManager[$refDomain] = \Aimeos\MShop::create( $context, $refDomain );
177
				$refManager[$refDomain]->begin();
178
179
				$refManager[$refDomain]->delete( $list );
180
			}
181
182
			$listManager->delete( $rmListItems );
183
184
185
			foreach( $item->getListItems( null, null, null, false ) as $listItem )
186
			{
187
				$refDomain = $listItem->getDomain();
188
189
				if( ( $refItem = $listItem->getRefItem() ) !== null )
190
				{
191
					if( !isset( $refManager[$refDomain] ) )
192
					{
193
						$refManager[$refDomain] = \Aimeos\MShop::create( $context, $refDomain );
194
						$refManager[$refDomain]->begin();
195
					}
196
197
					$refItem = $refManager[$refDomain]->save( $refItem );
198
					$listItem->setRefId( $refItem->getId() );
199
				}
200
201
				if( $listItem->getParentId() && $listItem->getParentId() != $item->getId() ) {
202
					$listItem->setId( null ); // create new list item if copied
203
				}
204
205
				$listManager->save( $listItem->setParentId( $item->getId() ), $fetch );
206
			}
207
208
209
			foreach( $refManager as $manager ) {
210
				$manager->commit();
211
			}
212
		}
213
		catch( \Exception $e )
214
		{
215
			foreach( $refManager as $manager ) {
216
				$manager->rollback();
217
			}
218
219
			throw $e;
220
		}
221
222
		return $item;
223
	}
224
}
225