Base   F
last analyzed

Complexity

Total Complexity 104

Size/Duplication

Total Lines 804
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 104
eloc 227
c 1
b 0
f 0
dl 0
loc 804
rs 2

39 Methods

Rating   Name   Duplication   Size   Complexity  
A setObject() 0 4 1
A __construct() 0 3 1
A data() 0 3 1
A view() 0 7 2
A setAimeos() 0 4 1
A getAimeos() 0 7 2
A setView() 0 4 1
A get() 0 12 2
A delete() 0 9 2
A export() 0 9 2
A create() 0 12 2
A copy() 0 12 2
A batch() 0 7 2
A createSubClient() 0 17 4
A addClientDecorators() 0 20 3
A import() 0 9 2
A context() 0 3 1
A getSubClients() 0 12 3
A report() 0 26 5
A storeFilter() 0 17 3
A require() 0 8 2
A flatten() 0 14 3
A initCriteria() 0 8 3
A search() 0 9 2
A log() 0 11 2
A response() 0 3 1
A addDecorators() 0 18 3
A getClientParams() 0 12 4
A object() 0 7 2
A notify() 0 17 4
A save() 0 9 2
A val() 0 12 4
B getCriteriaConditions() 0 21 9
A getSubClientNames() 0 3 1
A getSubClient() 0 4 1
A getClassNames() 0 21 6
B redirect() 0 37 7
A batchBase() 0 26 5
A getDomains() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Base often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Base, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2025
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 \Aimeos\MShop\ContextIface $context;
29
	private ?\Aimeos\Admin\JQAdm\Iface $object = null;
30
	private ?\Aimeos\Base\View\Iface $view = null;
31
	private ?\Aimeos\Bootstrap $aimeos = null;
32
	private ?array $subclients = null;
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
	 * Batch update of a resource
129
	 *
130
	 * @return string|null Output to display
131
	 */
132
	public function batch() : ?string
133
	{
134
		foreach( $this->getSubClients() as $client ) {
135
			$client->batch();
136
		}
137
138
		return null;
139
	}
140
141
142
	/**
143
	 * Copies a resource
144
	 *
145
	 * @return string|null Output to display
146
	 */
147
	public function copy() : ?string
148
	{
149
		$body = null;
150
		$view = $this->view();
151
152
		foreach( $this->getSubClients() as $idx => $client )
153
		{
154
			$view->tabindex = ++$idx + 1;
155
			$body .= $client->copy();
156
		}
157
158
		return $body;
159
	}
160
161
162
	/**
163
	 * Creates a new resource
164
	 *
165
	 * @return string|null Output to display
166
	 */
167
	public function create() : ?string
168
	{
169
		$body = null;
170
		$view = $this->view();
171
172
		foreach( $this->getSubClients() as $idx => $client )
173
		{
174
			$view->tabindex = ++$idx + 1;
175
			$body .= $client->create();
176
		}
177
178
		return $body;
179
	}
180
181
182
	/**
183
	 * Deletes a resource
184
	 *
185
	 * @return string|null Output to display
186
	 */
187
	public function delete() : ?string
188
	{
189
		$body = null;
190
191
		foreach( $this->getSubClients() as $client ) {
192
			$body .= $client->delete();
193
		}
194
195
		return $body;
196
	}
197
198
199
	/**
200
	 * Exports a resource
201
	 *
202
	 * @return string|null Output to display
203
	 */
204
	public function export() : ?string
205
	{
206
		$body = null;
207
208
		foreach( $this->getSubClients() as $client ) {
209
			$body .= $client->export();
210
		}
211
212
		return $body;
213
	}
214
215
216
	/**
217
	 * Returns a resource
218
	 *
219
	 * @return string|null Output to display
220
	 */
221
	public function get() : ?string
222
	{
223
		$body = null;
224
		$view = $this->view();
225
226
		foreach( $this->getSubClients() as $idx => $client )
227
		{
228
			$view->tabindex = ++$idx + 1;
229
			$body .= $client->get();
230
		}
231
232
		return $body;
233
	}
