Completed
Push — master ( 934d83...e7352b )
by Aimeos
02:20
created

Base::saveRelationships()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.8177
c 0
b 0
f 0
cc 6
nc 7
nop 3
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2018
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, $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( $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()
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\JQAdm\Iface Reference to this object for fluent calls
74
	 */
75
	public function setAimeos( \Aimeos\Bootstrap $aimeos )
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()
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\JQAdm\Iface Reference to this object for fluent calls
102
	 */
103
	public function setView( \Aimeos\MW\View\Iface $view )
104
	{
105
		$this->view = $view;
106
		return $this;
107
	}
108
109
110
	/**
111
	 * Returns the items with parent/child relationships
112
	 *
113
	 * @param array $items List of items implementing \Aimeos\MShop\Common\Item\Iface
114
	 * @param array $include List of resource types that should be fetched
115
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Iface
116
	 */
117
	protected function getChildItems( array $items, array $include )
118
	{
119
		return [];
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()
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 )
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
			$default = array(
162
				'attribute', 'catalog', 'coupon', 'customer', 'locale', 'media', 'order',
163
				'plugin', 'price', 'product', 'service', 'supplier', 'stock', 'tag', 'text'
164
			);
165
			$domains = $this->getContext()->getConfig()->get( 'admin/jsonadm/domains', $default );
166
		}
167
168
		return (array) $domains;
169
	}
170
171
172
	/**
173
	 * Returns the IDs sent in the request body
174
	 *
175
	 * @param \stdClass $request Decoded request body
176
	 * @return array List of item IDs
177
	 */
178
	protected function getIds( $request )
179
	{
180
		$ids = [];
181
182
		if( isset( $request->data ) )
183
		{
184
			foreach( (array) $request->data as $entry )
185
			{
186
				if( isset( $entry->id ) ) {
187
					$ids[] = $entry->id;
188
				}
189
			}
190
		}
191
192
		return $ids;
193
	}
194
195
196
	/**
197
	 * Returns the list items for association relationships
198
	 *
199
	 * @param array $items List of items implementing \Aimeos\MShop\Common\Item\Iface
200
	 * @param array $include List of resource types that should be fetched
201
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
202
	 */
203
	protected function getListItems( array $items, array $include )
204
	{
205
		return [];
206
	}
207
208
209
	/**
210
	 * Returns the path to the client
211
	 *
212
	 * @return string Client path, e.g. "product/property"
213
	 */
214
	protected function getPath()
215
	{
216
		return $this->path;
217
	}
218
219
220
	/**
221
	 * Returns the items associated via a lists table
222
	 *
223
	 * @param array $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface
224
	 * @return array List of items implementing \Aimeos\MShop\Common\Item\Iface
225
	 */
226
	protected function getRefItems( array $listItems )
227
	{
228
		$list = $map = [];
229
		$context = $this->getContext();
230
231
		foreach( $listItems as $listItem ) {
232
			$map[$listItem->getDomain()][] = $listItem->getRefId();
233
		}
234
235
		foreach( $map as $domain => $ids )
236
		{
237
			$manager = \Aimeos\MShop\Factory::createManager( $context, $domain );
238
239
			$search = $manager->createSearch();
240
			$search->setConditions( $search->compare( '==', str_replace( '/', '.', $domain ) . '.id', $ids ) );
241
242
			$list = array_merge( $list, $manager->searchItems( $search ) );
243
		}
244
245
		return $list;
246
	}
247
248
249
	/**
250
	 * Returns the list of allowed resources
251
	 *
252
	 * @param \Aimeos\MW\View\Iface $view View object with "access" helper
253
	 * @param array List of all available resources
254
	 * @return array List of allowed resources
255
	 */
256
	protected function getAllowedResources( \Aimeos\MW\View\Iface $view, array $resources )
257
	{
258
		$config = $this->getContext()->getConfig();
259
		$allowed = [];
260
261
		foreach( $resources as $resource )
262
		{
263
			if( $view->access( $config->get( 'admin/jsonadm/resource/' . $resource . '/groups', [] ) ) === true ) {
264
				$allowed[] = $resource;
265
			}
266
		}
267
268
		return $allowed;
269
	}
270
271
272
	/**
273
	 * Returns the list of additional resources
274
	 *
275
	 * @param \Aimeos\MW\View\Iface $view View object with "resource" parameter
276
	 * @return array List of domain names
277
	 */
278
	protected function getResources( \Aimeos\MW\View\Iface $view )
279
	{
280
		/** admin/jsonadm/resources
281
		 * A list of additional resources name whose clients are available for the JSON API
282
		 *
283
		 * The HTTP OPTIONS method returns a list of resources known by the
284
		 * JSON API including their URLs. The list of available resources
285
		 * can be exteded dynamically be implementing a new Jsonadm client
286
		 * class handling request for this new domain.
287
		 *
288
		 * The resource config lists the resources that are not automatically
289
		 * derived from the admin/jsonadm/domains configuration.
290
		 *
291
		 * @param array List of domain names
292
		 * @since 2017.07
293
		 * @category Developer
294
		 * @see admin/jsonadm/domains
295
		 */
296
		return (array) $view->config( 'admin/jsonadm/resources', [
297
			'coupon/config', 'plugin/config', 'service/config',
298
			'attribute/type', 'attribute/list/type', 'attribute/property/type',
299
			'catalog/list/type',
300
			'customer/list/type', 'customer/property/type',
301
			'media/type', 'media/list/type', 'media/property/type',
302
			'plugin/type',
303
			'price/type', 'price/list/type',
304
			'product/type', 'product/list/type', 'product/property/type',
305
			'service/type', 'service/list/type',
306
			'supplier/list/type',
307
			'text/type', 'text/list/type',
308
		] );
309
	}
