diff --git a/README.md b/README.md index 12130226..1c19e579 100644 --- a/README.md +++ b/README.md @@ -175,11 +175,11 @@ use alsvanzelf\jsonapi\ResourceDocument; use alsvanzelf\jsonapi\interfaces\ExtensionInterface; class ExampleExtension implements ExtensionInterface { - public function getOfficialLink() { + public function getOfficialLink(): string { return 'https://example.org/extension-documentation'; } - public function getNamespace() { + public function getNamespace(): string { return 'foo'; } } diff --git a/UPGRADE_2_TO_3.md b/UPGRADE_2_TO_3.md new file mode 100644 index 00000000..8940a243 --- /dev/null +++ b/UPGRADE_2_TO_3.md @@ -0,0 +1,43 @@ +# Upgrade from library v2 to v3 + +## Checking links, ... + +Objects more often use uninitialized properties. `has*()` helper methods have been added to support the new flow. + +- `$object->links` to `if ($object->hasLinks()) $object->links` + +## Interfaces + +When extending interfaces, you'll have to add method argument types and return types. + +Check [all interfaces](/src/interfaces) for the correct typing. + +## Enums + +Content types: +- `Document::CONTENT_TYPE_OFFICIAL` to `ContentTypeEnum::Official` +- `Document::CONTENT_TYPE_DEBUG` to `ContentTypeEnum::Debug` +- `Document::CONTENT_TYPE_JSONP` to `ContentTypeEnum::Jsonp` + +Jsonapi versions: +- `Document::JSONAPI_VERSION_1_0` to `JsonapiVersionEnum::V_1_0` +- `Document::JSONAPI_VERSION_1_1` to `JsonapiVersionEnum::V_1_1` +- `Document::JSONAPI_VERSION_LATEST` to `JsonapiVersionEnum::Latest` + +Document levels: +- `Document::LEVEL_ROOT` to `DocumentLevelEnum::Root` +- `Document::LEVEL_JSONAPI` to `DocumentLevelEnum::Jsonapi` +- `Document::LEVEL_Resource` to `DocumentLevelEnum::Resource` + +Sorting orders: +- `RequestParser->getSortFields()` returns a `SortOrderEnum` instead of `string` for the `order` field + +Relationship types: +- `RelationshipObject::TO_ONE` to `RelationshipTypeEnum::ToOne` +- `RelationshipObject::TO_MANY` to `RelationshipTypeEnum::ToMany` + +## Internal + +Enums: +- `RequestParser::SORT_*` to `SortOrderEnum::*` +- `Validator::OBJECT_CONTAINER_*` to `ObjectContainerEnum::*` diff --git a/examples/atomic_operations_extension.php b/examples/atomic_operations_extension.php index 4e97c6da..caa6aaae 100644 --- a/examples/atomic_operations_extension.php +++ b/examples/atomic_operations_extension.php @@ -1,5 +1,7 @@ Content-Type: '.$contentType.''.PHP_EOL; $options = [ diff --git a/examples/meta_only.php b/examples/meta_only.php index a41df02c..60562d7f 100644 --- a/examples/meta_only.php +++ b/examples/meta_only.php @@ -1,5 +1,7 @@ addRelationship('bar', null); -$document->addRelationshipObject('baz', new RelationshipObject(RelationshipObject::TO_ONE)); -$document->addRelationshipObject('baf', new RelationshipObject(RelationshipObject::TO_MANY)); +$document->addRelationshipObject('baz', new RelationshipObject(RelationshipTypeEnum::ToOne)); +$document->addRelationshipObject('baf', new RelationshipObject(RelationshipTypeEnum::ToMany)); /** * sending the response diff --git a/examples/output.php b/examples/output.php index 0844c336..f6726e8d 100644 --- a/examples/output.php +++ b/examples/output.php @@ -1,7 +1,9 @@ '; $document->sendResponse($options); echo ''; -echo '

Also sends http status code ('.$document->getHttpStatusCode().') and headers: [Content-Type: '.Document::CONTENT_TYPE_OFFICIAL.']

'; +echo '

Also sends http status code ('.$document->getHttpStatusCode().') and headers: [Content-Type: '.ContentTypeEnum::Official->value.']

'; diff --git a/examples/profile.php b/examples/profile.php index 8b070b6b..82458551 100644 --- a/examples/profile.php +++ b/examples/profile.php @@ -1,7 +1,9 @@ Content-Type: '.$contentType.''.PHP_EOL; $options = [ diff --git a/examples/relationship_to_many_document.php b/examples/relationship_to_many_document.php index 1f02263a..f2a2af2a 100644 --- a/examples/relationship_to_many_document.php +++ b/examples/relationship_to_many_document.php @@ -1,5 +1,7 @@ setSelfLink('/articles/1/relationship/author', $meta=[], $level=Document::LEVEL_ROOT); +$relationshipDocument->setSelfLink('/articles/1/relationship/author', $meta=[], $level=DocumentLevelEnum::Root); $relationshipDocument->addLink('related', '/articles/1/author'); /** diff --git a/examples/relationships.php b/examples/relationships.php index bc25dfe4..6755f34d 100644 --- a/examples/relationships.php +++ b/examples/relationships.php @@ -1,7 +1,10 @@ addResource($friend1Resource); $relationshipObject->addResource($friend2Resource); @@ -65,7 +68,7 @@ * to-many relationship, different types */ -$relationshipObject = new RelationshipObject($type=RelationshipObject::TO_MANY); +$relationshipObject = new RelationshipObject($type=RelationshipTypeEnum::ToMany); $relationshipObject->addResource($ship1Resource); $relationshipObject->addResource($dockResource); diff --git a/examples/request_superglobals.php b/examples/request_superglobals.php index fff59921..cb93d06f 100644 --- a/examples/request_superglobals.php +++ b/examples/request_superglobals.php @@ -1,6 +1,8 @@ value; /** * parsing the request diff --git a/examples/resource_human_api.php b/examples/resource_human_api.php index 67ed6578..b9ae514d 100644 --- a/examples/resource_human_api.php +++ b/examples/resource_human_api.php @@ -1,5 +1,7 @@ id); -$selfResourceMeta = ['level' => Document::LEVEL_RESOURCE]; -$partnerMeta = ['level' => Document::LEVEL_RESOURCE]; -$redirectMeta = ['level' => Document::LEVEL_ROOT]; +$selfResourceMeta = ['level' => DocumentLevelEnum::Resource->name]; +$partnerMeta = ['level' => DocumentLevelEnum::Resource->name]; +$redirectMeta = ['level' => DocumentLevelEnum::Root->name]; $document->setSelfLink('/user/42', $selfResourceMeta); -$document->addLink('partner', '/user/1', $partnerMeta, $level=Document::LEVEL_RESOURCE); -$document->addLink('redirect', '/login', $redirectMeta, $level=Document::LEVEL_ROOT); +$document->addLink('partner', '/user/1', $partnerMeta, $level=DocumentLevelEnum::Resource); +$document->addLink('redirect', '/login', $redirectMeta, $level=DocumentLevelEnum::Root); /** * sending the response diff --git a/examples/resource_nested_relations.php b/examples/resource_nested_relations.php index b0418f32..e182a48b 100644 --- a/examples/resource_nested_relations.php +++ b/examples/resource_nested_relations.php @@ -1,5 +1,7 @@ setType('user'); $resource->setAttributesObject($attributes42); -$relationship = new RelationshipObject(RelationshipObject::TO_ONE); +$relationship = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationship->setResource($resource); $relationships = new RelationshipsObject(); $relationships->addRelationshipObject('friend', $relationship); diff --git a/examples/status_only.php b/examples/status_only.php index abcced8a..94439c01 100644 --- a/examples/status_only.php +++ b/examples/status_only.php @@ -1,5 +1,7 @@ ' + treatPhpDocTypesAsCertain: false strictRules: diff --git a/rector.php b/rector.php index 9556204e..de660fc6 100644 --- a/rector.php +++ b/rector.php @@ -3,6 +3,8 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\Php70\Rector\StmtsAwareInterface\IfIssetToCoalescingRector; +use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector; // @see https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview.md for more rules @@ -12,16 +14,23 @@ __DIR__ . '/tests', __DIR__ . '/examples', ]) - + ->withRules([ + DeclareStrictTypesRector::class, + ]) + ->withSkip([ + // better explicit readability + IfIssetToCoalescingRector::class, + ]) + // tab-based indenting ->withIndent(indentChar: "\t", indentSize: 1) - - // slowly increase php version + + // lowest supported php version ->withPhpSets(php82: true) - + // slowly increase levels ->withTypeCoverageLevel(1) ->withDeadCodeLevel(1) - + // @todo add `->withPreparedSets()` once on a higher level with other rules ; diff --git a/src/CollectionDocument.php b/src/CollectionDocument.php index ba7c458b..29f3d435 100644 --- a/src/CollectionDocument.php +++ b/src/CollectionDocument.php @@ -1,5 +1,7 @@ addResource()} to change that behavior - * - * @param ResourceInterface ...$resources - * @return CollectionDocument */ - public static function fromResources(ResourceInterface ...$resources) { + public static function fromResources(ResourceInterface ...$resources): self { $collectionDocument = new self(); foreach ($resources as $resource) { @@ -50,11 +49,9 @@ public static function fromResources(ResourceInterface ...$resources) { } /** - * @param string $type - * @param string|int $id - * @param array $attributes optional, if given a ResourceObject is added, otherwise a ResourceIdentifierObject is added + * @param array $attributes if given a ResourceObject is added, otherwise a ResourceIdentifierObject is added */ - public function add($type, $id, array $attributes=[]) { + public function add(string $type, string|int $id, array $attributes=[]): void { if ($attributes === []) { $this->addResource(new ResourceIdentifierObject($type, $id)); } @@ -63,7 +60,12 @@ public function add($type, $id, array $attributes=[]) { } } - public function setPaginationLinks($previousHref=null, $nextHref=null, $firstHref=null, $lastHref=null) { + public function setPaginationLinks( + ?string $previousHref=null, + ?string $nextHref=null, + ?string $firstHref=null, + ?string $lastHref=null, + ): void { if ($previousHref !== null) { $this->addLink('prev', $previousHref); } @@ -87,12 +89,11 @@ public function setPaginationLinks($previousHref=null, $nextHref=null, $firstHre * * adds included resources if found inside the resource's relationships, unless $options['includeContainedResources'] is set to false * - * @param ResourceInterface $resource - * @param array $options optional {@see CollectionDocument::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see CollectionDocument::$defaults} * * @throws InputException if the resource is empty */ - public function addResource(ResourceInterface $resource, array $options=[]) { + public function addResource(ResourceInterface $resource, array $options=[]): void { if ($resource->getResource()->isEmpty()) { throw new InputException('does not make sense to add empty resources to a collection'); } @@ -112,7 +113,7 @@ public function addResource(ResourceInterface $resource, array $options=[]) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = parent::toArray(); $array['data'] = []; @@ -127,7 +128,7 @@ public function toArray() { * ResourceContainerInterface */ - public function getContainedResources() { + public function getContainedResources(): array { return $this->resources; } } diff --git a/src/DataDocument.php b/src/DataDocument.php index 470fcefc..8d44270e 100644 --- a/src/DataDocument.php +++ b/src/DataDocument.php @@ -1,5 +1,7 @@ validator->claimUsedResourceIdentifier($resourceObject); @@ -58,7 +58,7 @@ public function addIncludedResourceObject(ResourceObject ...$resourceObjects) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = parent::toArray(); $array['data'] = null; diff --git a/src/Document.php b/src/Document.php index cd26fccd..e95a4cc4 100644 --- a/src/Document.php +++ b/src/Document.php @@ -1,7 +1,11 @@ Document::CONTENT_TYPE_OFFICIAL, + 'contentType' => ContentTypeEnum::Official, /** * overwrite the array to encode to json @@ -94,26 +87,18 @@ public function __construct() { */ /** - * @param string $key - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT + * if $meta is given, a LinkObject is added, otherwise a link string is added + * + * @param array $meta * - * @throws InputException if the $level is Document::LEVEL_JSONAPI, Document::LEVEL_RESOURCE, or unknown + * @throws InputException if the $level is not DocumentLevelEnum::Root */ - public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT) { - if ($level === Document::LEVEL_ROOT) { - $this->linkManagerAddLink($key, $href, $meta); - } - elseif ($level === Document::LEVEL_JSONAPI) { - throw new InputException('level "jsonapi" can not be used for links'); - } - elseif ($level === Document::LEVEL_RESOURCE) { - throw new InputException('level "resource" can only be set on a ResourceDocument'); - } - else { - throw new InputException('unknown level "'.$level.'"'); - } + public function addLink(string $key, ?string $href, array $meta=[], DocumentLevelEnum $level=DocumentLevelEnum::Root): void { + match ($level) { + DocumentLevelEnum::Root => $this->linkManagerAddLink($key, $href, $meta), + DocumentLevelEnum::Jsonapi => throw new InputException('level "jsonapi" can not be used for links'), + DocumentLevelEnum::Resource => throw new InputException('level "resource" can only be set on a ResourceDocument'), + }; } /** @@ -121,13 +106,11 @@ public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT * * @note a LinkObject is added when extensions or profiles are applied * - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_ROOT) { - if ($level === Document::LEVEL_ROOT && ($this->extensions !== [] || $this->profiles !== [])) { - $contentType = Converter::prepareContentType(Document::CONTENT_TYPE_OFFICIAL, $this->extensions, $this->profiles); + public function setSelfLink(string $href, array $meta=[], DocumentLevelEnum $level=DocumentLevelEnum::Root): void { + if ($level === DocumentLevelEnum::Root && ($this->extensions !== [] || $this->profiles !== [])) { + $contentType = Converter::prepareContentType(ContentTypeEnum::Official, $this->extensions, $this->profiles); $linkObject = new LinkObject($href, $meta); $linkObject->setMediaType($contentType); @@ -144,43 +127,38 @@ public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_ROOT) * * for example this could link to an OpenAPI or JSON Schema document * - * @note according to the spec, this can only be set to Document::LEVEL_ROOT + * @note according to the spec, this can only be set to DocumentLevelEnum::Root * - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setDescribedByLink($href, array $meta=[]) { - $this->addLink('describedby', $href, $meta, $level=Document::LEVEL_ROOT); + public function setDescribedByLink(string $href, array $meta=[]): void { + $this->addLink('describedby', $href, $meta, $level=DocumentLevelEnum::Root); } /** - * @param string $key - * @param mixed $value - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT - * * @throws InputException if the $level is unknown - * @throws InputException if the $level is Document::LEVEL_RESOURCE + * @throws InputException if the $level is DocumentLevelEnum::Resource */ - public function addMeta($key, $value, $level=Document::LEVEL_ROOT) { - if ($level === Document::LEVEL_ROOT) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value, DocumentLevelEnum $level=DocumentLevelEnum::Root): void { + if ($level === DocumentLevelEnum::Root) { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } $this->meta->add($key, $value); } - elseif ($level === Document::LEVEL_JSONAPI) { - if ($this->jsonapi === null) { + elseif ($level === DocumentLevelEnum::Jsonapi) { + if (isset($this->jsonapi) === false) { $this->setJsonapiObject(new JsonapiObject()); } $this->jsonapi->addMeta($key, $value); } - elseif ($level === Document::LEVEL_RESOURCE) { + elseif ($level === DocumentLevelEnum::Resource) { throw new InputException('level "resource" can only be set on a ResourceDocument'); } else { - throw new InputException('unknown level "'.$level.'"'); + throw new InputException('unknown level "'.$level->value.'"'); } } @@ -188,24 +166,18 @@ public function addMeta($key, $value, $level=Document::LEVEL_ROOT) { * spec api */ - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } - /** - * @param JsonapiObject $jsonapiObject - */ - public function setJsonapiObject(JsonapiObject $jsonapiObject) { + public function setJsonapiObject(JsonapiObject $jsonapiObject): void { $this->jsonapi = $jsonapiObject; } /** * hide that this api supports jsonapi, or which version it is using */ - public function unsetJsonapiObject() { + public function unsetJsonapiObject(): void { $this->jsonapi = null; } @@ -218,12 +190,10 @@ public function unsetJsonapiObject() { * * @see https://jsonapi.org/extensions/#extensions * - * @param ExtensionInterface $extension - * * @throws Exception if namespace uses illegal characters * @throws DuplicateException if namespace conflicts with another applied extension */ - public function applyExtension(ExtensionInterface $extension) { + public function applyExtension(ExtensionInterface $extension): void { $namespace = $extension->getNamespace(); if (strlen($namespace) < 1 || preg_match('{[^a-zA-Z0-9]}', $namespace) === 1) { throw new Exception('invalid namespace "'.$namespace.'"'); @@ -234,7 +204,7 @@ public function applyExtension(ExtensionInterface $extension) { $this->extensions[$namespace] = $extension; - if ($this->jsonapi !== null) { + if (isset($this->jsonapi)) { $this->jsonapi->addExtension($extension); } } @@ -247,13 +217,11 @@ public function applyExtension(ExtensionInterface $extension) { * however the $profile could have custom methods to help * * @see https://jsonapi.org/extensions/#profiles - * - * @param ProfileInterface $profile */ - public function applyProfile(ProfileInterface $profile) { + public function applyProfile(ProfileInterface $profile): void { $this->profiles[] = $profile; - if ($this->jsonapi !== null) { + if (isset($this->jsonapi)) { $this->jsonapi->addProfile($profile); } } @@ -262,7 +230,7 @@ public function applyProfile(ProfileInterface $profile) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -272,20 +240,20 @@ public function toArray() { $array = array_merge($array, $this->getExtensionMembers()); } - if ($this->jsonapi !== null && $this->jsonapi->isEmpty() === false) { + if (isset($this->jsonapi) && $this->jsonapi->isEmpty() === false) { $array['jsonapi'] = $this->jsonapi->toArray(); } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { $array['links'] = $this->links->toArray(); } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } return $array; } - public function toJson(array $options=[]) { + public function toJson(array $options=[]): string { $options = array_merge(self::$defaults, $options); $array = $options['array'] ?? $this->toArray(); @@ -306,7 +274,7 @@ public function toJson(array $options=[]) { return $json; } - public function sendResponse(array $options=[]) { + public function sendResponse(array $options=[]): void { $options = array_merge(self::$defaults, $options); if ($this->httpStatusCode === 204) { @@ -329,7 +297,7 @@ public function sendResponse(array $options=[]) { */ #[\ReturnTypeWillChange] - public function jsonSerialize() { + public function jsonSerialize(): array { return $this->toArray(); } } diff --git a/src/ErrorsDocument.php b/src/ErrorsDocument.php index 69163dbc..3e905b44 100644 --- a/src/ErrorsDocument.php +++ b/src/ErrorsDocument.php @@ -1,9 +1,10 @@ > */ + protected array $httpStatusCodes; + /** @var PHPStanTypeAlias_InternalOptions */ + protected static array $defaults = [ /** * add the trace of exceptions when adding exceptions * in some cases it might be handy to disable if traces are too big @@ -28,9 +29,6 @@ class ErrorsDocument extends Document { 'includeExceptionPrevious' => true, ]; - /** - * @param ?ErrorObject $errorObject optional - */ public function __construct(?ErrorObject $errorObject=null) { parent::__construct(); @@ -44,11 +42,9 @@ public function __construct(?ErrorObject $errorObject=null) { */ /** - * @param \Throwable $exception - * @param array $options optional {@see ErrorsDocument::$defaults} - * @return ErrorsDocument + * @param PHPStanTypeAlias_InternalOptions $options {@see ErrorsDocument::$defaults} */ - public static function fromException(\Throwable $exception, array $options=[]) { + public static function fromException(\Throwable $exception, array $options=[]): self { $options = array_merge(self::$defaults, $options); $errorsDocument = new self(); @@ -62,10 +58,9 @@ public static function fromException(\Throwable $exception, array $options=[]) { * * recursively adds multiple ErrorObjects if $exception carries a ->getPrevious() * - * @param \Throwable $exception - * @param array $options optional {@see ErrorsDocument::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ErrorsDocument::$defaults} */ - public function addException(\Throwable $exception, array $options=[]) { + public function addException(\Throwable $exception, array $options=[]): void { $options = array_merge(self::$defaults, $options); $this->addErrorObject(ErrorObject::fromException($exception, $options)); @@ -82,11 +77,17 @@ public function addException(\Throwable $exception, array $options=[]) { /** * @param string|int $genericCode developer-friendly code of the generic type of error * @param string $genericTitle human-friendly title of the generic type of error - * @param string $specificDetails optional, human-friendly explanation of the specific error - * @param string $specificAboutLink optional, human-friendly explanation of the specific error - * @param string $genericTypeLink optional, human-friendly explanation of the generic type of error + * @param string $specificDetails human-friendly explanation of the specific error + * @param string $specificAboutLink human-friendly explanation of the specific error + * @param string $genericTypeLink human-friendly explanation of the generic type of error */ - public function add($genericCode, $genericTitle, $specificDetails=null, $specificAboutLink=null, $genericTypeLink=null) { + public function add( + string|int $genericCode, + string $genericTitle, + ?string $specificDetails=null, + ?string $specificAboutLink=null, + ?string $genericTypeLink=null, + ): void { $errorObject = new ErrorObject($genericCode, $genericTitle, $specificDetails, $specificAboutLink, $genericTypeLink); $this->addErrorObject($errorObject); @@ -98,10 +99,8 @@ public function add($genericCode, $genericTitle, $specificDetails=null, $specifi /** * @note also defines the http status code of the document if the ErrorObject has it defined - * - * @param ErrorObject $errorObject */ - public function addErrorObject(ErrorObject $errorObject) { + public function addErrorObject(ErrorObject $errorObject): void { $this->errors[] = $errorObject; if ($errorObject->hasHttpStatusCode()) { @@ -113,7 +112,7 @@ public function addErrorObject(ErrorObject $errorObject) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = parent::toArray(); $array['errors'] = []; @@ -134,11 +133,8 @@ public function toArray() { /** * @internal - * - * @param string|int $httpStatusCode - * @return int */ - protected function determineHttpStatusCode($httpStatusCode) { + protected function determineHttpStatusCode(string|int $httpStatusCode): int { // add the new code $category = substr((string) $httpStatusCode, 0, 1); $this->httpStatusCodes[$category][$httpStatusCode] = true; diff --git a/src/MetaDocument.php b/src/MetaDocument.php index 299ad201..22a18160 100644 --- a/src/MetaDocument.php +++ b/src/MetaDocument.php @@ -1,8 +1,11 @@ $meta */ - public static function fromArray(array $meta) { + public static function fromArray(array $meta): self { $metaDocument = new self(); $metaDocument->setMetaObject(MetaObject::fromArray($meta)); @@ -27,10 +29,9 @@ public static function fromArray(array $meta) { } /** - * @param object $meta - * @return MetaDocument + * @param object $meta */ - public static function fromObject($meta) { + public static function fromObject(object $meta): self { $array = Converter::objectToArray($meta); return self::fromArray($array); @@ -38,12 +39,8 @@ public static function fromObject($meta) { /** * wrapper for Document::addMeta() to the primary data of this document available via `add()` - * - * @param string $key - * @param mixed $value - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT */ - public function add($key, $value, $level=Document::LEVEL_ROOT) { + public function add(string $key, mixed $value, DocumentLevelEnum $level=DocumentLevelEnum::Root): void { parent::addMeta($key, $value, $level); } @@ -55,7 +52,7 @@ public function add($key, $value, $level=Document::LEVEL_ROOT) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = parent::toArray(); // force meta to be set, and be an object when converting to json diff --git a/src/ResourceDocument.php b/src/ResourceDocument.php index ff7ebca2..e4da6f13 100644 --- a/src/ResourceDocument.php +++ b/src/ResourceDocument.php @@ -1,10 +1,13 @@ setPrimaryResource() if not passing them during construction - * - * @param string $type optional - * @param string|int $id optional */ - public function __construct($type=null, $id=null) { + public function __construct(?string $type=null, string|int|null $id=null) { parent::__construct(); $this->setPrimaryResource(new ResourceObject($type, $id)); @@ -52,13 +51,14 @@ public function __construct($type=null, $id=null) { */ /** - * @param array $attributes - * @param string $type optional - * @param string|int $id optional - * @param array $options optional {@see ResourceDocument::$defaults} {@see ResourceObject::$defaults} - * @return ResourceDocument + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} {@see ResourceObject::$defaults} */ - public static function fromArray(array $attributes, $type=null, $id=null, array $options=[]) { + public static function fromArray( + array $attributes, + ?string $type=null, + string|int|null $id=null, + array $options=[], + ): self { $resourceDocument = new self(); $resourceDocument->setPrimaryResource(ResourceObject::fromArray($attributes, $type, $id, $options), $options); @@ -66,13 +66,14 @@ public static function fromArray(array $attributes, $type=null, $id=null, array } /** - * @param object $attributes - * @param string $type optional - * @param string|int $id optional - * @param array $options optional {@see ResourceDocument::$defaults} - * @return ResourceDocument + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} */ - public static function fromObject($attributes, $type=null, $id=null, array $options=[]) { + public static function fromObject( + object $attributes, + ?string $type=null, + string|int|null $id=null, + array $options=[], + ): self { $array = Converter::objectToArray($attributes); return self::fromArray($array, $type, $id, $options); @@ -81,11 +82,10 @@ public static function fromObject($attributes, $type=null, $id=null, array $opti /** * add key-value pairs to the resource's attributes * - * @param string $key - * @param mixed $value objects will be converted using `get_object_vars()` - * @param array $options optional {@see ResourceDocument::$defaults} + * @param mixed $value objects will be converted using `get_object_vars()` + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} */ - public function add($key, $value, array $options=[]) { + public function add(string $key, mixed $value, array $options=[]): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } @@ -98,13 +98,18 @@ public function add($key, $value, array $options=[]) { * * adds included resources if found inside the relation, unless $options['includeContainedResources'] is set to false * - * @param string $key - * @param mixed $relation ResourceInterface | ResourceInterface[] | CollectionDocument - * @param array $links optional - * @param array $meta optional - * @param array $options optional {@see ResourceDocument::$defaults} + * @param CollectionDocument|ResourceInterface|ResourceInterface[]|null $relation + * @param array $links + * @param array $meta + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} */ - public function addRelationship($key, $relation, array $links=[], array $meta=[], array $options=[]) { + public function addRelationship( + string $key, + array|CollectionDocument|ResourceInterface|null $relation, + array $links=[], + array $meta=[], + array $options=[], + ): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } @@ -119,17 +124,16 @@ public function addRelationship($key, $relation, array $links=[], array $meta=[] } /** - * @param string $key - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT + * if $meta is given, a LinkObject is added, otherwise a link string is added + * + * @param array $meta */ - public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT) { + public function addLink(string $key, ?string $href, array $meta=[], DocumentLevelEnum $level=DocumentLevelEnum::Root): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } - if ($level === Document::LEVEL_RESOURCE) { + if ($level === DocumentLevelEnum::Resource) { $this->resource->addLink($key, $href, $meta); } else { @@ -140,15 +144,14 @@ public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT /** * set the self link on the resource * - * @param string $href - * @param array $meta optional + * @param array $meta */ - public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_RESOURCE) { + public function setSelfLink(string $href, array $meta=[], DocumentLevelEnum $level=DocumentLevelEnum::Resource): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } - if ($level === Document::LEVEL_RESOURCE) { + if ($level === DocumentLevelEnum::Resource) { $this->resource->setSelfLink($href, $meta); } else { @@ -156,13 +159,8 @@ public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_RESOUR } } - /** - * @param string $key - * @param mixed $value - * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT - */ - public function addMeta($key, $value, $level=Document::LEVEL_ROOT) { - if ($level === Document::LEVEL_RESOURCE) { + public function addMeta(string $key, mixed $value, DocumentLevelEnum $level=DocumentLevelEnum::Root): void { + if ($level === DocumentLevelEnum::Resource) { $this->resource->addMeta($key, $value); } else { @@ -174,32 +172,28 @@ public function addMeta($key, $value, $level=Document::LEVEL_ROOT) { * wrapping ResourceObject spec api */ - /** - * @param string $type - */ - public function setType($type) { + public function setType(string $type): void { $this->resource->setType($type); } /** - * @param string|int $id will be casted to a string + * int $id will be casted to a string */ - public function setId($id) { + public function setId(string|int $id): void { $this->resource->setId($id); } /** - * @param string|int $localId will be casted to a string + * int $localId will be casted to a string */ - public function setLocalId($localId) { + public function setLocalId(string|int $localId): void { $this->resource->setLocalId($localId); } /** - * @param AttributesObject $attributesObject - * @param array $options optional {@see ResourceObject::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public function setAttributesObject(AttributesObject $attributesObject, array $options=[]) { + public function setAttributesObject(AttributesObject $attributesObject, array $options=[]): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } @@ -212,11 +206,9 @@ public function setAttributesObject(AttributesObject $attributesObject, array $o * * adds included resources if found inside the RelationshipObject, unless $options['includeContainedResources'] is set to false * - * @param string $key - * @param RelationshipObject $relationshipObject - * @param array $options optional {@see ResourceDocument::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} */ - public function addRelationshipObject($key, RelationshipObject $relationshipObject, array $options=[]) { + public function addRelationshipObject(string $key, RelationshipObject $relationshipObject, array $options=[]): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } @@ -235,10 +227,9 @@ public function addRelationshipObject($key, RelationshipObject $relationshipObje * * adds included resources if found inside the RelationshipObjects inside the RelationshipsObject, unless $options['includeContainedResources'] is set to false * - * @param RelationshipsObject $relationshipsObject - * @param array $options optional {@see ResourceDocument::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} */ - public function setRelationshipsObject(RelationshipsObject $relationshipsObject, array $options=[]) { + public function setRelationshipsObject(RelationshipsObject $relationshipsObject, array $options=[]): void { if ($this->resource instanceof ResourceObject === false) { throw new Exception('the resource is an identifier-only object'); } @@ -261,12 +252,11 @@ public function setRelationshipsObject(RelationshipsObject $relationshipsObject, * * adds included resources if found inside the resource's relationships, unless $options['includeContainedResources'] is set to false * - * @param ResourceInterface $resource - * @param array $options optional {@see ResourceDocument::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceDocument::$defaults} * * @throws InputException if the $resource is a ResourceDocument itself */ - public function setPrimaryResource(ResourceInterface $resource, array $options=[]) { + public function setPrimaryResource(ResourceInterface $resource, array $options=[]): void { if ($resource instanceof ResourceDocument) { throw new InputException('does not make sense to set a document inside a document, use ResourceObject or ResourceIdentifierObject instead'); } @@ -290,11 +280,11 @@ public function setPrimaryResource(ResourceInterface $resource, array $options=[ * DocumentInterface */ - public function toArray() { + public function toArray(): array { $array = parent::toArray(); $array['data'] = null; - if ($this->resource !== null && $this->resource->isEmpty() === false) { + if ($this->resource->isEmpty() === false) { $array['data'] = $this->resource->toArray(); } @@ -305,15 +295,15 @@ public function toArray() { * HasAttributesInterface */ - public function addAttribute($key, $value, array $options=[]) { - return $this->add($key, $value); + public function addAttribute(string $key, mixed $value, array $options=[]): void { + $this->add($key, $value); } /** * ResourceInterface */ - public function getResource($identifierOnly=false) { + public function getResource(bool $identifierOnly=false): ResourceIdentifierObject|ResourceObject { return $this->resource->getResource($identifierOnly); } } diff --git a/src/enums/ContentTypeEnum.php b/src/enums/ContentTypeEnum.php new file mode 100644 index 00000000..a3d23d11 --- /dev/null +++ b/src/enums/ContentTypeEnum.php @@ -0,0 +1,11 @@ +value; +} diff --git a/src/enums/ObjectContainerEnum.php b/src/enums/ObjectContainerEnum.php new file mode 100644 index 00000000..d2258c02 --- /dev/null +++ b/src/enums/ObjectContainerEnum.php @@ -0,0 +1,16 @@ +results = array_merge($this->results, $resources); } @@ -39,7 +40,7 @@ public function addResults(ResourceInterface ...$resources) { * DocumentInterface */ - public function toArray() { + public function toArray(): array { $results = []; foreach ($this->results as $result) { $results[] = [ diff --git a/src/extensions/AtomicOperationsExtension.php b/src/extensions/AtomicOperationsExtension.php index 6b6cffd4..f5f3f86b 100644 --- a/src/extensions/AtomicOperationsExtension.php +++ b/src/extensions/AtomicOperationsExtension.php @@ -1,5 +1,7 @@ */ + protected array $atMembers = []; /** * human api @@ -17,11 +19,7 @@ trait AtMemberManager { * spec api */ - /** - * @param string $key - * @param mixed $value - */ - public function addAtMember($key, $value) { + public function addAtMember(string $key, mixed $value): void { if (str_starts_with($key, '@')) { $key = substr($key, 1); } @@ -41,19 +39,17 @@ public function addAtMember($key, $value) { /** * @internal - * - * @return boolean */ - public function hasAtMembers() { + public function hasAtMembers(): bool { return ($this->atMembers !== []); } /** * @internal * - * @return array + * @return array */ - public function getAtMembers() { + public function getAtMembers(): array { return $this->atMembers; } } diff --git a/src/helpers/Converter.php b/src/helpers/Converter.php index 336d4a80..b0c0edd3 100644 --- a/src/helpers/Converter.php +++ b/src/helpers/Converter.php @@ -1,7 +1,10 @@ toArray(); } @@ -24,11 +23,8 @@ public static function objectToArray($object) { /** * @see https://stackoverflow.com/questions/7593969/regex-to-split-camelcase-or-titlecase-advanced/7599674#7599674 - * - * @param string $camelCase - * @return string */ - public static function camelCaseToWords($camelCase) { + public static function camelCaseToWords(string $camelCase): string { $parts = preg_split('/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/', $camelCase); return implode(' ', $parts); @@ -37,12 +33,12 @@ public static function camelCaseToWords($camelCase) { /** * generates the value for a content type header, with extensions and profiles merged in if available * - * @param string $contentType - * @param ExtensionInterface[] $extensions - * @param ProfileInterface[] $profiles - * @return string + * @param ExtensionInterface[] $extensions + * @param ProfileInterface[] $profiles */ - public static function prepareContentType($contentType, array $extensions, array $profiles) { + public static function prepareContentType(ContentTypeEnum $contentType, array $extensions, array $profiles): string { + $contentType = $contentType->value; + if ($extensions !== []) { $extensionLinks = []; foreach ($extensions as $extension) { diff --git a/src/helpers/ExtensionMemberManager.php b/src/helpers/ExtensionMemberManager.php index 1bfd257a..7d9c2c9a 100644 --- a/src/helpers/ExtensionMemberManager.php +++ b/src/helpers/ExtensionMemberManager.php @@ -1,5 +1,7 @@ */ + protected array $extensionMembers = []; /** * human api @@ -18,12 +20,7 @@ trait ExtensionMemberManager { * spec api */ - /** - * @param ExtensionInterface $extension - * @param string $key - * @param mixed $value - */ - public function addExtensionMember(ExtensionInterface $extension, $key, $value) { + public function addExtensionMember(ExtensionInterface $extension, string $key, mixed $value): void { $namespace = $extension->getNamespace(); if (str_starts_with($key, $namespace.':')) { @@ -45,19 +42,17 @@ public function addExtensionMember(ExtensionInterface $extension, $key, $value) /** * @internal - * - * @return boolean */ - public function hasExtensionMembers() { + public function hasExtensionMembers(): bool { return ($this->extensionMembers !== []); } /** * @internal * - * @return array + * @return array */ - public function getExtensionMembers() { + public function getExtensionMembers(): array { return $this->extensionMembers; } } diff --git a/src/helpers/HttpStatusCodeManager.php b/src/helpers/HttpStatusCodeManager.php index 7c051b45..67af3697 100644 --- a/src/helpers/HttpStatusCodeManager.php +++ b/src/helpers/HttpStatusCodeManager.php @@ -1,24 +1,23 @@ httpStatusCode !== null); + public function hasHttpStatusCode(): bool { + return isset($this->httpStatusCode); } /** * @internal - * - * @return int */ - public function getHttpStatusCode() { + public function getHttpStatusCode(): int { return $this->httpStatusCode; } } diff --git a/src/helpers/LinksManager.php b/src/helpers/LinksManager.php index 0fa10c92..514302e5 100644 --- a/src/helpers/LinksManager.php +++ b/src/helpers/LinksManager.php @@ -1,13 +1,14 @@ $meta */ - public function addLink($key, $href, array $meta=[]) { + public function addLink(string $key, ?string $href, array $meta=[]): void { $this->ensureLinksObject(); $this->links->add($key, $href, $meta); } @@ -31,21 +32,16 @@ public function addLink($key, $href, array $meta=[]) { /** * set a key containing a LinkObject - * - * @param string $key - * @param LinkObject $linkObject */ - public function addLinkObject($key, LinkObject $linkObject) { + public function addLinkObject(string $key, LinkObject $linkObject): void { $this->ensureLinksObject(); $this->links->addLinkObject($key, $linkObject); } /** * set a LinksObject containing all links - * - * @param LinksObject $linksObject */ - public function setLinksObject(LinksObject $linksObject) { + public function setLinksObject(LinksObject $linksObject): void { $this->links = $linksObject; } @@ -56,8 +52,23 @@ public function setLinksObject(LinksObject $linksObject) { /** * @internal */ - private function ensureLinksObject() { - if ($this->links === null) { + protected function hasLinks(): bool { + if (isset($this->links) === false) { + return false; + } + + if ($this->links->isEmpty()) { + return false; + } + + return true; + } + + /** + * @internal + */ + private function ensureLinksObject(): void { + if (isset($this->links) === false) { $this->setLinksObject(new LinksObject()); } } diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index b672ff7d..3348821c 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -1,17 +1,17 @@ > $queryParameters all query parameters defined by the specification + * @param array $document the request jsonapi document */ public function __construct( - private $selfLink='', - private array $queryParameters=[], - private array $document=[], + private readonly string $selfLink='', + private readonly array $queryParameters=[], + private readonly array $document=[], ) {} - /** - * @return self - */ - public static function fromSuperglobals() { + public static function fromSuperglobals(): self { $selfLink = ''; if (isset($_SERVER['REQUEST_SCHEME']) && isset($_SERVER['HTTP_HOST']) && isset($_SERVER['REQUEST_URI'])) { $selfLink = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; @@ -49,8 +46,8 @@ public static function fromSuperglobals() { $document = $_POST; if ($document === [] && isset($_SERVER['CONTENT_TYPE'])) { - $documentIsJsonapi = (str_contains((string) $_SERVER['CONTENT_TYPE'], Document::CONTENT_TYPE_OFFICIAL)); - $documentIsJson = (str_contains((string) $_SERVER['CONTENT_TYPE'], Document::CONTENT_TYPE_DEBUG)); + $documentIsJsonapi = (str_contains((string) $_SERVER['CONTENT_TYPE'], ContentTypeEnum::Official->value)); + $documentIsJson = (str_contains((string) $_SERVER['CONTENT_TYPE'], ContentTypeEnum::Debug->value)); if ($documentIsJsonapi || $documentIsJson) { $document = json_decode(file_get_contents('php://input'), true); @@ -64,11 +61,7 @@ public static function fromSuperglobals() { return new self($selfLink, $queryParameters, $document); } - /** - * @param ServerRequestInterface|RequestInterface $request - * @return self - */ - public static function fromPsrRequest(RequestInterface $request) { + public static function fromPsrRequest(ServerRequestInterface|RequestInterface $request): self { $selfLink = (string) $request->getUri(); if ($request instanceof ServerRequestInterface) { @@ -97,17 +90,12 @@ public static function fromPsrRequest(RequestInterface $request) { * the full link used to make this request * * this is not a bare self link of a resource and includes query parameters if used - * - * @return string */ - public function getSelfLink() { + public function getSelfLink(): string { return $this->selfLink; } - /** - * @return boolean - */ - public function hasIncludePaths() { + public function hasIncludePaths(): bool { return isset($this->queryParameters['include']); } @@ -117,10 +105,10 @@ public function hasIncludePaths() { * the nested format allows easier processing on each step of the chain * the raw format allows for custom processing * - * @param array $options optional {@see RequestParser::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see RequestParser::$defaults} * @return string[]|array */ - public function getIncludePaths(array $options=[]) { + public function getIncludePaths(array $options=[]): array { if ($this->queryParameters['include'] === '') { return []; } @@ -148,19 +136,14 @@ public function getIncludePaths(array $options=[]) { return $restructured; } - /** - * @param string $type - * @return boolean - */ - public function hasSparseFieldset($type) { + public function hasSparseFieldset(string $type): bool { return isset($this->queryParameters['fields'][$type]); } /** - * @param string $type * @return string[] */ - public function getSparseFieldset($type) { + public function getSparseFieldset(string $type): array { if ($this->queryParameters['fields'][$type] === '') { return []; } @@ -168,10 +151,7 @@ public function getSparseFieldset($type) { return explode(',', (string) $this->queryParameters['fields'][$type]); } - /** - * @return boolean - */ - public function hasSortFields() { + public function hasSortFields(): bool { return isset($this->queryParameters['sort']); } @@ -183,13 +163,13 @@ public function hasSortFields() { * * @todo return some kind of SortFieldObject * - * @param array $options optional {@see RequestParser::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see RequestParser::$defaults} * @return string[]|array */ - public function getSortFields(array $options=[]) { + public function getSortFields(array $options=[]): array { if ($this->queryParameters['sort'] === '') { return []; } @@ -203,11 +183,11 @@ public function getSortFields(array $options=[]) { $sort = []; foreach ($fields as $field) { - $order = RequestParser::SORT_ASCENDING; + $order = SortOrderEnum::Ascending; if (str_starts_with($field, '-')) { $field = substr($field, 1); - $order = RequestParser::SORT_DESCENDING; + $order = SortOrderEnum::Descending; } $sort[] = [ @@ -219,10 +199,7 @@ public function getSortFields(array $options=[]) { return $sort; } - /** - * @return boolean - */ - public function hasPagination() { + public function hasPagination(): bool { return isset($this->queryParameters['page']); } @@ -230,45 +207,32 @@ public function hasPagination() { * @todo return some kind of PaginatorObject which recognizes the strategy of pagination used * e.g. page-based, offset-based, cursor-based, or unknown * - * @return array + * @return array */ - public function getPagination() { + public function getPagination(): array { return $this->queryParameters['page']; } - /** - * @return boolean - */ - public function hasFilter() { + public function hasFilter(): bool { return isset($this->queryParameters['filter']); } /** - * @return array + * @return string|array */ - public function getFilter() { + public function getFilter(): string|array { return $this->queryParameters['filter']; } - /** - * @return boolean - */ - public function hasLocalId() { + public function hasLocalId(): bool { return (isset($this->document['data']['lid'])); } - /** - * @return string - */ - public function getLocalId() { + public function getLocalId(): string { return $this->document['data']['lid']; } - /** - * @param string $attributeName - * @return boolean - */ - public function hasAttribute($attributeName) { + public function hasAttribute(string $attributeName): bool { if (isset($this->document['data']['attributes']) === false) { return false; } @@ -279,19 +243,11 @@ public function hasAttribute($attributeName) { return true; } - /** - * @param string $attributeName - * @return mixed - */ - public function getAttribute($attributeName) { + public function getAttribute(string $attributeName): mixed { return $this->document['data']['attributes'][$attributeName]; } - /** - * @param string $relationshipName - * @return boolean - */ - public function hasRelationship($relationshipName) { + public function hasRelationship(string $relationshipName): bool { if (isset($this->document['data']['relationships']) === false) { return false; } @@ -305,18 +261,13 @@ public function hasRelationship($relationshipName) { /** * @todo return some kind of read-only ResourceIdentifierObject * - * @param string $relationshipName - * @return array + * @return ?array */ - public function getRelationship($relationshipName) { + public function getRelationship(string $relationshipName): ?array { return $this->document['data']['relationships'][$relationshipName]; } - /** - * @param string $metaKey - * @return boolean - */ - public function hasMeta($metaKey) { + public function hasMeta(string $metaKey): bool { if (isset($this->document['meta']) === false) { return false; } @@ -327,18 +278,14 @@ public function hasMeta($metaKey) { return true; } - /** - * @param string $metaKey - * @return mixed - */ - public function getMeta($metaKey) { + public function getMeta(string $metaKey): mixed { return $this->document['meta'][$metaKey]; } /** - * @return array + * @return array */ - public function getDocument() { + public function getDocument(): array { return $this->document; } } diff --git a/src/helpers/Validator.php b/src/helpers/Validator.php index 2c9e5737..0639a9c3 100644 --- a/src/helpers/Validator.php +++ b/src/helpers/Validator.php @@ -1,7 +1,10 @@ */ + protected array $usedFields = []; + /** @var array */ + protected array $usedResourceIdentifiers = []; + /** @var PHPStanTypeAlias_InternalOptions */ + protected static array $defaults = [ /** * blocks 'type' as a keyword inside attributes or relationships * the specification doesn't allow this as 'type' is already set at the root of a resource @@ -35,13 +32,12 @@ class Validator { * * @see https://jsonapi.org/format/1.1/#document-resource-object-fields * - * @param string[] $fieldNames - * @param string $objectContainer one of the Validator::OBJECT_CONTAINER_* constants - * @param array $options optional {@see Validator::$defaults} + * @param string[] $fieldNames + * @param PHPStanTypeAlias_InternalOptions $options {@see Validator::$defaults} * * @throws DuplicateException */ - public function claimUsedFields(array $fieldNames, $objectContainer, array $options=[]) { + public function claimUsedFields(array $fieldNames, ObjectContainerEnum $objectContainer, array $options=[]): void { $options = array_merge(self::$defaults, $options); foreach ($fieldNames as $fieldName) { @@ -56,18 +52,15 @@ public function claimUsedFields(array $fieldNames, $objectContainer, array $opti /** * @note this is not allowed by the specification */ - if ($this->usedFields[$fieldName] === Validator::OBJECT_CONTAINER_TYPE && $options['enforceTypeFieldNamespace'] === false) { + if ($this->usedFields[$fieldName] === ObjectContainerEnum::Type && $options['enforceTypeFieldNamespace'] === false) { continue; } - throw new DuplicateException('field name "'.$fieldName.'" already in use at "data.'.$this->usedFields[$fieldName].'"'); + throw new DuplicateException('field name "'.$fieldName.'" already in use at "data.'.$this->usedFields[$fieldName]->value.'"'); } } - /** - * @param string $objectContainerToClear one of the Validator::OBJECT_CONTAINER_* constants - */ - public function clearUsedFields($objectContainerToClear) { + public function clearUsedFields(ObjectContainerEnum $objectContainerToClear): void { foreach ($this->usedFields as $fieldName => $containerFound) { if ($containerFound !== $objectContainerToClear) { continue; @@ -78,12 +71,10 @@ public function clearUsedFields($objectContainerToClear) { } /** - * @param ResourceInterface $resource - * * @throws InputException if no type or id has been set on the resource * @throws DuplicateException if the combination of type and id has been set before */ - public function claimUsedResourceIdentifier(ResourceInterface $resource) { + public function claimUsedResourceIdentifier(ResourceInterface $resource): void { if ($resource->getResource()->hasIdentification() === false) { throw new InputException('can not validate resource without identifier, set type and id/lid first'); } @@ -102,11 +93,9 @@ public function claimUsedResourceIdentifier(ResourceInterface $resource) { * * @todo allow non-url safe chars * - * @param string $memberName - * * @throws InputException */ - public static function checkMemberName($memberName) { + public static function checkMemberName(string $memberName): void { $globallyAllowedCharacters = 'a-zA-Z0-9'; $generallyAllowedCharacters = $globallyAllowedCharacters.'_-'; @@ -129,11 +118,7 @@ public static function checkMemberName($memberName) { throw new InputException('invalid member name "'.$memberName.'"'); } - /** - * @param string|int $httpStatusCode - * @return boolean - */ - public static function checkHttpStatusCode($httpStatusCode) { + public static function checkHttpStatusCode(string|int $httpStatusCode): bool { $httpStatusCode = (int) $httpStatusCode; if ($httpStatusCode < 100) { diff --git a/src/interfaces/DocumentInterface.php b/src/interfaces/DocumentInterface.php index 6d3e3487..fc80a4a0 100644 --- a/src/interfaces/DocumentInterface.php +++ b/src/interfaces/DocumentInterface.php @@ -1,5 +1,7 @@ toJson()} * - * @return array + * @return array */ - public function toArray(); + public function toArray(): array; /** * generate json with the contents of the document, used by {@see ->sendResponse()} * - * @param array $options optional - * @return string json + * @param PHPStanTypeAlias_InternalOptions $options * * @throws Exception if generating json fails */ - public function toJson(array $options=[]); + public function toJson(array $options=[]): string; /** * send jsonapi response to the browser * * @note will set http status code and content type, and echo json * - * @param array $options optional + * @param PHPStanTypeAlias_InternalOptions $options */ - public function sendResponse(array $options=[]); + public function sendResponse(array $options=[]): void; } diff --git a/src/interfaces/ExtensionInterface.php b/src/interfaces/ExtensionInterface.php index 3c074978..1c8eae67 100644 --- a/src/interfaces/ExtensionInterface.php +++ b/src/interfaces/ExtensionInterface.php @@ -1,5 +1,7 @@ */ - public function getExtensionMembers(); + public function getExtensionMembers(): array; } diff --git a/src/interfaces/HasLinksInterface.php b/src/interfaces/HasLinksInterface.php index d867ada5..69ecb31c 100644 --- a/src/interfaces/HasLinksInterface.php +++ b/src/interfaces/HasLinksInterface.php @@ -13,20 +13,17 @@ interface HasLinksInterface { * * if $meta is given, a LinkObject is added, otherwise a link string is added * - * @param string $key - * @param string $href + * @param array $meta */ - public function addLink($key, $href, array $meta=[]); + public function addLink(string $key, ?string $href, array $meta=[]): void; /** * set a key containing a LinkObject - * - * @param string $key */ - public function addLinkObject($key, LinkObject $linkObject); + public function addLinkObject(string $key, LinkObject $linkObject): void; /** * set a LinksObject containing all links */ - public function setLinksObject(LinksObject $linksObject); + public function setLinksObject(LinksObject $linksObject): void; } diff --git a/src/interfaces/HasMetaInterface.php b/src/interfaces/HasMetaInterface.php index 52ac6b46..2c868397 100644 --- a/src/interfaces/HasMetaInterface.php +++ b/src/interfaces/HasMetaInterface.php @@ -5,9 +5,5 @@ namespace alsvanzelf\jsonapi\interfaces; interface HasMetaInterface { - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value); + public function addMeta(string $key, mixed $value): void; } diff --git a/src/interfaces/ObjectInterface.php b/src/interfaces/ObjectInterface.php index 76585401..0fc9c3a5 100644 --- a/src/interfaces/ObjectInterface.php +++ b/src/interfaces/ObjectInterface.php @@ -1,5 +1,7 @@ */ - public function toArray(); + public function toArray(): array; } diff --git a/src/interfaces/PaginableInterface.php b/src/interfaces/PaginableInterface.php index 2068244d..fbde5fb9 100644 --- a/src/interfaces/PaginableInterface.php +++ b/src/interfaces/PaginableInterface.php @@ -1,13 +1,14 @@ */ + protected array $attributes = []; /** * human api @@ -17,11 +19,8 @@ class AttributesObject extends AbstractObject { /** * @note if an `id` is set inside $attributes, it is removed from there * it is common to find it inside, and not doing so will cause an exception - * - * @param array $attributes - * @return AttributesObject */ - public static function fromArray(array $attributes) { + public static function fromArray(array $attributes): self { unset($attributes['id']); $attributesObject = new self(); @@ -33,11 +32,7 @@ public static function fromArray(array $attributes) { return $attributesObject; } - /** - * @param object $attributes - * @return AttributesObject - */ - public static function fromObject($attributes) { + public static function fromObject(object $attributes): self { $array = Converter::objectToArray($attributes); return self::fromArray($array); @@ -47,11 +42,7 @@ public static function fromObject($attributes) { * spec api */ - /** - * @param string $key - * @param mixed $value - */ - public function add($key, $value) { + public function add(string $key, mixed $value): void { Validator::checkMemberName($key); if (is_object($value)) { @@ -70,7 +61,7 @@ public function add($key, $value) { * * @return string[] */ - public function getKeys() { + public function getKeys(): array { return array_keys($this->attributes); } @@ -78,7 +69,7 @@ public function getKeys() { * ObjectInterface */ - public function isEmpty() { + public function isEmpty(): bool { if ($this->attributes !== []) { return false; } @@ -92,7 +83,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { diff --git a/src/objects/ErrorObject.php b/src/objects/ErrorObject.php index 92e3f17b..26e6ce73 100644 --- a/src/objects/ErrorObject.php +++ b/src/objects/ErrorObject.php @@ -1,9 +1,10 @@ setApplicationCode($genericCode); } @@ -63,11 +66,9 @@ public function __construct($genericCode=null, $genericTitle=null, $specificDeta */ /** - * @param \Throwable $exception - * @param array $options optional {@see ErrorObject::$defaults} - * @return ErrorObject + * @param PHPStanTypeAlias_InternalOptions $options {@see ErrorObject::$defaults} */ - public static function fromException(\Throwable $exception, array $options=[]) { + public static function fromException(\Throwable $exception, array $options=[]): self { $options = array_merge(self::$defaults, $options); $errorObject = new self(); @@ -117,12 +118,17 @@ public static function fromException(\Throwable $exception, array $options=[]) { /** * explain this particular occurence of the error in a human-friendly way * - * @param string $genericTitle title of the generic type of error - * @param string $specificDetails optional, explanation of the specific error - * @param string $specificAboutLink optional, explanation of the specific error - * @param string $genericTypeLink optional, explanation of the generic type of error + * @param string $genericTitle title of the generic type of error + * @param ?string $specificDetails explanation of the specific error + * @param ?string $specificAboutLink explanation of the specific error + * @param ?string $genericTypeLink explanation of the generic type of error */ - public function setHumanExplanation($genericTitle, $specificDetails=null, $specificAboutLink=null, $genericTypeLink=null) { + public function setHumanExplanation( + string $genericTitle, + ?string $specificDetails=null, + ?string $specificAboutLink=null, + ?string $genericTypeLink=null, + ): void { $this->setHumanTitle($genericTitle); if ($specificDetails !== null) { @@ -139,58 +145,47 @@ public function setHumanExplanation($genericTitle, $specificDetails=null, $speci /** * set the link about this specific occurence of the error, explained in a human-friendly way * - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setAboutLink($href, array $meta=[]) { + public function setAboutLink(string $href, array $meta=[]): void { $this->addLink('about', $href, $meta); } /** * set the link of the generic type of this error, explained in a human-friendly way * - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setTypeLink($href, array $meta=[]) { + public function setTypeLink(string $href, array $meta=[]): void { $this->addLink('type', $href, $meta); } /** * blame the json pointer from the request body causing this error + * e.g. "/data/attributes/title" or "/data" * * @see https://tools.ietf.org/html/rfc6901 - * - * @param string $pointer e.g. "/data/attributes/title" or "/data" */ - public function blameJsonPointer($pointer) { + public function blameJsonPointer(string $pointer): void { $this->addSource('pointer', $pointer); } /** * blame the query parameter from the request causing this error - * - * @param string $parameter */ - public function blameQueryParameter($parameter) { + public function blameQueryParameter(string $parameter): void { $this->addSource('parameter', $parameter); } /** * blame the header from the request causing this error - * - * @param string $headerName */ - public function blameHeader($headerName) { + public function blameHeader(string $headerName): void { $this->addSource('header', $headerName); } - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value): void { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } @@ -203,30 +198,27 @@ public function addMeta($key, $value) { /** * a unique identifier for this specific occurrence of the error - * - * @param string|int $id */ - public function setUniqueIdentifier($id) { + public function setUniqueIdentifier(string|int $id): void { $this->id = $id; } /** * a code expressing the generic type of this error * it should be application-specific and aimed at developers - * - * @param string|int $genericCode will be casted to a string + * ints will be casted to a string */ - public function setApplicationCode($genericCode) { + public function setApplicationCode(string|int $genericCode): void { $this->code = (string) $genericCode; } /** * add the source of the error * - * @param string $key {@see ->blameJsonPointer(), ->blameQueryParameter()} - * @param string $value + * @see ->blameJsonPointer() + * @see ->blameQueryParameter() */ - public function addSource($key, $value) { + public function addSource(string $key, string $value): void { Validator::checkMemberName($key); $this->source[$key] = $value; @@ -234,26 +226,19 @@ public function addSource($key, $value) { /** * a short human-friendly explanation of the generic type of this error - * - * @param string $genericTitle */ - public function setHumanTitle($genericTitle) { + public function setHumanTitle(string $genericTitle): void { $this->title = $genericTitle; } /** * a human-friendly explanation of this specific occurrence of the error - * - * @param string $specificDetails */ - public function setHumanDetails($specificDetails) { + public function setHumanDetails(string $specificDetails): void { $this->detail = $specificDetails; } - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } @@ -261,29 +246,29 @@ public function setMetaObject(MetaObject $metaObject) { * ObjectInterface */ - public function isEmpty() { - if ($this->id !== null) { + public function isEmpty(): bool { + if (isset($this->id)) { return false; } if ($this->hasHttpStatusCode()) { return false; } - if ($this->code !== null) { + if (isset($this->code)) { return false; } - if ($this->title !== null) { + if (isset($this->title)) { return false; } - if ($this->detail !== null) { + if (isset($this->detail)) { return false; } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { return false; } if ($this->source !== []) { return false; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { return false; } if ($this->hasAtMembers()) { @@ -296,7 +281,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -305,28 +290,28 @@ public function toArray() { if ($this->hasExtensionMembers()) { $array = array_merge($array, $this->getExtensionMembers()); } - if ($this->id !== null) { + if (isset($this->id)) { $array['id'] = $this->id; } if ($this->hasHttpStatusCode()) { $array['status'] = (string) $this->getHttpStatusCode(); } - if ($this->code !== null) { + if (isset($this->code)) { $array['code'] = $this->code; } - if ($this->title !== null) { + if (isset($this->title)) { $array['title'] = $this->title; } - if ($this->detail !== null) { + if (isset($this->detail)) { $array['detail'] = $this->detail; } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { $array['links'] = $this->links->toArray(); } if ($this->source !== []) { $array['source'] = $this->source; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } diff --git a/src/objects/JsonapiObject.php b/src/objects/JsonapiObject.php index 3d581d97..f54d1aba 100644 --- a/src/objects/JsonapiObject.php +++ b/src/objects/JsonapiObject.php @@ -1,8 +1,11 @@ setVersion($version); } @@ -32,12 +30,8 @@ public function __construct($version=Document::JSONAPI_VERSION_LATEST) { * human api */ - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value): void { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } @@ -48,31 +42,19 @@ public function addMeta($key, $value) { * spec api */ - /** - * @param string $version - */ - public function setVersion($version) { + public function setVersion(JsonapiVersionEnum $version): void { $this->version = $version; } - /** - * @param ExtensionInterface $extension - */ - public function addExtension(ExtensionInterface $extension) { + public function addExtension(ExtensionInterface $extension): void { $this->extensions[] = $extension; } - /** - * @param ProfileInterface $profile - */ - public function addProfile(ProfileInterface $profile) { + public function addProfile(ProfileInterface $profile): void { $this->profiles[] = $profile; } - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } @@ -80,8 +62,8 @@ public function setMetaObject(MetaObject $metaObject) { * ObjectInterface */ - public function isEmpty() { - if ($this->version !== null) { + public function isEmpty(): bool { + if (isset($this->version)) { return false; } if ($this->extensions !== []) { @@ -90,7 +72,7 @@ public function isEmpty() { if ($this->profiles !== []) { return false; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { return false; } if ($this->hasAtMembers()) { @@ -103,7 +85,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -112,8 +94,8 @@ public function toArray() { if ($this->hasExtensionMembers()) { $array = array_merge($array, $this->getExtensionMembers()); } - if ($this->version !== null) { - $array['version'] = $this->version; + if (isset($this->version)) { + $array['version'] = $this->version->value; } if ($this->extensions !== []) { $array['ext'] = []; @@ -127,7 +109,7 @@ public function toArray() { $array['profile'][] = $profile->getOfficialLink(); } } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } diff --git a/src/objects/LinkObject.php b/src/objects/LinkObject.php index e7a06e0b..0c483bef 100644 --- a/src/objects/LinkObject.php +++ b/src/objects/LinkObject.php @@ -1,5 +1,7 @@ $meta */ - public function __construct($href=null, array $meta=[]) { + public function __construct(?string $href=null, array $meta=[]) { if ($href !== null) { $this->setHref($href); } @@ -39,17 +34,11 @@ public function __construct($href=null, array $meta=[]) { * human api */ - /** - * @param string $href - */ - public function setDescribedBy($href) { + public function setDescribedBy(string $href): void { $this->setDescribedByLinkObject(new LinkObject($href)); } - /** - * @param string $language - */ - public function addLanguage($language) { + public function addLanguage(string $language): void { if ($this->hreflang === []) { $this->setHreflang($language); } @@ -58,12 +47,8 @@ public function addLanguage($language) { } } - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value): void { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } @@ -74,56 +59,37 @@ public function addMeta($key, $value) { * spec api */ - /** - * @param string $href - */ - public function setHref($href) { + public function setHref(string $href): void { $this->href = $href; } /** * @todo validate according to https://tools.ietf.org/html/rfc8288#section-2.1 - * - * @param string $relationType */ - public function setRelationType($relationType) { + public function setRelationType(string $relationType): void { $this->rel = $relationType; } - /** - * @param LinkObject $describedBy - */ - public function setDescribedByLinkObject(LinkObject $describedBy) { + public function setDescribedByLinkObject(LinkObject $describedBy): void { $this->describedby = $describedBy; } - /** - * @param string $humanTitle - */ - public function setHumanTitle($humanTitle) { + public function setHumanTitle(string $humanTitle): void { $this->title = $humanTitle; } - /** - * @param string $mediaType - */ - public function setMediaType($mediaType) { + public function setMediaType(string $mediaType): void { $this->type = $mediaType; } /** * @todo validate according to https://tools.ietf.org/html/rfc5646 - * - * @param string ...$hreflang */ - public function setHreflang(...$hreflang) { + public function setHreflang(string ...$hreflang): void { $this->hreflang = $hreflang; } - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } @@ -131,26 +97,26 @@ public function setMetaObject(MetaObject $metaObject) { * ObjectInterface */ - public function isEmpty() { - if ($this->href !== null) { + public function isEmpty(): bool { + if (isset($this->href)) { return false; } - if ($this->rel !== null) { + if (isset($this->rel)) { return false; } - if ($this->title !== null) { + if (isset($this->title)) { return false; } - if ($this->type !== null) { + if (isset($this->type)) { return false; } if ($this->hreflang !== []) { return false; } - if ($this->describedby !== null && $this->describedby->isEmpty() === false) { + if (isset($this->describedby) && $this->describedby->isEmpty() === false) { return false; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { return false; } if ($this->hasAtMembers()) { @@ -163,7 +129,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -173,15 +139,16 @@ public function toArray() { $array = array_merge($array, $this->getExtensionMembers()); } - $array['href'] = $this->href; - - if ($this->rel !== null) { + if (isset($this->href)) { + $array['href'] = $this->href; + } + if (isset($this->rel)) { $array['rel'] = $this->rel; } - if ($this->title !== null) { + if (isset($this->title)) { $array['title'] = $this->title; } - if ($this->type !== null) { + if (isset($this->type)) { $array['type'] = $this->type; } if ($this->hreflang !== []) { @@ -192,10 +159,10 @@ public function toArray() { $array['hreflang'] = $this->hreflang; } } - if ($this->describedby !== null && $this->describedby->isEmpty() === false) { + if (isset($this->describedby) && $this->describedby->isEmpty() === false) { $array['describedby'] = $this->describedby->toArray(); } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } diff --git a/src/objects/LinksObject.php b/src/objects/LinksObject.php index bad61559..65385ef7 100644 --- a/src/objects/LinksObject.php +++ b/src/objects/LinksObject.php @@ -1,5 +1,7 @@ */ + protected array $links = []; /** * human api */ /** - * @param array $links key-value with values being href strings - * @return LinksObject + * @param array $links key-value with values being href strings */ - public static function fromArray(array $links) { + public static function fromArray(array $links): LinksObject { $linksObject = new self(); foreach ($links as $key => $href) { @@ -30,22 +31,16 @@ public static function fromArray(array $links) { return $linksObject; } - /** - * @param object $links - * @return LinksObject - */ - public static function fromObject($links) { + public static function fromObject(object $links): LinksObject { $array = Converter::objectToArray($links); return self::fromArray($array); } /** - * @param string $key - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function add($key, $href, array $meta=[]) { + public function add(string $key, ?string $href, array $meta=[]): void { if ($meta === []) { $this->addLinkString($key, $href); } @@ -59,12 +54,9 @@ public function add($key, $href, array $meta=[]) { */ /** - * @param string $key - * @param string $href - * * @throws DuplicateException if another link is already using that $key */ - public function addLinkString($key, $href) { + public function addLinkString(string $key, ?string $href): void { Validator::checkMemberName($key); if (isset($this->links[$key])) { @@ -75,12 +67,9 @@ public function addLinkString($key, $href) { } /** - * @param string $key - * @param LinkObject $linkObject - * * @throws DuplicateException if another link is already using that $key */ - public function addLinkObject($key, LinkObject $linkObject) { + public function addLinkObject(string $key, LinkObject $linkObject): void { Validator::checkMemberName($key); if (isset($this->links[$key])) { @@ -94,7 +83,7 @@ public function addLinkObject($key, LinkObject $linkObject) { * ObjectInterface */ - public function isEmpty() { + public function isEmpty(): bool { if ($this->links !== []) { return false; } @@ -108,7 +97,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { diff --git a/src/objects/MetaObject.php b/src/objects/MetaObject.php index e98a2c96..e52c5847 100644 --- a/src/objects/MetaObject.php +++ b/src/objects/MetaObject.php @@ -1,5 +1,7 @@ */ + protected array $meta = []; /** * human api */ /** - * @param array $meta - * @return MetaObject + * @param array $meta */ - public static function fromArray(array $meta) { + public static function fromArray(array $meta): self { $metaObject = new self(); foreach ($meta as $key => $value) { @@ -28,11 +29,7 @@ public static function fromArray(array $meta) { return $metaObject; } - /** - * @param object $meta - * @return MetaObject - */ - public static function fromObject($meta) { + public static function fromObject(object $meta): self { $array = Converter::objectToArray($meta); return self::fromArray($array); @@ -42,11 +39,7 @@ public static function fromObject($meta) { * spec api */ - /** - * @param string $key - * @param mixed $value - */ - public function add($key, $value) { + public function add(string $key, mixed $value): void { Validator::checkMemberName($key); if (is_object($value)) { @@ -60,7 +53,7 @@ public function add($key, $value) { * ObjectInterface */ - public function isEmpty() { + public function isEmpty(): bool { if ($this->meta !== []) { return false; } @@ -74,7 +67,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { diff --git a/src/objects/RelationshipObject.php b/src/objects/RelationshipObject.php index 6cb0efdb..2a4af1a0 100644 --- a/src/objects/RelationshipObject.php +++ b/src/objects/RelationshipObject.php @@ -1,8 +1,11 @@ type = $type; - } + public function __construct( + protected readonly RelationshipTypeEnum $type, + ) {} /** * human api @@ -50,14 +37,17 @@ public function __construct($type) { /** * create a RelationshipObject from mixed input * - * @param mixed $relation ResourceInterface | ResourceInterface[] | CollectionDocument - * @param array $links optional - * @param array $meta optional - * @return RelationshipObject + * @param CollectionDocument|ResourceInterface|ResourceInterface[]|null $relation + * @param array $links + * @param array $meta * * @throws InputException if $relation is not one of the supported formats */ - public static function fromAnything($relation, array $links=[], array $meta=[]) { + public static function fromAnything( + array|CollectionDocument|ResourceInterface|null $relation, + array $links=[], + array $meta=[], + ): self { if (is_array($relation)) { $relation = CollectionDocument::fromResources(...$relation); } @@ -69,7 +59,7 @@ public static function fromAnything($relation, array $links=[], array $meta=[]) $relationshipObject = self::fromCollectionDocument($relation, $links, $meta); } elseif ($relation === null) { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); } else { throw new InputException('unknown format of relation "'.gettype($relation).'"'); @@ -79,21 +69,21 @@ public static function fromAnything($relation, array $links=[], array $meta=[]) } /** - * @param ResourceInterface $resource - * @param array $links optional - * @param array $meta optional - * @param string $type optional, one of the RelationshipObject::TO_* constants, defaults to RelationshipObject::TO_ONE - * @return RelationshipObject + * @param array $links + * @param array $meta */ - public static function fromResource(ResourceInterface $resource, array $links=[], array $meta=[], $type=RelationshipObject::TO_ONE) { + public static function fromResource( + ResourceInterface $resource, + array $links=[], + array $meta=[], + RelationshipTypeEnum $type=RelationshipTypeEnum::ToOne, + ): self { $relationshipObject = new self($type); - if ($type === RelationshipObject::TO_ONE) { - $relationshipObject->setResource($resource); - } - elseif ($type === RelationshipObject::TO_MANY) { - $relationshipObject->addResource($resource); - } + match ($type) { + RelationshipTypeEnum::ToOne => $relationshipObject->setResource($resource), + RelationshipTypeEnum::ToMany => $relationshipObject->addResource($resource), + }; if ($links !== []) { $relationshipObject->setLinksObject(LinksObject::fromArray($links)); @@ -106,13 +96,11 @@ public static function fromResource(ResourceInterface $resource, array $links=[] } /** - * @param CollectionDocument $collectionDocument - * @param array $links optional - * @param array $meta optional - * @return RelationshipObject + * @param array $links + * @param array $meta */ - public static function fromCollectionDocument(CollectionDocument $collectionDocument, array $links=[], array $meta=[]) { - $relationshipObject = new self(RelationshipObject::TO_MANY); + public static function fromCollectionDocument(CollectionDocument $collectionDocument, array $links=[], array $meta=[]): self { + $relationshipObject = new self(RelationshipTypeEnum::ToMany); foreach ($collectionDocument->getContainedResources() as $resource) { $relationshipObject->addResource($resource); @@ -129,26 +117,29 @@ public static function fromCollectionDocument(CollectionDocument $collectionDocu } /** - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setSelfLink($href, array $meta=[]) { + public function setSelfLink(string $href, array $meta=[]): void { $this->addLink('self', $href, $meta); } /** - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setRelatedLink($href, array $meta=[]) { + public function setRelatedLink(string $href, array $meta=[]): void { $this->addLink('related', $href, $meta); } /** * @throws InputException if used on a to-one relationship */ - public function setPaginationLinks($previousHref=null, $nextHref=null, $firstHref=null, $lastHref=null) { - if ($this->type === RelationshipObject::TO_ONE) { + public function setPaginationLinks( + ?string $previousHref=null, + ?string $nextHref=null, + ?string $firstHref=null, + ?string $lastHref=null, + ): void { + if ($this->type === RelationshipTypeEnum::ToOne) { throw new InputException('can not add pagination links to a to-one relationship'); } @@ -166,12 +157,8 @@ public function setPaginationLinks($previousHref=null, $nextHref=null, $firstHre } } - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value): void { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } @@ -185,12 +172,10 @@ public function addMeta($key, $value) { /** * set the resource on a to-one relationship * - * @param ResourceInterface $resource - * * @throws InputException if used on a to-many relationship, use {@see ->addResource()} instead */ - public function setResource(ResourceInterface $resource) { - if ($this->type === RelationshipObject::TO_MANY) { + public function setResource(ResourceInterface $resource): void { + if ($this->type === RelationshipTypeEnum::ToMany) { throw new InputException('can not set a resource on a to-many relationship, use ->addResource()'); } @@ -200,22 +185,17 @@ public function setResource(ResourceInterface $resource) { /** * add a resource to a to-many relationship * - * @param ResourceInterface $resource - * * @throws InputException if used on a to-one relationship, use {@see ->setResource()} instead */ - public function addResource(ResourceInterface $resource) { - if ($this->type === RelationshipObject::TO_ONE) { + public function addResource(ResourceInterface $resource): void { + if ($this->type === RelationshipTypeEnum::ToOne) { throw new InputException('can not add a resource to a to-one relationship, use ->setResource()'); } $this->resources[] = $resource; } - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } @@ -227,43 +207,42 @@ public function setMetaObject(MetaObject $metaObject) { * whether or not the $otherResource is (one of) the resource(s) inside the relationship * * @internal - * - * @param ResourceInterface $otherResource - * @return boolean */ - public function hasResource(ResourceInterface $otherResource) { + public function hasResource(ResourceInterface $otherResource): bool { if ($this->isEmpty()) { return false; } - if ($this->type === RelationshipObject::TO_ONE) { - return $this->resource->getResource()->equals($otherResource->getResource()); - } - if ($this->type === RelationshipObject::TO_MANY) { - foreach ($this->resources as $ownResource) { - if ($ownResource->getResource()->equals($otherResource->getResource())) { - return true; + + switch ($this->type) { + case RelationshipTypeEnum::ToOne: + return $this->resource->getResource()->equals($otherResource->getResource()); + + case RelationshipTypeEnum::ToMany: + foreach ($this->resources as $ownResource) { + if ($ownResource->getResource()->equals($otherResource->getResource())) { + return true; + } } - } + + return false; } - - return false; } /** * ObjectInterface */ - public function isEmpty() { - if ($this->type === RelationshipObject::TO_ONE && $this->resource !== null) { + public function isEmpty(): bool { + if ($this->type === RelationshipTypeEnum::ToOne && isset($this->resource)) { return false; } - if ($this->type === RelationshipObject::TO_MANY && $this->resources !== []) { + if ($this->type === RelationshipTypeEnum::ToMany && $this->resources !== []) { return false; } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { return false; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { return false; } if ($this->hasAtMembers()) { @@ -276,7 +255,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -286,22 +265,22 @@ public function toArray() { $array = array_merge($array, $this->getExtensionMembers()); } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { $array['links'] = $this->links->toArray(); } - if ($this->type === RelationshipObject::TO_ONE) { + if ($this->type === RelationshipTypeEnum::ToOne) { $array['data'] = null; - if ($this->resource !== null) { + if (isset($this->resource)) { $array['data'] = $this->resource->getResource($identifierOnly=true)->toArray(); } } - if ($this->type === RelationshipObject::TO_MANY) { + if ($this->type === RelationshipTypeEnum::ToMany) { $array['data'] = []; foreach ($this->resources as $resource) { $array['data'][] = $resource->getResource($identifierOnly=true)->toArray(); } } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } @@ -312,12 +291,12 @@ public function toArray() { * RecursiveResourceContainerInterface */ - public function getNestedContainedResourceObjects() { + public function getNestedContainedResourceObjects(): array { if ($this->isEmpty()) { return []; } - $resources = ($this->type === RelationshipObject::TO_ONE) ? [$this->resource] : $this->resources; + $resources = ($this->type === RelationshipTypeEnum::ToOne) ? [$this->resource] : $this->resources; $resourceObjects = []; foreach ($resources as $resource) { diff --git a/src/objects/RelationshipsObject.php b/src/objects/RelationshipsObject.php index 8c8d0be7..54edd3e0 100644 --- a/src/objects/RelationshipsObject.php +++ b/src/objects/RelationshipsObject.php @@ -1,10 +1,14 @@ $links + * @param array $meta */ - public function add($key, $relation, array $links=[], array $meta=[]) { + public function add( + string $key, + $relation, + array $links=[], + array $meta=[], + ): RelationshipObject { $relationshipObject = RelationshipObject::fromAnything($relation, $links, $meta); $this->addRelationshipObject($key, $relationshipObject); @@ -38,12 +45,9 @@ public function add($key, $relation, array $links=[], array $meta=[]) { */ /** - * @param string $key - * @param RelationshipObject $relationshipObject - * * @throws DuplicateException if another relationship is already using that $key */ - public function addRelationshipObject($key, RelationshipObject $relationshipObject) { + public function addRelationshipObject(string $key, RelationshipObject $relationshipObject): void { Validator::checkMemberName($key); if (isset($this->relationships[$key])) { @@ -62,7 +66,7 @@ public function addRelationshipObject($key, RelationshipObject $relationshipObje * * @return string[] */ - public function getKeys() { + public function getKeys(): array { return array_keys($this->relationships); } @@ -70,7 +74,7 @@ public function getKeys() { * ObjectInterface */ - public function isEmpty() { + public function isEmpty(): bool { if ($this->relationships !== []) { return false; } @@ -84,7 +88,7 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; if ($this->hasAtMembers()) { @@ -105,7 +109,7 @@ public function toArray() { * RecursiveResourceContainerInterface */ - public function getNestedContainedResourceObjects() { + public function getNestedContainedResourceObjects(): array { $resourceObjects = []; foreach ($this->relationships as $relationship) { diff --git a/src/objects/ResourceIdentifierObject.php b/src/objects/ResourceIdentifierObject.php index 715456d4..22d35e9b 100644 --- a/src/objects/ResourceIdentifierObject.php +++ b/src/objects/ResourceIdentifierObject.php @@ -1,9 +1,13 @@ setType() and ->setId() if not passing them during construction - * - * @param string $type optional - * @param string|int $id optional */ - public function __construct($type=null, $id=null) { + public function __construct(?string $type=null, string|int|null $id=null) { $this->validator = new Validator(); if ($type !== null) { @@ -41,21 +37,17 @@ public function __construct($type=null, $id=null) { } // always mark as used, as these keys are reserved - $this->validator->claimUsedFields($fieldNames=['type'], Validator::OBJECT_CONTAINER_TYPE); - $this->validator->claimUsedFields($fieldNames=['id'], Validator::OBJECT_CONTAINER_ID); - $this->validator->claimUsedFields($fieldNames=['lid'], Validator::OBJECT_CONTAINER_LID); + $this->validator->claimUsedFields($fieldNames=['type'], ObjectContainerEnum::Type); + $this->validator->claimUsedFields($fieldNames=['id'], ObjectContainerEnum::Id); + $this->validator->claimUsedFields($fieldNames=['lid'], ObjectContainerEnum::Lid); } /** * human api */ - /** - * @param string $key - * @param mixed $value - */ - public function addMeta($key, $value) { - if ($this->meta === null) { + public function addMeta(string $key, mixed $value): void { + if (isset($this->meta) === false) { $this->setMetaObject(new MetaObject()); } @@ -66,20 +58,17 @@ public function addMeta($key, $value) { * spec api */ - /** - * @param string $type - */ - public function setType($type) { + public function setType(string $type): void { $this->type = $type; } /** - * @param string|int $id will be casted to a string + * int $id will be casted to a string * * @throws DuplicateException if localId is already set */ - public function setId($id) { - if ($this->lid !== null) { + public function setId(string|int $id): void { + if (isset($this->lid)) { throw new DuplicateException('id is not allowed when localId is already set'); } @@ -91,22 +80,19 @@ public function setId($id) { * * @note this should not be used to send back from the server to the client * - * @param string|int $localId will be casted to a string + * int $localId will be casted to a string * * @throws DuplicateException if normal id is already set */ - public function setLocalId($localId) { - if ($this->id !== null) { + public function setLocalId(string|int $localId): void { + if (isset($this->id)) { throw new DuplicateException('localId is not allowed when id is already set'); } $this->lid = (string) $localId; } - /** - * @param MetaObject $metaObject - */ - public function setMetaObject(MetaObject $metaObject) { + public function setMetaObject(MetaObject $metaObject): void { $this->meta = $metaObject; } @@ -117,13 +103,16 @@ public function setMetaObject(MetaObject $metaObject) { /** * @internal * - * @param ResourceObject $resourceObject - * @return ResourceIdentifierObject + * @throws InputException if the $resourceoObject's type or id is not set yet */ - public static function fromResourceObject(ResourceObject $resourceObject) { + public static function fromResourceObject(ResourceObject $resourceObject): self { + if ($resourceObject->hasIdentification() === false) { + throw new InputException('resource has no identification yet<'); + } + $resourceIdentifierObject = new self($resourceObject->type, $resourceObject->primaryId()); - if ($resourceObject->meta !== null) { + if (isset($resourceObject->meta)) { $resourceIdentifierObject->setMetaObject($resourceObject->meta); } @@ -133,12 +122,9 @@ public static function fromResourceObject(ResourceObject $resourceObject) { /** * @internal * - * @param ResourceInterface $resource - * @return boolean - * * @throws Exception if one or both are missing identification */ - public function equals(ResourceInterface $resource) { + public function equals(ResourceInterface $resource): bool { if ($this->hasIdentification() === false || $resource->getResource()->hasIdentification() === false) { throw new Exception('can not compare resources if identification is missing'); } @@ -148,11 +134,17 @@ public function equals(ResourceInterface $resource) { /** * @internal - * - * @return boolean */ - public function hasIdentification() { - return ($this->type !== null && $this->primaryId() !== null); + public function hasIdentification(): bool { + if (isset($this->type) === false) { + return false; + } + + if (isset($this->id) === false && isset($this->lid) === false) { + return false; + } + + return true; } /** @@ -160,11 +152,9 @@ public function hasIdentification() { * * @internal * - * @return string - * * @throws Exception if type or id is not set yet */ - public function getIdentificationKey() { + public function getIdentificationKey(): string { if ($this->hasIdentification() === false) { throw new Exception('resource has no identification yet'); } @@ -176,11 +166,14 @@ public function getIdentificationKey() { * ObjectInterface */ - public function isEmpty() { - if ($this->type !== null || $this->primaryId() !== null) { + public function isEmpty(): bool { + if (isset($this->type)) { return false; } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->id) || isset($this->lid)) { + return false; + } + if (isset($this->meta) && $this->meta->isEmpty() === false) { return false; } if ($this->hasAtMembers()) { @@ -193,15 +186,16 @@ public function isEmpty() { return true; } - public function toArray() { + public function toArray(): array { $array = []; - $array['type'] = $this->type; - - if ($this->id !== null) { + if (isset($this->type)) { + $array['type'] = $this->type; + } + if (isset($this->id)) { $array['id'] = $this->id; } - elseif ($this->lid !== null) { + elseif (isset($this->lid)) { $array['lid'] = $this->lid; } @@ -212,7 +206,7 @@ public function toArray() { $array = array_merge($array, $this->getExtensionMembers()); } - if ($this->meta !== null && $this->meta->isEmpty() === false) { + if (isset($this->meta) && $this->meta->isEmpty() === false) { $array['meta'] = $this->meta->toArray(); } @@ -223,7 +217,7 @@ public function toArray() { * ResourceInterface */ - public function getResource($identifierOnly=false) { + public function getResource(bool $identifierOnly=false): ResourceIdentifierObject { return $this; } @@ -231,8 +225,12 @@ public function getResource($identifierOnly=false) { * @internal */ - private function primaryId() { - if ($this->lid !== null) { + private function primaryId(): string { + if (isset($this->id) === false && isset($this->lid) === false) { + throw new Exception('resource has no identification yet'); + } + + if (isset($this->lid)) { return $this->lid; } diff --git a/src/objects/ResourceObject.php b/src/objects/ResourceObject.php index e0d59d32..67a4478e 100644 --- a/src/objects/ResourceObject.php +++ b/src/objects/ResourceObject.php @@ -1,12 +1,14 @@ $attributes + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public static function fromArray(array $attributes, $type=null, $id=null, array $options=[]) { + public static function fromArray(array $attributes, ?string $type=null, string|int|null $id=null, array $options=[]): self { if (isset($attributes['id'])) { if ($id === null) { $id = $attributes['id']; @@ -64,13 +61,9 @@ public static function fromArray(array $attributes, $type=null, $id=null, array } /** - * @param object $attributes - * @param string $type optional - * @param string|int $id optional - * @param array $options optional {@see ResourceObject::$defaults} - * @return ResourceObject + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public static function fromObject($attributes, $type=null, $id=null, array $options=[]) { + public static function fromObject(object $attributes, ?string $type=null, string|int|null $id=null, array $options=[]): self { $array = Converter::objectToArray($attributes); return self::fromArray($array, $type, $id, $options); @@ -79,31 +72,33 @@ public static function fromObject($attributes, $type=null, $id=null, array $opti /** * add key-value pairs to attributes * - * @param string $key - * @param mixed $value - * @param array $options optional {@see ResourceObject::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public function add($key, $value, array $options=[]) { + public function add(string $key, mixed $value, array $options=[]): void { $options = array_merge(self::$defaults, $options); - if ($this->attributes === null) { + if (isset($this->attributes) === false) { $this->attributes = new AttributesObject(); } - $this->validator->claimUsedFields([$key], Validator::OBJECT_CONTAINER_ATTRIBUTES, $options); + $this->validator->claimUsedFields([$key], ObjectContainerEnum::Attributes, $options); $this->attributes->add($key, $value); } /** - * @param string $key - * @param mixed $relation ResourceInterface | ResourceInterface[] | CollectionDocument - * @param array $links optional - * @param array $meta optional - * @param array $options optional {@see ResourceObject::$defaults} - * @return RelationshipObject + * @param CollectionDocument|ResourceInterface|ResourceInterface[]|null $relation + * @param array $links + * @param array $meta + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public function addRelationship($key, $relation, array $links=[], array $meta=[], array $options=[]) { + public function addRelationship( + string $key, + array|CollectionDocument|ResourceInterface|null $relation, + array $links=[], + array $meta=[], + array $options=[], + ): RelationshipObject { $relationshipObject = RelationshipObject::fromAnything($relation, $links, $meta); $this->addRelationshipObject($key, $relationshipObject, $options); @@ -112,10 +107,9 @@ public function addRelationship($key, $relation, array $links=[], array $meta=[] } /** - * @param string $href - * @param array $meta optional, if given a LinkObject is added, otherwise a link string is added + * @param array $meta if given a LinkObject is added, otherwise a link string is added */ - public function setSelfLink($href, array $meta=[]) { + public function setSelfLink(string $href, array $meta=[]): void { $this->addLink('self', $href, $meta); } @@ -124,45 +118,39 @@ public function setSelfLink($href, array $meta=[]) { */ /** - * @param AttributesObject $attributesObject - * @param array $options optional {@see ResourceObject::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} */ - public function setAttributesObject(AttributesObject $attributesObject, array $options=[]) { + public function setAttributesObject(AttributesObject $attributesObject, array $options=[]): void { $newKeys = $attributesObject->getKeys(); - $this->validator->clearUsedFields(Validator::OBJECT_CONTAINER_ATTRIBUTES); - $this->validator->claimUsedFields($newKeys, Validator::OBJECT_CONTAINER_ATTRIBUTES, $options); + $this->validator->clearUsedFields(ObjectContainerEnum::Attributes); + $this->validator->claimUsedFields($newKeys, ObjectContainerEnum::Attributes, $options); $this->attributes = $attributesObject; } /** - * @param string $key - * @param RelationshipObject $relationshipObject - * @param array $options optional {@see ResourceObject::$defaults} + * @param PHPStanTypeAlias_InternalOptions $options {@see ResourceObject::$defaults} * * @throws DuplicateException if the resource is contained as a resource in the relationship */ - public function addRelationshipObject($key, RelationshipObject $relationshipObject, array $options=[]) { + public function addRelationshipObject(string $key, RelationshipObject $relationshipObject, array $options=[]): void { if ($relationshipObject->hasResource($this)) { throw new DuplicateException('can not add relation to self'); } - if ($this->relationships === null) { + if (isset($this->relationships) === false) { $this->setRelationshipsObject(new RelationshipsObject()); } - $this->validator->claimUsedFields([$key], Validator::OBJECT_CONTAINER_RELATIONSHIPS, $options); + $this->validator->claimUsedFields([$key], ObjectContainerEnum::Relationships, $options); $this->relationships->addRelationshipObject($key, $relationshipObject); } - /** - * @param RelationshipsObject $relationshipsObject - */ - public function setRelationshipsObject(RelationshipsObject $relationshipsObject) { + public function setRelationshipsObject(RelationshipsObject $relationshipsObject): void { $newKeys = $relationshipsObject->getKeys(); - $this->validator->clearUsedFields(Validator::OBJECT_CONTAINER_RELATIONSHIPS); - $this->validator->claimUsedFields($newKeys, Validator::OBJECT_CONTAINER_RELATIONSHIPS); + $this->validator->clearUsedFields(ObjectContainerEnum::Relationships); + $this->validator->claimUsedFields($newKeys, ObjectContainerEnum::Relationships); $this->relationships = $relationshipsObject; } @@ -177,17 +165,15 @@ public function setRelationshipsObject(RelationshipsObject $relationshipsObject) * this can be used to determine if a Relationship's resource could be added as included resource * * @internal - * - * @return boolean */ - public function hasIdentifierPropertiesOnly() { - if ($this->attributes !== null && $this->attributes->isEmpty() === false) { + public function hasIdentifierPropertiesOnly(): bool { + if (isset($this->attributes) && $this->attributes->isEmpty() === false) { return false; } - if ($this->relationships !== null && $this->relationships->isEmpty() === false) { + if (isset($this->relationships) && $this->relationships->isEmpty() === false) { return false; } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { return false; } @@ -198,15 +184,15 @@ public function hasIdentifierPropertiesOnly() { * HasAttributesInterface */ - public function addAttribute($key, $value, array $options=[]) { - return $this->add($key, $value); + public function addAttribute(string $key, mixed $value, array $options=[]): void { + $this->add($key, $value); } /** * ResourceInterface */ - public function getResource($identifierOnly=false) { + public function getResource(bool $identifierOnly=false): ResourceIdentifierObject|ResourceObject { if ($identifierOnly) { return ResourceIdentifierObject::fromResourceObject($this); } @@ -218,33 +204,33 @@ public function getResource($identifierOnly=false) { * ObjectInterface */ - public function isEmpty() { + public function isEmpty(): bool { if (parent::isEmpty() === false) { return false; } - if ($this->attributes !== null && $this->attributes->isEmpty() === false) { + if (isset($this->attributes) && $this->attributes->isEmpty() === false) { return false; } - if ($this->relationships !== null && $this->relationships->isEmpty() === false) { + if (isset($this->relationships) && $this->relationships->isEmpty() === false) { return false; } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { return false; } return true; } - public function toArray() { + public function toArray(): array { $array = parent::toArray(); - if ($this->attributes !== null && $this->attributes->isEmpty() === false) { + if (isset($this->attributes) && $this->attributes->isEmpty() === false) { $array['attributes'] = $this->attributes->toArray(); } - if ($this->relationships !== null && $this->relationships->isEmpty() === false) { + if (isset($this->relationships) && $this->relationships->isEmpty() === false) { $array['relationships'] = $this->relationships->toArray(); } - if ($this->links !== null && $this->links->isEmpty() === false) { + if ($this->hasLinks()) { $array['links'] = $this->links->toArray(); } @@ -255,8 +241,8 @@ public function toArray() { * RecursiveResourceContainerInterface */ - public function getNestedContainedResourceObjects() { - if ($this->relationships === null) { + public function getNestedContainedResourceObjects(): array { + if (isset($this->relationships) === false) { return []; } diff --git a/src/profiles/CursorPaginationProfile.php b/src/profiles/CursorPaginationProfile.php index 8ab4a9ff..aabf16dd 100644 --- a/src/profiles/CursorPaginationProfile.php +++ b/src/profiles/CursorPaginationProfile.php @@ -1,9 +1,11 @@ generatePreviousLink($baseOrCurrentUrl, $firstCursor)); $nextLinkObject = new LinkObject($this->generateNextLink($baseOrCurrentUrl, $lastCursor)); @@ -67,41 +71,32 @@ public function setLinks(PaginableInterface $paginable, $baseOrCurrentUrl, $firs } /** - * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject - * @param string $baseOrCurrentUrl - * @param string $lastCursor + * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject */ - public function setLinksFirstPage(PaginableInterface $paginable, $baseOrCurrentUrl, $lastCursor) { + public function setLinksFirstPage(PaginableInterface $paginable, string $baseOrCurrentUrl, string $lastCursor): void { $this->setPaginationLinkObjectsWithoutPrevious($paginable, $baseOrCurrentUrl, $lastCursor); } /** - * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject - * @param string $baseOrCurrentUrl - * @param string $firstCursor + * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject */ - public function setLinksLastPage(PaginableInterface $paginable, $baseOrCurrentUrl, $firstCursor) { + public function setLinksLastPage(PaginableInterface $paginable, string $baseOrCurrentUrl, string $firstCursor): void { $this->setPaginationLinkObjectsWithoutNext($paginable, $baseOrCurrentUrl, $firstCursor); } /** * set the cursor of a specific resource to allow pagination after or before this resource - * - * @param ResourceInterface $resource - * @param string $cursor */ - public function setCursor(ResourceInterface $resource, $cursor) { + public function setCursor(ResourceInterface $resource, string $cursor): void { $this->setItemMeta($resource, $cursor); } /** * set count(s) to tell about the (estimated) total size * - * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject - * @param int $exactTotal optional - * @param int $bestGuessTotal optional + * @param PaginableInterface $paginable a CollectionDocument or RelationshipObject */ - public function setCount(PaginableInterface $paginable, $exactTotal=null, $bestGuessTotal=null) { + public function setCount(PaginableInterface $paginable, ?int $exactTotal=null, ?int $bestGuessTotal=null) { $this->setPaginationMeta($paginable, $exactTotal, $bestGuessTotal); } @@ -111,21 +106,13 @@ public function setCount(PaginableInterface $paginable, $exactTotal=null, $bestG /** * helper to get generate a correct page[before] link, use to apply manually - * - * @param string $baseOrCurrentUrl - * @param string $beforeCursor - * @return string */ - public function generatePreviousLink($baseOrCurrentUrl, $beforeCursor) { + public function generatePreviousLink(string $baseOrCurrentUrl, string $beforeCursor): string { return $this->setQueryParameter($baseOrCurrentUrl, 'page[before]', $beforeCursor); } /** * helper to get generate a correct page[after] link, use to apply manually - * - * @param string $baseOrCurrentUrl - * @param string $afterCursor - * @return string */ public function generateNextLink($baseOrCurrentUrl, $afterCursor) { return $this->setQueryParameter($baseOrCurrentUrl, 'page[after]', $afterCursor); @@ -140,42 +127,25 @@ public function generateNextLink($baseOrCurrentUrl, $afterCursor) { * - /data/0/relationships/foo/links/prev & /data/0/relationships/foo/links/next * * @see https://jsonapi.org/profiles/ethanresnick/cursor-pagination/#terms-pagination-links - * - * @param PaginableInterface&HasLinksInterface $paginable - * @param LinkObject $previousLinkObject - * @param LinkObject $nextLinkObject */ - public function setPaginationLinkObjects(PaginableInterface $paginable, LinkObject $previousLinkObject, LinkObject $nextLinkObject) { - if ($paginable instanceof HasLinksInterface === false) { - throw new InputException('unsupported paginable to set pagination links on'); - } - + public function setPaginationLinkObjects( + PaginableInterface & HasLinksInterface $paginable, + LinkObject $previousLinkObject, + LinkObject $nextLinkObject, + ): void { $paginable->addLinkObject('prev', $previousLinkObject); $paginable->addLinkObject('next', $nextLinkObject); } - /** - * @param PaginableInterface $paginable - * @param string $baseOrCurrentUrl - * @param string $firstCursor - */ - public function setPaginationLinkObjectsWithoutNext(PaginableInterface $paginable, $baseOrCurrentUrl, $firstCursor) { + public function setPaginationLinkObjectsWithoutNext(PaginableInterface $paginable, string $baseOrCurrentUrl, string $firstCursor): void { $this->setPaginationLinkObjects($paginable, new LinkObject($this->generatePreviousLink($baseOrCurrentUrl, $firstCursor)), new LinkObject()); } - /** - * @param PaginableInterface $paginable - * @param string $baseOrCurrentUrl - * @param string $lastCursor - */ - public function setPaginationLinkObjectsWithoutPrevious(PaginableInterface $paginable, $baseOrCurrentUrl, $lastCursor) { + public function setPaginationLinkObjectsWithoutPrevious(PaginableInterface $paginable, string $baseOrCurrentUrl, string $lastCursor): void { $this->setPaginationLinkObjects($paginable, new LinkObject(), new LinkObject($this->generateNextLink($baseOrCurrentUrl, $lastCursor))); } - /** - * @param PaginableInterface $paginable - */ - public function setPaginationLinkObjectsExplicitlyEmpty(PaginableInterface $paginable) { + public function setPaginationLinkObjectsExplicitlyEmpty(PaginableInterface $paginable): void { $this->setPaginationLinkObjects($paginable, new LinkObject(), new LinkObject()); } @@ -188,21 +158,14 @@ public function setPaginationLinkObjectsExplicitlyEmpty(PaginableInterface $pagi * - /data/0/relationships/foo/meta/page * * @see https://jsonapi.org/profiles/ethanresnick/cursor-pagination/#terms-pagination-item-metadata - * - * @param ResourceInterface&HasMetaInterface $resource - * @param string $cursor */ - public function setItemMeta(ResourceInterface $resource, $cursor) { - if ($resource instanceof HasMetaInterface === false) { - throw new InputException('resource doesn\'t support meta'); - } - + public function setItemMeta(ResourceInterface & HasMetaInterface $resource, string $cursor): void { $metadata = [ 'cursor' => $cursor, ]; if ($resource instanceof ResourceDocument) { - $resource->addMeta('page', $metadata, $level=Document::LEVEL_RESOURCE); + $resource->addMeta('page', $metadata, $level=DocumentLevelEnum::Resource); } else { $resource->addMeta('page', $metadata); @@ -219,16 +182,14 @@ public function setItemMeta(ResourceInterface $resource, $cursor) { * * @see https://jsonapi.org/profiles/ethanresnick/cursor-pagination/#terms-pagination-metadata * - * @param PaginableInterface&HasMetaInterface $paginable - * @param int $exactTotal optional - * @param int $bestGuessTotal optional - * @param boolean $rangeIsTruncated optional, if both after and before are supplied but the items exceed requested or max size + * @param boolean $rangeIsTruncated, if both after and before are supplied but the items exceed requested or max size */ - public function setPaginationMeta(PaginableInterface $paginable, $exactTotal=null, $bestGuessTotal=null, $rangeIsTruncated=null) { - if ($paginable instanceof HasMetaInterface === false) { - throw new InputException('paginable doesn\'t support meta'); - } - + public function setPaginationMeta( + PaginableInterface & HasMetaInterface $paginable, + ?int $exactTotal=null, + ?int $bestGuessTotal=null, + ?bool $rangeIsTruncated=null, + ): void { $metadata = []; if ($exactTotal !== null) { @@ -250,18 +211,9 @@ public function setPaginationMeta(PaginableInterface $paginable, $exactTotal=nul * get an ErrorObject for when the requested sorting cannot efficiently be paginated * * ends up at: - * - /errors/0/code - * - /errors/0/status - * - /errors/0/source/parameter - * - /errors/0/links/type/0 - * - /errors/0/title optional - * - /errors/0/detail optional - * - * @param string $genericTitle optional - * @param string $specificDetails optional - * @return ErrorObject + * - /errors/0/* */ - public function getUnsupportedSortErrorObject($genericTitle=null, $specificDetails=null) { + public function getUnsupportedSortErrorObject(?string $genericTitle=null, ?string $specificDetails=null): ErrorObject { $errorObject = new ErrorObject('Unsupported sort'); $errorObject->setTypeLink('https://jsonapi.org/profiles/ethanresnick/cursor-pagination/unsupported-sort'); $errorObject->blameQueryParameter('sort'); @@ -278,20 +230,12 @@ public function getUnsupportedSortErrorObject($genericTitle=null, $specificDetai * get an ErrorObject for when the requested page size exceeds the server-defined max page size * * ends up at: - * - /errors/0/code - * - /errors/0/status - * - /errors/0/source/parameter - * - /errors/0/links/type/0 - * - /errors/0/meta/page/maxSize - * - /errors/0/title optional - * - /errors/0/detail optional + * - /errors/0/* * - * @param int $maxSize - * @param string $genericTitle optional, e.g. 'Page size requested is too large.' - * @param string $specificDetails optional, e.g. 'You requested a size of 200, but 100 is the maximum.' - * @return ErrorObject + * @param string $genericTitle e.g. 'Page size requested is too large.' + * @param string $specificDetails e.g. 'You requested a size of 200, but 100 is the maximum.' */ - public function getMaxPageSizeExceededErrorObject($maxSize, $genericTitle=null, $specificDetails=null) { + public function getMaxPageSizeExceededErrorObject(int $maxSize, ?string $genericTitle=null, ?string $specificDetails=null): ErrorObject { $errorObject = new ErrorObject('Max page size exceeded'); $errorObject->setTypeLink('https://jsonapi.org/profiles/ethanresnick/cursor-pagination/max-size-exceeded'); $errorObject->blameQueryParameter('page[size]'); @@ -309,20 +253,18 @@ public function getMaxPageSizeExceededErrorObject($maxSize, $genericTitle=null, * get an ErrorObject for when the requested page size is not a positive integer, or when the requested page after/before is not a valid cursor * * ends up at: - * - /errors/0/code - * - /errors/0/status - * - /errors/0/source/parameter - * - /errors/0/links/type/0 optional - * - /errors/0/title optional - * - /errors/0/detail optional + * - /errors/0/* * - * @param int $queryParameter e.g. 'sort' or 'page[size]' - * @param string $typeLink optional - * @param string $genericTitle optional, e.g. 'Invalid Parameter.' - * @param string $specificDetails optional, e.g. 'page[size] must be a positive integer; got 0' - * @return ErrorObject + * @param string $queryParameter e.g. 'sort' or 'page[size]' + * @param string $genericTitle e.g. 'Invalid Parameter.' + * @param string $specificDetails e.g. 'page[size] must be a positive integer; got 0' */ - public function getInvalidParameterValueErrorObject($queryParameter, $typeLink=null, $genericTitle=null, $specificDetails=null) { + public function getInvalidParameterValueErrorObject( + string $queryParameter, + ?string $typeLink=null, + ?string $genericTitle=null, + ?string $specificDetails=null, + ): ErrorObject { $errorObject = new ErrorObject('Invalid parameter value'); $errorObject->blameQueryParameter($queryParameter); $errorObject->setHttpStatusCode(400); @@ -342,15 +284,9 @@ public function getInvalidParameterValueErrorObject($queryParameter, $typeLink=n * get an ErrorObject for when range pagination requests (when both 'page[after]' and 'page[before]' are requested) are not supported * * ends up at: - * - /errors/0/code - * - /errors/0/status - * - /errors/0/links/type/0 - * - * @param string $genericTitle optional - * @param string $specificDetails optional - * @return ErrorObject + * - /errors/0/* */ - public function getRangePaginationNotSupportedErrorObject($genericTitle=null, $specificDetails=null) { + public function getRangePaginationNotSupportedErrorObject(?string $genericTitle=null, ?string $specificDetails=null): ErrorObject { $errorObject = new ErrorObject('Range pagination not supported'); $errorObject->setTypeLink('https://jsonapi.org/profiles/ethanresnick/cursor-pagination/range-pagination-not-supported'); $errorObject->setHttpStatusCode(400); @@ -368,12 +304,8 @@ public function getRangePaginationNotSupportedErrorObject($genericTitle=null, $s /** * add or adjust a key in the query string of a url - * - * @param string $url - * @param string $key - * @param string $value */ - private function setQueryParameter($url, $key, $value) { + private function setQueryParameter(string $url, string $key, string $value): string { $originalQuery = parse_url($url, PHP_URL_QUERY); $decodedQuery = urldecode($originalQuery); $originalIsEncoded = ($decodedQuery !== $originalQuery); @@ -400,7 +332,7 @@ private function setQueryParameter($url, $key, $value) { * ProfileInterface */ - public function getOfficialLink() { + public function getOfficialLink(): string { return 'https://jsonapi.org/profiles/ethanresnick/cursor-pagination/'; } } diff --git a/tests/CollectionDocumentTest.php b/tests/CollectionDocumentTest.php index fd255f09..97ce3e86 100644 --- a/tests/CollectionDocumentTest.php +++ b/tests/CollectionDocumentTest.php @@ -1,5 +1,7 @@ assertSame('foo', Converter::prepareContentType('foo', [], [])); + $this->assertSame(ContentTypeEnum::Official->value, Converter::prepareContentType(ContentTypeEnum::Official, [], [])); } /** @@ -78,7 +81,7 @@ public function testPrepareContentType_WithExtensionStringLink() { $extension = new TestExtension(); $extension->setOfficialLink('bar'); - $this->assertSame('foo; ext="bar"', Converter::prepareContentType('foo', [$extension], [])); + $this->assertSame(ContentTypeEnum::Official->value.'; ext="bar"', Converter::prepareContentType(ContentTypeEnum::Official, [$extension], [])); } /** @@ -88,7 +91,7 @@ public function testPrepareContentType_WithProfileStringLink() { $profile = new TestProfile(); $profile->setOfficialLink('bar'); - $this->assertSame('foo; profile="bar"', Converter::prepareContentType('foo', [], [$profile])); + $this->assertSame(ContentTypeEnum::Official->value.'; profile="bar"', Converter::prepareContentType(ContentTypeEnum::Official, [], [$profile])); } /** @@ -108,7 +111,7 @@ public function testPrepareContentType_WithMultipleExtensionsAndProfiles() { $profile2 = new TestProfile(); $profile2->setOfficialLink('baz'); - $this->assertSame('foo; ext="bar baz"; profile="bar baz"', Converter::prepareContentType('foo', [$extension1, $extension2], [$profile1, $profile2])); + $this->assertSame(ContentTypeEnum::Official->value.'; ext="bar baz"; profile="bar baz"', Converter::prepareContentType(ContentTypeEnum::Official, [$extension1, $extension2], [$profile1, $profile2])); } } diff --git a/tests/DocumentTest.php b/tests/DocumentTest.php index 6e8e51c6..024f989d 100644 --- a/tests/DocumentTest.php +++ b/tests/DocumentTest.php @@ -1,7 +1,10 @@ expectException(InputException::class); $this->expectExceptionMessage('level "jsonapi" can not be used for links'); - $document->addLink('foo', 'https://jsonapi.org', $meta=[], $level=Document::LEVEL_JSONAPI); + $document->addLink('foo', 'https://jsonapi.org', $meta=[], $level=DocumentLevelEnum::Jsonapi); } public function testAddLink_BlocksResourceLevel() { @@ -77,16 +80,7 @@ public function testAddLink_BlocksResourceLevel() { $this->expectException(InputException::class); $this->expectExceptionMessage('level "resource" can only be set on a ResourceDocument'); - $document->addLink('foo', 'https://jsonapi.org', $meta=[], $level=Document::LEVEL_RESOURCE); - } - - public function testAddLink_BlocksUnknownLevel() { - $document = new Document(); - - $this->expectException(InputException::class); - $this->expectExceptionMessage('unknown level "foo"'); - - $document->addLink('foo', 'https://jsonapi.org', $meta=[], $level='foo'); + $document->addLink('foo', 'https://jsonapi.org', $meta=[], $level=DocumentLevelEnum::Resource); } public function testSetSelfLink_HappyPath() { @@ -160,7 +154,7 @@ public function testAddMeta_AtJsonapiLevel() { $this->assertArrayHasKey('jsonapi', $array); $this->assertArrayNotHasKey('meta', $array['jsonapi']); - $document->addMeta('foo', 'bar', $level=Document::LEVEL_JSONAPI); + $document->addMeta('foo', 'bar', $level=DocumentLevelEnum::Jsonapi); $array = $document->toArray(); @@ -178,16 +172,7 @@ public function testAddMeta_BlocksResourceLevel() { $this->expectException(InputException::class); $this->expectExceptionMessage('level "resource" can only be set on a ResourceDocument'); - $document->addMeta('foo', 'bar', $level=Document::LEVEL_RESOURCE); - } - - public function testAddMeta_BlocksUnknownLevel() { - $document = new Document(); - - $this->expectException(InputException::class); - $this->expectExceptionMessage('unknown level "foo"'); - - $document->addMeta('foo', 'bar', $level='foo'); + $document->addMeta('foo', 'bar', $level=DocumentLevelEnum::Resource); } public function testAddLinkObject_HappyPath() { diff --git a/tests/ErrorsDocumentTest.php b/tests/ErrorsDocumentTest.php index 151f44e8..10e694f5 100644 --- a/tests/ErrorsDocumentTest.php +++ b/tests/ErrorsDocumentTest.php @@ -1,5 +1,7 @@ addMeta('foo', 'root', $level=Document::LEVEL_ROOT); - $document->addMeta('bar', 'resource', $level=Document::LEVEL_RESOURCE); - $document->addMeta('baz', 'jsonapi', $level=Document::LEVEL_JSONAPI); + $document->addMeta('foo', 'root', $level=DocumentLevelEnum::Root); + $document->addMeta('bar', 'resource', $level=DocumentLevelEnum::Resource); + $document->addMeta('baz', 'jsonapi', $level=DocumentLevelEnum::Jsonapi); $array = $document->toArray(); @@ -122,7 +124,7 @@ public function testAddMeta_RecreateJsonapiObject() { $this->assertArrayNotHasKey('jsonapi', $array); - $document->addMeta('baz', 'jsonapi', $level=Document::LEVEL_JSONAPI); + $document->addMeta('baz', 'jsonapi', $level=DocumentLevelEnum::Jsonapi); $array = $document->toArray(); diff --git a/tests/SeparateProcessTest.php b/tests/SeparateProcessTest.php index ec00ccdf..95f8290a 100644 --- a/tests/SeparateProcessTest.php +++ b/tests/SeparateProcessTest.php @@ -1,8 +1,11 @@ sendResponse(); @@ -28,7 +31,7 @@ public function testSendResponse_HappyPath() { * @runInSeparateProcess */ public function testSendResponse_NoContent() { - $document = new Document(); + $document = new TestableNonAbstractDocument(); $document->setHttpStatusCode(204); ob_start(); @@ -47,30 +50,30 @@ public function testSendResponse_ContentTypeHeader() { $this->markTestSkipped('can not run without xdebug'); } - $document = new Document(); + $document = new TestableNonAbstractDocument(); ob_start(); $document->sendResponse(); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value], xdebug_get_headers()); - $options = ['contentType' => Document::CONTENT_TYPE_OFFICIAL]; + $options = ['contentType' => ContentTypeEnum::Official]; ob_start(); $document->sendResponse($options); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value], xdebug_get_headers()); - $options = ['contentType' => Document::CONTENT_TYPE_DEBUG]; + $options = ['contentType' => ContentTypeEnum::Debug]; ob_start(); $document->sendResponse($options); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_DEBUG], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Debug->value], xdebug_get_headers()); - $options = ['contentType' => Document::CONTENT_TYPE_JSONP]; + $options = ['contentType' => ContentTypeEnum::Jsonp]; ob_start(); $document->sendResponse($options); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_JSONP], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Jsonp->value], xdebug_get_headers()); } /** @@ -86,13 +89,13 @@ public function testSendResponse_ContentTypeHeaderWithExtensions() { $extension->setNamespace('one'); $extension->setOfficialLink('https://jsonapi.org'); - $document = new Document(); + $document = new TestableNonAbstractDocument(); $document->applyExtension($extension); ob_start(); $document->sendResponse(); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL.'; ext="https://jsonapi.org"'], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value.'; ext="https://jsonapi.org"'], xdebug_get_headers()); $extension = new TestExtension(); $extension->setNamespace('two'); @@ -102,7 +105,7 @@ public function testSendResponse_ContentTypeHeaderWithExtensions() { ob_start(); $document->sendResponse(); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL.'; ext="https://jsonapi.org https://jsonapi.org/2"'], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value.'; ext="https://jsonapi.org https://jsonapi.org/2"'], xdebug_get_headers()); } /** @@ -117,13 +120,13 @@ public function testSendResponse_ContentTypeHeaderWithProfiles() { $profile = new TestProfile(); $profile->setOfficialLink('https://jsonapi.org'); - $document = new Document(); + $document = new TestableNonAbstractDocument(); $document->applyProfile($profile); ob_start(); $document->sendResponse(); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL.'; profile="https://jsonapi.org"'], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value.'; profile="https://jsonapi.org"'], xdebug_get_headers()); $profile = new TestProfile(); $profile->setOfficialLink('https://jsonapi.org/2'); @@ -132,14 +135,14 @@ public function testSendResponse_ContentTypeHeaderWithProfiles() { ob_start(); $document->sendResponse(); ob_end_clean(); - $this->assertSame(['Content-Type: '.Document::CONTENT_TYPE_OFFICIAL.'; profile="https://jsonapi.org https://jsonapi.org/2"'], xdebug_get_headers()); + $this->assertSame(['Content-Type: '.ContentTypeEnum::Official->value.'; profile="https://jsonapi.org https://jsonapi.org/2"'], xdebug_get_headers()); } /** * @runInSeparateProcess */ public function testSendResponse_StatusCodeHeader() { - $document = new Document(); + $document = new TestableNonAbstractDocument(); ob_start(); $document->sendResponse(); @@ -169,7 +172,7 @@ public function testSendResponse_StatusCodeHeader() { * @runInSeparateProcess */ public function testSendResponse_CustomJson() { - $document = new Document(); + $document = new TestableNonAbstractDocument(); $options = ['json' => '{"foo":42}']; ob_start(); diff --git a/tests/TestableNonAbstractDocument.php b/tests/TestableNonAbstractDocument.php index 4f1b018f..57f55161 100644 --- a/tests/TestableNonAbstractDocument.php +++ b/tests/TestableNonAbstractDocument.php @@ -1,5 +1,7 @@ claimUsedFields($fieldNames, $objectContainer); $fieldNames = ['bar']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); } @@ -28,12 +31,12 @@ public function testClaimUsedFields_EnforceNamespace() { $validator = new Validator(); $fieldNames = ['foo']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); $this->expectException(DuplicateException::class); - $objectContainer = Validator::OBJECT_CONTAINER_RELATIONSHIPS; + $objectContainer = ObjectContainerEnum::Relationships; $validator->claimUsedFields($fieldNames, $objectContainer); } @@ -42,10 +45,10 @@ public function testClaimUsedFields_AllowSameContainer() { $validator = new Validator(); $fieldNames = ['foo']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); } @@ -54,10 +57,10 @@ public function testClaimUsedFields_OptionForReusingTypeField() { $validator = new Validator(); $fieldNames = ['type']; - $objectContainer = Validator::OBJECT_CONTAINER_TYPE; + $objectContainer = ObjectContainerEnum::Type; $validator->claimUsedFields($fieldNames, $objectContainer); - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $options = ['enforceTypeFieldNamespace' => false]; $validator->claimUsedFields($fieldNames, $objectContainer, $options); } @@ -67,7 +70,7 @@ public function testClearUsedFields_HappyPath() { $validator = new Validator(); $fieldNames = ['foo']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); $validator->clearUsedFields($objectContainer); @@ -77,13 +80,13 @@ public function testClearUsedFields_FreesForAnotherNamespace() { $validator = new Validator(); $fieldNames = ['foo', 'bar']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); $thrown = false; try { $fieldNames = ['bar']; - $objectContainer = Validator::OBJECT_CONTAINER_RELATIONSHIPS; + $objectContainer = ObjectContainerEnum::Relationships; $validator->claimUsedFields($fieldNames, $objectContainer); } catch (DuplicateException) { @@ -91,21 +94,21 @@ public function testClearUsedFields_FreesForAnotherNamespace() { } $this->assertTrue($thrown); - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->clearUsedFields($objectContainer); $fieldNames = ['foo']; - $objectContainer = Validator::OBJECT_CONTAINER_ATTRIBUTES; + $objectContainer = ObjectContainerEnum::Attributes; $validator->claimUsedFields($fieldNames, $objectContainer); $fieldNames = ['bar']; - $objectContainer = Validator::OBJECT_CONTAINER_RELATIONSHIPS; + $objectContainer = ObjectContainerEnum::Relationships; $validator->claimUsedFields($fieldNames, $objectContainer); $this->expectException(DuplicateException::class); $fieldNames = ['foo']; - $objectContainer = Validator::OBJECT_CONTAINER_RELATIONSHIPS; + $objectContainer = ObjectContainerEnum::Relationships; $validator->claimUsedFields($fieldNames, $objectContainer); } diff --git a/tests/bootstrap_tests.php b/tests/bootstrap_tests.php index f695b44a..80a03b31 100644 --- a/tests/bootstrap_tests.php +++ b/tests/bootstrap_tests.php @@ -1,5 +1,7 @@ addAtMember('context', '/data/relationships/foo/meta/@context'); - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->addAtMember('context', '/data/relationships/foo/@context'); $relationshipObject->setResource($resourceObject); $relationshipObject->setLinksObject($linksObject); @@ -102,7 +105,7 @@ public static function createJsonapiDocument() { $resourceIdentifierObject->addAtMember('context', '/data/relationships/bar/data/@context'); $resourceIdentifierObject->setMetaObject($metaObject); - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->addAtMember('context', '/data/relationships/bar/@context'); $relationshipObject->setResource($resourceIdentifierObject); diff --git a/tests/example_output/at_members_in_errors/at_members_in_errors.php b/tests/example_output/at_members_in_errors/at_members_in_errors.php index 8d975137..e937eb88 100644 --- a/tests/example_output/at_members_in_errors/at_members_in_errors.php +++ b/tests/example_output/at_members_in_errors/at_members_in_errors.php @@ -1,5 +1,7 @@ addExtensionMember($extension, 'key', '/data/relationships/foo/meta/key'); - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->addExtensionMember($extension, 'key', '/data/relationships/foo/key'); $relationshipObject->setResource($resourceObject); $relationshipObject->setLinksObject($linksObject); @@ -107,7 +110,7 @@ public static function createJsonapiDocument() { $resourceIdentifierObject->addExtensionMember($extension, 'key', '/data/relationships/bar/data/key'); $resourceIdentifierObject->setMetaObject($metaObject); - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->addExtensionMember($extension, 'key', '/data/relationships/bar/key'); $relationshipObject->setResource($resourceIdentifierObject); diff --git a/tests/example_output/meta_only/meta_only.php b/tests/example_output/meta_only/meta_only.php index 2bf1ee62..2bf360d4 100644 --- a/tests/example_output/meta_only/meta_only.php +++ b/tests/example_output/meta_only/meta_only.php @@ -1,5 +1,7 @@ addLinkObject('bar', new LinkObject()); $document->addRelationship('bar', null); - $document->addRelationshipObject('baz', new RelationshipObject(RelationshipObject::TO_ONE)); - $document->addRelationshipObject('baf', new RelationshipObject(RelationshipObject::TO_MANY)); + $document->addRelationshipObject('baz', new RelationshipObject(RelationshipTypeEnum::ToOne)); + $document->addRelationshipObject('baf', new RelationshipObject(RelationshipTypeEnum::ToMany)); return $document; } diff --git a/tests/example_output/profile/profile.php b/tests/example_output/profile/profile.php index 16deba80..56bdde48 100644 --- a/tests/example_output/profile/profile.php +++ b/tests/example_output/profile/profile.php @@ -1,5 +1,7 @@ setSelfLink('/articles/1/relationship/author', $meta=[], $level=Document::LEVEL_ROOT); + $document->setSelfLink('/articles/1/relationship/author', $meta=[], $level=DocumentLevelEnum::Root); $document->addLink('related', '/articles/1/author'); return $document; diff --git a/tests/example_output/relationships/relationships.php b/tests/example_output/relationships/relationships.php index 8426cdd2..49f833f2 100644 --- a/tests/example_output/relationships/relationships.php +++ b/tests/example_output/relationships/relationships.php @@ -1,9 +1,12 @@ addResource($friend1Resource); $relationshipObject->addResource($friend2Resource); @@ -63,7 +66,7 @@ public static function createJsonapiDocument() { * to-many relationship, different types */ - $relationshipObject = new RelationshipObject($type=RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject($type=RelationshipTypeEnum::ToMany); $relationshipObject->addResource($ship1Resource); $relationshipObject->addResource($dockResource); diff --git a/tests/example_output/resource_document_identifier_only/resource_document_identifier_only.php b/tests/example_output/resource_document_identifier_only/resource_document_identifier_only.php index 493f7ccf..3c960584 100644 --- a/tests/example_output/resource_document_identifier_only/resource_document_identifier_only.php +++ b/tests/example_output/resource_document_identifier_only/resource_document_identifier_only.php @@ -1,5 +1,7 @@ id); - $selfResourceMeta = ['level' => Document::LEVEL_RESOURCE]; - $partnerMeta = ['level' => Document::LEVEL_RESOURCE]; - $redirectMeta = ['level' => Document::LEVEL_ROOT]; + $selfResourceMeta = ['level' => DocumentLevelEnum::Resource->name]; + $partnerMeta = ['level' => DocumentLevelEnum::Resource->name]; + $redirectMeta = ['level' => DocumentLevelEnum::Root->name]; $document->setSelfLink('/user/42', $selfResourceMeta); - $document->addLink('partner', '/user/1', $partnerMeta, $level=Document::LEVEL_RESOURCE); - $document->addLink('redirect', '/login', $redirectMeta, $level=Document::LEVEL_ROOT); + $document->addLink('partner', '/user/1', $partnerMeta, $level=DocumentLevelEnum::Resource); + $document->addLink('redirect', '/login', $redirectMeta, $level=DocumentLevelEnum::Root); return $document; } diff --git a/tests/example_output/resource_nested_relations/resource_nested_relations.php b/tests/example_output/resource_nested_relations/resource_nested_relations.php index 4095c84a..5db1d549 100644 --- a/tests/example_output/resource_nested_relations/resource_nested_relations.php +++ b/tests/example_output/resource_nested_relations/resource_nested_relations.php @@ -1,5 +1,7 @@ setType('user'); $resource->setAttributesObject($attributes42); - $relationship = new RelationshipObject(RelationshipObject::TO_ONE); + $relationship = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationship->setResource($resource); $relationships = new RelationshipsObject(); $relationships->addRelationshipObject('friend', $relationship); diff --git a/tests/example_output/status_only/status_only.php b/tests/example_output/status_only/status_only.php index 35462051..209e9cb7 100644 --- a/tests/example_output/status_only/status_only.php +++ b/tests/example_output/status_only/status_only.php @@ -1,5 +1,7 @@ namespace = $namespace; } - public function setOfficialLink($officialLink) { + public function setOfficialLink(string $officialLink) { $this->officialLink = $officialLink; } - public function getNamespace() { + public function getNamespace(): string { return $this->namespace; } - public function getOfficialLink() { + public function getOfficialLink(): string { return $this->officialLink; } } diff --git a/tests/helpers/AtMemberManagerTest.php b/tests/helpers/AtMemberManagerTest.php index b0244aab..ee2fc210 100644 --- a/tests/helpers/AtMemberManagerTest.php +++ b/tests/helpers/AtMemberManagerTest.php @@ -1,5 +1,7 @@ assertFalse($helper->hasHttpStatusCode()); - $this->assertNull($helper->getHttpStatusCode()); $helper->setHttpStatusCode(204); diff --git a/tests/helpers/LinksManagerTest.php b/tests/helpers/LinksManagerTest.php index b93ef1f3..97c462b0 100644 --- a/tests/helpers/LinksManagerTest.php +++ b/tests/helpers/LinksManagerTest.php @@ -1,5 +1,7 @@ value; $_POST = [ 'data' => [ @@ -61,7 +64,7 @@ public function testFromSuperglobals_HappyPath() { $this->assertSame(['ship' => ['wing' => []]], $requestParser->getIncludePaths()); $this->assertSame(['name', 'location'], $requestParser->getSparseFieldset('user')); - $this->assertSame([['field' => 'name', 'order' => RequestParser::SORT_ASCENDING], ['field' => 'location', 'order' => RequestParser::SORT_DESCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'name', 'order' => SortOrderEnum::Ascending], ['field' => 'location', 'order' => SortOrderEnum::Descending]], $requestParser->getSortFields()); $this->assertSame(['number' => '2', 'size' => '10'], $requestParser->getPagination()); $this->assertSame('42', $requestParser->getFilter()); @@ -80,7 +83,7 @@ public function testFromSuperglobals_WithPhpInputStream() { $_SERVER['REQUEST_SCHEME'] = 'https'; $_SERVER['HTTP_HOST'] = 'example.org'; $_SERVER['REQUEST_URI'] = '/'; - $_SERVER['CONTENT_TYPE'] = Document::CONTENT_TYPE_OFFICIAL; + $_SERVER['CONTENT_TYPE'] = ContentTypeEnum::Official->value; $_GET = []; $_POST = []; @@ -152,7 +155,7 @@ public function testFromPsrRequest_WithRequestInterface() { $this->assertSame(['ship' => ['wing' => []]], $requestParser->getIncludePaths()); $this->assertSame(['name', 'location'], $requestParser->getSparseFieldset('user')); - $this->assertSame([['field' => 'name', 'order' => RequestParser::SORT_ASCENDING], ['field' => 'location', 'order' => RequestParser::SORT_DESCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'name', 'order' => SortOrderEnum::Ascending], ['field' => 'location', 'order' => SortOrderEnum::Descending]], $requestParser->getSortFields()); $this->assertSame(['number' => '2', 'size' => '10'], $requestParser->getPagination()); $this->assertSame('42', $requestParser->getFilter()); @@ -190,7 +193,7 @@ public function testFromPsrRequest_WithServerRequestInterface() { $this->assertSame('https://example.org/user/42?'.http_build_query($queryParameters), $requestParser->getSelfLink()); $this->assertTrue($requestParser->hasSortFields()); - $this->assertSame([['field' => 'name', 'order' => RequestParser::SORT_ASCENDING], ['field' => 'location', 'order' => RequestParser::SORT_DESCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'name', 'order' => SortOrderEnum::Ascending], ['field' => 'location', 'order' => SortOrderEnum::Descending]], $requestParser->getSortFields()); } public function testGetSelfLink() { @@ -292,15 +295,15 @@ public function testHasSortFields() { public function testGetSortFields_Reformatted() { $queryParameters = ['sort' => 'foo']; $requestParser = new RequestParser($selfLink='', $queryParameters); - $this->assertSame([['field' => 'foo', 'order' => RequestParser::SORT_ASCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'foo', 'order' => SortOrderEnum::Ascending]], $requestParser->getSortFields()); $queryParameters = ['sort' => '-bar']; $requestParser = new RequestParser($selfLink='', $queryParameters); - $this->assertSame([['field' => 'bar', 'order' => RequestParser::SORT_DESCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'bar', 'order' => SortOrderEnum::Descending]], $requestParser->getSortFields()); $queryParameters = ['sort' => 'foo,-bar']; $requestParser = new RequestParser($selfLink='', $queryParameters); - $this->assertSame([['field' => 'foo', 'order' => RequestParser::SORT_ASCENDING], ['field' => 'bar', 'order' => RequestParser::SORT_DESCENDING]], $requestParser->getSortFields()); + $this->assertSame([['field' => 'foo', 'order' => SortOrderEnum::Ascending], ['field' => 'bar', 'order' => SortOrderEnum::Descending]], $requestParser->getSortFields()); } public function testGetSortFields_Raw() { diff --git a/tests/helpers/TestableNonInterfaceRequestInterface.php b/tests/helpers/TestableNonInterfaceRequestInterface.php index e2d26da7..1918c52e 100644 --- a/tests/helpers/TestableNonInterfaceRequestInterface.php +++ b/tests/helpers/TestableNonInterfaceRequestInterface.php @@ -1,5 +1,7 @@ links === null) { + if ($this->hasLinks() === false) { return []; } diff --git a/tests/objects/AttributesObjectTest.php b/tests/objects/AttributesObjectTest.php index 047e3d1a..90e69c0f 100644 --- a/tests/objects/AttributesObjectTest.php +++ b/tests/objects/AttributesObjectTest.php @@ -1,5 +1,7 @@ assertSame('bar', $array['foo']); } + public function testAdd_AllowsMixedValue() { + $attributesObject = new AttributesObject(); + $attributesObject->add('array-list', ['foo']); + $attributesObject->add('array-int-key', [42 => 'foo']); + $attributesObject->add('array-string-key', ['foo' => 'bar']); + $attributesObject->add('bool', true); + $attributesObject->add('int', 42); + $attributesObject->add('float', 4.2); + $attributesObject->add('null', null); + $attributesObject->add('object', new \stdClass); + $attributesObject->add('string', 'foo'); + + $array = $attributesObject->toArray(); + + $this->assertCount(9, $array); + } + public function testAdd_WithObject() { $object = new \stdClass(); $object->bar = 'baz'; diff --git a/tests/objects/ErrorObjectTest.php b/tests/objects/ErrorObjectTest.php index a794dca8..31365208 100644 --- a/tests/objects/ErrorObjectTest.php +++ b/tests/objects/ErrorObjectTest.php @@ -1,5 +1,7 @@ add('array-list', ['foo']); + $metaObject->add('array-int-key', [42 => 'foo']); + $metaObject->add('array-string-key', ['foo' => 'bar']); + $metaObject->add('bool', true); + $metaObject->add('int', 42); + $metaObject->add('float', 4.2); + $metaObject->add('null', null); + $metaObject->add('object', new \stdClass); + $metaObject->add('string', 'foo'); + + $array = $metaObject->toArray(); + + $this->assertCount(9, $array); + } + public function testFromObject_HappyPath() { $object = new \stdClass(); $object->foo = 'bar'; diff --git a/tests/objects/RelationshipObjectTest.php b/tests/objects/RelationshipObjectTest.php index a09dec13..8ce618d6 100644 --- a/tests/objects/RelationshipObjectTest.php +++ b/tests/objects/RelationshipObjectTest.php @@ -1,9 +1,12 @@ setResource(new ResourceObject('user', 42)); $this->validateToOneRelationshipArray($relationshipObject->toArray()); } public function testConstructor_ToMany() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $relationshipObject->addResource(new ResourceObject('user', 42)); $this->validateToManyRelationshipArray($relationshipObject->toArray()); } - public function testConstructor_UnknownType() { - $this->expectException(InputException::class); - - $relationshipObject = new RelationshipObject('foo'); - } - public function testFromAnything_WithResourceObject() { $resourceObject = new ResourceObject('user', 42); $resourceObject->addMeta('foo', 'bar'); @@ -68,19 +65,9 @@ public function testFromAnything_WithResourceObjects() { $this->validateToManyRelationshipArray($relationshipObject->toArray()); } - public function testFromAnything_WithUnknownType() { - $fakeResource = new \stdClass(); - $fakeResource->type = 'user'; - $fakeResource->id = 42; - - $this->expectException(InputException::class); - - RelationshipObject::fromAnything($fakeResource); - } - public function testFromResource_ToMany() { $resourceObject = new ResourceObject('user', 42); - $type = RelationshipObject::TO_MANY; + $type = RelationshipTypeEnum::ToMany; $relationshipObject = RelationshipObject::fromResource($resourceObject, $links=[], $meta=[], $type); @@ -137,7 +124,7 @@ public function testFromCollectionDocument_WithMeta() { } public function testSetSelfLink_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->setSelfLink('https://jsonapi.org'); $array = $relationshipObject->toArray(); @@ -148,7 +135,7 @@ public function testSetSelfLink_HappyPath() { } public function testSetRelatedLink_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->setRelatedLink('https://jsonapi.org'); $array = $relationshipObject->toArray(); @@ -159,7 +146,7 @@ public function testSetRelatedLink_HappyPath() { } public function testSetPaginationLinks_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $baseUrl = 'https://jsonapi.org/?page='; $relationshipObject->setPaginationLinks($baseUrl.'prev', $baseUrl.'next', $baseUrl.'first', $baseUrl.'last'); @@ -179,7 +166,7 @@ public function testSetPaginationLinks_HappyPath() { } public function testSetPaginationLinks_BlockedOnToOne() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->expectException(InputException::class); @@ -187,7 +174,7 @@ public function testSetPaginationLinks_BlockedOnToOne() { } public function testAddMeta_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->assertTrue($relationshipObject->isEmpty()); @@ -205,7 +192,7 @@ public function testAddMeta_HappyPath() { public function testHasResource_ToMany() { $resourceObject = new ResourceObject('user', 42); - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $relationshipObject->addResource($resourceObject); $this->assertTrue($relationshipObject->hasResource($resourceObject)); @@ -214,7 +201,7 @@ public function testHasResource_ToMany() { } public function testGetContainedResources_SkipsResourceIdentifierObjects() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $resourceIdentifierObject = new ResourceIdentifierObject('user', 24); $resourceObjectIdentifierOnly = new ResourceObject('user', 42); $resourceObjectWithAttributes = new ResourceObject('user', 42); @@ -236,14 +223,14 @@ public function testGetContainedResources_SkipsResourceIdentifierObjects() { } public function testSetResource_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->setResource(new ResourceObject('user', 42)); $this->validateToOneRelationshipArray($relationshipObject->toArray()); } public function testSetResource_RequiresToOneType() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $this->expectException(InputException::class); @@ -251,14 +238,14 @@ public function testSetResource_RequiresToOneType() { } public function testAddResource_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $relationshipObject->addResource(new ResourceObject('user', 42)); $this->validateToManyRelationshipArray($relationshipObject->toArray()); } public function testAddResource_RequiresToOneType() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->expectException(InputException::class); @@ -266,7 +253,7 @@ public function testAddResource_RequiresToOneType() { } public function testAddLinkObject_HappyPath() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->assertTrue($relationshipObject->isEmpty()); @@ -284,7 +271,7 @@ public function testAddLinkObject_HappyPath() { } public function testToArray_EmptyResource() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $array = $relationshipObject->toArray(); @@ -293,7 +280,7 @@ public function testToArray_EmptyResource() { } public function testToArray_EmptyResources() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_MANY); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToMany); $array = $relationshipObject->toArray(); @@ -302,7 +289,7 @@ public function testToArray_EmptyResources() { } public function testIsEmpty_WithAtMembers() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->assertTrue($relationshipObject->isEmpty()); @@ -315,7 +302,7 @@ public function testIsEmpty_WithAtMembers() { * @group Extensions */ public function testIsEmpty_WithExtensionMembers() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $this->assertTrue($relationshipObject->isEmpty()); diff --git a/tests/objects/RelationshipsObjectTest.php b/tests/objects/RelationshipsObjectTest.php index a1eb5101..9c98b613 100644 --- a/tests/objects/RelationshipsObjectTest.php +++ b/tests/objects/RelationshipsObjectTest.php @@ -1,7 +1,10 @@ addRelationshipObject($key='foo', $relationshipObject); diff --git a/tests/objects/ResourceIdentifierObjectTest.php b/tests/objects/ResourceIdentifierObjectTest.php index b7eb1eaf..6383aa20 100644 --- a/tests/objects/ResourceIdentifierObjectTest.php +++ b/tests/objects/ResourceIdentifierObjectTest.php @@ -1,5 +1,7 @@ toArray(); - $this->assertArrayHasKey('type', $array); + $this->assertArrayNotHasKey('type', $array); $this->assertArrayNotHasKey('id', $array); - $this->assertNull($array['type']); + $this->assertSame([], $array); $this->assertFalse($resourceIdentifierObject->hasIdentification()); $this->expectException(Exception::class); diff --git a/tests/objects/ResourceObjectTest.php b/tests/objects/ResourceObjectTest.php index f2873d63..693c8595 100644 --- a/tests/objects/ResourceObjectTest.php +++ b/tests/objects/ResourceObjectTest.php @@ -1,7 +1,10 @@ setResource(new ResourceObject('user', 42)); $resourceObject = new ResourceObject('user', 24); @@ -151,7 +154,7 @@ public function testAddRelationshipObject_HappyPath() { } public function testAddRelationshipObject_BlockDrosteEffect() { - $relationshipObject = new RelationshipObject(RelationshipObject::TO_ONE); + $relationshipObject = new RelationshipObject(RelationshipTypeEnum::ToOne); $relationshipObject->setResource(new ResourceObject('user', 42)); $resourceObject = new ResourceObject('user', 42); diff --git a/tests/profiles/CursorPaginationProfileTest.php b/tests/profiles/CursorPaginationProfileTest.php index 41fa3ef5..5b9a8c2a 100644 --- a/tests/profiles/CursorPaginationProfileTest.php +++ b/tests/profiles/CursorPaginationProfileTest.php @@ -1,5 +1,7 @@ officialLink = $officialLink; } - public function getOfficialLink() { + public function getOfficialLink(): string { return $this->officialLink; } }