Passed
Push — master ( d6fe7b...95ecc1 )
by Aimeos
04:33
created

StandardTest   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 904
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 59
eloc 507
dl 0
loc 904
rs 4.08
c 5
b 0
f 1

45 Methods

Rating   Name   Duplication   Size   Complexity  
A testAggregateMonth() 0 8 1
A testAggregateAvgMultiple() 0 11 1
A testAggregateSum() 0 7 1
A testClear() 0 3 1
A tearDown() 0 3 1
A testAggregateAddress() 0 8 1
A setUp() 0 5 1
A testAggregateAddressMultiple() 0 7 1
A testAggregateMultiple() 0 7 1
A testAggregateTimes() 0 8 1
A testAggregate() 0 8 1
A testAggregateSumMultiple() 0 11 1
A testAggregateAvg() 0 7 1
A testDelete() 0 3 1
A testSaveStatusUpdatePayment() 0 46 3
A testGetSubManagerInvalidName() 0 4 1
A testSearchRef() 0 15 1
A testSaveStatusUpdateDelivery() 0 46 3
B testSearch() 0 139 1
A testCreateService() 0 3 1
A testSaveBundles() 0 30 2
B testSaveUpdateDelete() 0 79 1
A testCreateStatus() 0 3 1
A getOrderItem() 0 10 1
A testCreateProductAttribute() 0 3 1
A testSaveProduct() 0 17 1
A testCreateServiceTransaction() 0 3 1
A testFilter() 0 3 1
A testSearchTotal() 0 16 2
A testSaveExisting() 0 23 3
A testCreate() 0 3 1
A testFilterSite() 0 4 1
A testCreateAddress() 0 3 1
A testSave() 0 49 5
A testGet() 0 13 1
A testGetSubManager() 0 19 1
A testCreateServiceAttribute() 0 3 1
A getBasket() 0 22 3
A testLoadSaveCoupons() 0 33 1
A testFilterDefault() 0 10 1
A testCreateCoupon() 0 3 1
A testCreateProduct() 0 3 1
A testSaveService() 0 17 1
A testSaveStatus() 0 13 1
A testSaveAddress() 0 17 1

How to fix   Complexity   

Complex Class

Complex classes like StandardTest 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 StandardTest, and based on these observations, apply Extract Interface, too.

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\Order\Manager;
11
12
13
class StandardTest extends \PHPUnit\Framework\TestCase
14
{
15
	private $context;
16
	private $object;
17
	private $editor = '';
18
19
20
	protected function setUp() : void
21
	{
22
		$this->context = \TestHelper::context();
23
		$this->editor = $this->context->editor();
24
		$this->object = new \Aimeos\MShop\Order\Manager\Standard( $this->context );
25
	}
26
27
28
	protected function tearDown() : void
29
	{
30
		unset( $this->object );
31
	}
32
33
34
	public function testAggregate()
35
	{
36
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
37
		$result = $this->object->aggregate( $search, 'order.channel' );
38
39
		$this->assertEquals( 2, count( $result ) );
40
		$this->assertArrayHasKey( 'web', $result );
41
		$this->assertEquals( 3, $result->get( 'web' ) );
42
	}
43
44
45
	public function testAggregateMultiple()
46
	{
47
		$cols = ['order.channel', 'order.statuspayment'];
48
		$search = $this->object->filter()->add( ['order.editor' => 'core'] )->order( $cols );
49
		$result = $this->object->aggregate( $search, $cols );
50
51
		$this->assertEquals( ['phone' => [6 => 1], 'web' => [5 => 1, 6 => 2]], $result->toArray() );
52
	}
53
54
55
	public function testAggregateAvg()
56
	{
57
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
58
		$result = $this->object->aggregate( $search, 'order.cmonth', 'order.price', 'avg' );
59
60
		$this->assertEquals( 1, count( $result ) );
61
		$this->assertEquals( '784.75', round( $result->first(), 2 ) );
62
	}
63
64
65
	public function testAggregateAvgMultiple()
66
	{
67
		$cols = ['order.cmonth', 'order.statuspayment'];
68
		$search = $this->object->filter()->add( ['order.editor' => 'core'] )->order( $cols );
69
		$result = $this->object->aggregate( $search, $cols, 'order.price', 'avg' );
70
71
		$this->assertEquals( 1, count( $result ) );
72
		$this->assertArrayHasKey( 5, $result->first() );
73
		$this->assertArrayHasKey( 6, $result->first() );
74
		$this->assertEquals( '13.50', round( $result->first()[5], 2 ) );
75
		$this->assertEquals( '1041.83', round( $result->first()[6], 2 ) );
76
	}
77
78
79
	public function testAggregateSum()
80
	{
81
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
82
		$result = $this->object->aggregate( $search, 'order.cmonth', 'order.price', 'sum' );
83
84
		$this->assertEquals( 1, count( $result ) );
85
		$this->assertEquals( '3139.00', $result->first() );
86
	}
87
88
89
	public function testAggregateSumMultiple()
90
	{
91
		$cols = ['order.cmonth', 'order.statuspayment'];
92
		$search = $this->object->filter()->add( ['order.editor' => 'core'] )->order( $cols );
93
		$result = $this->object->aggregate( $search, $cols, 'order.price', 'sum' );
94
95
		$this->assertEquals( 1, count( $result ) );
96
		$this->assertArrayHasKey( 5, $result->first() );
97
		$this->assertArrayHasKey( 6, $result->first() );
98
		$this->assertEquals( '13.50', round( $result->first()[5], 2 ) );
99
		$this->assertEquals( '3125.5', round( $result->first()[6], 2 ) );
100
	}
101
102
103
	public function testAggregateTimes()
104
	{
105
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
106
		$search->setSortations( array( $search->sort( '-', 'order.cdate' ) ) );
107
		$result = $this->object->aggregate( $search, 'order.cmonth' )->toArray();
108
109
		$this->assertEquals( 1, count( $result ) );
110
		$this->assertEquals( 4, reset( $result ) );
111
	}
112
113
114
	public function testAggregateAddress()
115
	{
116
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
117
		$result = $this->object->aggregate( $search, 'order.address.countryid' )->toArray();
118
119
		$this->assertEquals( 1, count( $result ) );
120
		$this->assertArrayHasKey( 'DE', $result );
121
		$this->assertEquals( 4, reset( $result ) );
122
	}
123
124
125
	public function testAggregateAddressMultiple()
126
	{
127
		$cols = ['order.address.countryid', 'order.statuspayment'];
128
		$search = $this->object->filter()->add( ['order.editor' => 'core'] )->order( $cols );
129
		$result = $this->object->aggregate( $search, $cols )->toArray();
130
131
		$this->assertEquals( ['DE' => [5 => 1, 6 => 3]], $result );
132
	}
133
134
135
	public function testAggregateMonth()
136
	{
137
		$search = $this->object->filter()->add( ['order.editor' => 'core'] );
138
		$result = $this->object->aggregate( $search, 'order.channel' )->toArray();
139
140
		$this->assertEquals( 2, count( $result ) );
141
		$this->assertArrayHasKey( 'web', $result );
142
		$this->assertEquals( 3, $result['web'] );
143
	}
144
145
146
	public function testClear()
147
	{
148
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->clear( [-1] ) );
149
	}
