diff --git a/.gitignore b/.gitignore index c86af6f..fa1d02a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /node_modules /.php_cs.cache +/.php-cs-fixer.cache /.phpunit.result.cache php-cs-fixer.phar diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 92% rename from .php_cs.dist rename to .php-cs-fixer.dist.php index 704f437..3594ae9 100644 --- a/.php_cs.dist +++ b/.php-cs-fixer.dist.php @@ -1,6 +1,6 @@ setRules([ '@PSR2' => true, 'array_syntax' => ['syntax' => 'short'], diff --git a/Makefile b/Makefile index ee99b2a..b4fae49 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ check-style: php-cs-fixer.phar fix-style: php-cs-fixer.phar $(DOCKER_PHP) vendor/bin/indent --tabs composer.json - $(DOCKER_PHP) vendor/bin/indent --spaces .php_cs.dist + $(DOCKER_PHP) vendor/bin/indent --spaces .php-cs-fixer.dist.php $(DOCKER_PHP) ./php-cs-fixer.phar fix src/ --diff install: composer.lock yarn.lock diff --git a/src/json/JsonPointer.php b/src/json/JsonPointer.php index 0e1f75e..3121e08 100644 --- a/src/json/JsonPointer.php +++ b/src/json/JsonPointer.php @@ -107,11 +107,11 @@ public function evaluate($jsonDocument) foreach ($this->getPath() as $part) { if (is_array($currentReference)) { -// if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { -// throw new NonexistentJsonPointerReferenceException( -// "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." -// ); -// } + // if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { + // throw new NonexistentJsonPointerReferenceException( + // "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." + // ); + // } if ($part === '-' || !array_key_exists($part, $currentReference)) { throw new NonexistentJsonPointerReferenceException( "Failed to evaluate pointer '$this->_pointer'. Array has no member $part at path '$currentPath'." diff --git a/src/spec/Paths.php b/src/spec/Paths.php index e504a90..7257bd7 100644 --- a/src/spec/Paths.php +++ b/src/spec/Paths.php @@ -46,6 +46,10 @@ class Paths implements SpecObjectInterface, DocumentContextInterface, ArrayAcces * @var JsonPointer|null */ private $_jsonPointer; + /** + * @var string + */ + private $_operationsIds = []; /** @@ -147,6 +151,18 @@ public function validate(): bool if (strpos($key, '/') !== 0) { $this->_errors[] = "Path must begin with /: $key"; } + $operations = $path->getOperations(); + foreach($operations as $operation) { + $id = $operation->operationId; + if(empty($id)) { + continue; + } + if(!empty($this->_operationsIds[$id]) && $this->_operationsIds[$id]) { + $this->_errors[] = "Operation ID '$id', already exist. Operation IDs must be unique."; + $valid = false; + } + $this->_operationsIds[$id] = true; + } } return $valid && empty($this->_errors); } diff --git a/tests/ReaderTest.php b/tests/ReaderTest.php index 589b7cb..218e504 100644 --- a/tests/ReaderTest.php +++ b/tests/ReaderTest.php @@ -129,6 +129,241 @@ public function testSymfonyYamlBugHunt() } + public function testForceUniqueOperationIdJSON(){ + //Duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertFalse($api->validate()); + + //Non duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertTrue($api->validate()); + } + + //Different Paths + public function testForceUniqueOperationIdInDifferentPathsJSON(){ + //Duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertFalse($api->validate()); + + // Non duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertTrue($api->validate()); + } + + //The same paths + public function testForceUniqueOperationIdYAML(){ + //Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertFalse($openapi->validate()); + + //Non Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertTrue($openapi->validate()); + } + + //Duplicate Different paths + public function testForceUniqueOperationIdInDifferentPathsYAML(){ + //Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertFalse($openapi->validate()); + + //Non Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertTrue($openapi->validate()); + } + + // TODO test invalid JSON // TODO test invalid YAML }