Passed
Push — master ( 4b9638...ca8d3f )
by Aimeos
11:06
created

Base::createSubClient()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
c 0
b 0
f 0
nc 6
nop 2
dl 0
loc 28
rs 9.4555
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2022
6
 * @package Admin
7
 * @subpackage JQAdm
8
 */
9
10
11
namespace Aimeos\Admin\JQAdm;
12
13
sprintf( 'type' ); // for translation
14
15
16
/**
17
 * Common abstract class for all admin client classes.
18
 *
19
 * @package Admin
20
 * @subpackage JQAdm
21
 */
22
abstract class Base
23
	implements \Aimeos\Admin\JQAdm\Iface, \Aimeos\Macro\Iface
24
{
25
	use \Aimeos\Macro\Macroable;
26
27
28
	private $view;
29
	private $aimeos;
30
	private $context;
31
	private $subclients;
32
	private $object;
33
34
35
	/**
36
	 * Initializes the class instance.
37
	 *
38
	 * @param \Aimeos\MShop\ContextIface $context Context object
39
	 */
40
	public function __construct( \Aimeos\MShop\ContextIface $context )
41
	{
42
		$this->context = $context;
43
	}
44
45
46
	/**
47
	 * Adds the required data used in the attribute template
48
	 *
49
	 * @param \Aimeos\Base\View\Iface $view View object
50
	 * @return \Aimeos\Base\View\Iface View object with assigned parameters
51
	 */
52
	public function data( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface
53
	{
54
		return $view;
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\JQAdm\Exception( $this->context->translate( 'admin', '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\JQAdm\Iface Reference to this object for fluent calls
78
	 */
79
	public function setAimeos( \Aimeos\Bootstrap $aimeos ) : \Aimeos\Admin\JQAdm\Iface
80
	{
81
		$this->aimeos = $aimeos;
82
		return $this;
83
	}
84
85
86
	/**
87
	 * Makes the outer decorator object available to inner objects
88
	 *
89
	 * @param \Aimeos\Admin\JQAdm\Iface $object Outmost object
90
	 * @return \Aimeos\Admin\JQAdm\Iface Same object for fluent interface
91
	 */
92
	public function setObject( \Aimeos\Admin\JQAdm\Iface $object ) : \Aimeos\Admin\JQAdm\Iface
93
	{
94
		$this->object = $object;
95
		return $this;
96
	}
97
98
99
	/**
100
	 * Returns the view object that will generate the admin output.
101
	 *
102
	 * @return \Aimeos\Base\View\Iface The view object which generates the admin output
103
	 */
104
	protected function view() : \Aimeos\Base\View\Iface
105
	{
106
		if( !isset( $this->view ) ) {
107
			throw new \Aimeos\Admin\JQAdm\Exception( $this->context->translate( 'admin', 'No view available' ) );
108
		}
109
110
		return $this->view;
111
	}
112
113
114
	/**
115
	 * Sets the view object that will generate the admin output.
116
	 *
117
	 * @param \Aimeos\Base\View\Iface $view The view object which generates the admin output
118
	 * @return \Aimeos\Admin\JQAdm\Iface Reference to this object for fluent calls
119
	 */
120
	public function setView( \Aimeos\Base\View\Iface $view ) : \Aimeos\Admin\JQAdm\Iface
121
	{
122
		$this->view = $view;
123
		return $this;
124
	}
125
126
127
	/**
128
	 * Copies a resource
129
	 *
130
	 * @return string|null Output to display
131
	 */
132
	public function copy() : ?string
133
	{
134
		$body = null;
135
		$view = $this->view();
136
137
		foreach( $this->getSubClients() as $idx => $client )
138
		{
139
			$view->tabindex = ++$idx + 1;
140
			$body .= $client->copy();
141
		}
142
143
		return $body;
144
	}
145
146
147
	/**
148
	 * Creates a new resource
149
	 *
150
	 * @return string|null Output to display
151
	 */
152
	public function create() : ?string
153
	{
154
		$body = null;
155
		$view = $this->view();
156
157
		foreach( $this->getSubClients() as $idx => $client )
158
		{
159
			$view->tabindex = ++$idx + 1;
160
			$body .= $client->create();
161
		}
162
163
		return $body;
164
	}
165
166
167
	/**
168
	 * Deletes a resource
169
	 *
170
	 * @return string|null Output to display
171
	 */
172
	public function delete() : ?string
173
	{
174
		$body = null;
175
176
		foreach( $this->getSubClients() as $client ) {
177
			$body .= $client->delete();
178
		}
179
180
		return $body;
181
	}
182
183
184
	/**
185
	 * Exports a resource
186
	 *
187
	 * @return string|null Output to display
188
	 */
189
	public function export() : ?string
190
	{
191
		$body = null;
192
193
		foreach( $this->getSubClients() as $client ) {
194
			$body .= $client->export();
195
		}
196
197
		return $body;
198
	}
199
200
201
	/**
202
	 * Returns a resource
203
	 *
204
	 * @return string|null Output to display
205
	 */
206
	public function get() : ?string
207
	{
208
		$body = null;
209
		$view = $this->view();
210
211
		foreach( $this->getSubClients() as $idx => $client )
212
		{
213
			$view->tabindex = ++$idx + 1;
214
			$body .= $client->get();
215
		}
216
217
		return $body;
218
	}
219
220
221
	/**
222
	 * Imports a resource
223
	 *
224
	 * @return string|null Output to display
225
	 * @deprecated 2021.01
226
	 */
227
	public function import() : ?string
228
	{
229
		$body = null;
230
231
		foreach( $this->getSubClients() as $client ) {
232
			$body .= $client->import();
233
		}
234
235
		return null;
236
	}
237
238
239
	/**
240
	 * Saves the data
241
	 *
242
	 * @return string|null Output to display
243
	 */
244
	public function save() : ?string
245
	{
246
		$body = null;
247
248
		foreach( $this->getSubClients() as $client ) {
249
			$body .= $client->save();
250
		}
251
252
		return $body;
253
	}
254
255
256
	/**
257
	 * Returns a list of resource according to the conditions
258
	 *
259
	 * @return string|null Output to display
260
	 */
261
	public function search() : ?string
262
	{
263
		$body = null;
264
265
		foreach( $this->getSubClients() as $client ) {
266
			$body .= $client->search();
267
		}
268
269
		return $body;
270
	}
271
272
273
	/**
274
	 * Returns the PSR-7 response object for the request
275
	 *
276
	 * @return \Psr\Http\Message\ResponseInterface Response object
277
	 */
278
	public function response() : \Psr\Http\Message\ResponseInterface
279
	{
280
		return $this->view()->response();
281
	}
282
283
284
	/**
285
	 * Adds the decorators to the client object
286
	 *
287
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
288
	 * @param array $decorators List of decorator name that should be wrapped around the client
289
	 * @param string $classprefix Decorator class prefix, e.g. "\Aimeos\Admin\JQAdm\Catalog\Decorator\"
290
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
291
	 */
292
	protected function addDecorators( \Aimeos\Admin\JQAdm\Iface $client, array $decorators, string $classprefix ) : \Aimeos\Admin\JQAdm\Iface
293
	{
294
		foreach( $decorators as $name )
295
		{
296
			$classname = $classprefix . $name;
297
298
			if( ctype_alnum( $name ) === false )
299
			{
300
				$msg = $this->context->translate( 'admin', 'Invalid class name "%1$s"' );
301
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
302
			}
303
304
			if( class_exists( $classname ) === false )
305
			{
306
				$msg = $this->context->translate( 'admin', 'Class "%1$s" not found' );
307
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
308
			}
309
310
			$client = new $classname( $client, $this->context );
311
312
			\Aimeos\MW\Common\Base::checkClass( '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\Iface', $client );
313
		}
314
315
		return $client;
316
	}
317
318
319
	/**
320
	 * Adds the decorators to the client object
321
	 *
322
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
323
	 * @param string $path Admin string in lower case, e.g. "catalog/detail/basic"
324
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
325
	 */
326
	protected function addClientDecorators( \Aimeos\Admin\JQAdm\Iface $client, string $path ) : \Aimeos\Admin\JQAdm\Iface
327
	{
328
		if( !is_string( $path ) || $path === '' )
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
329
		{
330
			$msg = $this->context->translate( 'admin', 'Invalid domain "%1$s"' );
331
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $path ) );
332
		}
333
334
		$localClass = str_replace( '/', '\\', ucwords( $path, '/' ) );
335
		$config = $this->context->config();
336
337
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\';
338
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/global', [] );
339
		$client = $this->addDecorators( $client, $decorators, $classprefix );
340
341
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\' . $localClass . '\\Decorator\\';
342
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/local', [] );
343
		$client = $this->addDecorators( $client, $decorators, $classprefix );
344
345
		return $client;
346
	}
347
348
349
	/**
350
	 * Returns the sub-client given by its name.
351
	 *
352
	 * @param string $path Name of the sub-part in lower case (can contain a path like catalog/filter/tree)
353
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
354
	 * @return \Aimeos\Admin\JQAdm\Iface Sub-part object
355
	 */
356
	protected function createSubClient( string $path, string $name = null ) : \Aimeos\Admin\JQAdm\Iface
357
	{
358
		$path = strtolower( $path );
359
360
		if( $name === null ) {
361
			$name = $this->context->config()->get( 'admin/jqadm/' . $path . '/name', 'Standard' );
362
		}
363
364
		if( empty( $name ) || ctype_alnum( $name ) === false )
365
		{
366
			$msg = $this->context->translate( 'admin', 'Invalid characters in client name "%1$s"' );
367
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $name ) );
368
		}
369
370
		$subnames = str_replace( '/', '\\', ucwords( $path, '/' ) );
371
		$classname = '\\Aimeos\\Admin\\JQAdm\\' . $subnames . '\\' . $name;
372
373
		if( class_exists( $classname ) === false )
374
		{
375
			$msg = $this->context->translate( 'admin', 'Class "%1$s" not available' );
376
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
377
		}
378
379
		$object = new $classname( $this->context );
380
		$object = \Aimeos\MW\Common\Base::checkClass( '\\Aimeos\\Admin\\JQAdm\\Iface', $object );
381
		$object = $this->addClientDecorators( $object, $path );
382
383
		return $object->setObject( $object )->setAimeos( $this->aimeos )->setView( $this->view );
0 ignored issues
show
Bug introduced by
The method setObject() does not exist on Aimeos\Admin\JQAdm\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Admin\JQAdm\Common\Admin\Factory\Iface or Aimeos\Admin\JQAdm\Common\Decorator\Iface. 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

383
		return $object->/** @scrutinizer ignore-call */ setObject( $object )->setAimeos( $this->aimeos )->setView( $this->view );
Loading history...
384
	}
385
386
387
	/**
388
	 * Returns the value for the given key in the array
389
	 *
390
	 * @param array $values Multi-dimensional associative list of key/value pairs
391
	 * @param string $key Parameter key like "name" or "list/test" for associative arrays
392
	 * @param mixed $default Returned value if no one for key is available
393
	 * @return mixed Value from the array or default value if not present in array
394
	 */
395
	protected function val( array $values, $key, $default = null )
396
	{
397
		foreach( explode( '/', trim( $key, '/' ) ) as $part )
398
		{
399
			if( is_array( $values ) && isset( $values[$part] ) ) {
400
				$values = $values[$part];
401
			} else {
402
				return $default;
403
			}
404
		}
405
406
		return $values;
407
	}
408
409
410
	/**
411
	 * Returns the known client parameters and their values
412
	 *
413
	 * @param array $names List of parameter names
414
	 * @return array Associative list of parameters names as key and their values
415
	 */
416
	protected function getClientParams( $names = ['id', 'resource', 'site', 'locale'] ) : array
417
	{
418
		$list = [];
419
420
		foreach( $names as $name )
421
		{
422
			if( ( $val = $this->view->param( $name ) ) !== null && !is_array( $val ) ) {
423
				$list[$name] = $val;
424
			}
425
		}
426
427
		return $list;
428
	}
429
430
431
	/**
432
	 * Returns the context object.
433
	 *
434
	 * @return \Aimeos\MShop\ContextIface Context object
435
	 */
436
	protected function context() : \Aimeos\MShop\ContextIface
437
	{
438
		return $this->context;
439
	}
440
441
442
	/**
443
	 * Returns the available class names without namespace that are stored in the given path
444
	 *
445
	 * @param string $relpath Path relative to the include paths
446
	 * @param string[] $excludes List of file names to execlude
447
	 * @return string[] List of available class names
448
	 */
449
	protected function getClassNames( string $relpath, array $excludes = ['Base.php', 'Iface.php', 'Example.php', 'None.php'] ) : array
450
	{
451
		$list = [];
452
453
		foreach( $this->getAimeos()->getIncludePaths() as $path )
454
		{
455
			$path .= DIRECTORY_SEPARATOR . $relpath;
456
457
			if( is_dir( $path ) )
458
			{
459
				foreach( new \DirectoryIterator( $path ) as $entry )
460
				{
461
					if( $entry->isFile() && !in_array( $entry->getFileName(), $excludes ) ) {
462
						$list[] = pathinfo( $entry->getFileName(), PATHINFO_FILENAME );
463
					}
464
				}
465
			}
466
		}
467
468
		sort( $list );
469
		return $list;
470
	}
471
472
473
	/**
474
	 * Returns the array of criteria conditions based on the given parameters
475
	 *
476
	 * @param array $params List of criteria data with condition, sorting and paging
477
	 * @return array Multi-dimensional associative list of criteria conditions
478
	 */
479
	protected function getCriteriaConditions( array $params ) : array
480
	{
481
		$expr = [];
482
483
		if( isset( $params['key'] ) )
484
		{
485
			foreach( (array) $params['key'] as $idx => $key )
486
			{
487
				if( $key != '' && isset( $params['op'][$idx] ) && $params['op'][$idx] != ''
488
					&& isset( $params['val'][$idx] ) && $params['val'][$idx] != ''
489
				) {
490
					$expr[] = [$params['op'][$idx] => [$key => $params['val'][$idx]]];
491
				}
492
			}
493
494
			if( !empty( $expr ) ) {
495
				$expr = ['&&' => $expr];
496
			}
497
		}
498
499
		return $expr;
500
	}
501
502
503
	/**
504
	 * Returns the outer decoratorator of the object
505
	 *
506
	 * @return \Aimeos\Admin\JQAdm\Iface Outmost object
507
	 */
508
	protected function object() : Iface
509
	{
510
		if( isset( $this->object ) ) {
511
			return $this->object;
512
		}
513
514
		return $this;
515
	}
516
517
518
	/**
519
	 * Returns the sub-client given by its name.
520
	 *
521
	 * @param string $type Name of the client type
522
	 * @param string|null $name Name of the sub-client (Default if null)
523
	 * @return \Aimeos\Admin\JQAdm\Iface Sub-client object
524
	 */
525
	public function getSubClient( string $type, string $name = null ) : \Aimeos\Admin\JQAdm\Iface
526
	{
527
		$msg = $this->context()->translate( 'admin', 'Not implemented' );
528
		throw new \Aimeos\Admin\JQAdm\Exception( $msg );
529
	}
530
531
532
	/**
533
	 * Returns the configured sub-clients or the ones named in the default parameter if none are configured.
534
	 *
535
	 * @return array List of sub-clients implementing \Aimeos\Admin\JQAdm\Iface ordered in the same way as the names
536
	 */
537
	protected function getSubClients() : array
538
	{
539
		if( !isset( $this->subclients ) )
540
		{
541
			$this->subclients = [];
542
543
			foreach( $this->getSubClientNames() as $name ) {
544
				$this->subclients[] = $this->getSubClient( $name );
545
			}
546
		}
547
548
		return $this->subclients;
549
	}
550
551
552
	/**
553
	 * Returns the list of sub-client names configured for the client.
554
	 *
555
	 * @return array List of admin client names
556
	 */
557
	protected function getSubClientNames() : array
558
	{
559
		return [];
560
	}
561
562
563
	/**
564
	 * Initializes the criteria object based on the given parameter
565
	 *
566
	 * @param \Aimeos\Base\Criteria\Iface $criteria Criteria object
567
	 * @param array $params List of criteria data with condition, sorting and paging
568
	 * @return \Aimeos\Base\Criteria\Iface Initialized criteria object
569
	 */
570
	protected function initCriteria( \Aimeos\Base\Criteria\Iface $criteria, array $params ) : \Aimeos\Base\Criteria\Iface
571
	{
572
		if( isset( $params['sort'] ) && !empty( $params['sort'] ) ) {
573
			$criteria->order( $params['sort'] );
574
		}
575
576
		return $criteria->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 )
577
			->add( $criteria->parse( $this->getCriteriaConditions( $params['filter'] ?? [] ) ) );
578
	}
