Completed
Push — master ( b94e09...a59c24 )
by Aimeos
02:35
created

Standard::addFilterAttribute()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 41
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 8.439
c 0
b 0
f 0
cc 5
eloc 23
nc 12
nop 4
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2017
6
 * @package Controller
7
 * @subpackage Frontend
8
 */
9
10
11
namespace Aimeos\Controller\Frontend\Index;
12
13
14
/**
15
 * Default implementation of the index frontend controller.
16
 *
17
 * @package Controller
18
 * @subpackage Frontend
19
 */
20
class Standard
21
	extends \Aimeos\Controller\Frontend\Base
2 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
22
	implements Iface, \Aimeos\Controller\Frontend\Common\Iface
1 ignored issue
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
23
{
24
	/**
25
	 * Returns the given search filter with the conditions attached for filtering by attribute.
26
	 *
27
	 * @param \Aimeos\MW\Criteria\Iface $filter Criteria object used for product search
28
	 * @param string|array $catid Selected category by the user
0 ignored issues
show
Bug introduced by
There is no parameter named $catid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
29
	 * @return \Aimeos\MW\Criteria\Iface Criteria object containing the conditions for searching
30
	 * @since 2017.03
31
	 */
32
	public function addFilterAttribute( \Aimeos\MW\Criteria\Iface $filter, array $attrIds, array $optIds, array $oneIds )
33
	{
34
		if( !empty( $attrIds ) )
35
		{
36
			$attrIds = $this->validateIds( $attrIds );
37
38
			$func = $filter->createFunction( 'index.attributeaggregate', array( $attrIds ) );
39
			$expr = array(
40
				$filter->getConditions(),
41
				$filter->compare( '==', $func, count( $attrIds ) ),
42
			);
43
			$filter->setConditions( $filter->combine( '&&', $expr ) );
44
		}
45
46
		if( !empty( $optIds ) )
47
		{
48
			$attrIds = $this->validateIds( $attrIds );
0 ignored issues
show
Unused Code introduced by
$attrIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
49
50
			$func = $filter->createFunction( 'index.attributeaggregate', array( $optIds ) );
51
			$expr = array(
52
				$filter->getConditions(),
53
				$filter->compare( '>', $func, 0 ),
54
			);
55
			$filter->setConditions( $filter->combine( '&&', $expr ) );
56
		}
57
58
		foreach( $oneIds as $type => $list )
59
		{
60
			if( ( $list = $this->validateIds( (array) $list ) ) !== array() )
61
			{
62
				$func = $filter->createFunction( 'index.attributeaggregate', array( $list ) );
63
				$expr = array(
64
					$filter->getConditions(),
65
					$filter->compare( '>', $func, 0 ),
66
				);
67
				$filter->setConditions( $filter->combine( '&&', $expr ) );
68
			}
69
		}
70
71
		return $filter;
72
	}
73
74
75
	/**
76
	 * Returns the given search filter with the conditions attached for filtering by category.
77
	 *
78
	 * @param \Aimeos\MW\Criteria\Iface $filter Criteria object used for product search
79
	 * @param string|array $catId Selected category by the user
80
	 * @param integer $level Constant for current category only, categories of next level (LEVEL_LIST) or whole subtree (LEVEL_SUBTREE)
81
	 * @return \Aimeos\MW\Criteria\Iface Criteria object containing the conditions for searching
82
	 * @since 2017.03
83
	 */
84
	public function addFilterCategory( \Aimeos\MW\Criteria\Iface $filter, $catId,
85
		$level = \Aimeos\MW\Tree\Manager\Base::LEVEL_ONE, $sort = null, $direction = '+', $listtype = 'default' )
86
	{
87
		$catIds = ( !is_array( $catId ) ? explode( ',', $catId ) : $catId );
88
89
		if( $level != \Aimeos\MW\Tree\Manager\Base::LEVEL_ONE )
90
		{
91
			$list = array();
92
			$cntl = \Aimeos\Controller\Frontend\Factory::createController( $this->getContext(), 'catalog' );
93
94
			foreach( $catIds as $catId )
95
			{
96
				$tree = $cntl->getCatalogTree( $catId, array(), $level );
97
				$list = array_merge( $list, $this->getCatalogIdsFromTree( $tree ) );
98
			}
99
100
			$catIds = $list;
101
		}
102
103
		$expr = array( $filter->compare( '==', 'index.catalog.id', array_unique( $catIds ) ) );
104
		$expr[] = $filter->getConditions();
105
106
		if( $sort === 'relevance' )
107
		{
108
			$cmpfunc = $filter->createFunction( 'index.catalog.position', array( $listtype, $catIds ) );
109
			$expr[] = $filter->compare( '>=', $cmpfunc, 0 );
110
111
			$sortfunc = $filter->createFunction( 'sort:index.catalog.position', array( $listtype, $catIds ) );
112
			$filter->setSortations( array( $filter->sort( $direction, $sortfunc ) ) );
113
		}
114
115
		$filter->setConditions( $filter->combine( '&&', $expr ) );
116
117
		return $filter;
118
	}
119
120
121
	/**
122
	 * Returns the given search filter with the conditions attached for filtering by text.
123
	 *
124
	 * @param \Aimeos\MW\Criteria\Iface $filter Criteria object used for product search
125
	 * @param string $input Search string entered by the user
126
	 * @param string $listtype List type of the text associated to the product, usually "default"
127
	 * @return \Aimeos\MW\Criteria\Iface Criteria object containing the conditions for searching
128
	 * @since 2017.03
129
	 */
130
	public function addFilterText( \Aimeos\MW\Criteria\Iface $filter, $input, $listtype = 'default' )
131
	{
132
		$langid = $this->getContext()->getLocale()->getLanguageId();
133
		$cmpfunc = $filter->createFunction( 'index.text.relevance', array( $listtype, $langid, $input ) );
134
		$expr = array( $filter->compare( '>', $cmpfunc, 0 ), $filter->getConditions() );
135
136
		return $filter->setConditions( $filter->combine( '&&', $expr ) );
137
	}
138
139
140
	/**
141
	 * Returns the aggregated count of products for the given key.
142
	 *
143
	 * @param \Aimeos\MW\Criteria\Iface $filter Critera object which contains the filter conditions
144
	 * @param string $key Search key to aggregate for, e.g. "index.attribute.id"
145
	 * @return array Associative list of key values as key and the product count for this key as value
146
	 * @since 2017.03
147
	 */
148
	public function aggregate( \Aimeos\MW\Criteria\Iface $filter, $key )
149
	{
150
		return \Aimeos\MShop\Factory::createManager( $this->getContext(), 'index' )->aggregate( $filter, $key );
151
	}
152
153
154
	/**
155
	 * Returns the default index filter.
156
	 *
157
	 * @param string|null $sort Sortation of the product list like "name", "code", "price" and "position", null for no sortation
158
	 * @param string $direction Sort direction of the product list ("+", "-")
159
	 * @param integer $start Position in the list of found products where to begin retrieving the items
160
	 * @param integer $size Number of products that should be returned
161
	 * @param string $listtype Type of the product list, e.g. default, promotion, etc.
162
	 * @return \Aimeos\MW\Criteria\Iface Criteria object containing the conditions for searching
163
	 * @since 2017.03
164
	 */
165
	public function createFilter( $sort = null, $direction = '+', $start = 0, $size = 100, $listtype = 'default' )
166
	{
167
		$sortations = array();
168
		$context = $this->getContext();
169
170
		$search = \Aimeos\MShop\Factory::createManager( $context, 'index' )->createSearch( true );
171
		$expr = array( $search->compare( '!=', 'index.catalog.id', null ) );
172
173
		switch( $sort )
174
		{
175
			case 'code':
176
				$sortations[] = $search->sort( $direction, 'product.code' );
177
				break;
178
179
			case 'name':
180
				$langid = $context->getLocale()->getLanguageId();
181
182
				$cmpfunc = $search->createFunction( 'index.text.value', array( $listtype, $langid, 'name', 'product' ) );
183
				$expr[] = $search->compare( '>=', $cmpfunc, '' );
184
185
				$sortfunc = $search->createFunction( 'sort:index.text.value', array( $listtype, $langid, 'name' ) );
186
				$sortations[] = $search->sort( $direction, $sortfunc );
187
				break;
188
189
			case 'price':
190
				$currencyid = $context->getLocale()->getCurrencyId();
191
192
				$cmpfunc = $search->createFunction( 'index.price.value', array( $listtype, $currencyid, 'default' ) );
193
				$expr[] = $search->compare( '>=', $cmpfunc, '0.00' );
194
195
				$sortfunc = $search->createFunction( 'sort:index.price.value', array( $listtype, $currencyid, 'default' ) );
196
				$sortations[] = $search->sort( $direction, $sortfunc );
197
				break;
198
		}
199
200
		$expr[] = $search->getConditions();
201
202
		$search->setConditions( $search->combine( '&&', $expr ) );
203
		$search->setSortations( $sortations );
204
		$search->setSlice( $start, $size );
205
206
		return $search;
207
	}
208
209
210
	/**
211
	 * Returns text filter for the given search string.
212
	 *
213
	 * @param string $input Search string entered by the user
214
	 * @param string|null $sort Sortation of the product list like "name" and "relevance", null for no sortation
215
	 * @param string $direction Sort direction of the product list ("asc", "desc")
216
	 * @param integer $start Position in the list of found products where to begin retrieving the items
217
	 * @param integer $size Number of products that should be returned
218
	 * @param string $listtype List type of the text associated to the product, usually "default"
219
	 * @param string $type Type of the text like "name", "short", "long", etc.
220
	 * @return \Aimeos\MW\Criteria\Iface Criteria object containing the conditions for searching
221
	 */
222
	public function createTextFilter( $input, $sort = null, $direction = '+', $start = 0, $size = 25, $listtype = 'default', $type = 'name' )
223
	{
224
		$locale = $this->getContext()->getLocale();
225
		$langid = $locale->getLanguageId();
226
227
		$search = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'index/text' )->createSearch( true );
228
229
		$expr = array(
230
			$search->compare( '>', $search->createFunction( 'index.text.relevance', array( $listtype, $langid, $input ) ), 0 ),
231
			$search->compare( '>', $search->createFunction( 'index.text.value', array( $listtype, $langid, $type, 'product' ) ), '' ),
232
		);
233
234
		$sortations = array();
235
236
		switch( $sort )
237
		{
238
			case 'name':
239
				$cmpfunc = $search->createFunction( 'index.text.value', array( $listtype, $langid, 'name', 'product' ) );
240
				$expr[] = $search->compare( '>=', $cmpfunc, '' );
241
242
				$sortfunc = $search->createFunction( 'sort:index.text.value', array( $listtype, $langid, 'name' ) );
243
				$sortations[] = $search->sort( $direction, $sortfunc );
244
				break;
245
246
			case 'relevance':
247
				// we don't need to sort by 'sort:index.text.relevance' because it's a boolean match (relevance is either 0 or 1)
248
		}
249
250
		$search->setConditions( $search->combine( '&&', $expr ) );
251
		$search->setSortations( $sortations );
252
		$search->setSlice( $start, $size );
253
254
		return $search;
255
	}
