Passed
Push — master ( 9703dd...7e8f09 )
by Aimeos
15:10
created

Base::saveEntry()   A

Complexity

Conditions 6
Paths 12

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
c 3
b 0
f 0
nc 12
nop 2
dl 0
loc 26
rs 9.2222
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
{
22
	private $context;
23
	private $aimeos;
24
	private $view;
25
	private $path;
26
27
28
	/**
29
	 * Initializes the client
30
	 *
31
	 * @param \Aimeos\MShop\Context\Item\Iface $context MShop context object
32
	 * @param string $path Name of the client separated by slashes, e.g "product/property"
33
	 */
34
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context, string $path )
35
	{
36
		$this->context = $context;
37
		$this->path = $path;
38
	}
39
40
41
	/**
42
	 * Catch unknown methods
43
	 *
44
	 * @param string $name Name of the method
45
	 * @param array $param List of method parameter
46
	 * @throws \Aimeos\Admin\JsonAdm\Exception If method call failed
47
	 */
48
	public function __call( string $name, array $param )
49
	{
50
		throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Unable to call method "%1$s"', $name ) );
51
	}
52
53
54
	/**
55
	 * Returns the Aimeos bootstrap object
56
	 *
57
	 * @return \Aimeos\Bootstrap The Aimeos bootstrap object
58
	 */
59
	public function getAimeos() : \Aimeos\Bootstrap
60
	{
61
		if( !isset( $this->aimeos ) ) {
62
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Aimeos object not available' ) );
63
		}
64
65
		return $this->aimeos;
66
	}
67
68
69
	/**
70
	 * Sets the Aimeos bootstrap object
71
	 *
72
	 * @param \Aimeos\Bootstrap $aimeos The Aimeos bootstrap object
73
	 * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls
74
	 */
75
	public function setAimeos( \Aimeos\Bootstrap $aimeos ) : \Aimeos\Admin\JsonAdm\Iface
76
	{
77
		$this->aimeos = $aimeos;
78
		return $this;
79
	}
80
81
82
	/**
83
	 * Returns the view object that will generate the admin output.
84
	 *
85
	 * @return \Aimeos\MW\View\Iface The view object which generates the admin output
86
	 */
87
	public function getView() : \Aimeos\MW\View\Iface
88
	{
89
		if( !isset( $this->view ) ) {
90
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'No view available' ) );
91
		}
92
93
		return $this->view;
94
	}
95
96
97
	/**
98
	 * Sets the view object that will generate the admin output.
99
	 *
100
	 * @param \Aimeos\MW\View\Iface $view The view object which generates the admin output
101
	 * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls
102
	 */
103
	public function setView( \Aimeos\MW\View\Iface $view ) : \Aimeos\Admin\JsonAdm\Iface
104
	{
105
		$this->view = $view;
106
		return $this;
107
	}
108
109
110
	/**
111
	 * Returns the items with parent/child relationships
112
	 *
113
	 * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface
114
	 * @param array $include List of resource types that should be fetched
115
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface
116
	 */
117
	protected function getChildItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map
118
	{
119
		return map();
120
	}
121
122
123
	/**
124
	 * Returns the context item object
125
	 *
126
	 * @return \Aimeos\MShop\Context\Item\Iface Context object
127
	 */
128
	protected function getContext() : \Aimeos\MShop\Context\Item\Iface
129
	{
130
		return $this->context;
131
	}
132
133
134
	/**
135
	 * Returns the list of domains that are available as resources
136
	 *
137
	 * @param \Aimeos\MW\View\Iface $view View object with "resource" parameter
138
	 * @return array List of domain names
139
	 */
140
	protected function getDomains( \Aimeos\MW\View\Iface $view ) : array
141
	{
142
		if( ( $domains = $view->param( 'resource' ) ) == '' )
143
		{
144
			/** admin/jsonadm/domains
145
			 * A list of domain names whose clients are available for the JSON API
146
			 *
147
			 * The HTTP OPTIONS method returns a list of resources known by the
148
			 * JSON API including their URLs. The list of available resources
149
			 * can be exteded dynamically be implementing a new Jsonadm client
150
			 * class handling request for this new domain.
151
			 *
152
			 * To add the new domain client to the list of resources returned
153
			 * by the HTTP OPTIONS method, you have to add its name in lower case
154
			 * to the existing configuration.
155
			 *
156
			 * @param array List of domain names
157
			 * @since 2016.01
158
			 * @category Developer
159
			 * @see admin/jsonadm/resources
160
			 */
161
			$domains = $this->getContext()->getConfig()->get( 'admin/jsonadm/domains', [] );
162
		}
163
164
		return (array) $domains;
165
	}
166
167
168
	/**
169
	 * Returns the list items for association relationships
170
	 *
171
	 * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface
172
	 * @param array $include List of resource types that should be fetched
173
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
174
	 */
175
	protected function getListItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map
176
	{
177
		return $items->filter( function( $item ) {
178
			return $item instanceof \Aimeos\MShop\Common\Item\Lists\Iface;
179
		} );
180
	}
