Passed
Pull Request — master (#368)
by Sergei
03:20
created

MagicActiveRecordTest::createConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Tests\Driver\Pgsql;
6
7
use ArrayAccess;
8
use Traversable;
9
use Yiisoft\ActiveRecord\ActiveQuery;
10
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\ArrayAndJsonTypes;
11
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Beta;
12
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\BoolAR;
13
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Customer;
14
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\CustomerClosureField;
15
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\DefaultPk;
16
use Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\UserAR;
17
use Yiisoft\ActiveRecord\Tests\Support\PgsqlHelper;
18
use Yiisoft\Db\Connection\ConnectionInterface;
19
use Yiisoft\Db\Expression\ArrayExpression;
20
use Yiisoft\Db\Expression\Expression;
21
use Yiisoft\Db\Expression\JsonExpression;
22
use Yiisoft\Db\Pgsql\Schema as SchemaPgsql;
23
24
final class MagicActiveRecordTest extends \Yiisoft\ActiveRecord\Tests\MagicActiveRecordTest
0 ignored issues
show
Bug introduced by
The type Yiisoft\ActiveRecord\Tests\MagicActiveRecordTest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
{
26
    protected function createConnection(): ConnectionInterface
27
    {
28
        return (new PgsqlHelper())->createConnection();
29
    }
30
31
    public function testExplicitPkOnAutoIncrement(): void
32
    {
33
        $this->checkFixture($this->db(), 'customer');
34
35
        $customer = new Customer();
36
        $customer->id = 1337;
37
        $customer->email = '[email protected]';
38
        $customer->name = 'user1337';
39
        $customer->address = 'address1337';
40
        $this->assertTrue($customer->isNewRecord);
0 ignored issues
show
Bug Best Practice introduced by
The property isNewRecord does not exist on Yiisoft\ActiveRecord\Tes...icActiveRecord\Customer. Since you implemented __get, consider adding a @property annotation.
Loading history...
41
42
        $customer->save();
43
        $this->assertEquals(1337, $customer->id);
44
        $this->assertFalse($customer->isNewRecord);
45
    }
46
47
    /**
48
     * {@see https://github.com/yiisoft/yii2/issues/15482}
49
     */
50
    public function testEagerLoadingUsingStringIdentifiers(): void
51
    {
52
        $this->checkFixture($this->db(), 'beta');
53
54
        $betaQuery = new ActiveQuery(Beta::class);
55
        $betas = $betaQuery->with('alpha')->all();
56
        $this->assertNotEmpty($betas);
57
58
        $alphaIdentifiers = [];
59
60
        /** @var Beta[] $betas */
61
        foreach ($betas as $beta) {
62
            $this->assertNotNull($beta->alpha);
63
            $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier);
64
            $alphaIdentifiers[] = $beta->alpha->string_identifier;
65
        }
66
67
        $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers);
68
    }
69
70
    public function testBooleanAttribute(): void
71
    {
72
        $this->checkFixture($this->db(), 'customer', true);
73
74
        $customer = new Customer();
75
        $customer->name = 'boolean customer';
76
        $customer->email = '[email protected]';
77
        $customer->bool_status = false;
0 ignored issues
show
Bug Best Practice introduced by
The property bool_status does not exist on Yiisoft\ActiveRecord\Tes...icActiveRecord\Customer. Since you implemented __set, consider adding a @property annotation.
Loading history...
78
        $customer->save();
79
80
        $customer->refresh();
81
        $this->assertFalse($customer->bool_status);
0 ignored issues
show
Bug Best Practice introduced by
The property bool_status does not exist on Yiisoft\ActiveRecord\Tes...icActiveRecord\Customer. Since you implemented __get, consider adding a @property annotation.
Loading history...
82
83
        $customer->bool_status = true;
84
85
        $customer->save();
86
        $customer->refresh();
87
        $this->assertTrue($customer->bool_status);
88
89
        $customerQuery = new ActiveQuery(Customer::class);
90
        $customers = $customerQuery->where(['bool_status' => true])->all();
91
        $this->assertCount(3, $customers);
92
93
        $customers = $customerQuery->where(['bool_status' => false])->all();
94
        $this->assertCount(1, $customers);
95
    }
