There are three steps to creating and using new rules:
Write a rule class, either to validate or sanitize a subject field
Set a factory for the class in the appropriate rule locator
Use the new rule in a filter specification
Writing a rule class is straightforward. Define a class with an
__invoke($subject, $field)
method, along with any additional needed arguments.
The method should return a boolean: true on success, or false on failure.
Here is an example of a hexdecimal validator:
namespace Vendor\Package\Filter\Rule\Validate;
class ValidateHex
{
public function __invoke($subject, $field, $max = null)
{
// must be scalar
$value = $subject->$field;
if (! is_scalar($value)) {
return false;
}
// must be hex
$hex = ctype_xdigit($value);
if (! $hex) {
return false;
}
// must be no longer than $max chars
if ($max && strlen($value) > $max) {
return false;
}
// done!
return true;
}
}
Here is an example of a hexadecimal sanitizer. Note how we modify the
$subject->$field
value directly at the end of the method.
namespace Vendor\Package\Filter\Rule\Sanitize;
class SanitizeHex
{
public function __invoke($subject, $field, $max = null)
{
$value = $subject->$field;
// must be scalar
if (! is_scalar($value)) {
// sanitizing failed
return false;
}
// strip out non-hex characters
$value = preg_replace('/[^0-9a-f]/i', '', $value);
if ($value === '') {
// failed to sanitize to a hex value
return false;
}
// now check length and chop if needed
if ($max && strlen($value) > $max) {
$value = substr($value, 0, $max);
}
// retain the sanitized value, and done!
$subject->$field = $value;
return true;
}
}
Now we set a factory for the rule into the appropriate locator from the FilterFactory. Pass additional $validate_factories
and $sanitize_factories
to the FilterFactory at construction time; Wrap the rule instantiation logic in a closure so that it is lazy-loaded only when the rule is called:
use Aura\Filter\FilterFactory;
$validate_factories = array(
'hex' => function () { return new Vendor\Package\Filter\Rule\Validate\ValidateHex(); },
);
$sanitize_factories = array(
'hex' => function () { return new Vendor\Package\Filter\Rule\Sanitize\SanitizeHex(); },
);
$filter_factory = new FilterFactory(
$validate_factories,
$sanitize_factories
);
Finally, we can use the rule in our filters:
$filter = $filter_factory->newSubjectFilter();
// the 'color' field must be a hex value of no more than 6 digits
$filter->validate('color')->is('hex', 6);
// force the 'color' field to a hex value of no more than 6 digits
$filter->sanitize('color')->to('hex', 6);