150
151
152
	public function testDelete()
153
	{
154
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->delete( [-1] ) );
155
	}
156
157
158
	public function testCreate()
159
	{
160
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Iface::class, $this->object->create() );
161
	}
162
163
164
	public function testCreateAddress()
165
	{
166
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Address\Iface::class, $this->object->createAddress() );
167
	}
168
169
170
	public function testCreateCoupon()
171
	{
172
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Coupon\Iface::class, $this->object->createCoupon() );
173
	}
174
175
176
	public function testCreateProduct()
177
	{
178
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Product\Iface::class, $this->object->createProduct() );
179
	}
180
181
182
	public function testCreateProductAttribute()
183
	{
184
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Product\Attribute\Iface::class, $this->object->createProductAttribute() );
185
	}
186
187
188
	public function testCreateService()
189
	{
190
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Service\Iface::class, $this->object->createService() );
191
	}
192
193
194
	public function testCreateServiceAttribute()
195
	{
196
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Service\Attribute\Iface::class, $this->object->createServiceAttribute() );
197
	}
198
199
200
	public function testCreateServiceTransaction()
201
	{
202
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Service\Transaction\Iface::class, $this->object->createServiceTransaction() );
203
	}
204
205
206
	public function testCreateStatus()
207
	{
208
		$this->assertInstanceOf( \Aimeos\MShop\Order\Item\Status\Iface::class, $this->object->createStatus() );
209
	}
210
211
212
	public function testGet()
213
	{
214
		$search = $this->object->filter()->slice( 0, 1 )
215
			->add( ['order.price' => '672.00', 'order.editor' => $this->editor] );
216
217
		$item = $this->object->search( $search )->first( new \RuntimeException( 'No order item found' ) );
218
219
		$actual = $this->object->get( $item->getId() );
220
221
		$this->assertEquals( $item, $actual );
222
		$this->assertEquals( '32.00', $item->getPrice()->getCosts() );
223
		$this->assertEquals( '5.00', $item->getPrice()->getRebate() );
224
		$this->assertEquals( '112.4034', $item->getPrice()->getTaxValue() );
225
	}
226
227
228
	public function testSaveUpdateDelete()