310
311
312
	/**
313
	 * Initializes the criteria object based on the given parameter
314
	 *
315
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
316
	 * @param array $params List of criteria data with condition, sorting and paging
317
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
318
	 */
319
	protected function initCriteria( \Aimeos\MW\Criteria\Iface $criteria, array $params )
320
	{
321
		$this->initCriteriaConditions( $criteria, $params );
322
		$this->initCriteriaSortations( $criteria, $params );
323
		$this->initCriteriaSlice( $criteria, $params );
324
325
		return $criteria;
326
	}
327
328
329
	/**
330
	 * Initializes the criteria object with conditions based on the given parameter
331
	 *
332
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
333
	 * @param array $params List of criteria data with condition, sorting and paging
334
	 */
335
	protected function initCriteriaConditions( \Aimeos\MW\Criteria\Iface $criteria, array $params )
336
	{
337
		if( !isset( $params['filter'] ) ) {
338
			return;
339
		}
340
341
		$existing = $criteria->getConditions();
342
		$criteria->setConditions( $criteria->toConditions( (array) $params['filter'] ) );
343
344
		$expr = array( $criteria->getConditions(), $existing );
345
		$criteria->setConditions( $criteria->combine( '&&', $expr ) );
346
	}
347
348
349
	/**
350
	 * Initializes the criteria object with the slice based on the given parameter.
351
	 *
352
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
353
	 * @param array $params List of criteria data with condition, sorting and paging
354
	 */
355
	protected function initCriteriaSlice( \Aimeos\MW\Criteria\Iface $criteria, array $params )
356
	{
357
		$start = ( isset( $params['page']['offset'] ) ? (int) $params['page']['offset'] : 0 );
358
		$size = ( isset( $params['page']['limit'] ) ? (int) $params['page']['limit'] : 25 );
359
360
		$criteria->setSlice( $start, $size );
361
	}
362
363
364
	/**
365
	 * Initializes the criteria object with sortations based on the given parameter
366
	 *
367
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
368
	 * @param array $params List of criteria data with condition, sorting and paging
369
	 */
370
	protected function initCriteriaSortations( \Aimeos\MW\Criteria\Iface $criteria, array $params )
371
	{
372
		if( !isset( $params['sort'] ) ) {
373
			return;
374
		}
375
376
		$sortation = [];
377
378
		foreach( explode( ',', $params['sort'] ) as $sort )
379
		{
380
			if( $sort[0] === '-' ) {
381
				$sortation[] = $criteria->sort( '-', substr( $sort, 1 ) );
382
			} else {
383
				$sortation[] = $criteria->sort( '+', $sort );
384
			}
385
		}
386
387
		$criteria->setSortations( $sortation );
388
	}
389
390
391
	/**
392
	 * Creates of updates several items at once
393
	 *
394
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
395
	 * @param \stdClass $request Object with request body data
396
	 * @return array List of items
397
	 */
398
	protected function saveData( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $request )
399
	{
400
		$data = [];
401
402
		if( isset( $request->data ) )
403
		{
404
			foreach( (array) $request->data as $entry ) {
405
				$data[] = $this->saveEntry( $manager, $entry );
406
			}
407
		}
408
409
		return $data;
410
	}
411
412
413
	/**
414
	 * Saves and returns the new or updated item
415
	 *
416
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
417
	 * @param \stdClass $entry Object including "id" and "attributes" elements
418
	 * @return \Aimeos\MShop\Common\Item\Iface New or updated item
419
	 */
420
	protected function saveEntry( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $entry )
421
	{
422
		if( isset( $entry->id ) ) {
423
			$item = $manager->getItem( $entry->id );
424
		} else {
425
			$item = $manager->createItem();
426
		}
427
428
		if( isset( $entry->attributes ) ) {
429
			$item->fromArray( (array) $entry->attributes );
430
		}
431
432
		$item = $manager->saveItem( $item );
433
434
		if( isset( $entry->relationships ) ) {
435
			$this->saveRelationships( $manager, $item, $entry->relationships );
436
		}
437
438
		return $manager->getItem( $item->getId() );
439
	}
440
441
442
	/**
443
	 * Saves the item references associated via the list
444
	 *
445
	 * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items
446
	 * @param \Aimeos\MShop\Common\Item\Iface $item Domain item with an unique ID set
447
	 * @param \stdClass $relationships Object including the <domain>/data/attributes structure
448
	 */
449
	protected function saveRelationships( \Aimeos\MShop\Common\Manager\Iface $manager,
450
		\Aimeos\MShop\Common\Item\Iface $item, \stdClass $relationships )
451
	{
452
		$id = $item->getId();
453
		$listManager = $manager->getSubManager( 'lists' );
454
455
		foreach( (array) $relationships as $domain => $list )
456
		{
457
			if( isset( $list->data ) )
458
			{
459
				foreach( (array) $list->data as $data )
460
				{
461
					$listItem = $listManager->createItem();
462
463
					if( isset( $data->attributes ) ) {
464
						$item->fromArray( (array) $data->attributes );
465
					}
466
467
					if( isset( $data->id ) ) {
468
						$listItem->setRefId( $data->id );
469
					}
470
471
					$listItem->setParentId( $id );
472
					$listItem->setDomain( $domain );
473
474
					$listManager->saveItem( $listItem, false );
475
				}
476
			}
477
		}
478
	}
479
}
480