181
182
183
	/**
184
	 * Returns the path to the client
185
	 *
186
	 * @return string Client path, e.g. "product/property"
187
	 */
188
	protected function getPath() : string
189
	{
190
		return $this->path;
191
	}
192
193
194
	/**
195
	 * Returns the items associated via a lists table
196
	 *
197
	 * @param \Aimeos\Map $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
198
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface
199
	 */
200
	protected function getRefItems( \Aimeos\Map $listItems ) : \Aimeos\Map
201
	{
202
		$list = [];
203
204
		foreach( $listItems as $listItem )
205
		{
206
			if( $refItem = $listItem->getRefItem() ) {
207
				$list[$refItem->getResourceType() . '-' . $refItem->getId()] = $refItem;
208
			}
209
		}
210
211
		return map( $list );
212
	}
213
214
215
	/**
216
	 * Returns the list of allowed resources
217
	 *
218
	 * @param \Aimeos\MW\View\Iface $view View object with "access" helper
219
	 * @param array List of all available resources
0 ignored issues
show
Bug introduced by
The type Aimeos\Admin\JsonAdm\List was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
220
	 * @return array List of allowed resources
221
	 */
222
	protected function getAllowedResources( \Aimeos\MW\View\Iface $view, array $resources ) : array
223
	{
224
		$config = $this->getContext()->getConfig();
225
		$allowed = [];
226
227
		foreach( $resources as $resource )
228
		{
229
			if( $view->access( $config->get( 'admin/jsonadm/resource/' . $resource . '/groups', [] ) ) === true ) {
230
				$allowed[] = $resource;
231
			}
232
		}
233
234
		return $allowed;
235
	}
236
237
238
	/**
239
	 * Returns the list of additional resources
240
	 *
241
	 * @param \Aimeos\MW\View\Iface $view View object with "resource" parameter
242
	 * @return array List of domain names
243
	 */
244
	protected function getResources( \Aimeos\MW\View\Iface $view ) : array
245
	{
246
		/** admin/jsonadm/resources
247
		 * A list of additional resources name whose clients are available for the JSON API
248
		 *
249
		 * The HTTP OPTIONS method returns a list of resources known by the
250
		 * JSON API including their URLs. The list of available resources
251
		 * can be exteded dynamically be implementing a new Jsonadm client
252
		 * class handling request for this new domain.
253
		 *
254
		 * The resource config lists the resources that are not automatically
255
		 * derived from the admin/jsonadm/domains configuration.
256
		 *
257
		 * @param array List of domain names
258
		 * @since 2017.07
259
		 * @category Developer
260
		 * @see admin/jsonadm/domains
261
		 */
262
		return (array) $view->config( 'admin/jsonadm/resources', [] );
263
	}
264
265
266
	/**
267
	 * Initializes the criteria object based on the given parameter
268
	 *
269
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
270
	 * @param array $params List of criteria data with condition, sorting and paging
271
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
272
	 */
273
	protected function initCriteria( \Aimeos\MW\Criteria\Iface $criteria, array $params ) : \Aimeos\MW\Criteria\Iface
274
	{
275
		return $criteria->order( $params['sort'] ?? [] )
276
			->add( $criteria->parse( $params['filter'] ?? [] ) )
277
			->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 );
278
	}
279
280
281
	/**
282
	 * Creates of updates several items at once
283
	 *
284
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
285
	 * @param \stdClass $request Object with request body data
286
	 * @return \Aimeos\Map List of items
287
	 */
288
	protected function saveData( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $request ) : \Aimeos\Map
289
	{
290
		$data = [];
291
292
		if( isset( $request->data ) )
293
		{
294
			foreach( (array) $request->data as $entry ) {
295
				$data[] = $this->saveEntry( $manager, $entry );
296
			}
297
		}
298
299
		return map( $data );
300
	}
301
302
303
	/**
304
	 * Saves and returns the new or updated item
305
	 *
306
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
307
	 * @param \stdClass $entry Object including "id" and "attributes" elements
308
	 * @return \Aimeos\MShop\Common\Item\Iface New or updated item
309
	 */
310
	protected function saveEntry( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $entry ) : \Aimeos\MShop\Common\Item\Iface
311
	{
312
		if( isset( $entry->id ) ) {
313
			$item = $manager->get( $entry->id );
314
		} else {
315
			$item = $manager->create();
316
		}
317
318
		if( isset( $entry->attributes ) && ( $attr = (array) $entry->attributes ) )
319
		{
320
			if( $item instanceof \Aimeos\MShop\Common\Item\Config\Iface )
321
			{
322
				$key = str_replace( '/', '.', $this->path ) . '.config';
323
				$attr[$key] = (array) ( $attr[$key] ?? [] );
324
			}
325
326
			$item = $item->fromArray( $attr, true );
327
		}
328
329
		$item = $manager->save( $item );
330
331
		if( isset( $entry->relationships ) ) {
332
			$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

332
			$this->saveRelationships( $manager, /** @scrutinizer ignore-type */ $item, $entry->relationships );
Loading history...
333
		}
334
335
		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

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