Passed
Push — master ( 5d4ac5...0241ad )
by Smoren
02:53 queued 36s
created

ArrayViewAccessTrait::toSelector()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 24
rs 7.6666
cc 10
nc 10
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\ArrayView\Traits;
6
7
use Smoren\ArrayView\Exceptions\IndexError;
8
use Smoren\ArrayView\Exceptions\KeyError;
9
use Smoren\ArrayView\Exceptions\NotSupportedError;
10
use Smoren\ArrayView\Exceptions\ReadonlyError;
11
use Smoren\ArrayView\Interfaces\ArraySelectorInterface;
12
use Smoren\ArrayView\Interfaces\ArrayViewInterface;
13
use Smoren\ArrayView\Selectors\IndexListSelector;
14
use Smoren\ArrayView\Selectors\MaskSelector;
15
use Smoren\ArrayView\Selectors\SliceSelector;
16
use Smoren\ArrayView\Structs\Slice;
17
use Smoren\ArrayView\Util;
18
19
/**
20
 * Trait providing methods for accessing elements in ArrayView object.
21
 * The trait implements methods for accessing, retrieving, setting,
22
 * and unsetting elements in the ArrayView object.
23
 *
24
 * @template T Type of ArrayView values.
25
 * @template S of string|array<mixed>|ArrayViewInterface<mixed>|ArraySelectorInterface Type of selectors.
26
 */
