This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Dimsav\Translatable; |
||
4 | |||
5 | use Illuminate\Support\Str; |
||
6 | use Illuminate\Database\Eloquent\Model; |
||
7 | use Illuminate\Database\Eloquent\Builder; |
||
8 | use Illuminate\Database\Query\JoinClause; |
||
9 | use Illuminate\Database\Eloquent\Collection; |
||
10 | use Illuminate\Database\Eloquent\Relations\HasMany; |
||
11 | use Illuminate\Database\Eloquent\Relations\Relation; |
||
12 | use Illuminate\Database\Query\Builder as QueryBuilder; |
||
13 | |||
14 | /** |
||
15 | * @property-read Collection|Model[] $translations |
||
16 | * @property-read string $translationModel |
||
17 | * @property-read string $translationForeignKey |
||
18 | * @property-read string $localeKey |
||
19 | * @property-read bool $useTranslationFallback |
||
20 | * |
||
21 | * @mixin Model |
||
22 | */ |
||
23 | trait Translatable |
||
24 | { |
||
25 | protected static $autoloadTranslations = null; |
||
26 | |||
27 | protected $defaultLocale; |
||
28 | |||
29 | 480 | public static function bootTranslatable(): void |
|
30 | { |
||
31 | static::saved(function (Model $model) { |
||
32 | /* @var Translatable $model */ |
||
33 | 480 | return $model->saveTranslations(); |
|
34 | 480 | }); |
|
35 | 480 | } |
|
36 | |||
37 | 52 | public function translate(?string $locale = null, bool $withFallback = false): ?Model |
|
38 | { |
||
39 | 52 | return $this->getTranslation($locale, $withFallback); |
|
40 | } |
||
41 | |||
42 | 4 | public function translateOrDefault(?string $locale = null): ?Model |
|
43 | { |
||
44 | 4 | return $this->getTranslation($locale, true); |
|
45 | } |
||
46 | |||
47 | 4 | public function translateOrNew(?string $locale = null): Model |
|
48 | { |
||
49 | 4 | return $this->getTranslationOrNew($locale); |
|
50 | } |
||
51 | |||
52 | 252 | public function getTranslation(?string $locale = null, bool $withFallback = null): ?Model |
|
53 | { |
||
54 | 252 | $configFallbackLocale = $this->getFallbackLocale(); |
|
55 | 252 | $locale = $locale ?: $this->locale(); |
|
56 | 252 | $withFallback = $withFallback === null ? $this->useFallback() : $withFallback; |
|
57 | 252 | $fallbackLocale = $this->getFallbackLocale($locale); |
|
58 | |||
59 | 252 | if ($translation = $this->getTranslationByLocaleKey($locale)) { |
|
60 | 144 | return $translation; |
|
61 | } |
||
62 | 172 | if ($withFallback && $fallbackLocale) { |
|
63 | 28 | if ($translation = $this->getTranslationByLocaleKey($fallbackLocale)) { |
|
64 | 16 | return $translation; |
|
65 | } |
||
66 | 12 | if ($fallbackLocale !== $configFallbackLocale && $translation = $this->getTranslationByLocaleKey($configFallbackLocale)) { |
|
67 | 8 | return $translation; |
|
68 | } |
||
69 | } |
||
70 | |||
71 | 168 | return null; |
|
72 | } |
||
73 | |||
74 | 12 | public function hasTranslation(?string $locale = null): bool |
|
75 | { |
||
76 | 12 | $locale = $locale ?: $this->locale(); |
|
77 | |||
78 | 12 | foreach ($this->translations as $translation) { |
|
79 | 4 | if ($translation->getAttribute($this->getLocaleKey()) == $locale) { |
|
80 | 4 | return true; |
|
81 | } |
||
82 | } |
||
83 | |||
84 | 12 | return false; |
|
85 | } |
||
86 | |||
87 | 316 | public function getTranslationModelName(): string |
|
88 | { |
||
89 | 316 | return $this->translationModel ?: $this->getTranslationModelNameDefault(); |
|
90 | } |
||
91 | |||
92 | 304 | public function getTranslationModelNameDefault(): string |
|
93 | { |
||
94 | 304 | $modelName = get_class($this); |
|
95 | |||
96 | 304 | if ($namespace = $this->getTranslationModelNamespace()) { |
|
97 | 4 | $modelName = $namespace.'\\'.class_basename(get_class($this)); |
|
98 | } |
||
99 | |||
100 | 304 | return $modelName.config('translatable.translation_suffix', 'Translation'); |
|
101 | } |
||
102 | |||
103 | 304 | public function getTranslationModelNamespace(): ?string |
|
104 | { |
||
105 | 304 | return config('translatable.translation_model_namespace'); |
|
106 | } |
||
107 | |||
108 | 316 | public function getRelationKey(): string |
|
109 | { |
||
110 | 316 | if ($this->translationForeignKey) { |
|
111 | 28 | return $this->translationForeignKey; |
|
112 | } |
||
113 | |||
114 | 292 | return $this->getForeignKey(); |
|
0 ignored issues
–
show
|
|||
115 | } |
||
116 | |||
117 | 296 | public function getLocaleKey(): string |
|
118 | { |
||
119 | 296 | return $this->localeKey ?: config('translatable.locale_key', 'locale'); |
|
120 | } |
||
121 | |||
122 | 296 | public function translations(): HasMany |
|
123 | { |
||
124 | 296 | return $this->hasMany($this->getTranslationModelName(), $this->getRelationKey()); |
|
0 ignored issues
–
show
It seems like
hasMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
125 | } |
||
126 | |||
127 | 16 | private function usePropertyFallback(): bool |
|
128 | { |
||
129 | 16 | return $this->useFallback() && config('translatable.use_property_fallback', false); |
|
130 | } |
||
131 | |||
132 | 96 | private function getAttributeOrFallback(?string $locale, string $attribute) |
|
133 | { |
||
134 | 96 | $translation = $this->getTranslation($locale); |
|
135 | |||
136 | if ( |
||
137 | ( |
||
138 | 96 | ! $translation instanceof Model |
|
139 | 96 | || $this->isEmptyTranslatableAttribute($attribute, $translation->$attribute) |
|
140 | ) |
||
141 | 96 | && $this->usePropertyFallback() |
|
142 | ) { |
||
143 | 12 | $translation = $this->getTranslation($this->getFallbackLocale(), false); |
|
144 | } |
||
145 | |||
146 | 96 | if ($translation instanceof Model) { |
|
147 | 92 | return $translation->$attribute; |
|
148 | } |
||
149 | |||
150 | 8 | return null; |
|
151 | } |
||
152 | |||
153 | 88 | protected function isEmptyTranslatableAttribute(string $key, $value): bool |
|
0 ignored issues
–
show
|
|||
154 | { |
||
155 | 88 | return empty($value); |
|
156 | } |
||
157 | |||
158 | 480 | public function getAttribute($key) |
|
159 | { |
||
160 | 480 | [$attribute, $locale] = $this->getAttributeAndLocale($key); |
|
0 ignored issues
–
show
|
|||
161 | |||
162 | 480 | if ($this->isTranslationAttribute($attribute)) { |
|
163 | 76 | if ($this->getTranslation($locale) === null) { |
|
164 | 12 | return $this->getAttributeValue($attribute); |
|
0 ignored issues
–
show
The method
getAttributeValue() does not exist on Dimsav\Translatable\Translatable . Did you maybe mean getAttribute() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
165 | } |
||
166 | |||
167 | // If the given $attribute has a mutator, we push it to $attributes and then call getAttributeValue |
||
168 | // on it. This way, we can use Eloquent's checking for Mutation, type casting, and |
||
169 | // Date fields. |
||
170 | 64 | if ($this->hasGetMutator($attribute)) { |
|
0 ignored issues
–
show
It seems like
hasGetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
171 | 4 | $this->attributes[$attribute] = $this->getAttributeOrFallback($locale, $attribute); |
|
0 ignored issues
–
show
The property
attributes does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
172 | |||
173 | 4 | return $this->getAttributeValue($attribute); |
|
0 ignored issues
–
show
The method
getAttributeValue() does not exist on Dimsav\Translatable\Translatable . Did you maybe mean getAttribute() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
174 | } |
||
175 | |||
176 | 60 | return $this->getAttributeOrFallback($locale, $attribute); |
|
177 | } |
||
178 | |||
179 | 480 | return parent::getAttribute($key); |
|
180 | } |
||
181 | |||
182 | 480 | public function setAttribute($key, $value) |
|
183 | { |
||
184 | 480 | [$attribute, $locale] = $this->getAttributeAndLocale($key); |
|
0 ignored issues
–
show
|
|||
185 | |||
186 | 480 | if ($this->isTranslationAttribute($attribute)) { |
|
187 | 40 | $this->getTranslationOrNew($locale)->$attribute = $value; |
|
188 | } else { |
||
189 | 480 | return parent::setAttribute($key, $value); |
|
190 | } |
||
191 | |||
192 | 40 | return $this; |
|
193 | } |
||
194 | |||
195 | 144 | protected function getTranslationOrNew(?string $locale = null): Model |
|
196 | { |
||
197 | 144 | $locale = $locale ?: $this->locale(); |
|
198 | |||
199 | 144 | if (($translation = $this->getTranslation($locale, false)) === null) { |
|
200 | 128 | $translation = $this->getNewTranslation($locale); |
|
201 | } |
||
202 | |||
203 | 144 | return $translation; |
|
204 | } |
||
205 | |||
206 | 480 | public function fill(array $attributes) |
|
207 | { |
||
208 | 480 | foreach ($attributes as $key => $values) { |
|
209 | 112 | if ($this->isKeyALocale($key)) { |
|
210 | 52 | $this->getTranslationOrNew($key)->fill($values); |
|
211 | 44 | unset($attributes[$key]); |
|
212 | } else { |
||
213 | 104 | [$attribute, $locale] = $this->getAttributeAndLocale($key); |
|
0 ignored issues
–
show
The variable
$attribute does not exist. Did you mean $attributes ?
This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name. The variable may have been renamed without also renaming all references. ![]() |
|||
214 | 104 | if ($this->isTranslationAttribute($attribute) and $this->isKeyALocale($locale)) { |
|
0 ignored issues
–
show
The variable
$attribute does not exist. Did you mean $attributes ?
This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name. The variable may have been renamed without also renaming all references. ![]() |
|||
215 | 48 | $this->getTranslationOrNew($locale)->fill([$attribute => $values]); |
|
0 ignored issues
–
show
The variable
$attribute does not exist. Did you mean $attributes ?
This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name. The variable may have been renamed without also renaming all references. ![]() |
|||
216 | 48 | unset($attributes[$key]); |
|
217 | } |
||
218 | } |
||
219 | } |
||
220 | |||
221 | 480 | return parent::fill($attributes); |
|
222 | } |
||
223 | |||
224 | 252 | private function getTranslationByLocaleKey(string $key): ?Model |
|
225 | { |
||
226 | 252 | foreach ($this->translations as $translation) { |
|
227 | 200 | if ($translation->getAttribute($this->getLocaleKey()) == $key) { |
|
228 | 168 | return $translation; |
|
229 | } |
||
230 | } |
||
231 | |||
232 | 172 | return null; |
|
233 | } |
||
234 | |||
235 | 256 | private function getFallbackLocale(?string $locale = null): ?string |
|
236 | { |
||
237 | 256 | if ($locale && $this->isLocaleCountryBased($locale)) { |
|
238 | 28 | if ($fallback = $this->getLanguageFromCountryBasedLocale($locale)) { |
|
239 | 28 | return $fallback; |
|
240 | } |
||
241 | } |
||
242 | |||
243 | 256 | return config('translatable.fallback_locale'); |
|
244 | } |
||
245 | |||
246 | 252 | private function isLocaleCountryBased(string $locale): bool |
|
247 | { |
||
248 | 252 | return $this->getLocalesHelper()->isLocaleCountryBased($locale); |
|
249 | } |
||
250 | |||
251 | 28 | private function getLanguageFromCountryBasedLocale(string $locale): string |
|
252 | { |
||
253 | 28 | return $this->getLocalesHelper()->getLanguageFromCountryBasedLocale($locale); |
|
254 | } |
||
255 | |||
256 | 148 | private function useFallback(): bool |
|
257 | { |
||
258 | 148 | if (isset($this->useTranslationFallback) && $this->useTranslationFallback !== null) { |
|
259 | 12 | return $this->useTranslationFallback; |
|
260 | } |
||
261 | |||
262 | 136 | return (bool) config('translatable.use_fallback'); |
|
263 | } |
||
264 | |||
265 | 480 | public function isTranslationAttribute(string $key): bool |
|
266 | { |
||
267 | 480 | return in_array($key, $this->translatedAttributes); |
|
0 ignored issues
–
show
The property
translatedAttributes does not seem to exist. Did you mean attributes ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
268 | } |
||
269 | |||
270 | 112 | protected function isKeyALocale(string $key): bool |
|
271 | { |
||
272 | 112 | return $this->getLocalesHelper()->has($key); |
|
273 | } |
||
274 | |||
275 | protected function getLocales(): array |
||
276 | { |
||
277 | return $this->getLocalesHelper()->all(); |
||
278 | } |
||
279 | |||
280 | protected function getLocaleSeparator(): string |
||
281 | { |
||
282 | return $this->getLocalesHelper()->getLocaleSeparator(); |
||
283 | } |
||
284 | |||
285 | 480 | protected function saveTranslations(): bool |
|
286 | { |
||
287 | 480 | $saved = true; |
|
288 | |||
289 | 480 | if (! $this->relationLoaded('translations')) { |
|
0 ignored issues
–
show
It seems like
relationLoaded() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
290 | 480 | return $saved; |
|
291 | } |
||
292 | |||
293 | 104 | foreach ($this->translations as $translation) { |
|
294 | 104 | if ($saved && $this->isTranslationDirty($translation)) { |
|
295 | 104 | if (! empty($connectionName = $this->getConnectionName())) { |
|
0 ignored issues
–
show
It seems like
getConnectionName() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
296 | 104 | $translation->setConnection($connectionName); |
|
297 | } |
||
298 | |||
299 | 104 | $translation->setAttribute($this->getRelationKey(), $this->getKey()); |
|
0 ignored issues
–
show
It seems like
getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
300 | 104 | $saved = $translation->save(); |
|
301 | } |
||
302 | } |
||
303 | |||
304 | 100 | return $saved; |
|
305 | } |
||
306 | |||
307 | 4 | public function replicateWithTranslations(array $except = null): Model |
|
308 | { |
||
309 | 4 | $newInstance = parent::replicate($except); |
|
0 ignored issues
–
show
It seems like you call parent on a different method (
replicate() instead of replicateWithTranslations() ). Are you sure this is correct? If so, you might want to change this to $this->replicate() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
310 | |||
311 | 4 | unset($newInstance->translations); |
|
312 | 4 | foreach ($this->translations as $translation) { |
|
313 | 4 | $newTranslation = $translation->replicate(); |
|
314 | 4 | $newInstance->translations->add($newTranslation); |
|
315 | } |
||
316 | |||
317 | 4 | return $newInstance; |
|
318 | } |
||
319 | |||
320 | 104 | protected function isTranslationDirty(Model $translation): bool |
|
321 | { |
||
322 | 104 | $dirtyAttributes = $translation->getDirty(); |
|
323 | 104 | unset($dirtyAttributes[$this->getLocaleKey()]); |
|
324 | |||
325 | 104 | return count($dirtyAttributes) > 0; |
|
326 | } |
||
327 | |||
328 | 132 | public function getNewTranslation(string $locale): Model |
|
329 | { |
||
330 | 132 | $modelName = $this->getTranslationModelName(); |
|
331 | 132 | $translation = new $modelName(); |
|
332 | 132 | $translation->setAttribute($this->getLocaleKey(), $locale); |
|
333 | 132 | $this->translations->add($translation); |
|
334 | |||
335 | 132 | return $translation; |
|
336 | } |
||
337 | |||
338 | 152 | public function __isset($key) |
|
339 | { |
||
340 | 152 | return $this->isTranslationAttribute($key) || parent::__isset($key); |
|
341 | } |
||
342 | |||
343 | 8 | public function scopeTranslatedIn(Builder $query, ?string $locale = null) |
|
344 | { |
||
345 | 8 | $locale = $locale ?: $this->locale(); |
|
346 | |||
347 | return $query->whereHas('translations', function (Builder $q) use ($locale) { |
||
348 | 8 | $q->where($this->getLocaleKey(), '=', $locale); |
|
349 | 8 | }); |
|
350 | } |
||
351 | |||
352 | 8 | public function scopeNotTranslatedIn(Builder $query, ?string $locale = null) |
|
353 | { |
||
354 | 8 | $locale = $locale ?: $this->locale(); |
|
355 | |||
356 | return $query->whereDoesntHave('translations', function (Builder $q) use ($locale) { |
||
357 | 8 | $q->where($this->getLocaleKey(), '=', $locale); |
|
358 | 8 | }); |
|
359 | } |
||
360 | |||
361 | 4 | public function scopeTranslated(Builder $query) |
|
362 | { |
||
363 | 4 | return $query->has('translations'); |
|
364 | } |
||
365 | |||
366 | 12 | public function scopeListsTranslations(Builder $query, string $translationField) |
|
367 | { |
||
368 | 12 | $withFallback = $this->useFallback(); |
|
369 | 12 | $translationTable = $this->getTranslationsTable(); |
|
370 | 12 | $localeKey = $this->getLocaleKey(); |
|
371 | |||
372 | $query |
||
0 ignored issues
–
show
The method
select() does not exist on Illuminate\Database\Eloquent\Builder . Did you maybe mean createSelectWithConstraint() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
373 | 12 | ->select($this->getTable().'.'.$this->getKeyName(), $translationTable.'.'.$translationField) |
|
0 ignored issues
–
show
It seems like
getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() It seems like
getKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
374 | 12 | ->leftJoin($translationTable, $translationTable.'.'.$this->getRelationKey(), '=', $this->getTable().'.'.$this->getKeyName()) |
|
0 ignored issues
–
show
It seems like
getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() It seems like
getKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
375 | 12 | ->where($translationTable.'.'.$localeKey, $this->locale()); |
|
376 | 12 | if ($withFallback) { |
|
377 | $query->orWhere(function (Builder $q) use ($translationTable, $localeKey) { |
||
378 | 4 | $q->where($translationTable.'.'.$localeKey, $this->getFallbackLocale()) |
|
379 | ->whereNotIn($translationTable.'.'.$this->getRelationKey(), function (QueryBuilder $q) use ( |
||
380 | 4 | $translationTable, |
|
381 | 4 | $localeKey |
|
382 | ) { |
||
383 | 4 | $q->select($translationTable.'.'.$this->getRelationKey()) |
|
384 | 4 | ->from($translationTable) |
|
385 | 4 | ->where($translationTable.'.'.$localeKey, $this->locale()); |
|
386 | 4 | }); |
|
387 | 4 | }); |
|
388 | } |
||
389 | 12 | } |
|
390 | |||
391 | 12 | public function scopeWithTranslation(Builder $query) |
|
392 | { |
||
393 | 12 | $query->with([ |
|
394 | 'translations' => function (Relation $query) { |
||
395 | 12 | if ($this->useFallback()) { |
|
396 | 8 | $locale = $this->locale(); |
|
397 | 8 | $countryFallbackLocale = $this->getFallbackLocale($locale); // e.g. de-DE => de |
|
398 | 8 | $locales = array_unique([$locale, $countryFallbackLocale, $this->getFallbackLocale()]); |
|
399 | |||
400 | 8 | return $query->whereIn($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locales); |
|
0 ignored issues
–
show
The method
whereIn() does not exist on Illuminate\Database\Eloquent\Relations\Relation . Did you maybe mean whereInMethod() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
401 | } |
||
402 | |||
403 | 4 | return $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $this->locale()); |
|
404 | 12 | }, |
|
405 | ]); |
||
406 | 12 | } |
|
407 | |||
408 | 12 | public function scopeWhereTranslation(Builder $query, string $translationField, $value, ?string $locale = null) |
|
409 | { |
||
410 | return $query->whereHas('translations', function (Builder $query) use ($translationField, $value, $locale) { |
||
411 | 12 | $query->where($this->getTranslationsTable().'.'.$translationField, $value); |
|
412 | 12 | if ($locale) { |
|
413 | 4 | $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locale); |
|
414 | } |
||
415 | 12 | }); |
|
416 | } |
||
417 | |||
418 | 4 | public function scopeOrWhereTranslation(Builder $query, string $translationField, $value, ?string $locale = null) |
|
419 | { |
||
420 | return $query->orWhereHas('translations', function (Builder $query) use ($translationField, $value, $locale) { |
||
421 | 4 | $query->where($this->getTranslationsTable().'.'.$translationField, $value); |
|
422 | 4 | if ($locale) { |
|
423 | $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locale); |
||
424 | } |
||
425 | 4 | }); |
|
426 | } |
||
427 | |||
428 | 12 | public function scopeWhereTranslationLike(Builder $query, string $translationField, $value, ?string $locale = null) |
|
429 | { |
||
430 | return $query->whereHas('translations', function (Builder $query) use ($translationField, $value, $locale) { |
||
431 | 12 | $query->where($this->getTranslationsTable().'.'.$translationField, 'LIKE', $value); |
|
432 | 12 | if ($locale) { |
|
433 | 4 | $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), 'LIKE', $locale); |
|
434 | } |
||
435 | 12 | }); |
|
436 | } |
||
437 | |||
438 | 4 | public function scopeOrWhereTranslationLike(Builder $query, string $translationField, $value, ?string $locale = null) |
|
439 | { |
||
440 | return $query->orWhereHas('translations', function (Builder $query) use ($translationField, $value, $locale) { |
||
441 | 4 | $query->where($this->getTranslationsTable().'.'.$translationField, 'LIKE', $value); |
|
442 | 4 | if ($locale) { |
|
443 | $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), 'LIKE', $locale); |
||
444 | } |
||
445 | 4 | }); |
|
446 | } |
||
447 | |||
448 | 8 | public function scopeOrderByTranslation(Builder $query, string $translationField, string $sortMethod = 'asc') |
|
449 | { |
||
450 | 8 | $translationTable = $this->getTranslationsTable(); |
|
451 | 8 | $localeKey = $this->getLocaleKey(); |
|
452 | 8 | $table = $this->getTable(); |
|
0 ignored issues
–
show
It seems like
getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
453 | 8 | $keyName = $this->getKeyName(); |
|
0 ignored issues
–
show
It seems like
getKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
454 | |||
455 | return $query |
||
456 | ->join($translationTable, function (JoinClause $join) use ($translationTable, $localeKey, $table, $keyName) { |
||
457 | $join |
||
458 | 8 | ->on($translationTable.'.'.$this->getRelationKey(), '=', $table.'.'.$keyName) |
|
459 | 8 | ->where($translationTable.'.'.$localeKey, $this->locale()); |
|
460 | 8 | }) |
|
461 | 8 | ->orderBy($translationTable.'.'.$translationField, $sortMethod) |
|
462 | 8 | ->select($table.'.*') |
|
463 | 8 | ->with('translations'); |
|
464 | } |
||
465 | |||
466 | 48 | public function attributesToArray() |
|
467 | { |
||
468 | 48 | $attributes = parent::attributesToArray(); |
|
469 | |||
470 | if ( |
||
471 | 48 | (! $this->relationLoaded('translations') && ! $this->toArrayAlwaysLoadsTranslations() && is_null(self::$autoloadTranslations)) |
|
0 ignored issues
–
show
It seems like
relationLoaded() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
472 | 48 | || self::$autoloadTranslations === false |
|
473 | ) { |
||
474 | 16 | return $attributes; |
|
475 | } |
||
476 | |||
477 | 32 | $hiddenAttributes = $this->getHidden(); |
|
0 ignored issues
–
show
It seems like
getHidden() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
478 | |||
479 | 32 | foreach ($this->translatedAttributes as $field) { |
|
0 ignored issues
–
show
The property
translatedAttributes does not seem to exist. Did you mean attributes ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
480 | 32 | if (in_array($field, $hiddenAttributes)) { |
|
481 | 4 | continue; |
|
482 | } |
||
483 | |||
484 | 32 | $attributes[$field] = $this->getAttributeOrFallback(null, $field); |
|
485 | } |
||
486 | |||
487 | 32 | return $attributes; |
|
488 | } |
||
489 | |||
490 | 4 | public function getTranslationsArray(): array |
|
491 | { |
||
492 | 4 | $translations = []; |
|
493 | |||
494 | 4 | foreach ($this->translations as $translation) { |
|
495 | 4 | foreach ($this->translatedAttributes as $attr) { |
|
0 ignored issues
–
show
The property
translatedAttributes does not seem to exist. Did you mean attributes ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
496 | 4 | $translations[$translation->{$this->getLocaleKey()}][$attr] = $translation->{$attr}; |
|
497 | } |
||
498 | } |
||
499 | |||
500 | 4 | return $translations; |
|
501 | } |
||
502 | |||
503 | 56 | private function getTranslationsTable(): string |
|
504 | { |
||
505 | 56 | return app()->make($this->getTranslationModelName())->getTable(); |
|
506 | } |
||
507 | |||
508 | 480 | protected function locale(): string |
|
509 | { |
||
510 | 480 | if ($this->defaultLocale) { |
|
511 | 4 | return $this->defaultLocale; |
|
512 | } |
||
513 | |||
514 | 480 | return $this->getLocalesHelper()->current(); |
|
515 | } |
||
516 | |||
517 | 4 | public function setDefaultLocale(?string $locale) |
|
518 | { |
||
519 | 4 | $this->defaultLocale = $locale; |
|
520 | |||
521 | 4 | return $this; |
|
522 | } |
||
523 | |||
524 | public function getDefaultLocale(): ?string |
||
525 | { |
||
526 | return $this->defaultLocale; |
||
527 | } |
||
528 | |||
529 | /** |
||
530 | * @param string|array|null $locales The locales to be deleted |
||
531 | */ |
||
532 | 12 | public function deleteTranslations($locales = null) |
|
533 | { |
||
534 | 12 | if ($locales === null) { |
|
535 | 4 | $translations = $this->translations()->get(); |
|
536 | } else { |
||
537 | 8 | $locales = (array) $locales; |
|
538 | 8 | $translations = $this->translations()->whereIn($this->getLocaleKey(), $locales)->get(); |
|
0 ignored issues
–
show
The method
whereIn() does not exist on Illuminate\Database\Eloquent\Relations\HasMany . Did you maybe mean whereInMethod() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
539 | } |
||
540 | 12 | foreach ($translations as $translation) { |
|
541 | 8 | $translation->delete(); |
|
542 | } |
||
543 | |||
544 | // we need to manually "reload" the collection built from the relationship |
||
545 | // otherwise $this->translations()->get() would NOT be the same as $this->translations |
||
546 | 12 | $this->load('translations'); |
|
0 ignored issues
–
show
It seems like
load() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
547 | 12 | } |
|
548 | |||
549 | 480 | private function getAttributeAndLocale(string $key): array |
|
550 | { |
||
551 | 480 | if (Str::contains($key, ':')) { |
|
552 | 44 | return explode(':', $key); |
|
553 | } |
||
554 | |||
555 | 480 | return [$key, $this->locale()]; |
|
556 | } |
||
557 | |||
558 | 32 | private function toArrayAlwaysLoadsTranslations(): bool |
|
559 | { |
||
560 | 32 | return config('translatable.to_array_always_loads_translations', true); |
|
561 | } |
||
562 | |||
563 | public static function enableAutoloadTranslations(): void |
||
564 | { |
||
565 | self::$autoloadTranslations = true; |
||
566 | } |
||
567 | |||
568 | 4 | public static function defaultAutoloadTranslations(): void |
|
569 | { |
||
570 | 4 | self::$autoloadTranslations = null; |
|
571 | 4 | } |
|
572 | |||
573 | 4 | public static function disableAutoloadTranslations(): void |
|
574 | { |
||
575 | 4 | self::$autoloadTranslations = false; |
|
576 | 4 | } |
|
577 | |||
578 | 480 | protected function getLocalesHelper(): Locales |
|
579 | { |
||
580 | 480 | return app(Locales::class); |
|
581 | } |
||
582 | } |
||
583 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.