229
	{
230
		$search = $this->object->filter()->slice( 0, 1 )
231
			->add( ['order.channel' => 'phone', 'order.editor' => $this->editor] );
232
233
		$item = $this->object->search( $search )->first( new \RuntimeException( 'No order item found' ) );
234
235
		$item->setId( null );
236
		$resultSaved = $this->object->save( $item );
237
		$itemSaved = $this->object->get( $item->getId() );
238
239
		$itemExp = clone $itemSaved;
240
		$itemExp->setChannel( 'web' );
241
		$resultUpd = $this->object->save( $itemExp );
242
		$itemUpd = $this->object->get( $itemExp->getId() );
243
244
		$this->object->delete( $itemSaved->getId() );
245
246
247
		$itemPrice = $item->getPrice();
248
		$itemSavedPrice = $itemSaved->getPrice();
249
250
		$this->assertTrue( $item->getId() !== null );
251
		$this->assertEquals( $item->getId(), $itemSaved->getId() );
252
		$this->assertEquals( $item->getSiteId(), $itemSaved->getSiteId() );
253
		$this->assertEquals( $item->getChannel(), $itemSaved->getChannel() );
254
		$this->assertEquals( $item->getDatePayment(), $itemSaved->getDatePayment() );
255
		$this->assertEquals( $item->getDateDelivery(), $itemSaved->getDateDelivery() );
256
		$this->assertEquals( $item->getStatusPayment(), $itemSaved->getStatusPayment() );
257
		$this->assertEquals( $item->getStatusDelivery(), $itemSaved->getStatusDelivery() );
258
		$this->assertEquals( $item->getInvoiceNumber(), $itemSaved->getInvoiceNumber() );
259
		$this->assertEquals( $item->getRelatedId(), $itemSaved->getRelatedId() );
260
		$this->assertEquals( $item->getCustomerId(), $itemSaved->getCustomerId() );
261
		$this->assertEquals( $item->locale()->getLanguageId(), $itemSaved->locale()->getLanguageId() );
262
		$this->assertEquals( $item->getCustomerReference(), $itemSaved->getCustomerReference() );
263
		$this->assertEquals( $item->getComment(), $itemSaved->getComment() );
264
		$this->assertEquals( $item->getSiteCode(), $itemSaved->getSiteCode() );
265
		$this->assertEquals( $itemPrice->getValue(), $itemSavedPrice->getValue() );
266
		$this->assertEquals( $itemPrice->getCosts(), $itemSavedPrice->getCosts() );
267
		$this->assertEquals( $itemPrice->getRebate(), $itemSavedPrice->getRebate() );
268
		$this->assertEquals( $itemPrice->getTaxValue(), $itemSavedPrice->getTaxValue() );
269
		$this->assertEquals( $itemPrice->getCurrencyId(), $itemSavedPrice->getCurrencyId() );
270
271
		$this->assertEquals( $this->editor, $itemSaved->editor() );
272
		$this->assertMatchesRegularExpression( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemSaved->getTimeCreated() );
273
		$this->assertMatchesRegularExpression( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemSaved->getTimeModified() );
274
275
		$itemExpPrice = $itemExp->getPrice();
276
		$itemUpdPrice = $itemUpd->getPrice();
277
278
		$this->assertEquals( $itemExp->getId(), $itemUpd->getId() );
279
		$this->assertEquals( $itemExp->getSiteId(), $itemUpd->getSiteId() );
280
		$this->assertEquals( $itemExp->getChannel(), $itemUpd->getChannel() );
281
		$this->assertEquals( $itemExp->getDatePayment(), $itemUpd->getDatePayment() );
282
		$this->assertEquals( $itemExp->getDateDelivery(), $itemUpd->getDateDelivery() );
283
		$this->assertEquals( $itemExp->getStatusPayment(), $itemUpd->getStatusPayment() );
284
		$this->assertEquals( $itemExp->getStatusDelivery(), $itemUpd->getStatusDelivery() );
285
		$this->assertEquals( $itemExp->getInvoiceNumber(), $itemUpd->getInvoiceNumber() );
286
		$this->assertEquals( $itemExp->getRelatedId(), $itemUpd->getRelatedId() );
287
		$this->assertEquals( $itemExp->getCustomerId(), $itemUpd->getCustomerId() );
288
		$this->assertEquals( $itemExp->locale()->getLanguageId(), $itemUpd->locale()->getLanguageId() );
289
		$this->assertEquals( $itemExp->getCustomerReference(), $itemUpd->getCustomerReference() );
290
		$this->assertEquals( $itemExp->getComment(), $itemUpd->getComment() );
291
		$this->assertEquals( $itemExp->getSiteCode(), $itemUpd->getSiteCode() );
292
		$this->assertEquals( $itemExpPrice->getValue(), $itemUpdPrice->getValue() );
293
		$this->assertEquals( $itemExpPrice->getCosts(), $itemUpdPrice->getCosts() );
294
		$this->assertEquals( $itemExpPrice->getRebate(), $itemUpdPrice->getRebate() );
295
		$this->assertEquals( $itemExpPrice->getTaxValue(), $itemUpdPrice->getTaxValue() );
296
		$this->assertEquals( $itemExpPrice->getCurrencyId(), $itemUpdPrice->getCurrencyId() );
297
298
		$this->assertEquals( $this->editor, $itemUpd->editor() );
299
		$this->assertEquals( $itemExp->getTimeCreated(), $itemUpd->getTimeCreated() );
300
		$this->assertMatchesRegularExpression( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemUpd->getTimeModified() );
301
302
		$this->assertInstanceOf( \Aimeos\MShop\Common\Item\Iface::class, $resultSaved );
303
		$this->assertInstanceOf( \Aimeos\MShop\Common\Item\Iface::class, $resultUpd );
304
305
		$this->expectException( \Aimeos\MShop\Exception::class );
306
		$this->object->get( $itemSaved->getId() );
307
	}
308
309
310
	public function testSaveStatusUpdatePayment()
311
	{
312
		$statusManager = \Aimeos\MShop::create( $this->context, 'order/status' );
313
314
		$search = $this->object->filter();
315
		$conditions = array(
316
			$search->compare( '==', 'order.channel', 'phone' ),
317
			$search->compare( '==', 'order.editor', $this->editor )
318
		);
319
		$search->setConditions( $search->and( $conditions ) );
320
		$results = $this->object->search( $search )->toArray();
321
322
		if( ( $item = reset( $results ) ) === false ) {
323
			throw new \RuntimeException( 'No order item found.' );
324
		}
325
326
		$item->setId( null );
327
		$this->object->save( $item );
328
329
330
		$search = $statusManager->filter();
331
		$search->setConditions( $search->compare( '==', 'order.status.parentid', $item->getId() ) );
332
		$results = $statusManager->search( $search )->toArray();
333
334
		$this->object->delete( $item->getId() );
335
336
		$this->assertEquals( 0, count( $results ) );
337
338
339
		$item->setId( null );
340
		$item->setStatusPayment( \Aimeos\MShop\Order\Item\Base::PAY_CANCELED );
341
		$this->object->save( $item );
342
343
		$search = $statusManager->filter();
344
		$search->setConditions( $search->compare( '==', 'order.status.parentid', $item->getId() ) );
345
		$results = $statusManager->search( $search )->toArray();
346
347
		$this->object->delete( $item->getId() );
348
349
		if( ( $statusItem = reset( $results ) ) === false ) {
350
			throw new \RuntimeException( 'No status item found' );
351
		}
352
353
		$this->assertEquals( 1, count( $results ) );
354
		$this->assertEquals( \Aimeos\MShop\Order\Item\Status\Base::STATUS_PAYMENT, $statusItem->getType() );
355
		$this->assertEquals( \Aimeos\MShop\Order\Item\Base::PAY_CANCELED, $statusItem->getValue() );
356
	}
