Passed
Push — master ( e3d357...daade4 )
by Aimeos
10:32 queued 08:10
created

Base   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 356
Duplicated Lines 0 %

Importance

Changes 13
Bugs 0 Features 0
Metric Value
wmc 38
eloc 75
c 13
b 0
f 0
dl 0
loc 356
rs 9.36

18 Methods

Rating   Name   Duplication   Size   Complexity  
A initCriteria() 0 5 1
A getRefItems() 0 12 3
A setAimeos() 0 4 1
A getResources() 0 19 1
A getAllowedResources() 0 13 3
A getPath() 0 3 1
A setView() 0 4 1
A saveEntry() 0 26 6
B saveRelationships() 0 26 7
A getDomains() 0 25 2
A getListItems() 0 4 1
A saveData() 0 12 3
A getAimeos() 0 7 2
A __call() 0 3 1
A getContext() 0 3 1
A __construct() 0 4 1
A getChildItems() 0 3 1
A view() 0 7 2
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2021
6
 * @package Admin
7
 * @subpackage JsonAdm
8
 */
9
10
11
namespace Aimeos\Admin\JsonAdm;
12
13
14
/**
15
 * JSON API common client
16
 *
17
 * @package Admin
18
 * @subpackage JsonAdm
19
 */
20
abstract class Base
21
	implements \Aimeos\MW\Macro\Iface
22
{
23
	use \Aimeos\MW\Macro\Traits;
24
25
26
	private $context;
27
	private $aimeos;
28
	private $view;
29
	private $path;
30
31
32
	/**
33
	 * Initializes the client
34
	 *
35
	 * @param \Aimeos\MShop\Context\Item\Iface $context MShop context object
36
	 * @param string $path Name of the client separated by slashes, e.g "product/property"
37
	 */
38
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context, string $path )
39
	{
40
		$this->context = $context;
41
		$this->path = $path;
42
	}
43
44
45
	/**
46
	 * Catch unknown methods
47
	 *
48
	 * @param string $name Name of the method
49
	 * @param array $param List of method parameter
50
	 * @throws \Aimeos\Admin\JsonAdm\Exception If method call failed
51
	 */
52
	public function __call( string $name, array $param )
53
	{
54
		throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Unable to call method "%1$s"', $name ) );
55
	}
56
57
58
	/**
59
	 * Returns the Aimeos bootstrap object
60
	 *
61
	 * @return \Aimeos\Bootstrap The Aimeos bootstrap object
62
	 */
63
	public function getAimeos() : \Aimeos\Bootstrap
64
	{
65
		if( !isset( $this->aimeos ) ) {
66
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Aimeos object not available' ) );
67
		}
68
69
		return $this->aimeos;
70
	}
71
72
73
	/**
74
	 * Sets the Aimeos bootstrap object
75
	 *
76
	 * @param \Aimeos\Bootstrap $aimeos The Aimeos bootstrap object
77
	 * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls
78
	 */
79
	public function setAimeos( \Aimeos\Bootstrap $aimeos ) : \Aimeos\Admin\JsonAdm\Iface
80
	{
81
		$this->aimeos = $aimeos;
82
		return $this;
83
	}
84
85
86
	/**
87
	 * Returns the view object that will generate the admin output.
88
	 *
89
	 * @return \Aimeos\MW\View\Iface The view object which generates the admin output
90
	 */
91
	public function view() : \Aimeos\MW\View\Iface
92
	{
93
		if( !isset( $this->view ) ) {
94
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'No view available' ) );
95
		}
96
97
		return $this->view;
98
	}
99
100
101
	/**
102
	 * Sets the view object that will generate the admin output.
103
	 *
104
	 * @param \Aimeos\MW\View\Iface $view The view object which generates the admin output
105
	 * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls
106
	 */
107
	public function setView( \Aimeos\MW\View\Iface $view ) : \Aimeos\Admin\JsonAdm\Iface
108
	{
109
		$this->view = $view;
110
		return $this;
111
	}
112
113
114
	/**
115
	 * Returns the items with parent/child relationships
116
	 *
117
	 * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface
118
	 * @param array $include List of resource types that should be fetched
119
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface
120
	 */
121
	protected function getChildItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map
122
	{
123
		return map();
124
	}
125
126
127
	/**
128
	 * Returns the context item object
129
	 *
130
	 * @return \Aimeos\MShop\Context\Item\Iface Context object
131
	 */