579
580
581
	/**
582
	 * Flattens the nested configuration array
583
	 *
584
	 * @param array $config Multi-dimensional list of key/value pairs
585
	 * @param string $path Path of keys separated by slashes (/) to add new values for
586
	 * @return array List of arrays with "key" and "val" keys
587
	 */
588
	protected function flatten( array $config, string $path = '' ) : array
589
	{
590
		$list = [];
591
592
		foreach( $config as $key => $val )
593
		{
594
			if( is_array( $val ) ) {
595
				$list = array_merge( $list, $this->flatten( $val, $path . '/' . $key ) );
596
			} else {
597
				$list[] = ['key' => trim( $path . '/' . $key, '/' ), 'val' => $val];
598
			}
599
		}
600
601
		return $list;
602
	}
603
604
605
	/**
606
	 * Writes the exception details to the log
607
	 *
608
	 * @param \Exception $e Exception object
609
	 * @return \Aimeos\Admin\JQAdm\Iface Reference to this object for fluent calls
610
	 */
611
	protected function log( \Exception $e ) : Iface
612
	{
613
		$msg = $e->getMessage() . PHP_EOL;
614
615
		if( $e instanceof \Aimeos\Admin\JQAdm\Exception ) {
616
			$msg .= print_r( $e->getDetails(), true ) . PHP_EOL;
0 ignored issues
show
Bug introduced by
Are you sure print_r($e->getDetails(), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

616
			$msg .= /** @scrutinizer ignore-type */ print_r( $e->getDetails(), true ) . PHP_EOL;
Loading history...
617
		}
618
619
		$this->context->logger()->error( $msg . $e->getTraceAsString(), 'admin/jqadm' );
620
621
		return $this;
622
	}
623
624
625
	/**
626
	 * Returns a map of code/item pairs
627
	 *
628
	 * @param \Aimeos\MShop\Common\Item\Type\Iface[] $items Associative list of type items
629
	 * @return \Aimeos\MShop\Common\Item\Type\Iface[] Associative list of codes as keys and items as values
630
	 * @deprecated 2021.01
631
	 */
632
	protected function map( \Aimeos\Map $items ) : array
633
	{
634
		$list = [];
635
636
		foreach( $items as $item ) {
637
			$list[$item->getCode()] = $item;
638
		}
639
640
		return $list;
641
	}
642
643
644
	/**
645
	 * Adds a redirect to the response for the next action
646
	 *
647
	 * @param string $resource Resource name
648
	 * @param string|null $action Next action
649
	 * @param string|null $id ID of the next resource item
650
	 * @param string|null $act Current action name
651
	 * @return string|null Returns value for the actions
652
	 */
653
	protected function redirect( string $resource, ?string $action, string $id = null,
654
		string $method = null ) : ?string
655
	{
656
		$params = $this->getClientParams();
657
		$context = $this->context();
658
		$view = $this->view();
659
660
		$params['resource'] = $resource;
661
		unset( $params['id'] );
662
663
		switch( $action )
664
		{
665
			case 'search':
666
				$target = $view->config( 'admin/jqadm/url/search/target' );
667
				$cntl = $view->config( 'admin/jqadm/url/search/controller', 'Jqadm' );
668
				$action = $view->config( 'admin/jqadm/url/search/action', 'search' );
669
				$conf = $view->config( 'admin/jqadm/url/search/config', [] );
670
				$url = $view->url( $target, $cntl, $action, $params, [], $conf );
671
				break;
672
			case 'create':
673
				$params['parentid'] = $id;
674
				$target = $view->config( 'admin/jqadm/url/create/target' );
675
				$cntl = $view->config( 'admin/jqadm/url/create/controller', 'Jqadm' );
676
				$action = $view->config( 'admin/jqadm/url/create/action', 'create' );
677
				$conf = $view->config( 'admin/jqadm/url/create/config', [] );
678
				$url = $view->url( $target, $cntl, $action, $params, [], $conf );
679
				break;
680
			case 'copy':
681
				$target = $view->config( 'admin/jqadm/url/copy/target' );
682
				$cntl = $view->config( 'admin/jqadm/url/copy/controller', 'Jqadm' );
683
				$action = $view->config( 'admin/jqadm/url/copy/action', 'copy' );
684
				$conf = $view->config( 'admin/jqadm/url/copy/config', [] );
685
				$url = $view->url( $target, $cntl, $action, ['id' => $id] + $params, [], $conf );
686
				break;
687
			default:
688
				$target = $view->config( 'admin/jqadm/url/get/target' );
689
				$cntl = $view->config( 'admin/jqadm/url/get/controller', 'Jqadm' );
690
				$action = $view->config( 'admin/jqadm/url/get/action', 'get' );
691
				$conf = $view->config( 'admin/jqadm/url/get/config', [] );
692
				$url = $view->url( $target, $cntl, $action, ['id' => $id] + $params, [], $conf );
693
		}
694
695
		switch( $method )
696
		{
697
			case 'save':
698
				$context->session()->set( 'info', [$context->translate( 'admin', 'Item saved successfully' )] ); break;
699
			case 'delete':
700
				$context->session()->set( 'info', [$context->translate( 'admin', 'Item deleted successfully' )] ); break;
701
		}
702
703
		$view->response()->withStatus( 302 );
704
		$view->response()->withHeader( 'Location', $url );
705
		$view->response()->withHeader( 'Cache-Control', 'no-store' );
706
707
		return null;
708
	}
709
710
711
	/**
712
	 * Writes the exception details to the log
713
	 *
714
	 * @param \Exception $e Exception object
715
	 * @param string $method Method it's called from
716
	 * @return \Aimeos\Admin\JQAdm\Iface Reference to this object for fluent calls
717
	 */
718
	protected function report( \Exception $e, string $method ) : Iface
719
	{
720
		$view = $this->view;
721
		$i18n = $this->context->i18n();
722
723
		if( $e instanceof \Aimeos\Admin\JQAdm\Exception )
724
		{
725
			$view->errors = array_merge( $view->get( 'errors', [] ), [$e->getMessage()] );
726
			return $this->log( $e );
727
		}
728
		elseif( $e instanceof \Aimeos\MShop\Exception )
729
		{
730
			$view->errors = array_merge( $view->get( 'errors', [] ), [$i18n->dt( 'mshop', $e->getMessage() )] );
731
			return $this->log( $e );
732
		}
733
734
		switch( $method )
735
		{
736
			case 'save': $msg = $i18n->dt( 'admin', 'Error saving data' ); break;
737
			case 'delete': $msg = $i18n->dt( 'admin', 'Error deleting data' ); break;
738
			default: $msg = $i18n->dt( 'admin', 'Error retrieving data' ); break;
739
		}
740
741
		$view->errors = array_merge( $view->get( 'errors', [] ), [$msg] );
742
743
		return $this->log( $e );
744
	}
745
746
747
	/**
748
	 * Checks and returns the request parameter for the given name
749
	 *
750
	 * @param string $name Name of the request parameter, can be a path like 'page/limit'
751
	 * @return mixed Parameter value
752
	 * @throws \Aimeos\Admin\JQAdm\Exception If the parameter is missing
753
	 */
754
	protected function require( string $name )
755
	{
756
		if( ( $value = $this->view()->param( $name ) ) !== null ) {
757
			return $value;
758
		}
759
760
		$msg = $this->context->translate( 'admin', 'Required parameter "%1$s" is missing' );
761
		throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $name ) );