357
358
359
	public function testSaveStatusUpdateDelivery()
360
	{
361
		$statusManager = \Aimeos\MShop::create( $this->context, 'order/status' );
362
363
		$search = $this->object->filter();
364
		$conditions = array(
365
			$search->compare( '==', 'order.channel', 'phone' ),
366
			$search->compare( '==', 'order.editor', $this->editor )
367
		);
368
		$search->setConditions( $search->and( $conditions ) );
369
		$results = $this->object->search( $search )->toArray();
370
371
		if( ( $item = reset( $results ) ) === false ) {
372
			throw new \RuntimeException( 'No order item found.' );
373
		}
374
375
		$item->setId( null );
376
		$this->object->save( $item );
377
378
379
		$search = $statusManager->filter();
380
		$search->setConditions( $search->compare( '==', 'order.status.parentid', $item->getId() ) );
381
		$results = $statusManager->search( $search )->toArray();
382
383
		$this->object->delete( $item->getId() );
384
385
		$this->assertEquals( 0, count( $results ) );
386
387
388
		$item->setId( null );
389
		$item->setStatusDelivery( \Aimeos\MShop\Order\Item\Base::STAT_LOST );
390
		$this->object->save( $item );
391
392
		$search = $statusManager->filter();
393
		$search->setConditions( $search->compare( '==', 'order.status.parentid', $item->getId() ) );
394
		$results = $statusManager->search( $search )->toArray();
395
396
		$this->object->delete( $item->getId() );
397
398
		if( ( $statusItem = reset( $results ) ) === false ) {
399
			throw new \RuntimeException( 'No status item found' );
400
		}
401
402
		$this->assertEquals( 1, count( $results ) );
403
		$this->assertEquals( \Aimeos\MShop\Order\Item\Status\Base::STATUS_DELIVERY, $statusItem->getType() );
404
		$this->assertEquals( \Aimeos\MShop\Order\Item\Base::STAT_LOST, $statusItem->getValue() );
405
	}
406
407
408
	public function testFilter()
409
	{
410
		$this->assertInstanceOf( \Aimeos\Base\Criteria\Iface::class, $this->object->filter() );
411
	}
412
413
414
	public function testFilterDefault()
415
	{
416
		$search = $this->object->filter( true );
417
418
		$this->assertInstanceOf( \Aimeos\Base\Criteria\Iface::class, $search );
419
		$this->assertInstanceOf( \Aimeos\Base\Criteria\Expression\Combine\Iface::class, $search->getConditions() );
420
421
		$list = $search->getConditions()->getExpressions();
422
		$this->assertArrayHasKey( 0, $list );
423
		$this->assertInstanceOf( \Aimeos\Base\Criteria\Expression\Combine\Iface::class, $list[0] );
424
	}
425
426
427
	public function testFilterSite()
428
	{
429
		$result = $this->object->filter( false, true );
430
		$this->assertInstanceOf( \Aimeos\Base\Criteria\Expression\Combine\Iface::class, $result->getConditions() );
431
	}
432
433
434
	public function testSearch()
