Skip to content

Commit

Permalink
Ability to pass a callable to CodeDefinitionBuilder::set*Validator() [c…
Browse files Browse the repository at this point in the history
…loses jbowens#60]

From this commit, it is possible to:

 - pass either InputValidor or a callable to both:
   - CodeDefinitionBuilder::setOptionValidator()
   - CodeDefinitionBuilder::setBodyValidator()
 - wrap any method or function into JBBCode\validators\CallableValidatorAdapter
   without need to manually implement InputValidator (this is also what internally
   CodeDefinitionBuilder does)
  • Loading branch information
Kubo2 committed Jul 28, 2015
1 parent 5b61239 commit 438147d
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 8 deletions.
32 changes: 28 additions & 4 deletions JBBCode/CodeDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
namespace JBBCode;

require_once "CodeDefinition.php";
require_once "validators/CallableValidatorAdapter.php";

/**
* Implements the builder pattern for the CodeDefinition class. A builder
* is the recommended way of constructing CodeDefinition objects.
*
* @author jbowens
* @author Kubo2
*/
class CodeDefinitionBuilder
{
Expand Down Expand Up @@ -111,26 +113,28 @@ public function setNestLimit($limit)
/**
* Sets the InputValidator that option arguments should be validated with.
*
* @param InputValidator $validator the InputValidator instance to use
* @param InputValidator|callable $validator the validator to use when validating input
* @return self
*/
public function setOptionValidator(InputValidator $validator, $option=null)
public function setOptionValidator($validator, $option=null)
{
if(empty($option)){
$option = $this->tagName;
}
$validator = $this->checkInputValidator($validator);
$this->optionValidator[$option] = $validator;
return $this;
}

/**
* Sets the InputValidator that body ({param}) text should be validated with.
*
* @param InputValidator $validator the InputValidator instance to use
* @param InputValidator|callable $validator the validator to use when validating input
* @return self
*/
public function setBodyValidator(InputValidator $validator)
public function setBodyValidator($validator)
{
$validator = $this->checkInputValidator($validator);
$this->bodyValidator = $validator;
return $this;
}
Expand Down Expand Up @@ -158,6 +162,26 @@ public function removeBodyValidator()
return $this;
}

/**
* Checks if `$validator` is a valid input validator, otherwise throws an exception
*
* @internal
* @return InputValidator
* @throws \InvalidArgumentException
*/
private function checkInputValidator($validator) {
if($validator instanceof InputValidator) {
return $validator;
} elseif(is_callable($validator)) {
return new validators\CallableValidatorAdapter($validator);
} else {
throw new \InvalidArgumentException(
'$validator must be either of type callable, or an instance of JBBCode\InputValidator, ' .
(is_object($validator) ? get_class($validator) : gettype($validator)) . ' given'
);
}
}

/**
* Builds a CodeDefinition with the current state of the builder.
*
Expand Down
2 changes: 1 addition & 1 deletion JBBCode/InputValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface InputValidator
{

/**
* Returns true iff the given input is valid, false otherwise.
* Returns true if the given input is valid, false otherwise.
* @param string $input
* @return boolean
*/
Expand Down
19 changes: 16 additions & 3 deletions JBBCode/tests/ValidatorTest.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<?php

require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'validators' . DIRECTORY_SEPARATOR . 'UrlValidator.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'validators' . DIRECTORY_SEPARATOR . 'CssColorValidator.php';
require_once __DIR__ . '/../Parser.php';
require_once __DIR__ . '/../validators/UrlValidator.php';
require_once __DIR__ . '/../validators/CssColorValidator.php';
require_once __DIR__ . '/../validators/CallableValidatorAdapter.php';

/**
* Test cases for InputValidators.
*
* @author jbowens
* @author Kubo2
* @since May 2013
*/
class ValidatorTest extends PHPUnit_Framework_TestCase
Expand Down Expand Up @@ -148,4 +150,15 @@ public function testInvalidColorBBCode()
$parser->getAsHtml());
}

/**
* Test functionality of {@link JBBCode\CallableValidatorAdapter}
*/
public function testCallableValidatorAdapter() {
$emptyValidator = new \JBBCode\validators\CallableValidatorAdapter(function($input) {
return empty($input);
});
$this->assertTrue($emptyValidator->validate(''));
$this->assertFalse($emptyValidator->validate('Hey! I am here'));
}

}
40 changes: 40 additions & 0 deletions JBBCode/validators/CallableValidatorAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace JBBCode\validators;

use JBBCode,
JBBCode\InputValidator;

require_once __DIR__ . '/../InputValidator.php';

/**
* An adapter for callable input validator.
*
* This class is most often created by {@link CodeDefinitionBuilder}
* and used as wrapper for different types of `callable` validators.
*
* @author Kubo2
* @since August 2015
*/
final class CallableValidatorAdapter implements InputValidator {

/** @var callable */
private $validator;

/**
* Constructs adapter's instance, taking `callable` validator as parameter.
*
* @param callable $validator The callable validator
*/
public function __construct(callable $validator) {
$this->validator = $validator;
}

/**
* {@inheritdoc}
* @return boolean Anything returned by the callable validator, coerced to boolean
*/
public function validate($input) {
return (boolean) call_user_func($this->validator, $input);
}
}

0 comments on commit 438147d

Please sign in to comment.