Passed
Push — master ( 0f1828...ed6c8e )
by Aimeos
04:20
created

Standard   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 754
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 2
Metric Value
eloc 145
c 7
b 0
f 2
dl 0
loc 754
rs 9.2
wmc 40

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubClient() 0 77 1
A getSubClientNames() 0 3 1
B header() 0 83 8
B body() 0 128 11
F data() 0 300 13
B init() 0 42 6

How to fix   Complexity   

Complex Class

Complex classes like Standard 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 Standard, 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 Metaways Infosystems GmbH, 2012
6
 * @copyright Aimeos (aimeos.org), 2015-2021
7
 * @package Client
8
 * @subpackage Html
9
 */
10
11
12
namespace Aimeos\Client\Html\Catalog\Lists;
13
14
15
/**
16
 * Default implementation of catalog list section HTML clients.
17
 *
18
 * @package Client
19
 * @subpackage Html
20
 */
21
class Standard
22
	extends \Aimeos\Client\Html\Catalog\Base
23
	implements \Aimeos\Client\Html\Common\Client\Factory\Iface
24
{
25
	/** client/html/catalog/lists/subparts
26
	 * List of HTML sub-clients rendered within the catalog list section
27
	 *
28
	 * The output of the frontend is composed of the code generated by the HTML
29
	 * clients. Each HTML client can consist of serveral (or none) sub-clients
30
	 * that are responsible for rendering certain sub-parts of the output. The
31
	 * sub-clients can contain HTML clients themselves and therefore a
32
	 * hierarchical tree of HTML clients is composed. Each HTML client creates
33
	 * the output that is placed inside the container of its parent.
34
	 *
35
	 * At first, always the HTML code generated by the parent is printed, then
36
	 * the HTML code of its sub-clients. The order of the HTML sub-clients
37
	 * determines the order of the output of these sub-clients inside the parent
38
	 * container. If the configured list of clients is
39
	 *
40
	 *  array( "subclient1", "subclient2" )
41
	 *
42
	 * you can easily change the order of the output by reordering the subparts:
43
	 *
44
	 *  client/html/<clients>/subparts = array( "subclient1", "subclient2" )
45
	 *
46
	 * You can also remove one or more parts if they shouldn't be rendered:
47
	 *
48
	 *  client/html/<clients>/subparts = array( "subclient1" )
49
	 *
50
	 * As the clients only generates structural HTML, the layout defined via CSS
51
	 * should support adding, removing or reordering content by a fluid like
52
	 * design.
53
	 *
54
	 * @param array List of sub-client names
55
	 * @since 2014.03
56
	 * @category Developer
57
	 */
58
	private $subPartPath = 'client/html/catalog/lists/subparts';
59
60
	/** client/html/catalog/lists/promo/name
61
	 * Name of the promotion part used by the catalog list client implementation
62
	 *
63
	 * Use "Myname" if your class is named "\Aimeos\Client\Html\Catalog\Lists\Promo\Myname".
64
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
65
	 *
66
	 * @param string Last part of the client class name
67
	 * @since 2014.03
68
	 * @category Developer
69
	 */
70
71
	/** client/html/catalog/lists/items/name
72
	 * Name of the items part used by the catalog list client implementation
73
	 *
74
	 * Use "Myname" if your class is named "\Aimeos\Client\Html\Catalog\Lists\Items\Myname".
75
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
76
	 *
77
	 * @param string Last part of the client class name
78
	 * @since 2014.03
79
	 * @category Developer
80
	 */
81
	private $subPartNames = array( 'items' );
82
83
	private $tags = [];
84
	private $expire;
85
	private $view;
86
87
88
	/**
89
	 * Returns the HTML code for insertion into the body.
90
	 *
91
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
92
	 * @return string HTML code
93
	 */
94
	public function body( string $uid = '' ) : string
95
	{
96
		$view = $this->getView();
97
		$context = $this->getContext();
98
		$prefixes = ['f_catid', 'f_supid', 'f_sort', 'l_page', 'l_type'];
99
100
		/** client/html/catalog/lists/cache
101
		 * Enables or disables caching only for the catalog lists component
102
		 *
103
		 * Disable caching for components can be useful if you would have too much
104
		 * entries to cache or if the component contains non-cacheable parts that
105
		 * can't be replaced using the modifyBody() and modifyHeader() methods.
106
		 *
107
		 * @param boolean True to enable caching, false to disable
108
		 * @category Developer
109
		 * @category User
110
		 * @see client/html/catalog/detail/cache
111
		 * @see client/html/catalog/filter/cache
112
		 * @see client/html/catalog/stage/cache
113
		 */
114
115
		/** client/html/catalog/lists
116
		 * All parameters defined for the catalog list component and its subparts
117
		 *
118
		 * This returns all settings related to the filter component.
119
		 * Please refer to the single settings for details.
120
		 *
121
		 * @param array Associative list of name/value settings
122
		 * @category Developer
123
		 * @see client/html/catalog#list
124
		 */
125
		$confkey = 'client/html/catalog/lists';
126
127
		$args = map( $view->param() )->except( $prefixes )->filter( function( $val, $key ) {
128
			return !strncmp( $key, 'f_', 2 ) || !strncmp( $key, 'l_', 2 );
129
		} );
130
131
		if( !$args->isEmpty() || ( $html = $this->getCached( 'body', $uid, $prefixes, $confkey ) ) === null )
132
		{
133
			/** client/html/catalog/lists/template-body
134
			 * Relative path to the HTML body template of the catalog list client.
135
			 *
136
			 * The template file contains the HTML code and processing instructions
137
			 * to generate the result shown in the body of the frontend. The
138
			 * configuration string is the path to the template file relative
139
			 * to the templates directory (usually in client/html/templates).
140
			 *
141
			 * You can overwrite the template file configuration in extensions and
142
			 * provide alternative templates. These alternative templates should be
143
			 * named like the default one but with the string "standard" replaced by
144
			 * an unique name. You may use the name of your project for this. If
145
			 * you've implemented an alternative client class as well, "standard"
146
			 * should be replaced by the name of the new class.
147
			 *
148
			 * It's also possible to create a specific template for each type, e.g.
149
			 * for the grid, list or whatever view you want to offer your users. In
150
			 * that case, you can configure the template by adding "-<type>" to the
151
			 * configuration key. To configure an alternative list view template for
152
			 * example, use the key
153
			 *
154
			 * client/html/catalog/lists/template-body-list = catalog/lists/body-list.php
155
			 *
156
			 * The argument is the relative path to the new template file. The type of
157
			 * the view is determined by the "l_type" parameter (allowed characters for
158
			 * the types are a-z and 0-9), which is also stored in the session so users
159
			 * will keep the view during their visit. The catalog list type subpart
160
			 * contains the template for switching between list types.
161
			 *
162
			 * @param string Relative path to the template creating code for the HTML page body
163
			 * @since 2014.03
164
			 * @category Developer
165
			 * @see client/html/catalog/lists/template-header
166
			 * @see client/html/catalog/lists/type/template-body
167
			 */
168
			$tplconf = 'client/html/catalog/lists/template-body';
169
			$default = 'catalog/lists/body-standard';
170
171
			try
172
			{
173
				$html = '';
174
175
				if( !isset( $this->view ) ) {
176
					$view = $this->view = $this->getObject()->data( $view, $this->tags, $this->expire );
177
				}
178
179
				foreach( $this->getSubClients() as $subclient ) {
180
					$html .= $subclient->setView( $view )->body( $uid );
181
				}
182
				$view->listBody = $html;
183
184
				$html = $view->render( $this->getTemplatePath( $tplconf, $default ) );
185
186
				if( $args->isEmpty() ) {
187
					$this->setCached( 'body', $uid, $prefixes, $confkey, $html, $this->tags, $this->expire );
188
				}
189
190
				return $html;
191
			}
192
			catch( \Aimeos\Client\Html\Exception $e )
193
			{
194
				$error = array( $context->translate( 'client', $e->getMessage() ) );
195
				$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
196
			}
197
			catch( \Aimeos\Controller\Frontend\Exception $e )
198
			{
199
				$error = array( $context->translate( 'controller/frontend', $e->getMessage() ) );
200
				$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
201
			}
202
			catch( \Aimeos\MShop\Exception $e )
203
			{
204
				$error = array( $context->translate( 'mshop', $e->getMessage() ) );
205
				$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
206
			}
207
			catch( \Exception $e )
208
			{
209
				$error = array( $context->translate( 'client', 'A non-recoverable error occured' ) );
210
				$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
211
				$this->logException( $e );
212
			}
213
214
			$html = $view->render( $this->getTemplatePath( $tplconf, $default ) );
215
		}
216
		else
217
		{
218
			$html = $this->modifyBody( $html, $uid );
219
		}
220
221
		return $html;
222
	}
223
224
225
	/**
226
	 * Returns the HTML string for insertion into the header.
227
	 *
228
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
229
	 * @return string|null String including HTML tags for the header on error
230
	 */
231
	public function header( string $uid = '' ) : ?string
232
	{
233
		$view = $this->getView();
234
		$confkey = 'client/html/catalog/lists';
235
		$prefixes = ['f_catid', 'f_supid', 'f_sort', 'l_page', 'l_type'];
236
237
		$args = map( $view->param() )->except( $prefixes )->filter( function( $val, $key ) {
238
			return !strncmp( $key, 'f_', 2 ) || !strncmp( $key, 'l_', 2 );
239
		} );
240
241
		if( !$args->isEmpty() || ( $html = $this->getCached( 'header', $uid, $prefixes, $confkey ) ) === null )
242
		{
243
			/** client/html/catalog/lists/template-header
244
			 * Relative path to the HTML header template of the catalog list client.
245
			 *
246
			 * The template file contains the HTML code and processing instructions
247
			 * to generate the HTML code that is inserted into the HTML page header
248
			 * of the rendered page in the frontend. The configuration string is the
249
			 * path to the template file relative to the templates directory (usually
250
			 * in client/html/templates).
251
			 *
252
			 * You can overwrite the template file configuration in extensions and
253
			 * provide alternative templates. These alternative templates should be
254
			 * named like the default one but with the string "standard" replaced by
255
			 * an unique name. You may use the name of your project for this. If
256
			 * you've implemented an alternative client class as well, "standard"
257
			 * should be replaced by the name of the new class.
258
			 *
259
			 * It's also possible to create a specific template for each type, e.g.
260
			 * for the grid, list or whatever view you want to offer your users. In
261
			 * that case, you can configure the template by adding "-<type>" to the
262
			 * configuration key. To configure an alternative list view template for
263
			 * example, use the key
264
			 *
265
			 * client/html/catalog/lists/template-header-list = catalog/lists/header-list.php
266
			 *
267
			 * The argument is the relative path to the new template file. The type of
268
			 * the view is determined by the "l_type" parameter (allowed characters for
269
			 * the types are a-z and 0-9), which is also stored in the session so users
270
			 * will keep the view during their visit. The catalog list type subpart
271
			 * contains the template for switching between list types.
272
			 *
273
			 * @param string Relative path to the template creating code for the HTML page head
274
			 * @since 2014.03
275
			 * @category Developer
276
			 * @see client/html/catalog/lists/template-body
277
			 * @see client/html/catalog/lists/type/template-body
278
			 */
279
			$tplconf = 'client/html/catalog/lists/template-header';
280
			$default = 'catalog/lists/header-standard';
281
282
			try
283
			{
284
				$html = '';
285
286
				if( !isset( $this->view ) ) {
287
					$view = $this->view = $this->getObject()->data( $view, $this->tags, $this->expire );
288
				}
289
290
				foreach( $this->getSubClients() as $subclient ) {
291
					$html .= $subclient->setView( $view )->header( $uid );
292
				}
293
				$view->listHeader = $html;
294
295
				$html = $view->render( $this->getTemplatePath( $tplconf, $default ) );
296
297
				if( $args->isEmpty() ) {
298
					$this->setCached( 'header', $uid, $prefixes, $confkey, $html, $this->tags, $this->expire );
299
				}
300
301
				return $html;
302
			}
303
			catch( \Exception $e )
304
			{
305
				$this->logException( $e );
306
			}
307
		}
308
		else
309
		{
310
			$html = $this->modifyHeader( $html, $uid );
311
		}
312
313
		return $html;
314
	}
315
316
317
	/**
318
	 * Returns the sub-client given by its name.
319
	 *
320
	 * @param string $type Name of the client type
321
	 * @param string|null $name Name of the sub-client (Default if null)
322
	 * @return \Aimeos\Client\Html\Iface Sub-client object
323
	 */
324
	public function getSubClient( string $type, string $name = null ) : \Aimeos\Client\Html\Iface
325
	{
326
		/** client/html/catalog/lists/decorators/excludes
327
		 * Excludes decorators added by the "common" option from the catalog list html client
328
		 *
329
		 * Decorators extend the functionality of a class by adding new aspects
330
		 * (e.g. log what is currently done), executing the methods of the underlying
331
		 * class only in certain conditions (e.g. only for logged in users) or
332
		 * modify what is returned to the caller.
333
		 *
334
		 * This option allows you to remove a decorator added via
335
		 * "client/html/common/decorators/default" before they are wrapped
336
		 * around the html client.
337
		 *
338
		 *  client/html/catalog/lists/decorators/excludes = array( 'decorator1' )
339
		 *
340
		 * This would remove the decorator named "decorator1" from the list of
341
		 * common decorators ("\Aimeos\Client\Html\Common\Decorator\*") added via
342
		 * "client/html/common/decorators/default" to the html client.
343
		 *
344
		 * @param array List of decorator names
345
		 * @since 2014.05
346
		 * @category Developer
347
		 * @see client/html/common/decorators/default
348
		 * @see client/html/catalog/lists/decorators/global
349
		 * @see client/html/catalog/lists/decorators/local
350
		 */
351
352
		/** client/html/catalog/lists/decorators/global
353
		 * Adds a list of globally available decorators only to the catalog list html client
354
		 *
355
		 * Decorators extend the functionality of a class by adding new aspects
356
		 * (e.g. log what is currently done), executing the methods of the underlying
357
		 * class only in certain conditions (e.g. only for logged in users) or
358
		 * modify what is returned to the caller.
359
		 *
360
		 * This option allows you to wrap global decorators
361
		 * ("\Aimeos\Client\Html\Common\Decorator\*") around the html client.
362
		 *
363
		 *  client/html/catalog/lists/decorators/global = array( 'decorator1' )
364
		 *
365
		 * This would add the decorator named "decorator1" defined by
366
		 * "\Aimeos\Client\Html\Common\Decorator\Decorator1" only to the html client.
367
		 *
368
		 * @param array List of decorator names
369
		 * @since 2014.05
370
		 * @category Developer
371
		 * @see client/html/common/decorators/default
372
		 * @see client/html/catalog/lists/decorators/excludes
373
		 * @see client/html/catalog/lists/decorators/local
374
		 */
375
376
		/** client/html/catalog/lists/decorators/local
377
		 * Adds a list of local decorators only to the catalog list html client
378
		 *
379
		 * Decorators extend the functionality of a class by adding new aspects
380
		 * (e.g. log what is currently done), executing the methods of the underlying
381
		 * class only in certain conditions (e.g. only for logged in users) or
382
		 * modify what is returned to the caller.
383
		 *
384
		 * This option allows you to wrap local decorators
385
		 * ("\Aimeos\Client\Html\Catalog\Decorator\*") around the html client.
386
		 *
387
		 *  client/html/catalog/lists/decorators/local = array( 'decorator2' )
388
		 *
389
		 * This would add the decorator named "decorator2" defined by
390
		 * "\Aimeos\Client\Html\Catalog\Decorator\Decorator2" only to the html client.
391
		 *
392
		 * @param array List of decorator names
393
		 * @since 2014.05
394
		 * @category Developer
395
		 * @see client/html/common/decorators/default
396
		 * @see client/html/catalog/lists/decorators/excludes
397
		 * @see client/html/catalog/lists/decorators/global
398
		 */
399
400
		return $this->createSubClient( 'catalog/lists/' . $type, $name );
401
	}
402
403
404
	/**
405
	 * Processes the input, e.g. store given values.
406
	 *
407
	 * A view must be available and this method doesn't generate any output
408
	 * besides setting view variables if necessary.
409
	 */
410
	public function init()
411
	{
412
		$context = $this->getContext();
413
		$view = $this->getView();
414
415
		try
416
		{
417
			$site = $context->getLocale()->getSiteItem()->getCode();
418
			$params = $this->getClientParams( $view->param() );
419
420
			$catId = $context->getConfig()->get( 'client/html/catalog/lists/catid-default' );
421
422
			if( ( $catId = $view->param( 'f_catid', $catId ) ) )
423
			{
424
				$params['f_name'] = $view->param( 'f_name' );
425
				$params['f_catid'] = $catId;
426
			}
427
428
			$context->getSession()->set( 'aimeos/catalog/lists/params/last/' . $site, $params );
429
430
			parent::init();
431
		}
432
		catch( \Aimeos\Client\Html\Exception $e )
433
		{
434
			$error = array( $context->translate( 'client', $e->getMessage() ) );
435
			$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
436
		}
437
		catch( \Aimeos\Controller\Frontend\Exception $e )
438
		{
439
			$error = array( $context->translate( 'controller/frontend', $e->getMessage() ) );
440
			$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
441
		}
442
		catch( \Aimeos\MShop\Exception $e )
443
		{
444
			$error = array( $context->translate( 'mshop', $e->getMessage() ) );
445
			$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
446
		}
447
		catch( \Exception $e )
448
		{
449
			$error = array( $context->translate( 'client', 'A non-recoverable error occured' ) );
450
			$view->listErrorList = array_merge( $view->get( 'listErrorList', [] ), $error );
451
			$this->logException( $e );
452
		}
453
	}
454
455
456
	/**
457
	 * Returns the list of sub-client names configured for the client.
458
	 *
459
	 * @return array List of HTML client names
460
	 */
461
	protected function getSubClientNames() : array
462
	{
463
		return $this->getContext()->getConfig()->get( $this->subPartPath, $this->subPartNames );
464
	}
465
466
467
	/**
468
	 * Sets the necessary parameter values in the view.
469
	 *
470
	 * @param \Aimeos\MW\View\Iface $view The view object which generates the HTML output
471
	 * @param array &$tags Result array for the list of tags that are associated to the output
472
	 * @param string|null &$expire Result variable for the expiration date of the output (null for no expiry)
473
	 * @return \Aimeos\MW\View\Iface Modified view object
474
	 */
475
	public function data( \Aimeos\MW\View\Iface $view, array &$tags = [], string &$expire = null ) : \Aimeos\MW\View\Iface
476
	{
477
		$total = 0;
478
		$context = $this->getContext();
479
		$config = $context->getConfig();
480
481
482
		/** client/html/catalog/domains
483
		 * A list of domain names whose items should be available in the catalog view templates
484
		 *
485
		 * The templates rendering catalog related data usually add the images and
486
		 * texts associated to each item. If you want to display additional
487
		 * content like the attributes, you can configure your own list of
488
		 * domains (attribute, media, price, product, text, etc. are domains)
489
		 * whose items are fetched from the storage. Please keep in mind that
490
		 * the more domains you add to the configuration, the more time is required
491
		 * for fetching the content!
492
		 *
493
		 * This configuration option can be overwritten by the "client/html/catalog/lists/domains"
494
		 * configuration option that allows to configure the domain names of the
495
		 * items fetched specifically for all types of product listings.
496
		 *
497
		 * @param array List of domain names
498
		 * @since 2014.03
499
		 * @category Developer
500
		 * @see client/html/catalog/lists/domains
501
		 * @see client/html/catalog/lists/size
502
		 * @see client/html/catalog/lists/levels
503
		 * @see client/html/catalog/lists/sort
504
		 * @see client/html/catalog/lists/pages
505
		 */
506
		$domains = $config->get( 'client/html/catalog/domains', ['media', 'media/property', 'price', 'text'] );
507
508
		/** client/html/catalog/lists/domains
509
		 * A list of domain names whose items should be available in the product list view template
510
		 *
511
		 * The templates rendering product lists usually add the images, prices
512
		 * and texts associated to each product item. If you want to display additional
513
		 * content like the product attributes, you can configure your own list of
514
		 * domains (attribute, media, price, product, text, etc. are domains)
515
		 * whose items are fetched from the storage. Please keep in mind that
516
		 * the more domains you add to the configuration, the more time is required
517
		 * for fetching the content!
518
		 *
519
		 * This configuration option overwrites the "client/html/catalog/domains"
520
		 * option that allows to configure the domain names of the items fetched
521
		 * for all catalog related data.
522
		 *
523
		 * @param array List of domain names
524
		 * @since 2014.03
525
		 * @category Developer
526
		 * @see client/html/catalog/domains
527
		 * @see client/html/catalog/detail/domains
528
		 * @see client/html/catalog/stage/domains
529
		 * @see client/html/catalog/lists/catid-default
530
		 * @see client/html/catalog/lists/supid-default
531
		 * @see client/html/catalog/lists/size
532
		 * @see client/html/catalog/lists/levels
533
		 * @see client/html/catalog/lists/sort
534
		 * @see client/html/catalog/lists/pages
535
		 * @see client/html/catalog/lists/instock
536
		 */
537
		$domains = $config->get( 'client/html/catalog/lists/domains', $domains );
538
539
		/** client/html/catalog/lists/instock
540
		 * Show only products which are in stock
541
		 *
542
		 * This configuration option overwrites the "client/html/catalog/domains"
543
		 * option that allows to configure the domain names of the items fetched
544
		 * for all catalog related data.
545
		 *
546
		 * @param int Zero to show all products, "1" to show only products with stock
547
		 * @since 2021.10
548
		 * @see client/html/catalog/domains
549
		 * @see client/html/catalog/lists/domains
550
		 * @see client/html/catalog/detail/domains
551
		 * @see client/html/catalog/stage/domains
552
		 * @see client/html/catalog/lists/catid-default
553
		 * @see client/html/catalog/lists/supid-default
554
		 * @see client/html/catalog/lists/size
555
		 * @see client/html/catalog/lists/levels
556
		 * @see client/html/catalog/lists/sort
557
		 * @see client/html/catalog/lists/pages
558
		 */
559
		$inStock = $config->get( 'client/html/catalog/lists/instock', 0 );
560
561
		/** client/html/catalog/lists/pages
562
		 * Maximum number of product pages shown in pagination
563
		 *
564
		 * Limits the number of product pages that are shown in the navigation.
565
		 * The user is able to move to the next page (or previous one if it's not
566
		 * the first) to display the next (or previous) products.
567
		 *
568
		 * The value must be a positive integer number. Negative values are not
569
		 * allowed. The value can't be overwritten per request.
570
		 *
571
		 * @param integer Number of pages
572
		 * @since 2019.04
573
		 * @category User
574
		 * @category Developer
575
		 * @see client/html/catalog/lists/catid-default
576
		 * @see client/html/catalog/lists/supid-default
577
		 * @see client/html/catalog/lists/domains
578
		 * @see client/html/catalog/lists/levels
579
		 * @see client/html/catalog/lists/sort
580
		 * @see client/html/catalog/lists/size
581
		 * @see client/html/catalog/lists/instock
582
		 */
583
		$pages = $config->get( 'client/html/catalog/lists/pages', 100 );
584
585
		/** client/html/catalog/lists/size
586
		 * The number of products shown in a list page
587
		 *
588
		 * Limits the number of products that are shown in the list pages to the
589
		 * given value. If more products are available, the products are split
590
		 * into bunches which will be shown on their own list page. The user is
591
		 * able to move to the next page (or previous one if it's not the first)
592
		 * to display the next (or previous) products.
593
		 *
594
		 * The value must be an integer number from 1 to 100. Negative values as
595
		 * well as values above 100 are not allowed. The value can be overwritten
596
		 * per request if the "l_size" parameter is part of the URL.
597
		 *
598
		 * @param integer Number of products
599
		 * @since 2014.03
600
		 * @category User
601
		 * @category Developer
602
		 * @see client/html/catalog/lists/catid-default
603
		 * @see client/html/catalog/lists/supid-default
604
		 * @see client/html/catalog/lists/domains
605
		 * @see client/html/catalog/lists/levels
606
		 * @see client/html/catalog/lists/sort
607
		 * @see client/html/catalog/lists/pages
608
		 * @see client/html/catalog/lists/instock
609
		 */
610
		$size = $config->get( 'client/html/catalog/lists/size', 48 );
611
612
		/** client/html/catalog/lists/levels
613
		 * Include products of sub-categories in the product list of the current category
614
		 *
615
		 * Sometimes it may be useful to show products of sub-categories in the
616
		 * current category product list, e.g. if the current category contains
617
		 * no products at all or if there are only a few products in all categories.
618
		 *
619
		 * Possible constant values for this setting are:
620
		 *
621
		 * * 1 : Only products from the current category
622
		 * * 2 : Products from the current category and the direct child categories
623
		 * * 3 : Products from the current category and the whole category sub-tree
624
		 *
625
		 * Caution: Please keep in mind that displaying products of sub-categories
626
		 * can slow down your shop, especially if it contains more than a few
627
		 * products! You have no real control over the positions of the products
628
		 * in the result list too because all products from different categories
629
		 * with the same position value are placed randomly.
630
		 *
631
		 * Usually, a better way is to associate products to all categories they
632
		 * should be listed in. This can be done manually if there are only a few
633
		 * ones or during the product import automatically.
634
		 *
635
		 * @param integer Tree level constant
636
		 * @since 2015.11
637
		 * @category Developer
638
		 * @see client/html/catalog/lists/catid-default
639
		 * @see client/html/catalog/lists/supid-default
640
		 * @see client/html/catalog/lists/domains
641
		 * @see client/html/catalog/lists/size
642
		 * @see client/html/catalog/lists/sort
643
		 * @see client/html/catalog/lists/pages
644
		 * @see client/html/catalog/lists/instock
645
		 */
646
		$level = $config->get( 'client/html/catalog/lists/levels', \Aimeos\MW\Tree\Manager\Base::LEVEL_ONE );
647
648
649
		/** client/html/catalog/lists/catid-default
650
		 * The default category ID used if none is given as parameter
651
		 *
652
		 * If users view a product list page without a category ID in the
653
		 * parameter list, the first found products are displayed with a
654
		 * random order. You can circumvent this by configuring a default
655
		 * category ID that should be used in this case (the ID of the root
656
		 * category is best for this). In most cases you can set this value
657
		 * via the administration interface of the shop application.
658
		 *
659
		 * @param array|string Category ID or IDs
660
		 * @since 2014.03
661
		 * @category User
662
		 * @category Developer
663
		 * @see client/html/catalog/lists/sort
664
		 * @see client/html/catalog/lists/size
665
		 * @see client/html/catalog/lists/domains
666
		 * @see client/html/catalog/lists/levels
667
		 * @see client/html/catalog/detail/prodid-default
668
		 * @see client/html/catalog/lists/supid-default
669
		 * @see client/html/catalog/lists/instock
670
		 */
671
		$catids = $view->param( 'f_catid', $config->get( 'client/html/catalog/lists/catid-default' ) );
672
		$catids = $catids != null && is_scalar( $catids ) ? explode( ',', $catids ) : $catids; // workaround for TYPO3
673
674
675
		/** client/html/catalog/lists/supid-default
676
		 * The default supplier ID used if none is given as parameter
677
		 *
678
		 * Products in the list page can be limited to one or more suppliers.
679
		 * By default, the products are not limited to any supplier until one or
680
		 * more supplier IDs are passed in the URL using the f_supid parameter.
681
		 * You can also configure the default supplier IDs for limiting the
682
		 * products if no IDs are passed in the URL using this configuration.
683
		 *
684
		 * @param array|string Supplier ID or IDs
685
		 * @since 2021.01
686
		 * @category User
687
		 * @category Developer
688
		 * @see client/html/catalog/lists/sort
689
		 * @see client/html/catalog/lists/size
690
		 * @see client/html/catalog/lists/domains
691
		 * @see client/html/catalog/lists/levels
692
		 * @see client/html/catalog/lists/catid-default
693
		 * @see client/html/catalog/detail/prodid-default
694
		 * @see client/html/catalog/lists/instock
695
		 */
696
		$supids = $view->param( 'f_supid', $config->get( 'client/html/catalog/lists/supid-default' ) );
697
		$supids = $supids != null && is_scalar( $supids ) ? explode( ',', $supids ) : $supids; // workaround for TYPO3
698
699
		/** client/html/catalog/lists/sort
700
		 * Default sorting of product list if no other sorting is given by parameter
701
		 *
702
		 * Configures the standard sorting of products in list views. This sorting is used
703
		 * as long as it's not overwritten by an URL parameter. Except "relevance", all
704
		 * other sort codes can be prefixed by a "-" (minus) sign to sort the products in
705
		 * a descending order. By default, the sorting is ascending.
706
		 *
707
		 * @param string Sort code "relevance", "name", "-name", "price", "-price", "ctime" or "-ctime"
708
		 * @since 2018.07
709
		 * @category User
710
		 * @category Developer
711
		 * @see client/html/catalog/lists/catid-default
712
		 * @see client/html/catalog/lists/supid-default
713
		 * @see client/html/catalog/lists/domains
714
		 * @see client/html/catalog/lists/levels
715
		 * @see client/html/catalog/lists/size
716
		 * @see client/html/catalog/lists/instock
717
		 */
718
		$sort = $view->param( 'f_sort', $config->get( 'client/html/catalog/lists/sort', 'relevance' ) );
719
		$size = min( max( $view->param( 'l_size', $size ), 1 ), 100 );
720
		$page = min( max( $view->param( 'l_page', 1 ), 1 ), $pages );
721
722
		if( $catids != null )
723
		{
724
			$controller = \Aimeos\Controller\Frontend::create( $context, 'catalog' )->uses( $domains );
725
			$listCatPath = $controller->getPath( is_array( $catids ) ? reset( $catids ) : $catids );
726
727
			if( ( $categoryItem = $listCatPath->last() ) !== null ) {
728
				$view->listCurrentCatItem = $categoryItem;
729
			}
730
731
			$view->listCatPath = $listCatPath;
732
			$this->addMetaItems( $listCatPath, $expire, $tags );
733
		}
734
735
		if( $view->config( 'client/html/catalog/lists/basket-add', false ) ) {
736
			$domains = array_merge_recursive( $domains, ['product' => ['default'], 'attribute' => ['variant', 'custom', 'config']] );
737
		}
738
739
		$cntl = \Aimeos\Controller\Frontend::create( $context, 'product' )
740
			->sort( $sort ) // prioritize user sorting over the sorting through relevance and category
741
			->text( $view->param( 'f_search' ) )
742
			->price( $view->param( 'f_price' ) )
743
			->category( $catids, 'default', $level )
744
			->supplier( $supids )
745
			->allOf( $view->param( 'f_attrid', [] ) )
746
			->oneOf( $view->param( 'f_optid', [] ) )
747
			->oneOf( $view->param( 'f_oneid', [] ) )
748
			->slice( ( $page - 1 ) * $size, $size )
749
			->uses( $domains );
750
751
		if( $inStock ) {
752
			$cntl->compare( '>', 'product.instock', 0 );
753
		}
754
755
		$products = $cntl->search( $total );
756
757
758
		// Delete cache when products are added or deleted even when in "tag-all" mode
759
		$this->addMetaItems( $products, $expire, $tags, ['product'] );
760
761
762
		$view->listProductItems = $products;
763
		$view->listProductSort = $sort;
764
		$view->listProductTotal = $total;
765
766
		$view->listPageSize = $size;
767
		$view->listPageCurr = $page;
768
		$view->listPagePrev = ( $page > 1 ? $page - 1 : 1 );
769
		$view->listPageLast = ( $total != 0 ? min( ceil( $total / $size ), $pages ) : 1 );
0 ignored issues
show
introduced by
The condition $total != 0 is always false.
Loading history...
770
		$view->listPageNext = ( $page < $view->listPageLast ? $page + 1 : $view->listPageLast );
771
772
		$view->listParams = $this->getClientParams( map( $view->param() )->toArray() );
773
774
		return parent::data( $view, $tags, $expire );
775
	}
776
}
777