435
	{
436
		$siteid = $this->context->locale()->getSiteId();
437
438
		$total = 0;
439
		$search = $this->object->filter();
440
		$funcStatus = $search->make( 'order:status', ['typestatus', 'shipped'] );
441
442
		$expr = [];
443
		$expr[] = $search->compare( '!=', 'order.id', null );
444
		$expr[] = $search->compare( '==', 'order.siteid', $siteid );
445
		$expr[] = $search->compare( '==', 'order.channel', 'web' );
446
		$expr[] = $search->compare( '==', 'order.invoiceno', 'UINV-001' );
447
		$expr[] = $search->compare( '==', 'order.datepayment', '2008-02-15 12:34:56' );
448
		$expr[] = $search->compare( '==', 'order.datedelivery', null );
449
		$expr[] = $search->compare( '==', 'order.statuspayment', \Aimeos\MShop\Order\Item\Base::PAY_RECEIVED );
450
		$expr[] = $search->compare( '==', 'order.statusdelivery', 4 );
451
		$expr[] = $search->compare( '==', 'order.relatedid', '' );
452
		$expr[] = $search->compare( '==', 'order.sitecode', 'unittest' );
453
		$expr[] = $search->compare( '>=', 'order.customerid', '' );
454
		$expr[] = $search->compare( '==', 'order.languageid', 'de' );
455
		$expr[] = $search->compare( '==', 'order.currencyid', 'EUR' );
456
		$expr[] = $search->compare( '==', 'order.price', '53.50' );
457
		$expr[] = $search->compare( '==', 'order.costs', '1.50' );
458
		$expr[] = $search->compare( '==', 'order.rebate', '14.50' );
459
		$expr[] = $search->compare( '~=', 'order.comment', 'This is a comment' );
460
		$expr[] = $search->compare( '>=', 'order.mtime', '1970-01-01 00:00:00' );
461
		$expr[] = $search->compare( '>=', 'order.ctime', '1970-01-01 00:00:00' );
462
		$expr[] = $search->compare( '==', 'order.editor', $this->editor );
463
		$expr[] = $search->compare( '==', $funcStatus, 1 );
464
465
		$expr[] = $search->compare( '!=', 'order.status.id', null );
466
		$expr[] = $search->compare( '==', 'order.status.siteid', $siteid );
467
		$expr[] = $search->compare( '!=', 'order.status.parentid', null );
468
		$expr[] = $search->compare( '>=', 'order.status.type', 'typestatus' );
469
		$expr[] = $search->compare( '==', 'order.status.value', 'shipped' );
470
		$expr[] = $search->compare( '>=', 'order.status.mtime', '1970-01-01 00:00:00' );
471
		$expr[] = $search->compare( '>=', 'order.status.ctime', '1970-01-01 00:00:00' );
472
		$expr[] = $search->compare( '==', 'order.status.editor', $this->editor );
473
474
		$expr[] = $search->compare( '!=', 'order.address.id', null );
475
		$expr[] = $search->compare( '==', 'order.address.siteid', $siteid );
476
		$expr[] = $search->compare( '!=', 'order.address.parentid', null );
477
		$expr[] = $search->compare( '==', 'order.address.type', 'payment' );
478
		$expr[] = $search->compare( '==', 'order.address.company', 'Example company' );
479
		$expr[] = $search->compare( '==', 'order.address.vatid', 'DE999999999' );
480
		$expr[] = $search->compare( '==', 'order.address.salutation', 'mr' );
481
		$expr[] = $search->compare( '==', 'order.address.title', '' );
482
		$expr[] = $search->compare( '==', 'order.address.firstname', 'Our' );
483
		$expr[] = $search->compare( '==', 'order.address.lastname', 'Unittest' );
484
		$expr[] = $search->compare( '==', 'order.address.address1', 'Durchschnitt' );
485
		$expr[] = $search->compare( '==', 'order.address.address2', '1' );
486
		$expr[] = $search->compare( '==', 'order.address.address3', '' );
487
		$expr[] = $search->compare( '==', 'order.address.postal', '20146' );
488
		$expr[] = $search->compare( '==', 'order.address.city', 'Hamburg' );
489
		$expr[] = $search->compare( '==', 'order.address.state', 'Hamburg' );
490
		$expr[] = $search->compare( '==', 'order.address.countryid', 'DE' );
491
		$expr[] = $search->compare( '==', 'order.address.languageid', 'de' );
492
		$expr[] = $search->compare( '==', 'order.address.telephone', '055544332211' );
493
		$expr[] = $search->compare( '==', 'order.address.telefax', '055544332212' );
494
		$expr[] = $search->compare( '==', 'order.address.mobile', '055544332213' );
495
		$expr[] = $search->compare( '==', 'order.address.email', '[email protected]' );
496
		$expr[] = $search->compare( '==', 'order.address.website', 'www.example.net' );
497
		$expr[] = $search->compare( '>=', 'order.address.mtime', '1970-01-01 00:00:00' );
498
		$expr[] = $search->compare( '>=', 'order.address.ctime', '1970-01-01 00:00:00' );
499
		$expr[] = $search->compare( '==', 'order.address.editor', $this->editor );
500
501
		$expr[] = $search->compare( '!=', 'order.coupon.id', null );
502
		$expr[] = $search->compare( '==', 'order.coupon.siteid', $siteid );
503
		$expr[] = $search->compare( '!=', 'order.coupon.parentid', null );
504
		$expr[] = $search->compare( '!=', 'order.coupon.productid', null );
505
		$expr[] = $search->compare( '==', 'order.coupon.code', 'OPQR' );
506
		$expr[] = $search->compare( '>=', 'order.coupon.mtime', '1970-01-01 00:00:00' );
507
		$expr[] = $search->compare( '>=', 'order.coupon.ctime', '1970-01-01 00:00:00' );
508
		$expr[] = $search->compare( '>=', 'order.coupon.editor', '' );
509
510
		$expr[] = $search->compare( '!=', 'order.product.id', null );
511
		$expr[] = $search->compare( '==', 'order.product.siteid', $siteid );
512
		$expr[] = $search->compare( '!=', 'order.product.parentid', null );
513
		$expr[] = $search->compare( '!=', 'order.product.productid', null );
514
		$expr[] = $search->compare( '==', 'order.product.prodcode', 'CNE' );
515
		$expr[] = $search->compare( '==', 'order.product.vendor', 'Test vendor' );
516
		$expr[] = $search->compare( '==', 'order.product.name', 'Cafe Noire Expresso' );
517
		$expr[] = $search->compare( '==', 'order.product.mediaurl', 'somewhere/thump1.jpg' );
518
		$expr[] = $search->compare( '==', 'order.product.quantity', 9 );
519
		$expr[] = $search->compare( '==', 'order.product.price', '4.50' );
520
		$expr[] = $search->compare( '==', 'order.product.costs', '0.00' );
521
		$expr[] = $search->compare( '==', 'order.product.rebate', '0.00' );
522
		$expr[] = $search->compare( '=~', 'order.product.taxrates', '{' );
523
		$expr[] = $search->compare( '==', 'order.product.flags', 0 );
524
		$expr[] = $search->compare( '==', 'order.product.position', 1 );
525
		$expr[] = $search->compare( '==', 'order.product.statuspayment', 5 );
526
		$expr[] = $search->compare( '==', 'order.product.statusdelivery', 1 );
527
		$expr[] = $search->compare( '>=', 'order.product.mtime', '1970-01-01 00:00:00' );
528
		$expr[] = $search->compare( '>=', 'order.product.ctime', '1970-01-01 00:00:00' );
529
		$expr[] = $search->compare( '==', 'order.product.editor', $this->editor );
530
531
		$expr[] = $search->compare( '!=', 'order.product.attribute.id', null );
532
		$expr[] = $search->compare( '==', 'order.product.attribute.siteid', $siteid );
533
		$expr[] = $search->compare( '!=', 'order.product.attribute.parentid', null );
534
		$expr[] = $search->compare( '==', 'order.product.attribute.code', 'width' );
535
		$expr[] = $search->compare( '==', 'order.product.attribute.value', '33' );
536
		$expr[] = $search->compare( '==', 'order.product.attribute.name', '33' );
537
		$expr[] = $search->compare( '==', 'order.product.attribute.quantity', 1 );
538
		$expr[] = $search->compare( '>=', 'order.product.attribute.mtime', '1970-01-01 00:00:00' );
539
		$expr[] = $search->compare( '>=', 'order.product.attribute.ctime', '1970-01-01 00:00:00' );
540
		$expr[] = $search->compare( '==', 'order.product.attribute.editor', $this->editor );
541
542
		$expr[] = $search->compare( '!=', 'order.service.id', null );
543
		$expr[] = $search->compare( '==', 'order.service.siteid', $siteid );
544
		$expr[] = $search->compare( '!=', 'order.service.parentid', null );
545
		$expr[] = $search->compare( '==', 'order.service.type', 'payment' );
546
		$expr[] = $search->compare( '==', 'order.service.code', 'unitpaymentcode' );
547
		$expr[] = $search->compare( '==', 'order.service.name', 'unitpaymentcode' );
548
		$expr[] = $search->compare( '==', 'order.service.price', '0.00' );
549
		$expr[] = $search->compare( '==', 'order.service.costs', '0.00' );
550
		$expr[] = $search->compare( '==', 'order.service.rebate', '0.00' );
551
		$expr[] = $search->compare( '=~', 'order.service.taxrates', '{' );
552
		$expr[] = $search->compare( '>=', 'order.service.mtime', '1970-01-01 00:00:00' );
553
		$expr[] = $search->compare( '>=', 'order.service.ctime', '1970-01-01 00:00:00' );
554
		$expr[] = $search->compare( '==', 'order.service.editor', $this->editor );
555
556
		$expr[] = $search->compare( '!=', 'order.service.attribute.id', null );
557
		$expr[] = $search->compare( '==', 'order.service.attribute.siteid', $siteid );
558
		$expr[] = $search->compare( '!=', 'order.service.attribute.parentid', null );
559
		$expr[] = $search->compare( '==', 'order.service.attribute.code', 'NAME' );
560
		$expr[] = $search->compare( '==', 'order.service.attribute.value', '"CreditCard"' );
561
		$expr[] = $search->compare( '==', 'order.service.attribute.quantity', 1 );
562
		$expr[] = $search->compare( '>=', 'order.service.attribute.mtime', '1970-01-01 00:00:00' );
563
		$expr[] = $search->compare( '>=', 'order.service.attribute.ctime', '1970-01-01 00:00:00' );
564
		$expr[] = $search->compare( '==', 'order.service.attribute.editor', $this->editor );
565
566
567
568
		$search->setConditions( $search->and( $expr ) );
569
		$result = $this->object->search( $search, [], $total )->toArray();
570
571
		$this->assertEquals( 1, count( $result ) );
572
		$this->assertEquals( 1, $total );
573
	}
