Test Failed
Pull Request — master (#315)
by Sergei
15:26 queued 02:13
created

ArrayColumnSchema   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 24
eloc 54
c 1
b 0
f 0
dl 0
loc 130
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A dimension() 0 3 1
A dbTypecastArray() 0 27 6
A dbTypecast() 0 13 5
A getDimension() 0 3 1
A phpTypecast() 0 26 6
A getColumn() 0 25 5
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
            } elseif (PHP_INT_SIZE !== 8 && $this->getType() === SchemaInterface::TYPE_BIGINT) {
48
                $this->column = new BigIntColumnSchema($this->getName());
49
            } else {
50
                $this->column = match ($this->getPhpType()) {
51
                    SchemaInterface::PHP_TYPE_INTEGER => new IntegerColumnSchema($this->getName()),
52
                    SchemaInterface::PHP_TYPE_DOUBLE => new DoubleColumnSchema($this->getName()),
53
                    SchemaInterface::PHP_TYPE_BOOLEAN => new BooleanColumnSchema($this->getName()),
54
                    SchemaInterface::PHP_TYPE_RESOURCE => new BinaryColumnSchema($this->getName()),
55
                    SchemaInterface::PHP_TYPE_ARRAY => new JsonColumnSchema($this->getName()),
56
                    default => new StringColumnSchema($this->getName()),
57
                };
58
            }
59
60
            $this->column->dbType($this->getDbType());
61
            $this->column->type($this->getType());
62
            $this->column->phpType($this->getPhpType());
63
        }
64
65
        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...
66
    }
67
68
    /**
69
     * @return int Get the dimension of the array.
70
     */
71
    public function getDimension(): int
72
    {
73
        return $this->dimension;
74
    }
75
76
    public function dbTypecast(mixed $value): ExpressionInterface|null
77
    {
78
        if ($value === null || $value instanceof ExpressionInterface) {
79
            return $value;
80
        }
81
82
        if ($this->dimension === 1 && is_array($value)) {
83
            $value = array_map([$this->getColumn(), 'dbTypecast'], $value);
84
        } else {
85
            $value = $this->dbTypecastArray($value, $this->dimension);
86
        }
87
88
        return new ArrayExpression($value, $this->getDbType(), $this->dimension);
89
    }
90
91
    /**
92
     * Recursively converts array values for use in a db query.
93
     *
94
     * @param mixed $value The array or iterable object.
95
     * @param int $dimension The array dimension. Should be more than 0.
96
     *
97
     * @return array|null Converted values.
98
     */
99
    private function dbTypecastArray(mixed $value, int $dimension): array|null
100
    {
101
        if ($value === null) {
102
            return null;
103
        }
104
105
        if (!is_iterable($value)) {
106
            return [];
107
        }
108
109
        $items = [];
110
        $column = $this->getColumn();
111
112
        if ($dimension > 1) {
113
            /** @psalm-var mixed $val */
114
            foreach ($value as $val) {
115
                $items[] = $this->dbTypecastArray($val, $dimension - 1);
116
            }
117
        } else {
118
            /** @psalm-var mixed $val */
119
            foreach ($value as $val) {
120
                /** @psalm-var mixed */
121
                $items[] = $column->dbTypecast($val);
122
            }
123
        }
124
125
        return $items;
126
    }
127
128
    public function phpTypecast(mixed $value): array|null
129
    {
130
        if (is_string($value)) {
131
            $value = (new ArrayParser())->parse($value);
132
        }
133
134
        if (!is_array($value)) {
135
            return null;
136
        }
137
138
        if ($this->getType() === SchemaInterface::TYPE_STRING) {
139
            return $value;
140
        }
141
142
        $column = $this->getColumn();
143
144
        if ($this->dimension === 1 && $this->getType() !== SchemaInterface::TYPE_JSON) {
145
            return array_map([$column, 'phpTypecast'], $value);
146
        }
147
148
        array_walk_recursive($value, function (string|null &$val) use ($column): void {
149
            /** @psalm-var mixed $val */
150
            $val = $column->phpTypecast($val);
151
        });
152
153
        return $value;
154
    }
155
}
156