From 71b1ab0958741e822ae896389ede6ac8b4b2d70c Mon Sep 17 00:00:00 2001 From: Ori Hoch Date: Thu, 8 Jun 2017 15:59:44 +0300 Subject: [PATCH] fixed validations of relative paths against json schema --- CONTRIBUTING.md | 6 +++++ src/Validators/DatapackageValidator.php | 16 ++++++++++++++ src/Validators/ResourceValidator.php | 8 ++++++- tests/FactoryTest.php | 29 +++++++++++++++++++------ 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 61bf6ca..a267109 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,3 +56,9 @@ At the moment, the integration with frictionlessdata repo is not working, you ca * Login with GitHub which has permissions * click "Update" * all releases from GitHub appear as releases on Packagist + +## updating frictionlessdata schemas + +The json schemas for the frictionlessdata specs are stored locally as part of the package. + +They might change from time to time, to donwnload the latest specs run `composer update_registry` diff --git a/src/Validators/DatapackageValidator.php b/src/Validators/DatapackageValidator.php index 17277e8..1cb9191 100644 --- a/src/Validators/DatapackageValidator.php +++ b/src/Validators/DatapackageValidator.php @@ -19,6 +19,22 @@ protected function getValidationProfile() return Registry::getDatapackageValidationProfile($this->descriptor); } + protected function getDescriptorForValidation() + { + // add base path to uri fields + // TODO: find a more elegant way to do it with support for registring custom url fields + $descriptor = clone $this->descriptor; + if (isset($descriptor->resources)) { + foreach ($descriptor->resources as &$resource) { + $resource = clone $resource; + foreach ($resource->data as &$url) { + $url = "file://".$url; + } + } + } + return $descriptor; + } + protected function validateSchema() { parent::validateSchema(); diff --git a/src/Validators/ResourceValidator.php b/src/Validators/ResourceValidator.php index 77de8a1..36c6374 100644 --- a/src/Validators/ResourceValidator.php +++ b/src/Validators/ResourceValidator.php @@ -21,7 +21,13 @@ protected function getValidationProfile() protected function getDescriptorForValidation() { - return $this->descriptor; + // add base path to uri fields + // TODO: find a more elegant way to do it with support for registring custom url fields + $descriptor = clone $this->descriptor; + foreach ($descriptor->data as &$url) { + $url = "file://".$url; + } + return $descriptor; } protected function getValidationErrorMessage($error) diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 9bfec45..6ea94a1 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -8,31 +8,39 @@ class FactoryTest extends TestCase { public function testRegisterDatapackageClass() { + // the MyCustomDatapackage datapackage class checks for a myCustomDatapackage property on the descriptor + // it is only used when this attribute exists + Factory::registerDatapackageClass( + "frictionlessdata\\datapackage\\tests\\Mocks\\MyCustomDatapackage" + ); + // descriptor without the myCustomDatapackage property $descriptor = (object)[ "name" => "my-custom-datapackage", "resources" => [ (object)["name" => "my-custom-resource", "data" => ["tests/fixtures/foo.txt"]] ] ]; - Factory::registerDatapackageClass( - "frictionlessdata\\datapackage\\tests\\Mocks\\MyCustomDatapackage" - ); - // descriptor without the custom property + // get a datapackage object based on this descriptor $datapackage = Factory::datapackage($descriptor); + // the custom datapackage is not used (because the myCustomDatapackage property didn't exist) $this->assertEquals( - // custom datapackage is not used "frictionlessdata\\datapackage\\Datapackages\\DefaultDatapackage", get_class($datapackage) ); - // add the custom property - which is checked by MyCustomDatapackage + // add the myCustomDatapackage property to the descriptor $descriptor->myCustomDatapackage = true; + // get a datapackage object $datapackage = Factory::datapackage($descriptor); + // voila - we got a MyCustomDatapackage class $this->assertEquals( "frictionlessdata\\datapackage\\tests\\Mocks\\MyCustomDatapackage", get_class($datapackage) ); + // make sure to clear the custom datapackage class we registered Factory::clearRegisteredDatapackageClasses(); + // create a datapackage object from the descriptor with the myCustomDatapackage property $datapackage = Factory::datapackage($descriptor); + // got the normal default datapackage class (because we cleared the custom registered classes) $this->assertEquals( "frictionlessdata\\datapackage\\Datapackages\\DefaultDatapackage", get_class($datapackage) @@ -41,21 +49,28 @@ public function testRegisterDatapackageClass() public function testRegisterResourceClass() { - $descriptor = (object)["name" => "my-custom-resource", "data" => ["tests/fixtures/foo.txt"]]; + // register a custom resource class which is used for resources that have the goGoPowerRangers property Factory::registerResourceClass( "frictionlessdata\\datapackage\\tests\\Mocks\\MyCustomResource" ); + // a descriptor without the goGoPowerRangers property + $descriptor = (object)["name" => "my-custom-resource", "data" => ["tests/fixtures/foo.txt"]]; + // create a resource object based on the descriptor $resource = Factory::resource($descriptor); + // got a normal resource $this->assertEquals( "frictionlessdata\\datapackage\\Resources\DefaultResource", get_class($resource) ); + // add the goGoPowerRangers property $descriptor->goGoPowerRangers = true; $resource = Factory::resource($descriptor); + // got the custom resource $this->assertEquals( "frictionlessdata\\datapackage\\tests\\Mocks\\MyCustomResource", get_class($resource) ); + // clear the registered classes and ensure it's cleared Factory::clearRegisteredResourceClasses(); $resource = Factory::resource($descriptor); $this->assertEquals(