574
575
576
	public function testSearchTotal()
577
	{
578
		$total = 0;
579
		$search = $this->object->filter()->slice( 0, 1 );
580
		$conditions = array(
581
			$search->compare( '==', 'order.statuspayment', \Aimeos\MShop\Order\Item\Base::PAY_RECEIVED ),
582
			$search->compare( '==', 'order.editor', $this->editor )
583
		);
584
		$search->setConditions( $search->and( $conditions ) );
585
		$items = $this->object->search( $search, [], $total )->toArray();
586
587
		$this->assertEquals( 1, count( $items ) );
588
		$this->assertEquals( 3, $total );
589
590
		foreach( $items as $itemId => $item ) {
591
			$this->assertEquals( $itemId, $item->getId() );
592
		}
593
	}
594
595
596
	public function testSearchRef()
597
	{
598
		$total = 0;
599
		$search = $this->object->filter()->slice( 0, 1 );
600
		$conditions = array(
601
			$search->compare( '==', 'order.datepayment', '2008-02-15 12:34:56' ),
602
			$search->compare( '==', 'order.editor', $this->editor )
603
		);
604
		$search->setConditions( $search->and( $conditions ) );
605
		$item = $this->object->search( $search, ['order/address', 'order/coupon', 'order/product', 'order/service'], $total )->first();
606
607
		$this->assertEquals( 2, count( $item->getAddresses() ) );
608
		$this->assertEquals( 2, count( $item->getCoupons() ) );
609
		$this->assertEquals( 4, count( $item->getProducts() ) );
610
		$this->assertEquals( 2, count( $item->getServices() ) );
611
	}
612
613
614
	public function testGetSubManager()
