Standard::body()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2021-2025
6
 * @package Client
7
 * @subpackage Html
8
 */
9
10
11
namespace Aimeos\Client\Html\Cms\Page\Cataloglist;
12
13
14
/**
15
 * Default implementation for CMS cataloglist.
16
 *
17
 * @package Client
18
 * @subpackage Html
19
 */
20
class Standard
21
	extends \Aimeos\Client\Html\Catalog\Base
22
	implements \Aimeos\Client\Html\Common\Client\Factory\Iface
23
{
24
	/**
25
	 * Returns the HTML code for insertion into the body.
26
	 *
27
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
28
	 * @return string HTML code
29
	 */
30
	public function body( string $uid = '' ) : string
31
	{
32
		return '';
33
	}
34
35
36
	/**
37
	 * Modifies the cached content to replace content based on sessions or cookies.
38
	 *
39
	 * @param string $content Cached content
40
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
41
	 * @return string Modified content
42
	 */
43
	public function modify( string $content, string $uid ) : string
44
	{
45
		return $this->replaceSection( $content, $this->view()->csrf()->formfield(), 'catalog.lists.items.csrf' );
46
	}
47
48
49
	/**
50
	 * Sets the necessary parameter values in the view.
51
	 *
52
	 * @param \Aimeos\Base\View\Iface $view The view object which generates the HTML output
53
	 * @param array &$tags Result array for the list of tags that are associated to the output
54
	 * @param string|null &$expire Result variable for the expiration date of the output (null for no expiry)
55
	 * @return \Aimeos\Base\View\Iface Modified view object
56
	 */
57
	public function data( \Aimeos\Base\View\Iface $view, array &$tags = [], ?string &$expire = null ) : \Aimeos\Base\View\Iface
58
	{
59
		if( !isset( $view->pageContent ) ) {
60
			return parent::data( $view, $tags, $expire );
61
		}
62
63
		$texts = [];
64
		$context = $this->context();
65
		$config = $context->config();
66
		$cntl = \Aimeos\Controller\Frontend::create( $context, 'product' );
67
68
		/** client/html/cms/page/template-cataloglist
69
		 * Relative path to the HTML template of the page catalog list client.
70
		 *
71
		 * The template file contains the HTML code and processing instructions
72
		 * to generate the HTML code that is inserted into the HTML page
73
		 * of the rendered page in the frontend. The configuration string is the
74
		 * path to the template file relative to the templates directory (usually
75
		 * in client/html/templates).
76
		 *
77
		 * You can overwrite the template file configuration in extensions and
78
		 * provide alternative templates. These alternative templates should be
79
		 * named like the default one but with the string "standard" replaced by
80
		 * an unique name. You may use the name of your project for this. If
81
		 * you've implemented an alternative client class as well, "standard"
82
		 * should be replaced by the name of the new class.
83
		 *
84
		 * @param string Relative path to the template creating code for the catalog list
85
		 * @since 2021.07
86
		 * @category Developer
87
		 * @see client/html/cms/page/template-body
88
		 * @see client/html/cms/page/template-header
89
		 */
90
		$template = $config->get( 'client/html/cms/page/template-cataloglist', 'cms/page/cataloglist/list' );
91
		$domains = $config->get( 'client/html/catalog/lists/domains', ['media', 'media/property', 'price', 'text'] );
92
93
		if( $view->config( 'client/html/cms/page/basket-add', false ) ) {
94
			$domains = array_merge_recursive( $domains, ['product' => ['default'], 'attribute' => ['variant', 'custom', 'config']] );
95
		}
96
97
		libxml_use_internal_errors( true );
98
99
		foreach( $view->pageContent as $content )
100
		{
101
			$dom = new \DOMDocument( '1.0', 'UTF-8' );
102
			$dom->loadHTML( '<?xml encoding="utf-8" ?>' . $content, LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD );
103
			$nodes = $dom->getElementsByTagName( 'cataloglist' );
104
105
			while( $nodes->length > 0 )
106
			{
107
				$node = $nodes->item( 0 );
108
				$catid = $node->hasAttribute( 'catid' ) ? $node->getAttribute( 'catid' ) : null;
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()? ( Ignorable by Annotation )

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

108
				$catid = $node->/** @scrutinizer ignore-call */ hasAttribute( 'catid' ) ? $node->getAttribute( 'catid' ) : null;

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...
109
				$type = $node->hasAttribute( 'type' ) ? $node->getAttribute( 'type' ) : 'default';
110
				$limit = $node->hasAttribute( 'limit' ) ? $node->getAttribute( 'limit' ) : 3;
111
112
				$products = ( clone $cntl )->uses( $domains )
0 ignored issues
show
Bug introduced by
The method uses() does not exist on Aimeos\Controller\Frontend\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Controller\Frontend\Common\Iface or Aimeos\Controller\Frontend\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

112
				$products = ( clone $cntl )->/** @scrutinizer ignore-call */ uses( $domains )
Loading history...
113
					->category( $catid, $type )
114
					->slice( 0, $limit )
115
					->search();
116
117
				$articles = $products->getRefItems( 'product', 'default', 'default' )->flat( 1 )->union( $products );
118
				$attrMap = $articles->getRefItems( 'attribute' )->flat( 1 )->groupBy( 'attribute.type' );
119
				$attrTypes = $this->attributeTypes( $attrMap->keys() );
120
121
				$this->addMetaItems( $products, $expire, $tags );
122
123
				$tview = $context->view()->set( 'products', $products )->set( 'attributeTypes', $attrTypes );
124
125
				if( !$products->isEmpty() && (bool) $config->get( 'client/html/catalog/lists/stock/enable', true ) === true ) {
126
					$tview->itemsStockUrl = $this->getStockUrl( $tview, $articles );
127
				}
128
129
				$pdom = new \DOMDocument( '1.0', 'UTF-8' );
130
				$pdom->loadHTML( '<?xml encoding="utf-8" ?>' . $tview->render( $template ), LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD );
131
132
				$pnode = $dom->importNode( $pdom->documentElement, true );
133
				$node->parentNode->replaceChild( $pnode, $node );
0 ignored issues
show
Bug introduced by
The method replaceChild() 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

133
				$node->parentNode->/** @scrutinizer ignore-call */ 
134
                       replaceChild( $pnode, $node );

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...
134
			}
135
136
			$texts[] = substr( $dom->saveHTML(), 25 );
137
		}
138
139
		libxml_clear_errors();
140
141
		$view->pageContent = $texts;
142
143
		return parent::data( $view, $tags, $expire );
144
	}
145
146
147
	/**
148
	 * Returns the attribute type items for the given codes
149
	 *
150
	 * @param \Aimeos\Map $codes List of attribute type codes
151
	 * @return \Aimeos\Map List of attribute type items
152
	 */
153
	protected function attributeTypes( \Aimeos\Map $codes ) : \Aimeos\Map
154
	{
155
		$manager = \Aimeos\MShop::create( $this->context(), 'attribute/type' );
156
157
		$filter = $manager->filter( true )
158
			->add( 'attribute.type.domain', '==', 'product' )
159
			->add( 'attribute.type.code', '==', $codes )
160
			->order( 'attribute.type.position' );
161
162
		return $manager->search( $filter->slice( 0, count( $codes ) ) );
163
	}
164
}
165