132
	protected function getContext() : \Aimeos\MShop\Context\Item\Iface
133
	{
134
		return $this->context;
135
	}
136
137
138
	/**
139
	 * Returns the list of domains that are available as resources
140
	 *
141
	 * @param \Aimeos\MW\View\Iface $view View object with "resource" parameter
142
	 * @return array List of domain names
143
	 */
144
	protected function getDomains( \Aimeos\MW\View\Iface $view ) : array
145
	{
146
		if( ( $domains = $view->param( 'resource' ) ) == '' )
147
		{
148
			/** admin/jsonadm/domains
149
			 * A list of domain names whose clients are available for the JSON API
150
			 *
151
			 * The HTTP OPTIONS method returns a list of resources known by the
152
			 * JSON API including their URLs. The list of available resources
153
			 * can be exteded dynamically be implementing a new Jsonadm client
154
			 * class handling request for this new domain.
155
			 *
156
			 * To add the new domain client to the list of resources returned
157
			 * by the HTTP OPTIONS method, you have to add its name in lower case
158
			 * to the existing configuration.
159
			 *
160
			 * @param array List of domain names
161
			 * @since 2016.01
162
			 * @category Developer
163
			 * @see admin/jsonadm/resources
164
			 */
165
			$domains = $this->getContext()->getConfig()->get( 'admin/jsonadm/domains', [] );
166
		}
167
168
		return (array) $domains;
169
	}
170
171
172
	/**
173
	 * Returns the list items for association relationships
174
	 *
175
	 * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface
176
	 * @param array $include List of resource types that should be fetched
177
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
178
	 */
179
	protected function getListItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map
180
	{
181
		return $items->filter( function( $item ) {
182
			return $item instanceof \Aimeos\MShop\Common\Item\Lists\Iface;
183
		} );
184
	}
185
186
187
	/**
188
	 * Returns the path to the client
189
	 *
190
	 * @return string Client path, e.g. "product/property"
191
	 */
192
	protected function getPath() : string
193
	{
194
		return $this->path;
195
	}
196
197
198
	/**
199
	 * Returns the items associated via a lists table
200
	 *
201
	 * @param \Aimeos\Map $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
202
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface
203
	 */
204
	protected function getRefItems( \Aimeos\Map $listItems ) : \Aimeos\Map
205
	{
206
		$list = [];
207
208
		foreach( $listItems as $listItem )
209
		{
210
			if( $refItem = $listItem->getRefItem() ) {
211
				$list[$refItem->getResourceType() . '-' . $refItem->getId()] = $refItem;
212
			}
213
		}
214
215
		return map( $list );
216
	}
217
218
219
	/**
220
	 * Returns the list of allowed resources
221
	 *
222
	 * @param \Aimeos\MW\View\Iface $view View object with "access" helper
223
	 * @param array $resources List of all available resources
224
	 * @return array List of allowed resources
225
	 */
226
	protected function getAllowedResources( \Aimeos\MW\View\Iface $view, array $resources ) : array
227
	{
228
		$config = $this->getContext()->getConfig();
229
		$allowed = [];
230
231
		foreach( $resources as $resource )
232
		{
233
			if( $view->access( $config->get( 'admin/jsonadm/resource/' . $resource . '/groups', [] ) ) === true ) {
234
				$allowed[] = $resource;
235
			}
236
		}
237
238
		return $allowed;
239
	}
240
241
242
	/**
243
	 * Returns the list of additional resources
244
	 *
245
	 * @param \Aimeos\MW\View\Iface $view View object with "resource" parameter
246
	 * @return array List of domain names
247
	 */
248
	protected function getResources( \Aimeos\MW\View\Iface $view ) : array
249
	{
250
		/** admin/jsonadm/resources
251
		 * A list of additional resources name whose clients are available for the JSON API
252
		 *
253
		 * The HTTP OPTIONS method returns a list of resources known by the
254
		 * JSON API including their URLs. The list of available resources
255
		 * can be exteded dynamically be implementing a new Jsonadm client
256
		 * class handling request for this new domain.
257
		 *
258
		 * The resource config lists the resources that are not automatically
259
		 * derived from the admin/jsonadm/domains configuration.
260
		 *
261
		 * @param array List of domain names
262
		 * @since 2017.07
263
		 * @category Developer
264
		 * @see admin/jsonadm/domains
265
		 */
266
		return (array) $view->config( 'admin/jsonadm/resources', [] );
267
	}