96
97
    public function testBooleanValues(): void
98
    {
99
        $this->checkFixture($this->db(), 'bool_values');
100
101
        $command = $this->db()->createCommand();
102
        $command->batchInsert('bool_values', ['bool_col'], [[true], [false]])->execute();
103
        $boolARQuery = new ActiveQuery(BoolAR::class);
104
105
        $this->assertTrue($boolARQuery->where(['bool_col' => true])->onePopulate()->bool_col);
0 ignored issues
show
Bug introduced by
Accessing bool_col on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
106
        $this->assertFalse($boolARQuery->where(['bool_col' => false])->onePopulate()->bool_col);
107
108
        $this->assertEquals(1, $boolARQuery->where('bool_col = TRUE')->count('*'));
109
        $this->assertEquals(1, $boolARQuery->where('bool_col = FALSE')->count('*'));
110
        $this->assertEquals(2, $boolARQuery->where('bool_col IN (TRUE, FALSE)')->count('*'));
111
112
        $this->assertEquals(1, $boolARQuery->where(['bool_col' => true])->count('*'));
113
        $this->assertEquals(1, $boolARQuery->where(['bool_col' => false])->count('*'));
114
        $this->assertEquals(2, $boolARQuery->where(['bool_col' => [true, false]])->count('*'));
115
116
        $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => true])->count('*'));
117
        $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => false])->count('*'));
118
    }
119
120
    /**
121
     * {@see https://github.com/yiisoft/yii2/issues/4672}
122
     */
123
    public function testBooleanValues2(): void
124
    {
125
        $this->checkFixture($this->db(), 'bool_user');
126
127
        //$this->db()->setCharset('utf8');
128
        $this->db()->createCommand('DROP TABLE IF EXISTS bool_user;')->execute();
129
        $this->db()->createCommand()->createTable('bool_user', [
130
            'id' => SchemaPgsql::TYPE_PK,
131
            'username' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
132
            'auth_key' => SchemaPgsql::TYPE_STRING . '(32) NOT NULL',
133
            'password_hash' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
134
            'password_reset_token' => SchemaPgsql::TYPE_STRING,
135
            'email' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
136
            'role' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',
137
            'status' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',
138
            'created_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL',
139
            'updated_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL',
140
        ])->execute();
141
        $this->db()->createCommand()->addColumn(
142
            'bool_user',
143
            'is_deleted',
144
            SchemaPgsql::TYPE_BOOLEAN . ' NOT NULL DEFAULT FALSE'
145
        )->execute();
146
147
        $user = new UserAR();
148
        $user->username = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property username does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
149
        $user->auth_key = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property auth_key does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
150
        $user->password_hash = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property password_hash does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
151
        $user->email = '[email protected]';
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
152
        $user->created_at = time();
0 ignored issues
show
Bug Best Practice introduced by
The property created_at does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
153
        $user->updated_at = time();
0 ignored issues
show
Bug Best Practice introduced by
The property updated_at does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
154
        $user->save();
155
156
        $userQuery = new ActiveQuery(UserAR::class);
157
        $this->assertCount(1, $userQuery->where(['is_deleted' => false])->all());
158
        $this->assertCount(0, $userQuery->where(['is_deleted' => true])->all());
159
        $this->assertCount(1, $userQuery->where(['is_deleted' => [true, false]])->all());
160
    }
161
162
    public function testBooleanDefaultValues(): void
163
    {
164
        $this->checkFixture($this->db(), 'bool_values');
165
166
        $arClass = new BoolAR();
167
168
        $this->assertNull($arClass->bool_col);
0 ignored issues
show
Bug Best Practice introduced by
The property bool_col does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
169
        $this->assertNull($arClass->default_true);
0 ignored issues
show
Bug Best Practice introduced by
The property default_true does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
170
        $this->assertNull($arClass->default_false);
0 ignored issues
show
Bug Best Practice introduced by
The property default_false does not exist on Yiisoft\ActiveRecord\Tes...agicActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
171
172
        $arClass->loadDefaultValues();
173
174
        $this->assertNull($arClass->bool_col);
175
        $this->assertTrue($arClass->default_true);
176
        $this->assertFalse($arClass->default_false);
177
        $this->assertTrue($arClass->save());
178
    }
