Passed
Push — chore/add-feature-tests ( 36c2df...e56562 )
by Bas
04:12 queued 19s
created

AsEnumArrayObject.php$0 ➔ get()   A

Complexity

Conditions 5

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.7283

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
c 1
b 0
f 0
dl 0
loc 22
ccs 9
cts 13
cp 0.6923
crap 5.7283
rs 9.2568
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Eloquent\Casts;
4
5
use BackedEnum;
6
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
7
use Illuminate\Database\Eloquent\Casts\ArrayObject;
8
use Illuminate\Database\Eloquent\Casts\AsEnumArrayObject as IlluminateAsEnumArrayObjectAlias;
9
use Illuminate\Support\Collection;
10
use LaravelFreelancerNL\Aranguent\Eloquent\Model;
11
12
/**
13
 * @SuppressWarnings(PHPMD.UndefinedVariable)
14
 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
15
 */
16
class AsEnumArrayObject extends IlluminateAsEnumArrayObjectAlias
17
{
18
    /**
19
     * Get the caster class to use when casting from / to this cast target.
20
     *
21
     * @template TEnum
22
     *
23
     * @param  array{class-string<TEnum>}  $arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array{class-string<TEnum>} at position 2 could not be parsed: Expected ':' at position 2, but found 'class-string'.
Loading history...
24
     * @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Database\Eloquent\Casts\ArrayObject<array-key, TEnum>, iterable<TEnum>>
25
     *
26
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
27
     */
28 1
    public static function castUsing(array $arguments)
29
    {
30 1
        return new class ($arguments) implements CastsAttributes {
31
            /**
32
             * @var array<class-string<TEnum>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<TEnum>> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<TEnum>>.
Loading history...
33
             */
34
            protected $arguments;
35
36
            /**
37
             * @param array<class-string<TEnum>> $arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<TEnum>> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<TEnum>>.
Loading history...
38
             *
39
             * @SuppressWarnings(PHPMD.UndefinedVariable)
40
             */
41
            public function __construct(array $arguments)
42
            {
43 1
                $this->arguments = $arguments;
44
            }
45
46
            /**
47
             * @param $model
48
             * @param $key
49
             * @param $value
50
             * @param $attributes
51
             * @return ArrayObject|void
52
             *
53
             * @SuppressWarnings(PHPMD.UndefinedVariable)
54
             */
55
            public function get($model, $key, $value, $attributes)
56
            {
57 1
                if (! isset($attributes[$key])) {
58
                    return;
59
                }
60
61 1
                $data = $attributes[$key];
62 1
                if (is_object($data)) {
63
                    $data = (array) $data;
64
                }
65
66 1
                if (! is_array($data)) {
67
                    return;
68
                }
69
70 1
                $enumClass = $this->arguments[0];
71
72 1
                return new ArrayObject((new Collection($data))->map(function ($value) use ($enumClass) {
0 ignored issues
show
Bug introduced by
$data of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::__construct(). ( Ignorable by Annotation )

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

72
                return new ArrayObject((new Collection(/** @scrutinizer ignore-type */ $data))->map(function ($value) use ($enumClass) {
Loading history...
Bug Best Practice introduced by
The expression return new Illuminate\Da...* ... */ })->toArray()) returns the type Illuminate\Database\Eloquent\Casts\ArrayObject which is incompatible with the return type mandated by Illuminate\Contracts\Dat...\CastsAttributes::get() of Illuminate\Contracts\Database\Eloquent\TGet|null.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
73 1
                    return is_subclass_of($enumClass, BackedEnum::class)
74
                        ? $enumClass::from($value)
75 1
                        : constant($enumClass . '::' . $value);
76 1
                })->toArray());
77
            }
78
79
            /**
80
             * @param Model $model
81
             * @param string $key
82
             * @param mixed $value
83
             * @param mixed[] $attributes
84
             * @return mixed[]
85
             *
86
             * @SuppressWarnings(PHPMD.UnusedFormalParameter)
87
             * @SuppressWarnings(PHPMD.UndefinedVariable)
88
             */
89
            public function set($model, $key, $value, $attributes)
90
            {
91 1
                if ($value === null) {
92
                    return [$key => null];
93
                }
94
95 1
                $storable = [];
96
97 1
                foreach ($value as $enum) {
98 1
                    $storable[] = $this->getStorableEnumValue($enum);
99
                }
100
101 1
                return [$key => $storable];
102
            }
103
104
            /**
105
             * @param Model $model
106
             * @param string $key
107
             * @param mixed $value
108
             * @param mixed[] $attributes
109
             * @return mixed[]
110
             */
111
            public function serialize($model, string $key, $value, array $attributes)
0 ignored issues
show
Unused Code introduced by
The parameter $model 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

111
            public function serialize(/** @scrutinizer ignore-unused */ $model, string $key, $value, array $attributes)

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...
Unused Code introduced by
The parameter $key 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

111
            public function serialize($model, /** @scrutinizer ignore-unused */ string $key, $value, array $attributes)

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...
Unused Code introduced by
The parameter $attributes 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

111
            public function serialize($model, string $key, $value, /** @scrutinizer ignore-unused */ array $attributes)

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...
112
            {
113
                return (new Collection($value->getArrayCopy()))->map(function ($enum) {
114
                    return $this->getStorableEnumValue($enum);
115
                })->toArray();
116
            }
117
118
            /**
119
             * @param mixed $enum
120
             * @return int|string
121
             */
122
            protected function getStorableEnumValue($enum)
123
            {
124 1
                if (is_string($enum) || is_int($enum)) {
125
                    return $enum;
126
                }
127
128 1
                return $enum instanceof BackedEnum ? $enum->value : $enum->name;
0 ignored issues
show
Bug introduced by
Accessing value on the interface BackedEnum suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
129
            }
130 1
        };
131
    }
132
133
    /**
134
     * Specify the Enum for the cast.
135
     *
136
     * @param  class-string  $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
137
     * @return string
138
     *
139
     * @SuppressWarnings(PHPMD.ShortMethodName)
140
     */
141 10
    public static function of($class)
142
    {
143 10
        return static::class . ':' . $class;
144
    }
145
}
146