Skip to content

Commit

Permalink
Fix Form Object Validation uninitialised properties. (#6731)
Browse files Browse the repository at this point in the history
* add failing test

* Add implementation for JIT form rules.

* wip

* wip

---------

Co-authored-by: Adrian Nürnberger <[email protected]>
Co-authored-by: Caleb Porzio <[email protected]>
  • Loading branch information
3 people committed Sep 13, 2023
1 parent 99e2933 commit 1a41fdd
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 24 deletions.
36 changes: 18 additions & 18 deletions src/Features/SupportFormObjects/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,38 @@ public function getPropertyName() { return $this->propertyName; }

protected function addValidationRulesToComponent()
{
$rules = [];
$this->component->addRulesFromOutside(function() {
$rules = [];

if (method_exists($this, 'rules')) $rules = $this->rules();
else if (property_exists($this, 'rules')) $rules = $this->rules;
if (method_exists($this, 'rules')) $rules = $this->rules();
else if (property_exists($this, 'rules')) $rules = $this->rules;

$this->component->addRulesFromOutside(
$this->getAttributesWithPrefixedKeys($rules)
);
return $this->getAttributesWithPrefixedKeys($rules);
});
}

protected function addValidationAttributesToComponent()
{
$validationAttributes = [];
$this->component->addValidationAttributesFromOutside(function() {
$validationAttributes = [];

if (method_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes();
else if (property_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes;
if (method_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes();
else if (property_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes;

$this->component->addValidationAttributesFromOutside(
$this->getAttributesWithPrefixedKeys($validationAttributes)
);
return $this->getAttributesWithPrefixedKeys($validationAttributes);
});
}

protected function addMessagesToComponent()
{
$messages = [];
$this->component->addMessagesFromOutside(function() {
$messages = [];

if (method_exists($this, 'messages')) $messages = $this->messages();
else if (property_exists($this, 'messages')) $messages = $this->messages;
if (method_exists($this, 'messages')) $messages = $this->messages();
else if (property_exists($this, 'messages')) $messages = $this->messages;

$this->component->addMessagesFromOutside(
$this->getAttributesWithPrefixedKeys($messages)
);
return $this->getAttributesWithPrefixedKeys($messages);
});
}

public function addError($key, $message)
Expand Down
49 changes: 49 additions & 0 deletions src/Features/SupportFormObjects/UnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Livewire\Component;
use Livewire\Form;
use Livewire\Livewire;
use PHPUnit\Framework\Assert;
use Sushi\Sushi;

class UnitTest extends \Tests\TestCase
Expand Down Expand Up @@ -206,6 +207,32 @@ function render() {
;
}

/** @test */
function all_properties_are_available_in_rules_method()
{
Livewire::test(new class extends Component {
public PostFormWithRulesStub $form;

public function mount()
{
$this->form->setPost(42);
}

function save() {
$this->form->validate();
}

function render() {
return '<div></div>';
}
})
->assertSet('form.post', 42)
->call('save')
->assertSet('form.post', 42)
->assertHasErrors()
;
}

/** @test */
function can_get_only_specific_properties()
{
Expand Down Expand Up @@ -408,6 +435,28 @@ class PostFormStub extends Form
public $content = '';
}

class PostFormWithRulesStub extends Form
{
public ?int $post = null;
public $title = '';
public $content = '';

public function setPost($model)
{
$this->post = $model;
}

public function rules()
{
Assert::assertEquals(42, $this->post, 'post should be available to run more complex rules');

return [
'title' => 'required',
'content' => 'required',
];
}
}

class PostFormValidateStub extends Form
{
public $title = '';
Expand Down
33 changes: 27 additions & 6 deletions src/Features/SupportValidation/HandlesValidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ trait HandlesValidation

public function addRulesFromOutside($rules)
{
$this->rulesFromOutside = array_merge_recursive($this->rulesFromOutside, $rules);
$this->rulesFromOutside[] = $rules;
}

public function addMessagesFromOutside($messages)
{
$this->messagesFromOutside = array_merge($this->messagesFromOutside, $messages);
$this->messagesFromOutside[] = $messages;
}

public function addValidationAttributesFromOutside($validationAttributes)
{
$this->validationAttributesFromOutside = array_merge($this->validationAttributesFromOutside, $validationAttributes);
$this->validationAttributesFromOutside[] = $validationAttributes;
}

public function getErrorBag()
Expand Down Expand Up @@ -107,7 +107,14 @@ public function getRules()
if (method_exists($this, 'rules')) $rulesFromComponent = $this->rules();
else if (property_exists($this, 'rules')) $rulesFromComponent = $this->rules;

return array_merge($rulesFromComponent, $this->rulesFromOutside);
$rulesFromOutside = array_merge_recursive(
...array_map(
fn($i) => value($i),
$this->rulesFromOutside
)
);

return array_merge($rulesFromComponent, $rulesFromOutside);
}

protected function getMessages()
Expand All @@ -117,7 +124,14 @@ protected function getMessages()
if (method_exists($this, 'messages')) $messages = $this->messages();
elseif (property_exists($this, 'messages')) $messages = $this->messages;

return array_merge($messages, $this->messagesFromOutside);
$messagesFromOutside = array_merge(
...array_map(
fn($i) => value($i),
$this->messagesFromOutside
)
);

return array_merge($messages, $messagesFromOutside);
}

protected function getValidationAttributes()
Expand All @@ -127,7 +141,14 @@ protected function getValidationAttributes()
if (method_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes();
elseif (property_exists($this, 'validationAttributes')) $validationAttributes = $this->validationAttributes;

return array_merge($validationAttributes, $this->validationAttributesFromOutside);
$validationAttributesFromOutside = array_merge(
...array_map(
fn($i) => value($i),
$this->validationAttributesFromOutside
)
);

return array_merge($validationAttributes, $validationAttributesFromOutside);
}

protected function getValidationCustomValues()
Expand Down

0 comments on commit 1a41fdd

Please sign in to comment.