1 | <?php |
||||||
2 | |||||||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||||||
3 | namespace BristolSU\ControlDB\AdditionalProperties; |
||||||
4 | |||||||
5 | use Exception; |
||||||
6 | use Illuminate\Database\Eloquent\Model; |
||||||
7 | use Illuminate\Support\Str; |
||||||
8 | |||||||
9 | /** |
||||||
10 | * Allow a model to have any arbitrary properties, set at runtime |
||||||
11 | */ |
||||||
0 ignored issues
–
show
|
|||||||
12 | trait HasAdditionalProperties |
||||||
13 | { |
||||||
14 | |||||||
15 | /** |
||||||
16 | * Initialise the trait |
||||||
17 | * |
||||||
18 | * - Add all additional properties to the appends array |
||||||
19 | * - Add additional_properties column to hidden |
||||||
20 | * - Cast the additional_properties column to an array |
||||||
21 | */ |
||||||
0 ignored issues
–
show
|
|||||||
22 | 442 | public function initializeHasAdditionalProperties() |
|||||
23 | { |
||||||
24 | 442 | if (is_subclass_of($this, Model::class)) { |
|||||
25 | 441 | $this->append(static::getAdditionalAttributes()); |
|||||
0 ignored issues
–
show
The method
append() does not exist on BristolSU\ControlDB\Addi...HasAdditionalProperties . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
26 | 441 | $this->addHidden($this->getColumnName()); |
|||||
0 ignored issues
–
show
The method
addHidden() does not exist on BristolSU\ControlDB\Addi...HasAdditionalProperties . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
27 | 441 | $this->casts[] = $this->getColumnName(); |
|||||
0 ignored issues
–
show
|
|||||||
28 | } else { |
||||||
29 | 1 | throw new Exception('The HasAdditionalProperties trait must only be used in an Eloquent model'); |
|||||
30 | } |
||||||
31 | 441 | } |
|||||
32 | |||||||
33 | /** |
||||||
34 | * Add an additional property |
||||||
35 | * |
||||||
36 | * @param $key |
||||||
0 ignored issues
–
show
|
|||||||
37 | */ |
||||||
0 ignored issues
–
show
|
|||||||
38 | 44 | public static function addProperty(string $key): void |
|||||
39 | { |
||||||
40 | 44 | app(AdditionalPropertyStore::class)->addProperty(static::class, $key); |
|||||
41 | 44 | } |
|||||
42 | |||||||
43 | /** |
||||||
44 | * Get all additional attributes the model is using |
||||||
45 | * |
||||||
46 | * @return array |
||||||
47 | */ |
||||||
48 | 442 | public static function getAdditionalAttributes(): array |
|||||
49 | { |
||||||
50 | 442 | return (app(AdditionalPropertyStore::class)->getProperties(static::class) ?? []); |
|||||
51 | } |
||||||
52 | |||||||
53 | /** |
||||||
54 | * Retrieve an additional attribute value |
||||||
55 | * |
||||||
56 | * @param string $key Key of the attribute |
||||||
57 | * @return mixed Value of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
58 | */ |
||||||
59 | 29 | public function getAdditionalAttribute(string $key) |
|||||
60 | { |
||||||
61 | 29 | return (array_key_exists($key, ($this->{$this->getColumnName()}??[])) |
|||||
62 | 29 | ? $this->{$this->getColumnName()}[$key] : null); |
|||||
63 | } |
||||||
64 | |||||||
65 | /** |
||||||
66 | * Set an additional attribute value |
||||||
67 | * |
||||||
68 | * @param string $key Key of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
69 | * @param mixed $value Value of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
70 | */ |
||||||
0 ignored issues
–
show
|
|||||||
71 | 31 | public function setAdditionalAttribute(string $key, $value) |
|||||
72 | { |
||||||
73 | 31 | $this->attributes[$this->getColumnName()] = array_merge(($this->{$this->getColumnName()}??[]), [$key => $value]); |
|||||
0 ignored issues
–
show
|
|||||||
74 | 31 | } |
|||||
75 | |||||||
76 | /** |
||||||
77 | * Save an additional attribute value |
||||||
78 | * |
||||||
79 | * @param string $key Key of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
80 | * @param mixed $value Value of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
81 | */ |
||||||
0 ignored issues
–
show
|
|||||||
82 | 13 | public function saveAdditionalAttribute(string $key, $value) |
|||||
83 | { |
||||||
84 | 13 | $this->setAdditionalAttribute($key, $value); |
|||||
85 | 13 | $this->save(); |
|||||
0 ignored issues
–
show
The method
save() does not exist on BristolSU\ControlDB\Addi...HasAdditionalProperties . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
86 | 13 | } |
|||||
87 | |||||||
88 | /** |
||||||
89 | * Override the default getAttribute function |
||||||
90 | * |
||||||
91 | * Any time an attribute is retrieved, we will check if it's an additional property and return it if so |
||||||
92 | * |
||||||
93 | * @param string $key Key of the property to retrieve |
||||||
94 | * @return mixed Value of the property |
||||||
0 ignored issues
–
show
|
|||||||
95 | */ |
||||||
96 | 412 | public function getAttribute($key) |
|||||
97 | { |
||||||
98 | 412 | if (in_array($key, static::getAdditionalAttributes())) { |
|||||
99 | 5 | return $this->getAdditionalAttribute($key); |
|||||
100 | } |
||||||
101 | 412 | return parent::getAttribute($key); |
|||||
102 | } |
||||||
103 | |||||||
104 | /** |
||||||
105 | * Override the default getAttribute function |
||||||
106 | * |
||||||
107 | * Any time an attribute is set, we will check if it's an additional property and set it correspondingly if so |
||||||
108 | * |
||||||
109 | * @param string $key Key of the property to retrieve |
||||||
0 ignored issues
–
show
|
|||||||
110 | * @param mixed $value Value of the attribute |
||||||
0 ignored issues
–
show
|
|||||||
111 | * @return mixed Value of the property |
||||||
0 ignored issues
–
show
|
|||||||
112 | */ |
||||||
113 | 427 | public function setAttribute($key, $value) |
|||||
114 | { |
||||||
115 | 427 | if (in_array($key, static::getAdditionalAttributes())) { |
|||||
116 | 14 | $this->setAdditionalAttribute($key, $value); |
|||||
117 | } else { |
||||||
118 | 427 | parent::setAttribute($key, $value); |
|||||
119 | } |
||||||
120 | 427 | } |
|||||
121 | |||||||
122 | /** |
||||||
123 | * Cast the additional attributes column to an array, or return an empty array by default. |
||||||
124 | * |
||||||
125 | * @return array|mixed |
||||||
126 | */ |
||||||
127 | 38 | public function getAdditionalAttributesAttribute() |
|||||
128 | { |
||||||
129 | 38 | if(!array_key_exists($this->getColumnName(), $this->attributes)) { |
|||||
0 ignored issues
–
show
|
|||||||
130 | 28 | return []; |
|||||
131 | } |
||||||
132 | 33 | if(is_string($this->attributes[$this->getColumnName()])) { |
|||||
0 ignored issues
–
show
|
|||||||
133 | 18 | return (json_decode($this->attributes[$this->getColumnName()], true) ?? []); |
|||||
134 | } |
||||||
135 | 15 | return $this->attributes[$this->getColumnName()]; |
|||||
136 | } |
||||||
137 | |||||||
138 | /** |
||||||
139 | * Get the name of the additional attributes column |
||||||
140 | * |
||||||
141 | * @return string Name of the additional attributes column |
||||||
142 | */ |
||||||
143 | 441 | private function getColumnName() |
|||||
0 ignored issues
–
show
|
|||||||
144 | { |
||||||
145 | 441 | return 'additional_attributes'; |
|||||
146 | } |
||||||
147 | |||||||
148 | /** |
||||||
149 | * Dynamically define accessors for the appended properties. |
||||||
150 | * |
||||||
151 | * By catching all method calls, we can check if they are calls for an accessor or mutator to an attribute and |
||||||
152 | * carry out the corresponding action. |
||||||
153 | * |
||||||
154 | * @param string $method Method of the call |
||||||
155 | * @param array $args Arguments for the call |
||||||
0 ignored issues
–
show
|
|||||||
156 | * @return mixed |
||||||
0 ignored issues
–
show
|
|||||||
157 | */ |
||||||
158 | 134 | public function __call($method, $args) |
|||||
159 | { |
||||||
160 | // Check if the call was an accessor |
||||||
161 | $additionalAccessors = array_map(function($propertyKey) { |
||||||
0 ignored issues
–
show
|
|||||||
162 | 22 | return 'get'.Str::studly($propertyKey).'Attribute'; |
|||||
163 | 134 | }, static::getAdditionalAttributes()); |
|||||
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
![]() |
|||||||
164 | 134 | if(in_array($method, $additionalAccessors)) { |
|||||
0 ignored issues
–
show
|
|||||||
165 | 14 | return $this->getAdditionalAttribute( |
|||||
166 | 14 | Str::snake(Str::substr(Str::substr($method, 3), 0, -9)) |
|||||
167 | ); |
||||||
168 | } |
||||||
169 | |||||||
170 | // Check if the call was a mutator |
||||||
171 | $additionalAccessors = array_map(function($propertyKey) { |
||||||
0 ignored issues
–
show
|
|||||||
172 | 18 | return 'set'.Str::studly($propertyKey).'Attribute'; |
|||||
173 | 130 | }, static::getAdditionalAttributes()); |
|||||
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
![]() |
|||||||
174 | 130 | if(in_array($method, $additionalAccessors)) { |
|||||
0 ignored issues
–
show
|
|||||||
175 | 1 | $this->setAdditionalAttribute( |
|||||
176 | 1 | Str::snake(Str::substr(Str::substr($method, 3), 0, -9)), $args[0] |
|||||
177 | ); |
||||||
178 | } else { |
||||||
179 | 129 | return parent::__call($method, |
|||||
0 ignored issues
–
show
|
|||||||
180 | $args); |
||||||
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
![]() |
|||||||
181 | } |
||||||
182 | |||||||
183 | |||||||
184 | 1 | } |
|||||
185 | } |
||||||
186 |