234
235
236
	/**
237
	 * Imports a resource
238
	 *
239
	 * @return string|null Output to display
240
	 */
241
	public function import() : ?string
242
	{
243
		$body = null;
244
245
		foreach( $this->getSubClients() as $client ) {
246
			$body .= $client->import();
247
		}
248
249
		return $body;
250
	}
251
252
253
	/**
254
	 * Saves the data
255
	 *
256
	 * @return string|null Output to display
257
	 */
258
	public function save() : ?string
259
	{
260
		$body = null;
261
262
		foreach( $this->getSubClients() as $client ) {
263
			$body .= $client->save();
264
		}
265
266
		return $body;
267
	}
268
269
270
	/**
271
	 * Returns a list of resource according to the conditions
272
	 *
273
	 * @return string|null Output to display
274
	 */
275
	public function search() : ?string
276
	{
277
		$body = null;
278
279
		foreach( $this->getSubClients() as $client ) {
280
			$body .= $client->search();
281
		}
282
283
		return $body;
284
	}
285
286
287
	/**
288
	 * Returns the PSR-7 response object for the request
289
	 *
290
	 * @return \Psr\Http\Message\ResponseInterface Response object
291
	 */
292
	public function response() : \Psr\Http\Message\ResponseInterface
293
	{
294
		return $this->view()->response();
295
	}
296
297
298
	/**
299
	 * Adds the decorators to the client object
300
	 *
301
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
302
	 * @param array $decorators List of decorator name that should be wrapped around the client
303
	 * @param string $classprefix Decorator class prefix, e.g. "\Aimeos\Admin\JQAdm\Catalog\Decorator\"
304
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
305
	 * @throws \LogicException If class can't be instantiated
306
	 */
307
	protected function addDecorators( \Aimeos\Admin\JQAdm\Iface $client, array $decorators, string $classprefix ) : \Aimeos\Admin\JQAdm\Iface
308
	{
309
		$interface = \Aimeos\Admin\JQAdm\Common\Decorator\Iface::class;
310
311
		foreach( $decorators as $name )
312
		{
313
			$classname = $classprefix . $name;
314
315
			if( ctype_alnum( $name ) === false )
316
			{
317
				$msg = $this->context->translate( 'admin', 'Invalid class name "%1$s"' );
318
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
319
			}
320
321
			$client = \Aimeos\Utils::create( $classname, [$client, $this->context], $interface );
322
		}
323
324
		return $client;
325
	}
326
327
328
	/**
329
	 * Adds the decorators to the client object
330
	 *
331
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
332
	 * @param string $path Admin string in lower case, e.g. "catalog/detail/basic"
333
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
334
	 */
335
	protected function addClientDecorators( \Aimeos\Admin\JQAdm\Iface $client, string $path ) : \Aimeos\Admin\JQAdm\Iface
336
	{
337
		if( !is_string( $path ) || $path === '' )
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
338
		{
339
			$msg = $this->context->translate( 'admin', 'Invalid domain "%1$s"' );
340
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $path ) );
341
		}
342
343
		$localClass = str_replace( '/', '\\', ucwords( $path, '/' ) );
344
		$config = $this->context->config();
345
346
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\';
347
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/global', [] );
348
		$client = $this->addDecorators( $client, $decorators, $classprefix );
349
350
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\' . $localClass . '\\Decorator\\';
351
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/local', [] );
352
		$client = $this->addDecorators( $client, $decorators, $classprefix );
353
354
		return $client;
355
	}
356
357
358
	/**
359
	 * Modifiy several items at once
360
	 *
361
	 * @param string $domain Data domain of the items
362
	 * @param string|null $resource Resource name or null for domain name
363
	 * @return string|null Output to display
364
	 */
365
	protected function batchBase( string $domain, ?string $resource = null ) : ?string
