Issues (31)

src/Admin/JsonAdm/Base.php (2 issues)

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

323
			$this->saveRelationships( $manager, /** @scrutinizer ignore-type */ $item, $entry->relationships );
Loading history...
324
		}
325
326
		return $manager->get( $item->getId() );
0 ignored issues
show
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

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