diff --git a/src/JsonSchema/Constraints/Factory.php b/src/JsonSchema/Constraints/Factory.php index a4570f61..8cd25c1f 100644 --- a/src/JsonSchema/Constraints/Factory.php +++ b/src/JsonSchema/Constraints/Factory.php @@ -19,10 +19,27 @@ class Factory { /** - * @var UriRetriever + * @var UriRetriever $uriRetriever */ protected $uriRetriever; + /** + * @var array $constraintMap + */ + protected $constraintMap = array( + 'array' => 'JsonSchema\Constraints\CollectionConstraint', + 'collection' => 'JsonSchema\Constraints\CollectionConstraint', + 'object' => 'JsonSchema\Constraints\ObjectConstraint', + 'type' => 'JsonSchema\Constraints\TypeConstraint', + 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint', + 'string' => 'JsonSchema\Constraints\StringConstraint', + 'number' => 'JsonSchema\Constraints\NumberConstraint', + 'enum' => 'JsonSchema\Constraints\EnumConstraint', + 'format' => 'JsonSchema\Constraints\FormatConstraint', + 'schema' => 'JsonSchema\Constraints\SchemaConstraint', + 'validator' => 'JsonSchema\Validator', + ); + /** * @param UriRetriever $uriRetriever */ @@ -43,6 +60,25 @@ public function getUriRetriever() return $this->uriRetriever; } + /** + * @param string $name + * @param string $class + * @return Factory + */ + public function setConstraintClass($name, $class) + { + // Ensure class exists + if (!class_exists($class)) { + throw new InvalidArgumentException('Unknown constraint ' . $name); + } + // Ensure class is appropriate + if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) { + throw new InvalidArgumentException('Invalid class ' . $name); + } + $this->constraintMap[$name] = $class; + return $this; + } + /** * Create a constraint instance for the given constraint name. * @@ -52,30 +88,9 @@ public function getUriRetriever() */ public function createInstanceFor($constraintName) { - switch ($constraintName) { - case 'array': - case 'collection': - return new CollectionConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'object': - return new ObjectConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'type': - return new TypeConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'undefined': - return new UndefinedConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'string': - return new StringConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'number': - return new NumberConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'enum': - return new EnumConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'format': - return new FormatConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'schema': - return new SchemaConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); - case 'validator': - return new Validator(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); + if (array_key_exists($constraintName, $this->constraintMap)) { + return new $this->constraintMap[$constraintName](Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this); } - throw new InvalidArgumentException('Unknown constraint ' . $constraintName); } } diff --git a/tests/JsonSchema/Tests/Constraints/FactoryTest.php b/tests/JsonSchema/Tests/Constraints/FactoryTest.php index b7c6cbe5..e3a2acab 100644 --- a/tests/JsonSchema/Tests/Constraints/FactoryTest.php +++ b/tests/JsonSchema/Tests/Constraints/FactoryTest.php @@ -9,9 +9,25 @@ namespace JsonSchema\Tests\Constraints; +use JsonSchema\Constraints\Constraint; use JsonSchema\Constraints\Factory; use PHPUnit_Framework_TestCase as TestCase; + +/** + * Class MyBadConstraint + * @package JsonSchema\Tests\Constraints + */ +class MyBadConstraint {} + +/** + * Class MyStringConstraint + * @package JsonSchema\Tests\Constraints + */ +class MyStringConstraint extends Constraint { + public function check($value, $schema = null, $path = null, $i = null){} +} + class FactoryTest extends TestCase { /** @@ -69,10 +85,34 @@ public function testExceptionWhenCreateInstanceForInvalidConstraintName($constra $this->factory->createInstanceFor($constraintName); } - public function invalidConstraintNameProvider() + public function invalidConstraintNameProvider() { + return array( + array('invalidConstraintName'), + ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetConstraintClassExistsCondition() + { + $this->factory->setConstraintClass('string', 'SomeConstraint'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetConstraintClassImplementsCondition() + { + $this->factory->setConstraintClass('string', 'JsonSchema\Tests\Constraints\MyBadConstraint'); + } + + public function testSetConstraintClassInstance() { - return array( - array('invalidConstraintName'), - ); + $this->factory->setConstraintClass('string', 'JsonSchema\Tests\Constraints\MyStringConstraint'); + $constraint = $this->factory->createInstanceFor('string'); + $this->assertInstanceOf('JsonSchema\Tests\Constraints\MyStringConstraint', $constraint); + $this->assertInstanceOf('JsonSchema\Constraints\ConstraintInterface', $constraint); + $this->assertSame($this->factory->getUriRetriever(), $constraint->getUriRetriever()); } }