Skip to content

Commit

Permalink
Fix incorrect string handling of callbacks #26
Browse files Browse the repository at this point in the history
Fix incorrect scoping of callbacks preventing access to rule properties via $this
  • Loading branch information
dave-redfern committed Mar 22, 2024
1 parent 06af1b5 commit bb7baa2
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Change Log
==========

2024-03-21
----------

* fix callback strings as error messages (#26 thanks to [jakewhiteley](https://github.com/jakewhiteley)
* fix bug in callback binding in Callback rule, not setting scope to the rule instance

2024-03-02
----------

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,11 @@ $validation = $validator->validate($_POST, [
]);
```

You can set a custom message by returning a string instead of false:
You can set a custom message by returning a string instead of false. To allow for message translation, instead of
a literal string; return a message key instead and add this to the message bag on the Factory.

> Note: returning a message string will be removed in a future version, requiring only boolean responses.
> Instead, set the message string directly before returning true/false via `$this->message = "";`.
```php
$validation = $validator->validate($_POST, [
Expand Down
11 changes: 11 additions & 0 deletions src/MessageBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,15 @@ public function has(string $key, string $lang = null): bool
{
return isset($this->messages[$lang ?? $this->defaultLang][$key]);
}

public function hasAnyOf(array $keys, string $lang = null): bool
{
foreach ($keys as $key) {
if ($this->has($key, $lang)) {
return true;
}
}

return false;
}
}
2 changes: 1 addition & 1 deletion src/Rules/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function check(mixed $value): bool
throw new InvalidArgumentException(sprintf('Callback rule for "%s" is not callable.', $this->attribute->key()));
}

$callback = $callback->bindTo($this);
$callback = $callback->bindTo($this, $this);
$invalidMessage = $callback($value);

if (is_string($invalidMessage)) {
Expand Down
7 changes: 6 additions & 1 deletion src/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use Somnambulist\Components\Validation\Exceptions\RuleException;
use Somnambulist\Components\Validation\Rules\Callback;
use Somnambulist\Components\Validation\Rules\Contracts\ModifyValue;
use Somnambulist\Components\Validation\Rules\Required;

Expand Down Expand Up @@ -361,7 +362,11 @@ protected function resolveMessage(Attribute $attribute, Rule $rule, mixed $value
array_splice($messageKeys, 3, 0, $primaryAttributeKey);
}

$message->setMessage($this->messages->firstOf($messageKeys, $this->lang));
$message->setMessage(
$this->messages->hasAnyOf($messageKeys, $this->lang)
?
$this->messages->firstOf($messageKeys, $this->lang) : $message->key()
);

// Replace key indexes
$keyIndexes = $attribute->indexes();
Expand Down
58 changes: 58 additions & 0 deletions tests/Issues/GH26HandlingCallbackErrorMessagesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php declare(strict_types=1);

namespace Somnambulist\Components\Validation\Tests\Issues;

use PHPUnit\Framework\TestCase;
use Somnambulist\Components\Validation\Factory;

class GH26HandlingCallbackErrorMessagesTest extends TestCase
{
/**
* @link https://github.com/somnambulist-tech/validation/issues/26
*/
public function testReturningMessageStringsProducesErrorMessage()
{
$testData = [
'name' => 'John Doe',
'custom' => 'foo',
];

$validation = (new Factory)->validate($testData, [
'name' => 'required',
'custom' => [
'required',
function ($value) {
if ($value !== 'bar') {
return ':attribute should be bar';
}

return true;
},
],
]);

$this->assertEquals('custom should be bar', $validation->errors()->first('custom'));
}

public function testCanSetMessageIdentityViaCallback()
{
$testData = [
'name' => 'John Doe',
'custom' => 'foo',
];

$validation = (new Factory)->validate($testData, [
'name' => 'required',
'custom' => [
'required',
function ($value) {
$this->message = ':attribute should be bar';

return $value === 'bar';
},
],
]);

$this->assertEquals('custom should be bar', $validation->errors()->first('custom'));
}
}

0 comments on commit bb7baa2

Please sign in to comment.