Passed
Push — master ( 74acd6...794220 )
by Aimeos
03:19
created

Base::getContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2020
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 array 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 map();
178
	}
179
180
181
	/**
182
	 * Returns the path to the client
183
	 *
184
	 * @return string Client path, e.g. "product/property"
185
	 */
186
	protected function getPath() : string
187
	{
188
		return $this->path;
189
	}
190
191
192
	/**
193
	 * Returns the items associated via a lists table
194
	 *
195
	 * @param \Aimeos\Map $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
196
	 * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface
197
	 */
198
	protected function getRefItems( \Aimeos\Map $listItems ) : \Aimeos\Map
199
	{
200
		$map = [];
201
		$list = map();
202
		$context = $this->getContext();
203
204
		foreach( $listItems as $listItem ) {
205
			$map[$listItem->getDomain()][] = $listItem->getRefId();
206
		}
207
208
		foreach( $map as $domain => $ids )
209
		{
210
			$manager = \Aimeos\MShop::create( $context, $domain );
211
212
			$search = $manager->filter();
213
			$search->setConditions( $search->compare( '==', str_replace( '/', '.', $domain ) . '.id', $ids ) );
0 ignored issues
show
Bug introduced by
The method setConditions() does not exist on Aimeos\MW\Criteria\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\MW\Criteria\Base. Are you sure you never get one of those? ( Ignorable by Annotation )

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

213
			$search->/** @scrutinizer ignore-call */ 
214
            setConditions( $search->compare( '==', str_replace( '/', '.', $domain ) . '.id', $ids ) );
Loading history...
Bug introduced by
The method compare() does not exist on Aimeos\MW\Criteria\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\MW\Criteria\Base. Are you sure you never get one of those? ( Ignorable by Annotation )

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

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

339
			$this->saveRelationships( $manager, /** @scrutinizer ignore-type */ $item, $entry->relationships );
Loading history...
340
		}
341
342
		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

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