615
	{
616
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'address' ) );
617
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'address', 'Standard' ) );
618
619
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'coupon' ) );
620
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'coupon', 'Standard' ) );
621
622
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'product' ) );
623
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'product', 'Standard' ) );
624
625
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'service' ) );
626
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'service', 'Standard' ) );
627
628
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'status' ) );
629
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->getSubManager( 'status', 'Standard' ) );
630
631
		$this->expectException( \LogicException::class );
632
		$this->object->getSubManager( 'unknown' );
633
	}
634
635
636
	public function testGetSubManagerInvalidName()
637
	{
638
		$this->expectException( \LogicException::class );
639
		$this->object->getSubManager( 'status', 'unknown' );
640
	}
641
642
643
	public function testSave()
644
	{
645
		$item = $this->getOrderItem();
646
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
647
648
		$basket = $this->getBasket( $item->getId(), $ref, true );
649
		$this->object->save( $basket );
650
651
		$newBasketId = $basket->getId();
652
653
		$basket = $this->getBasket( $newBasketId, $ref );
654
		$this->object->delete( $newBasketId );
655
656
657
		$this->assertEquals( $item->getCustomerId(), $basket->getCustomerId() );
658
		$this->assertEquals( $basket->locale()->getSiteId(), $basket->getSiteId() );
659
660
		$this->assertEquals( 1.50, $basket->getPrice()->getCosts() );
661
662
		$pos = 1;
663
		$products = $basket->getProducts();
664
		$this->assertEquals( 4, count( $products ) );
665
666
		foreach( $products as $product )
667
		{
668
			if( $product->getProductCode() != 'U:MD' ) {
669
				$this->assertGreaterThanOrEqual( 2, count( $product->getAttributeItems() ) );
670
			}
671
			$this->assertEquals( $pos++, $product->getPosition() );
672
		}
673
674
		$this->assertEquals( 2, count( $basket->getAddresses() ) );
675
676
		$services = $basket->getServices();
677
		$this->assertEquals( 2, count( $services ) );
678
679
		$attributes = [];
680
		foreach( $services as $list )
681
		{
682
			foreach( $list as $service ) {
683
				$attributes[$service->getCode()] = $service->getAttributeItems();
684
			}
685
		}
686
687
		$this->assertEquals( 9, count( $attributes['unitpaymentcode'] ) );
688
		$this->assertEquals( 0, count( $attributes['unitdeliverycode'] ) );
689
690
		$this->expectException( \Aimeos\MShop\Exception::class );
691
		$this->object->get( $newBasketId );
692
	}
693
694
695
	public function testSaveExisting()
696
	{
697
		$item = $this->getOrderItem();
698
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
699
700
		$basket = $this->getBasket( $item->getId(), $ref, true );
701
		$this->object->save( $basket );
702
		$newBasketId = $basket->getId();
703
		$this->object->save( $basket );
704
		$newBasket = $this->getBasket( $newBasketId, $ref );
705
706
		$this->object->delete( $newBasketId );
707
708
		foreach( $basket->getAddresses() as $type => $list )
709
		{
710
			$this->assertTrue( map( $list )->getId()->equals( map( $newBasket->getAddress( $type ) )->getId() ) );
711
		}
712
713
		$this->assertTrue( $basket->getProducts()->getId()->equals( $newBasket->getProducts()->getId() ) );
714
715
		foreach( $basket->getServices() as $type => $list )
716
		{
717
			$this->assertTrue( map( $list )->getId()->equals( map( $newBasket->getService( $type ) )->getId() ) );
718
		}
719
	}
720
721
722
	public function testSaveBundles()
723
	{
724
		$search = $this->object->filter()->add( ['order.sitecode' => 'unittest', 'order.price' => 2400.00] );
725
		$item = $this->object->search( $search )->first( new \RuntimeException( 'No order found' ) );
726
727
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
728
		$basket = $this->getBasket( $item->getId(), $ref, true );
729
		$this->object->save( $basket );
730
731
		$newBasketId = $basket->getId();
732
733
		$basket = $this->getBasket( $newBasketId, $ref );
734
		$this->object->delete( $newBasketId );
735
736
		$this->assertEquals( $item->getCustomerId(), $basket->getCustomerId() );
737
		$this->assertEquals( $basket->locale()->getSiteId(), $basket->getSiteId() );
738
739
		$pos = 1;
740
		$products = $basket->getProducts();
741
742
		$this->assertEquals( 2, count( $products ) );
743
		foreach( $products as $product )
744
		{
745
			$this->assertEquals( 2, count( $product->getProducts() ) );
746
			$this->assertEquals( $pos, $product->getPosition() );
747
			$pos += 3; // two sub-products in between
748
		}
749
750
		$this->expectException( \Aimeos\MShop\Exception::class );
751
		$this->object->get( $newBasketId );
752
	}
753
754
755
	public function testSaveAddress()
756
	{
757
		$item = $this->getOrderItem();
758
759
		$basket = $this->getBasket( $item->getId(), ['order/address'], true );
760
		$this->object->save( $basket );
761
762
		$newBasketId = $basket->getId();
763
764
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
765
		$basket = $this->getBasket( $newBasketId, $ref );
766
		$this->object->delete( $newBasketId );
767
768
		$this->assertGreaterThan( 0, count( $basket->getAddresses() ) );
769
		$this->assertEquals( [], $basket->getProducts()->toArray() );
770
		$this->assertEquals( [], $basket->getCoupons()->toArray() );
771
		$this->assertEquals( [], $basket->getServices()->toArray() );
772
	}
773
774
775
	public function testSaveProduct()