366
	{
367
		$view = $this->view();
368
369
		if( !empty( $ids = $view->param( 'id' ) ) )
370
		{
371
			$manager = \Aimeos\MShop::create( $this->context(), $domain );
372
			$filter = $manager->filter()->add( [str_replace( '/', '.', $domain ) . '.id' => $ids] )->slice( 0, count( $ids ) );
373
			$items = $manager->search( $filter, $this->getDomains() );
374
375
			$data = $view->param( 'item', [] );
376
377
			foreach( $items as $item ) {
378
				$temp = $data; $item->fromArray( $temp, true );
379
			}
380
381
			$view->items = $items;
382
383
			foreach( $this->getSubClients() as $client ) {
384
				$client->batch();
385
			}
386
387
			$manager->save( $items );
388
		}
389
390
		return $this->redirect( $resource ?: $domain, 'search', null, 'save' );
391
	}
392
393
394
	/**
395
	 * Returns the sub-client given by its name.
396
	 *
397
	 * @param string $path Name of the sub-part in lower case (can contain a path like catalog/filter/tree)
398
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
399
	 * @return \Aimeos\Admin\JQAdm\Iface Sub-part object
400
	 * @throws \LogicException If class can't be instantiated
401
	 */
402
	protected function createSubClient( string $path, ?string $name = null ) : \Aimeos\Admin\JQAdm\Iface
403
	{
404
		$path = strtolower( $path );
405
		$name = $name ?: $this->context->config()->get( 'admin/jqadm/' . $path . '/name', 'Standard' );
406
407
		if( empty( $name ) || ctype_alnum( $name ) === false ) {
408
			throw new \LogicException( sprintf( 'Invalid characters in client name "%1$s"', $name ), 400 );
409
		}
410
411
		$subnames = str_replace( '/', '\\', ucwords( $path, '/' ) );
412
		$classname = '\\Aimeos\\Admin\\JQAdm\\' . $subnames . '\\' . $name;
413
		$interface = \Aimeos\Admin\JQAdm\Iface::class;
414
415
		$object = \Aimeos\Utils::create( $classname, [$this->context], $interface );
416
		$object = $this->addClientDecorators( $object, $path );
417
418
		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

418
		return $object->/** @scrutinizer ignore-call */ setObject( $object )->setAimeos( $this->aimeos )->setView( $this->view );
Loading history...
419
	}
420
421
422
	/**
423
	 * Returns the value for the given key in the array
424
	 *
425
	 * @param array $values Multi-dimensional associative list of key/value pairs
426
	 * @param string $key Parameter key like "name" or "list/test" for associative arrays
427
	 * @param mixed $default Returned value if no one for key is available
428
	 * @return mixed Value from the array or default value if not present in array
429
	 */
430
	protected function val( array $values, $key, $default = null )
431
	{
432
		foreach( explode( '/', trim( $key, '/' ) ) as $part )
433
		{
434
			if( is_array( $values ) && isset( $values[$part] ) ) {
435
				$values = $values[$part];
436
			} else {
437
				return $default;
438
			}
439
		}
440
441
		return $values;
442
	}
443
444
445
	/**
446
	 * Returns the known client parameters and their values
447
	 *
448
	 * @param array $names List of parameter names
449
	 * @return array Associative list of parameters names as key and their values
450
	 */
451
	protected function getClientParams( $names = ['id', 'resource', 'site', 'locale'] ) : array
452
	{
453
		$list = [];
454
455
		foreach( $names as $name )
456
		{
457
			if( ( $val = $this->view->param( $name ) ) !== null && !is_array( $val ) ) {
0 ignored issues
show
Bug introduced by
The method param() does not exist on null. ( Ignorable by Annotation )

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

457
			if( ( $val = $this->view->/** @scrutinizer ignore-call */ param( $name ) ) !== null && !is_array( $val ) ) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
458
				$list[$name] = $val;
459
			}
460
		}
461
462
		return $list;
463
	}
464
465
466
	/**
467
	 * Returns the domain names whose items should be fetched too
468
	 *
469
	 * @return string[] List of domain names
470
	 */
471
	protected function getDomains() : array
472
	{
473
		return [];
474
	}
475
476
477
	/**
478
	 * Returns the context object.
479
	 *
480
	 * @return \Aimeos\MShop\ContextIface Context object
481
	 */
482
	protected function context() : \Aimeos\MShop\ContextIface
