Passed
Push — master ( 1c1daf...484f92 )
by Aimeos
04:34
created

StandardTest   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 381
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 177
dl 0
loc 381
rs 9.84
c 0
b 0
f 0
wmc 32

23 Methods

Rating   Name   Duplication   Size   Complexity  
A setUpBeforeClass() 0 23 3
A testAggregate() 0 25 2
A testCreateItem() 0 3 1
A testCreateSearch() 0 3 1
A setUp() 0 5 1
A tearDown() 0 3 1
A testSaveItems() 0 8 1
A testDeleteItems() 0 3 1
A testGetResourceType() 0 10 1
A testGetSearchAttributes() 0 11 2
A testSaveItem() 0 24 1
A testSearchItemsBase() 0 14 2
A testSearchItems() 0 17 1
A testGetItem() 0 7 1
A testFindItem() 0 6 1
A testRebuildIndexCategorizedOnly() 0 13 1
A testCleanupIndex() 0 3 1
A testSearchItemsSub() 0 20 1
A testOptimize() 0 3 1
A testRebuildIndexAll() 0 20 1
A testRebuildIndexWithList() 0 16 1
A getCatalogSubDomainItems() 0 13 1
A getValue() 0 38 5
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2018
7
 */
8
9
10
namespace Aimeos\MShop\Index\Manager;
11
12
13
class StandardTest extends \PHPUnit\Framework\TestCase
14
{
15
	private static $products;
16
	private $context;
17
	private $object;
18
	private $editor = '';
19
20
21
	public static function setUpBeforeClass()
22
	{
23
		$context = \TestHelperMShop::getContext();
24
25
		$manager = new \Aimeos\MShop\Index\Manager\Standard( $context );
26
		$productManager = \Aimeos\MShop\Product\Manager\Factory::create( $context );
27
28
		$search = $productManager->createSearch();
29
		$conditions = array(
30
			$search->compare( '==', 'product.code', array( 'CNC', 'CNE' ) ),
31
			$search->compare( '==', 'product.editor', $context->getEditor() ),
32
		);
33
		$search->setConditions( $search->combine( '&&', $conditions ) );
34
		$result = $productManager->searchItems( $search, array( 'attribute', 'price', 'text', 'product' ) );
35
36
		if( count( $result ) !== 2 ) {
37
			throw new \RuntimeException( 'Products not available' );
38
		}
39
40
		foreach( $result as $item )
41
		{
42
			self::$products[$item->getCode()] = $item;
43
			$manager->saveItem( $item );
44
		}
45
	}
46
47
48
	protected function setUp()
49
	{
50
		$this->context = \TestHelperMShop::getContext();
51
		$this->editor = $this->context->getEditor();
52
		$this->object = new \Aimeos\MShop\Index\Manager\Standard( $this->context );
53
	}
54
55
56
	protected function tearDown()
57
	{
58
		unset( $this->object );
59
	}
60
61
62
	public function testCreateItem()
63
	{
64
		$this->assertInstanceOf( \Aimeos\MShop\Product\Item\Iface::class, $this->object->createItem() );
65
	}
66
67
68
	public function testCreateSearch()
69
	{
70
		$this->assertInstanceOf( \Aimeos\MW\Criteria\Iface::class, $this->object->createSearch() );
71
	}
72
73
74
	public function testAggregate()
75
	{
76
		$manager = \Aimeos\MShop::create( \TestHelperMShop::getContext(), 'attribute' );
77
78
		$search = $manager->createSearch();
79
		$expr = array(
80
			$search->compare( '==', 'attribute.code', 'white' ),
81
			$search->compare( '==', 'attribute.domain', 'product' ),
82
			$search->compare( '==', 'attribute.type', 'color' ),
83
		);
84
		$search->setConditions( $search->combine( '&&', $expr ) );
85
86
		$items = $manager->searchItems( $search );
87
88
		if( ( $item = reset( $items ) ) === false ) {
89
			throw new \RuntimeException( 'No attribute found' );
90
		}
91
92
93
		$search = $this->object->createSearch( true );
94
		$result = $this->object->aggregate( $search, 'index.attribute.id' );
95
96
		$this->assertEquals( 14, count( $result ) );
97
		$this->assertArrayHasKey( $item->getId(), $result );
98
		$this->assertEquals( 3, $result[$item->getId()] );
99
	}
100
101
102
	public function testDeleteItems()
103
	{
104
		$this->assertEquals( $this->object, $this->object->deleteItems( [-1] ) );
105
	}
106
107
108
	public function testFindItem()
109
	{
110
		$productManager = \Aimeos\MShop\Product\Manager\Factory::create( $this->context );
111
		$product = $productManager->findItem( 'CNE' );
112
113
		$this->assertEquals( $product, $this->object->findItem( 'CNE' ) );
114
	}
115
116
117
	public function testGetItem()
118
	{
119
		$productManager = \Aimeos\MShop\Product\Manager\Factory::create( $this->context );
120
		$product = $productManager->findItem( 'CNE' );
121
122
		$item = $this->object->getItem( $product->getId() );
123
		$this->assertEquals( $product, $item );
124
	}
125
126
127
	public function testGetResourceType()
128
	{
129
		$result = $this->object->getResourceType();
130
131
		$this->assertContains( 'index', $result );
132
		$this->assertContains( 'index/attribute', $result );
133
		$this->assertContains( 'index/supplier', $result );
134
		$this->assertContains( 'index/catalog', $result );
135
		$this->assertContains( 'index/price', $result );
136
		$this->assertContains( 'index/text', $result );
137
	}
138
139
140
	public function testGetSearchAttributes()
141
	{
142
		$attributes = $this->object->getSearchAttributes();
143
144
		foreach( $attributes as $attribute ) {
145
			$this->assertInstanceOf( \Aimeos\MW\Criteria\Attribute\Iface::class, $attribute );
146
		}
147
148
		$this->assertArrayHasKey( 'index.attribute.id', $attributes );
149
		$this->assertArrayHasKey( 'index.catalog.id', $attributes );
150
		$this->assertArrayHasKey( 'index.supplier.id', $attributes );
151
	}
152
153
154
	public function testSaveItem()
155
	{
156
		$item = self::$products['CNE'];
157
158
		$context = $this->context;
159
		$dbm = $context->getDatabaseManager();
160
		$siteId = $context->getLocale()->getSiteId();
161
162
		$sqlAttribute = 'SELECT COUNT(*) as count FROM "mshop_index_attribute" WHERE "siteid" = ? AND "prodid" = ?';
163
		$sqlCatalog = 'SELECT COUNT(*) as count FROM "mshop_index_catalog" WHERE "siteid" = ? AND "prodid" = ?';
164
		$sqlPrice = 'SELECT COUNT(*) as count FROM "mshop_index_price" WHERE "siteid" = ? AND "prodid" = ?';
165
		$sqlText = 'SELECT COUNT(*) as count FROM "mshop_index_text" WHERE "siteid" = ? AND "prodid" = ?';
166
167
		$this->object->saveItem( $item );
168
169
		$cntAttribute = $this->getValue( $dbm, $sqlAttribute, 'count', $siteId, $item->getId() );
170
		$cntCatalog = $this->getValue( $dbm, $sqlCatalog, 'count', $siteId, $item->getId() );
171
		$cntPrice = $this->getValue( $dbm, $sqlPrice, 'count', $siteId, $item->getId() );
172
		$cntText = $this->getValue( $dbm, $sqlText, 'count', $siteId, $item->getId() );
173
174
		$this->assertEquals( 6, $cntAttribute );
175
		$this->assertEquals( 5, $cntCatalog );
176
		$this->assertEquals( 1, $cntPrice );
177
		$this->assertEquals( 2, $cntText );
178
	}
179
180
181
	public function testSaveItems()
182
	{
183
		$result = $this->object->saveItems( self::$products );
184
		$expected = [
185
			self::$products['CNC']->getId() => self::$products['CNC'],
186
			self::$products['CNE']->getId() => self::$products['CNE']
187
		];
188
		$this->assertEquals( $expected, $result );
189
	}
190
191
192
	public function testSearchItems()
193
	{
194
		$total = 0;
195
		$search = $this->object->createSearch();
196
		$search->setSlice( 0, 1 );
197
198
		$expr = array(
199
			$search->compare( '!=', 'index.catalog.id', null ),
200
			$search->compare( '=~', 'product.label', 'Cafe Noire' ),
201
			$search->compare( '==', 'product.editor', $this->editor ),
202
		);
203
		$search->setConditions( $search->combine( '&&', $expr ) );
204
205
		$result = $this->object->searchItems( $search, [], $total );
206
207
		$this->assertEquals( 1, count( $result ) );
208
		$this->assertEquals( 2, $total );
209
	}
210
211
212
	public function testSearchItemsBase()
213
	{
214
		$search = $this->object->createSearch( true );
215
		$conditions = array(
216
			$search->compare( '!=', 'index.catalog.id', null ),
217
			$search->compare( '==', 'product.editor', $this->editor ),
218
			$search->getConditions()
219
		);
220
		$search->setConditions( $search->combine( '&&', $conditions ) );
221
		$products = $this->object->searchItems( $search );
222
		$this->assertEquals( 8, count( $products ) );
223
224
		foreach( $products as $itemId => $item ) {
225
			$this->assertEquals( $itemId, $item->getId() );
226
		}
227
	}
228
229
230
	public function testSearchItemsSub()
231
	{
232
		$total = 0;
233
		$search = $this->object->createSearch();
234
		$search->setSlice( 0, 1 );
235
236
		$expr = array(
237
			$search->compare( '!=', 'index.attribute.id', null ),
238
			$search->compare( '!=', 'index.catalog.id', null ),
239
			$search->compare( '!=', 'index.supplier.id', null ),
240
			$search->compare( '>=', $search->createFunction( 'index.price:value', ['EUR'] ), 0 ),
241
			$search->compare( '>=', $search->createFunction( 'index.text:name', ['de'] ), '' ),
242
			$search->compare( '==', 'product.editor', $this->editor )
243
		);
244
245
		$search->setConditions( $search->combine( '&&', $expr ) );
246
		$result = $this->object->searchItems( $search, [], $total );
247
248
		$this->assertEquals( 1, count( $result ) );
249
		$this->assertEquals( 2, $total );
250
	}
251
252
253
	public function testOptimize()
254
	{
255
		$this->object->optimize();
256
	}
257
258
259
	public function testCleanupIndex()
260
	{
261
		$this->object->cleanupIndex( '1970-01-01 00:00:00' );
262
	}
263
264
265
	public function testRebuildIndexAll()
266
	{
267
		$config = $this->context->getConfig();
268
269
		$manager = \Aimeos\MShop\Product\Manager\Factory::create( $this->context );
270
		$search = $manager->createSearch( true );
0 ignored issues
show
Unused Code introduced by
The assignment to $search is dead and can be removed.
Loading history...
271
272
		//build catalog with all products
273
		$config->set( 'mshop/index/manager/standard/index', 'all' );
274
		$this->object->cleanupIndex( date( 'Y-m-d H:i:s', time() + 1 ) )->rebuildIndex();
275
276
		$afterInsertAttr = $this->getCatalogSubDomainItems( 'index.attribute.id', 'attribute' );
277
		$afterInsertCat = $this->getCatalogSubDomainItems( 'index.catalog.id', 'catalog' );
278
279
		//restore index with categorized products only
280
		$config->set( 'mshop/index/manager/standard/index', 'categorized' );
281
		$this->object->cleanupIndex( date( 'Y-m-d H:i:s', time() + 1 ) )->rebuildIndex();
282
283
		$this->assertEquals( 13, count( $afterInsertAttr ) );
284
		$this->assertEquals( 9, count( $afterInsertCat ) );
285
	}
286
287
288
	public function testRebuildIndexWithList()
289
	{
290
		$manager = \Aimeos\MShop\Product\Manager\Factory::create( $this->context );
291
		$search = $manager->createSearch();
0 ignored issues
show
Unused Code introduced by
The assignment to $search is dead and can be removed.
Loading history...
292
293
		$search = $manager->createSearch();
294
		$search->setConditions( $search->compare( '==', 'product.code', array( 'CNE', 'CNC' ) ) );
295
		$items = $manager->searchItems( $search );
296
297
		$this->object->cleanupIndex( date( 'Y-m-d H:i:s', time() + 1 ) )->rebuildIndex( $items );
298
299
		$afterInsertAttr = $this->getCatalogSubDomainItems( 'index.attribute.id', 'attribute' );
300
		$afterInsertCat = $this->getCatalogSubDomainItems( 'index.catalog.id', 'catalog' );
301
302
		$this->assertEquals( 2, count( $afterInsertAttr ) );
303
		$this->assertEquals( 2, count( $afterInsertCat ) );
304
	}
305
306
307
	public function testRebuildIndexCategorizedOnly()
308
	{
309
		$context = $this->context;
310
		$config = $context->getConfig();
311
312
		$config->set( 'mshop/index/manager/standard/index', 'categorized' );
313
		$this->object->cleanupIndex( date( 'Y-m-d H:i:s', time() + 1 ) )->rebuildIndex();
314
315
		$afterInsertAttr = $this->getCatalogSubDomainItems( 'index.attribute.id', 'attribute' );
316
		$afterInsertCat = $this->getCatalogSubDomainItems( 'index.catalog.id', 'catalog' );
317
318
		$this->assertEquals( 7, count( $afterInsertAttr ) );
319
		$this->assertEquals( 9, count( $afterInsertCat ) );
320
	}
321
322
323
	/**
324
	 * Returns value of a catalog_index column.
325
	 *
326
	 * @param \Aimeos\MW\DB\Manager\Iface $dbm Database Manager for connection
327
	 * @param string $sql Specified db query to find only one value
328
	 * @param string $column Column where to search
329
	 * @param string $siteId Siteid of the db entry
330
	 * @param string $productId Product id
331
	 * @return string $value Value returned for specified sql statement
332
	 * @throws \Exception If column not available or error during a connection to db
333
	 */
334
	protected function getValue( \Aimeos\MW\DB\Manager\Iface $dbm, $sql, $column, $siteId, $productId )
335
	{
336
		$config = $this->context->getConfig();
337
338
		if( $config->get( 'resource/db-product' ) === null ) {
339
			$dbname = $config->get( 'resource/default', 'db' );
340
		} else {
341
			$dbname = 'db-product';
342
		}
343
344
		$conn = $dbm->acquire( $dbname );
345
346
		try
347
		{
348
			$stmt = $conn->create( $sql );
349
			$stmt->bind( 1, $siteId, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
350
			$stmt->bind( 2, $productId, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
351
			$result = $stmt->execute();
352
353
			if( ( $row = $result->fetch() ) === false ) {
354
				throw new \RuntimeException( 'No rows available' );
355
			}
356
357
			if( !isset( $row[$column] ) ) {
358
				throw new \RuntimeException( sprintf( 'Column "%1$s" not available for "%2$s"', $column, $sql ) );
359
			}
360
361
			$value = $row[$column];
362
363
			$dbm->release( $conn, $dbname );
364
		}
365
		catch( \Exception $e )
366
		{
367
			$dbm->release( $conn, $dbname );
368
			throw $e;
369
		}
370
371
		return $value;
372
	}
373
374
375
	/**
376
	 * Gets product items of index subdomains specified by the key.
377
	 *
378
	 * @param string $key Key for searchItems
379
	 * @param string $domain Subdomain of index manager
380
	 */
381
	protected function getCatalogSubDomainItems( $key, $domain )
382
	{
383
		$subIndex = $this->object->getSubManager( $domain );
384
		$search = $subIndex->createSearch();
385
386
		$expr = array(
387
			$search->compare( '!=', $key, null ),
388
			$search->compare( '==', 'product.editor', $this->editor )
389
		);
390
391
		$search->setConditions( $search->combine( '&&', $expr ) );
392
393
		return $subIndex->searchItems( $search );
394
	}
395
396
}
397