762
	}
763
764
765
	/**
766
	 * Stores and returns the parameters used for searching items
767
	 *
768
	 * @param array $params GET/POST parameter set
769
	 * @param string $name Name of the panel/subpanel
770
	 * @return array Associative list of parameters for searching items
771
	 */
772
	protected function storeFilter( array $params, string $name ) : array
773
	{
774
		$key = 'aimeos/admin/jqadm/' . $name;
775
		$session = $this->context()->session();
776
777
		foreach( ['fields', 'filter', 'page', 'sort'] as $part )
778
		{
779
			if( isset( $params[$part] ) ) {
780
				$session->set( $key . '/' . $part, $params[$part] );
781
			}
782
		}
783
784
		return [
785
			'fields' => $session->get( $key . '/fields' ),
786
			'filter' => $session->get( $key . '/filter' ),
787
			'page' => $session->get( $key . '/page' ),
788
			'sort' => $session->get( $key . '/sort' ),
789
		];
790
	}
791
792
793
	/**
794
	 * Throws an exception with given details
795
	 *
796
	 * @param array $errors List of key/message pairs of errors
797
	 * @throws \Aimeos\Admin\JQAdm\Exception Exception with error details
798
	 */
799
	protected function notify( array $errors ) : Iface
800
	{
801
		$list = [];
802
		$i18n = $this->context->i18n();
803
804
		foreach( $errors as $key => $error )
805
		{
806
			if( $error ) {
807
				$list[] = $key . ': ' . $i18n->dt( 'mshop', $error );
808
			}
809
		}
810
811
		if( !empty( $list ) ) {
812
			throw new \Aimeos\Admin\JQAdm\Exception( join( "\n", $list ) );
813
		}
814
815
		return $this;
816
	}
817
}
818