27
trait ArrayViewAccessTrait
28
{
29
    /**
30
     * Check if the specified offset exists in the ArrayView object.
31
     *
32
     * @param numeric|S $offset The offset to check.
0 ignored issues
show
Bug introduced by
The type Smoren\ArrayView\Traits\numeric 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...
Bug introduced by
The type Smoren\ArrayView\Traits\S 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...
33
     *
34
     * @return bool
35
     *
36
     * {@inheritDoc}
37
     */
38
    public function offsetExists($offset): bool
39
    {
40
        if (\is_numeric($offset)) {
0 ignored issues
show
introduced by
The condition is_numeric($offset) is always false.
Loading history...
41
            return $this->numericOffsetExists($offset);
42
        }
43
44
        try {
45
            return $this->toSelector($offset)->compatibleWith($this);
0 ignored issues
show
Bug introduced by
$this of type Smoren\ArrayView\Traits\ArrayViewAccessTrait is incompatible with the type Smoren\ArrayView\Interfaces\ArrayViewInterface expected by parameter $view of Smoren\ArrayView\Selecto...ector::compatibleWith(). ( Ignorable by Annotation )

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

45
            return $this->toSelector($offset)->compatibleWith(/** @scrutinizer ignore-type */ $this);
Loading history...
Bug introduced by
$this of type Smoren\ArrayView\Traits\ArrayViewAccessTrait is incompatible with the type Smoren\ArrayView\Interfaces\ArrayViewInterface expected by parameter $view of Smoren\ArrayView\Selecto...ector::compatibleWith(). ( Ignorable by Annotation )

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

45
            return $this->toSelector($offset)->compatibleWith(/** @scrutinizer ignore-type */ $this);
Loading history...
Bug introduced by
$this of type Smoren\ArrayView\Traits\ArrayViewAccessTrait is incompatible with the type Smoren\ArrayView\Interfaces\ArrayViewInterface expected by parameter $view of Smoren\ArrayView\Selecto...ector::compatibleWith(). ( Ignorable by Annotation )

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

45
            return $this->toSelector($offset)->compatibleWith(/** @scrutinizer ignore-type */ $this);
Loading history...
46
        } catch (KeyError $e) {
47
            return false;
48
        }
49
    }
50
51
    /**
52
     * Get the value at the specified offset in the ArrayView object.
53
     *
54
     * @param numeric|S $offset The offset to get the value from.
55
     *
56
     * @return T|array<T> The value at the specified offset.
57
     *
58
     * @throws IndexError if the offset is out of range.
59
     * @throws KeyError if the key is invalid.
60
     *
61
     * {@inheritDoc}
62
     */
63
    #[\ReturnTypeWillChange]
64
    public function offsetGet($offset)
65
    {
66
        if (\is_numeric($offset)) {
0 ignored issues
show
introduced by
The condition is_numeric($offset) is always false.
Loading history...
67
            if (!$this->numericOffsetExists($offset)) {
68
                throw new IndexError("Index {$offset} is out of range.");
69
            }
70
            return $this->source[$this->convertIndex(\intval($offset))];
71
        }
72
73
        return $this->subview($this->toSelector($offset))->toArray();
0 ignored issues
show
Bug introduced by
It seems like subview() 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

73
        return $this->/** @scrutinizer ignore-call */ subview($this->toSelector($offset))->toArray();
Loading history...
74
    }
75
76
    /**
77
     * Set the value at the specified offset in the ArrayView object.
78
     *
79
     * @param numeric|S $offset The offset to set the value at.
80
     * @param T|array<T>|ArrayViewInterface<T> $value The value to set.
0 ignored issues
show
Bug introduced by
The type Smoren\ArrayView\Traits\T 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...
81
     *
82
     * @return void
83
     *
84
     * @throws IndexError if the offset is out of range.
85
     * @throws KeyError if the key is invalid.
86
     * @throws ReadonlyError if the object is readonly.
87
     *
88
     * {@inheritDoc}
89
     */
90
    public function offsetSet($offset, $value): void
91
    {
92
        if ($this->isReadonly()) {
0 ignored issues
show
Bug introduced by
It seems like isReadonly() 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

92
        if ($this->/** @scrutinizer ignore-call */ isReadonly()) {
Loading history...
93
            throw new ReadonlyError("Cannot modify a readonly view.");
94
        }
95
96
        if (!\is_numeric($offset)) {
0 ignored issues
show
introduced by
The condition is_numeric($offset) is always false.
Loading history...
97
            $this->subview($this->toSelector($offset))->set($value);
98
            return;
99
        }
100
101
        if (!$this->numericOffsetExists($offset)) {
102
            throw new IndexError("Index {$offset} is out of range.");
103
        }
104
105
        // @phpstan-ignore-next-line
106
        $this->source[$this->convertIndex(\intval($offset))] = $value;
107
    }
108
109
    /**
110
     * Unset the value at the specified offset in the array-like object.
111
     *
112
     * @param numeric|S $offset The offset to unset the value at.
113
     *
114
     * @return void
115
     *
116
     * @throws NotSupportedError always.
117
     *
118
     * {@inheritDoc}
119
     */
120
    public function offsetUnset($offset): void
0 ignored issues
show
Unused Code introduced by
The parameter $offset is not used and could be removed. ( Ignorable by Annotation )

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

120
    public function offsetUnset(/** @scrutinizer ignore-unused */ $offset): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
121
    {
122
        throw new NotSupportedError();
123
    }
124
125
    /**
126
     * Converts array to selector.
127
     *
128
     * @param S $input value to convert.
129
     *
130
     * @return ArraySelectorInterface
131
     */
132
    protected function toSelector($input): ArraySelectorInterface
133
    {
134
        if ($input instanceof ArraySelectorInterface) {
135
            return $input;
136
        }
137
138
        if (\is_string($input) && Slice::isSlice($input)) {
139
            return new SliceSelector($input);
140
        }
141
142
        if ($input instanceof ArrayViewInterface) {
143
            $input = $input->toArray();
144
        }
145
146
        if (!\is_array($input) || !Util::isArraySequential($input)) {
147
            $strOffset = \is_scalar($input) ? \strval($input) : \gettype($input);
148
            throw new KeyError("Invalid key: \"{$strOffset}\".");
149
        }
150
151
        if (\count($input) > 0 && \is_bool($input[0])) {
152
            return new MaskSelector($input);
153
        }
154
155
        return new IndexListSelector($input);
156
    }
157
}
158