Skip to content

Commit 3af6d0f

Browse files
committed
Support spatie/nova-translatable (#7)
1 parent 587cbd3 commit 3af6d0f

File tree

3 files changed

+135
-6
lines changed

3 files changed

+135
-6
lines changed

src/UniqueTranslationValidator.php

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class UniqueTranslationValidator
2121
*/
2222
public function validate($attribute, $value, $parameters, $validator)
2323
{
24-
list ($name, $locale) = $this->getAttributeNameAndLocale($attribute);
24+
list ($name, $locale) = $this->isNovaTranslation($attribute)
25+
? $this->getNovaAttributeNameAndLocale($attribute)
26+
: $this->getArrayAttributeNameAndLocale($attribute);
2527

2628
if ($this->isUnique($value, $name, $locale, $parameters)) {
2729
return true;
@@ -49,6 +51,7 @@ protected function setMissingErrorMessages($validator, $name, $locale)
4951
"{$name}.{$rule}",
5052
"{$name}.*.{$rule}",
5153
"{$name}.{$locale}.{$rule}",
54+
"translations_{$name}_{$locale}.{$rule}",
5255
];
5356

5457
foreach ($keys as $key) {
@@ -58,21 +61,87 @@ protected function setMissingErrorMessages($validator, $name, $locale)
5861
}
5962
}
6063

64+
/**
65+
* Check if the attribute is a Nova translation field name.
66+
*
67+
* @param string $attribute
68+
*
69+
* @return bool
70+
*/
71+
protected function isNovaTranslation($attribute)
72+
{
73+
return strpos($attribute, '.') === false && strpos($attribute, 'translations_') === 0;
74+
}
75+
76+
/**
77+
* Get the attribute name and locale of a Nova translation field.
78+
*
79+
* @param string $attribute
80+
*
81+
* @return array
82+
*/
83+
protected function getNovaAttributeNameAndLocale($attribute)
84+
{
85+
$attribute = str_replace('translations_', '', $attribute);
86+
87+
return $this->getAttributeNameAndLocale($attribute, '_');
88+
}
89+
90+
/**
91+
* Get the attribute name and locale of an array field.
92+
*
93+
* @param string $attribute
94+
*
95+
* @return array
96+
*/
97+
protected function getArrayAttributeNameAndLocale($attribute)
98+
{
99+
return $this->getAttributeNameAndLocale($attribute, '.');
100+
}
101+
61102
/**
62103
* Get the attribute name and locale.
63104
*
64105
* @param string $attribute
106+
* @param string $delimiter
65107
*
66108
* @return array
67109
*/
68-
protected function getAttributeNameAndLocale($attribute)
110+
protected function getAttributeNameAndLocale($attribute, $delimiter)
111+
{
112+
$locale = $this->getAttributeLocale($attribute, $delimiter);
113+
$name = $this->getAttributeName($attribute, $locale, $delimiter);
114+
115+
return [$name, $locale ?: App::getLocale()];
116+
}
117+
118+
/**
119+
* Get the locale from the attribute name.
120+
*
121+
* @param string $attribute
122+
* @param string $delimiter
123+
*
124+
* @return string|null
125+
*/
126+
protected function getAttributeLocale($attribute, $delimiter)
69127
{
70-
$parts = explode('.', $attribute);
128+
$pos = strrpos($attribute, $delimiter);
71129

72-
$name = $parts[0];
73-
$locale = $parts[1] ?? App::getLocale();
130+
return $pos > 0 ? substr($attribute, $pos + 1) : null;
131+
}
74132

75-
return [$name, $locale];
133+
/**
134+
* Get the attribute name without the locale.
135+
*
136+
* @param string $attribute
137+
* @param string|null $locale
138+
* @param string $delimiter
139+
*
140+
* @return string
141+
*/
142+
protected function getAttributeName($attribute, $locale, $delimiter)
143+
{
144+
return $locale ? str_replace("{$delimiter}{$locale}", '', $attribute) : $attribute;
76145
}
77146

78147
/**

tests/UniqueTranslationTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,32 @@ public function it_ignores_null_values()
237237

238238
$this->assertTrue($validation->passes());
239239
}
240+
241+
/** @test */
242+
public function it_validates_nova_translations()
243+
{
244+
Model::create([
245+
'slug' => ['nl' => 'existing-slug-nl'],
246+
'name' => ['nl' => 'existing-name-nl'],
247+
]);
248+
249+
$rules = [
250+
'translations_slug_nl' => "{$this->rule}:{$this->table},slug",
251+
'translations_name_nl' => UniqueTranslationRule::for($this->table, 'slug'),
252+
];
253+
254+
$validation = Validator::make([
255+
'translations_slug_nl' => 'existing-slug-nl',
256+
'translations_name_nl' => 'existing-name-nl',
257+
], $rules);
258+
259+
$this->assertTrue($validation->fails());
260+
261+
$validation = Validator::make([
262+
'translations_slug_nl' => 'different-slug-nl',
263+
'translations_name_nl' => 'different-name-nl',
264+
], $rules);
265+
266+
$this->assertTrue($validation->passes());
267+
}
240268
}

tests/ValidationMessageTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,36 @@ public function it_returns_a_custom_error_message_when_validating_an_array()
139139
'form_name.en' => [$expectedNameError],
140140
], $validation->errors()->messages());
141141
}
142+
143+
/** @test */
144+
public function it_returns_a_default_error_message_when_validating_a_nova_translation()
145+
{
146+
Model::create([
147+
'slug' => ['en' => 'existing-slug-en'],
148+
'name' => ['en' => 'existing-name-en'],
149+
]);
150+
151+
$formAttributes = [
152+
'translations_form_slug_en' => ['en' => 'existing-slug-en'],
153+
'translations_form_name_en' => ['en' => 'existing-name-en'],
154+
];
155+
156+
$rules = [
157+
'translations_form_slug_en' => "{$this->rule}:{$this->table},slug",
158+
'translations_form_name_en' => UniqueTranslationRule::for($this->table, 'name'),
159+
];
160+
161+
$expectedSlugError = trans('validation.unique', ['attribute' => 'translations form slug en']);
162+
$expectedNameError = trans('validation.unique', ['attribute' => 'translations form name en']);
163+
164+
$this->assertNotEmpty($expectedSlugError);
165+
$this->assertNotEmpty($expectedNameError);
166+
167+
$validation = Validator::make($formAttributes, $rules);
168+
169+
$this->assertEquals([
170+
'translations_form_slug_en' => [$expectedSlugError],
171+
'translations_form_name_en' => [$expectedNameError],
172+
], $validation->errors()->messages());
173+
}
142174
}

0 commit comments

Comments
 (0)