179
180
    public function testPrimaryKeyAfterSave(): void
181
    {
182
        $this->checkFixture($this->db(), 'default_pk');
183
184
        $record = new DefaultPk();
185
186
        $record->type = 'type';
0 ignored issues
show
Bug Best Practice introduced by
The property type does not exist on Yiisoft\ActiveRecord\Tes...cActiveRecord\DefaultPk. Since you implemented __set, consider adding a @property annotation.
Loading history...
187
188
        $record->save();
189
190
        $this->assertEquals(5, $record->primaryKey);
0 ignored issues
show
Bug Best Practice introduced by
The property primaryKey does not exist on Yiisoft\ActiveRecord\Tes...cActiveRecord\DefaultPk. Since you implemented __get, consider adding a @property annotation.
Loading history...
191
    }
192
193
    public static function arrayValuesProvider(): array
194
    {
195
        return [
196
            'simple arrays values' => [[
197
                'intarray_col' => [
198
                    new ArrayExpression([1,-2,null,'42'], 'int4', 1),
199
                    new ArrayExpression([1,-2,null,42], 'int4', 1),
200
                ],
201
                'textarray2_col' => [
202
                    new ArrayExpression([['text'], [null], [1]], 'text', 2),
203
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
204
                ],
205
                'json_col' => [['a' => 1, 'b' => null, 'c' => [1,3,5]]],
206
                'jsonb_col' => [[null, 'a', 'b', '\"', '{"af"}']],
207
                'jsonarray_col' => [new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json')],
208
            ]],
209
            'null arrays values' => [[
210
                'intarray_col' => [
211
                    null,
212
                ],
213
                'textarray2_col' => [
214
                    [null, null],
215
                    new ArrayExpression([null, null], 'text', 2),
216
                ],
217
                'json_col' => [
218
                    null,
219
                ],
220
                'jsonarray_col' => [
221
                    null,
222
                ],
223
            ]],
224
            'empty arrays values' => [[
225
                'textarray2_col' => [
226
                    [[], []],
227
                    new ArrayExpression([], 'text', 2),
228
                ],
229
            ]],
230
            'nested objects' => [[
231
                'intarray_col' => [
232
                    new ArrayExpression(new ArrayExpression([1,2,3]), 'int', 1),
233
                    new ArrayExpression([1,2,3], 'int4', 1),
234
                ],
235
                'textarray2_col' => [
236
                    new ArrayExpression([new ArrayExpression(['text']), [null], [1]], 'text', 2),
237
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
238
                ],
239
                'json_col' => [
240
                    new JsonExpression(new JsonExpression(new JsonExpression(['a' => 1, 'b' => null, 'c' => new JsonExpression([1,3,5])]))),
241
                    ['a' => 1, 'b' => null, 'c' => [1,3,5]],
242
                ],
243
                'jsonb_col' => [
244
                    new JsonExpression(new ArrayExpression([1,2,3])),
245
                    [1,2,3],
246
                ],
247
                'jsonarray_col' => [
248
                    new ArrayExpression([new JsonExpression(['1', 2]), [3,4,5]], 'json'),
249
                    new ArrayExpression([['1', 2], [3,4,5]], 'json'),
250
                ],
251
            ]],
252
            'arrays packed in classes' => [[
253
                'intarray_col' => [
254
                    new ArrayExpression([1,-2,null,'42'], 'int', 1),
255
                    new ArrayExpression([1,-2,null,42], 'int4', 1),
256
                ],
257
                'textarray2_col' => [
258
                    new ArrayExpression([['text'], [null], [1]], 'text', 2),
259
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
260
                ],
261
                'json_col' => [
262
                    new JsonExpression(['a' => 1, 'b' => null, 'c' => [1,3,5]]),
263
                    ['a' => 1, 'b' => null, 'c' => [1,3,5]],
264
                ],
265
                'jsonb_col' => [
266
                    new JsonExpression([null, 'a', 'b', '\"', '{"af"}']),
267
                    [null, 'a', 'b', '\"', '{"af"}'],
268
                ],
269
                'jsonarray_col' => [
270
                    new Expression("array['[\",\",\"null\",true,\"false\",\"f\"]'::json]::json[]"),
271
                    new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json'),
272
                ],
273
            ]],
274
            'scalars' => [[
275
                'json_col' => [
276
                    '5.8',
277
                ],
278
                'jsonb_col' => [
279
                    M_PI,
280
                ],
281
            ]],
282
        ];
283
    }
284
285
    /**
286
     * @dataProvider arrayValuesProvider
287
     */
288
    public function testArrayValues($attributes): void
289
    {
290
        $this->checkFixture($this->db(), 'array_and_json_types', true);
291
292
        $type = new ArrayAndJsonTypes();
293
294
        foreach ($attributes as $attribute => $expected) {
295
            $type->$attribute = $expected[0];
296
        }
297
298
        $type->save();
299
300
        $typeQuery = new ActiveQuery($type::class);
301
302
        $type = $typeQuery->onePopulate();
303
304
        foreach ($attributes as $attribute => $expected) {
305
            $expected = $expected[1] ?? $expected[0];
306
            $value = $type->$attribute;
307
308
            if ($expected instanceof ArrayExpression) {
309
                $expected = $expected->getValue();
310
            }
311
312
            $this->assertEquals($expected, $value, 'In column ' . $attribute);
313
314
            if ($value instanceof ArrayExpression) {
315
                $this->assertInstanceOf(ArrayAccess::class, $value);
316
                $this->assertInstanceOf(Traversable::class, $value);
317
                /** testing arrayaccess */
318
                foreach ($type->$attribute as $key => $v) {
319
                    $this->assertSame($expected[$key], $value[$key]);
320
                }
321
            }
322
        }
323
324
        /** Testing update */
325
        foreach ($attributes as $attribute => $expected) {
326
            $type->markAttributeDirty($attribute);
0 ignored issues
show
Bug introduced by
The method markAttributeDirty() 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

326
            $type->/** @scrutinizer ignore-call */ 
327
                   markAttributeDirty($attribute);
Loading history...
327
        }
328
329
        $this->assertSame(1, $type->update(), 'The record got updated');
330
    }
331
332
    public function testToArray(): void
333
    {
334
        $this->checkFixture($this->db(), 'customer', true);
335
336
        $customerQuery = new ActiveQuery(Customer::class);
337
        $customer = $customerQuery->findOne(1);
338
339
        $this->assertSame(
340
            [
341
                'id' => 1,
342
                'email' => '[email protected]',
343
                'name' => 'user1',
344
                'address' => 'address1',
345
                'status' => 1,
346
                'bool_status' => true,
347
                'profile_id' => 1,
348
            ],
349
            $customer->toArray(),
0 ignored issues
show
Bug introduced by
The method toArray() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. It seems like you code against a sub-type of Yiisoft\ActiveRecord\ActiveRecordInterface such as Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord or Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord. ( Ignorable by Annotation )

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

349
            $customer->/** @scrutinizer ignore-call */ 
350
                       toArray(),
Loading history...
350
        );
351
    }
352
353
    public function testToArrayWithClosure(): void
354
    {
355
        $this->checkFixture($this->db(), 'customer', true);
356
357
        $customerQuery = new ActiveQuery(CustomerClosureField::class);
358
        $customer = $customerQuery->findOne(1);
359
360
        $this->assertSame(
361
            [
362
                'id' => 1,
363
                'email' => '[email protected]',
364
                'name' => 'user1',
365
                'address' => 'address1',
366
                'status' => 'active',
367
                'bool_status' => true,
368
                'profile_id' => 1,
369
            ],
370
            $customer->toArray(),
371
        );
372
    }
373
}
374