diff --git a/.gitignore b/.gitignore index 688d850..97eab31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea composer.lock -vendor \ No newline at end of file +vendor +.php_cs.cache +.phpunit.result.cache diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..363296d --- /dev/null +++ b/.php_cs @@ -0,0 +1,10 @@ +getFinder()->in(__DIR__); + +$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__; + +$config->setCacheFile($cacheDir . '/.php_cs.cache'); + +return $config; diff --git a/composer.json b/composer.json index 45c3f16..77843e2 100644 --- a/composer.json +++ b/composer.json @@ -17,18 +17,18 @@ ], "require": { "php": "^7.4 || ^8.0", + "ext-json": "*", "event-engine/php-data": "^2.0", "event-engine/php-engine-utils": "^0.2", "event-engine/php-schema": "^0.2", "ramsey/uuid": "^3.6 || ^4.0" }, "require-dev": { - "ext-json": "*", "justinrainbow/json-schema": "^5.2", "malukenho/docheader": "^0.1.4", "opis/json-schema": "^1.0", "phpunit/phpunit": "^8.0 || ^9.0", - "prooph/php-cs-fixer-config": "^0.4", + "prooph/php-cs-fixer-config": "^v0.4.0", "roave/security-advisories": "dev-master", "php-coveralls/php-coveralls": "^2.0" }, diff --git a/src/Exception/CouldNotReadFileException.php b/src/Exception/CouldNotReadFileException.php new file mode 100644 index 0000000..54987b4 --- /dev/null +++ b/src/Exception/CouldNotReadFileException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace EventEngine\JsonSchema\Exception; + +final class CouldNotReadFileException extends RuntimeException +{ + public static function forFile(string $file): self + { + return new self( + \sprintf('Could not read "%s" file.', $file) + ); + } +} diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php new file mode 100644 index 0000000..2ec67f6 --- /dev/null +++ b/src/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace EventEngine\JsonSchema\Exception; + +use RuntimeException as PhpRuntimeException; + +class RuntimeException extends PhpRuntimeException implements JsonSchemaException +{ +} diff --git a/src/JsonSchemaArray.php b/src/JsonSchemaArray.php index 317ca78..d11c717 100644 --- a/src/JsonSchemaArray.php +++ b/src/JsonSchemaArray.php @@ -1,4 +1,5 @@ @@ -11,16 +12,31 @@ namespace EventEngine\JsonSchema; +use EventEngine\JsonSchema\Exception\CouldNotReadFileException; use EventEngine\Schema\InputTypeSchema; use EventEngine\Schema\PayloadSchema; use EventEngine\Schema\ResponseTypeSchema; +use const JSON_THROW_ON_ERROR; final class JsonSchemaArray implements PayloadSchema, ResponseTypeSchema, InputTypeSchema { - /** - * @var array - */ - private $schema; + private array $schema; + + public static function fromFile(string $file, int $flags = JSON_THROW_ON_ERROR, int $depth = 512): self + { + if (! \file_exists($file) || ! \is_readable($file)) { + throw CouldNotReadFileException::forFile($file); + } + + return self::fromString(\file_get_contents($file), $depth, $flags); + } + + public static function fromString(string $jsonSchema, int $flags = JSON_THROW_ON_ERROR, int $depth = 512): self + { + return new self( + \json_decode($jsonSchema, true, $depth, $flags) + ); + } public function __construct(array $schema) { diff --git a/tests/JsonSchemaArrayTest.php b/tests/JsonSchemaArrayTest.php new file mode 100644 index 0000000..1905f77 --- /dev/null +++ b/tests/JsonSchemaArrayTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace EventEngineTest\JsonSchema; + +use EventEngine\JsonSchema\Exception\CouldNotReadFileException; +use EventEngine\JsonSchema\JsonSchemaArray; + +final class JsonSchemaArrayTest extends BasicTestCase +{ + private const FILE = __DIR__ . DIRECTORY_SEPARATOR . '_files/schema.json'; + + /** + * @test + */ + public function it_creates_json_schema_from_file(): void + { + $cut = JsonSchemaArray::fromFile(self::FILE); + $this->assertArrayHasKey('properties', $cut->toArray()); + } + + /** + * @test + */ + public function it_creates_json_schema_from_string(): void + { + $cut = JsonSchemaArray::fromString(\file_get_contents(self::FILE)); + $this->assertArrayHasKey('properties', $cut->toArray()); + } + + /** + * @test + */ + public function it_throws_exception_if_file_is_not_found(): void + { + $this->expectException(CouldNotReadFileException::class); + JsonSchemaArray::fromFile('unknown.json'); + } +} diff --git a/tests/_files/schema.json b/tests/_files/schema.json new file mode 100644 index 0000000..ee50efd --- /dev/null +++ b/tests/_files/schema.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "additionalProperties": false +}