268
269
270
	/**
271
	 * Initializes the criteria object based on the given parameter
272
	 *
273
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
274
	 * @param array $params List of criteria data with condition, sorting and paging
275
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
276
	 */
277
	protected function initCriteria( \Aimeos\MW\Criteria\Iface $criteria, array $params ) : \Aimeos\MW\Criteria\Iface
278
	{
279
		return $criteria->order( $params['sort'] ?? [] )
280
			->add( $criteria->parse( $params['filter'] ?? [] ) )
281
			->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 );
282
	}
283
284
285
	/**
286
	 * Creates of updates several items at once
287
	 *
288
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
289
	 * @param \stdClass $request Object with request body data
290
	 * @return \Aimeos\Map List of items
291
	 */
292
	protected function saveData( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $request ) : \Aimeos\Map
293
	{
294
		$data = [];
295
296
		if( isset( $request->data ) )
297
		{
298
			foreach( (array) $request->data as $entry ) {
299
				$data[] = $this->saveEntry( $manager, $entry );
300
			}
301
		}
302
303
		return map( $data );
304
	}
305
306
307
	/**
308
	 * Saves and returns the new or updated item
309
	 *
310
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
311
	 * @param \stdClass $entry Object including "id" and "attributes" elements
312
	 * @return \Aimeos\MShop\Common\Item\Iface New or updated item
313
	 */
314
	protected function saveEntry( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $entry ) : \Aimeos\MShop\Common\Item\Iface
315
	{
316
		if( isset( $entry->id ) ) {
317
			$item = $manager->get( $entry->id );
318
		} else {
319
			$item = $manager->create();
320
		}
321
322
		if( isset( $entry->attributes ) && ( $attr = (array) $entry->attributes ) )
323
		{
324
			if( $item instanceof \Aimeos\MShop\Common\Item\Config\Iface )
325
			{
326
				$key = str_replace( '/', '.', $this->path ) . '.config';
327
				$attr[$key] = (array) ( $attr[$key] ?? [] );
328
			}
329
330
			$item = $item->fromArray( $attr, true );
331
		}
332
333
		$item = $manager->save( $item );
334
335
		if( isset( $entry->relationships ) ) {
336
			$this->saveRelationships( $manager, $item, $entry->relationships );
0 ignored issues
show
Bug introduced by
It seems like $item can also be of type Aimeos\Map; however, parameter $item of Aimeos\Admin\JsonAdm\Base::saveRelationships() does only seem to accept Aimeos\MShop\Common\Item\Iface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

336
			$this->saveRelationships( $manager, /** @scrutinizer ignore-type */ $item, $entry->relationships );
Loading history...
337
		}
338
339
		return $manager->get( $item->getId() );
0 ignored issues
show
Bug introduced by
It seems like $item->getId() can also be of type Aimeos\Map and null; however, parameter $id of Aimeos\MShop\Common\Manager\Iface::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

339
		return $manager->get( /** @scrutinizer ignore-type */ $item->getId() );
Loading history...
340
	}
341
342
343
	/**
344
	 * Saves the item references associated via the list
345
	 *
346
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
347
	 * @param \Aimeos\MShop\Common\Item\Iface $item Domain item with an unique ID set
348
	 * @param \stdClass $relationships Object including the <domain>/data/attributes structure
349
	 */
350
	protected function saveRelationships( \Aimeos\MShop\Common\Manager\Iface $manager,
351
		\Aimeos\MShop\Common\Item\Iface $item, \stdClass $relationships )
352
	{
353
		$id = $item->getId();
354
		$listManager = $manager->getSubManager( 'lists' );
355
356
		foreach( (array) $relationships as $domain => $list )
357
		{
358
			if( isset( $list->data ) )
359
			{
360
				foreach( (array) $list->data as $data )
361
				{
362
					$listItem = $listManager->create()->setType( 'default' );
363
364
					if( isset( $data->attributes ) && ( $attr = (array) $data->attributes ) ) {
365
						$key = str_replace( '/', '.', $this->path ) . '.config';
366
						$attr[$key] = (array) ( $attr[$key] ?? [] );
367
						$listItem = $listItem->fromArray( $attr, true );
368
					}
369
370
					if( isset( $data->id ) ) {
371
						$listItem->setRefId( $data->id );
372
					}
373
374
					$listItem->setParentId( $id )->setDomain( $domain );
375
					$listManager->save( $listItem, false );
376
				}
377
			}
378
		}
379
	}
380
}
381