483
	{
484
		return $this->context;
485
	}
486
487
488
	/**
489
	 * Returns the available class names without namespace that are stored in the given path
490
	 *
491
	 * @param string $relpath Path relative to the include paths
492
	 * @param string[] $excludes List of file names to execlude
493
	 * @return string[] List of available class names
494
	 */
495
	protected function getClassNames( string $relpath, array $excludes = ['Base.php', 'Iface.php', 'Example.php', 'None.php'] ) : array
496
	{
497
		$list = [];
498
499
		foreach( $this->getAimeos()->getIncludePaths() as $path )
500
		{
501
			$path .= DIRECTORY_SEPARATOR . $relpath;
502
503
			if( is_dir( $path ) )
504
			{
505
				foreach( new \DirectoryIterator( $path ) as $entry )
506
				{
507
					if( $entry->isFile() && !in_array( $entry->getFileName(), $excludes ) ) {
508
						$list[] = pathinfo( $entry->getFileName(), PATHINFO_FILENAME );
509
					}
510
				}
511
			}
512
		}
513
514
		sort( $list );
515
		return $list;
516
	}
517
518
519
	/**
520
	 * Returns the array of criteria conditions based on the given parameters
521
	 *
522
	 * @param array $params List of criteria data with condition, sorting and paging
523
	 * @return array Multi-dimensional associative list of criteria conditions
524
	 */
525
	protected function getCriteriaConditions( array $params ) : array
526
	{
527
		$expr = [];
528
529
		if( isset( $params['key'] ) )
530
		{
531
			foreach( (array) $params['key'] as $idx => $key )
532
			{
533
				if( $key != '' && isset( $params['op'][$idx] ) && $params['op'][$idx] != ''
534
					&& isset( $params['val'][$idx] ) && $params['val'][$idx] != ''
535
				) {
536
					$expr[] = [$params['op'][$idx] => [$key => $params['val'][$idx]]];
537
				}
538
			}
539
540
			if( !empty( $expr ) ) {
541
				$expr = ['&&' => $expr];
542
			}
543
		}
544
545
		return $expr;
546
	}
547
548
549
	/**
550
	 * Returns the outer decoratorator of the object
551
	 *
552
	 * @return \Aimeos\Admin\JQAdm\Iface Outmost object
553
	 */
554
	protected function object() : Iface
555
	{
556
		if( isset( $this->object ) ) {
557
			return $this->object;
558
		}
559
560
		return $this;
561
	}
562
563
564
	/**
565
	 * Returns the sub-client given by its name.
566
	 *
567
	 * @param string $type Name of the client type
568
	 * @param string|null $name Name of the sub-client (Default if null)
569
	 * @return \Aimeos\Admin\JQAdm\Iface Sub-client object
570
	 */
571
	public function getSubClient( string $type, ?string $name = null ) : \Aimeos\Admin\JQAdm\Iface
572
	{
573
		$msg = $this->context()->translate( 'admin', 'Not implemented' );
574
		throw new \Aimeos\Admin\JQAdm\Exception( $msg );
575
	}
576
577
578
	/**
579
	 * Returns the configured sub-clients or the ones named in the default parameter if none are configured.
580
	 *
581
	 * @return array List of sub-clients implementing \Aimeos\Admin\JQAdm\Iface ordered in the same way as the names
582
	 */
583
	protected function getSubClients() : array
584
	{
585
		if( !isset( $this->subclients ) )
586
		{
587
			$this->subclients = [];
588
589
			foreach( $this->getSubClientNames() as $name ) {
590
				$this->subclients[] = $this->getSubClient( $name );
591
			}
592
		}
593
594
		return $this->subclients;
595
	}
596
597
598
	/**
599
	 * Returns the list of sub-client names configured for the client.
600
	 *
601
	 * @return array List of admin client names
602
	 */
603
	protected function getSubClientNames() : array
604
	{
605
		return [];
606
	}
