Test Failed
Pull Request — master (#315)
by Sergei
02:49
created

ArrayColumnSchema::phpTypecast()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 26
rs 9.2222
cc 6
nc 8
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql\Column;
6
7
use Yiisoft\Db\Expression\ArrayExpression;
8
use Yiisoft\Db\Expression\ExpressionInterface;
9
use Yiisoft\Db\Pgsql\ArrayParser;
10
use Yiisoft\Db\Pgsql\Schema;
11
use Yiisoft\Db\Schema\Column\AbstractColumnSchema;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Schema\Column\AbstractColumnSchema 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...
12
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Schema\Column\ColumnSchemaInterface 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...
13
use Yiisoft\Db\Schema\Column\DoubleColumnSchema;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Schema\Column\DoubleColumnSchema 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...
14
use Yiisoft\Db\Schema\Column\JsonColumnSchema;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Schema\Column\JsonColumnSchema 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...
15
use Yiisoft\Db\Schema\Column\StringColumnSchema;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Schema\Column\StringColumnSchema 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...
16
use Yiisoft\Db\Schema\SchemaInterface;
17
18
use function array_map;
19
use function array_walk_recursive;
20
use function is_array;
21
use function is_iterable;
22
use function is_string;
23
24
final class ArrayColumnSchema extends AbstractColumnSchema
25
{
26
    private ColumnSchemaInterface|null $column = null;
27
28
    /**
29
     * @var int The dimension of array, must be greater than 0.
30
     */
31
    private int $dimension = 1;
32
33
    /**
34
     * Set dimension of an array, must be greater than 0.
35
     */
36
    public function dimension(int $dimension): void
37
    {
38
        $this->dimension = $dimension;
39
    }
40
41
    private function getColumn(): ColumnSchemaInterface
42
    {
43
        if ($this->column === null) {
44
            if ($this->getType() === Schema::TYPE_BIT) {
45
                $this->column = new BitColumnSchema($this->getName());
46
                $this->column->size($this->getSize());
0 ignored issues
show
Bug introduced by
The method size() does not exist on null. ( Ignorable by Annotation )

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

46
                $this->column->/** @scrutinizer ignore-call */ 
47
                               size($this->getSize());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
47
            } else {
48
                $this->column = match ($this->getPhpType()) {
49
                    SchemaInterface::PHP_TYPE_INTEGER => new IntegerColumnSchema($this->getName()),
50
                    SchemaInterface::PHP_TYPE_DOUBLE => new DoubleColumnSchema($this->getName()),
51
                    SchemaInterface::PHP_TYPE_BOOLEAN => new BooleanColumnSchema($this->getName()),
52
                    SchemaInterface::PHP_TYPE_RESOURCE => new BinaryColumnSchema($this->getName()),
53
                    SchemaInterface::PHP_TYPE_ARRAY => new JsonColumnSchema($this->getName()),
54
                    default => new StringColumnSchema($this->getName()),
55
                };
56
            }
57
        }
58
59
        return $this->column;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->column could return the type null which is incompatible with the type-hinted return Yiisoft\Db\Schema\Column\ColumnSchemaInterface. Consider adding an additional type-check to rule them out.
Loading history...
60
    }
61
62
    /**
63
     * @return int Get the dimension of the array.
64
     */
65
    public function getDimension(): int
66
    {
67
        return $this->dimension;
68
    }
69
70
    public function dbTypecast(mixed $value): ExpressionInterface|null
71
    {
72
        if ($value === null || $value instanceof ExpressionInterface) {
73
            return $value;
74
        }
75
76
        if ($this->dimension === 1 && is_array($value)) {
77
            $value = array_map([$this->getColumn(), 'dbTypecast'], $value);
78
        } else {
79
            $value = $this->dbTypecastArray($value, $this->dimension);
80
        }
81
82
        return new ArrayExpression($value, $this->getDbType(), $this->dimension);
83
    }
84
85
    /**
86
     * Recursively converts array values for use in a db query.
87
     *
88
     * @param mixed $value The array or iterable object.
89
     * @param int $dimension The array dimension. Should be more than 0.
90
     *
91
     * @return array|null Converted values.
92
     */
93
    private function dbTypecastArray(mixed $value, int $dimension): array|null
94
    {
95
        if ($value === null) {
96
            return null;
97
        }
98
99
        if (!is_iterable($value)) {
100
            return [];
101
        }
102
103
        $items = [];
104
        $column = $this->getColumn();
105
106
        /** @psalm-var mixed $val */
107
        foreach ($value as $val) {
108
            if ($dimension > 1) {
109
                $items[] = $this->dbTypecastArray($val, $dimension - 1);
110
            } else {
111
                /** @psalm-var mixed */
112
                $items[] = $column->dbTypecast($val);
113
            }
114
        }
115
116
        return $items;
117
    }
118
119
    public function phpTypecast(mixed $value): array|null
120
    {
121
        if (is_string($value)) {
122
            $value = (new ArrayParser())->parse($value);
123
        }
124
125
        if (!is_array($value)) {
126
            return null;
127
        }
128
129
        if ($this->getType() === SchemaInterface::TYPE_STRING) {
130
            return $value;
131
        }
132
133
        $column = $this->getColumn();
134
135
        if ($this->dimension === 1 && $this->getType() !== SchemaInterface::TYPE_JSON) {
136
            return array_map([$column, 'phpTypecast'], $value);
137
        }
138
139
        array_walk_recursive($value, function (string|null &$val) use ($column): void {
140
            /** @psalm-var mixed $val */
141
            $val = $column->phpTypecast($val);
142
        });
143
144
        return $value;
145
    }
146
}
147