Passed
Push — master ( a75adc...a47013 )
by Wilmer
14:47 queued 12:46
created

ActiveRecordTestTrait::testLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 44
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 30
c 1
b 0
f 0
dl 0
loc 44
rs 9.44
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Tests;
6
7
use Yiisoft\ActiveRecord\ActiveQueryInterface;
8
use Yiisoft\ActiveRecord\ActiveRecordInterface;
9
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
10
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Item;
11
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Order;
12
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderItem;
13
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderWithNullFK;
14
use Yiisoft\Db\Exception\Exception;
15
use Yiisoft\Db\Exception\InvalidCallException;
16
17
trait ActiveRecordTestTrait
18
{
19
    public function testFind(): void
20
    {
21
        /** find one */
22
        $result = Customer::find();
23
        $this->assertInstanceOf(ActiveQueryInterface::class, $result);
0 ignored issues
show
Bug introduced by
It seems like assertInstanceOf() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

23
        $this->/** @scrutinizer ignore-call */ 
24
               assertInstanceOf(ActiveQueryInterface::class, $result);
Loading history...
24
        $customer = $result->one();
25
        $this->assertInstanceOf(Customer::class, $customer);
26
27
        /** find all */
28
        $customers = Customer::find()->all();
29
        $this->assertCount(3, $customers);
0 ignored issues
show
Bug introduced by
It seems like assertCount() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

29
        $this->/** @scrutinizer ignore-call */ 
30
               assertCount(3, $customers);
Loading history...
30
        $this->assertInstanceOf(Customer::class, $customers[0]);
31
        $this->assertInstanceOf(Customer::class, $customers[1]);
32
        $this->assertInstanceOf(Customer::class, $customers[2]);
33
34
        /** find by a single primary key */
35
        $customer = Customer::findOne(2);
36
        $this->assertInstanceOf(Customer::class, $customer);
37
        $this->assertEquals('user2', $customer->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

37
        $this->/** @scrutinizer ignore-call */ 
38
               assertEquals('user2', $customer->name);
Loading history...
38
        $customer = Customer::findOne(5);
39
        $this->assertNull($customer);
0 ignored issues
show
Bug introduced by
It seems like assertNull() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

39
        $this->/** @scrutinizer ignore-call */ 
40
               assertNull($customer);
Loading history...
40
        $customer = Customer::findOne(['id' => [5, 6, 1]]);
41
        $this->assertInstanceOf(Customer::class, $customer);
42
        $customer = Customer::find()->where(['id' => [5, 6, 1]])->one();
43
        $this->assertNotNull($customer);
0 ignored issues
show
Bug introduced by
It seems like assertNotNull() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
        $this->/** @scrutinizer ignore-call */ 
44
               assertNotNull($customer);
Loading history...
44
45
        /** find by column values */
46
        $customer = Customer::findOne(['id' => 2, 'name' => 'user2']);
47
        $this->assertInstanceOf(Customer::class, $customer);
48
        $this->assertEquals('user2', $customer->name);
49
        $customer = Customer::findOne(['id' => 2, 'name' => 'user1']);
50
        $this->assertNull($customer);
51
        $customer = Customer::findOne(['id' => 5]);
52
        $this->assertNull($customer);
53
        $customer = Customer::findOne(['name' => 'user5']);
54
        $this->assertNull($customer);
55
56
        /** find by attributes */
57
        $customer = Customer::find()->where(['name' => 'user2'])->one();
58
        $this->assertInstanceOf(Customer::class, $customer);
59
        $this->assertEquals(2, $customer->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
60
61
        /** scope */
62
        $this->assertCount(2, Customer::find()->active()->all());
63
        $this->assertEquals(2, Customer::find()->active()->count());
64
    }
65
66
    public function testFindAsArray(): void
67
    {
68
        /** asArray */
69
        $customer = Customer::find()->where(['id' => 2])->asArray()->one();
70
        $this->assertEquals([
71
            'id' => 2,
72
            'email' => '[email protected]',
73
            'name' => 'user2',
74
            'address' => 'address2',
75
            'status' => 1,
76
            'profile_id' => null,
77
        ], $customer);
78
79
        /** find all asArray */
80
        $customers = Customer::find()->asArray()->all();
81
        $this->assertCount(3, $customers);
82
        $this->assertArrayHasKey('id', $customers[0]);
0 ignored issues
show
Bug introduced by
It seems like assertArrayHasKey() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
        $this->/** @scrutinizer ignore-call */ 
83
               assertArrayHasKey('id', $customers[0]);
Loading history...
83
        $this->assertArrayHasKey('name', $customers[0]);
84
        $this->assertArrayHasKey('email', $customers[0]);
85
        $this->assertArrayHasKey('address', $customers[0]);
86
        $this->assertArrayHasKey('status', $customers[0]);
87
        $this->assertArrayHasKey('id', $customers[1]);
88
        $this->assertArrayHasKey('name', $customers[1]);
89
        $this->assertArrayHasKey('email', $customers[1]);
90
        $this->assertArrayHasKey('address', $customers[1]);
91
        $this->assertArrayHasKey('status', $customers[1]);
92
        $this->assertArrayHasKey('id', $customers[2]);
93
        $this->assertArrayHasKey('name', $customers[2]);
94
        $this->assertArrayHasKey('email', $customers[2]);
95
        $this->assertArrayHasKey('address', $customers[2]);
96
        $this->assertArrayHasKey('status', $customers[2]);
97
    }
98
99
    public function testHasAttribute(): void
100
    {
101
        $customer = new Customer();
102
103
        $this->assertTrue($customer->hasAttribute('id'));
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        $this->/** @scrutinizer ignore-call */ 
104
               assertTrue($customer->hasAttribute('id'));
Loading history...
104
        $this->assertTrue($customer->hasAttribute('email'));
105
        $this->assertFalse($customer->hasAttribute(0));
0 ignored issues
show
Bug introduced by
It seems like assertFalse() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $this->/** @scrutinizer ignore-call */ 
106
               assertFalse($customer->hasAttribute(0));
Loading history...
106
        $this->assertFalse($customer->hasAttribute(null));
107
        $this->assertFalse($customer->hasAttribute(42));
108
109
        $customer = Customer::findOne(1);
110
        $this->assertTrue($customer->hasAttribute('id'));
111
        $this->assertTrue($customer->hasAttribute('email'));
112
        $this->assertFalse($customer->hasAttribute(0));
113
        $this->assertFalse($customer->hasAttribute(null));
114
        $this->assertFalse($customer->hasAttribute(42));
115
    }
116
117
    public function testFindScalar(): void
118
    {
119
        $customerName = Customer::find()->where(['id' => 2])->scalar('name');
0 ignored issues
show
Unused Code introduced by
The call to Yiisoft\Db\Query\Query::scalar() has too many arguments starting with 'name'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
        $customerName = Customer::find()->where(['id' => 2])->/** @scrutinizer ignore-call */ scalar('name');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
120
        $this->assertEquals('user2', $customerName);
121
        $customerName = Customer::find()->where(['status' => 2])->scalar('name');
122
        $this->assertEquals('user3', $customerName);
123
        $customerName = Customer::find()->where(['status' => 2])->scalar('noname');
124
        $this->assertNull($customerName);
125
        $customerId = Customer::find()->where(['status' => 2])->scalar('id');
126
        $this->assertEquals(3, $customerId);
127
    }
128
129
    public function testFindColumn(): void
130
    {
131
        $this->assertEquals(['user1', 'user2', 'user3'], Customer::find()->orderBy(['name' => SORT_ASC])->column('name'));
0 ignored issues
show
Unused Code introduced by
The call to Yiisoft\Db\Query\Query::column() has too many arguments starting with 'name'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

131
        $this->assertEquals(['user1', 'user2', 'user3'], Customer::find()->orderBy(['name' => SORT_ASC])->/** @scrutinizer ignore-call */ column('name'));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
132
        $this->assertEquals(['user3', 'user2', 'user1'], Customer::find()->orderBy(['name' => SORT_DESC])->column('name'));
133
    }
134
135
    public function testFindIndexBy(): void
136
    {
137
        $customers = Customer::find()->indexBy('name')->orderBy('id')->all();
138
139
        $this->assertCount(3, $customers);
140
        $this->assertInstanceOf(Customer::class, $customers['user1']);
141
        $this->assertInstanceOf(Customer::class, $customers['user2']);
142
        $this->assertInstanceOf(Customer::class, $customers['user3']);
143
144
        /** indexBy callable */
145
        $customers = Customer::find()->indexBy(function ($customer) {
146
            return $customer->id . '-' . $customer->name;
147
        })->orderBy('id')->all();
148
149
        $this->assertCount(3, $customers);
150
        $this->assertInstanceOf(Customer::class, $customers['1-user1']);
151
        $this->assertInstanceOf(Customer::class, $customers['2-user2']);
152
        $this->assertInstanceOf(Customer::class, $customers['3-user3']);
153
    }
154
155
    public function testFindIndexByAsArray(): void
156
    {
157
        $customers = Customer::find()->asArray()->indexBy('name')->all();
158
159
        $this->assertCount(3, $customers);
160
        $this->assertArrayHasKey('id', $customers['user1']);
161
        $this->assertArrayHasKey('name', $customers['user1']);
162
        $this->assertArrayHasKey('email', $customers['user1']);
163
        $this->assertArrayHasKey('address', $customers['user1']);
164
        $this->assertArrayHasKey('status', $customers['user1']);
165
        $this->assertArrayHasKey('id', $customers['user2']);
166
        $this->assertArrayHasKey('name', $customers['user2']);
167
        $this->assertArrayHasKey('email', $customers['user2']);
168
        $this->assertArrayHasKey('address', $customers['user2']);
169
        $this->assertArrayHasKey('status', $customers['user2']);
170
        $this->assertArrayHasKey('id', $customers['user3']);
171
        $this->assertArrayHasKey('name', $customers['user3']);
172
        $this->assertArrayHasKey('email', $customers['user3']);
173
        $this->assertArrayHasKey('address', $customers['user3']);
174
        $this->assertArrayHasKey('status', $customers['user3']);
175
176
        /** indexBy callable + asArray */
177
        $customers = Customer::find()->indexBy(function ($customer) {
178
            return $customer['id'] . '-' . $customer['name'];
179
        })->asArray()->all();
180
181
        $this->assertCount(3, $customers);
182
        $this->assertArrayHasKey('id', $customers['1-user1']);
183
        $this->assertArrayHasKey('name', $customers['1-user1']);
184
        $this->assertArrayHasKey('email', $customers['1-user1']);
185
        $this->assertArrayHasKey('address', $customers['1-user1']);
186
        $this->assertArrayHasKey('status', $customers['1-user1']);
187
        $this->assertArrayHasKey('id', $customers['2-user2']);
188
        $this->assertArrayHasKey('name', $customers['2-user2']);
189
        $this->assertArrayHasKey('email', $customers['2-user2']);
190
        $this->assertArrayHasKey('address', $customers['2-user2']);
191
        $this->assertArrayHasKey('status', $customers['2-user2']);
192
        $this->assertArrayHasKey('id', $customers['3-user3']);
193
        $this->assertArrayHasKey('name', $customers['3-user3']);
194
        $this->assertArrayHasKey('email', $customers['3-user3']);
195
        $this->assertArrayHasKey('address', $customers['3-user3']);
196
        $this->assertArrayHasKey('status', $customers['3-user3']);
197
    }
198
199
    public function testRefresh(): void
200
    {
201
        $customer = new Customer();
202
203
        $this->assertFalse($customer->refresh());
204
205
        $customer = Customer::findOne(1);
206
        $customer->name = 'to be refreshed';
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __set, consider adding a @property annotation.
Loading history...
207
208
        $this->assertTrue($customer->refresh());
209
        $this->assertEquals('user1', $customer->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
210
    }
211
212
    public function testEquals(): void
213
    {
214
        $customerA = new Customer();
215
        $customerB = new Customer();
216
        $this->assertFalse($customerA->equals($customerB));
217
218
        $customerA = new Customer();
219
        $customerB = new Item();
220
        $this->assertFalse($customerA->equals($customerB));
221
222
        $customerA = Customer::findOne(1);
223
        $customerB = Customer::findOne(2);
224
        $this->assertFalse($customerA->equals($customerB));
225
226
        $customerB = Customer::findOne(1);
227
        $this->assertTrue($customerA->equals($customerB));
228
229
        $customerA = Customer::findOne(1);
230
        $customerB = Item::findOne(1);
231
        $this->assertFalse($customerA->equals($customerB));
232
    }
233
234
    public function testFindCount(): void
235
    {
236
        /** @var $this TestCase|ActiveRecordTestTrait */
237
        $this->assertEquals(3, Customer::find()->count());
238
239
        $this->assertEquals(1, Customer::find()->where(['id' => 1])->count());
240
        $this->assertEquals(2, Customer::find()->where(['id' => [1, 2]])->count());
241
        $this->assertEquals(2, Customer::find()->where(['id' => [1, 2]])->offset(1)->count());
242
        $this->assertEquals(2, Customer::find()->where(['id' => [1, 2]])->offset(2)->count());
243
244
        /** limit should have no effect on count() */
245
        $this->assertEquals(3, Customer::find()->limit(1)->count());
246
        $this->assertEquals(3, Customer::find()->limit(2)->count());
247
        $this->assertEquals(3, Customer::find()->limit(10)->count());
248
        $this->assertEquals(3, Customer::find()->offset(2)->limit(2)->count());
249
    }
250
251
    public function testFindLimit(): void
252
    {
253
        $customers = Customer::find()->all();
254
        $this->assertCount(3, $customers);
255
256
        $customers = Customer::find()->orderBy('id')->limit(1)->all();
257
        $this->assertCount(1, $customers);
258
        $this->assertEquals('user1', $customers[0]->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
259
260
        $customers = Customer::find()->orderBy('id')->limit(1)->offset(1)->all();
261
        $this->assertCount(1, $customers);
262
        $this->assertEquals('user2', $customers[0]->name);
263
264
        $customers = Customer::find()->orderBy('id')->limit(1)->offset(2)->all();
265
        $this->assertCount(1, $customers);
266
        $this->assertEquals('user3', $customers[0]->name);
267
268
        $customers = Customer::find()->orderBy('id')->limit(2)->offset(1)->all();
269
        $this->assertCount(2, $customers);
270
        $this->assertEquals('user2', $customers[0]->name);
271
        $this->assertEquals('user3', $customers[1]->name);
272
273
        $customers = Customer::find()->limit(2)->offset(3)->all();
274
        $this->assertCount(0, $customers);
275
276
        $customer = Customer::find()->orderBy('id')->one();
277
        $this->assertEquals('user1', $customer->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
278
279
        $customer = Customer::find()->orderBy('id')->offset(0)->one();
280
        $this->assertEquals('user1', $customer->name);
281
282
        $customer = Customer::find()->orderBy('id')->offset(1)->one();
283
        $this->assertEquals('user2', $customer->name);
284
285
        $customer = Customer::find()->orderBy('id')->offset(2)->one();
286
        $this->assertEquals('user3', $customer->name);
287
288
        $customer = Customer::find()->offset(3)->one();
289
        $this->assertNull($customer);
290
    }
291
292
    public function testFindComplexCondition(): void
293
    {
294
        $this->assertEquals(2, Customer::find()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->count());
295
        $this->assertCount(2, Customer::find()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->all());
296
297
        $this->assertEquals(2, Customer::find()->where(['name' => ['user1', 'user2']])->count());
298
        $this->assertCount(2, Customer::find()->where(['name' => ['user1', 'user2']])->all());
299
300
        $this->assertEquals(1, Customer::find()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->count());
301
        $this->assertCount(1, Customer::find()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->all());
302
    }
303
304
    public function testFindNullValues(): void
305
    {
306
        $customer = Customer::findOne(2);
307
        $customer->name = null;
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __set, consider adding a @property annotation.
Loading history...
308
        $customer->save();
309
310
        $result = Customer::find()->where(['name' => null])->all();
311
        $this->assertCount(1, $result);
312
        $this->assertEquals(2, reset($result)->primaryKey);
313
    }
314
315
    public function testExists(): void
316
    {
317
        $this->assertTrue(Customer::find()->where(['id' => 2])->exists());
318
        $this->assertFalse(Customer::find()->where(['id' => 5])->exists());
319
        $this->assertTrue(Customer::find()->where(['name' => 'user1'])->exists());
320
        $this->assertFalse(Customer::find()->where(['name' => 'user5'])->exists());
321
322
        $this->assertTrue(Customer::find()->where(['id' => [2, 3]])->exists());
323
        $this->assertTrue(Customer::find()->where(['id' => [2, 3]])->offset(1)->exists());
324
        $this->assertFalse(Customer::find()->where(['id' => [2, 3]])->offset(2)->exists());
325
    }
326
327
    public function testFindLazy(): void
328
    {
329
        $customer = Customer::findOne(2);
330
        $this->assertFalse($customer->isRelationPopulated('orders'));
331
        $orders = $customer->orders;
0 ignored issues
show
Bug Best Practice introduced by
The property orders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
332
        $this->assertTrue($customer->isRelationPopulated('orders'));
333
        $this->assertCount(2, $orders);
334
        $this->assertCount(1, $customer->relatedRecords);
335
336
        unset($customer['orders']);
337
        $this->assertFalse($customer->isRelationPopulated('orders'));
338
339
        $customer = Customer::findOne(2);
340
        $this->assertFalse($customer->isRelationPopulated('orders'));
341
        $orders = $customer->getOrders()->where(['id' => 3])->all();
0 ignored issues
show
Bug introduced by
The method getOrders() does not exist on Yiisoft\ActiveRecord\ActiveRecord. It seems like you code against a sub-type of Yiisoft\ActiveRecord\ActiveRecord such as Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Customer or Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Category. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

341
        $orders = $customer->/** @scrutinizer ignore-call */ getOrders()->where(['id' => 3])->all();
Loading history...
342
        $this->assertFalse($customer->isRelationPopulated('orders'));
343
        $this->assertCount(0, $customer->relatedRecords);
344
        $this->assertCount(1, $orders);
345
        $this->assertEquals(3, $orders[0]->id);
346
    }
347
348
    public function testFindEager(): void
349
    {
350
        $this->loadFixture(Customer::getConnection());
0 ignored issues
show
Bug introduced by
It seems like loadFixture() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

350
        $this->/** @scrutinizer ignore-call */ 
351
               loadFixture(Customer::getConnection());
Loading history...
351
352
        $customers = Customer::find()->with('orders')->indexBy('id')->all();
353
354
        ksort($customers);
355
        $this->assertCount(3, $customers);
356
        $this->assertTrue($customers[1]->isRelationPopulated('orders'));
357
        $this->assertTrue($customers[2]->isRelationPopulated('orders'));
358
        $this->assertTrue($customers[3]->isRelationPopulated('orders'));
359
        $this->assertCount(1, $customers[1]->orders);
360
        $this->assertCount(2, $customers[2]->orders);
361
        $this->assertCount(0, $customers[3]->orders);
362
363
        unset($customers[1]->orders);
364
        $this->assertFalse($customers[1]->isRelationPopulated('orders'));
365
366
        $customer = Customer::find()->where(['id' => 1])->with('orders')->one();
367
        $this->assertTrue($customer->isRelationPopulated('orders'));
368
        $this->assertCount(1, $customer->orders);
0 ignored issues
show
Bug Best Practice introduced by
The property orders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
369
        $this->assertCount(1, $customer->relatedRecords);
370
371
        /** multiple with() calls */
372
        $orders = Order::find()->with('customer', 'items')->all();
373
        $this->assertCount(3, $orders);
374
        $this->assertTrue($orders[0]->isRelationPopulated('customer'));
0 ignored issues
show
Bug introduced by
The method isRelationPopulated() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\ActiveRecord\ActiveRecordInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

374
        $this->assertTrue($orders[0]->/** @scrutinizer ignore-call */ isRelationPopulated('customer'));
Loading history...
375
        $this->assertTrue($orders[0]->isRelationPopulated('items'));
376
377
        $orders = Order::find()->with('customer')->with('items')->all();
378
        $this->assertCount(3, $orders);
379
        $this->assertTrue($orders[0]->isRelationPopulated('customer'));
380
        $this->assertTrue($orders[0]->isRelationPopulated('items'));
381
    }
382
383
    public function testFindLazyVia(): void
384
    {
385
        /**
386
         * @var $this TestCase|ActiveRecordTestTrait
387
         * @var $order Order
388
         */
389
        $order = Order::findOne(1);
390
391
        $this->assertEquals(1, $order->id);
392
        $this->assertCount(2, $order->items);
0 ignored issues
show
Bug Best Practice introduced by
The property items does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
393
        $this->assertEquals(1, $order->items[0]->id);
394
        $this->assertEquals(2, $order->items[1]->id);
395
    }
396
397
    public function testFindEagerViaRelation(): void
398
    {
399
        /** @var $this TestCase|ActiveRecordTestTrait */
400
        $orders = Order::find()->with('items')->orderBy('id')->all();
401
402
        $this->assertCount(3, $orders);
403
        $order = $orders[0];
404
405
        $this->assertEquals(1, $order->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
406
        $this->assertTrue($order->isRelationPopulated('items'));
407
        $this->assertCount(2, $order->items);
0 ignored issues
show
Bug introduced by
Accessing items on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
408
        $this->assertEquals(1, $order->items[0]->id);
409
        $this->assertEquals(2, $order->items[1]->id);
410
    }
411
412
    public function testFindNestedRelation(): void
413
    {
414
        /** @var $this TestCase|ActiveRecordTestTrait */
415
        $customers = Customer::find()->with('orders', 'orders.items')->indexBy('id')->all();
416
417
        ksort($customers);
418
        $this->assertCount(3, $customers);
419
        $this->assertTrue($customers[1]->isRelationPopulated('orders'));
420
        $this->assertTrue($customers[2]->isRelationPopulated('orders'));
421
        $this->assertTrue($customers[3]->isRelationPopulated('orders'));
422
        $this->assertCount(1, $customers[1]->orders);
423
        $this->assertCount(2, $customers[2]->orders);
424
        $this->assertCount(0, $customers[3]->orders);
425
        $this->assertTrue($customers[1]->orders[0]->isRelationPopulated('items'));
426
        $this->assertTrue($customers[2]->orders[0]->isRelationPopulated('items'));
427
        $this->assertTrue($customers[2]->orders[1]->isRelationPopulated('items'));
428
        $this->assertCount(2, $customers[1]->orders[0]->items);
429
        $this->assertCount(3, $customers[2]->orders[0]->items);
430
        $this->assertCount(1, $customers[2]->orders[1]->items);
431
432
        $customers = Customer::find()->where(['id' => 1])->with('ordersWithItems')->one();
433
        $this->assertTrue($customers->isRelationPopulated('ordersWithItems'));
434
        $this->assertCount(1, $customers->ordersWithItems);
0 ignored issues
show
Bug Best Practice introduced by
The property ordersWithItems does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
435
436
        /** @var Order $order */
437
        $order = $customers->ordersWithItems[0];
438
        $this->assertTrue($order->isRelationPopulated('orderItems'));
439
        $this->assertCount(2, $order->orderItems);
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
440
    }
441
442
    /**
443
     * Ensure ActiveRelationTrait does preserve order of items on find via().
444
     *
445
     * {@see https://github.com/yiisoft/yii2/issues/1310.}
446
     */
447
    public function testFindEagerViaRelationPreserveOrder(): void
448
    {
449
        $orders = Order::find()->with('itemsInOrder1')->orderBy('created_at')->all();
450
        $this->assertCount(3, $orders);
451
452
        $order = $orders[0];
453
        $this->assertEquals(1, $order->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
454
        $this->assertTrue($order->isRelationPopulated('itemsInOrder1'));
455
        $this->assertCount(2, $order->itemsInOrder1);
0 ignored issues
show
Bug introduced by
Accessing itemsInOrder1 on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
456
        $this->assertEquals(1, $order->itemsInOrder1[0]->id);
457
        $this->assertEquals(2, $order->itemsInOrder1[1]->id);
458
459
        $order = $orders[1];
460
        $this->assertEquals(2, $order->id);
461
        $this->assertTrue($order->isRelationPopulated('itemsInOrder1'));
462
        $this->assertCount(3, $order->itemsInOrder1);
463
        $this->assertEquals(5, $order->itemsInOrder1[0]->id);
464
        $this->assertEquals(3, $order->itemsInOrder1[1]->id);
465
        $this->assertEquals(4, $order->itemsInOrder1[2]->id);
466
467
        $order = $orders[2];
468
        $this->assertEquals(3, $order->id);
469
        $this->assertTrue($order->isRelationPopulated('itemsInOrder1'));
470
        $this->assertCount(1, $order->itemsInOrder1);
471
        $this->assertEquals(2, $order->itemsInOrder1[0]->id);
472
    }
473
474
    public function testFindEagerViaRelationPreserveOrderB(): void
475
    {
476
        /**
477
         *  different order in via table.
478
         *
479
         *  @var Order \yii\db\ActiveRecordInterface
480
         */
481
        $orders = Order::find()->with('itemsInOrder2')->orderBy('created_at')->all();
482
        $this->assertCount(3, $orders);
483
484
        $order = $orders[0];
485
        $this->assertEquals(1, $order->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
486
        $this->assertTrue($order->isRelationPopulated('itemsInOrder2'));
487
        $this->assertCount(2, $order->itemsInOrder2);
0 ignored issues
show
Bug introduced by
Accessing itemsInOrder2 on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
488
        $this->assertEquals(1, $order->itemsInOrder2[0]->id);
489
        $this->assertEquals(2, $order->itemsInOrder2[1]->id);
490
491
        $order = $orders[1];
492
        $this->assertEquals(2, $order->id);
493
        $this->assertTrue($order->isRelationPopulated('itemsInOrder2'));
494
        $this->assertCount(3, $order->itemsInOrder2);
495
        $this->assertEquals(5, $order->itemsInOrder2[0]->id);
496
        $this->assertEquals(3, $order->itemsInOrder2[1]->id);
497
        $this->assertEquals(4, $order->itemsInOrder2[2]->id);
498
499
        $order = $orders[2];
500
        $this->assertEquals(3, $order->id);
501
        $this->assertTrue($order->isRelationPopulated('itemsInOrder2'));
502
        $this->assertCount(1, $order->itemsInOrder2);
503
        $this->assertEquals(2, $order->itemsInOrder2[0]->id);
504
    }
505
506
    public function testUnlink(): void
507
    {
508
        $this->loadFixture(Customer::getConnection());
509
510
        /**
511
         * has many without delete
512
         * @var $this TestCase|ActiveRecordTestTrait
513
         */
514
        $customer = Customer::findOne(2);
515
        $this->assertCount(2, $customer->ordersWithNullFK);
0 ignored issues
show
Bug Best Practice introduced by
The property ordersWithNullFK does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
516
        $customer->unlink('ordersWithNullFK', $customer->ordersWithNullFK[1], false);
517
        $this->assertCount(1, $customer->ordersWithNullFK);
518
519
        $orderWithNullFK = OrderWithNullFK::findOne(3);
520
        $this->assertEquals(3, $orderWithNullFK->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
521
        $this->assertNull($orderWithNullFK->customer_id);
0 ignored issues
show
Bug Best Practice introduced by
The property customer_id does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
522
523
        /** has many with delete */
524
        $customer = Customer::findOne(2);
525
        $this->assertCount(2, $customer->orders);
0 ignored issues
show
Bug Best Practice introduced by
The property orders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
526
        $customer->unlink('orders', $customer->orders[1], true);
527
        $this->assertCount(1, $customer->orders);
528
        $this->assertNull(Order::findOne(3));
529
530
        /** via model with delete */
531
        $order = Order::findOne(2);
532
        $this->assertCount(3, $order->items);
0 ignored issues
show
Bug Best Practice introduced by
The property items does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
533
        $this->assertCount(3, $order->orderItems);
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
534
        $order->unlink('items', $order->items[2], true);
535
        $this->assertCount(2, $order->items);
536
        $this->assertCount(2, $order->orderItems);
537
538
        /** via model without delete */
539
        $this->assertCount(3, $order->itemsWithNullFK);
0 ignored issues
show
Bug Best Practice introduced by
The property itemsWithNullFK does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
540
        $order->unlink('itemsWithNullFK', $order->itemsWithNullFK[2], false);
541
        $this->assertCount(2, $order->itemsWithNullFK);
542
        $this->assertCount(2, $order->orderItems);
543
    }
544
545
    public function testUnlinkAllAndConditionSetNull(): void
546
    {
547
        /** in this test all orders are owned by customer 1 */
548
        OrderWithNullFK::updateAll(['customer_id' => 1]);
549
550
        $customer = Customer::findOne(1);
551
        $this->assertCount(3, $customer->ordersWithNullFK);
0 ignored issues
show
Bug Best Practice introduced by
The property ordersWithNullFK does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
552
        $this->assertCount(1, $customer->expensiveOrdersWithNullFK);
0 ignored issues
show
Bug Best Practice introduced by
The property expensiveOrdersWithNullFK does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
553
        $this->assertEquals(3, OrderWithNullFK::find()->count());
554
555
        $customer->unlinkAll('expensiveOrdersWithNullFK');
556
        $this->assertCount(3, $customer->ordersWithNullFK);
557
        $this->assertCount(0, $customer->expensiveOrdersWithNullFK);
558
        $this->assertEquals(3, OrderWithNullFK::find()->count());
559
560
        $customer = Customer::findOne(1);
561
        $this->assertCount(2, $customer->ordersWithNullFK);
562
        $this->assertCount(0, $customer->expensiveOrdersWithNullFK);
563
    }
564
565
    public function testUnlinkAllAndConditionDelete(): void
566
    {
567
        $this->loadFixture(Customer::getConnection());
568
569
        /** in this test all orders are owned by customer 1 */
570
        Order::updateAll(['customer_id' => 1]);
571
572
        $customer = Customer::findOne(1);
573
        $this->assertCount(3, $customer->orders);
0 ignored issues
show
Bug Best Practice introduced by
The property orders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
574
        $this->assertCount(1, $customer->expensiveOrders);
0 ignored issues
show
Bug Best Practice introduced by
The property expensiveOrders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
575
        $this->assertEquals(3, Order::find()->count());
576
577
        $customer->unlinkAll('expensiveOrders', true);
578
        $this->assertCount(3, $customer->orders);
579
        $this->assertCount(0, $customer->expensiveOrders);
580
        $this->assertEquals(2, Order::find()->count());
581
582
        $customer = Customer::findOne(1);
583
        $this->assertCount(2, $customer->orders);
584
        $this->assertCount(0, $customer->expensiveOrders);
585
    }
586
587
    public function testInsert(): void
588
    {
589
        /** @var $this TestCase|ActiveRecordTestTrait */
590
        $customer = new Customer();
591
        $customer->email = '[email protected]';
592
        $customer->name = 'user4';
593
        $customer->address = 'address4';
594
595
        $this->assertNull($customer->id);
596
        $this->assertTrue($customer->isNewRecord);
597
598
        $customer->save();
599
600
        $this->assertNotNull($customer->id);
601
        $this->assertFalse($customer->isNewRecord);
602
    }
603
604
    public function testExplicitPkOnAutoIncrement()
605
    {
606
        /** @var $this TestCase|ActiveRecordTestTrait */
607
        $customer = new Customer();
608
        $customer->id = 1337;
609
        $customer->email = '[email protected]';
610
        $customer->name = 'user1337';
611
        $customer->address = 'address1337';
612
613
        $this->assertTrue($customer->isNewRecord);
614
        $customer->save();
615
616
        $this->assertEquals(1337, $customer->id);
617
        $this->assertFalse($customer->isNewRecord);
618
    }
619
620
    public function testUpdate()
621
    {
622
        $this->loadFixture(Customer::getConnection());
623
624
        /** @var $customer Customer */
625
        $customer = Customer::findOne(2);
626
        $this->assertInstanceOf(Customer::class, $customer);
627
        $this->assertEquals('user2', $customer->name);
628
        $this->assertFalse($customer->isNewRecord);
629
        $this->assertEmpty($customer->dirtyAttributes);
0 ignored issues
show
Bug introduced by
It seems like assertEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

629
        $this->/** @scrutinizer ignore-call */ 
630
               assertEmpty($customer->dirtyAttributes);
Loading history...
630
631
        $customer->name = 'user2x';
632
        $customer->save();
633
634
        $this->assertEquals('user2x', $customer->name);
635
        $this->assertFalse($customer->isNewRecord);
636
637
        $customer2 = Customer::findOne(2);
638
        $this->assertEquals('user2x', $customer2->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
639
640
        /** updateAll */
641
        $customer = Customer::findOne(3);
642
        $this->assertEquals('user3', $customer->name);
643
644
        $ret = Customer::updateAll(['name' => 'temp'], ['id' => 3]);
645
        $this->assertEquals(1, $ret);
646
647
        $customer = Customer::findOne(3);
648
        $this->assertEquals('temp', $customer->name);
649
650
        $ret = Customer::updateAll(['name' => 'tempX']);
651
        $this->assertEquals(3, $ret);
652
653
        $ret = Customer::updateAll(['name' => 'temp'], ['name' => 'user6']);
654
        $this->assertEquals(0, $ret);
655
    }
656
657
    public function testUpdateAttributes(): void
658
    {
659
        $this->loadFixture(Customer::getConnection());
660
661
        /** @var $customer Customer */
662
        $customer = Customer::findOne(2);
663
        $this->assertInstanceOf(Customer::class, $customer);
664
        $this->assertEquals('user2', $customer->name);
665
        $this->assertFalse($customer->isNewRecord);
666
667
        $customer->updateAttributes(['name' => 'user2x']);
668
        $this->assertEquals('user2x', $customer->name);
669
        $this->assertFalse($customer->isNewRecord);
670
671
        $customer2 = Customer::findOne(2);
672
        $this->assertEquals('user2x', $customer2->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
673
674
        $customer = Customer::findOne(1);
675
        $this->assertEquals('user1', $customer->name);
676
        $this->assertEquals(1, $customer->status);
0 ignored issues
show
Bug Best Practice introduced by
The property status does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
677
678
        $customer->name = 'user1x';
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __set, consider adding a @property annotation.
Loading history...
679
        $customer->status = 2;
0 ignored issues
show
Bug Best Practice introduced by
The property status does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __set, consider adding a @property annotation.
Loading history...
680
        $customer->updateAttributes(['name']);
681
        $this->assertEquals('user1x', $customer->name);
682
        $this->assertEquals(2, $customer->status);
683
684
        $customer = Customer::findOne(1);
685
        $this->assertEquals('user1x', $customer->name);
686
        $this->assertEquals(1, $customer->status);
687
    }
688
689
    public function testUpdateCounters(): void
690
    {
691
        $this->loadFixture(Customer::getConnection());
692
693
        /** updateCounters */
694
        $pk = ['order_id' => 2, 'item_id' => 4];
695
        $orderItem = OrderItem::findOne($pk);
696
        $this->assertEquals(1, $orderItem->quantity);
0 ignored issues
show
Bug Best Practice introduced by
The property quantity does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
697
698
        $ret = $orderItem->updateCounters(['quantity' => -1]);
699
        $this->assertEquals(1, $ret);
700
        $this->assertEquals(0, $orderItem->quantity);
701
702
        $orderItem = OrderItem::findOne($pk);
703
        $this->assertEquals(0, $orderItem->quantity);
704
705
        /** updateAllCounters */
706
        $pk = ['order_id' => 1, 'item_id' => 2];
707
        $orderItem = OrderItem::findOne($pk);
708
        $this->assertEquals(2, $orderItem->quantity);
709
710
        $ret = OrderItem::updateAllCounters([
711
            'quantity' => 3,
712
            'subtotal' => -10,
713
        ], $pk);
714
        $this->assertEquals(1, $ret);
715
716
        $orderItem = OrderItem::findOne($pk);
717
        $this->assertEquals(5, $orderItem->quantity);
718
        $this->assertEquals(30, $orderItem->subtotal);
0 ignored issues
show
Bug Best Practice introduced by
The property subtotal does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
719
    }
720
721
    public function testDelete(): void
722
    {
723
        /** delete */
724
        $customer = Customer::findOne(2);
725
        $this->assertInstanceOf(Customer::class, $customer);
726
        $this->assertEquals('user2', $customer->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
727
728
        $customer->delete();
729
730
        $customer = Customer::findOne(2);
731
        $this->assertNull($customer);
732
733
        /** deleteAll */
734
        $customers = Customer::find()->all();
735
        $this->assertCount(2, $customers);
736
737
        $ret = Customer::deleteAll();
738
        $this->assertEquals(2, $ret);
739
740
        $customers = Customer::find()->all();
741
        $this->assertCount(0, $customers);
742
743
        $ret = Customer::deleteAll();
744
        $this->assertEquals(0, $ret);
745
    }
746
747
    /**
748
     * Some PDO implementations (e.g. cubrid) do not support boolean values.
749
     *
750
     * Make sure this does not affect AR layer.
751
     */
752
    public function testBooleanAttribute(): void
753
    {
754
        $this->loadFixture(Customer::getConnection());
755
756
        /** @var $this TestCase|ActiveRecordTestTrait */
757
        $customer = new Customer();
758
        $customer->name = 'boolean customer';
759
        $customer->email = '[email protected]';
760
        $customer->status = true;
0 ignored issues
show
Documentation Bug introduced by
The property $status was declared of type integer, but true is of type true. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
761
762
        $customer->save();
763
        $customer->refresh();
764
        $this->assertEquals(1, $customer->status);
765
766
        $customer->status = false;
767
        $customer->save();
768
769
        $customer->refresh();
770
        $this->assertEquals(0, $customer->status);
771
772
        $customers = Customer::find()->where(['status' => true])->all();
773
        $this->assertCount(2, $customers);
774
775
        $customers = Customer::find()->where(['status' => false])->all();
776
        $this->assertCount(1, $customers);
777
    }
778
779
    public function testFindEmptyInCondition(): void
780
    {
781
        $this->loadFixture(Customer::getConnection());
782
783
        /** @var $this TestCase|ActiveRecordTestTrait */
784
        $customers = Customer::find()->where(['id' => [1]])->all();
785
        $this->assertCount(1, $customers);
786
787
        $customers = Customer::find()->where(['id' => []])->all();
788
        $this->assertCount(0, $customers);
789
790
        $customers = Customer::find()->where(['IN', 'id', [1]])->all();
791
        $this->assertCount(1, $customers);
792
793
        $customers = Customer::find()->where(['IN', 'id', []])->all();
794
        $this->assertCount(0, $customers);
795
    }
796
797
    public function testFindEagerIndexBy(): void
798
    {
799
        $this->loadFixture(Customer::getConnection());
800
801
        /** @var $order Order */
802
        $order = Order::find()->with('itemsIndexed')->where(['id' => 1])->one();
803
        $this->assertTrue($order->isRelationPopulated('itemsIndexed'));
804
805
        $items = $order->itemsIndexed;
0 ignored issues
show
Bug Best Practice introduced by
The property itemsIndexed does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
806
        $this->assertCount(2, $items);
807
        $this->assertTrue(isset($items[1]));
808
        $this->assertTrue(isset($items[2]));
809
810
        /** @var $order Order */
811
        $order = Order::find()->with('itemsIndexed')->where(['id' => 2])->one();
812
        $this->assertTrue($order->isRelationPopulated('itemsIndexed'));
813
814
        $items = $order->itemsIndexed;
815
        $this->assertCount(3, $items);
816
        $this->assertTrue(isset($items[3]));
817
        $this->assertTrue(isset($items[4]));
818
        $this->assertTrue(isset($items[5]));
819
    }
820
821
    public function testAttributeAccess(): void
822
    {
823
        /** @var Customer \Yiisoft\ActiveRecord\ActiveRecordInterface */
824
        $model = new Customer();
825
826
        $this->assertTrue($model->canSetProperty('name'));
827
        $this->assertTrue($model->canGetProperty('name'));
828
        $this->assertFalse($model->canSetProperty('unExistingColumn'));
829
        $this->assertFalse(isset($model->name));
830
831
        $model->name = 'foo';
832
        $this->assertTrue(isset($model->name));
833
834
        unset($model->name);
835
        $this->assertNull($model->name);
836
837
        /** {@see https://github.com/yiisoft/yii2-gii/issues/190} */
838
        $baseModel = new Customer();
839
        $this->assertFalse($baseModel->hasProperty('unExistingColumn'));
840
841
842
        /** @var $customer ActiveRecord */
843
        $customer = new Customer();
844
        $this->assertInstanceOf(Customer::class, $customer);
845
        $this->assertTrue($customer->canGetProperty('id'));
846
        $this->assertTrue($customer->canSetProperty('id'));
847
848
        /** tests that we really can get and set this property */
849
        $this->assertNull($customer->id);
850
        $customer->id = 10;
851
        $this->assertNotNull($customer->id);
852
853
        /** Let's test relations */
854
        $this->assertTrue($customer->canGetProperty('orderItems'));
855
        $this->assertFalse($customer->canSetProperty('orderItems'));
856
857
        /** Newly created model must have empty relation */
858
        $this->assertSame([], $customer->orderItems);
0 ignored issues
show
Bug introduced by
It seems like assertSame() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

858
        $this->/** @scrutinizer ignore-call */ 
859
               assertSame([], $customer->orderItems);
Loading history...
859
860
        /** does it still work after accessing the relation? */
861
        $this->assertTrue($customer->canGetProperty('orderItems'));
862
        $this->assertFalse($customer->canSetProperty('orderItems'));
863
864
        try {
865
            /** @var $itemClass ActiveRecordInterface */
866
            $customer->orderItems = [new Item()];
867
            $this->fail('setter call above MUST throw Exception');
0 ignored issues
show
Bug introduced by
It seems like fail() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

867
            $this->/** @scrutinizer ignore-call */ 
868
                   fail('setter call above MUST throw Exception');
Loading history...
868
        } catch (\Exception $e) {
869
            /** catch exception "Setting read-only property" */
870
            $this->assertInstanceOf(InvalidCallException::class, $e);
871
        }
872
873
        /** related attribute $customer->orderItems didn't change cause it's read-only */
874
        $this->assertSame([], $customer->orderItems);
875
        $this->assertFalse($customer->canGetProperty('non_existing_property'));
876
        $this->assertFalse($customer->canSetProperty('non_existing_property'));
877
    }
878
879
    /**
880
     * {@see https://github.com/yiisoft/yii2/issues/17089}
881
     */
882
    public function testViaWithCallable(): void
883
    {
884
        $this->loadFixture(Customer::getConnection());
885
886
        /** @var Order $order */
887
        $order = Order::findOne(2);
888
889
        $expensiveItems = $order->expensiveItemsUsingViaWithCallable;
0 ignored issues
show
Bug Best Practice introduced by
The property expensiveItemsUsingViaWithCallable does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
890
        $cheapItems = $order->cheapItemsUsingViaWithCallable;
0 ignored issues
show
Bug Best Practice introduced by
The property cheapItemsUsingViaWithCallable does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
891
892
        $this->assertCount(2, $expensiveItems);
893
        $this->assertEquals(4, $expensiveItems[0]->id);
894
        $this->assertEquals(5, $expensiveItems[1]->id);
895
        $this->assertCount(1, $cheapItems);
896
        $this->assertEquals(3, $cheapItems[0]->id);
897
    }
898
899
    public function testLink()
900
    {
901
        $this->loadFixture(Customer::getConnection());
902
903
        $customer = Customer::findOne(2);
904
        $this->assertCount(2, $customer->orders);
0 ignored issues
show
Bug Best Practice introduced by
The property orders does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
905
906
        /** has many */
907
        $order = new Order();
908
        $order->total = 100;
909
        $order->created_at = time();
910
        $this->assertTrue($order->isNewRecord);
911
912
        /** belongs to */
913
        $order = new Order();
914
        $order->total = 100;
915
        $order->created_at = time();
916
        $this->assertTrue($order->isNewRecord);
917
918
        $customer = Customer::findOne(1);
919
        $this->assertNull($order->customer);
0 ignored issues
show
Bug Best Practice introduced by
The property customer does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
920
921
        $order->link('customer', $customer);
922
        $this->assertFalse($order->isNewRecord);
923
        $this->assertEquals(1, $order->customer_id);
924
        $this->assertEquals(1, $order->customer->primaryKey);
925
926
        /** via model */
927
        $order = Order::findOne(1);
928
        $this->assertCount(2, $order->items);
0 ignored issues
show
Bug Best Practice introduced by
The property items does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
929
        $this->assertCount(2, $order->orderItems);
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
930
931
        $orderItem = OrderItem::findOne(['order_id' => 1, 'item_id' => 3]);
932
        $this->assertNull($orderItem);
933
934
        $item = Item::findOne(3);
935
        $order->link('items', $item, ['quantity' => 10, 'subtotal' => 100]);
936
        $this->assertCount(3, $order->items);
937
        $this->assertCount(3, $order->orderItems);
938
939
        $orderItem = OrderItem::findOne(['order_id' => 1, 'item_id' => 3]);
940
        $this->assertInstanceOf(OrderItem::class, $orderItem);
941
        $this->assertEquals(10, $orderItem->quantity);
0 ignored issues
show
Bug Best Practice introduced by
The property quantity does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
942
        $this->assertEquals(100, $orderItem->subtotal);
0 ignored issues
show
Bug Best Practice introduced by
The property subtotal does not exist on Yiisoft\ActiveRecord\ActiveRecord. Since you implemented __get, consider adding a @property annotation.
Loading history...
943
    }
944
}
945