Skip to content

Commit

Permalink
refs kristijanhusak#447: adding same: rule automatically
Browse files Browse the repository at this point in the history
- adding `same:` rule to first field of repeated type
- proper handling of rules on repeated field itself and first subfield
  • Loading branch information
Eloar committed Apr 13, 2023
1 parent 7775b3e commit d6deadd
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ composer.phar
composer.lock
.DS_Store
.idea
.vscode
coverage
*.taskpaper
NOTES.md
NOTES.md
.phpunit.result.cache
14 changes: 13 additions & 1 deletion src/Kris/LaravelFormBuilder/Fields/FormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ protected function prepareRules(array &$sourceOptions = [])

// Append rules
if ($rulesToBeAppended = Arr::pull($sourceOptions, 'rules_append')) {
$mergedRules = array_values(array_unique(array_merge($options['rules'], $rulesToBeAppended), SORT_REGULAR));
$mergedRules = $this->mergeRules($options['rules'], $rulesToBeAppended);
$options['rules'] = $mergedRules;
}

Expand Down Expand Up @@ -390,6 +390,18 @@ protected function normalizeRules($rules)
return $rules;
}

/**
* Merges two sets of rules into one
*
* @param array $first first set of rules
* @param array $second second set of rules
* @return array merged set of rules without duplicates
*/
protected function mergeRules($first, $second)
{
return array_values(array_unique(array_merge($first, $second), SORT_REGULAR));
}


/**
* Get name of the field.
Expand Down
19 changes: 18 additions & 1 deletion src/Kris/LaravelFormBuilder/Fields/RepeatedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Kris\LaravelFormBuilder\Fields;

use Illuminate\Support\Arr;

class RepeatedType extends ParentType
{

Expand Down Expand Up @@ -42,21 +44,36 @@ public function getAllAttributes()
*/
protected function createChildren()
{
$this->prepareOptions();

$firstName = $this->getRealName();
$secondName = $this->getOption('second_name');

if (is_null($secondName)) {
$secondName = $firstName.'_confirmation';
}

// merge field rules and first field rules
$firstOptions = $this->getOption('first_options');
$firstOptions['rules'] = $this->normalizeRules(Arr::pull($firstOptions, 'rules', []));
if ($mainRules = $this->getOption('rules')) {
$firstOptions['rules'] = $this->mergeRules($mainRules, $firstOptions['rules']);
}

$sameRule = 'same:' . $secondName;
if (!in_array($sameRule, $firstOptions['rules'])) {
$firstOptions['rules'][] = $sameRule;
}

$form = $this->parent->getFormBuilder()->plain([
'name' => $this->parent->getName(),
'model' => $this->parent->getModel()
])
->add($firstName, $this->getOption('type'), $this->getOption('first_options'))
->add($firstName, $this->getOption('type'), $firstOptions)
->add($secondName, $this->getOption('type'), $this->getOption('second_options'));

$this->children['first'] = $form->getField($firstName);
$this->children['second'] = $form->getField($secondName);
}

}
90 changes: 89 additions & 1 deletion tests/Fields/RepeatedTypeTest.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?php


use Kris\LaravelFormBuilder\Fields\RepeatedType;
use Kris\LaravelFormBuilder\Form;


class RepeatedTypeTest extends FormBuilderTestCase
{
Expand Down Expand Up @@ -36,4 +37,91 @@ public function it_checks_if_field_rendered_by_children()

$this->assertTrue($this->plainForm->getFormOption('files'));
}

/** @test */
public function handles_validation_rules_properly()
{
// has no other rules
$plainForm = $this->formBuilder->plain();
$plainForm->add('password', 'repeated');
$repeated = $plainForm->getField('password');

$this->assertContains('same:password_confirmation', $repeated->first->getOption('rules'));

$this->request['password'] = '123';
$this->request['password_confirmation'] = '124';

$valid = $plainForm->isValid();
$this->assertFalse($valid);

$errors = [
'password' => ['The Password and password confirmation must match.'],
];
$this->assertEquals($errors, $plainForm->getErrors());

// has own rules
$plainForm = $this->formBuilder->plain();
$plainForm->add('password', 'repeated', [
'rules' => 'required|min:5',
]);
$plainForm->renderForm();

$rules = ['password' => ['required', 'min:5', 'same:password_confirmation']];
$this->assertEquals($rules, $plainForm->getRules());

$valid = $plainForm->isValid();
$this->assertFalse($valid);

$errors = [
'password' => [
'The Password must be at least 5 characters.',
'The Password and password confirmation must match.',
]
];
$this->assertEquals($errors, $plainForm->getErrors());

// has own rules on field and in first field options
$plainForm = $this->formBuilder->plain();
$plainForm->add('password', 'repeated', [
'rules' => 'required',
'first_options' => [
'rules' => 'min:5',
]
]);
$rules = ['password' => ['required', 'min:5', 'same:password_confirmation']];
$this->assertEquals($rules, $plainForm->getRules());
$valid = $plainForm->isValid();
$this->assertFalse($valid);

$errors = [
'password' => [
'The Password must be at least 5 characters.',
'The Password and password confirmation must match.',
]
];
$this->assertEquals($errors, $plainForm->getErrors());

// has rules only in field options
$plainForm = $this->formBuilder->plain();
$plainForm->add('password', 'repeated', [
'rules' => 'required',
'first_options' => [
'rules' => 'required|min:5',
]
]);
$rules = ['password' => ['required', 'min:5', 'same:password_confirmation']];
$this->assertEquals($rules, $plainForm->getRules());

$valid = $plainForm->isValid();
$this->assertFalse($valid);

$errors = [
'password' => [
'The Password must be at least 5 characters.',
'The Password and password confirmation must match.',
]
];
$this->assertEquals($errors, $plainForm->getErrors());
}

}

0 comments on commit d6deadd

Please sign in to comment.