607
608
609
	/**
610
	 * Initializes the criteria object based on the given parameter
611
	 *
612
	 * @param \Aimeos\Base\Criteria\Iface $criteria Criteria object
613
	 * @param array $params List of criteria data with condition, sorting and paging
614
	 * @return \Aimeos\Base\Criteria\Iface Initialized criteria object
615
	 */
616
	protected function initCriteria( \Aimeos\Base\Criteria\Iface $criteria, array $params ) : \Aimeos\Base\Criteria\Iface
617
	{
618
		if( isset( $params['sort'] ) && !empty( $params['sort'] ) ) {
619
			$criteria->order( $params['sort'] );
620
		}
621
622
		return $criteria->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 )
623
			->add( $criteria->parse( $this->getCriteriaConditions( $params['filter'] ?? [] ) ) );
624
	}
625
626
627
	/**
628
	 * Flattens the nested configuration array
629
	 *
630
	 * @param array $config Multi-dimensional list of key/value pairs
631
	 * @param string $path Path of keys separated by slashes (/) to add new values for
632
	 * @return array List of arrays with "key" and "val" keys
633
	 */
634
	protected function flatten( array $config, string $path = '' ) : array
635
	{
636
		$list = [];
637
638
		foreach( $config as $key => $val )
639
		{
640
			if( is_array( $val ) ) {
641
				$list = array_merge( $list, $this->flatten( $val, $path . '/' . $key ) );
642
			} else {
643
				$list[] = ['key' => trim( $path . '/' . $key, '/' ), 'val' => $val];
644
			}
645
		}
646
647
		return $list;
648
	}
649
650
651
	/**
652
	 * Writes the exception details to the log
653
	 *
654
	 * @param \Exception $e Exception object
655
	 * @return \Aimeos\Admin\JQAdm\Iface Reference to this object for fluent calls
656
	 */
657
	protected function log( \Exception $e ) : Iface
658
	{
659
		$msg = $e->getMessage() . PHP_EOL;
660
661
		if( $e instanceof \Aimeos\Admin\JQAdm\Exception ) {
662
			$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

662
			$msg .= /** @scrutinizer ignore-type */ print_r( $e->getDetails(), true ) . PHP_EOL;
Loading history...
663
		}
664
665
		$this->context->logger()->error( $msg . $e->getTraceAsString(), 'admin/jqadm' );
666
667
		return $this;
668
	}
669
670
671
	/**
672
	 * Adds a redirect to the response for the next action
673
	 *
674
	 * @param string $resource Resource name
675
	 * @param string|null $action Next action
676
	 * @param string|null $id ID of the next resource item
677
	 * @param string|null $method Current method name
678
	 * @param array $params URL parameters to use
679
	 * @return string|null Returns value for the actions
680
	 */
681
	protected function redirect( string $resource, ?string $action, ?string $id = null,
682
		?string $method = null, array $params = [] ) : ?string
683
	{
684
		$params += $this->getClientParams();
685
		$context = $this->context();
686
		$view = $this->view();
687
688
		$params['resource'] = $resource;
689
		unset( $params['id'] );
690
691
		switch( $action )
692
		{
693
			case 'search':
694
				$url = $view->link( 'admin/jqadm/url/search', $params ); break;
695
			case 'create':
696
				$url = $view->link( 'admin/jqadm/url/create', ['parentid' => $id] + $params ); break;
697
			case 'copy':
698
				$url = $view->link( 'admin/jqadm/url/copy', ['id' => $id] + $params ); break;
699
			default:
700
				$url = $view->link( 'admin/jqadm/url/get', ['id' => $id] + $params );
701
		}
702
703
		switch( $method )
704
		{
705
			case 'save':
706
				$context->session()->set( 'info', [$context->translate( 'admin', 'Entry saved successfully' )] ); break;
707
			case 'delete':
708
				$context->session()->set( 'info', [$context->translate( 'admin', 'Entry deleted successfully' )] ); break;
709
			case 'upload':
710
				$context->session()->set( 'info', [$context->translate( 'admin', 'File uploaded successfully' )] ); break;
711
		}
712
713
		$view->response()->withStatus( 302 );
714
		$view->response()->withHeader( 'Location', $url );
715
		$view->response()->withHeader( 'Cache-Control', 'no-store' );
716
717
		return null;
718
	}
