├── .gitignore ├── src └── Validation │ ├── ValidationException.php │ ├── Schema │ ├── ClosureSchema.php │ ├── ResourceSchema.php │ ├── AlternativeSchema.php │ ├── ObjectSchema.php │ ├── BooleanSchema.php │ ├── DateSchema.php │ ├── NumberSchema.php │ ├── ArraySchema.php │ ├── AbstractSchema.php │ ├── AnySchema.php │ └── StringSchema.php │ ├── Assertions │ ├── IsArray.php │ ├── IsFloat.php │ ├── BooleanFalse.php │ ├── BooleanTrue.php │ ├── IsBoolean.php │ ├── IsObject.php │ ├── IsString.php │ ├── IsCallable.php │ ├── IsInteger.php │ ├── IsResource.php │ ├── ArrayNotEmpty.php │ ├── StringAlphaNum.php │ ├── IsNumber.php │ ├── Email.php │ ├── InArray.php │ ├── NumberMax.php │ ├── NumberMin.php │ ├── StringLengthMax.php │ ├── StringLengthMin.php │ ├── StringLength.php │ ├── IpAddress.php │ ├── Required.php │ ├── IsDate.php │ ├── ArrayLengthMax.php │ ├── ArrayLengthMin.php │ ├── ArrayLength.php │ ├── CustomCallback.php │ ├── RegexReplace.php │ ├── Uri.php │ ├── AlternativeAny.php │ ├── NotInArray.php │ ├── StringReplace.php │ ├── ObjectInstanceOf.php │ ├── DateAfter.php │ ├── StringLowercase.php │ ├── StringTrim.php │ ├── StringUppercase.php │ ├── DateBefore.php │ ├── DateTimeObject.php │ ├── Regex.php │ ├── DateBetween.php │ ├── AbstractAssertion.php │ └── ArrayKeys.php │ ├── InputValue.php │ ├── Utils.php │ └── Validation.php ├── .travis.yml ├── tests ├── ValidationErrorTest.php ├── InputValueTest.php ├── stubs │ └── TestAnyCustomClassMethod.php ├── AlternativeSchemaTest.php ├── ClosureSchemaTest.php ├── ResourceSchemaTest.php ├── UtilsTest.php ├── ObjectSchemaTest.php ├── BooleanSchemaTest.php ├── ValidationTest.php ├── ArraySchemaTest.php ├── DateSchemaTest.php ├── NumberSchemaTest.php ├── AnySchemaTest.php └── StringSchemaTest.php ├── Makefile ├── composer.json ├── phpunit.xml ├── LICENSE ├── README.md ├── DOCUMENTATION.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject 2 | ._* 3 | .~lock.* 4 | .buildpath 5 | .DS_Store 6 | .idea 7 | .project 8 | .settings 9 | vendor 10 | build 11 | -------------------------------------------------------------------------------- /src/Validation/ValidationException.php: -------------------------------------------------------------------------------- 1 | getMessage(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Validation/Schema/ClosureSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsCallable()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Validation/Schema/ResourceSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsResource()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 7.0 6 | - hhvm 7 | 8 | matrix: 9 | allow_failures: 10 | - php: hhvm 11 | 12 | before_install: 13 | - composer self-update 14 | 15 | install: 16 | - travis_retry make deps 17 | 18 | script: 19 | - make cs 20 | - make test 21 | 22 | after_script: 23 | - make coveralls 24 | -------------------------------------------------------------------------------- /tests/ValidationErrorTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('test', $error->getMessage()); 14 | $this->assertEquals('test', (string) $error); 15 | $this->assertEquals('test', $error); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Validation/Schema/AlternativeSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\AlternativeAny(['options' => Utils::variadicToArray($arguments)])); 17 | 18 | return $this; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | cs: lint 2 | ./vendor/bin/phpcbf --standard=PSR2 src tests 3 | ./vendor/bin/phpcs --standard=PSR2 --warning-severity=0 src tests 4 | 5 | lint: 6 | find src/ tests/ -name "*.php" -exec php -l {} \; 7 | 8 | test: 9 | ./vendor/bin/phpunit 10 | 11 | coveralls: 12 | ./vendor/bin/coveralls -v 13 | 14 | deps: 15 | composer install 16 | 17 | coverage: 18 | ./vendor/bin/phpunit --coverage-html=build/logs/coverage 19 | 20 | clean: 21 | rm -rf coverage 22 | 23 | .PHONY: cs lint test coveralls deps coverage clean 24 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsArray.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not an array'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsFloat.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not a float'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/BooleanFalse.php: -------------------------------------------------------------------------------- 1 | getValue() !== false) { 17 | throw new ValidationException('value is not FALSE'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/BooleanTrue.php: -------------------------------------------------------------------------------- 1 | getValue() !== true) { 17 | throw new ValidationException('value is not TRUE'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsBoolean.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not a boolean'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsObject.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not an object'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsString.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not a string'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsCallable.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not callable'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsInteger.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not an integer'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsResource.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value is not a resource'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ArrayNotEmpty.php: -------------------------------------------------------------------------------- 1 | getValue()) === 0) { 17 | throw new ValidationException('value is an empty array'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Schema/ObjectSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsObject()); 12 | } 13 | 14 | /** 15 | * @param $className 16 | * @return $this 17 | */ 18 | public function instance($className) 19 | { 20 | $this->assert(new Assertions\ObjectInstanceOf(['of' => $className])); 21 | 22 | return $this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringAlphaNum.php: -------------------------------------------------------------------------------- 1 | getValue())) { 17 | throw new ValidationException('value contains not alphanumeric chars'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsNumber.php: -------------------------------------------------------------------------------- 1 | getValue()) && !is_float($input->getValue())) { 17 | throw new ValidationException('value is not a number'); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/Email.php: -------------------------------------------------------------------------------- 1 | getValue(), FILTER_VALIDATE_EMAIL)) { 17 | throw new ValidationException(sprintf('"%s" is not a valid email', $input->getValue())); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/InArray.php: -------------------------------------------------------------------------------- 1 | getValue(), $this->getOption('allowed'))) { 17 | throw new ValidationException(sprintf('value "%s" is not allowed', $input->getValue())); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Validation/Assertions/NumberMax.php: -------------------------------------------------------------------------------- 1 | getOption('number'); 17 | 18 | if ($input->getValue() > $number) { 19 | throw new ValidationException(sprintf('value must be <= %d', $number)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Validation/Assertions/NumberMin.php: -------------------------------------------------------------------------------- 1 | getOption('number'); 17 | 18 | if ($input->getValue() < $number) { 19 | throw new ValidationException(sprintf('value must be >= %d', $number)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringLengthMax.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $length = strlen($input->getValue()); 18 | 19 | if ($length > $number) { 20 | throw new ValidationException(sprintf('value length > %d', $number)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringLengthMin.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $length = strlen($input->getValue()); 18 | 19 | if ($length < $number) { 20 | throw new ValidationException(sprintf('value length < %d', $number)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/InputValueTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('foo', $input->getValue()); 14 | 15 | $input->setValue('bar'); 16 | $this->assertEquals('bar', $input->getValue()); 17 | 18 | $input->setValue(2); 19 | 20 | $input->replace(function ($value) { 21 | return $value * 2; 22 | }); 23 | 24 | $this->assertEquals(4, $input->getValue()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/stubs/TestAnyCustomClassMethod.php: -------------------------------------------------------------------------------- 1 | replace(function ($value) { 16 | return strtoupper($value); 17 | }); 18 | } 19 | 20 | /** 21 | * @throws ValidationException 22 | */ 23 | public function throwException() 24 | { 25 | throw new ValidationException('A custom validation message'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringLength.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $length = strlen($input->getValue()); 18 | 19 | if ($length != $number) { 20 | throw new ValidationException(sprintf('value length is %d, expected %d', $length, $number)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Validation/Schema/BooleanSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsBoolean()); 12 | } 13 | 14 | /** 15 | * @return $this 16 | */ 17 | public function false() 18 | { 19 | $this->assert(new Assertions\BooleanFalse()); 20 | 21 | return $this; 22 | } 23 | 24 | /** 25 | * @return $this 26 | */ 27 | public function true() 28 | { 29 | $this->assert(new Assertions\BooleanTrue()); 30 | 31 | return $this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IpAddress.php: -------------------------------------------------------------------------------- 1 | getOption('options', FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6); 17 | 18 | if (!filter_var($input->getValue(), FILTER_VALIDATE_IP, $options)) { 19 | throw new ValidationException(sprintf('"%s" is not a valid IP address', $input->getValue())); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Validation/Assertions/Required.php: -------------------------------------------------------------------------------- 1 | getValue() === null) { 17 | throw new ValidationException('value is required'); 18 | } 19 | 20 | if (is_string($input->getValue()) && !strlen($input->getValue())) { 21 | throw new ValidationException('value is required'); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Validation/Assertions/IsDate.php: -------------------------------------------------------------------------------- 1 | getValue() instanceof \DateTime) { 17 | return; 18 | } 19 | 20 | if (is_string($input->getValue()) && false !== strtotime($input->getValue())) { 21 | return; 22 | } 23 | 24 | throw new ValidationException('value is not a date'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ArrayLengthMax.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $actual = count($input->getValue()); 18 | 19 | if ($actual > $expected) { 20 | $message = sprintf('array needs to have at most %d items', $expected); 21 | throw new ValidationException($message); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ArrayLengthMin.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $actual = count($input->getValue()); 18 | 19 | if ($actual < $expected) { 20 | $message = sprintf('array needs to have at least %d items', $expected); 21 | throw new ValidationException($message); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ArrayLength.php: -------------------------------------------------------------------------------- 1 | getOption('length'); 17 | $actual = count($input->getValue()); 18 | 19 | if ($actual != $expected) { 20 | $message = sprintf('array length is %d, while length of %d was expected', $actual, $expected); 21 | throw new ValidationException($message); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Validation/Assertions/CustomCallback.php: -------------------------------------------------------------------------------- 1 | getOption('callback'); 20 | $callback($input); 21 | } 22 | 23 | /** 24 | * @return ArraySchema 25 | */ 26 | protected function getOptionsSchema() 27 | { 28 | return V::arr()->keys([ 29 | 'callback' => V::closure() 30 | ]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Validation/Assertions/RegexReplace.php: -------------------------------------------------------------------------------- 1 | replace(function ($value) { 17 | return preg_replace($this->getOption('pattern'), $this->getOption('replace'), $value); 18 | }); 19 | } 20 | 21 | /** 22 | * @return AbstractSchema 23 | */ 24 | public function getOptionsSchema() 25 | { 26 | return V::arr()->keys([ 27 | 'pattern' => V::string()->min(1), 28 | 'replace' => V::string() 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Validation/InputValue.php: -------------------------------------------------------------------------------- 1 | setValue($value); 18 | } 19 | 20 | /** 21 | * @param $value 22 | */ 23 | public function setValue($value) 24 | { 25 | $this->value = $value; 26 | } 27 | 28 | /** 29 | * @return mixed 30 | */ 31 | public function getValue() 32 | { 33 | return $this->value; 34 | } 35 | 36 | /** 37 | * @param \Closure $callback 38 | */ 39 | public function replace(\Closure $callback) 40 | { 41 | $this->setValue($callback($this->getValue())); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Validation/Assertions/Uri.php: -------------------------------------------------------------------------------- 1 | getOption('options'); 17 | 18 | if ($options == null && !filter_var($input->getValue(), FILTER_VALIDATE_URL)) { 19 | throw new ValidationException(sprintf('"%s" is not a valid URI', $input->getValue())); 20 | } 21 | 22 | if ($options !== null && !filter_var($input->getValue(), FILTER_VALIDATE_URL, $options)) { 23 | throw new ValidationException(sprintf('"%s" is not a valid URI', $input->getValue())); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Validation/Assertions/AlternativeAny.php: -------------------------------------------------------------------------------- 1 | getOption('options') as $schema) { 18 | try { 19 | $input->replace(function ($value) use ($schema) { 20 | return V::attempt($value, $schema); 21 | }); 22 | return; 23 | } catch (ValidationException $e) { 24 | } 25 | } 26 | 27 | throw new ValidationException('none of the alternatives matched'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bartosz-maciaszek/validation", 3 | "description": "Validation library for PHP 5.6+ / HHVM inspired by Joi.", 4 | "type": "library", 5 | "keywords": [ 6 | "validate", 7 | "validation" 8 | ], 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Bartosz Maciaszek", 13 | "email": "bartosz.maciaszek@gmail.com", 14 | "role": "lead" 15 | } 16 | ], 17 | "support": { 18 | "issues": "https://github.com/bartosz-maciaszek/validation/issues" 19 | }, 20 | "require": { 21 | "php": ">=5.6" 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "5.4.*", 25 | "squizlabs/php_codesniffer": "~2.0", 26 | "satooshi/php-coveralls": "~1.0.0" 27 | }, 28 | "autoload": { 29 | "psr-4": {"Validation\\": "src/Validation/"} 30 | }, 31 | "autoload-dev": { 32 | "psr-4": {"Validation\\Tests\\": "tests/"} 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Validation/Assertions/NotInArray.php: -------------------------------------------------------------------------------- 1 | getValue(), $this->getOption('disallowed'))) { 19 | throw new ValidationException(sprintf('value "%s" is disallowed', $input->getValue())); 20 | } 21 | } 22 | 23 | /** 24 | * @return AbstractSchema 25 | */ 26 | protected function getOptionsSchema() 27 | { 28 | return Validation::arr()->keys([ 29 | 'disallowed' => Validation::arr()->notEmpty() 30 | ]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ./src 20 | 21 | 22 | 23 | 24 | ./tests 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringReplace.php: -------------------------------------------------------------------------------- 1 | replace(function ($value) { 17 | return str_replace($this->getOption('search'), $this->getOption('replace'), $value); 18 | }); 19 | } 20 | 21 | /** 22 | * @return AbstractSchema 23 | */ 24 | public function getOptionsSchema() 25 | { 26 | return V::arr()->keys([ 27 | 'search' => V::alternative()->any(V::string()->min(1), V::arr()->notEmpty()), 28 | 'replace' => V::alternative()->any(V::string(), V::arr()->notEmpty()) 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ObjectInstanceOf.php: -------------------------------------------------------------------------------- 1 | getOption('of'); 19 | 20 | if (!$input->getValue() instanceof $name) { 21 | throw new ValidationException(sprintf('object is not an instance of %s', $name)); 22 | } 23 | } 24 | 25 | /** 26 | * @return AbstractSchema 27 | */ 28 | protected function getOptionsSchema() 29 | { 30 | return V::arr()->keys([ 31 | 'of' => V::string()->min(1) 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/AlternativeSchemaTest.php: -------------------------------------------------------------------------------- 1 | any(V::string()->valid('foo'), V::boolean()), function ($err, $output) { 12 | $this->assertNull($err); 13 | $this->assertEquals('foo', $output); 14 | }); 15 | 16 | V::validate(true, V::alternative()->any(V::string()->valid('foo'), V::boolean()), function ($err, $output) { 17 | $this->assertNull($err); 18 | $this->assertTrue(true, $output); 19 | }); 20 | 21 | V::validate(null, V::alternative()->any(V::string()->valid('foo'), V::boolean()), function ($err, $output) { 22 | $this->assertEquals('none of the alternatives matched', $err); 23 | $this->assertNull($output); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Validation/Assertions/DateAfter.php: -------------------------------------------------------------------------------- 1 | process($input); 20 | 21 | $date = Utils::toDateObject($input->getValue()); 22 | 23 | $toCompare = $this->getOption('time'); 24 | 25 | if ($date <= $toCompare) { 26 | throw new ValidationException('Date should be after ' . $toCompare->format(\DateTime::ISO8601)); 27 | } 28 | } 29 | 30 | protected function getOptionsSchema() 31 | { 32 | return V::arr()->keys([ 33 | 'time' => V::date()->dateTimeObject() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringLowercase.php: -------------------------------------------------------------------------------- 1 | getOption('convert') === false && !ctype_lower($input->getValue())) { 19 | throw new ValidationException('value must be lowercase'); 20 | } 21 | 22 | $input->replace(function ($value) { 23 | return strtolower($value); 24 | }); 25 | } 26 | 27 | /** 28 | * @return AbstractSchema 29 | */ 30 | protected function getOptionsSchema() 31 | { 32 | return V::arr()->keys([ 33 | 'convert' => V::boolean() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringTrim.php: -------------------------------------------------------------------------------- 1 | getOption('convert') === false && trim($input->getValue()) !== $input->getValue()) { 19 | throw new ValidationException('value is not trimmed'); 20 | } 21 | 22 | $input->replace(function ($value) { 23 | return trim($value); 24 | }); 25 | } 26 | 27 | /** 28 | * @return AbstractSchema 29 | */ 30 | protected function getOptionsSchema() 31 | { 32 | return V::arr()->keys([ 33 | 'convert' => V::boolean() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Assertions/StringUppercase.php: -------------------------------------------------------------------------------- 1 | getOption('convert') === false && !ctype_upper($input->getValue())) { 19 | throw new ValidationException('value must be uppercase'); 20 | } 21 | 22 | $input->replace(function ($value) { 23 | return strtoupper($value); 24 | }); 25 | } 26 | 27 | /** 28 | * @return AbstractSchema 29 | */ 30 | protected function getOptionsSchema() 31 | { 32 | return V::arr()->keys([ 33 | 'convert' => V::boolean() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Assertions/DateBefore.php: -------------------------------------------------------------------------------- 1 | process($input); 20 | 21 | $date = Utils::toDateObject($input->getValue()); 22 | 23 | $toCompare = $this->getOption('time'); 24 | 25 | if ($date >= $toCompare) { 26 | throw new ValidationException('Date should be before ' . $toCompare->format(\DateTime::ISO8601)); 27 | } 28 | } 29 | 30 | protected function getOptionsSchema() 31 | { 32 | return V::arr()->keys([ 33 | 'time' => V::date()->dateTimeObject() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Assertions/DateTimeObject.php: -------------------------------------------------------------------------------- 1 | getOption('convert') === false && !$input->getValue() instanceof \DateTime) { 20 | throw new ValidationException('value is not a DateTime object'); 21 | } 22 | 23 | $input->replace(function ($value) { 24 | return Utils::toDateObject($value); 25 | }); 26 | } 27 | 28 | /** 29 | * @return AbstractSchema 30 | */ 31 | protected function getOptionsSchema() 32 | { 33 | return V::arr()->keys([ 34 | 'convert' => V::boolean() 35 | ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Validation/Assertions/Regex.php: -------------------------------------------------------------------------------- 1 | getOption('pattern'); 19 | $message = $this->getOption('message', sprintf('value does not match pattern %s', $pattern)); 20 | 21 | if (!preg_match($this->getOption('pattern'), $input->getValue())) { 22 | throw new ValidationException($message); 23 | } 24 | } 25 | 26 | /** 27 | * @return AbstractSchema 28 | */ 29 | protected function getOptionsSchema() 30 | { 31 | return Validation::arr()->keys([ 32 | 'pattern' => Validation::string(), 33 | // 'message' => Validation::string()->optional() 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Validation/Utils.php: -------------------------------------------------------------------------------- 1 | 1) { 18 | return $arguments; 19 | } 20 | 21 | $arg = current($arguments); 22 | 23 | if (is_array($arg)) { 24 | if (count($arg) === 0) { 25 | throw new \InvalidArgumentException('Argument needs to be a not empty array'); 26 | } 27 | 28 | return $arg; 29 | } 30 | 31 | return [$arg]; 32 | } 33 | 34 | /** 35 | * @param $date 36 | * @return \DateTime 37 | */ 38 | public static function toDateObject($date) 39 | { 40 | if ($date instanceof \DateTime) { 41 | return $date; 42 | } 43 | 44 | return new \DateTime($date); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Bartosz Maciaszek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /tests/ClosureSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 17 | $this->assertEquals($function, $output); 18 | }); 19 | 20 | V::validate('123', V::closure(), function ($err, $output) { 21 | $this->assertEquals('value is not callable', $err); 22 | $this->assertNull($output); 23 | }); 24 | 25 | V::validate([], V::closure(), function ($err, $output) { 26 | $this->assertEquals('value is not callable', $err); 27 | $this->assertNull($output); 28 | }); 29 | 30 | V::validate(new \stdClass(), V::closure(), function ($err, $output) { 31 | $this->assertEquals('value is not callable', $err); 32 | $this->assertNull($output); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/ResourceSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 15 | $this->assertEquals($fileHandler, $output); 16 | }); 17 | 18 | fclose($fileHandler); 19 | 20 | V::validate('123', V::resource(), function ($err, $output) { 21 | $this->assertEquals('value is not a resource', $err); 22 | $this->assertNull($output); 23 | }); 24 | 25 | V::validate([], V::resource(), function ($err, $output) { 26 | $this->assertEquals('value is not a resource', $err); 27 | $this->assertNull($output); 28 | }); 29 | 30 | V::validate(new \stdClass(), V::resource(), function ($err, $output) { 31 | $this->assertEquals('value is not a resource', $err); 32 | $this->assertNull($output); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Validation/Assertions/DateBetween.php: -------------------------------------------------------------------------------- 1 | process($input); 20 | 21 | $date = Utils::toDateObject($input->getValue()); 22 | 23 | $time1 = $this->getOption('time1'); 24 | $time2 = $this->getOption('time2'); 25 | 26 | if ($date < $time1 || $date > $time2) { 27 | throw new ValidationException('Date should be between ' 28 | . $time1->format(\DateTime::ISO8601) . ' and ' 29 | . $time2->format(\DateTime::ISO8601)); 30 | } 31 | } 32 | 33 | protected function getOptionsSchema() 34 | { 35 | return V::arr()->keys([ 36 | 'time1' => V::date()->dateTimeObject(), 37 | 'time2' => V::date()->dateTimeObject() 38 | ]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/UtilsTest.php: -------------------------------------------------------------------------------- 1 | provideVariadicFunction(); 12 | 13 | $this->assertEquals(['abc'], $function('abc')); 14 | $this->assertEquals(['abc'], $function(['abc'])); 15 | $this->assertEquals(['abc', 'def'], $function(['abc', 'def'])); 16 | $this->assertEquals(['abc', 'def'], $function('abc', 'def')); 17 | } 18 | 19 | public function testVariadicToArrayEmptyArray() 20 | { 21 | $this->setExpectedException('\InvalidArgumentException'); 22 | 23 | $function = $this->provideVariadicFunction(); 24 | $function([]); 25 | } 26 | 27 | public function testVariadicToArrayNoArgs() 28 | { 29 | $this->setExpectedException('\InvalidArgumentException'); 30 | 31 | $function = $this->provideVariadicFunction(); 32 | $function(); 33 | } 34 | 35 | /** 36 | * @return \Closure 37 | */ 38 | protected function provideVariadicFunction() 39 | { 40 | return function () { 41 | return Utils::variadicToArray(func_get_args()); 42 | }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validation/Schema/DateSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsDate()); 12 | } 13 | 14 | /** 15 | * @param bool $convert 16 | * @return $this 17 | */ 18 | public function dateTimeObject($convert = true) 19 | { 20 | $this->assert(new Assertions\DateTimeObject(['convert' => $convert])); 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * @param $time 27 | * @return $this 28 | */ 29 | public function after($time) 30 | { 31 | $this->assert(new Assertions\DateAfter(['time' => $time])); 32 | 33 | return $this; 34 | } 35 | 36 | /** 37 | * @param $time 38 | * @return $this 39 | */ 40 | public function before($time) 41 | { 42 | $this->assert(new Assertions\DateBefore(['time' => $time])); 43 | 44 | return $this; 45 | } 46 | 47 | /** 48 | * @param $time1 49 | * @param $time2 50 | * @return $this 51 | */ 52 | public function between($time1, $time2) 53 | { 54 | $this->assert(new Assertions\DateBetween(['time1' => $time1, 'time2' => $time2])); 55 | 56 | return $this; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Validation/Schema/NumberSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsNumber()); 12 | } 13 | 14 | /** 15 | * @return $this 16 | */ 17 | public function integer() 18 | { 19 | $this->assert(new Assertions\IsInteger()); 20 | 21 | return $this; 22 | } 23 | 24 | /** 25 | * @return $this 26 | */ 27 | public function float() 28 | { 29 | $this->assert(new Assertions\IsFloat()); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * @param $number 36 | * @return $this 37 | */ 38 | public function min($number) 39 | { 40 | $this->assert(new Assertions\NumberMin(['number' => $number])); 41 | 42 | return $this; 43 | } 44 | 45 | /** 46 | * @param $number 47 | * @return $this 48 | */ 49 | public function max($number) 50 | { 51 | $this->assert(new Assertions\NumberMax(['number' => $number])); 52 | 53 | return $this; 54 | } 55 | 56 | /** 57 | * @param $min 58 | * @param $max 59 | * @return $this 60 | */ 61 | public function between($min, $max) 62 | { 63 | $this->min($min); 64 | $this->max($max); 65 | 66 | return $this; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Validation/Schema/ArraySchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsArray()); 12 | } 13 | 14 | /** 15 | * @param array $keys 16 | * @return $this 17 | */ 18 | public function keys(array $keys) 19 | { 20 | $this->assert(new Assertions\ArrayKeys(['keys' => $keys])); 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * @param $length 27 | * @return $this 28 | */ 29 | public function length($length) 30 | { 31 | $this->assert(new Assertions\ArrayLength(['length' => $length])); 32 | 33 | return $this; 34 | } 35 | 36 | /** 37 | * @param $length 38 | * @return $this 39 | */ 40 | public function max($length) 41 | { 42 | $this->assert(new Assertions\ArrayLengthMax(['length' => $length])); 43 | 44 | return $this; 45 | } 46 | 47 | /** 48 | * @param $length 49 | * @return $this 50 | */ 51 | public function min($length) 52 | { 53 | $this->assert(new Assertions\ArrayLengthMin(['length' => $length])); 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * @return $this 60 | */ 61 | public function notEmpty() 62 | { 63 | $this->assert(new Assertions\ArrayNotEmpty()); 64 | 65 | return $this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Validation/Schema/AbstractSchema.php: -------------------------------------------------------------------------------- 1 | false, 21 | 'default' => null 22 | ]; 23 | 24 | /** 25 | * @param InputValue $input 26 | * @return mixed 27 | */ 28 | public function process(InputValue $input) 29 | { 30 | foreach ($this->assertions() as $assertion) { 31 | $assertion->process($input); 32 | } 33 | 34 | return $input->getValue(); 35 | } 36 | 37 | /** 38 | * @return Assertions\AbstractAssertion[] 39 | */ 40 | protected function assertions() 41 | { 42 | return $this->assertions; 43 | } 44 | 45 | /** 46 | * @param Assertions\AbstractAssertion $assertion 47 | */ 48 | protected function assert(Assertions\AbstractAssertion $assertion) 49 | { 50 | $this->assertions[] = $assertion; 51 | } 52 | 53 | /** 54 | * @param $name 55 | * @param $value 56 | */ 57 | protected function setOption($name, $value) 58 | { 59 | $this->options[$name] = $value; 60 | } 61 | 62 | /** 63 | * @param $name 64 | * @return mixed 65 | */ 66 | public function getOption($name) 67 | { 68 | return $this->options[$name]; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Validation/Schema/AnySchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\CustomCallback(['callback' => $callback])); 17 | 18 | return $this; 19 | } 20 | 21 | /** 22 | * @param $value 23 | * @return $this 24 | */ 25 | public function defaultValue($value) 26 | { 27 | $this->setOption('default', $value); 28 | 29 | return $this; 30 | } 31 | 32 | /** 33 | * @param ...$arguments 34 | * @return $this 35 | */ 36 | public function invalid(...$arguments) 37 | { 38 | $this->assert(new Assertions\NotInArray(['disallowed' => Utils::variadicToArray($arguments)])); 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * @return $this 45 | */ 46 | public function required() 47 | { 48 | $this->assert(new Assertions\Required()); 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * @return $this 55 | */ 56 | public function strip() 57 | { 58 | $this->setOption('strip', true); 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * @param ...$arguments 65 | * @return $this 66 | */ 67 | public function valid(...$arguments) 68 | { 69 | $this->assert(new Assertions\InArray(['allowed' => Utils::variadicToArray($arguments)])); 70 | 71 | return $this; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Validation/Assertions/AbstractAssertion.php: -------------------------------------------------------------------------------- 1 | setOptions($options); 23 | } 24 | 25 | /** 26 | * @param $name 27 | * @param mixed $default 28 | * @return mixed 29 | */ 30 | public function getOption($name, $default = null) 31 | { 32 | if (!isset($this->options[$name])) { 33 | return $default; 34 | } 35 | 36 | return $this->options[$name]; 37 | } 38 | 39 | /** 40 | * @param array $options 41 | */ 42 | public function setOptions(array $options) 43 | { 44 | if ($schema = $this->getOptionsSchema()) { 45 | try { 46 | $this->options = V::attempt($options, $schema); 47 | } catch (ValidationException $e) { 48 | throw new \InvalidArgumentException($e); 49 | } 50 | } else { 51 | $this->options = $options; 52 | } 53 | } 54 | 55 | /** 56 | * @return AbstractSchema|null 57 | */ 58 | protected function getOptionsSchema() 59 | { 60 | return null; 61 | } 62 | 63 | /** 64 | * @param InputValue $input 65 | */ 66 | abstract public function process(InputValue $input); 67 | } 68 | -------------------------------------------------------------------------------- /tests/ObjectSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 15 | $this->assertEquals($instance, $output); 16 | }); 17 | 18 | V::validate(123, V::object(), function ($err, $output) { 19 | $this->assertEquals('value is not an object', $err); 20 | $this->assertNull($output); 21 | }); 22 | 23 | V::validate([], V::object(), function ($err, $output) { 24 | $this->assertEquals('value is not an object', $err); 25 | $this->assertNull($output); 26 | }); 27 | 28 | V::validate('foo', V::object(), function ($err, $output) { 29 | $this->assertEquals('value is not an object', $err); 30 | $this->assertNull($output); 31 | }); 32 | } 33 | 34 | public function testObjectInstance() 35 | { 36 | $instance = new \DateTime(); 37 | 38 | V::validate($instance, V::object()->instance('\DateTime'), function ($err, $output) use ($instance) { 39 | $this->assertNull($err); 40 | $this->assertEquals($instance, $output); 41 | }); 42 | 43 | V::validate(new \stdClass(), V::object()->instance('\DateTime'), function ($err, $output) { 44 | $this->assertEquals('object is not an instance of \DateTime', $err); 45 | $this->assertNull($output); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/BooleanSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 13 | $this->assertTrue($output); 14 | }); 15 | 16 | V::validate(false, V::boolean(), function ($err, $output) { 17 | $this->assertNull($err); 18 | $this->assertFalse($output); 19 | }); 20 | 21 | V::validate(null, V::boolean(), function ($err, $output) { 22 | $this->assertEquals('value is not a boolean', $err); 23 | $this->assertNull($output); 24 | }); 25 | } 26 | 27 | public function testBooleanTrue() 28 | { 29 | V::validate(true, V::boolean()->true(), function ($err, $output) { 30 | $this->assertNull($err); 31 | $this->assertTrue($output); 32 | }); 33 | 34 | V::validate(false, V::boolean()->true(), function ($err, $output) { 35 | $this->assertEquals('value is not TRUE', $err); 36 | $this->assertNull($output); 37 | }); 38 | } 39 | 40 | public function testBooleanFalse() 41 | { 42 | V::validate(false, V::boolean()->false(), function ($err, $output) { 43 | $this->assertNull($err); 44 | $this->assertFalse($output); 45 | }); 46 | 47 | V::validate(true, V::boolean()->false(), function ($err, $output) { 48 | $this->assertEquals('value is not FALSE', $err); 49 | $this->assertNull($output); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/ValidationTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 13 | $this->assertEquals('string', $output); 14 | }); 15 | } 16 | 17 | public function testValidateWithCallbackNegative() 18 | { 19 | V::validate('string', V::number(), function ($err, $output) { 20 | $this->assertEquals('value is not a number', (string) $err); 21 | $this->assertNull($output); 22 | }); 23 | } 24 | 25 | public function testValidateWithoutCallbackPositive() 26 | { 27 | $result = V::validate('string', V::string()); 28 | 29 | $this->assertArrayHasKey('err', $result); 30 | $this->assertArrayHasKey('output', $result); 31 | 32 | $this->assertNull($result['err']); 33 | $this->assertEquals('string', $result['output']); 34 | } 35 | 36 | public function testValidateWithoutCallbackNegative() 37 | { 38 | $result = V::validate('string', V::number()); 39 | 40 | $this->assertArrayHasKey('err', $result); 41 | $this->assertArrayHasKey('output', $result); 42 | 43 | $this->assertEquals('value is not a number', (string) $result['err']); 44 | $this->assertNull($result['output']); 45 | } 46 | 47 | public function testAssertPositive() 48 | { 49 | V::assert('string', V::string()); 50 | } 51 | 52 | public function testAssertNegative() 53 | { 54 | $this->setExpectedException('\Validation\ValidationException'); 55 | 56 | V::assert('string', V::number()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Validation/Assertions/ArrayKeys.php: -------------------------------------------------------------------------------- 1 | getOption('keys') as $key => $schema) { 20 | $this->processKey($input, $key, $schema); 21 | } 22 | } 23 | 24 | /** 25 | * @param InputValue $input 26 | * @param $key 27 | * @param AbstractSchema $schema 28 | * @throws ValidationException 29 | */ 30 | private function processKey(InputValue $input, $key, AbstractSchema $schema) 31 | { 32 | if (!array_key_exists($key, $input->getValue())) { 33 | $this->handleMissingKey($input, $key, $schema->getOption('default')); 34 | } else { 35 | $this->validateAndReplaceKey($input, $key, $schema); 36 | } 37 | } 38 | 39 | /** 40 | * @param InputValue $input 41 | * @param $key 42 | * @param $defaultValue 43 | * @throws ValidationException 44 | */ 45 | private function handleMissingKey(InputValue $input, $key, $defaultValue) 46 | { 47 | if (!isset($defaultValue)) { 48 | throw new ValidationException(sprintf('key "%s" is missing', $key)); 49 | } 50 | 51 | $input->replace(function ($value) use ($key, $defaultValue) { 52 | $value[$key] = is_callable($defaultValue) ? $defaultValue($value) : $defaultValue; 53 | 54 | return $value; 55 | }); 56 | } 57 | 58 | /** 59 | * @param InputValue $input 60 | * @param $key 61 | * @param AbstractSchema $schema 62 | * @throws ValidationException 63 | */ 64 | private function validateAndReplaceKey(InputValue $input, $key, AbstractSchema $schema) 65 | { 66 | try { 67 | $input->replace(function ($value) use ($key, $schema) { 68 | $value[$key] = V::attempt($value[$key], $schema); 69 | 70 | return $value; 71 | }); 72 | 73 | if ($schema->getOption('strip')) { 74 | $input->replace(function ($value) use ($key) { 75 | unset($value[$key]); 76 | 77 | return $value; 78 | }); 79 | } 80 | } catch (ValidationException $e) { 81 | throw new ValidationException(sprintf('key "%s" is invalid, because [ %s ]', $key, $e->getMessage())); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | About 2 | ----- 3 | 4 | Validation library for PHP 5.6+ / PHP 7 / HHVM inspired by [Joi](https://github.com/hapijs/joi) from [Hapi](http://hapijs.com). 5 | 6 | [![Build Status](https://travis-ci.org/bartosz-maciaszek/validation.svg?branch=master)](https://travis-ci.org/bartosz-maciaszek/validation) 7 | [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg)](https://php.net/) 8 | [![Coverage Status](https://coveralls.io/repos/bartosz-maciaszek/validation/badge.svg?branch=master&service=github)](https://coveralls.io/github/bartosz-maciaszek/validation?branch=master) 9 | [![Dependency Status](https://www.versioneye.com/user/projects/56a8ec827e03c7003db68c73/badge.svg?style=flat)](https://www.versioneye.com/user/projects/56a8ec827e03c7003db68c73) 10 | 11 | 12 | Installation 13 | ------------ 14 | 15 | The recommended way to install the library is through [Composer](http://getcomposer.com) 16 | 17 | composer require bartosz-maciaszek/validation 18 | 19 | 20 | Examples 21 | -------- 22 | 23 | Validation with the library is straightforward. You can validate primitives like this: 24 | 25 | ```php 26 | email(), function($err, $output) { 44 | // ... 45 | }); 46 | ``` 47 | 48 | The library also supports transformations: 49 | 50 | ```php 51 | V::validate('FooBar', V::string()->lowercase(), function($err, $output) { 52 | // $output equals 'foobar'! 53 | }); 54 | ``` 55 | 56 | Wanna something more complex? Let's try to validate an array! 57 | 58 | ```php 59 | $input = [ 60 | 'username' => 'foobar', 61 | 'password' => 'secret123', 62 | 'birthyear' => 1980, 63 | 'email' => 'foobar@example.com', 64 | 'sex' => 'male' 65 | ]; 66 | 67 | $schema = V::arr()->keys([ 68 | 'username' => V::string()->alphanum()->min(3)->max(30), 69 | 'password' => V::string()->regex('/[a-z-A-Z0-9]{3,30}/'), 70 | 'birthyear' => V::number()->integer()->min(1900)->max(2013), 71 | 'email' => V::string()->email(), 72 | 'sex' => V::string()->valid('male', 'female') 73 | ]); 74 | 75 | V::validate($input, $schema, function ($err, $output) { 76 | // $err === null -> valid! 77 | }); 78 | ``` 79 | 80 | Documentation can be found [here](DOCUMENTATION.md) (please note it's not 100% completed :)). 81 | 82 | Tests 83 | ----- 84 | 85 | To run the unit test, simply install the dependencies and invoke `make test` 86 | 87 | $ make deps 88 | $ make test 89 | 90 | Contributing 91 | ------------ 92 | 93 | Contributions are welcome. If you want to help, please fork the repo and submit a pull request. To maintain the coding style, please make sure your code complies with PSR2 standard. 94 | 95 | $ make cs 96 | -------------------------------------------------------------------------------- /src/Validation/Validation.php: -------------------------------------------------------------------------------- 1 | $err, 'output' => $output ]; 20 | }; 21 | } 22 | 23 | try { 24 | return $callback(null, self::attempt($value, $schema)); 25 | } catch (ValidationException $e) { 26 | return $callback($e, null); 27 | } 28 | } 29 | 30 | /** 31 | * @param $value 32 | * @param AbstractSchema $schema 33 | */ 34 | public static function assert($value, AbstractSchema $schema) 35 | { 36 | self::attempt($value, $schema); 37 | } 38 | 39 | /** 40 | * @param $value 41 | * @param AbstractSchema $schema 42 | * @return mixed 43 | */ 44 | public static function attempt($value, AbstractSchema $schema) 45 | { 46 | return $schema->process(new InputValue($value)); 47 | } 48 | 49 | /** 50 | * @return Schema\AnySchema 51 | */ 52 | public static function any() 53 | { 54 | return new Schema\AnySchema(); 55 | } 56 | 57 | /** 58 | * @return Schema\StringSchema 59 | */ 60 | public static function string() 61 | { 62 | return new Schema\StringSchema(); 63 | } 64 | 65 | /** 66 | * @return Schema\ObjectSchema 67 | */ 68 | public static function object() 69 | { 70 | return new Schema\ObjectSchema(); 71 | } 72 | 73 | /** 74 | * @return Schema\ArraySchema 75 | */ 76 | public static function arr() 77 | { 78 | return new Schema\ArraySchema(); 79 | } 80 | 81 | /** 82 | * @return Schema\NumberSchema 83 | */ 84 | public static function number() 85 | { 86 | return new Schema\NumberSchema(); 87 | } 88 | 89 | /** 90 | * @return Schema\DateSchema 91 | */ 92 | public static function date() 93 | { 94 | return new Schema\DateSchema(); 95 | } 96 | 97 | /** 98 | * @return Schema\BooleanSchema 99 | */ 100 | public static function boolean() 101 | { 102 | return new Schema\BooleanSchema(); 103 | } 104 | 105 | /** 106 | * @return Schema\ResourceSchema 107 | */ 108 | public static function resource() 109 | { 110 | return new Schema\ResourceSchema(); 111 | } 112 | 113 | /** 114 | * @return Schema\ClosureSchema 115 | */ 116 | public static function closure() 117 | { 118 | return new Schema\ClosureSchema(); 119 | } 120 | 121 | /** 122 | * @return Schema\AlternativeSchema 123 | */ 124 | public static function alternative() 125 | { 126 | return new Schema\AlternativeSchema(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Validation/Schema/StringSchema.php: -------------------------------------------------------------------------------- 1 | assert(new Assertions\IsString()); 12 | } 13 | 14 | /** 15 | * @return $this 16 | */ 17 | public function alphanum() 18 | { 19 | $this->assert(new Assertions\StringAlphaNum()); 20 | 21 | return $this; 22 | } 23 | 24 | /** 25 | * @return $this 26 | */ 27 | public function email() 28 | { 29 | $this->assert(new Assertions\Email()); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * @param int $options 36 | * @return $this 37 | */ 38 | public function ip($options = null) 39 | { 40 | $this->assert(new Assertions\IpAddress(['options' => $options])); 41 | 42 | return $this; 43 | } 44 | 45 | /** 46 | * @param $length 47 | * @return $this 48 | */ 49 | public function length($length) 50 | { 51 | $this->assert(new Assertions\StringLength(['length' => $length])); 52 | 53 | return $this; 54 | } 55 | 56 | /** 57 | * @param bool $convert 58 | * @return $this 59 | */ 60 | public function lowercase($convert = true) 61 | { 62 | $this->assert(new Assertions\StringLowercase(['convert' => $convert])); 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * @param $length 69 | * @return $this 70 | */ 71 | public function max($length) 72 | { 73 | $this->assert(new Assertions\StringLengthMax(['length' => $length])); 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * @param $length 80 | * @return $this 81 | */ 82 | public function min($length) 83 | { 84 | $this->assert(new Assertions\StringLengthMin(['length' => $length])); 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * @param $pattern 91 | * @return $this 92 | */ 93 | public function regex($pattern) 94 | { 95 | $this->assert(new Assertions\Regex(['pattern' => $pattern])); 96 | 97 | return $this; 98 | } 99 | 100 | /** 101 | * @param $pattern 102 | * @param $replace 103 | * @return $this 104 | */ 105 | public function regexReplace($pattern, $replace) 106 | { 107 | $this->assert(new Assertions\RegexReplace(['pattern' => $pattern, 'replace' => $replace])); 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * @param $search 114 | * @param $replace 115 | * @return $this 116 | */ 117 | public function replace($search, $replace) 118 | { 119 | $this->assert(new Assertions\StringReplace(['search' => $search, 'replace' => $replace])); 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * @return $this 126 | */ 127 | public function token() 128 | { 129 | $this->assert(new Assertions\Regex([ 130 | 'pattern' => '/^[A-Za-z0-9_]+$/', 131 | 'message' => 'value is not a token' 132 | ])); 133 | 134 | return $this; 135 | } 136 | 137 | /** 138 | * @param bool $convert 139 | * @return $this 140 | */ 141 | public function uppercase($convert = true) 142 | { 143 | $this->assert(new Assertions\StringUppercase(['convert' => $convert])); 144 | 145 | return $this; 146 | } 147 | 148 | /** 149 | * @param bool $convert 150 | * @return $this 151 | */ 152 | public function trim($convert = true) 153 | { 154 | $this->assert(new Assertions\StringTrim(['convert' => $convert])); 155 | 156 | return $this; 157 | } 158 | 159 | /** 160 | * @param null $options 161 | * @return $this 162 | */ 163 | public function uri($options = null) 164 | { 165 | $this->assert(new Assertions\Uri(['options' => $options])); 166 | 167 | return $this; 168 | } 169 | 170 | /** 171 | * @return $this 172 | */ 173 | public function notEmpty() 174 | { 175 | $this->assert(new Assertions\StringLengthMin(['length' => 1])); 176 | 177 | return $this; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /tests/ArraySchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 13 | $this->assertEquals([], $output); 14 | }); 15 | 16 | V::validate(123, V::arr(), function ($err, $output) { 17 | $this->assertEquals('value is not an array', $err); 18 | $this->assertNull($output); 19 | }); 20 | 21 | 22 | V::validate('foo', V::arr(), function ($err, $output) { 23 | $this->assertEquals('value is not an array', $err); 24 | $this->assertNull($output); 25 | }); 26 | } 27 | 28 | public function testKeys() 29 | { 30 | $input = [ 'foo' => 'bar', 'baz' => 'quux' ]; 31 | 32 | $schema = V::arr()->keys([ 33 | 'foo' => V::string()->valid('bar'), 34 | 'baz' => V::string()->valid('quux') 35 | ]); 36 | 37 | V::validate($input, $schema, function ($err, $output) use ($input) { 38 | $this->assertNull($err); 39 | $this->assertEquals($input, $output); 40 | }); 41 | } 42 | 43 | public function testKeysMissingKey() 44 | { 45 | $input = [ 'foo' => 'bar' ]; 46 | 47 | $schema = V::arr()->keys([ 48 | 'foo' => V::string(), 49 | 'baz' => V::string() 50 | ]); 51 | 52 | V::validate($input, $schema, function ($err, $output) use ($input) { 53 | $this->assertEquals('key "baz" is missing', $err); 54 | $this->assertNull($output); 55 | }); 56 | } 57 | 58 | public function testKeysNestedWithConversion() 59 | { 60 | $input = [ 'foo' => [ 'bar' => 'baz' ]]; 61 | 62 | $schema = V::arr()->keys([ 63 | 'foo' => V::arr()->keys([ 64 | 'bar' => V::string()->uppercase() 65 | ]) 66 | ]); 67 | 68 | V::validate($input, $schema, function ($err, $output) { 69 | $this->assertNull($err); 70 | $this->assertEquals([ 'foo' => [ 'bar' => 'BAZ' ]], $output); 71 | }); 72 | } 73 | 74 | public function testKeysNestedInvalid() 75 | { 76 | $input = [ 'foo' => 'bar', 'baz' => 'quux', 'array' => [ 'foo' => 'bar', 'baz' => 'quux' ] ]; 77 | 78 | $schema = V::arr()->keys([ 79 | 'foo' => V::string()->valid('bar'), 80 | 'baz' => V::string()->valid('quux'), 81 | 'array' => V::arr()->keys([ 82 | 'foo' => V::string()->valid('bar'), 83 | 'baz' => V::string()->valid('quux1') 84 | ]) 85 | ]); 86 | 87 | V::validate($input, $schema, function ($err, $output) { 88 | $message = 'key "array" is invalid, because ' 89 | . '[ key "baz" is invalid, because ' 90 | . '[ value "quux" is not allowed ] ]'; 91 | $this->assertEquals($message, $err); 92 | $this->assertNull($output); 93 | }); 94 | } 95 | 96 | public function testArrayNotEmpty() 97 | { 98 | V::validate([1, 2, 3], V::arr()->notEmpty(), function ($err, $output) { 99 | $this->assertNull($err); 100 | $this->assertEquals([1, 2, 3], $output); 101 | }); 102 | 103 | V::validate([], V::arr()->notEmpty(), function ($err, $output) { 104 | $this->assertEquals('value is an empty array', $err); 105 | $this->assertNull($output); 106 | }); 107 | } 108 | 109 | public function testArrayLength() 110 | { 111 | V::validate([1, 2, 3], V::arr()->length(3), function ($err, $output) { 112 | $this->assertNull($err); 113 | $this->assertEquals([1, 2, 3], $output); 114 | }); 115 | 116 | V::validate([1, 2, 3], V::arr()->length(4), function ($err, $output) { 117 | $this->assertEquals('array length is 3, while length of 4 was expected', $err); 118 | $this->assertNull($output); 119 | }); 120 | } 121 | 122 | public function testArrayMin() 123 | { 124 | V::validate([1, 2, 3], V::arr()->min(3), function ($err, $output) { 125 | $this->assertNull($err); 126 | $this->assertEquals([1, 2, 3], $output); 127 | }); 128 | 129 | V::validate([1, 2, 3, 4], V::arr()->min(3), function ($err, $output) { 130 | $this->assertNull($err); 131 | $this->assertEquals([1, 2, 3, 4], $output); 132 | }); 133 | 134 | V::validate([1, 2, 3], V::arr()->min(4), function ($err, $output) { 135 | $this->assertEquals('array needs to have at least 4 items', $err); 136 | $this->assertNull($output); 137 | }); 138 | } 139 | 140 | public function testArrayMax() 141 | { 142 | V::validate([1, 2, 3], V::arr()->max(3), function ($err, $output) { 143 | $this->assertNull($err); 144 | $this->assertEquals([1, 2, 3], $output); 145 | }); 146 | 147 | V::validate([1, 2, 3], V::arr()->max(4), function ($err, $output) { 148 | $this->assertNull($err); 149 | $this->assertEquals([1, 2, 3], $output); 150 | }); 151 | 152 | V::validate([1, 2, 3], V::arr()->max(2), function ($err, $output) { 153 | $this->assertEquals('array needs to have at most 2 items', $err); 154 | $this->assertNull($output); 155 | }); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /tests/DateSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 14 | $this->assertEquals('2015-01-01', $output); 15 | }); 16 | 17 | V::validate('2004-02-12T15:19:21+00:00', V::date(), function ($err, $output) { 18 | $this->assertNull($err); 19 | $this->assertEquals('2004-02-12T15:19:21+00:00', $output); 20 | }); 21 | 22 | $dateTime = new \DateTime(); 23 | V::validate($dateTime, V::date(), function ($err, $output) use ($dateTime) { 24 | $this->assertNull($err); 25 | $this->assertEquals($dateTime, $output); 26 | }); 27 | 28 | V::validate('123', V::date(), function ($err, $output) { 29 | $this->assertEquals('value is not a date', $err); 30 | $this->assertNull($output); 31 | }); 32 | 33 | V::validate([], V::date(), function ($err, $output) { 34 | $this->assertEquals('value is not a date', $err); 35 | $this->assertNull($output); 36 | }); 37 | 38 | V::validate(new \stdClass(), V::date(), function ($err, $output) { 39 | $this->assertEquals('value is not a date', $err); 40 | $this->assertNull($output); 41 | }); 42 | } 43 | 44 | public function testDateConvertToObject() 45 | { 46 | V::validate('2015-01-01', V::date()->dateTimeObject(), function ($err, $output) { 47 | $this->assertNull($err); 48 | $this->assertInstanceOf('\DateTime', $output); 49 | 50 | /** @var \DateTime $output */ 51 | $this->assertEquals('2015-01-01', $output->format('Y-m-d')); 52 | }); 53 | 54 | $dateTime = new \DateTime(); 55 | 56 | V::validate($dateTime, V::date()->dateTimeObject(), function ($err, $output) use ($dateTime) { 57 | $this->assertNull($err); 58 | $this->assertInstanceOf('\DateTime', $output); 59 | 60 | /** @var \DateTime $output */ 61 | $this->assertEquals($dateTime->format('Y-m-d'), $output->format('Y-m-d')); 62 | }); 63 | } 64 | 65 | public function testDateConvertToObjectWithoutConversion() 66 | { 67 | $dateTime = new \DateTime(); 68 | 69 | V::validate($dateTime, V::date()->dateTimeObject(false), function ($err, $output) use ($dateTime) { 70 | $this->assertNull($err); 71 | $this->assertInstanceOf('\DateTime', $output); 72 | 73 | /** @var \DateTime $output */ 74 | $this->assertEquals($dateTime->format('Y-m-d'), $output->format('Y-m-d')); 75 | }); 76 | 77 | V::validate('2015-01-01', V::date()->dateTimeObject(false), function ($err, $output) { 78 | $this->assertEquals('value is not a DateTime object', $err); 79 | $this->assertNull($output); 80 | }); 81 | } 82 | 83 | public function testAfter() 84 | { 85 | V::validate('2015-06-01', V::date()->after('2015-05-30'), function ($err, $output) { 86 | $this->assertNotNull($output); 87 | $this->assertNull($err); 88 | }); 89 | 90 | V::validate('2015-06-01 06:00:01', V::date()->after('2015-06-01 06:00:00'), function ($err, $output) { 91 | $this->assertNotNull($output); 92 | $this->assertNull($err); 93 | }); 94 | 95 | V::validate('2015-06-01 06:00:00', V::date()->after('2015-06-01 06:00:00'), function ($err, $output) { 96 | $this->assertNull($output); 97 | /** @var ValidationException $err */ 98 | $this->assertContains('Date should be after', $err->getMessage()); 99 | }); 100 | } 101 | 102 | public function testBefore() 103 | { 104 | V::validate('2015-05-30', V::date()->before('2015-06-01'), function ($err, $output) { 105 | $this->assertNotNull($output); 106 | $this->assertNull($err); 107 | }); 108 | 109 | V::validate('2015-06-01 06:00:00', V::date()->before('2015-06-01 06:00:01'), function ($err, $output) { 110 | $this->assertNotNull($output); 111 | $this->assertNull($err); 112 | }); 113 | 114 | V::validate('2015-06-01 06:00:00', V::date()->before('2015-06-01 06:00:00'), function ($err, $output) { 115 | $this->assertNull($output); 116 | /** @var ValidationException $err */ 117 | $this->assertContains('Date should be before', $err->getMessage()); 118 | }); 119 | } 120 | 121 | public function testBetween() 122 | { 123 | V::validate('2015-05-30', V::date()->between('2015-05-01', '2015-06-01'), function ($err, $output) { 124 | $this->assertNotNull($output); 125 | $this->assertNull($err); 126 | }); 127 | 128 | V::validate('2015-06-01 06:00:00', V::date()->between('2015-06-01 05:59:59', '2015-06-01 06:00:01'), function ($err, $output) { 129 | $this->assertNotNull($output); 130 | $this->assertNull($err); 131 | }); 132 | 133 | V::validate('2015-06-01 06:00:00', V::date()->between('2015-06-01 06:00:00', '2015-06-01 07:00:00'), function ($err, $output) { 134 | $this->assertNotNull($output); 135 | $this->assertNull($err); 136 | }); 137 | 138 | V::validate('2015-06-01 05:00:00', V::date()->between('2015-06-01 06:00:00', '2015-06-01 07:00:00'), function ($err, $output) { 139 | $this->assertNull($output); 140 | /** @var ValidationException $err */ 141 | $this->assertContains('Date should be between', $err->getMessage()); 142 | }); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /tests/NumberSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 13 | $this->assertEquals(123, $output); 14 | }); 15 | 16 | V::validate(1.23, V::number(), function ($err, $output) { 17 | $this->assertNull($err); 18 | $this->assertEquals(1.23, $output); 19 | }); 20 | 21 | V::validate('123', V::number(), function ($err, $output) { 22 | $this->assertEquals('value is not a number', $err); 23 | $this->assertNull($output); 24 | }); 25 | 26 | V::validate('1.23', V::number(), function ($err, $output) { 27 | $this->assertEquals('value is not a number', $err); 28 | $this->assertNull($output); 29 | }); 30 | 31 | V::validate(null, V::number(), function ($err, $output) { 32 | $this->assertEquals('value is not a number', $err); 33 | $this->assertNull($output); 34 | }); 35 | 36 | V::validate(false, V::number(), function ($err, $output) { 37 | $this->assertEquals('value is not a number', $err); 38 | $this->assertNull($output); 39 | }); 40 | 41 | V::validate([], V::number(), function ($err, $output) { 42 | $this->assertEquals('value is not a number', $err); 43 | $this->assertNull($output); 44 | }); 45 | 46 | V::validate(new \stdClass(), V::number(), function ($err, $output) { 47 | $this->assertEquals('value is not a number', $err); 48 | $this->assertNull($output); 49 | }); 50 | } 51 | 52 | public function testNumberInteger() 53 | { 54 | V::validate(123, V::number()->integer(), function ($err, $output) { 55 | $this->assertNull($err); 56 | $this->assertEquals(123, $output); 57 | }); 58 | 59 | V::validate(1.23, V::number()->integer(), function ($err, $output) { 60 | $this->assertEquals('value is not an integer', $err); 61 | $this->assertNull($output); 62 | }); 63 | } 64 | 65 | public function testNumberFloat() 66 | { 67 | V::validate(1.23, V::number()->float(), function ($err, $output) { 68 | $this->assertNull($err); 69 | $this->assertEquals(1.23, $output); 70 | }); 71 | 72 | V::validate(123, V::number()->float(), function ($err, $output) { 73 | $this->assertEquals('value is not a float', $err); 74 | $this->assertNull($output); 75 | }); 76 | } 77 | 78 | public function testNumberMin() 79 | { 80 | V::validate(10, V::number()->min(5), function ($err, $output) { 81 | $this->assertNull($err); 82 | $this->assertEquals(10, $output); 83 | }); 84 | 85 | V::validate(5, V::number()->min(5), function ($err, $output) { 86 | $this->assertNull($err); 87 | $this->assertEquals(5, $output); 88 | }); 89 | 90 | V::validate(4, V::number()->min(5), function ($err, $output) { 91 | $this->assertEquals('value must be >= 5', $err); 92 | $this->assertNull($output); 93 | }); 94 | 95 | V::validate(0, V::number()->min(5), function ($err, $output) { 96 | $this->assertEquals('value must be >= 5', $err); 97 | $this->assertNull($output); 98 | }); 99 | 100 | V::validate(-5, V::number()->min(5), function ($err, $output) { 101 | $this->assertEquals('value must be >= 5', $err); 102 | $this->assertNull($output); 103 | }); 104 | } 105 | 106 | public function testNumberMax() 107 | { 108 | V::validate(-5, V::number()->max(5), function ($err, $output) { 109 | $this->assertNull($err); 110 | $this->assertEquals(-5, $output); 111 | }); 112 | 113 | V::validate(0, V::number()->max(5), function ($err, $output) { 114 | $this->assertNull($err); 115 | $this->assertEquals(0, $output); 116 | }); 117 | 118 | V::validate(5, V::number()->max(5), function ($err, $output) { 119 | $this->assertNull($err); 120 | $this->assertEquals(5, $output); 121 | }); 122 | 123 | V::validate(6, V::number()->max(5), function ($err, $output) { 124 | $this->assertEquals('value must be <= 5', $err); 125 | $this->assertNull($output); 126 | }); 127 | 128 | V::validate(10, V::number()->max(5), function ($err, $output) { 129 | $this->assertEquals('value must be <= 5', $err); 130 | $this->assertNull($output); 131 | }); 132 | } 133 | 134 | public function testNumberBetween() 135 | { 136 | V::validate(0, V::number()->between(5, 10), function ($err, $output) { 137 | $this->assertEquals('value must be >= 5', $err); 138 | $this->assertNull($output); 139 | }); 140 | 141 | V::validate(4, V::number()->between(5, 10), function ($err, $output) { 142 | $this->assertEquals('value must be >= 5', $err); 143 | $this->assertNull($output); 144 | }); 145 | 146 | V::validate(5, V::number()->between(5, 10), function ($err, $output) { 147 | $this->assertNull($err); 148 | $this->assertEquals(5, $output); 149 | }); 150 | 151 | V::validate(7, V::number()->between(5, 10), function ($err, $output) { 152 | $this->assertNull($err); 153 | $this->assertEquals(7, $output); 154 | }); 155 | 156 | V::validate(10, V::number()->between(5, 10), function ($err, $output) { 157 | $this->assertNull($err); 158 | $this->assertEquals(10, $output); 159 | }); 160 | 161 | V::validate(11, V::number()->between(5, 10), function ($err, $output) { 162 | $this->assertEquals('value must be <= 10', $err); 163 | $this->assertNull($output); 164 | }); 165 | 166 | V::validate(100, V::number()->between(5, 10), function ($err, $output) { 167 | $this->assertEquals('value must be <= 10', $err); 168 | $this->assertNull($output); 169 | }); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /tests/AnySchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 16 | $this->assertEquals('foo', $output); 17 | }); 18 | 19 | V::validate(123, V::any(), function ($err, $output) { 20 | $this->assertNull($err); 21 | $this->assertEquals(123, $output); 22 | }); 23 | 24 | V::validate(null, V::any(), function ($err, $output) { 25 | $this->assertNull($err); 26 | $this->assertEquals(null, $output); 27 | }); 28 | 29 | V::validate(true, V::any(), function ($err, $output) { 30 | $this->assertNull($err); 31 | $this->assertEquals(true, $output); 32 | }); 33 | 34 | V::validate([], V::any(), function ($err, $output) { 35 | $this->assertNull($err); 36 | $this->assertEquals([], $output); 37 | }); 38 | } 39 | 40 | public function testAnyValid() 41 | { 42 | V::validate('string', V::any()->valid('string', 'foobar'), function ($err, $output) { 43 | $this->assertNull($err); 44 | $this->assertEquals('string', $output); 45 | }); 46 | 47 | V::validate('quux', V::any()->valid('string', 'foobar'), function ($err, $output) { 48 | $this->assertEquals('value "quux" is not allowed', $err); 49 | $this->assertNull($output); 50 | }); 51 | } 52 | 53 | public function testAnyInvalid() 54 | { 55 | V::validate('quux', V::any()->invalid('string', 'foobar'), function ($err, $output) { 56 | $this->assertNull($err); 57 | $this->assertEquals('quux', $output); 58 | }); 59 | 60 | V::validate('string', V::any()->invalid('string', 'foobar'), function ($err, $output) { 61 | $this->assertEquals('value "string" is disallowed', $err); 62 | $this->assertNull($output); 63 | }); 64 | } 65 | 66 | public function testAnyRequired() 67 | { 68 | V::validate('quux', V::any()->required(), function ($err, $output) { 69 | $this->assertNull($err); 70 | $this->assertEquals('quux', $output); 71 | }); 72 | 73 | V::validate(0, V::any()->required(), function ($err, $output) { 74 | $this->assertNull($err); 75 | $this->assertEquals(0, $output); 76 | }); 77 | 78 | V::validate(false, V::any()->required(), function ($err, $output) { 79 | $this->assertNull($err); 80 | $this->assertEquals(false, $output); 81 | }); 82 | 83 | V::validate('', V::any()->required(), function ($err, $output) { 84 | $this->assertEquals('value is required', $err); 85 | $this->assertNull($output); 86 | }); 87 | 88 | V::validate(null, V::any()->required(), function ($err, $output) { 89 | $this->assertEquals('value is required', $err); 90 | $this->assertNull($output); 91 | }); 92 | } 93 | 94 | public function testAnyStrip() 95 | { 96 | $input = ['foo' => 'bar', 'baz' => 'quux']; 97 | 98 | $schema = V::arr()->keys([ 99 | 'foo' => V::string(), 100 | 'baz' => V::string()->strip() 101 | ]); 102 | 103 | V::validate($input, $schema, function ($err, $output) { 104 | $this->assertNull($err); 105 | $this->assertEquals(['foo' => 'bar'], $output); 106 | }); 107 | } 108 | 109 | public function testAnyDefault() 110 | { 111 | $input = ['firstname' => 'Smok', 'lastname' => 'Wawelski']; 112 | 113 | $schema = V::arr()->keys([ 114 | 'username' => V::string()->defaultValue(function ($context) { 115 | return strtolower($context['firstname']) . '-' . strtolower($context['lastname']); 116 | }), 117 | 'firstname' => V::string(), 118 | 'lastname' => V::string(), 119 | 'created' => V::date()->defaultValue(new \DateTime()), 120 | 'status' => V::string()->defaultValue('registered') 121 | ]); 122 | 123 | $user = V::attempt($input, $schema); 124 | 125 | $this->assertEquals('smok-wawelski', $user['username']); 126 | $this->assertEquals('Smok', $user['firstname']); 127 | $this->assertEquals('Wawelski', $user['lastname']); 128 | $this->assertEquals((new \DateTime())->format('Y-m-d'), $user['created']->format('Y-m-d')); 129 | $this->assertEquals('registered', $user['status']); 130 | } 131 | 132 | public function testAnyDefaultPreset() 133 | { 134 | $input = [ 135 | 'firstname' => 'Smok', 136 | 'lastname' => 'Wawelski', 137 | 'username' => 'foobar', 138 | 'created' => '2015-01-01', 139 | 'status' => 'foo' 140 | ]; 141 | 142 | $schema = V::arr()->keys([ 143 | 'username' => V::string()->defaultValue(function ($context) { 144 | return strtolower($context['firstname']) . '-' . strtolower($context['lastname']); 145 | }), 146 | 'firstname' => V::string(), 147 | 'lastname' => V::string(), 148 | 'created' => V::date()->dateTimeObject()->defaultValue(new \DateTime()), 149 | 'status' => V::string()->defaultValue('registered') 150 | ]); 151 | 152 | $user = V::attempt($input, $schema); 153 | 154 | $this->assertEquals('foobar', $user['username']); 155 | $this->assertEquals('Smok', $user['firstname']); 156 | $this->assertEquals('Wawelski', $user['lastname']); 157 | $this->assertEquals('2015-01-01 00:00:00', $user['created']->format('Y-m-d H:i:s')); 158 | $this->assertEquals('foo', $user['status']); 159 | } 160 | 161 | public function testAnyCustom() 162 | { 163 | $schema = V::string()->custom(function (InputValue $input) { 164 | if ($input->getValue() !== 'string') { 165 | throw new ValidationException('custom error message'); 166 | } 167 | }); 168 | 169 | V::validate('string', $schema, function ($err, $output) { 170 | $this->assertNull($err); 171 | $this->assertEquals('string', $output); 172 | }); 173 | 174 | $schema = V::string()->custom(function (InputValue $input) { 175 | if ($input->getValue() === 'string') { 176 | throw new ValidationException('custom error message'); 177 | } 178 | }); 179 | 180 | V::validate('string', $schema, function ($err, $output) { 181 | $this->assertEquals('custom error message', $err); 182 | $this->assertNull($output); 183 | }); 184 | } 185 | 186 | public function testAnyCustomTransform() 187 | { 188 | $schema = V::number()->custom(function (InputValue $input) { 189 | $input->replace(function ($value) { 190 | return $value * 2; 191 | }); 192 | }); 193 | 194 | V::validate(2, $schema, function ($err, $output) { 195 | $this->assertNull($err); 196 | $this->assertEquals(4, $output); 197 | }); 198 | 199 | V::validate(2.5, $schema, function ($err, $output) { 200 | $this->assertNull($err); 201 | $this->assertEquals(5, $output); 202 | }); 203 | } 204 | 205 | public function testAnyCustomClassMethodPositive() 206 | { 207 | $obj = new TestAnyCustomClassMethod(); 208 | 209 | V::validate('string', V::any()->custom([$obj, 'toUpper']), function ($err, $output) { 210 | $this->assertNull($err); 211 | $this->assertEquals('STRING', $output); 212 | }); 213 | } 214 | 215 | public function testAnyCustomClassMethodNegative() 216 | { 217 | $obj = new TestAnyCustomClassMethod(); 218 | 219 | V::validate('string', V::any()->custom([$obj, 'throwException']), function ($err, $output) { 220 | $this->assertEquals('A custom validation message', $err); 221 | $this->assertNull($output); 222 | }); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | ## Table of contents 2 | 3 | - [Example](#example) 4 | - [Usage](#usage) 5 | - [`validate($value, $schema[, $callback])`](#validatevalue-schema-callback) 6 | - [`assert($value, $schema)`](#assertvalue-schema) 7 | - [`attempt($value, $schema)`](#attemptvalue-schema) 8 | - [`any()`](#any) 9 | - [`any::custom($callable)`](#anycustomcallable) 10 | - [`any::defaultValue($value)`](#anydefaultvaluevalue) 11 | - [`any::invalid($value)`](#anyinvalidvalue) 12 | - [`any::required()`](#anyrequired) 13 | - [`any::strip()`](#anystrip) 14 | - [`any::valid($value)`](#anyvalidvalue) 15 | - [`arr()`](#arr) 16 | - [`arr::keys([$keys])`](#arrkeyskeys) 17 | - [`arr::length($length)`](#arrlengthlength) 18 | - [`arr::max($length)`](#arrmaxlength) 19 | - [`arr::min($length)`](#arrminlength) 20 | - [`arr::notEmpty()`](#arrnotempty) 21 | - [`boolean()`](#array) 22 | - [`boolean::false()`](#booleanfalse) 23 | - [`boolean::true()`](#booleantrue) 24 | - [`closure()`](#closure) 25 | - [`date()`](#date) 26 | - [`date::after($time)`](#dateaftertime) 27 | - [`date::before($time)`](#datebeforetime) 28 | - [`date::between($time1, $time2)`](#datebetweentime1-time2) 29 | - [`date::dateTimeObject($convert)`](#datedatetimeobjectconvert) 30 | - [`number()`](#number) 31 | - [`number::integer()`](#numberinteger) 32 | - [`number::float()`](#numberfloat) 33 | - [`number::min(number)`](#numberminnumber) 34 | - [`number::max(number)`](#numbermaxnumber) 35 | - [`number::between(min, max)`](#numberbetweenmin-max) 36 | - [`object()`](#object) 37 | - [`object::instance($className)`](#objectinstanceclassname) 38 | - [`resource()`](#resource) 39 | - [`string()`](#string) 40 | - [`string::alphanum()`](#stringalphanum) 41 | - [`string::email()`](#stringemail) 42 | - [`string::ip($options)`](#stringipoptions) 43 | - [`string::length($length)`](#stringlengthlength) 44 | - [`string::lowercase($convert)`](#stringlowercaseconvert) 45 | - [`string::max($length)`](#stringmaxlength) 46 | - [`string::min($length)`](#stringminlength) 47 | - [`string::regex($pattern)`](#stringregexpattern) 48 | - [`string::regexReplace($pattern, $replace)`](#stringregexreplacepattern-replace) 49 | - [`string::replace($search, $replace)`](#stringreplacesearch-replace) 50 | - [`string::token()`](#stringtoken) 51 | - [`string::trim($convert)`](#stringurloptions) 52 | - [`string::uppercase($convert)`](#stringuppercaseconvert) 53 | - [`string::url($options)`](#stringurloptions) 54 | - [`string::notEmpty()`](#stringnotempty) 55 | - [`alternative()`](#alternative) 56 | - [`string::any($schemas)`](#alternativeanyschemas) 57 | 58 | # Example 59 | 60 | ```php 61 | 'foobar', 67 | 'password' => 'secret123', 68 | 'birthyear' => 1980, 69 | 'email' => 'foobar@example.com', 70 | 'sex' => 'male' 71 | ]; 72 | 73 | $schema = V::arr()->keys([ 74 | 'username' => V::string()->alphanum()->min(3)->max(30), 75 | 'password' => V::string()->regex('/[a-z-A-Z0-9]{3,30}/'), 76 | 'birthyear' => V::number()->integer()->min(1900)->max(2013), 77 | 'email' => V::string()->email(), 78 | 'sex' => V::string()->valid('male', 'female') 79 | ]); 80 | 81 | V::validate($input, $schema, function ($err, $output) { 82 | // $err === null -> valid! 83 | }); 84 | ``` 85 | 86 | The code snippet illustrates how to check an input array against a set of constraints: 87 | * `username` 88 | * must be a string 89 | * must contain only alphanumeric characters 90 | * the length must be between 3 and 30 alphanumeric characters 91 | * `password` 92 | * must be a string 93 | * must satisfy the custom regex 94 | * `birthyear` 95 | * an integer between 1900 and 2013 96 | * `email` 97 | * a valid email address string 98 | * `sex` 99 | * "male" or "female" string, any other values are disallowed 100 | 101 | Once validation process has completed, the callback is invoked. If there was a failure, `$err` argument contains 102 | `ValidationException` object and `$output` argument is `null`. Otherwise `$err` argument is `null` and 103 | `$output` argument contains validated/filtered input value. 104 | 105 | # Usage 106 | 107 | ### `validate($value, $schema[, $callback])` 108 | 109 | Validates the given `$value` against `$schema` and, if `$callback` attribute is specified, invokes 110 | the callback with attributes `$err` and `$output` as described above. If `$callback` is not specified, the method 111 | returns an array with two keys: `err` and `output`. 112 | 113 | Examples with callback: 114 | 115 | ```php 116 | V::validate('string', V::string(), function ($err, $output) { 117 | // $err is null 118 | // $output is 'string' 119 | }); 120 | ``` 121 | 122 | ```php 123 | V::validate('string', V::number(), function ($err, $output) { 124 | // $err contains the ValidationException object 125 | // $output is null 126 | }); 127 | ``` 128 | 129 | Examples without callback: 130 | 131 | ```php 132 | $result = V::validate('string', V::string()); 133 | 134 | // $result['err'] is null 135 | // $result['output'] is 'string' 136 | ``` 137 | 138 | ```php 139 | $result = V::validate('string', V::number()); 140 | 141 | // $result['err'] contains the ValidationException object 142 | // $result['output'] is null 143 | ``` 144 | 145 | ### `assert($value, $schema)` 146 | 147 | Validates given `$value` against `$schema` and throws `ValidationException` if validation fails. 148 | This method does not return any value. 149 | 150 | ```php 151 | V::assert('string', V::string()); // No exception 152 | V::assert('string', V::number()); // ValidationException is thrown 153 | ``` 154 | 155 | ### `attempt($value, $schema)` 156 | 157 | Validates given `$value` against `$schema` and throws `ValidationException` if validation fails. 158 | Otherwise it returns validated/filtered value. 159 | 160 | ### `any()` 161 | 162 | Does not check the input value for any specific type and gives access to the shared assertions like `valid` 163 | or `invalid`. 164 | 165 | ```php 166 | V::attempt('string', V::any()); // 'string' 167 | V::attempt(123, V::any()); // 123 168 | V::attempt(null, V::any()); // null 169 | ``` 170 | 171 | #### `any::custom($callable)` 172 | 173 | Applies a custom validation implemented as a callback or any other callable expression. The callable need to accept 174 | one parameter, which is an `InputValue` object. To raise a validation error, callable needs to throw 175 | `ValidationException`. If exception is not thrown, library assumes the input value is valid. 176 | 177 | ```php 178 | V::attempt('string', V::any()->custom(function (InputValue $input) { 179 | if ($input->getValue() !== 'string') { 180 | throw new ValidationException('A custom validation message'); 181 | } 182 | })); // Success - the result is 'string' 183 | 184 | V::attempt('string', V::any()->custom(function (InputValue $input) { 185 | if ($input->getValue() === 'string') { 186 | throw new ValidationException('A custom validation message'); 187 | } 188 | })); // ValidationException with message 'A custom validation message' is thrown 189 | ``` 190 | 191 | Custom callable also supports transformations. 192 | 193 | ```php 194 | V::attempt('string', V::string()->custom(function (InputValue $input) { 195 | $input->replace(function ($value) { 196 | return md5($value); 197 | }); 198 | // above is the same as: $input->setValue(md5($input->getValue())); 199 | })); // Result is 'b45cffe084dd3d20d928bee85e7b0f21' 200 | ``` 201 | 202 | #### `any::defaultValue($value)` 203 | 204 | Sets a default value if the relevant array key is missing. `$value` attribute might be a callback. 205 | 206 | Example: 207 | 208 | ```php 209 | $input = [ 'firstname' => 'Smok', 'lastname' => 'Wawelski' ]; 210 | 211 | $schema = V::arr()->keys([ 212 | 'firstname' => V::string(), 213 | 'lastname' => V::string(), 214 | 'username' => V::string()->defaultValue(function ($context) { 215 | return strtolower($context['firstname'] . '-' . $context['lastname']); 216 | }), 217 | 'created' => V::date()->defaultValue(new \DateTime), 218 | 'status' => V::string()->defaultValue('registered') 219 | ]); 220 | 221 | $user = V::attempt($input, $schema); 222 | 223 | // $user['firstname'] - 'Smok' 224 | // $user['lastname'] - 'Wawelski' 225 | // $user['username'] - 'smok-wawelski' 226 | // $user['created'] - instance of \DateTime 227 | // $user['status'] - registered 228 | ``` 229 | 230 | #### `any::invalid($value)` 231 | 232 | This shared assertion checks if the input value is none of the passed values. 233 | 234 | ```php 235 | V::attempt('a', V::any()->invalid('a')); // ValidationException! 236 | V::attempt('a', V::any()->invalid('a', 'b')); // ValidationException! 237 | V::attempt('a', V::any()->invalid(['a', 'b'])); // ValidationException! 238 | V::attempt('a', V::any()->invalid('c', 'd')); // 'a' 239 | ``` 240 | 241 | #### `any::required()` 242 | 243 | Checks if value is not `null` or an empty string. 244 | 245 | ```php 246 | V::attempt(null, V::any->required()); // ValidationException! 247 | V::attempt('', V::any->required()); // ValidationException! 248 | V::attempt('foo', V::any->required()); // 'foo' 249 | ``` 250 | 251 | #### `any::strip()` 252 | 253 | Removes the given array ket from the `$output` value. 254 | 255 | ```php 256 | $input = [ 'foo' => 'bar', 'baz' => 'quux' ]; 257 | 258 | $schema = V::arr()->keys([ 259 | 'foo' => V::string(), 260 | 'baz' => V::string()->strip() 261 | ]); 262 | 263 | V::attempt($input, $schema); // -> [ 'foo' => 'bar' ] 264 | ``` 265 | 266 | #### `any::valid($value)` 267 | 268 | This shared assertion checks if the input value is one of the passed values. 269 | 270 | ```php 271 | V::attempt('a', V::any()->valid('a')); // 'a' 272 | V::attempt('a', V::any()->valid('a', 'b')); // 'a' 273 | V::attempt('a', V::any()->valid(['a', 'b'])); // 'a' 274 | V::attempt('a', V::any()->valid('c', 'd')); // ValidationException! 275 | ``` 276 | 277 | ### `arr()` 278 | 279 | Checks if the input value is an array. Gives access to any array-specific assertions and filters. 280 | 281 | ```php 282 | V::attempt([], V::arr()); // [] 283 | V::attempt(123, V::arr()); // ValidationException! 284 | ``` 285 | 286 | #### `arr::keys($length)` 287 | 288 | Checks if the input array has a set of specified keys. Each key can be checked against some rule. 289 | 290 | ```php 291 | $valid = ['name' => 'John', 'surname' => 'Doe', 'email' => 'jd@example.com', 'sex' => 'male']; 292 | $invalid = []; 293 | 294 | V::attempt($valid, $schema); // Outputs the validated array 295 | V::attempt($invalid, $schema); // ValidationException with detailed message which key caused the error 296 | ``` 297 | 298 | #### `arr::length($length)` 299 | 300 | *To be documented.* 301 | 302 | #### `arr::max($length)` 303 | 304 | *To be documented.* 305 | 306 | #### `arr::min($length)` 307 | 308 | *To be documented.* 309 | 310 | #### `arr::notEmpty($length)` 311 | 312 | *To be documented.* 313 | 314 | 315 | ### `boolean()` 316 | 317 | Checks if the input value is a boolean. Gives access to any boolean-specific assertions and filters. 318 | 319 | #### `boolean::false()` 320 | 321 | *To be documented.* 322 | 323 | #### `boolean::true()` 324 | 325 | *To be documented.* 326 | 327 | 328 | ### `closure()` 329 | 330 | Checks if the input value is a closure or any other callable expression. 331 | 332 | ### `date()` 333 | 334 | Checks if the input value is a valid date string or `DateTime` object. Gives access to any date-specific assertions and filters. 335 | 336 | #### `date::after($time)` 337 | 338 | Checks if the input value is after a specific date/time. 339 | 340 | ```php 341 | V::attempt('2015-07-01', V::date()->after('2015-01-01')); // '2015-07-01' 342 | V::attempt('2015-07-01 12:40:00', V::date()->after('2015-07-01 12:30:00')); // '2015-07-01 12:40:00' 343 | V::attempt('2015-07-01 12:40:00', V::date()->after('2015-07-01 13:00:00')); // ValidationException! 344 | ``` 345 | 346 | #### `date::before($time)` 347 | 348 | Checks if the input value is after a specific date/time. 349 | 350 | ```php 351 | V::attempt('2015-07-01', V::date()->before('2015-10-01')); // '2015-07-01' 352 | V::attempt('2015-07-01 12:40:00', V::date()->before('2015-07-01 13:00:00')); // '2015-07-01 12:40:00' 353 | V::attempt('2015-07-01 12:40:00', V::date()->before('2015-07-01 12:00:00')); // ValidationException! 354 | ``` 355 | 356 | #### `date::between($time1, $time2)` 357 | 358 | Checks if the input value is between two dates/times. 359 | 360 | ```php 361 | V::attempt('2015-07-01', V::date()->between('2015-01-01', '2015-10-01')); // '2015-07-01' 362 | V::attempt('2015-07-01 12:40:00', V::date()->between('2015-07-01 12:00:00', '2015-07-01 13:00:00')); // '2015-07-01 12:40:00' 363 | V::attempt('2015-07-01 12:40:00', V::date()->between('2015-07-01 10:00:00', '2015-07-01 11:00:00')); // ValidationException! 364 | ``` 365 | 366 | #### `date::dateTimeObject($convert)` 367 | 368 | If `$convert` parameter is `true` (default), it converts the input value to `DateTime` object, otherwise it checks if the input value is a `DateTime` object. 369 | 370 | ```php 371 | V::attempt('2015-07-01', V::date()->dateTimeObject()); // DateTime object 372 | V::attempt(new \DateTime('2015-07-01'), V::date()->dateTimeObject(false)); // DateTime object 373 | V::attempt('2015-07-01', V::date()->dateTimeObject(false)); // ValidationException! 374 | ``` 375 | 376 | ### `number()` 377 | 378 | Checks if the input value is a number. Gives access to any number-specific assertions and filters. 379 | 380 | #### `number::integer()` 381 | 382 | *To be documented.* 383 | 384 | #### `number::float()` 385 | 386 | *To be documented.* 387 | 388 | #### `number::min(number)` 389 | 390 | *To be documented.* 391 | 392 | #### `number::max(number)` 393 | 394 | *To be documented.* 395 | 396 | #### `number::between(min, max)` 397 | 398 | *To be documented.* 399 | 400 | 401 | ### `object()` 402 | 403 | Checks if the input value is an object. Gives access to any object-specific assertions and filters. 404 | 405 | #### `object::instance($className)` 406 | 407 | *To be documented.* 408 | 409 | 410 | ### `resource()` 411 | 412 | Checks if the input value is a resource. Gives access to any resource-specific assertions and filters. 413 | 414 | ### `string()` 415 | 416 | Checks if the input value is a string. Gives access to any string-specific assertions and filters. 417 | 418 | #### `string::alphanum()` 419 | 420 | *To be documented.* 421 | 422 | #### `string::email()` 423 | 424 | *To be documented.* 425 | 426 | #### `string::ip($options)` 427 | 428 | *To be documented.* 429 | 430 | #### `string::length($length)` 431 | 432 | *To be documented.* 433 | 434 | #### `string::lowercase($convert)` 435 | 436 | *To be documented.* 437 | 438 | #### `string::max($length)` 439 | 440 | *To be documented.* 441 | 442 | #### `string::min($length)` 443 | 444 | *To be documented.* 445 | 446 | #### `string::regex($pattern)` 447 | 448 | *To be documented.* 449 | 450 | #### `string::regexReplace($pattern, $replace)` 451 | 452 | *To be documented.* 453 | 454 | #### `string::replace($search, $replace)` 455 | 456 | *To be documented.* 457 | 458 | #### `string::token()` 459 | 460 | *To be documented.* 461 | 462 | #### `string::uppercase($convert)` 463 | 464 | *To be documented.* 465 | 466 | #### `string::trim($convert)` 467 | 468 | *To be documented.* 469 | 470 | #### `string::url($options)` 471 | 472 | *To be documented.* 473 | 474 | #### `string::notEmpty()` 475 | 476 | *To be documented.* 477 | 478 | 479 | ### `alternative()` 480 | 481 | Enables alternative schema. Details below. 482 | 483 | #### `alternative::any($schemas)` 484 | 485 | *To be documented.* 486 | -------------------------------------------------------------------------------- /tests/StringSchemaTest.php: -------------------------------------------------------------------------------- 1 | assertNull($err); 13 | $this->assertEquals('string', $output); 14 | }); 15 | 16 | V::validate(123, V::string(), function ($err, $output) { 17 | $this->assertEquals('value is not a string', $err); 18 | $this->assertNull($output); 19 | }); 20 | 21 | V::validate([], V::string(), function ($err, $output) { 22 | $this->assertEquals('value is not a string', $err); 23 | $this->assertNull($output); 24 | }); 25 | } 26 | 27 | public function testStringMin() 28 | { 29 | V::validate('foo', V::string()->min(1), function ($err, $output) { 30 | $this->assertNull($err); 31 | $this->assertEquals('foo', $output); 32 | }); 33 | 34 | V::validate('foo', V::string()->min(8), function ($err, $output) { 35 | $this->assertEquals('value length < 8', $err); 36 | $this->assertNull($output); 37 | }); 38 | } 39 | 40 | public function testStringMax() 41 | { 42 | V::validate('foo', V::string()->max(10), function ($err, $output) { 43 | $this->assertNull($err); 44 | $this->assertEquals('foo', $output); 45 | }); 46 | 47 | V::validate('foo', V::string()->max(1), function ($err, $output) { 48 | $this->assertEquals('value length > 1', $err); 49 | $this->assertNull($output); 50 | }); 51 | } 52 | 53 | public function testStringValid() 54 | { 55 | V::validate('foo', V::string()->valid('foo'), function ($err, $output) { 56 | $this->assertNull($err); 57 | $this->assertEquals('foo', $output); 58 | }); 59 | 60 | V::validate('foo', V::string()->valid('foo', 'bar'), function ($err, $output) { 61 | $this->assertNull($err); 62 | $this->assertEquals('foo', $output); 63 | }); 64 | 65 | V::validate('foo', V::string()->valid(['foo', 'bar']), function ($err, $output) { 66 | $this->assertNull($err); 67 | $this->assertEquals('foo', $output); 68 | }); 69 | 70 | V::validate('foo', V::string()->valid('bar'), function ($err, $output) { 71 | $this->assertEquals('value "foo" is not allowed', $err); 72 | $this->assertNull($output); 73 | }); 74 | } 75 | 76 | public function testStringInvalid() 77 | { 78 | V::validate('bar', V::string()->invalid('foo'), function ($err, $output) { 79 | $this->assertNull($err); 80 | $this->assertEquals('bar', $output); 81 | }); 82 | 83 | V::validate('bar', V::string()->invalid('foo', 'bar'), function ($err, $output) { 84 | $this->assertEquals('value "bar" is disallowed', $err); 85 | $this->assertNull($output); 86 | }); 87 | 88 | V::validate('bar', V::string()->invalid(['foo', 'bar']), function ($err, $output) { 89 | $this->assertEquals('value "bar" is disallowed', $err); 90 | $this->assertNull($output); 91 | }); 92 | 93 | V::validate('bar', V::string()->invalid('bar'), function ($err, $output) { 94 | $this->assertEquals('value "bar" is disallowed', $err); 95 | $this->assertNull($output); 96 | }); 97 | } 98 | 99 | public function testStringLength() 100 | { 101 | V::validate('bar', V::string()->length(3), function ($err, $output) { 102 | $this->assertNull($err); 103 | $this->assertEquals('bar', $output); 104 | }); 105 | 106 | V::validate('bar', V::string()->length(5), function ($err, $output) { 107 | $this->assertEquals('value length is 3, expected 5', $err); 108 | $this->assertNull($output); 109 | }); 110 | } 111 | 112 | public function testStringRegex() 113 | { 114 | V::validate('test-123456', V::string()->regex('/test\-[0-9]+/'), function ($err, $output) { 115 | $this->assertNull($err); 116 | $this->assertEquals('test-123456', $output); 117 | }); 118 | 119 | V::validate('test-abcdef', V::string()->regex('/test\-[0-9]+/'), function ($err, $output) { 120 | $this->assertEquals('value does not match pattern /test\-[0-9]+/', $err); 121 | $this->assertNull($output); 122 | }); 123 | } 124 | 125 | public function testStringAlphanum() 126 | { 127 | V::validate('ABCdef123', V::string()->alphanum(), function ($err, $output) { 128 | $this->assertNull($err); 129 | $this->assertEquals('ABCdef123', $output); 130 | }); 131 | 132 | V::validate('ABCdef!', V::string()->alphanum(), function ($err, $output) { 133 | $this->assertEquals('value contains not alphanumeric chars', $err); 134 | $this->assertNull($output); 135 | }); 136 | } 137 | 138 | public function testStringToken() 139 | { 140 | V::validate('ABCdef123', V::string()->token(), function ($err, $output) { 141 | $this->assertNull($err); 142 | $this->assertEquals('ABCdef123', $output); 143 | }); 144 | 145 | V::validate('ABC_def_123', V::string()->token(), function ($err, $output) { 146 | $this->assertNull($err); 147 | $this->assertEquals('ABC_def_123', $output); 148 | }); 149 | 150 | V::validate('ABCdef!', V::string()->token(), function ($err, $output) { 151 | $this->assertEquals('value is not a token', $err); 152 | $this->assertNull($output); 153 | }); 154 | } 155 | 156 | public function testStringLowercase() 157 | { 158 | V::validate('abcdef', V::string()->lowercase(), function ($err, $output) { 159 | $this->assertNull($err); 160 | $this->assertEquals('abcdef', $output); 161 | }); 162 | 163 | V::validate('AbCdEf', V::string()->lowercase(), function ($err, $output) { 164 | $this->assertNull($err); 165 | $this->assertEquals('abcdef', $output); 166 | }); 167 | 168 | V::validate('ABCDEF', V::string()->lowercase(), function ($err, $output) { 169 | $this->assertNull($err); 170 | $this->assertEquals('abcdef', $output); 171 | }); 172 | } 173 | 174 | public function testStringLowercaseWithoutConversion() 175 | { 176 | V::validate('abcdef', V::string()->lowercase(false), function ($err, $output) { 177 | $this->assertNull($err); 178 | $this->assertEquals('abcdef', $output); 179 | }); 180 | 181 | V::validate('AbCdEf', V::string()->lowercase(false), function ($err, $output) { 182 | $this->assertEquals('value must be lowercase', $err); 183 | $this->assertNull($output); 184 | }); 185 | 186 | V::validate('ABCDEF', V::string()->lowercase(false), function ($err, $output) { 187 | $this->assertEquals('value must be lowercase', $err); 188 | $this->assertNull($output); 189 | }); 190 | } 191 | 192 | public function testStringUppercase() 193 | { 194 | V::validate('ABCDEF', V::string()->uppercase(), function ($err, $output) { 195 | $this->assertNull($err); 196 | $this->assertEquals('ABCDEF', $output); 197 | }); 198 | 199 | V::validate('AbCdEf', V::string()->uppercase(), function ($err, $output) { 200 | $this->assertNull($err); 201 | $this->assertEquals('ABCDEF', $output); 202 | }); 203 | 204 | V::validate('abcdef', V::string()->uppercase(), function ($err, $output) { 205 | $this->assertNull($err); 206 | $this->assertEquals('ABCDEF', $output); 207 | }); 208 | } 209 | 210 | public function testStringUppercaseWithoutConversion() 211 | { 212 | V::validate('ABCDEF', V::string()->uppercase(false), function ($err, $output) { 213 | $this->assertNull($err); 214 | $this->assertEquals('ABCDEF', $output); 215 | }); 216 | 217 | V::validate('AbCdEf', V::string()->uppercase(false), function ($err, $output) { 218 | $this->assertEquals('value must be uppercase', $err); 219 | $this->assertNull($output); 220 | }); 221 | 222 | V::validate('abcdef', V::string()->uppercase(false), function ($err, $output) { 223 | $this->assertEquals('value must be uppercase', $err); 224 | $this->assertNull($output); 225 | }); 226 | } 227 | 228 | public function testStringReplace() 229 | { 230 | V::validate('foobar', V::string()->replace('bar', 'baz'), function ($err, $output) { 231 | $this->assertNull($err); 232 | $this->assertEquals('foobaz', $output); 233 | }); 234 | 235 | V::validate('foobar', V::string()->replace(['foo', 'bar'], ['baz', 'quux']), function ($err, $output) { 236 | $this->assertNull($err); 237 | $this->assertEquals('bazquux', $output); 238 | }); 239 | 240 | V::validate('foobar', V::string()->replace(['foo', 'bar'], 'baz'), function ($err, $output) { 241 | $this->assertNull($err); 242 | $this->assertEquals('bazbaz', $output); 243 | }); 244 | } 245 | 246 | public function testStringEmail() 247 | { 248 | V::validate('foo@example.com', V::string()->email(), function ($err, $output) { 249 | $this->assertNull($err); 250 | $this->assertEquals('foo@example.com', $output); 251 | }); 252 | 253 | V::validate('@example.com', V::string()->email(), function ($err, $output) { 254 | $this->assertEquals('"@example.com" is not a valid email', $err); 255 | $this->assertNull($output); 256 | }); 257 | 258 | V::validate('example.com', V::string()->email(), function ($err, $output) { 259 | $this->assertEquals('"example.com" is not a valid email', $err); 260 | $this->assertNull($output); 261 | }); 262 | } 263 | 264 | public function testStringRegexReplace() 265 | { 266 | V::validate('foobar', V::string()->regexReplace('/...$/', 'baz'), function ($err, $output) { 267 | $this->assertNull($err); 268 | $this->assertEquals('foobaz', $output); 269 | }); 270 | } 271 | 272 | public function testStringIp() 273 | { 274 | V::validate('127.0.0.1', V::string()->ip(), function ($err, $output) { 275 | $this->assertNull($err); 276 | $this->assertEquals('127.0.0.1', $output); 277 | }); 278 | 279 | V::validate('::1', V::string()->ip(), function ($err, $output) { 280 | $this->assertNull($err); 281 | $this->assertEquals('::1', $output); 282 | }); 283 | 284 | V::validate('127.0.0.1', V::string()->ip(FILTER_FLAG_IPV6), function ($err, $output) { 285 | $this->assertEquals('"127.0.0.1" is not a valid IP address', $err); 286 | $this->assertNull($output); 287 | }); 288 | 289 | V::validate('::1', V::string()->ip(FILTER_FLAG_IPV4), function ($err, $output) { 290 | $this->assertEquals('"::1" is not a valid IP address', $err); 291 | $this->assertNull($output); 292 | }); 293 | 294 | V::validate('127.00.1', V::string()->ip(), function ($err, $output) { 295 | $this->assertEquals('"127.00.1" is not a valid IP address', $err); 296 | $this->assertNull($output); 297 | }); 298 | 299 | V::validate(':1', V::string()->ip(), function ($err, $output) { 300 | $this->assertEquals('":1" is not a valid IP address', $err); 301 | $this->assertNull($output); 302 | }); 303 | } 304 | 305 | public function testStringUriSimple() 306 | { 307 | V::validate('http://localhost/', V::string()->uri(), function ($err, $output) { 308 | $this->assertNull($err); 309 | $this->assertEquals('http://localhost/', $output); 310 | }); 311 | } 312 | 313 | public function testStringUriWithPath() 314 | { 315 | V::validate('http://localhost/dir/test.html', V::string()->uri(), function ($err, $output) { 316 | $this->assertNull($err); 317 | $this->assertEquals('http://localhost/dir/test.html', $output); 318 | }); 319 | } 320 | 321 | public function testStringUriPathRequired() 322 | { 323 | $schema = V::string()->uri(FILTER_FLAG_PATH_REQUIRED); 324 | 325 | V::validate('http://localhost/dir/test.html', $schema, function ($err, $output) { 326 | $this->assertNull($err); 327 | $this->assertEquals('http://localhost/dir/test.html', $output); 328 | }); 329 | } 330 | 331 | public function testStringUriWithQs() 332 | { 333 | $schema = V::string()->uri(); 334 | 335 | V::validate('http://localhost/dir/test.html?foo=bar', $schema, function ($err, $output) { 336 | $this->assertNull($err); 337 | $this->assertEquals('http://localhost/dir/test.html?foo=bar', $output); 338 | }); 339 | } 340 | 341 | public function testStringUriQsRequired() 342 | { 343 | $schema = V::string()->uri(FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED); 344 | 345 | V::validate('http://localhost/dir/test.html?foo=bar', $schema, function ($err, $output) { 346 | $this->assertNull($err); 347 | $this->assertEquals('http://localhost/dir/test.html?foo=bar', $output); 348 | }); 349 | } 350 | 351 | public function testStringUriPathRequiredNoPath() 352 | { 353 | $schema = V::string()->uri(FILTER_FLAG_PATH_REQUIRED); 354 | 355 | V::validate('http://localhost', $schema, function ($err, $output) { 356 | $this->assertEquals('"http://localhost" is not a valid URI', $err); 357 | $this->assertNull($output); 358 | }); 359 | } 360 | 361 | public function testStringUriQsRequiredNoQs() 362 | { 363 | $schema = V::string()->uri(FILTER_FLAG_QUERY_REQUIRED); 364 | 365 | V::validate('http://localhost/', $schema, function ($err, $output) { 366 | $this->assertEquals('"http://localhost/" is not a valid URI', $err); 367 | $this->assertNull($output); 368 | }); 369 | } 370 | 371 | public function testStringUriQsRequiredWithPath() 372 | { 373 | $schema = V::string()->uri(FILTER_FLAG_QUERY_REQUIRED); 374 | V::validate('http://localhost/dir/test.html', $schema, function ($err, $output) { 375 | $this->assertEquals('"http://localhost/dir/test.html" is not a valid URI', $err); 376 | $this->assertNull($output); 377 | }); 378 | } 379 | 380 | public function testStringUriPlainString() 381 | { 382 | V::validate('foobar', V::string()->uri(), function ($err, $output) { 383 | $this->assertEquals('"foobar" is not a valid URI', $err); 384 | $this->assertNull($output); 385 | }); 386 | } 387 | 388 | public function testStringTrim() 389 | { 390 | V::validate('foo', V::string()->trim(), function ($err, $output) { 391 | $this->assertNull($err); 392 | $this->assertEquals('foo', $output); 393 | }); 394 | 395 | V::validate(' foo', V::string()->trim(), function ($err, $output) { 396 | $this->assertNull($err); 397 | $this->assertEquals('foo', $output); 398 | }); 399 | 400 | V::validate('foo ', V::string()->trim(), function ($err, $output) { 401 | $this->assertNull($err); 402 | $this->assertEquals('foo', $output); 403 | }); 404 | 405 | V::validate(' foo ', V::string()->trim(), function ($err, $output) { 406 | $this->assertNull($err); 407 | $this->assertEquals('foo', $output); 408 | }); 409 | } 410 | 411 | public function testStringTrimWithoutConversion() 412 | { 413 | V::validate('foo', V::string()->trim(false), function ($err, $output) { 414 | $this->assertNull($err); 415 | $this->assertEquals('foo', $output); 416 | }); 417 | 418 | V::validate(' foo', V::string()->trim(false), function ($err, $output) { 419 | $this->assertEquals('value is not trimmed', $err); 420 | $this->assertNull($output); 421 | }); 422 | 423 | V::validate('foo ', V::string()->trim(false), function ($err, $output) { 424 | $this->assertEquals('value is not trimmed', $err); 425 | $this->assertNull($output); 426 | }); 427 | 428 | V::validate(' foo ', V::string()->trim(false), function ($err, $output) { 429 | $this->assertEquals('value is not trimmed', $err); 430 | $this->assertNull($output); 431 | }); 432 | } 433 | 434 | public function testStringTrimInvalidOption() 435 | { 436 | $this->setExpectedException( 437 | 'InvalidArgumentException', 438 | 'key "convert" is invalid, because [ value is not a boolean ]' 439 | ); 440 | 441 | V::assert('foo', V::string()->trim('foo')); 442 | } 443 | 444 | public function testStringNotEmpty() 445 | { 446 | V::validate('foo', V::string()->notEmpty(), function ($err, $output) { 447 | $this->assertNull($err); 448 | $this->assertEquals('foo', $output); 449 | }); 450 | 451 | V::validate('', V::string()->notEmpty(), function ($err, $output) { 452 | $this->assertEquals('value length < 1', $err); 453 | $this->assertNull($output); 454 | }); 455 | } 456 | } 457 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "c9ddc5d0d8ed5b3e7249fef6f942f57d", 8 | "content-hash": "8fee6919d7651423e3682fa49b205616", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "1.0.5", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 22 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "~2.0" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2015-06-14 21:17:01" 64 | }, 65 | { 66 | "name": "guzzle/guzzle", 67 | "version": "v3.9.3", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/guzzle/guzzle3.git", 71 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", 76 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "ext-curl": "*", 81 | "php": ">=5.3.3", 82 | "symfony/event-dispatcher": "~2.1" 83 | }, 84 | "replace": { 85 | "guzzle/batch": "self.version", 86 | "guzzle/cache": "self.version", 87 | "guzzle/common": "self.version", 88 | "guzzle/http": "self.version", 89 | "guzzle/inflection": "self.version", 90 | "guzzle/iterator": "self.version", 91 | "guzzle/log": "self.version", 92 | "guzzle/parser": "self.version", 93 | "guzzle/plugin": "self.version", 94 | "guzzle/plugin-async": "self.version", 95 | "guzzle/plugin-backoff": "self.version", 96 | "guzzle/plugin-cache": "self.version", 97 | "guzzle/plugin-cookie": "self.version", 98 | "guzzle/plugin-curlauth": "self.version", 99 | "guzzle/plugin-error-response": "self.version", 100 | "guzzle/plugin-history": "self.version", 101 | "guzzle/plugin-log": "self.version", 102 | "guzzle/plugin-md5": "self.version", 103 | "guzzle/plugin-mock": "self.version", 104 | "guzzle/plugin-oauth": "self.version", 105 | "guzzle/service": "self.version", 106 | "guzzle/stream": "self.version" 107 | }, 108 | "require-dev": { 109 | "doctrine/cache": "~1.3", 110 | "monolog/monolog": "~1.0", 111 | "phpunit/phpunit": "3.7.*", 112 | "psr/log": "~1.0", 113 | "symfony/class-loader": "~2.1", 114 | "zendframework/zend-cache": "2.*,<2.3", 115 | "zendframework/zend-log": "2.*,<2.3" 116 | }, 117 | "suggest": { 118 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." 119 | }, 120 | "type": "library", 121 | "extra": { 122 | "branch-alias": { 123 | "dev-master": "3.9-dev" 124 | } 125 | }, 126 | "autoload": { 127 | "psr-0": { 128 | "Guzzle": "src/", 129 | "Guzzle\\Tests": "tests/" 130 | } 131 | }, 132 | "notification-url": "https://packagist.org/downloads/", 133 | "license": [ 134 | "MIT" 135 | ], 136 | "authors": [ 137 | { 138 | "name": "Michael Dowling", 139 | "email": "mtdowling@gmail.com", 140 | "homepage": "https://github.com/mtdowling" 141 | }, 142 | { 143 | "name": "Guzzle Community", 144 | "homepage": "https://github.com/guzzle/guzzle/contributors" 145 | } 146 | ], 147 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", 148 | "homepage": "http://guzzlephp.org/", 149 | "keywords": [ 150 | "client", 151 | "curl", 152 | "framework", 153 | "http", 154 | "http client", 155 | "rest", 156 | "web service" 157 | ], 158 | "time": "2015-03-18 18:23:50" 159 | }, 160 | { 161 | "name": "myclabs/deep-copy", 162 | "version": "1.5.1", 163 | "source": { 164 | "type": "git", 165 | "url": "https://github.com/myclabs/DeepCopy.git", 166 | "reference": "a8773992b362b58498eed24bf85005f363c34771" 167 | }, 168 | "dist": { 169 | "type": "zip", 170 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a8773992b362b58498eed24bf85005f363c34771", 171 | "reference": "a8773992b362b58498eed24bf85005f363c34771", 172 | "shasum": "" 173 | }, 174 | "require": { 175 | "php": ">=5.4.0" 176 | }, 177 | "require-dev": { 178 | "doctrine/collections": "1.*", 179 | "phpunit/phpunit": "~4.1" 180 | }, 181 | "type": "library", 182 | "autoload": { 183 | "psr-4": { 184 | "DeepCopy\\": "src/DeepCopy/" 185 | } 186 | }, 187 | "notification-url": "https://packagist.org/downloads/", 188 | "license": [ 189 | "MIT" 190 | ], 191 | "description": "Create deep copies (clones) of your objects", 192 | "homepage": "https://github.com/myclabs/DeepCopy", 193 | "keywords": [ 194 | "clone", 195 | "copy", 196 | "duplicate", 197 | "object", 198 | "object graph" 199 | ], 200 | "time": "2015-11-20 12:04:31" 201 | }, 202 | { 203 | "name": "phpdocumentor/reflection-common", 204 | "version": "1.0", 205 | "source": { 206 | "type": "git", 207 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 208 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 209 | }, 210 | "dist": { 211 | "type": "zip", 212 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 213 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 214 | "shasum": "" 215 | }, 216 | "require": { 217 | "php": ">=5.5" 218 | }, 219 | "require-dev": { 220 | "phpunit/phpunit": "^4.6" 221 | }, 222 | "type": "library", 223 | "extra": { 224 | "branch-alias": { 225 | "dev-master": "1.0.x-dev" 226 | } 227 | }, 228 | "autoload": { 229 | "psr-4": { 230 | "phpDocumentor\\Reflection\\": [ 231 | "src" 232 | ] 233 | } 234 | }, 235 | "notification-url": "https://packagist.org/downloads/", 236 | "license": [ 237 | "MIT" 238 | ], 239 | "authors": [ 240 | { 241 | "name": "Jaap van Otterdijk", 242 | "email": "opensource@ijaap.nl" 243 | } 244 | ], 245 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 246 | "homepage": "http://www.phpdoc.org", 247 | "keywords": [ 248 | "FQSEN", 249 | "phpDocumentor", 250 | "phpdoc", 251 | "reflection", 252 | "static analysis" 253 | ], 254 | "time": "2015-12-27 11:43:31" 255 | }, 256 | { 257 | "name": "phpdocumentor/reflection-docblock", 258 | "version": "3.1.0", 259 | "source": { 260 | "type": "git", 261 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 262 | "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" 263 | }, 264 | "dist": { 265 | "type": "zip", 266 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", 267 | "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", 268 | "shasum": "" 269 | }, 270 | "require": { 271 | "php": ">=5.5", 272 | "phpdocumentor/reflection-common": "^1.0@dev", 273 | "phpdocumentor/type-resolver": "^0.2.0", 274 | "webmozart/assert": "^1.0" 275 | }, 276 | "require-dev": { 277 | "mockery/mockery": "^0.9.4", 278 | "phpunit/phpunit": "^4.4" 279 | }, 280 | "type": "library", 281 | "autoload": { 282 | "psr-4": { 283 | "phpDocumentor\\Reflection\\": [ 284 | "src/" 285 | ] 286 | } 287 | }, 288 | "notification-url": "https://packagist.org/downloads/", 289 | "license": [ 290 | "MIT" 291 | ], 292 | "authors": [ 293 | { 294 | "name": "Mike van Riel", 295 | "email": "me@mikevanriel.com" 296 | } 297 | ], 298 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 299 | "time": "2016-06-10 09:48:41" 300 | }, 301 | { 302 | "name": "phpdocumentor/type-resolver", 303 | "version": "0.2", 304 | "source": { 305 | "type": "git", 306 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 307 | "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" 308 | }, 309 | "dist": { 310 | "type": "zip", 311 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", 312 | "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", 313 | "shasum": "" 314 | }, 315 | "require": { 316 | "php": ">=5.5", 317 | "phpdocumentor/reflection-common": "^1.0" 318 | }, 319 | "require-dev": { 320 | "mockery/mockery": "^0.9.4", 321 | "phpunit/phpunit": "^5.2||^4.8.24" 322 | }, 323 | "type": "library", 324 | "extra": { 325 | "branch-alias": { 326 | "dev-master": "1.0.x-dev" 327 | } 328 | }, 329 | "autoload": { 330 | "psr-4": { 331 | "phpDocumentor\\Reflection\\": [ 332 | "src/" 333 | ] 334 | } 335 | }, 336 | "notification-url": "https://packagist.org/downloads/", 337 | "license": [ 338 | "MIT" 339 | ], 340 | "authors": [ 341 | { 342 | "name": "Mike van Riel", 343 | "email": "me@mikevanriel.com" 344 | } 345 | ], 346 | "time": "2016-06-10 07:14:17" 347 | }, 348 | { 349 | "name": "phpspec/prophecy", 350 | "version": "v1.6.1", 351 | "source": { 352 | "type": "git", 353 | "url": "https://github.com/phpspec/prophecy.git", 354 | "reference": "58a8137754bc24b25740d4281399a4a3596058e0" 355 | }, 356 | "dist": { 357 | "type": "zip", 358 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", 359 | "reference": "58a8137754bc24b25740d4281399a4a3596058e0", 360 | "shasum": "" 361 | }, 362 | "require": { 363 | "doctrine/instantiator": "^1.0.2", 364 | "php": "^5.3|^7.0", 365 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 366 | "sebastian/comparator": "^1.1", 367 | "sebastian/recursion-context": "^1.0" 368 | }, 369 | "require-dev": { 370 | "phpspec/phpspec": "^2.0" 371 | }, 372 | "type": "library", 373 | "extra": { 374 | "branch-alias": { 375 | "dev-master": "1.6.x-dev" 376 | } 377 | }, 378 | "autoload": { 379 | "psr-0": { 380 | "Prophecy\\": "src/" 381 | } 382 | }, 383 | "notification-url": "https://packagist.org/downloads/", 384 | "license": [ 385 | "MIT" 386 | ], 387 | "authors": [ 388 | { 389 | "name": "Konstantin Kudryashov", 390 | "email": "ever.zet@gmail.com", 391 | "homepage": "http://everzet.com" 392 | }, 393 | { 394 | "name": "Marcello Duarte", 395 | "email": "marcello.duarte@gmail.com" 396 | } 397 | ], 398 | "description": "Highly opinionated mocking framework for PHP 5.3+", 399 | "homepage": "https://github.com/phpspec/prophecy", 400 | "keywords": [ 401 | "Double", 402 | "Dummy", 403 | "fake", 404 | "mock", 405 | "spy", 406 | "stub" 407 | ], 408 | "time": "2016-06-07 08:13:47" 409 | }, 410 | { 411 | "name": "phpunit/php-code-coverage", 412 | "version": "4.0.0", 413 | "source": { 414 | "type": "git", 415 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 416 | "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9" 417 | }, 418 | "dist": { 419 | "type": "zip", 420 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/900370c81280cc0d942ffbc5912d80464eaee7e9", 421 | "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9", 422 | "shasum": "" 423 | }, 424 | "require": { 425 | "php": "^5.6 || ^7.0", 426 | "phpunit/php-file-iterator": "~1.3", 427 | "phpunit/php-text-template": "~1.2", 428 | "phpunit/php-token-stream": "^1.4.2", 429 | "sebastian/code-unit-reverse-lookup": "~1.0", 430 | "sebastian/environment": "^1.3.2", 431 | "sebastian/version": "~1.0|~2.0" 432 | }, 433 | "require-dev": { 434 | "ext-xdebug": ">=2.1.4", 435 | "phpunit/phpunit": "^5.4" 436 | }, 437 | "suggest": { 438 | "ext-dom": "*", 439 | "ext-xdebug": ">=2.4.0", 440 | "ext-xmlwriter": "*" 441 | }, 442 | "type": "library", 443 | "extra": { 444 | "branch-alias": { 445 | "dev-master": "4.0.x-dev" 446 | } 447 | }, 448 | "autoload": { 449 | "classmap": [ 450 | "src/" 451 | ] 452 | }, 453 | "notification-url": "https://packagist.org/downloads/", 454 | "license": [ 455 | "BSD-3-Clause" 456 | ], 457 | "authors": [ 458 | { 459 | "name": "Sebastian Bergmann", 460 | "email": "sb@sebastian-bergmann.de", 461 | "role": "lead" 462 | } 463 | ], 464 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 465 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 466 | "keywords": [ 467 | "coverage", 468 | "testing", 469 | "xunit" 470 | ], 471 | "time": "2016-06-03 05:03:56" 472 | }, 473 | { 474 | "name": "phpunit/php-file-iterator", 475 | "version": "1.4.1", 476 | "source": { 477 | "type": "git", 478 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 479 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 480 | }, 481 | "dist": { 482 | "type": "zip", 483 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 484 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 485 | "shasum": "" 486 | }, 487 | "require": { 488 | "php": ">=5.3.3" 489 | }, 490 | "type": "library", 491 | "extra": { 492 | "branch-alias": { 493 | "dev-master": "1.4.x-dev" 494 | } 495 | }, 496 | "autoload": { 497 | "classmap": [ 498 | "src/" 499 | ] 500 | }, 501 | "notification-url": "https://packagist.org/downloads/", 502 | "license": [ 503 | "BSD-3-Clause" 504 | ], 505 | "authors": [ 506 | { 507 | "name": "Sebastian Bergmann", 508 | "email": "sb@sebastian-bergmann.de", 509 | "role": "lead" 510 | } 511 | ], 512 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 513 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 514 | "keywords": [ 515 | "filesystem", 516 | "iterator" 517 | ], 518 | "time": "2015-06-21 13:08:43" 519 | }, 520 | { 521 | "name": "phpunit/php-text-template", 522 | "version": "1.2.1", 523 | "source": { 524 | "type": "git", 525 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 526 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 527 | }, 528 | "dist": { 529 | "type": "zip", 530 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 531 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 532 | "shasum": "" 533 | }, 534 | "require": { 535 | "php": ">=5.3.3" 536 | }, 537 | "type": "library", 538 | "autoload": { 539 | "classmap": [ 540 | "src/" 541 | ] 542 | }, 543 | "notification-url": "https://packagist.org/downloads/", 544 | "license": [ 545 | "BSD-3-Clause" 546 | ], 547 | "authors": [ 548 | { 549 | "name": "Sebastian Bergmann", 550 | "email": "sebastian@phpunit.de", 551 | "role": "lead" 552 | } 553 | ], 554 | "description": "Simple template engine.", 555 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 556 | "keywords": [ 557 | "template" 558 | ], 559 | "time": "2015-06-21 13:50:34" 560 | }, 561 | { 562 | "name": "phpunit/php-timer", 563 | "version": "1.0.8", 564 | "source": { 565 | "type": "git", 566 | "url": "https://github.com/sebastianbergmann/php-timer.git", 567 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" 568 | }, 569 | "dist": { 570 | "type": "zip", 571 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", 572 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", 573 | "shasum": "" 574 | }, 575 | "require": { 576 | "php": ">=5.3.3" 577 | }, 578 | "require-dev": { 579 | "phpunit/phpunit": "~4|~5" 580 | }, 581 | "type": "library", 582 | "autoload": { 583 | "classmap": [ 584 | "src/" 585 | ] 586 | }, 587 | "notification-url": "https://packagist.org/downloads/", 588 | "license": [ 589 | "BSD-3-Clause" 590 | ], 591 | "authors": [ 592 | { 593 | "name": "Sebastian Bergmann", 594 | "email": "sb@sebastian-bergmann.de", 595 | "role": "lead" 596 | } 597 | ], 598 | "description": "Utility class for timing", 599 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 600 | "keywords": [ 601 | "timer" 602 | ], 603 | "time": "2016-05-12 18:03:57" 604 | }, 605 | { 606 | "name": "phpunit/php-token-stream", 607 | "version": "1.4.8", 608 | "source": { 609 | "type": "git", 610 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 611 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" 612 | }, 613 | "dist": { 614 | "type": "zip", 615 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 616 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 617 | "shasum": "" 618 | }, 619 | "require": { 620 | "ext-tokenizer": "*", 621 | "php": ">=5.3.3" 622 | }, 623 | "require-dev": { 624 | "phpunit/phpunit": "~4.2" 625 | }, 626 | "type": "library", 627 | "extra": { 628 | "branch-alias": { 629 | "dev-master": "1.4-dev" 630 | } 631 | }, 632 | "autoload": { 633 | "classmap": [ 634 | "src/" 635 | ] 636 | }, 637 | "notification-url": "https://packagist.org/downloads/", 638 | "license": [ 639 | "BSD-3-Clause" 640 | ], 641 | "authors": [ 642 | { 643 | "name": "Sebastian Bergmann", 644 | "email": "sebastian@phpunit.de" 645 | } 646 | ], 647 | "description": "Wrapper around PHP's tokenizer extension.", 648 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 649 | "keywords": [ 650 | "tokenizer" 651 | ], 652 | "time": "2015-09-15 10:49:45" 653 | }, 654 | { 655 | "name": "phpunit/phpunit", 656 | "version": "5.4.6", 657 | "source": { 658 | "type": "git", 659 | "url": "https://github.com/sebastianbergmann/phpunit.git", 660 | "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59" 661 | }, 662 | "dist": { 663 | "type": "zip", 664 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", 665 | "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", 666 | "shasum": "" 667 | }, 668 | "require": { 669 | "ext-dom": "*", 670 | "ext-json": "*", 671 | "ext-pcre": "*", 672 | "ext-reflection": "*", 673 | "ext-spl": "*", 674 | "myclabs/deep-copy": "~1.3", 675 | "php": "^5.6 || ^7.0", 676 | "phpspec/prophecy": "^1.3.1", 677 | "phpunit/php-code-coverage": "^4.0", 678 | "phpunit/php-file-iterator": "~1.4", 679 | "phpunit/php-text-template": "~1.2", 680 | "phpunit/php-timer": "^1.0.6", 681 | "phpunit/phpunit-mock-objects": "^3.2", 682 | "sebastian/comparator": "~1.1", 683 | "sebastian/diff": "~1.2", 684 | "sebastian/environment": "^1.3 || ^2.0", 685 | "sebastian/exporter": "~1.2", 686 | "sebastian/global-state": "~1.0", 687 | "sebastian/object-enumerator": "~1.0", 688 | "sebastian/resource-operations": "~1.0", 689 | "sebastian/version": "~1.0|~2.0", 690 | "symfony/yaml": "~2.1|~3.0" 691 | }, 692 | "conflict": { 693 | "phpdocumentor/reflection-docblock": "3.0.2" 694 | }, 695 | "suggest": { 696 | "phpunit/php-invoker": "~1.1" 697 | }, 698 | "bin": [ 699 | "phpunit" 700 | ], 701 | "type": "library", 702 | "extra": { 703 | "branch-alias": { 704 | "dev-master": "5.4.x-dev" 705 | } 706 | }, 707 | "autoload": { 708 | "classmap": [ 709 | "src/" 710 | ] 711 | }, 712 | "notification-url": "https://packagist.org/downloads/", 713 | "license": [ 714 | "BSD-3-Clause" 715 | ], 716 | "authors": [ 717 | { 718 | "name": "Sebastian Bergmann", 719 | "email": "sebastian@phpunit.de", 720 | "role": "lead" 721 | } 722 | ], 723 | "description": "The PHP Unit Testing framework.", 724 | "homepage": "https://phpunit.de/", 725 | "keywords": [ 726 | "phpunit", 727 | "testing", 728 | "xunit" 729 | ], 730 | "time": "2016-06-16 06:01:15" 731 | }, 732 | { 733 | "name": "phpunit/phpunit-mock-objects", 734 | "version": "3.2.3", 735 | "source": { 736 | "type": "git", 737 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 738 | "reference": "b13d0d9426ced06958bd32104653526a6c998a52" 739 | }, 740 | "dist": { 741 | "type": "zip", 742 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/b13d0d9426ced06958bd32104653526a6c998a52", 743 | "reference": "b13d0d9426ced06958bd32104653526a6c998a52", 744 | "shasum": "" 745 | }, 746 | "require": { 747 | "doctrine/instantiator": "^1.0.2", 748 | "php": "^5.6 || ^7.0", 749 | "phpunit/php-text-template": "^1.2", 750 | "sebastian/exporter": "^1.2" 751 | }, 752 | "conflict": { 753 | "phpunit/phpunit": "<5.4.0" 754 | }, 755 | "require-dev": { 756 | "phpunit/phpunit": "^5.4" 757 | }, 758 | "suggest": { 759 | "ext-soap": "*" 760 | }, 761 | "type": "library", 762 | "extra": { 763 | "branch-alias": { 764 | "dev-master": "3.2.x-dev" 765 | } 766 | }, 767 | "autoload": { 768 | "classmap": [ 769 | "src/" 770 | ] 771 | }, 772 | "notification-url": "https://packagist.org/downloads/", 773 | "license": [ 774 | "BSD-3-Clause" 775 | ], 776 | "authors": [ 777 | { 778 | "name": "Sebastian Bergmann", 779 | "email": "sb@sebastian-bergmann.de", 780 | "role": "lead" 781 | } 782 | ], 783 | "description": "Mock Object library for PHPUnit", 784 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 785 | "keywords": [ 786 | "mock", 787 | "xunit" 788 | ], 789 | "time": "2016-06-12 07:37:26" 790 | }, 791 | { 792 | "name": "psr/log", 793 | "version": "1.0.0", 794 | "source": { 795 | "type": "git", 796 | "url": "https://github.com/php-fig/log.git", 797 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" 798 | }, 799 | "dist": { 800 | "type": "zip", 801 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", 802 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", 803 | "shasum": "" 804 | }, 805 | "type": "library", 806 | "autoload": { 807 | "psr-0": { 808 | "Psr\\Log\\": "" 809 | } 810 | }, 811 | "notification-url": "https://packagist.org/downloads/", 812 | "license": [ 813 | "MIT" 814 | ], 815 | "authors": [ 816 | { 817 | "name": "PHP-FIG", 818 | "homepage": "http://www.php-fig.org/" 819 | } 820 | ], 821 | "description": "Common interface for logging libraries", 822 | "keywords": [ 823 | "log", 824 | "psr", 825 | "psr-3" 826 | ], 827 | "time": "2012-12-21 11:40:51" 828 | }, 829 | { 830 | "name": "satooshi/php-coveralls", 831 | "version": "v1.0.1", 832 | "source": { 833 | "type": "git", 834 | "url": "https://github.com/satooshi/php-coveralls.git", 835 | "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" 836 | }, 837 | "dist": { 838 | "type": "zip", 839 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c", 840 | "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c", 841 | "shasum": "" 842 | }, 843 | "require": { 844 | "ext-json": "*", 845 | "ext-simplexml": "*", 846 | "guzzle/guzzle": "^2.8|^3.0", 847 | "php": ">=5.3.3", 848 | "psr/log": "^1.0", 849 | "symfony/config": "^2.1|^3.0", 850 | "symfony/console": "^2.1|^3.0", 851 | "symfony/stopwatch": "^2.0|^3.0", 852 | "symfony/yaml": "^2.0|^3.0" 853 | }, 854 | "suggest": { 855 | "symfony/http-kernel": "Allows Symfony integration" 856 | }, 857 | "bin": [ 858 | "bin/coveralls" 859 | ], 860 | "type": "library", 861 | "autoload": { 862 | "psr-4": { 863 | "Satooshi\\": "src/Satooshi/" 864 | } 865 | }, 866 | "notification-url": "https://packagist.org/downloads/", 867 | "license": [ 868 | "MIT" 869 | ], 870 | "authors": [ 871 | { 872 | "name": "Kitamura Satoshi", 873 | "email": "with.no.parachute@gmail.com", 874 | "homepage": "https://www.facebook.com/satooshi.jp" 875 | } 876 | ], 877 | "description": "PHP client library for Coveralls API", 878 | "homepage": "https://github.com/satooshi/php-coveralls", 879 | "keywords": [ 880 | "ci", 881 | "coverage", 882 | "github", 883 | "test" 884 | ], 885 | "time": "2016-01-20 17:35:46" 886 | }, 887 | { 888 | "name": "sebastian/code-unit-reverse-lookup", 889 | "version": "1.0.0", 890 | "source": { 891 | "type": "git", 892 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 893 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" 894 | }, 895 | "dist": { 896 | "type": "zip", 897 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 898 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 899 | "shasum": "" 900 | }, 901 | "require": { 902 | "php": ">=5.6" 903 | }, 904 | "require-dev": { 905 | "phpunit/phpunit": "~5" 906 | }, 907 | "type": "library", 908 | "extra": { 909 | "branch-alias": { 910 | "dev-master": "1.0.x-dev" 911 | } 912 | }, 913 | "autoload": { 914 | "classmap": [ 915 | "src/" 916 | ] 917 | }, 918 | "notification-url": "https://packagist.org/downloads/", 919 | "license": [ 920 | "BSD-3-Clause" 921 | ], 922 | "authors": [ 923 | { 924 | "name": "Sebastian Bergmann", 925 | "email": "sebastian@phpunit.de" 926 | } 927 | ], 928 | "description": "Looks up which function or method a line of code belongs to", 929 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 930 | "time": "2016-02-13 06:45:14" 931 | }, 932 | { 933 | "name": "sebastian/comparator", 934 | "version": "1.2.0", 935 | "source": { 936 | "type": "git", 937 | "url": "https://github.com/sebastianbergmann/comparator.git", 938 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 939 | }, 940 | "dist": { 941 | "type": "zip", 942 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 943 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 944 | "shasum": "" 945 | }, 946 | "require": { 947 | "php": ">=5.3.3", 948 | "sebastian/diff": "~1.2", 949 | "sebastian/exporter": "~1.2" 950 | }, 951 | "require-dev": { 952 | "phpunit/phpunit": "~4.4" 953 | }, 954 | "type": "library", 955 | "extra": { 956 | "branch-alias": { 957 | "dev-master": "1.2.x-dev" 958 | } 959 | }, 960 | "autoload": { 961 | "classmap": [ 962 | "src/" 963 | ] 964 | }, 965 | "notification-url": "https://packagist.org/downloads/", 966 | "license": [ 967 | "BSD-3-Clause" 968 | ], 969 | "authors": [ 970 | { 971 | "name": "Jeff Welch", 972 | "email": "whatthejeff@gmail.com" 973 | }, 974 | { 975 | "name": "Volker Dusch", 976 | "email": "github@wallbash.com" 977 | }, 978 | { 979 | "name": "Bernhard Schussek", 980 | "email": "bschussek@2bepublished.at" 981 | }, 982 | { 983 | "name": "Sebastian Bergmann", 984 | "email": "sebastian@phpunit.de" 985 | } 986 | ], 987 | "description": "Provides the functionality to compare PHP values for equality", 988 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 989 | "keywords": [ 990 | "comparator", 991 | "compare", 992 | "equality" 993 | ], 994 | "time": "2015-07-26 15:48:44" 995 | }, 996 | { 997 | "name": "sebastian/diff", 998 | "version": "1.4.1", 999 | "source": { 1000 | "type": "git", 1001 | "url": "https://github.com/sebastianbergmann/diff.git", 1002 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 1003 | }, 1004 | "dist": { 1005 | "type": "zip", 1006 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 1007 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 1008 | "shasum": "" 1009 | }, 1010 | "require": { 1011 | "php": ">=5.3.3" 1012 | }, 1013 | "require-dev": { 1014 | "phpunit/phpunit": "~4.8" 1015 | }, 1016 | "type": "library", 1017 | "extra": { 1018 | "branch-alias": { 1019 | "dev-master": "1.4-dev" 1020 | } 1021 | }, 1022 | "autoload": { 1023 | "classmap": [ 1024 | "src/" 1025 | ] 1026 | }, 1027 | "notification-url": "https://packagist.org/downloads/", 1028 | "license": [ 1029 | "BSD-3-Clause" 1030 | ], 1031 | "authors": [ 1032 | { 1033 | "name": "Kore Nordmann", 1034 | "email": "mail@kore-nordmann.de" 1035 | }, 1036 | { 1037 | "name": "Sebastian Bergmann", 1038 | "email": "sebastian@phpunit.de" 1039 | } 1040 | ], 1041 | "description": "Diff implementation", 1042 | "homepage": "https://github.com/sebastianbergmann/diff", 1043 | "keywords": [ 1044 | "diff" 1045 | ], 1046 | "time": "2015-12-08 07:14:41" 1047 | }, 1048 | { 1049 | "name": "sebastian/environment", 1050 | "version": "1.3.7", 1051 | "source": { 1052 | "type": "git", 1053 | "url": "https://github.com/sebastianbergmann/environment.git", 1054 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" 1055 | }, 1056 | "dist": { 1057 | "type": "zip", 1058 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", 1059 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", 1060 | "shasum": "" 1061 | }, 1062 | "require": { 1063 | "php": ">=5.3.3" 1064 | }, 1065 | "require-dev": { 1066 | "phpunit/phpunit": "~4.4" 1067 | }, 1068 | "type": "library", 1069 | "extra": { 1070 | "branch-alias": { 1071 | "dev-master": "1.3.x-dev" 1072 | } 1073 | }, 1074 | "autoload": { 1075 | "classmap": [ 1076 | "src/" 1077 | ] 1078 | }, 1079 | "notification-url": "https://packagist.org/downloads/", 1080 | "license": [ 1081 | "BSD-3-Clause" 1082 | ], 1083 | "authors": [ 1084 | { 1085 | "name": "Sebastian Bergmann", 1086 | "email": "sebastian@phpunit.de" 1087 | } 1088 | ], 1089 | "description": "Provides functionality to handle HHVM/PHP environments", 1090 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1091 | "keywords": [ 1092 | "Xdebug", 1093 | "environment", 1094 | "hhvm" 1095 | ], 1096 | "time": "2016-05-17 03:18:57" 1097 | }, 1098 | { 1099 | "name": "sebastian/exporter", 1100 | "version": "1.2.1", 1101 | "source": { 1102 | "type": "git", 1103 | "url": "https://github.com/sebastianbergmann/exporter.git", 1104 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e" 1105 | }, 1106 | "dist": { 1107 | "type": "zip", 1108 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", 1109 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e", 1110 | "shasum": "" 1111 | }, 1112 | "require": { 1113 | "php": ">=5.3.3", 1114 | "sebastian/recursion-context": "~1.0" 1115 | }, 1116 | "require-dev": { 1117 | "phpunit/phpunit": "~4.4" 1118 | }, 1119 | "type": "library", 1120 | "extra": { 1121 | "branch-alias": { 1122 | "dev-master": "1.2.x-dev" 1123 | } 1124 | }, 1125 | "autoload": { 1126 | "classmap": [ 1127 | "src/" 1128 | ] 1129 | }, 1130 | "notification-url": "https://packagist.org/downloads/", 1131 | "license": [ 1132 | "BSD-3-Clause" 1133 | ], 1134 | "authors": [ 1135 | { 1136 | "name": "Jeff Welch", 1137 | "email": "whatthejeff@gmail.com" 1138 | }, 1139 | { 1140 | "name": "Volker Dusch", 1141 | "email": "github@wallbash.com" 1142 | }, 1143 | { 1144 | "name": "Bernhard Schussek", 1145 | "email": "bschussek@2bepublished.at" 1146 | }, 1147 | { 1148 | "name": "Sebastian Bergmann", 1149 | "email": "sebastian@phpunit.de" 1150 | }, 1151 | { 1152 | "name": "Adam Harvey", 1153 | "email": "aharvey@php.net" 1154 | } 1155 | ], 1156 | "description": "Provides the functionality to export PHP variables for visualization", 1157 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1158 | "keywords": [ 1159 | "export", 1160 | "exporter" 1161 | ], 1162 | "time": "2015-06-21 07:55:53" 1163 | }, 1164 | { 1165 | "name": "sebastian/global-state", 1166 | "version": "1.1.1", 1167 | "source": { 1168 | "type": "git", 1169 | "url": "https://github.com/sebastianbergmann/global-state.git", 1170 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1171 | }, 1172 | "dist": { 1173 | "type": "zip", 1174 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1175 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1176 | "shasum": "" 1177 | }, 1178 | "require": { 1179 | "php": ">=5.3.3" 1180 | }, 1181 | "require-dev": { 1182 | "phpunit/phpunit": "~4.2" 1183 | }, 1184 | "suggest": { 1185 | "ext-uopz": "*" 1186 | }, 1187 | "type": "library", 1188 | "extra": { 1189 | "branch-alias": { 1190 | "dev-master": "1.0-dev" 1191 | } 1192 | }, 1193 | "autoload": { 1194 | "classmap": [ 1195 | "src/" 1196 | ] 1197 | }, 1198 | "notification-url": "https://packagist.org/downloads/", 1199 | "license": [ 1200 | "BSD-3-Clause" 1201 | ], 1202 | "authors": [ 1203 | { 1204 | "name": "Sebastian Bergmann", 1205 | "email": "sebastian@phpunit.de" 1206 | } 1207 | ], 1208 | "description": "Snapshotting of global state", 1209 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1210 | "keywords": [ 1211 | "global state" 1212 | ], 1213 | "time": "2015-10-12 03:26:01" 1214 | }, 1215 | { 1216 | "name": "sebastian/object-enumerator", 1217 | "version": "1.0.0", 1218 | "source": { 1219 | "type": "git", 1220 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1221 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" 1222 | }, 1223 | "dist": { 1224 | "type": "zip", 1225 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", 1226 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", 1227 | "shasum": "" 1228 | }, 1229 | "require": { 1230 | "php": ">=5.6", 1231 | "sebastian/recursion-context": "~1.0" 1232 | }, 1233 | "require-dev": { 1234 | "phpunit/phpunit": "~5" 1235 | }, 1236 | "type": "library", 1237 | "extra": { 1238 | "branch-alias": { 1239 | "dev-master": "1.0.x-dev" 1240 | } 1241 | }, 1242 | "autoload": { 1243 | "classmap": [ 1244 | "src/" 1245 | ] 1246 | }, 1247 | "notification-url": "https://packagist.org/downloads/", 1248 | "license": [ 1249 | "BSD-3-Clause" 1250 | ], 1251 | "authors": [ 1252 | { 1253 | "name": "Sebastian Bergmann", 1254 | "email": "sebastian@phpunit.de" 1255 | } 1256 | ], 1257 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1258 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1259 | "time": "2016-01-28 13:25:10" 1260 | }, 1261 | { 1262 | "name": "sebastian/recursion-context", 1263 | "version": "1.0.2", 1264 | "source": { 1265 | "type": "git", 1266 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1267 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791" 1268 | }, 1269 | "dist": { 1270 | "type": "zip", 1271 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", 1272 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791", 1273 | "shasum": "" 1274 | }, 1275 | "require": { 1276 | "php": ">=5.3.3" 1277 | }, 1278 | "require-dev": { 1279 | "phpunit/phpunit": "~4.4" 1280 | }, 1281 | "type": "library", 1282 | "extra": { 1283 | "branch-alias": { 1284 | "dev-master": "1.0.x-dev" 1285 | } 1286 | }, 1287 | "autoload": { 1288 | "classmap": [ 1289 | "src/" 1290 | ] 1291 | }, 1292 | "notification-url": "https://packagist.org/downloads/", 1293 | "license": [ 1294 | "BSD-3-Clause" 1295 | ], 1296 | "authors": [ 1297 | { 1298 | "name": "Jeff Welch", 1299 | "email": "whatthejeff@gmail.com" 1300 | }, 1301 | { 1302 | "name": "Sebastian Bergmann", 1303 | "email": "sebastian@phpunit.de" 1304 | }, 1305 | { 1306 | "name": "Adam Harvey", 1307 | "email": "aharvey@php.net" 1308 | } 1309 | ], 1310 | "description": "Provides functionality to recursively process PHP variables", 1311 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1312 | "time": "2015-11-11 19:50:13" 1313 | }, 1314 | { 1315 | "name": "sebastian/resource-operations", 1316 | "version": "1.0.0", 1317 | "source": { 1318 | "type": "git", 1319 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1320 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1321 | }, 1322 | "dist": { 1323 | "type": "zip", 1324 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1325 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1326 | "shasum": "" 1327 | }, 1328 | "require": { 1329 | "php": ">=5.6.0" 1330 | }, 1331 | "type": "library", 1332 | "extra": { 1333 | "branch-alias": { 1334 | "dev-master": "1.0.x-dev" 1335 | } 1336 | }, 1337 | "autoload": { 1338 | "classmap": [ 1339 | "src/" 1340 | ] 1341 | }, 1342 | "notification-url": "https://packagist.org/downloads/", 1343 | "license": [ 1344 | "BSD-3-Clause" 1345 | ], 1346 | "authors": [ 1347 | { 1348 | "name": "Sebastian Bergmann", 1349 | "email": "sebastian@phpunit.de" 1350 | } 1351 | ], 1352 | "description": "Provides a list of PHP built-in functions that operate on resources", 1353 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1354 | "time": "2015-07-28 20:34:47" 1355 | }, 1356 | { 1357 | "name": "sebastian/version", 1358 | "version": "2.0.0", 1359 | "source": { 1360 | "type": "git", 1361 | "url": "https://github.com/sebastianbergmann/version.git", 1362 | "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" 1363 | }, 1364 | "dist": { 1365 | "type": "zip", 1366 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", 1367 | "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", 1368 | "shasum": "" 1369 | }, 1370 | "require": { 1371 | "php": ">=5.6" 1372 | }, 1373 | "type": "library", 1374 | "extra": { 1375 | "branch-alias": { 1376 | "dev-master": "2.0.x-dev" 1377 | } 1378 | }, 1379 | "autoload": { 1380 | "classmap": [ 1381 | "src/" 1382 | ] 1383 | }, 1384 | "notification-url": "https://packagist.org/downloads/", 1385 | "license": [ 1386 | "BSD-3-Clause" 1387 | ], 1388 | "authors": [ 1389 | { 1390 | "name": "Sebastian Bergmann", 1391 | "email": "sebastian@phpunit.de", 1392 | "role": "lead" 1393 | } 1394 | ], 1395 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1396 | "homepage": "https://github.com/sebastianbergmann/version", 1397 | "time": "2016-02-04 12:56:52" 1398 | }, 1399 | { 1400 | "name": "squizlabs/php_codesniffer", 1401 | "version": "2.6.1", 1402 | "source": { 1403 | "type": "git", 1404 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1405 | "reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d" 1406 | }, 1407 | "dist": { 1408 | "type": "zip", 1409 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fb72ed32f8418db5e7770be1653e62e0d6f5dd3d", 1410 | "reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d", 1411 | "shasum": "" 1412 | }, 1413 | "require": { 1414 | "ext-simplexml": "*", 1415 | "ext-tokenizer": "*", 1416 | "ext-xmlwriter": "*", 1417 | "php": ">=5.1.2" 1418 | }, 1419 | "require-dev": { 1420 | "phpunit/phpunit": "~4.0" 1421 | }, 1422 | "bin": [ 1423 | "scripts/phpcs", 1424 | "scripts/phpcbf" 1425 | ], 1426 | "type": "library", 1427 | "extra": { 1428 | "branch-alias": { 1429 | "dev-master": "2.x-dev" 1430 | } 1431 | }, 1432 | "autoload": { 1433 | "classmap": [ 1434 | "CodeSniffer.php", 1435 | "CodeSniffer/CLI.php", 1436 | "CodeSniffer/Exception.php", 1437 | "CodeSniffer/File.php", 1438 | "CodeSniffer/Fixer.php", 1439 | "CodeSniffer/Report.php", 1440 | "CodeSniffer/Reporting.php", 1441 | "CodeSniffer/Sniff.php", 1442 | "CodeSniffer/Tokens.php", 1443 | "CodeSniffer/Reports/", 1444 | "CodeSniffer/Tokenizers/", 1445 | "CodeSniffer/DocGenerators/", 1446 | "CodeSniffer/Standards/AbstractPatternSniff.php", 1447 | "CodeSniffer/Standards/AbstractScopeSniff.php", 1448 | "CodeSniffer/Standards/AbstractVariableSniff.php", 1449 | "CodeSniffer/Standards/IncorrectPatternException.php", 1450 | "CodeSniffer/Standards/Generic/Sniffs/", 1451 | "CodeSniffer/Standards/MySource/Sniffs/", 1452 | "CodeSniffer/Standards/PEAR/Sniffs/", 1453 | "CodeSniffer/Standards/PSR1/Sniffs/", 1454 | "CodeSniffer/Standards/PSR2/Sniffs/", 1455 | "CodeSniffer/Standards/Squiz/Sniffs/", 1456 | "CodeSniffer/Standards/Zend/Sniffs/" 1457 | ] 1458 | }, 1459 | "notification-url": "https://packagist.org/downloads/", 1460 | "license": [ 1461 | "BSD-3-Clause" 1462 | ], 1463 | "authors": [ 1464 | { 1465 | "name": "Greg Sherwood", 1466 | "role": "lead" 1467 | } 1468 | ], 1469 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 1470 | "homepage": "http://www.squizlabs.com/php-codesniffer", 1471 | "keywords": [ 1472 | "phpcs", 1473 | "standards" 1474 | ], 1475 | "time": "2016-05-30 22:24:32" 1476 | }, 1477 | { 1478 | "name": "symfony/config", 1479 | "version": "v3.1.1", 1480 | "source": { 1481 | "type": "git", 1482 | "url": "https://github.com/symfony/config.git", 1483 | "reference": "048dc47e07f92333203c3b7045868bbc864fc40e" 1484 | }, 1485 | "dist": { 1486 | "type": "zip", 1487 | "url": "https://api.github.com/repos/symfony/config/zipball/048dc47e07f92333203c3b7045868bbc864fc40e", 1488 | "reference": "048dc47e07f92333203c3b7045868bbc864fc40e", 1489 | "shasum": "" 1490 | }, 1491 | "require": { 1492 | "php": ">=5.5.9", 1493 | "symfony/filesystem": "~2.8|~3.0" 1494 | }, 1495 | "suggest": { 1496 | "symfony/yaml": "To use the yaml reference dumper" 1497 | }, 1498 | "type": "library", 1499 | "extra": { 1500 | "branch-alias": { 1501 | "dev-master": "3.1-dev" 1502 | } 1503 | }, 1504 | "autoload": { 1505 | "psr-4": { 1506 | "Symfony\\Component\\Config\\": "" 1507 | }, 1508 | "exclude-from-classmap": [ 1509 | "/Tests/" 1510 | ] 1511 | }, 1512 | "notification-url": "https://packagist.org/downloads/", 1513 | "license": [ 1514 | "MIT" 1515 | ], 1516 | "authors": [ 1517 | { 1518 | "name": "Fabien Potencier", 1519 | "email": "fabien@symfony.com" 1520 | }, 1521 | { 1522 | "name": "Symfony Community", 1523 | "homepage": "https://symfony.com/contributors" 1524 | } 1525 | ], 1526 | "description": "Symfony Config Component", 1527 | "homepage": "https://symfony.com", 1528 | "time": "2016-05-20 11:48:17" 1529 | }, 1530 | { 1531 | "name": "symfony/console", 1532 | "version": "v3.1.1", 1533 | "source": { 1534 | "type": "git", 1535 | "url": "https://github.com/symfony/console.git", 1536 | "reference": "64a4d43b045f07055bb197650159769604cb2a92" 1537 | }, 1538 | "dist": { 1539 | "type": "zip", 1540 | "url": "https://api.github.com/repos/symfony/console/zipball/64a4d43b045f07055bb197650159769604cb2a92", 1541 | "reference": "64a4d43b045f07055bb197650159769604cb2a92", 1542 | "shasum": "" 1543 | }, 1544 | "require": { 1545 | "php": ">=5.5.9", 1546 | "symfony/polyfill-mbstring": "~1.0" 1547 | }, 1548 | "require-dev": { 1549 | "psr/log": "~1.0", 1550 | "symfony/event-dispatcher": "~2.8|~3.0", 1551 | "symfony/process": "~2.8|~3.0" 1552 | }, 1553 | "suggest": { 1554 | "psr/log": "For using the console logger", 1555 | "symfony/event-dispatcher": "", 1556 | "symfony/process": "" 1557 | }, 1558 | "type": "library", 1559 | "extra": { 1560 | "branch-alias": { 1561 | "dev-master": "3.1-dev" 1562 | } 1563 | }, 1564 | "autoload": { 1565 | "psr-4": { 1566 | "Symfony\\Component\\Console\\": "" 1567 | }, 1568 | "exclude-from-classmap": [ 1569 | "/Tests/" 1570 | ] 1571 | }, 1572 | "notification-url": "https://packagist.org/downloads/", 1573 | "license": [ 1574 | "MIT" 1575 | ], 1576 | "authors": [ 1577 | { 1578 | "name": "Fabien Potencier", 1579 | "email": "fabien@symfony.com" 1580 | }, 1581 | { 1582 | "name": "Symfony Community", 1583 | "homepage": "https://symfony.com/contributors" 1584 | } 1585 | ], 1586 | "description": "Symfony Console Component", 1587 | "homepage": "https://symfony.com", 1588 | "time": "2016-06-14 11:18:07" 1589 | }, 1590 | { 1591 | "name": "symfony/event-dispatcher", 1592 | "version": "v2.8.7", 1593 | "source": { 1594 | "type": "git", 1595 | "url": "https://github.com/symfony/event-dispatcher.git", 1596 | "reference": "2a6b8713f8bdb582058cfda463527f195b066110" 1597 | }, 1598 | "dist": { 1599 | "type": "zip", 1600 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110", 1601 | "reference": "2a6b8713f8bdb582058cfda463527f195b066110", 1602 | "shasum": "" 1603 | }, 1604 | "require": { 1605 | "php": ">=5.3.9" 1606 | }, 1607 | "require-dev": { 1608 | "psr/log": "~1.0", 1609 | "symfony/config": "~2.0,>=2.0.5|~3.0.0", 1610 | "symfony/dependency-injection": "~2.6|~3.0.0", 1611 | "symfony/expression-language": "~2.6|~3.0.0", 1612 | "symfony/stopwatch": "~2.3|~3.0.0" 1613 | }, 1614 | "suggest": { 1615 | "symfony/dependency-injection": "", 1616 | "symfony/http-kernel": "" 1617 | }, 1618 | "type": "library", 1619 | "extra": { 1620 | "branch-alias": { 1621 | "dev-master": "2.8-dev" 1622 | } 1623 | }, 1624 | "autoload": { 1625 | "psr-4": { 1626 | "Symfony\\Component\\EventDispatcher\\": "" 1627 | }, 1628 | "exclude-from-classmap": [ 1629 | "/Tests/" 1630 | ] 1631 | }, 1632 | "notification-url": "https://packagist.org/downloads/", 1633 | "license": [ 1634 | "MIT" 1635 | ], 1636 | "authors": [ 1637 | { 1638 | "name": "Fabien Potencier", 1639 | "email": "fabien@symfony.com" 1640 | }, 1641 | { 1642 | "name": "Symfony Community", 1643 | "homepage": "https://symfony.com/contributors" 1644 | } 1645 | ], 1646 | "description": "Symfony EventDispatcher Component", 1647 | "homepage": "https://symfony.com", 1648 | "time": "2016-06-06 11:11:27" 1649 | }, 1650 | { 1651 | "name": "symfony/filesystem", 1652 | "version": "v3.1.1", 1653 | "source": { 1654 | "type": "git", 1655 | "url": "https://github.com/symfony/filesystem.git", 1656 | "reference": "5751e80d6f94b7c018f338a4a7be0b700d6f3058" 1657 | }, 1658 | "dist": { 1659 | "type": "zip", 1660 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/5751e80d6f94b7c018f338a4a7be0b700d6f3058", 1661 | "reference": "5751e80d6f94b7c018f338a4a7be0b700d6f3058", 1662 | "shasum": "" 1663 | }, 1664 | "require": { 1665 | "php": ">=5.5.9" 1666 | }, 1667 | "type": "library", 1668 | "extra": { 1669 | "branch-alias": { 1670 | "dev-master": "3.1-dev" 1671 | } 1672 | }, 1673 | "autoload": { 1674 | "psr-4": { 1675 | "Symfony\\Component\\Filesystem\\": "" 1676 | }, 1677 | "exclude-from-classmap": [ 1678 | "/Tests/" 1679 | ] 1680 | }, 1681 | "notification-url": "https://packagist.org/downloads/", 1682 | "license": [ 1683 | "MIT" 1684 | ], 1685 | "authors": [ 1686 | { 1687 | "name": "Fabien Potencier", 1688 | "email": "fabien@symfony.com" 1689 | }, 1690 | { 1691 | "name": "Symfony Community", 1692 | "homepage": "https://symfony.com/contributors" 1693 | } 1694 | ], 1695 | "description": "Symfony Filesystem Component", 1696 | "homepage": "https://symfony.com", 1697 | "time": "2016-04-12 18:27:47" 1698 | }, 1699 | { 1700 | "name": "symfony/polyfill-mbstring", 1701 | "version": "v1.2.0", 1702 | "source": { 1703 | "type": "git", 1704 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1705 | "reference": "dff51f72b0706335131b00a7f49606168c582594" 1706 | }, 1707 | "dist": { 1708 | "type": "zip", 1709 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", 1710 | "reference": "dff51f72b0706335131b00a7f49606168c582594", 1711 | "shasum": "" 1712 | }, 1713 | "require": { 1714 | "php": ">=5.3.3" 1715 | }, 1716 | "suggest": { 1717 | "ext-mbstring": "For best performance" 1718 | }, 1719 | "type": "library", 1720 | "extra": { 1721 | "branch-alias": { 1722 | "dev-master": "1.2-dev" 1723 | } 1724 | }, 1725 | "autoload": { 1726 | "psr-4": { 1727 | "Symfony\\Polyfill\\Mbstring\\": "" 1728 | }, 1729 | "files": [ 1730 | "bootstrap.php" 1731 | ] 1732 | }, 1733 | "notification-url": "https://packagist.org/downloads/", 1734 | "license": [ 1735 | "MIT" 1736 | ], 1737 | "authors": [ 1738 | { 1739 | "name": "Nicolas Grekas", 1740 | "email": "p@tchwork.com" 1741 | }, 1742 | { 1743 | "name": "Symfony Community", 1744 | "homepage": "https://symfony.com/contributors" 1745 | } 1746 | ], 1747 | "description": "Symfony polyfill for the Mbstring extension", 1748 | "homepage": "https://symfony.com", 1749 | "keywords": [ 1750 | "compatibility", 1751 | "mbstring", 1752 | "polyfill", 1753 | "portable", 1754 | "shim" 1755 | ], 1756 | "time": "2016-05-18 14:26:46" 1757 | }, 1758 | { 1759 | "name": "symfony/stopwatch", 1760 | "version": "v3.1.1", 1761 | "source": { 1762 | "type": "git", 1763 | "url": "https://github.com/symfony/stopwatch.git", 1764 | "reference": "e7238f98c90b99e9b53f3674a91757228663b04d" 1765 | }, 1766 | "dist": { 1767 | "type": "zip", 1768 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e7238f98c90b99e9b53f3674a91757228663b04d", 1769 | "reference": "e7238f98c90b99e9b53f3674a91757228663b04d", 1770 | "shasum": "" 1771 | }, 1772 | "require": { 1773 | "php": ">=5.5.9" 1774 | }, 1775 | "type": "library", 1776 | "extra": { 1777 | "branch-alias": { 1778 | "dev-master": "3.1-dev" 1779 | } 1780 | }, 1781 | "autoload": { 1782 | "psr-4": { 1783 | "Symfony\\Component\\Stopwatch\\": "" 1784 | }, 1785 | "exclude-from-classmap": [ 1786 | "/Tests/" 1787 | ] 1788 | }, 1789 | "notification-url": "https://packagist.org/downloads/", 1790 | "license": [ 1791 | "MIT" 1792 | ], 1793 | "authors": [ 1794 | { 1795 | "name": "Fabien Potencier", 1796 | "email": "fabien@symfony.com" 1797 | }, 1798 | { 1799 | "name": "Symfony Community", 1800 | "homepage": "https://symfony.com/contributors" 1801 | } 1802 | ], 1803 | "description": "Symfony Stopwatch Component", 1804 | "homepage": "https://symfony.com", 1805 | "time": "2016-06-06 11:42:41" 1806 | }, 1807 | { 1808 | "name": "symfony/yaml", 1809 | "version": "v3.1.1", 1810 | "source": { 1811 | "type": "git", 1812 | "url": "https://github.com/symfony/yaml.git", 1813 | "reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623" 1814 | }, 1815 | "dist": { 1816 | "type": "zip", 1817 | "url": "https://api.github.com/repos/symfony/yaml/zipball/c5a7e7fc273c758b92b85dcb9c46149ccda89623", 1818 | "reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623", 1819 | "shasum": "" 1820 | }, 1821 | "require": { 1822 | "php": ">=5.5.9" 1823 | }, 1824 | "type": "library", 1825 | "extra": { 1826 | "branch-alias": { 1827 | "dev-master": "3.1-dev" 1828 | } 1829 | }, 1830 | "autoload": { 1831 | "psr-4": { 1832 | "Symfony\\Component\\Yaml\\": "" 1833 | }, 1834 | "exclude-from-classmap": [ 1835 | "/Tests/" 1836 | ] 1837 | }, 1838 | "notification-url": "https://packagist.org/downloads/", 1839 | "license": [ 1840 | "MIT" 1841 | ], 1842 | "authors": [ 1843 | { 1844 | "name": "Fabien Potencier", 1845 | "email": "fabien@symfony.com" 1846 | }, 1847 | { 1848 | "name": "Symfony Community", 1849 | "homepage": "https://symfony.com/contributors" 1850 | } 1851 | ], 1852 | "description": "Symfony Yaml Component", 1853 | "homepage": "https://symfony.com", 1854 | "time": "2016-06-14 11:18:07" 1855 | }, 1856 | { 1857 | "name": "webmozart/assert", 1858 | "version": "1.0.2", 1859 | "source": { 1860 | "type": "git", 1861 | "url": "https://github.com/webmozart/assert.git", 1862 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" 1863 | }, 1864 | "dist": { 1865 | "type": "zip", 1866 | "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1867 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1868 | "shasum": "" 1869 | }, 1870 | "require": { 1871 | "php": ">=5.3.3" 1872 | }, 1873 | "require-dev": { 1874 | "phpunit/phpunit": "^4.6" 1875 | }, 1876 | "type": "library", 1877 | "extra": { 1878 | "branch-alias": { 1879 | "dev-master": "1.0-dev" 1880 | } 1881 | }, 1882 | "autoload": { 1883 | "psr-4": { 1884 | "Webmozart\\Assert\\": "src/" 1885 | } 1886 | }, 1887 | "notification-url": "https://packagist.org/downloads/", 1888 | "license": [ 1889 | "MIT" 1890 | ], 1891 | "authors": [ 1892 | { 1893 | "name": "Bernhard Schussek", 1894 | "email": "bschussek@gmail.com" 1895 | } 1896 | ], 1897 | "description": "Assertions to validate method input/output with nice error messages.", 1898 | "keywords": [ 1899 | "assert", 1900 | "check", 1901 | "validate" 1902 | ], 1903 | "time": "2015-08-24 13:29:44" 1904 | } 1905 | ], 1906 | "aliases": [], 1907 | "minimum-stability": "stable", 1908 | "stability-flags": [], 1909 | "prefer-stable": false, 1910 | "prefer-lowest": false, 1911 | "platform": { 1912 | "php": ">=5.6" 1913 | }, 1914 | "platform-dev": [] 1915 | } 1916 | --------------------------------------------------------------------------------