776
	{
777
		$item = $this->getOrderItem();
778
779
		$basket = $this->getBasket( $item->getId(), ['order/product'], true );
780
		$this->object->save( $basket );
781
782
		$newBasketId = $basket->getId();
783
784
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
785
		$basket = $this->getBasket( $newBasketId, $ref );
786
		$this->object->delete( $newBasketId );
787
788
		$this->assertGreaterThan( 0, count( $basket->getProducts() ) );
789
		$this->assertEquals( [], $basket->getAddresses()->toArray() );
790
		$this->assertEquals( [], $basket->getCoupons()->toArray() );
791
		$this->assertEquals( [], $basket->getServices()->toArray() );
792
	}
793
794
795
	public function testSaveService()
796
	{
797
		$item = $this->getOrderItem();
798
799
		$basket = $this->getBasket( $item->getId(), ['order/service'], true );
800
		$this->object->save( $basket );
801
802
		$newBasketId = $basket->getId();
803
804
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
805
		$basket = $this->getBasket( $newBasketId, $ref );
806
		$this->object->delete( $newBasketId );
807
808
		$this->assertGreaterThan( 0, count( $basket->getServices() ) );
809
		$this->assertEquals( [], $basket->getProducts()->toArray() );
810
		$this->assertEquals( [], $basket->getAddresses()->toArray() );
811
		$this->assertEquals( [], $basket->getCoupons()->toArray() );
812
	}
813
814
815
	public function testLoadSaveCoupons()
816
	{
817
		$ref = ['order/address', 'order/product', 'order/service'];
818
819
		$search = $this->object->filter()->add( ['order.price' => '53.50'] );
820
		$item = $this->object->search( $search )->first( new \RuntimeException( 'No order found' ) );
821
822
		$basket = $this->getBasket( $item->getId(), $ref, true );
823
824
		$this->assertEquals( '53.50', $basket->getPrice()->getValue() );
825
		$this->assertEquals( '1.50', $basket->getPrice()->getCosts() );
826
		$this->assertEquals( '14.50', $basket->getPrice()->getRebate() );
827
		$this->assertEquals( 0, count( $basket->getCoupons() ) );
828
829
		$basket->addCoupon( 'CDEF' );
830
		$basket->addCoupon( '90AB' );
831
832
		$this->assertEquals( '47.05', $basket->getPrice()->getValue() );
833
		$this->assertEquals( '1.50', $basket->getPrice()->getCosts() );
834
		$this->assertEquals( '20.95', $basket->getPrice()->getRebate() );
835
		$this->assertEquals( 2, count( $basket->getCoupons() ) );
836
837
		$this->object->save( $basket );
838
839
		$ref = ['order/address', 'order/coupon', 'order/product', 'order/service'];
840
841
		$newBasket = $this->object->get( $basket->getId(), $ref );
842
		$this->object->delete( $newBasket->getId() );
843
844
		$this->assertEquals( '47.05', $newBasket->getPrice()->getValue() );
845
		$this->assertEquals( '1.50', $newBasket->getPrice()->getCosts() );
846
		$this->assertEquals( '20.95', $newBasket->getPrice()->getRebate() );
847
		$this->assertEquals( 2, count( $newBasket->getCoupons() ) );
848
	}
849
850
851
	public function testSaveStatus()
852
	{
853
		$item = $this->getOrderItem();
854
855
		$basket = $this->getBasket( $item->getId(), ['order/status'], true );
856
		$this->object->save( $basket );
857
858
		$newBasketId = $basket->getId();
859
860
		$basket = $this->getBasket( $newBasketId, ['order/status'] );
861
		$this->object->delete( $newBasketId );
862
863
		$this->assertGreaterThan( 0, count( $basket->getStatuses()->flat( 1 ) ) );
864
	}
865
866
867
	/**
868
	 * Returns the basket object
869
	 *
870
	 * @param string|null $id Unique order ID
871
	 * @param array $ref List of items that should be fetched too
872
	 * @param bool $fresh TRUE to return items without IDs
873
	 * @return \Aimeos\MShop\Order\Item\Iface Order base item
874
	 * @throws \Exception If no found
875
	 */
876
	protected function getBasket( ?string $id, array $ref = [], bool $fresh = false )
877
	{
878
		if( $id === null ) {
879
			throw new \Exception( 'ID can not be NULL' );
880
		}
881
882
		$basket = $this->object->get( $id, $ref );
883
884
		if( $fresh )
885
		{
886
			$basket->setId( null );
887
888
			$basket->getAddresses()->flat( 1 )->setParentId( null )->setId( null );
889
			$basket->getServices()->flat( 1 )->setParentId( null )->setId( null );
890
891
			$basket->getProducts()->merge( $basket->getProducts()->getProducts()->flat( 1 ) )
892
				->setParentId( null )->setPosition( null )->setId( null );
893
894
			$basket->getStatuses()->flat( 1 )->setParentId( null )->setId( null );
895
		}
896
897
		return $basket;
898
	}
899
900
901
	/**
902
	 * Returns an order base item
903
	 *
904
	 * @return \Aimeos\MShop\Order\Item\Iface Order base item
905
	 * @throws \Exception If no found
906
	 */
907
	protected function getOrderItem()
908
	{
909
		$search = $this->object->filter()->add( [
910
			'order.sitecode' => 'unittest',
911
			'order.price' => 53.50,
912
			'order.rebate' => 14.50,
913
			'order.editor' => $this->editor
914
		] );
915
916
		return $this->object->search( $search )->first( new \RuntimeException( 'No order found' ) );
917
	}
918
}
919