719
720
721
	/**
722
	 * Writes the exception details to the log
723
	 *
724
	 * @param \Exception $e Exception object
725
	 * @param string $method Method it's called from
726
	 * @return \Aimeos\Admin\JQAdm\Iface Reference to this object for fluent calls
727
	 */
728
	protected function report( \Exception $e, string $method ) : Iface
729
	{
730
		$view = $this->view;
731
		$i18n = $this->context->i18n();
732
733
		if( $e instanceof \Aimeos\Admin\JQAdm\Exception )
734
		{
735
			$view->errors = array_merge( $view->get( 'errors', [] ), [$e->getMessage()] );
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

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

735
			$view->errors = array_merge( $view->/** @scrutinizer ignore-call */ get( 'errors', [] ), [$e->getMessage()] );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
736
			return $this->log( $e );
737
		}
738
		elseif( $e instanceof \Aimeos\MShop\Exception )
739
		{
740
			$view->errors = array_merge( $view->get( 'errors', [] ), [$i18n->dt( 'mshop', $e->getMessage() )] );
741
			return $this->log( $e );
742
		}
743
744
		switch( $method )
745
		{
746
			case 'save': $msg = $i18n->dt( 'admin', 'Error saving data' ); break;
747
			case 'delete': $msg = $i18n->dt( 'admin', 'Error deleting data' ); break;
748
			default: $msg = $i18n->dt( 'admin', 'Error retrieving data' ); break;
749
		}
750
751
		$view->errors = array_merge( $view->get( 'errors', [] ), [$msg] );
752
753
		return $this->log( $e );
754
	}
755
756
757
	/**
758
	 * Checks and returns the request parameter for the given name
759
	 *
760
	 * @param string $name Name of the request parameter, can be a path like 'page/limit'
761
	 * @return mixed Parameter value
762
	 * @throws \Aimeos\Admin\JQAdm\Exception If the parameter is missing
763
	 */
764
	protected function require( string $name )
765
	{
766
		if( ( $value = $this->view()->param( $name ) ) !== null ) {
767
			return $value;
768
		}
769
770
		$msg = $this->context->translate( 'admin', 'Required parameter "%1$s" is missing' );
771
		throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $name ) );
772
	}
773
774
775
	/**
776
	 * Stores and returns the parameters used for searching items
777
	 *
778
	 * @param array $params GET/POST parameter set
779
	 * @param string $name Name of the panel/subpanel
780
	 * @return array Associative list of parameters for searching items
781
	 */
782
	protected function storeFilter( array $params, string $name ) : array
783
	{
784
		$key = 'aimeos/admin/jqadm/' . $name;
785
		$session = $this->context()->session();
786
787
		foreach( ['fields', 'filter', 'page', 'sort'] as $part )
788
		{
789
			if( isset( $params[$part] ) ) {
790
				$session->set( $key . '/' . $part, $params[$part] );
791
			}
792
		}
793
794
		return [
795
			'fields' => $session->get( $key . '/fields' ),
796
			'filter' => $session->get( $key . '/filter' ),
797
			'page' => $session->get( $key . '/page' ),
798
			'sort' => $session->get( $key . '/sort' ),
799
		];
800
	}
801
802
803
	/**
804
	 * Throws an exception with given details
805
	 *
806
	 * @param array $errors List of key/message pairs of errors
807
	 * @throws \Aimeos\Admin\JQAdm\Exception Exception with error details
808
	 */
809
	protected function notify( array $errors ) : Iface
810
	{
811
		$list = [];
812
		$i18n = $this->context->i18n();
813
814
		foreach( $errors as $key => $error )
815
		{
816
			if( $error ) {
817
				$list[] = $key . ': ' . $i18n->dt( 'mshop', $error );
818
			}
819
		}
820
821
		if( !empty( $list ) ) {
822
			throw new \Aimeos\Admin\JQAdm\Exception( join( "\n", $list ) );
823
		}
824
825
		return $this;
826
	}
827
}
828