256
257
258
	/**
259
	 * Returns the products from the index filtered by the given criteria object.
260
	 *
261
	 * @param \Aimeos\MW\Criteria\Iface $filter Critera object which contains the filter conditions
262
	 * @param string[] $domains Domain names of items that are associated with the products and that should be fetched too
263
	 * @param integer &$total Parameter where the total number of found products will be stored in
264
	 * @return array Ordered list of product items implementing \Aimeos\MShop\Product\Item\Iface
265
	 * @since 2017.03
266
	 */
267
	public function getItems( \Aimeos\MW\Criteria\Iface $filter, array $domains = array( 'media', 'price', 'text' ), &$total = null )
268
	{
269
		return \Aimeos\MShop\Factory::createManager( $this->getContext(), 'index' )->searchItems( $filter, $domains, $total );
270
	}
271
272
273
	/**
274
	 * Returns an list of product text strings matched by the filter.
275
	 *
276
	 * @param \Aimeos\MW\Criteria\Iface $filter Critera object which contains the filter conditions
277
	 * @return array Associative list of the product ID as key and the product text as value
278
	 */
279
	public function getTextList( \Aimeos\MW\Criteria\Iface $filter )
280
	{
281
		return \Aimeos\MShop\Factory::createManager( $this->getContext(), 'index/text' )->searchTexts( $filter );
282
	}
283
284
285
	/**
286
	 * Returns the list of catalog IDs for the given catalog tree
287
	 *
288
	 * @param \Aimeos\MShop\Catalog\Item\Iface $item Catalog item with children
289
	 * @return array List of catalog IDs
290
	 */
291
	protected function getCatalogIdsFromTree( \Aimeos\MShop\Catalog\Item\Iface $item )
292
	{
293
		$list = array( $item->getId() );
294
295
		foreach( $item->getChildren() as $child ) {
296
			$list = array_merge( $list, $this->getCatalogIdsFromTree( $child ) );
297
		}
298
299
		return $list;
300
	}
301
302
303
	/**
304
	 * Validates the given IDs as integers
305
	 *
306
	 * @param array $ids List of IDs to validate
307
	 * @return array List of validated IDs
308
	 */
309
	protected function validateIds( array $ids )
310
	{
311
		$list = array();
312
313
		foreach( $ids as $id )
314
		{
315
			if( $id != '' ) {
316
				$list[] = (int) $id;
317
			}
318
		}
319
320
		return $ids;
321
	}
322
}
323