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 BrunoFernandes\LaravelMultiLanguage; |
||
4 | |||
5 | use Illuminate\Support\Arr; |
||
6 | use Illuminate\Support\Facades\App; |
||
7 | use Illuminate\Database\Eloquent\Builder; |
||
8 | use BrunoFernandes\LaravelMultiLanguage\Scopes\LangScope; |
||
9 | use BrunoFernandes\LaravelMultiLanguage\Exceptions\ModelTranslationAlreadyExistsException; |
||
10 | |||
11 | trait Translatable |
||
12 | { |
||
13 | abstract public function getKeyName(); |
||
14 | |||
15 | /** |
||
16 | * @return void |
||
17 | */ |
||
18 | public static function bootTranslatable(): void |
||
19 | { |
||
20 | static::creating(function ($model) { |
||
21 | // set default language if not set |
||
22 | if (!$model->{$model->getLangKey()}) { |
||
23 | $model->{$model->getLangKey()} = App::getLocale(); |
||
24 | } |
||
25 | }); |
||
26 | |||
27 | static::created(function ($model) { |
||
28 | // Set original field id when created |
||
29 | if (!$model->{$model->getForeignKey()}) { |
||
30 | $model->{$model->getForeignKey()} = $model->id; |
||
31 | $model->save(); |
||
32 | } |
||
33 | }); |
||
34 | |||
35 | if (config('laravel-multi-language.apply_lang_global_scope')) { |
||
36 | static::addGlobalScope(new LangScope); |
||
37 | } |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * @return string |
||
42 | */ |
||
43 | public function getLangKey(): String |
||
44 | { |
||
45 | return config('laravel-multi-language.lang_key', 'lang'); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * @return string |
||
50 | */ |
||
51 | public function getForeignKey(): String |
||
52 | { |
||
53 | return config('laravel-multi-language.foreign_key', 'original_id'); |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * @return \Illuminate\Database\Eloquent\Relations\HasMany |
||
58 | */ |
||
59 | public function translations() |
||
60 | { |
||
61 | return $this->hasMany(get_class($this), $this->getForeignKey(), $this->getForeignKey()); |
||
0 ignored issues
–
show
|
|||
62 | } |
||
63 | |||
64 | // public function original() |
||
65 | // { |
||
66 | // return $this->belongsTo(get_class($this), 'profile_id', 'id'); |
||
67 | // } |
||
68 | |||
69 | /** |
||
70 | * Determin fields to be excluded from the translation |
||
71 | * |
||
72 | * @return array |
||
73 | */ |
||
74 | private function fieldsToExclude(): array |
||
75 | { |
||
76 | $exclude = []; |
||
77 | if ($this->excludeFieldsFromTranslation && is_array($this->excludeFieldsFromTranslation)) { |
||
78 | $exclude = $this->excludeFieldsFromTranslation; |
||
79 | } |
||
80 | |||
81 | return array_merge( |
||
82 | [$this->getKeyName(), $this->getLangKey(), $this->getForeignKey(), 'created_at', 'updated_at'], |
||
83 | $exclude |
||
84 | ); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Translate model to another language |
||
89 | * |
||
90 | * @param String $lang |
||
91 | * @param array $data |
||
92 | * @return Illuminate\Database\Eloquent\Model |
||
93 | */ |
||
94 | public function translateTo($lang, $data = []) |
||
95 | { |
||
96 | $newLangData = [$this->getLangKey() => $lang, $this->getForeignKey() => $this->{$this->getForeignKey()}]; |
||
97 | $originalData = Arr::except($this->toArray(), $this->fieldsToExclude()); |
||
0 ignored issues
–
show
It seems like
toArray() 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 ![]() |
|||
98 | $data = Arr::except($data, $this->fieldsToExclude()); // clean up passed data |
||
99 | $data = array_merge($originalData, $data, $newLangData); |
||
100 | |||
101 | if ($this->hasTranslation($lang)) { |
||
102 | throw new ModelTranslationAlreadyExistsException('Translation already exists.', 1); |
||
103 | } |
||
104 | |||
105 | // TODO: add event here: model.translating |
||
106 | |||
107 | $translation = self::create($data); |
||
108 | |||
109 | // TODO: add event here: model.translated |
||
110 | |||
111 | return $translation; |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Checks if record has a translation |
||
116 | * |
||
117 | * @param String $lang |
||
118 | * @return Boolean |
||
119 | */ |
||
120 | public function hasTranslation($lang): bool |
||
121 | { |
||
122 | if ($this->lang == $lang) { |
||
123 | return true; |
||
124 | } |
||
125 | return $this->getTranslationBaseQuery($lang)->exists(); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Undocumented function |
||
130 | * |
||
131 | * @param String $lang |
||
132 | * @return \Illuminate\Database\Eloquent\Builder |
||
133 | */ |
||
134 | private function getTranslationBaseQuery($lang): Builder |
||
135 | { |
||
136 | return self::withoutGlobalScope(LangScope::class) |
||
137 | ->where($this->getLangKey(), $lang) |
||
138 | ->where($this->getForeignKey(), $this->{$this->getForeignKey()}); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Get translation |
||
143 | * |
||
144 | * @param String $lang |
||
145 | * @return Illuminate\Database\Eloquent\Model|null |
||
146 | */ |
||
147 | public function translation($lang) |
||
148 | { |
||
149 | return $this->getTranslationBaseQuery($lang)->first(); |
||
150 | } |
||
151 | |||
152 | /* |
||
153 | * Return translation excluding the current language |
||
154 | * |
||
155 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
156 | */ |
||
157 | public function scopeWithTranslations(Builder $query, $lang = null, $fields = []) |
||
158 | { |
||
159 | return $query->with(['translations' => function ($q) use ($lang, $fields) { |
||
160 | $q->notLang($lang, $fields); |
||
161 | }]); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * @param \Illuminate\Database\Eloquent\Builder $query |
||
166 | * @param string $lang |
||
167 | * |
||
168 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
169 | */ |
||
170 | public function scopeLang(Builder $query, $lang = null) |
||
171 | { |
||
172 | return $query->where($this->getLangKey(), $lang ?: App::getLocale()); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * @param \Illuminate\Database\Eloquent\Builder $query |
||
177 | * @param string $lang |
||
178 | * |
||
179 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
180 | */ |
||
181 | public function scopeNotLang(Builder $query, $lang = null) |
||
182 | { |
||
183 | return $query->where($this->getLangKey(), '!=', $lang ?: App::getLocale()) |
||
184 | ->withoutGlobalScope(LangScope::class); |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Return only original rows |
||
189 | * @param \Illuminate\Database\Eloquent\Builder $query |
||
190 | * |
||
191 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
192 | */ |
||
193 | public function scopeOnlyOriginal(Builder $query) |
||
194 | { |
||
195 | return $query->whereRaw($this->getTable() . '.id = ' . $this->getTable() . '.' . $this->getForeignKey()); |
||
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 ![]() |
|||
196 | } |
||
197 | |||
198 | /* @param \Illuminate \Database \Eloquent \Builder $query |
||
199 | * |
||
200 | * @return \Illuminate\Database\Eloquent\Builder | static |
||
201 | */ |
||
202 | public function scopeOnlyOriginals(Builder $query) |
||
203 | { |
||
204 | return $this->scopeOnlyOriginal($query); |
||
205 | } |
||
206 | } |
||
207 |
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.