Passed
Push — master ( 0ebe2c...f735a4 )
by Wilmer
11:50
created

ActiveRecordTest::testIsPrimaryKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 15
nc 1
nop 0
dl 0
loc 20
rs 9.7666
c 1
b 0
f 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Tests;
6
7
use ReflectionException;
8
use Yiisoft\ActiveRecord\ActiveQuery;
9
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Animal;
10
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat;
11
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
12
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerClosureField;
13
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithAlias;
14
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Dog;
15
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Item;
16
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\NoExist;
17
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\NullValues;
18
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Order;
19
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderItem;
20
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderItemWithNullFK;
21
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Type;
22
use Yiisoft\ActiveRecord\Tests\Support\Assert;
23
use Yiisoft\Db\Exception\Exception;
24
use Yiisoft\Db\Exception\InvalidArgumentException;
25
use Yiisoft\Db\Exception\InvalidCallException;
26
use Yiisoft\Db\Exception\InvalidConfigException;
27
use Yiisoft\Db\Query\Query;
28
29
abstract class ActiveRecordTest extends TestCase
30
{
31
    public function testStoreNull(): void
32
    {
33
        $this->checkFixture($this->db, 'null_values', true);
34
35
        $record = new NullValues($this->db);
36
37
        $this->assertNull($record->getAttribute('var1'));
38
        $this->assertNull($record->getAttribute('var2'));
39
        $this->assertNull($record->getAttribute('var3'));
40
        $this->assertNull($record->getAttribute('stringcol'));
41
42
        $record->setAttribute('var1', 123);
43
        $record->setAttribute('var2', 456);
44
        $record->setAttribute('var3', 789);
45
        $record->setAttribute('stringcol', 'hello!');
46
        $record->save();
47
48
        $this->assertTrue($record->refresh());
49
        $this->assertEquals(123, $record->getAttribute('var1'));
50
        $this->assertEquals(456, $record->getAttribute('var2'));
51
        $this->assertEquals(789, $record->getAttribute('var3'));
52
        $this->assertEquals('hello!', $record->getAttribute('stringcol'));
53
54
        $record->setAttribute('var1', null);
55
        $record->setAttribute('var2', null);
56
        $record->setAttribute('var3', null);
57
        $record->setAttribute('stringcol', null);
58
        $record->save();
59
60
        $this->assertTrue($record->refresh());
61
        $this->assertNull($record->getAttribute('var1'));
62
        $this->assertNull($record->getAttribute('var2'));
63
        $this->assertNull($record->getAttribute('var3'));
64
        $this->assertNull($record->getAttribute('>stringcol'));
65
66
        $record->setAttribute('var1', 0);
67
        $record->setAttribute('var2', 0);
68
        $record->setAttribute('var3', 0);
69
        $record->setAttribute('stringcol', '');
70
        $record->save();
71
72
        $this->assertTrue($record->refresh());
73
        $this->assertEquals(0, $record->getAttribute('var1'));
74
        $this->assertEquals(0, $record->getAttribute('var2'));
75
        $this->assertEquals(0, $record->getAttribute('var3'));
76
        $this->assertEquals('', $record->getAttribute('stringcol'));
77
    }
78
79
    public function testStoreEmpty(): void
80
    {
81
        $this->checkFixture($this->db, 'null_values');
82
83
        $record = new NullValues($this->db);
84
85
        /** this is to simulate empty html form submission */
86
        $record->var1 = '';
87
        $record->var2 = '';
88
        $record->var3 = '';
89
        $record->stringcol = '';
90
        $record->save();
91
92
        $this->assertTrue($record->refresh());
93
94
        /** {@see https://github.com/yiisoft/yii2/commit/34945b0b69011bc7cab684c7f7095d837892a0d4#commitcomment-4458225} */
95
        $this->assertSame($record->var1, $record->var2);
96
        $this->assertSame($record->var2, $record->var3);
97
    }
98
99
    public function testIsPrimaryKey(): void
100
    {
101
        $this->checkFixture($this->db, 'customer');
102
103
        $customer = new Customer($this->db);
104
        $orderItem = new OrderItem($this->db);
105
106
        $this->assertTrue($customer->isPrimaryKey(['id']));
107
        $this->assertFalse($customer->isPrimaryKey([]));
108
        $this->assertFalse($customer->isPrimaryKey(['id', 'name']));
109
        $this->assertFalse($customer->isPrimaryKey(['name']));
110
        $this->assertFalse($customer->isPrimaryKey(['name', 'email']));
111
112
        $this->assertTrue($orderItem->isPrimaryKey(['order_id', 'item_id']));
113
        $this->assertFalse($orderItem->isPrimaryKey([]));
114
        $this->assertFalse($orderItem->isPrimaryKey(['order_id']));
115
        $this->assertFalse($orderItem->isPrimaryKey(['item_id']));
116
        $this->assertFalse($orderItem->isPrimaryKey(['quantity']));
117
        $this->assertFalse($orderItem->isPrimaryKey(['quantity', 'subtotal']));
118
        $this->assertFalse($orderItem->isPrimaryKey(['order_id', 'item_id', 'quantity']));
119
    }
120
121
    public function testOutdatedRelationsAreResetForNewRecords(): void
122
    {
123
        $this->checkFixture($this->db, 'order_item');
124
125
        $orderItem = new OrderItem($this->db);
126
127
        $orderItem->order_id = 1;
128
        $orderItem->item_id = 3;
129
        $this->assertEquals(1, $orderItem->order->id);
130
        $this->assertEquals(3, $orderItem->item->id);
131
132
        /** test `__set()`. */
133
        $orderItem->order_id = 2;
134
        $orderItem->item_id = 1;
135
        $this->assertEquals(2, $orderItem->order->id);
136
        $this->assertEquals(1, $orderItem->item->id);
137
138
        /** test `setAttribute()`. */
139
        $orderItem->setAttribute('order_id', 2);
140
        $orderItem->setAttribute('item_id', 2);
141
        $this->assertEquals(2, $orderItem->order->id);
142
        $this->assertEquals(2, $orderItem->item->id);
143
    }
144
145
    public function testDefaultValues(): void
146
    {
147
        $this->checkFixture($this->db, 'type');
148
149
        $arClass = new Type($this->db);
150
151
        $arClass->loadDefaultValues();
152
153
        $this->assertEquals(1, $arClass->int_col2);
154
        $this->assertEquals('something', $arClass->char_col2);
155
        $this->assertEquals(1.23, $arClass->float_col2);
156
        $this->assertEquals(33.22, $arClass->numeric_col);
157
        $this->assertEquals(true, $arClass->bool_col2);
158
        $this->assertEquals('2002-01-01 00:00:00', $arClass->time);
159
160
        $arClass = new Type($this->db);
161
        $arClass->char_col2 = 'not something';
162
163
        $arClass->loadDefaultValues();
164
        $this->assertEquals('not something', $arClass->char_col2);
165
166
        $arClass = new Type($this->db);
167
        $arClass->char_col2 = 'not something';
168
169
        $arClass->loadDefaultValues(false);
170
        $this->assertEquals('something', $arClass->char_col2);
171
    }
172
173
    public function testCastValues(): void
174
    {
175
        $this->checkFixture($this->db, 'type');
176
177
        $arClass = new Type($this->db);
178
179
        $arClass->int_col = 123;
180
        $arClass->int_col2 = 456;
181
        $arClass->smallint_col = 42;
182
        $arClass->char_col = '1337';
183
        $arClass->char_col2 = 'test';
184
        $arClass->char_col3 = 'test123';
185
        $arClass->float_col = 3.742;
186
        $arClass->float_col2 = 42.1337;
187
        $arClass->bool_col = true;
188
        $arClass->bool_col2 = false;
189
190
        $arClass->save();
191
192
        /** @var $model Type */
193
        $aqClass = new ActiveQuery(Type::class, $this->db);
194
        $query = $aqClass->onePopulate();
195
196
        $this->assertSame(123, $query->int_col);
197
        $this->assertSame(456, $query->int_col2);
198
        $this->assertSame(42, $query->smallint_col);
199
        $this->assertSame('1337', trim($query->char_col));
200
        $this->assertSame('test', $query->char_col2);
201
        $this->assertSame('test123', $query->char_col3);
202
    }
203
204
    public function testPopulateRecordCallWhenQueryingOnParentClass(): void
205
    {
206
        $this->checkFixture($this->db, 'cat');
207
208
        $cat = new Cat($this->db);
209
        $cat->save();
210
211
        $dog = new Dog($this->db);
212
        $dog->save();
213
214
        $animal = new ActiveQuery(Animal::class, $this->db);
215
216
        $animals = $animal->where(['type' => Dog::class])->onePopulate();
217
        $this->assertEquals('bark', $animals->getDoes());
218
219
        $animals = $animal->where(['type' => Cat::class])->onePopulate();
220
        $this->assertEquals('meow', $animals->getDoes());
221
    }
222
223
    public function testSaveEmpty(): void
224
    {
225
        $this->checkFixture($this->db, 'null_values', true);
226
227
        $record = new NullValues($this->db);
228
229
        $this->assertTrue($record->save());
230
        $this->assertEquals(1, $record->id);
231
    }
232
233
    /**
234
     * Verify that {{}} are not going to be replaced in parameters.
235
     */
236
    public function testNoTablenameReplacement(): void
237
    {
238
        $this->checkFixture($this->db, 'customer');
239
240
        $customer = new Customer($this->db);
241
242
        $customer->name = 'Some {{weird}} name';
243
        $customer->email = '[email protected]';
244
        $customer->address = 'Some {{%weird}} address';
245
        $customer->insert();
246
        $customer->refresh();
247
248
        $this->assertEquals('Some {{weird}} name', $customer->name);
249
        $this->assertEquals('Some {{%weird}} address', $customer->address);
250
251
        $customer->name = 'Some {{updated}} name';
252
        $customer->address = 'Some {{%updated}} address';
253
        $customer->update();
254
255
        $this->assertEquals('Some {{updated}} name', $customer->name);
256
        $this->assertEquals('Some {{%updated}} address', $customer->address);
257
    }
258
259
    public static function legalValuesForFindByCondition(): array
260
    {
261
        return [
262
            [Customer::class, ['id' => 1]],
263
            [Customer::class, ['customer.id' => 1]],
264
            [Customer::class, ['[[id]]' => 1]],
265
            [Customer::class, ['{{customer}}.[[id]]' => 1]],
266
            [Customer::class, ['{{%customer}}.[[id]]' => 1]],
267
            [CustomerWithAlias::class, ['id' => 1]],
268
            [CustomerWithAlias::class, ['customer.id' => 1]],
269
            [CustomerWithAlias::class, ['[[id]]' => 1]],
270
            [CustomerWithAlias::class, ['{{customer}}.[[id]]' => 1]],
271
            [CustomerWithAlias::class, ['{{%customer}}.[[id]]' => 1]],
272
            [CustomerWithAlias::class, ['csr.id' => 1], 'csr'],
273
            [CustomerWithAlias::class, ['{{csr}}.[[id]]' => 1], 'csr'],
274
        ];
275
    }
276
277
    /**
278
     * @dataProvider legalValuesForFindByCondition
279
     *
280
     * @throws ReflectionException
281
     */
282
    public function testLegalValuesForFindByCondition(
283
        string $modelClassName,
284
        array $validFilter,
285
        ?string $alias = null
286
    ): void {
287
        $this->checkFixture($this->db, 'customer');
288
289
        $activeQuery = new ActiveQuery($modelClassName, $this->db);
290
291
        if ($alias !== null) {
292
            $activeQuery->alias('csr');
293
        }
294
295
        /** @var Query $query */
296
        $query = Assert::invokeMethod($activeQuery, 'findByCondition', [$validFilter]);
297
298
299
        $this->db->getQueryBuilder()->build($query);
300
301
        $this->assertTrue(true);
302
    }
303
304
    public static function illegalValuesForFindByCondition(): array
305
    {
306
        return [
307
            [Customer::class, [['`id`=`id` and 1' => 1]]],
308
            [Customer::class, [[
309
                'legal' => 1,
310
                '`id`=`id` and 1' => 1,
311
            ]]],
312
            [Customer::class, [[
313
                'nested_illegal' => [
314
                    'false or 1=' => 1,
315
                ],
316
            ]]],
317
            [Customer::class, [['true--' => 1]]],
318
319
            [CustomerWithAlias::class, [['`csr`.`id`=`csr`.`id` and 1' => 1]]],
320
            [CustomerWithAlias::class, [[
321
                'legal' => 1,
322
                '`csr`.`id`=`csr`.`id` and 1' => 1,
323
            ]]],
324
            [CustomerWithAlias::class, [[
325
                'nested_illegal' => [
326
                    'false or 1=' => 1,
327
                ],
328
            ]]],
329
            [CustomerWithAlias::class, [['true--' => 1]]],
330
        ];
331
    }
332
333
    /**
334
     * @dataProvider illegalValuesForFindByCondition
335
     *
336
     * @throws ReflectionException
337
     */
338
    public function testValueEscapingInFindByCondition(string $modelClassName, array $filterWithInjection): void
339
    {
340
        $this->checkFixture($this->db, 'customer');
341
        $this->expectException(InvalidArgumentException::class);
342
        $this->expectExceptionMessageMatches(
343
            '/^Key "(.+)?" is not a column name and can not be used as a filter$/'
344
        );
345
346
        $query = new ActiveQuery($modelClassName, $this->db);
347
348
        /** @var Query $query */
349
        $query = Assert::invokeMethod($query, 'findByCondition', $filterWithInjection);
350
351
        $this->db->getQueryBuilder()->build($query);
352
    }
353
354
    public function testRefreshQuerySetAliasFindRecord(): void
355
    {
356
        $this->checkFixture($this->db, 'customer');
357
358
        $customer = new CustomerWithAlias($this->db);
359
360
        $customer->id = 1;
361
        $customer->refresh();
362
363
        $this->assertEquals(1, $customer->id);
364
    }
365
366
    public function testResetNotSavedRelation(): void
367
    {
368
        $this->checkFixture($this->db, 'order');
369
370
        $order = new Order($this->db);
371
372
        $order->customer_id = 1;
373
        $order->created_at = 1_325_502_201;
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING on line 373 at column 30
Loading history...
374
        $order->total = 0;
375
376
        $orderItem = new OrderItem($this->db);
377
378
        $order->orderItems;
379
380
        $order->populateRelation('orderItems', [$orderItem]);
381
382
        $order->save();
383
384
        $this->assertCount(1, $order->orderItems);
385
    }
386
387
    public function testIssetException(): void
388
    {
389
        $this->checkFixture($this->db, 'cat');
390
391
        $cat = new Cat($this->db);
392
393
        $this->assertFalse(isset($cat->exception));
394
    }
395
396
    public function testIssetThrowable(): void
397
    {
398
        $this->checkFixture($this->db, 'cat');
399
400
        $cat = new Cat($this->db);
401
402
        $this->assertFalse(isset($cat->throwable));
403
    }
404
405
    public function testSetAttributes(): void
406
    {
407
        $attributes = [];
408
        $this->checkFixture($this->db, 'customer');
409
410
        $attributes['email'] = '[email protected]';
411
        $attributes['name'] = 'samdark';
412
        $attributes['address'] = 'rusia';
413
        $attributes['status'] = 1;
414
415
        if ($this->db->getDriverName() === 'pgsql') {
416
            $attributes['bool_status'] = true;
417
        }
418
419
        $attributes['profile_id'] = null;
420
421
        $customer = new Customer($this->db);
422
423
        $customer->setAttributes($attributes);
424
425
        $this->assertTrue($customer->save());
426
    }
427
428
    public function testSetAttributeNoExist(): void
429
    {
430
        $this->checkFixture($this->db, 'cat');
431
432
        $cat = new Cat($this->db);
433
434
        $this->expectException(InvalidArgumentException::class);
435
        $this->expectExceptionMessage(
436
            'Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat has no attribute named "noExist"'
437
        );
438
439
        $cat->setAttribute('noExist', 1);
440
    }
441
442
    public function testSetOldAttribute(): void
443
    {
444
        $this->checkFixture($this->db, 'customer');
445
446
        $customer = new Customer($this->db);
447
448
        $this->assertEmpty($customer->getOldAttribute('name'));
449
450
        $customer->setOldAttribute('name', 'samdark');
451
452
        $this->assertEquals('samdark', $customer->getOldAttribute('name'));
453
    }
454
455
    public function testSetOldAttributeException(): void
456
    {
457
        $this->checkFixture($this->db, 'customer');
458
459
        $customer = new Customer($this->db);
460
461
        $this->assertEmpty($customer->getOldAttribute('name'));
462
463
        $this->expectException(InvalidArgumentException::class);
464
        $this->expectExceptionMessage(
465
            'Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer has no attribute named "noExist"'
466
        );
467
        $customer->setOldAttribute('noExist', 'samdark');
468
    }
469
470
    public function testIsAttributeChangedNotChanged(): void
471
    {
472
        $this->checkFixture($this->db, 'customer');
473
474
        $customer = new Customer($this->db);
475
476
        $this->assertEmpty($customer->getAttribute('name'));
477
        $this->assertEmpty($customer->getOldAttribute('name'));
478
        $this->assertFalse($customer->isAttributeChanged('name', false));
479
    }
480
481
    public function testTableSchemaException(): void
482
    {
483
        $noExist = new NoExist($this->db);
484
485
        $this->expectException(InvalidConfigException::class);
486
        $this->expectExceptionMessage('The table does not exist: NoExist');
487
        $noExist->getTableSchema();
488
    }
489
490
    public function testInsert(): void
491
    {
492
        $this->checkFixture($this->db, 'customer');
493
494
        $customer = new Customer($this->db);
495
496
        $customer->email = '[email protected]';
497
        $customer->name = 'user4';
498
        $customer->address = 'address4';
499
500
        $this->assertNull($customer->id);
501
        $this->assertTrue($customer->isNewRecord);
502
503
        $customer->save();
504
505
        $this->assertNotNull($customer->id);
506
        $this->assertFalse($customer->isNewRecord);
507
    }
508
509
    /**
510
     * Some PDO implementations (e.g. cubrid) do not support boolean values.
511
     *
512
     * Make sure this does not affect AR layer.
513
     */
514
    public function testBooleanAttribute(): void
515
    {
516
        $this->checkFixture($this->db, 'customer', true);
517
518
        $customer = new Customer($this->db);
519
520
        $customer->name = 'boolean customer';
521
        $customer->email = '[email protected]';
522
        $customer->status = true;
523
524
        $customer->save();
525
        $customer->refresh();
526
        $this->assertEquals(1, $customer->status);
527
528
        $customer->status = false;
529
        $customer->save();
530
531
        $customer->refresh();
532
        $this->assertEquals(0, $customer->status);
533
534
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
535
        $customers = $customerQuery->where(['status' => true])->all();
536
        $this->assertCount(2, $customers);
537
538
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
539
        $customers = $customerQuery->where(['status' => false])->all();
540
        $this->assertCount(1, $customers);
541
    }
542
543
    public function testAttributeAccess(): void
544
    {
545
        $this->checkFixture($this->db, 'customer');
546
547
        $arClass = new Customer($this->db);
548
549
        $this->assertTrue($arClass->canSetProperty('name'));
550
        $this->assertTrue($arClass->canGetProperty('name'));
551
        $this->assertFalse($arClass->canSetProperty('unExistingColumn'));
552
        $this->assertFalse(isset($arClass->name));
553
554
        $arClass->name = 'foo';
555
        $this->assertTrue(isset($arClass->name));
556
557
        unset($arClass->name);
558
        $this->assertNull($arClass->name);
559
560
        /** {@see https://github.com/yiisoft/yii2-gii/issues/190} */
561
        $baseModel = new Customer($this->db);
562
        $this->assertFalse($baseModel->hasProperty('unExistingColumn'));
563
564
        $customer = new Customer($this->db);
565
        $this->assertInstanceOf(Customer::class, $customer);
566
        $this->assertTrue($customer->canGetProperty('id'));
567
        $this->assertTrue($customer->canSetProperty('id'));
568
569
        /** tests that we really can get and set this property */
570
        $this->assertNull($customer->id);
571
        $customer->id = 10;
572
        $this->assertNotNull($customer->id);
573
574
        /** Let's test relations */
575
        $this->assertTrue($customer->canGetProperty('orderItems'));
576
        $this->assertFalse($customer->canSetProperty('orderItems'));
577
578
        /** Newly created model must have empty relation */
579
        $this->assertSame([], $customer->orderItems);
580
581
        /** does it still work after accessing the relation? */
582
        $this->assertTrue($customer->canGetProperty('orderItems'));
583
        $this->assertFalse($customer->canSetProperty('orderItems'));
584
585
        try {
586
            /** @var $itemClass ActiveRecordInterface */
587
            $customer->orderItems = [new Item($this->db)];
588
            $this->fail('setter call above MUST throw Exception');
589
        } catch (Exception $e) {
590
            /** catch exception "Setting read-only property" */
591
            $this->assertInstanceOf(InvalidCallException::class, $e);
592
        }
593
594
        /** related attribute $customer->orderItems didn't change cause it's read-only */
595
        $this->assertSame([], $customer->orderItems);
596
        $this->assertFalse($customer->canGetProperty('non_existing_property'));
597
        $this->assertFalse($customer->canSetProperty('non_existing_property'));
598
    }
599
600
    public function testHasAttribute(): void
601
    {
602
        $this->checkFixture($this->db, 'customer');
603
604
        $customer = new Customer($this->db);
605
606
        $this->assertTrue($customer->hasAttribute('id'));
607
        $this->assertTrue($customer->hasAttribute('email'));
608
        $this->assertFalse($customer->hasAttribute(0));
609
        $this->assertFalse($customer->hasAttribute(null));
610
        $this->assertFalse($customer->hasAttribute(42));
611
612
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
613
        $customer = $customerQuery->findOne(1);
614
        $this->assertTrue($customer->hasAttribute('id'));
615
        $this->assertTrue($customer->hasAttribute('email'));
616
        $this->assertFalse($customer->hasAttribute(0));
617
        $this->assertFalse($customer->hasAttribute(null));
618
        $this->assertFalse($customer->hasAttribute(42));
619
    }
620
621
    public function testRefresh(): void
622
    {
623
        $this->checkFixture($this->db, 'customer');
624
625
        $customer = new Customer($this->db);
626
627
        $this->assertFalse($customer->refresh());
628
629
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
630
        $customer = $customerQuery->findOne(1);
631
        $customer->name = 'to be refreshed';
632
633
        $this->assertTrue($customer->refresh());
634
        $this->assertEquals('user1', $customer->name);
635
    }
636
637
    public function testEquals(): void
638
    {
639
        $this->checkFixture($this->db, 'customer');
640
641
        $customerA = new Customer($this->db);
642
        $customerB = new Customer($this->db);
643
        $this->assertFalse($customerA->equals($customerB));
644
645
        $customerA = new Customer($this->db);
646
        $customerB = new Item($this->db);
647
        $this->assertFalse($customerA->equals($customerB));
648
    }
649
650
    public static function providerForUnlinkDelete()
651
    {
652
        return [
653
            'with delete' => [true, 0],
654
            'without delete' => [false, 1],
655
        ];
656
    }
657
658
    /**
659
     * @dataProvider providerForUnlinkDelete
660
     *
661
     * @see https://github.com/yiisoft/yii2/issues/17174
662
     */
663
    public function testUnlinkWithViaOnCondition($delete, $count)
664
    {
665
        $this->checkFixture($this->db, 'order', true);
666
        $this->checkFixture($this->db, 'order_item_with_null_fk', true);
667
668
        $orderQuery = new ActiveQuery(Order::class, $this->db);
669
        $order = $orderQuery->findOne(2);
670
671
        $this->assertCount(1, $order->itemsFor8);
672
        $order->unlink('itemsFor8', $order->itemsFor8[0], $delete);
673
674
        $order = $orderQuery->findOne(2);
675
        $this->assertCount(0, $order->itemsFor8);
676
        $this->assertCount(2, $order->orderItemsWithNullFK);
677
678
        $orderItemQuery = new ActiveQuery(OrderItemWithNullFK::class, $this->db);
679
        $this->assertCount(1, $orderItemQuery->findAll([
680
            'order_id' => 2,
681
            'item_id' => 5,
682
        ]));
683
        $this->assertCount($count, $orderItemQuery->findAll([
684
            'order_id' => null,
685
            'item_id' => null,
686
        ]));
687
    }
688
689
    public function testVirtualRelation()
690
    {
691
        $this->checkFixture($this->db, 'order', true);
692
693
        $orderQuery = new ActiveQuery(Order::class, $this->db);
694
        /** @var Order $order */
695
        $order = $orderQuery->findOne(2);
696
697
        $order->setVirtualCustomerId($order->customer_id);
698
        $this->assertNotNull($order->getVirtualCustomer());
699
    }
700
701
    /**
702
     * Test joinWith eager loads via relation
703
     *
704
     * @see https://github.com/yiisoft/yii2/issues/19507
705
     */
706
    public function testJoinWithEager()
707
    {
708
        $this->checkFixture($this->db, 'customer', true);
709
710
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
711
        $eagerCustomers = $customerQuery->joinWith(['items2'])->all();
712
        $eagerItemsCount = 0;
713
        foreach ($eagerCustomers as $customer) {
714
            $eagerItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0;
715
        }
716
717
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
718
        $lazyCustomers = $customerQuery->all();
719
        $lazyItemsCount = 0;
720
        foreach ($lazyCustomers as $customer) {
721
            $lazyItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0;
722
        }
723
724
        $this->assertEquals($eagerItemsCount, $lazyItemsCount);
725
    }
726
727
    public function testToArray(): void
728
    {
729
        $this->checkFixture($this->db, 'customer', true);
730
731
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
732
        $customer = $customerQuery->findOne(1);
733
734
        $this->assertSame(
735
            [
736
                'id' => 1,
737
                'email' => '[email protected]',
738
                'name' => 'user1',
739
                'address' => 'address1',
740
                'status' => 1,
741
                'profile_id' => 1,
742
            ],
743
            $customer->toArray(),
744
        );
745
    }
746
747
    public function testToArrayWithClosure(): void
748
    {
749
        $this->checkFixture($this->db, 'customer', true);
750
751
        $customerQuery = new ActiveQuery(CustomerClosureField::class, $this->db);
752
        $customer = $customerQuery->findOne(1);
753
754
        $this->assertSame(
755
            [
756
                'id' => 1,
757
                'email' => '[email protected]',
758
                'name' => 'user1',
759
                'address' => 'address1',
760
                'status' => 'active',
761
                'profile_id' => 1,
762
            ],
763
            $customer->toArray(),
764
        );
765
    }
766
}
767