{{ __('Add') }} {{ search }}
@@ -253,6 +253,10 @@ export default {
this.rules = rules;
},
+ valueWithoutTrailingColon(value) {
+ return this.hasUnfinishedParameters(value) ? value.replace(':', '') : value;
+ }
+
}
}
diff --git a/resources/js/components/field-validation/Rules.js b/resources/js/components/field-validation/Rules.js
index e5000917890..fd1b8e99061 100644
--- a/resources/js/components/field-validation/Rules.js
+++ b/resources/js/components/field-validation/Rules.js
@@ -286,6 +286,10 @@ export default [
// value: 'unique:',
// example: 'unique:table,column,except,idColumn'
// },
+ {
+ label: 'Unique Entry Value',
+ value: 'unique_entry_value:{collection},{id},{site}',
+ },
{
label: 'URL',
value: 'url'
diff --git a/src/Fields/Validator.php b/src/Fields/Validator.php
index e0d194255c6..59b5a4c5562 100644
--- a/src/Fields/Validator.php
+++ b/src/Fields/Validator.php
@@ -4,11 +4,13 @@
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Validator as LaravelValidator;
+use Statamic\Support\Arr;
+use Statamic\Support\Str;
class Validator
{
protected $fields;
- protected $data = [];
+ protected $replacements = [];
protected $extraRules = [];
public function make()
@@ -34,7 +36,11 @@ public function rules()
{
return $this
->merge($this->fieldRules(), $this->extraRules)
- ->all();
+ ->map(function ($rules) {
+ return collect($rules)->map(function ($rule) {
+ return $this->parse($rule);
+ })->all();
+ })->all();
}
private function fieldRules()
@@ -65,6 +71,13 @@ public function merge($original, $overrides)
return collect($original);
}
+ public function withReplacements($replacements)
+ {
+ $this->replacements = $replacements;
+
+ return $this;
+ }
+
public function validate()
{
return LaravelValidator::validate(
@@ -84,6 +97,17 @@ private function fieldAttributes()
})->all();
}
+ private function parse($rule)
+ {
+ if (! Str::contains($rule, '{')) {
+ return $rule;
+ }
+
+ return preg_replace_callback('/{\s*([a-zA-Z0-9_\-]+)\s*}/', function ($match) {
+ return Arr::get($this->replacements, $match[1], 'NULL');
+ }, $rule);
+ }
+
public static function explodeRules($rules)
{
if (! $rules) {
diff --git a/src/Http/Controllers/CP/Collections/EntriesController.php b/src/Http/Controllers/CP/Collections/EntriesController.php
index 7974b10f8d3..118a2b0aca9 100644
--- a/src/Http/Controllers/CP/Collections/EntriesController.php
+++ b/src/Http/Controllers/CP/Collections/EntriesController.php
@@ -164,7 +164,14 @@ public function update(Request $request, $collection, $entry)
$fields = $entry->blueprint()->fields()->addValues($data);
- $fields->validate(Entry::updateRules($collection, $entry));
+ $fields
+ ->validator()
+ ->withRules(Entry::updateRules($collection, $entry))
+ ->withReplacements([
+ 'id' => $entry->id(),
+ 'collection' => $collection->handle(),
+ 'site' => $entry->locale(),
+ ])->validate();
$values = $fields->process()->values();
@@ -302,7 +309,13 @@ public function store(Request $request, $collection, $site)
$fields = $blueprint->fields()->addValues($data);
- $fields->validate(Entry::createRules($collection, $site));
+ $fields
+ ->validator()
+ ->withRules(Entry::createRules($collection, $site))
+ ->withReplacements([
+ 'collection' => $collection->handle(),
+ 'site' => $site->handle(),
+ ])->validate();
$values = $fields->process()->values()->except(['slug', 'date', 'blueprint']);
diff --git a/tests/Fields/ValidatorTest.php b/tests/Fields/ValidatorTest.php
index a600ef03185..3dc8447500b 100644
--- a/tests/Fields/ValidatorTest.php
+++ b/tests/Fields/ValidatorTest.php
@@ -116,4 +116,32 @@ public function it_merges_additional_rules_into_field_rules()
'additional' => ['required'],
], $validation->rules());
}
+
+ /** @test */
+ public function it_makes_replacements()
+ {
+ $field = Mockery::mock(Field::class);
+ $field->shouldReceive('rules')->andReturn([
+ 'one' => ['required', 'test:{foo}'],
+ ]);
+
+ $fields = Mockery::mock(Fields::class);
+ $fields->shouldReceive('all')->andReturn(collect([$field]));
+ $fields->shouldReceive('preProcessValidatables')->andReturnSelf();
+
+ $validation = (new Validator)->fields($fields)->withRules([
+ 'one' => 'test:{bar}',
+ 'two' => 'another:{baz},{qux},{quux}',
+ ])->withReplacements([
+ 'foo' => 'FOO',
+ 'bar' => 'BAR',
+ 'baz' => 'BAZ',
+ 'quux' => 'QUUX',
+ ]);
+
+ $this->assertEquals([
+ 'one' => ['required', 'test:FOO', 'test:BAR'],
+ 'two' => ['another:BAZ,NULL,QUUX'],
+ ], $validation->rules());
+ }
}