Passed
Push — master ( ba6e3e...c663a5 )
by Aimeos
14:17
created

StandardTest::testGet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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