diff --git a/README.md b/README.md index 3366a1a8..618e6dd4 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Assuming you've got an ```$author``` of type ```\Author``` you can encode it to ```php $encoder = Encoder::instance([ '\Author' => '\AuthorSchema', -], new JsonEncodeOptions(JSON_PRETTY_PRINT)); +], new EncoderOptions(JSON_PRETTY_PRINT, 'http://example.com/api/v1')); echo $encoder->encode($author) . PHP_EOL; ``` @@ -52,7 +52,7 @@ will output "last_name": "Dow" }, "links": { - "self": "http:\/\/example.com\/people\/123" + "self": "http://example.com/api/v1/people/123" } } } @@ -64,7 +64,7 @@ The ```AuthorSchema``` provides information about resource's attributes and migh class AuthorSchema extends SchemaProvider { protected $resourceType = 'people'; - protected $baseSelfUrl = 'http://example.com/people/'; + protected $selfSubUrl = '/people/'; public function getId($author) { @@ -83,6 +83,10 @@ class AuthorSchema extends SchemaProvider } ``` +The first ```EncoderOptions``` parameter ```JSON_PRETTY_PRINT``` is a PHP predefined [JSON constant](http://php.net/manual/en/json.constants.php). + +The second ```EncoderOptions``` parameter ```http://example.com/api/v1``` is a URL prefix that will be applied to all encoded links unless they have ```$treatAsHref``` flag set to ```true```. + **For more advanced usage please check out the [Wiki](https://github.com/neomerx/json-api/wiki)**. ## Questions? diff --git a/sample/composer.json b/sample/composer.json index c3e73c99..005e7252 100644 --- a/sample/composer.json +++ b/sample/composer.json @@ -16,6 +16,6 @@ }, "minimum-stability": "dev", "require": { - "neomerx/json-api": "0.4.2" + "neomerx/json-api": "~0.5.0" } } diff --git a/sample/sample.php b/sample/sample.php index 4361bb0c..b3ac7346 100644 --- a/sample/sample.php +++ b/sample/sample.php @@ -18,7 +18,7 @@ use \Neomerx\JsonApi\Schema\Link; use \Neomerx\JsonApi\Encoder\Encoder; -use \Neomerx\JsonApi\Encoder\JsonEncodeOptions; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\JsonApi\Parameters\EncodingParameters; require './vendor/autoload.php'; @@ -39,7 +39,7 @@ private function showBasicExample() $encoder = Encoder::instance([ Author::class => AuthorSchema::class, - ], new JsonEncodeOptions(JSON_PRETTY_PRINT)); + ], new EncoderOptions(JSON_PRETTY_PRINT, 'http://example.com/api/v1')); echo $encoder->encode($author) . PHP_EOL; } @@ -64,7 +64,7 @@ private function showIncludedObjectsExample() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class - ], new JsonEncodeOptions(JSON_PRETTY_PRINT)); + ], new EncoderOptions(JSON_PRETTY_PRINT, 'http://example.com')); echo $encoder->encode($site) . PHP_EOL; } @@ -97,7 +97,7 @@ private function showSparseAndFieldSetsExample() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class - ], new JsonEncodeOptions(JSON_PRETTY_PRINT)); + ], new EncoderOptions(JSON_PRETTY_PRINT)); echo $encoder->encode($site, null, null, $options) . PHP_EOL; } @@ -119,10 +119,10 @@ private function showTopLevelMetaAndLinksExample() ] ]; $links = [ - Link::FIRST => new Link('http://example.com/people?first'), - Link::LAST => new Link('http://example.com/people?last'), - Link::PREV => new Link('http://example.com/people?prev'), - Link::NEXT => new Link('http://example.com/people?next'), + Link::FIRST => new Link('http://example.com/people?first', null, true), + Link::LAST => new Link('http://example.com/people?last', null, true), + Link::PREV => new Link('http://example.com/people?prev', null, true), + Link::NEXT => new Link('http://example.com/people?next', null, true), ]; $encoder = Encoder::instance([ @@ -130,7 +130,7 @@ private function showTopLevelMetaAndLinksExample() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class - ], new JsonEncodeOptions(JSON_PRETTY_PRINT)); + ], new EncoderOptions(JSON_PRETTY_PRINT, 'http://example.com')); echo $encoder->encode($author, $links, $meta) . PHP_EOL; } @@ -166,7 +166,7 @@ private function runPerformanceTest($iterations) $encoder->encode( $site, - [Link::SELF => new Link('http://example.com/sites/1?' . $rand)], + [Link::SELF => new Link('http://example.com/sites/1?' . $rand, null, true)], ['some' => ['meta' => 'information' . $rand]], $options ); diff --git a/sample/schemas/AuthorSchema.php b/sample/schemas/AuthorSchema.php index 2ea54b0d..deb7bf41 100644 --- a/sample/schemas/AuthorSchema.php +++ b/sample/schemas/AuthorSchema.php @@ -24,7 +24,7 @@ class AuthorSchema extends SchemaProvider { protected $resourceType = 'people'; - protected $baseSelfUrl = 'http://example.com/people/'; + protected $selfSubUrl = '/people/'; public function getId($author) { diff --git a/sample/schemas/CommentSchema.php b/sample/schemas/CommentSchema.php index 646a39e5..8998101d 100644 --- a/sample/schemas/CommentSchema.php +++ b/sample/schemas/CommentSchema.php @@ -24,7 +24,7 @@ class CommentSchema extends SchemaProvider { protected $resourceType = 'comments'; - protected $baseSelfUrl = 'http://example.com/comments/'; + protected $selfSubUrl = '/comments/'; protected $isShowSelfInIncluded = true; diff --git a/sample/schemas/PostSchema.php b/sample/schemas/PostSchema.php index 43a3607c..d092732c 100644 --- a/sample/schemas/PostSchema.php +++ b/sample/schemas/PostSchema.php @@ -24,7 +24,7 @@ class PostSchema extends SchemaProvider { protected $resourceType = 'posts'; - protected $baseSelfUrl = 'http://example.com/posts'; + protected $selfSubUrl = '/posts/'; public function getId($post) { diff --git a/sample/schemas/SiteSchema.php b/sample/schemas/SiteSchema.php index 23a01458..5da1f757 100644 --- a/sample/schemas/SiteSchema.php +++ b/sample/schemas/SiteSchema.php @@ -24,7 +24,7 @@ class SiteSchema extends SchemaProvider { protected $resourceType = 'sites'; - protected $baseSelfUrl = 'http://example.com/sites'; + protected $selfSubUrl = '/sites/'; public function getId($site) { diff --git a/src/Codec/CodecMatcher.php b/src/Codec/CodecMatcher.php index e7cd3deb..10ced135 100644 --- a/src/Codec/CodecMatcher.php +++ b/src/Codec/CodecMatcher.php @@ -52,12 +52,12 @@ class CodecMatcher implements CodecMatcherInterface private $inputMediaTypes; /** - * @var EncoderInterface|null + * @var EncoderInterface|Closure|null */ private $foundEncoder; /** - * @var DecoderInterface|null + * @var DecoderInterface|Closure|null */ private $foundDecoder; @@ -102,17 +102,43 @@ public function registerDecoder(MediaTypeInterface $mediaType, Closure $decoderC */ public function getEncoder() { + if ($this->foundEncoder instanceof Closure) { + $closure = $this->foundEncoder; + $this->foundEncoder = $closure(); + } + return $this->foundEncoder; } + /** + * @inheritdoc + */ + public function setEncoder($encoder) + { + $this->foundEncoder = $encoder; + } + /** * @inheritdoc */ public function getDecoder() { + if ($this->foundDecoder instanceof Closure) { + $closure = $this->foundDecoder; + $this->foundDecoder = $closure(); + } + return $this->foundDecoder; } + /** + * @inheritdoc + */ + public function setDecoder($decoder) + { + $this->foundDecoder = $decoder; + } + /** * @inheritdoc */ @@ -126,7 +152,7 @@ public function matchEncoder(AcceptHeaderInterface $acceptHeader) if ($registeredType->matchesTo($headerMediaType) === true) { $this->encoderHeaderMatchedType = $headerMediaType; $this->encoderRegisteredMatchedType = $registeredType; - $this->foundEncoder = $closure(); + $this->foundEncoder = $closure; return; } @@ -154,7 +180,7 @@ public function findDecoder(HeaderInterface $contentTypeHeader) if ($registeredType->equalsTo($headerMediaType) === true) { $this->decoderHeaderMatchedType = $headerMediaType; $this->decoderRegisteredMatchedType = $registeredType; - $this->foundDecoder = $closure(); + $this->foundDecoder = $closure; return; } diff --git a/src/Contracts/Codec/CodecMatcherInterface.php b/src/Contracts/Codec/CodecMatcherInterface.php index 6cfd5d5b..59eca2ac 100644 --- a/src/Contracts/Codec/CodecMatcherInterface.php +++ b/src/Contracts/Codec/CodecMatcherInterface.php @@ -56,6 +56,15 @@ public function registerDecoder(MediaTypeInterface $mediaType, Closure $decoderC */ public function getEncoder(); + /** + * Set encoder. + * + * @param EncoderInterface|Closure $encoder + * + * @return void + */ + public function setEncoder($encoder); + /** * Get decoder. * @@ -63,6 +72,15 @@ public function getEncoder(); */ public function getDecoder(); + /** + * Set decoder. + * + * @param DecoderInterface|Closure $decoder + * + * @return DecoderInterface + */ + public function setDecoder($decoder); + /** * Find best encoder match for 'Accept' header. * diff --git a/src/Contracts/Document/DocumentFactoryInterface.php b/src/Contracts/Document/DocumentFactoryInterface.php index f643b1b9..d567a31c 100644 --- a/src/Contracts/Document/DocumentFactoryInterface.php +++ b/src/Contracts/Document/DocumentFactoryInterface.php @@ -16,6 +16,8 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; + /** * @package Neomerx\JsonApi */ @@ -31,20 +33,20 @@ public function createDocument(); /** * Create error instance. * - * @param int|string|null $idx - * @param string|null $href - * @param string|null $status - * @param string|null $code - * @param string|null $title - * @param string|null $detail - * @param mixed|null $source - * @param array|null $meta + * @param int|string|null $idx + * @param LinkInterface|null $aboutLink + * @param string|null $status + * @param string|null $code + * @param string|null $title + * @param string|null $detail + * @param mixed|null $source + * @param array|null $meta * * @return ErrorInterface */ public function createError( $idx = null, - $href = null, + LinkInterface $aboutLink = null, $status = null, $code = null, $title = null, diff --git a/src/Contracts/Document/DocumentInterface.php b/src/Contracts/Document/DocumentInterface.php index 15f1ad20..64ef7643 100644 --- a/src/Contracts/Document/DocumentInterface.php +++ b/src/Contracts/Document/DocumentInterface.php @@ -57,13 +57,17 @@ interface DocumentInterface const KEYWORD_DATA = 'data'; /** Reserved keyword */ const KEYWORD_INCLUDED = 'included'; + /** Reserved keyword */ + const KEYWORD_JSON_API = 'jsonapi'; + /** Reserved keyword */ + const KEYWORD_VERSION = 'version'; /** Reserved keyword */ const KEYWORD_ERRORS = 'errors'; /** Reserved keyword */ const KEYWORD_ERRORS_ID = 'id'; /** Reserved keyword */ - const KEYWORD_ERRORS_HREF = 'href'; + const KEYWORD_ERRORS_LINKS = self::KEYWORD_LINKS; /** Reserved keyword */ const KEYWORD_ERRORS_STATUS = 'status'; /** Reserved keyword */ @@ -76,11 +80,13 @@ interface DocumentInterface const KEYWORD_ERRORS_META = 'meta'; /** Reserved keyword */ const KEYWORD_ERRORS_SOURCE = 'source'; + /** Reserved keyword */ + const KEYWORD_ERRORS_ABOUT = 'about'; /** * Set URLs to top-level 'links' section. * - * @param LinkInterface[]|null $links + * @param array|null $links * * @return void */ @@ -133,16 +139,6 @@ public function addRelationshipToData( ResourceObjectInterface $resource ); - /** - * Add a reference to resource in 'data' section. - * - * @param ResourceObjectInterface $parent - * @param RelationshipObjectInterface $current - * - * @return void - */ - public function addReferenceToData(ResourceObjectInterface $parent, RelationshipObjectInterface $current); - /** * Add an empty relationship to resource in 'data' section. * @@ -187,16 +183,6 @@ public function addRelationshipToIncluded( ResourceObjectInterface $resource ); - /** - * Add a reference to resource in 'included' section. - * - * @param ResourceObjectInterface $parent - * @param RelationshipObjectInterface $current - * - * @return void - */ - public function addReferenceToIncluded(ResourceObjectInterface $parent, RelationshipObjectInterface $current); - /** * Add an empty relationship to resource in 'included' section. * @@ -243,6 +229,29 @@ public function setResourceCompleted(ResourceObjectInterface $resource); */ public function addError(ErrorInterface $error); + /** + * Add JSON API version information. + * + * @link http://jsonapi.org/format/#document-jsonapi-object + * + * @param string $version + * @param mixed|null $meta + * + * @return void + */ + public function addJsonApiVersion($version, $meta = null); + + /** + * Set a prefix that will be applied to all URLs in the document except marked as href. + * + * @see LinkInterface + * + * @param string $prefix + * + * @return void + */ + public function setUrlPrefix($prefix); + /** * Remove 'data' top-level section. * diff --git a/src/Contracts/Document/ErrorInterface.php b/src/Contracts/Document/ErrorInterface.php index 341325dd..738e2f03 100644 --- a/src/Contracts/Document/ErrorInterface.php +++ b/src/Contracts/Document/ErrorInterface.php @@ -22,18 +22,18 @@ interface ErrorInterface { /** - * Get a unique identifier for this particular occurrence of the problem. + * Get a unique identifier for this particular occurrence of the problem. * * @return int|string|null */ public function getId(); /** - * Get a URI that may yield further details about this particular occurrence of the problem. + * Get links that may lead to further details about this particular occurrence of the problem. * - * @return string|null + * @return null|array */ - public function getHref(); + public function getLinks(); /** * Get the HTTP status code applicable to this problem, expressed as a string value. diff --git a/src/Contracts/Encoder/EncoderInterface.php b/src/Contracts/Encoder/EncoderInterface.php index 03ca080b..8c7d1efb 100644 --- a/src/Contracts/Encoder/EncoderInterface.php +++ b/src/Contracts/Encoder/EncoderInterface.php @@ -16,7 +16,7 @@ * limitations under the License. */ -use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\JsonApi\Contracts\Document\ErrorInterface; use \Neomerx\JsonApi\Contracts\Parameters\EncodingParametersInterface; @@ -25,11 +25,14 @@ */ interface EncoderInterface { + /** JSON API version implemented by the encoder */ + const JSON_API_VERSION = '1.0'; + /** * Encode input as JSON API string. * * @param object|array $data Data to encode. - * @param LinkInterface[]|null $links Optional document links information (e.g. request URL, paging). + * @param array|null $links Optional document links information (e.g. request URL, paging). * @param array|object|null $meta Optional document meta information. * @param EncodingParametersInterface|null $parameters Encoding parameters. * @@ -63,4 +66,11 @@ public function error(ErrorInterface $error); * @return string */ public function errors($errors); + + /** + * Get encoder options. + * + * @return EncoderOptions|null + */ + public function getEncoderOptions(); } diff --git a/src/Contracts/Encoder/Parser/ParserReplyInterface.php b/src/Contracts/Encoder/Parser/ParserReplyInterface.php index 43f3709a..de387193 100644 --- a/src/Contracts/Encoder/Parser/ParserReplyInterface.php +++ b/src/Contracts/Encoder/Parser/ParserReplyInterface.php @@ -25,14 +25,12 @@ interface ParserReplyInterface { /** Indicates resource description started */ const REPLY_TYPE_RESOURCE_STARTED = 0; - /** Indicates resource description completed */ + /** Indicates resource description started */ const REPLY_TYPE_NULL_RESOURCE_STARTED = 1; - /** Indicates resource description completed */ + /** Indicates resource description started */ const REPLY_TYPE_EMPTY_RESOURCE_STARTED = 2; /** Indicates resource description completed */ - const REPLY_TYPE_REFERENCE_STARTED = 3; - /** Indicates resource description completed */ - const REPLY_TYPE_RESOURCE_COMPLETED = 4; + const REPLY_TYPE_RESOURCE_COMPLETED = 3; /** * Get reply type. diff --git a/src/Contracts/Integration/CurrentRequestInterface.php b/src/Contracts/Integration/CurrentRequestInterface.php index 3d946862..33f7db72 100644 --- a/src/Contracts/Integration/CurrentRequestInterface.php +++ b/src/Contracts/Integration/CurrentRequestInterface.php @@ -40,7 +40,7 @@ public function getQueryParameters(); * * @param string $name * - * @return string|array|null + * @return string */ public function getHeader($name); } diff --git a/src/Contracts/Integration/ExceptionThrowerInterface.php b/src/Contracts/Integration/ExceptionThrowerInterface.php index a3bfe43d..4eac82fd 100644 --- a/src/Contracts/Integration/ExceptionThrowerInterface.php +++ b/src/Contracts/Integration/ExceptionThrowerInterface.php @@ -28,6 +28,12 @@ interface ExceptionThrowerInterface */ public function throwBadRequest(); + /** + * Throw 'Forbidden' exception (HTTP code 403). + * + * @return void + */ + public function throwForbidden(); /** * Throw 'Not Acceptable' exception (HTTP code 406). * @@ -35,6 +41,13 @@ public function throwBadRequest(); */ public function throwNotAcceptable(); + /** + * Throw 'Conflict' exception (HTTP code 409). + * + * @return void + */ + public function throwConflict(); + /** * Throw 'Unsupported Media Type' exception (HTTP code 415). * diff --git a/src/Contracts/Parameters/ParametersInterface.php b/src/Contracts/Parameters/ParametersInterface.php index 27584425..0a68d825 100644 --- a/src/Contracts/Parameters/ParametersInterface.php +++ b/src/Contracts/Parameters/ParametersInterface.php @@ -71,4 +71,11 @@ public function getFilteringParameters(); * @return array|null */ public function getUnrecognizedParameters(); + + /** + * Returns true if inclusion, field set, sorting, paging, filtering and unrecognized parameters are empty. + * + * @return bool + */ + public function isEmpty(); } diff --git a/src/Contracts/Parameters/ParametersParserInterface.php b/src/Contracts/Parameters/ParametersParserInterface.php index a91d1974..1f1ce787 100644 --- a/src/Contracts/Parameters/ParametersParserInterface.php +++ b/src/Contracts/Parameters/ParametersParserInterface.php @@ -24,6 +24,21 @@ */ interface ParametersParserInterface { + /** Parameter name */ + const PARAM_INCLUDE = 'include'; + + /** Parameter name */ + const PARAM_FIELDS = 'fields'; + + /** Parameter name */ + const PARAM_PAGE = 'page'; + + /** Parameter name */ + const PARAM_FILTER = 'filter'; + + /** Parameter name */ + const PARAM_SORT = 'sort'; + /** * Parse input parameters from request. * diff --git a/src/Contracts/Schema/LinkInterface.php b/src/Contracts/Schema/LinkInterface.php index 889ded07..570e09f8 100644 --- a/src/Contracts/Schema/LinkInterface.php +++ b/src/Contracts/Schema/LinkInterface.php @@ -51,4 +51,11 @@ public function getSubHref(); * @return array|object|null */ public function getMeta(); + + /** + * If $subHref is a full URL and must not be concatenated with other URLs. + * + * @return bool + */ + public function isTreatAsHref(); } diff --git a/src/Contracts/Schema/RelationshipObjectInterface.php b/src/Contracts/Schema/RelationshipObjectInterface.php index d444d48e..b261a359 100644 --- a/src/Contracts/Schema/RelationshipObjectInterface.php +++ b/src/Contracts/Schema/RelationshipObjectInterface.php @@ -29,32 +29,25 @@ interface RelationshipObjectInterface public function getName(); /** - * If 'self' endpoint URL should be shown. - * - * @return bool - */ - public function isShowSelf(); - - /** - * Get 'self' URL of link object. + * Get resource data from relationship. * - * @return LinkInterface + * @return object|array|null */ - public function getSelfLink(); + public function getData(); /** - * If link should be shown as URL reference ('related'). + * Get links. * - * @return bool + * @return array */ - public function isShowAsReference(); + public function getLinks(); /** - * If 'related' endpoint URL should be shown. + * Get meta. * - * @return bool + * @return mixed */ - public function isShowRelated(); + public function getMeta(); /** * If 'data' should be shown. @@ -62,39 +55,4 @@ public function isShowRelated(); * @return bool */ public function isShowData(); - - /** - * Get 'related' URL of link object. - * - * @return LinkInterface - */ - public function getRelatedLink(); - - /** - * If 'meta' should be shown. - * - * @return bool - */ - public function isShowMeta(); - - /** - * If pagination information should be shown. - * - * @return bool - */ - public function isShowPagination(); - - /** - * Get resource data from relationship. - * - * @return object|array|null - */ - public function getData(); - - /** - * Get pagination information. - * - * @return LinkInterface[]|null - */ - public function getPagination(); } diff --git a/src/Contracts/Schema/ResourceObjectInterface.php b/src/Contracts/Schema/ResourceObjectInterface.php index 5303c78c..0a9f74cf 100644 --- a/src/Contracts/Schema/ResourceObjectInterface.php +++ b/src/Contracts/Schema/ResourceObjectInterface.php @@ -47,49 +47,63 @@ public function getAttributes(); * * @return array|object|null */ - public function getMeta(); + public function getPrimaryMeta(); /** - * Get resource 'self' endpoint URL. + * Get meta-information about resource relationships when resource is primary. * - * @return string + * @return array|object|null */ - public function getSelfUrl(); + public function getRelationshipsPrimaryMeta(); /** - * If 'self' endpoint URL should be shown for resource in 'data' section. + * Get meta-information about resource object. * - * @return bool + * @return array|object|null */ - public function isShowSelf(); + public function getLinkageMeta(); /** - * If 'meta' should be shown for resource in 'data' section. + * Get meta-information about resource object. * - * @return bool + * @return array|object|null */ - public function isShowMeta(); + public function getInclusionMeta(); /** - * If 'self' endpoint URL should be shown for included resources. + * Get meta-information about resource relationships when resource is included. + * + * @return array|object|null + */ + public function getRelationshipsInclusionMeta(); + + /** + * Get resource 'self' endpoint URL. + * + * @return LinkInterface + */ + public function getSelfSubLink(); + + /** + * If 'self' endpoint URL should be shown for resource in 'data' section. * * @return bool */ - public function isShowSelfInIncluded(); + public function isShowSelf(); /** - * If 'meta' should be shown for included resources. + * If 'self' endpoint URL should be shown for included resources. * * @return bool */ - public function isShowMetaInIncluded(); + public function isShowSelfInIncluded(); /** - * If 'meta' should be shown in relationships. + * If resource attributes should be shown when the resource is within 'included'. * * @return bool */ - public function isShowMetaInRelationships(); + public function isShowAttributesInIncluded(); /** * If resource relationships should be shown for included resources. diff --git a/src/Contracts/Schema/SchemaFactoryInterface.php b/src/Contracts/Schema/SchemaFactoryInterface.php index f751cebc..8b239b7b 100644 --- a/src/Contracts/Schema/SchemaFactoryInterface.php +++ b/src/Contracts/Schema/SchemaFactoryInterface.php @@ -33,66 +33,32 @@ public function createContainer(array $providers = []); /** * Create resource object. * - * @param bool $isInArray - * @param string $type - * @param string $idx - * @param array $attributes - * @param mixed $meta - * @param string $selfUrl - * @param bool $isShowSelf - * @param bool $isShowMeta - * @param bool $isShowSelfInIncluded - * @param bool $isShowRelShipsInIncluded - * @param bool $isShowMetaInIncluded - * @param bool $isShowMetaInRlShips + * @param SchemaProviderInterface $schema + * @param object $resource + * @param bool $isInArray + * @param array|null $attributeKeysFilter * * @return ResourceObjectInterface */ public function createResourceObject( + SchemaProviderInterface $schema, + $resource, $isInArray, - $type, - $idx, - array $attributes, - $meta, - $selfUrl, - $isShowSelf, - $isShowMeta, - $isShowSelfInIncluded, - $isShowRelShipsInIncluded, - $isShowMetaInIncluded, - $isShowMetaInRlShips + $attributeKeysFilter = null ); /** * Create relationship object. * - * @param string $name - * @param object|array|null $data - * @param LinkInterface $selfLink - * @param LinkInterface $relatedLink - * @param bool $isShowAsRef - * @param bool $isShowSelf - * @param bool $isShowRelated - * @param bool $isShowData - * @param bool $isShowMeta - * @param bool $isShowPagination - * @param LinkInterface[]|null $pagination + * @param string $name + * @param object|array|null $data + * @param array $links + * @param mixed $meta + * @param bool $isShowData * * @return RelationshipObjectInterface */ - public function createRelationshipObject( - $name, - $data, - LinkInterface $selfLink, - LinkInterface $relatedLink, - $isShowAsRef, - $isShowSelf, - $isShowRelated, - $isShowData, - $isShowMeta, - $isShowPagination, - $pagination - ); + public function createRelationshipObject($name, $data, $links, $meta, $isShowData); /** * Create link. diff --git a/src/Contracts/Schema/SchemaProviderInterface.php b/src/Contracts/Schema/SchemaProviderInterface.php index dddb969f..63280d56 100644 --- a/src/Contracts/Schema/SchemaProviderInterface.php +++ b/src/Contracts/Schema/SchemaProviderInterface.php @@ -44,9 +44,9 @@ public function getId($resource); * * @param object $resource * - * @return string + * @return LinkInterface */ - public function getSelfUrl($resource); + public function getSelfSubLink($resource); /** * Get resource attributes. @@ -58,22 +58,24 @@ public function getSelfUrl($resource); public function getAttributes($resource); /** - * Get resource's relationship objects. + * Create resource object. * - * @param object $resource + * @param object $resource + * @param bool $isOriginallyArrayed + * @param array |null $attributeKeysFilter * - * @return Iterator LinkObjectInterface[] + * @return ResourceObjectInterface */ - public function getRelationshipObjectIterator($resource); + public function createResourceObject($resource, $isOriginallyArrayed, $attributeKeysFilter = null); /** - * Get resource meta information. + * Get resource's relationship objects. * * @param object $resource * - * @return mixed + * @return Iterator LinkObjectInterface[] */ - public function getMeta($resource); + public function getRelationshipObjectIterator($resource); /** * If 'self' endpoint URL. @@ -83,18 +85,18 @@ public function getMeta($resource); public function isShowSelf(); /** - * If 'meta' should be shown for resource. + * If 'self' endpoint URL should be shown for included resources. * * @return bool */ - public function isShowMeta(); + public function isShowSelfInIncluded(); /** - * If 'self' endpoint URL should be shown for included resources. + * If resource attributes should be shown when the resource is within 'included'. * * @return bool */ - public function isShowSelfInIncluded(); + public function isShowAttributesInIncluded(); /** * If links be shown for included resources. @@ -104,34 +106,54 @@ public function isShowSelfInIncluded(); public function isShowRelationshipsInIncluded(); /** - * If 'meta' should be shown for included resources. + * Get schema default include paths. * - * @return bool + * @return string[] */ - public function isShowMetaInIncluded(); + public function getIncludePaths(); /** - * If 'meta' should be shown in relationships. + * Get meta when resource is primary (top level 'data' section). * - * @return bool + * @param object $resource + * + * @return mixed */ - public function isShowMetaInRelationships(); + public function getPrimaryMeta($resource); /** - * Create resource object. + * Get meta when resource is within included resources. * * @param object $resource - * @param bool $isOriginallyArrayed - * @param array |null $attributeKeysFilter * - * @return ResourceObjectInterface + * @return mixed */ - public function createResourceObject($resource, $isOriginallyArrayed, array $attributeKeysFilter = null); + public function getInclusionMeta($resource); /** - * Get schema default include paths. + * Get get relationships meta when the resource is primary. * - * @return string[] + * @param object $resource + * + * @return mixed */ - public function getIncludePaths(); + public function getRelationshipsPrimaryMeta($resource); + + /** + * Get get relationships meta when the resource is within included. + * + * @param object $resource + * + * @return mixed + */ + public function getRelationshipsInclusionMeta($resource); + + /** + * Get meta when resource is within relationship of a primary resource. + * + * @param object $resource + * + * @return mixed + */ + public function getLinkageMeta($resource); } diff --git a/src/Document/Document.php b/src/Document/Document.php index 73672dfd..ea67f24c 100644 --- a/src/Document/Document.php +++ b/src/Document/Document.php @@ -38,7 +38,7 @@ class Document implements DocumentInterface private $meta; /** - * @var array + * @var array|null|string */ private $links; @@ -48,10 +48,15 @@ class Document implements DocumentInterface private $isIncludedMarks; /** - * @var array + * @var array|null */ private $included; + /** + * @var array|null + */ + private $version; + /** * @var array|null */ @@ -84,12 +89,17 @@ class Document implements DocumentInterface */ private $showData = true; + /** + * @var string|null + */ + private $urlPrefix; + /** * Constructor. */ public function __construct() { - $this->presenter = new ElementPresenter(); + $this->presenter = new ElementPresenter($this); } /** @@ -97,7 +107,7 @@ public function __construct() */ public function setDocumentLinks($links) { - $links === null ?: $this->links = $this->presenter->getLinksRepresentation($links); + $this->links = $this->presenter->getLinksRepresentation($this->urlPrefix, $links); } /** @@ -138,7 +148,7 @@ public function addToData(ResourceObjectInterface $resource) $idx = $resource->getId(); $type = $resource->getType(); assert('isset($this->bufferForData[$type][$idx]) === false'); - $this->bufferForData[$type][$idx] = $this->presenter->convertDataResourceToArray($resource); + $this->bufferForData[$type][$idx] = $this->presenter->convertDataResourceToArray($resource, true); } /** @@ -179,24 +189,6 @@ public function addRelationshipToIncluded( $this->presenter->addRelationshipTo($this->bufferForIncluded, $parent, $relationship, $resource); } - /** - * @inheritdoc - */ - public function addReferenceToData(ResourceObjectInterface $parent, RelationshipObjectInterface $current) - { - $url = $this->presenter->concatUrls($parent->getSelfUrl(), $current->getRelatedLink()); - $this->presenter->setRelationshipTo($this->bufferForData, $parent, $current, $url); - } - - /** - * @inheritdoc - */ - public function addReferenceToIncluded(ResourceObjectInterface $parent, RelationshipObjectInterface $current) - { - $url = $this->presenter->concatUrls($parent->getSelfUrl(), $current->getRelatedLink()); - $this->presenter->setRelationshipTo($this->bufferForIncluded, $parent, $current, $url); - } - /** * @inheritdoc */ @@ -243,12 +235,22 @@ public function setResourceCompleted(ResourceObjectInterface $resource) $foundInIncluded = isset($this->bufferForIncluded[$type][$idx]); if ($foundInData === true) { - $this->data[] = $this->presenter->correctRelationships($this->bufferForData[$type][$idx]); + $representation = $this->presenter->correctRelationships($this->bufferForData[$type][$idx]); + $relShipsMeta = $resource->getRelationshipsPrimaryMeta(); + if (empty($relShipsMeta) === false && isset($representation[self::KEYWORD_RELATIONSHIPS]) === true) { + $representation[self::KEYWORD_RELATIONSHIPS][self::KEYWORD_META] = $relShipsMeta; + } + $this->data[] = $representation; unset($this->bufferForData[$type][$idx]); } if ($foundInIncluded === true) { - $this->included[] = $this->presenter->correctRelationships($this->bufferForIncluded[$type][$idx]); + $representation = $this->presenter->correctRelationships($this->bufferForIncluded[$type][$idx]); + $relShipsMeta = $resource->getRelationshipsInclusionMeta(); + if (empty($relShipsMeta) === false && isset($representation[self::KEYWORD_RELATIONSHIPS]) === true) { + $representation[self::KEYWORD_RELATIONSHIPS][self::KEYWORD_META] = $relShipsMeta; + } + $this->included[] = $representation; unset($this->bufferForIncluded[$type][$idx]); } } @@ -263,6 +265,7 @@ public function getDocument() } $document = array_filter([ + self::KEYWORD_JSON_API => $this->version, self::KEYWORD_META => $this->meta, self::KEYWORD_LINKS => $this->links, self::KEYWORD_DATA => true, // this field wont be filtered @@ -281,6 +284,15 @@ public function getDocument() return $document; } + /** + * @inheritdoc + */ + public function addJsonApiVersion($version, $meta = null) + { + $this->version = $meta === null ? + [self::KEYWORD_VERSION => $version] : [self::KEYWORD_VERSION => $version, self::KEYWORD_META => $meta]; + } + /** * @inheritdoc */ @@ -298,7 +310,8 @@ public function addError(ErrorInterface $error) $representation = array_filter([ self::KEYWORD_ERRORS_ID => $errorId, - self::KEYWORD_ERRORS_HREF => $error->getHref(), + self::KEYWORD_ERRORS_LINKS => $this->presenter + ->getLinksRepresentation($this->urlPrefix, $error->getLinks()), self::KEYWORD_ERRORS_STATUS => $error->getStatus(), self::KEYWORD_ERRORS_CODE => $error->getCode(), self::KEYWORD_ERRORS_TITLE => $error->getTitle(), @@ -311,4 +324,22 @@ public function addError(ErrorInterface $error) $this->errors[] = $representation; } + + /** + * @inheritdoc + */ + public function setUrlPrefix($prefix) + { + $this->urlPrefix = (string)$prefix; + } + + /** + * Get URL prefix. + * + * @return null|string + */ + public function getUrlPrefix() + { + return $this->urlPrefix; + } } diff --git a/src/Document/DocumentFactory.php b/src/Document/DocumentFactory.php index 5f9a78b7..faf6b6c6 100644 --- a/src/Document/DocumentFactory.php +++ b/src/Document/DocumentFactory.php @@ -16,6 +16,7 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Document\DocumentFactoryInterface; /** @@ -36,7 +37,7 @@ public function createDocument() */ public function createError( $idx = null, - $href = null, + LinkInterface $aboutLink = null, $status = null, $code = null, $title = null, @@ -44,6 +45,6 @@ public function createError( $source = null, array $meta = null ) { - return new Error($idx, $href, $status, $code, $title, $detail, $source, $meta); + return new Error($idx, $aboutLink, $status, $code, $title, $detail, $source, $meta); } } diff --git a/src/Document/Error.php b/src/Document/Error.php index 652f94de..1cc09b5b 100644 --- a/src/Document/Error.php +++ b/src/Document/Error.php @@ -16,7 +16,9 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Document\ErrorInterface; +use \Neomerx\JsonApi\Contracts\Document\DocumentInterface; /** * @package Neomerx\JsonApi @@ -29,9 +31,9 @@ class Error implements ErrorInterface private $idx; /** - * @var string|null + * @var null|array */ - private $href; + private $links; /** * @var string|null @@ -64,18 +66,18 @@ class Error implements ErrorInterface private $meta; /** - * @param int|string|null $idx - * @param string|null $href - * @param string|null $status - * @param string|null $code - * @param string|null $title - * @param string|null $detail - * @param array|null $source - * @param array|null $meta + * @param int|string|null $idx + * @param LinkInterface|null $aboutLink + * @param string|null $status + * @param string|null $code + * @param string|null $title + * @param string|null $detail + * @param array|null $source + * @param array|null $meta */ public function __construct( $idx = null, - $href = null, + LinkInterface $aboutLink = null, $status = null, $code = null, $title = null, @@ -83,17 +85,15 @@ public function __construct( array $source = null, array $meta = null ) { - assert('$idx === null || is_int($idx) || is_string($idx)'); - assert('$href === null || is_string($href)'); - assert('$status === null || is_string($status)'); - assert('$code === null || is_string($code)'); - assert('$title === null || is_string($title)'); - assert('$title === null || is_string($title)'); - assert('$detail === null || is_string($detail)'); - assert('$meta === null || is_array($meta)'); + assert( + '($idx === null || is_int($idx) || is_string($idx)) &&'. + '($status === null || is_string($status)) && ($code === null || is_string($code)) &&'. + '($title === null || is_string($title)) && ($title === null || is_string($title)) &&'. + '($detail === null || is_string($detail)) && ($meta === null || is_array($meta))' + ); $this->idx = $idx; - $this->href = $href; + $this->links = ($aboutLink === null ? null : [DocumentInterface::KEYWORD_ERRORS_ABOUT => $aboutLink]); $this->status = $status; $this->code = $code; $this->title = $title; @@ -113,9 +113,9 @@ public function getId() /** * @inheritdoc */ - public function getHref() + public function getLinks() { - return $this->href; + return $this->links; } /** diff --git a/src/Document/Presenters/ElementPresenter.php b/src/Document/Presenters/ElementPresenter.php index 09745a3b..d6bfcb43 100644 --- a/src/Document/Presenters/ElementPresenter.php +++ b/src/Document/Presenters/ElementPresenter.php @@ -28,6 +28,19 @@ */ class ElementPresenter { + /** + * @var Document + */ + private $document; + + /** + * @param Document $document + */ + public function __construct(Document $document) + { + $this->document = $document; + } + /** * @param array $target * @param ResourceObjectInterface $parent @@ -120,12 +133,18 @@ public function correctRelationships(array $resource) * Convert resource object for 'data' section to array. * * @param ResourceObjectInterface $resource + * @param bool $isShowAttributes * * @return array */ - public function convertDataResourceToArray(ResourceObjectInterface $resource) + public function convertDataResourceToArray(ResourceObjectInterface $resource, $isShowAttributes) { - return $this->convertResourceToArray($resource, $resource->isShowSelf(), $resource->isShowMeta()); + return $this->convertResourceToArray( + $resource, + $resource->isShowSelf(), + $resource->getPrimaryMeta(), + $isShowAttributes + ); } /** @@ -137,45 +156,27 @@ public function convertDataResourceToArray(ResourceObjectInterface $resource) */ public function convertIncludedResourceToArray(ResourceObjectInterface $resource) { - return $this - ->convertResourceToArray($resource, $resource->isShowSelfInIncluded(), $resource->isShowMetaInIncluded()); - } - - /** - * @param string $url - * @param LinkInterface $subLink - * - * @return string|array - */ - public function concatUrls($url, LinkInterface $subLink) - { - $subUrl = $subLink->getSubHref(); - - $urlEndsWithSlash = (substr($url, -1) === '/'); - $subStartsWithSlash = (substr($subUrl, 0, 1) === '/'); - if ($urlEndsWithSlash === false && $subStartsWithSlash === false) { - $resultUrl = $url . '/' . $subUrl; - } elseif (($urlEndsWithSlash xor $subStartsWithSlash) === true) { - $resultUrl = $url . $subUrl; - } else { - $resultUrl = rtrim($url, '/') . $subUrl; - } - - return $this->getUrlRepresentation($resultUrl, $subLink->getMeta()); + return $this->convertResourceToArray( + $resource, + $resource->isShowSelfInIncluded(), + $resource->getInclusionMeta(), + $resource->isShowAttributesInIncluded() + ); } /** - * @param LinkInterface[]|null $links + * @param string|null $prefix + * @param array|null $links * - * @return string|null|array + * @return array|null|string */ - public function getLinksRepresentation($links) + public function getLinksRepresentation($prefix = null, $links = null) { $result = null; - if ($links !== null) { + if (empty($links) === false) { foreach ($links as $name => $link) { /** @var LinkInterface $link */ - $result[$name] = $this->getLinkRepresentation($link); + $result[$name] = $this->getLinkRepresentation($prefix, $link); } } @@ -211,20 +212,24 @@ private function getLinkageRepresentation(ResourceObjectInterface $resource) Document::KEYWORD_TYPE => $resource->getType(), Document::KEYWORD_ID => $resource->getId(), ]; - if ($resource->isShowMetaInRelationships() === true) { - $representation[Document::KEYWORD_META] = $resource->getMeta(); + if (($meta = $resource->getLinkageMeta()) !== null) { + $representation[Document::KEYWORD_META] = $meta; } return $representation; } /** + * @param string|null $prefix * @param LinkInterface|null $link * - * @return string|null|array + * @return array|null|string */ - private function getLinkRepresentation(LinkInterface $link = null) + private function getLinkRepresentation($prefix = null, LinkInterface $link = null) { - return $link === null ? null : $this->getUrlRepresentation($link->getSubHref(), $link->getMeta()); + return $link === null ? null : $this->getUrlRepresentation( + $link->isTreatAsHref() === true ? $link->getSubHref() : $prefix . $link->getSubHref(), + $link->getMeta() + ); } /** @@ -244,41 +249,25 @@ private function getRelationRepresentation( '"self" is a reserved keyword and cannot be used as a related resource link name' ); - $selfUrl = $parent->getSelfUrl(); - $representation = []; - if ($relation->isShowSelf() === true) { - $representation[Document::KEYWORD_LINKS][Document::KEYWORD_SELF] = - $this->concatUrls($selfUrl, $relation->getSelfLink()); - } - - if ($relation->isShowRelated() === true) { - $representation[Document::KEYWORD_LINKS][Document::KEYWORD_RELATED] = - $this->concatUrls($selfUrl, $relation->getRelatedLink()); - } if ($relation->isShowData() === true) { $representation[Document::KEYWORD_LINKAGE_DATA][] = $this->getLinkageRepresentation($resource); } - if ($relation->isShowMeta() === true) { - $representation[Document::KEYWORD_META] = $resource->getMeta(); + if (($meta = $relation->getMeta()) !== null) { + $representation[Document::KEYWORD_META] = $meta; } - if ($relation->isShowPagination() === true && $relation->getPagination() !== null) { - if (empty($representation[Document::KEYWORD_LINKS]) === true) { - $representation[Document::KEYWORD_LINKS] = - $this->getLinksRepresentation($relation->getPagination()); - } else { - $representation[Document::KEYWORD_LINKS] += - $this->getLinksRepresentation($relation->getPagination()); - } + $baseUrl = null; + if (($selfSubLink = $parent->getSelfSubLink()) !== null) { + $baseUrl = $selfSubLink->isTreatAsHref() === true ? $selfSubLink->getSubHref() . '/' : + $this->document->getUrlPrefix() . $selfSubLink->getSubHref() . '/'; } - assert( - '$relation->isShowSelf()||$relation->isShowRelated()||$relation->isShowData()||$relation->isShowMeta()', - 'Specification requires at least one of them to be shown' - ); + foreach ($relation->getLinks() as $name => $link) { + $representation[Document::KEYWORD_LINKS][$name] = $this->getLinkRepresentation($baseUrl, $link); + } return $representation; } @@ -288,14 +277,13 @@ private function getRelationRepresentation( * * @param ResourceObjectInterface $resource * @param bool $isShowSelf - * @param bool $isShowMeta + * @param mixed $meta + * @param bool $isShowAttributes * * @return array */ - private function convertResourceToArray(ResourceObjectInterface $resource, $isShowSelf, $isShowMeta) + private function convertResourceToArray(ResourceObjectInterface $resource, $isShowSelf, $meta, $isShowAttributes) { - assert('is_bool($isShowSelf) && is_bool($isShowMeta)'); - $representation = [ Document::KEYWORD_TYPE => $resource->getType(), Document::KEYWORD_ID => $resource->getId(), @@ -307,7 +295,7 @@ private function convertResourceToArray(ResourceObjectInterface $resource, $isSh 'isset($attributes[\''.Document::KEYWORD_ID.'\']) === false', '"type" and "id" are reserved keywords and cannot be used as resource object attributes' ); - if (empty($attributes) === false) { + if ($isShowAttributes === true && empty($attributes) === false) { $representation[Document::KEYWORD_ATTRIBUTES] = $attributes; } @@ -316,11 +304,12 @@ private function convertResourceToArray(ResourceObjectInterface $resource, $isSh $representation[Document::KEYWORD_RELATIONSHIPS] = null; if ($isShowSelf === true) { - $representation[Document::KEYWORD_LINKS][Document::KEYWORD_SELF] = $resource->getSelfUrl(); + $representation[Document::KEYWORD_LINKS][Document::KEYWORD_SELF] = + $this->getLinkRepresentation($this->document->getUrlPrefix(), $resource->getSelfSubLink()); } - if ($isShowMeta === true) { - $representation[Document::KEYWORD_META] = $resource->getMeta(); + if ($meta !== null) { + $representation[Document::KEYWORD_META] = $meta; } return $representation; diff --git a/src/Encoder/Encoder.php b/src/Encoder/Encoder.php index acebc31a..b31a5119 100644 --- a/src/Encoder/Encoder.php +++ b/src/Encoder/Encoder.php @@ -56,9 +56,9 @@ class Encoder implements EncoderInterface private $parametersFactory; /** - * @var JsonEncodeOptions|null + * @var EncoderOptions|null */ - protected $encodeOptions; + protected $encoderOptions; /** * @param DocumentFactoryInterface $documentFactory @@ -66,7 +66,7 @@ class Encoder implements EncoderInterface * @param HandlerFactoryInterface $handlerFactory * @param ParametersFactoryInterface $parametersFactory * @param ContainerInterface $container - * @param JsonEncodeOptions|null $encodeOptions + * @param EncoderOptions|null $encoderOptions */ public function __construct( DocumentFactoryInterface $documentFactory, @@ -74,12 +74,12 @@ public function __construct( HandlerFactoryInterface $handlerFactory, ParametersFactoryInterface $parametersFactory, ContainerInterface $container, - JsonEncodeOptions $encodeOptions = null + EncoderOptions $encoderOptions = null ) { $this->container = $container; - $this->encodeOptions = $encodeOptions; $this->parserFactory = $parserFactory; $this->handlerFactory = $handlerFactory; + $this->encoderOptions = $encoderOptions; $this->documentFactory = $documentFactory; $this->parametersFactory = $parametersFactory; } @@ -98,6 +98,10 @@ public function encode( $parserManager = $this->parserFactory->createManager($parameters); $parser = $this->parserFactory->createParser($this->container, $parserManager); $interpreter = $this->handlerFactory->createReplyInterpreter($docWriter, $parameters); + + $this->encoderOptions !== null && $this->encoderOptions->getUrlPrefix() !== null ? + $docWriter->setUrlPrefix($this->encoderOptions->getUrlPrefix()) : null; + foreach ($parser->parse($data) as $reply) { $interpreter->handle($reply); } @@ -105,6 +109,10 @@ public function encode( $meta === null ?: $docWriter->setMetaToDocument($meta); $links === null ?: $docWriter->setDocumentLinks($links); + if ($this->encoderOptions !== null && $this->encoderOptions->isShowVersionInfo() === true) { + $docWriter->addJsonApiVersion(self::JSON_API_VERSION, $this->encoderOptions->getVersionMeta()); + } + return $this->encodeToJson($docWriter->getDocument()); } @@ -147,6 +155,14 @@ public function meta($meta) return $this->encodeToJson($docWriter->getDocument()); } + /** + * @inheritdoc + */ + public function getEncoderOptions() + { + return $this->encoderOptions; + } + /** * Encode array to JSON. * @@ -156,20 +172,20 @@ public function meta($meta) */ protected function encodeToJson(array $document) { - return $this->encodeOptions === null ? + return $this->encoderOptions === null ? json_encode($document) : - json_encode($document, $this->encodeOptions->getOptions(), $this->encodeOptions->getDepth()); + json_encode($document, $this->encoderOptions->getOptions(), $this->encoderOptions->getDepth()); } /** * Create encoder instance. * - * @param array $schemas Schema providers. - * @param JsonEncodeOptions|null $encodeOptions + * @param array $schemas Schema providers. + * @param EncoderOptions|null $encodeOptions * * @return Encoder */ - public static function instance(array $schemas, JsonEncodeOptions $encodeOptions = null) + public static function instance(array $schemas, EncoderOptions $encodeOptions = null) { /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ $schemaFactory = new \Neomerx\JsonApi\Schema\SchemaFactory(); diff --git a/src/Encoder/EncoderOptions.php b/src/Encoder/EncoderOptions.php new file mode 100644 index 00000000..87c3d23e --- /dev/null +++ b/src/Encoder/EncoderOptions.php @@ -0,0 +1,124 @@ +options = $options; + $this->depth = $depth; + $this->urlPrefix = $urlPrefix; + $this->isShowVersionInfo = $isShowVersionInfo; + $this->versionMeta = $versionMeta; + } + + /** + * @link http://php.net/manual/en/function.json-encode.php + * + * @return int + */ + public function getOptions() + { + return $this->options; + } + + /** + * @link http://php.net/manual/en/function.json-encode.php + * + * @return int + */ + public function getDepth() + { + return $this->depth; + } + + /** + * If JSON API version should be rendered on document top level. + * + * @return bool + */ + public function isShowVersionInfo() + { + return $this->isShowVersionInfo; + } + + /** + * Get JSON API meta information for version. + * + * @link http://jsonapi.org/format/#document-jsonapi-object + * + * @return mixed|null + */ + public function getVersionMeta() + { + return $this->versionMeta; + } + + /** + * @return null|string + */ + public function getUrlPrefix() + { + return $this->urlPrefix; + } +} diff --git a/src/Encoder/Handlers/ReplyInterpreter.php b/src/Encoder/Handlers/ReplyInterpreter.php index 76c0d1b5..9ea55fd4 100644 --- a/src/Encoder/Handlers/ReplyInterpreter.php +++ b/src/Encoder/Handlers/ReplyInterpreter.php @@ -168,10 +168,6 @@ private function addRelationshipToData(ParserReplyInterface $reply, Frame $curre $parent = $previous->getResource(); switch($reply->getReplyType()) { - case ParserReplyInterface::REPLY_TYPE_REFERENCE_STARTED: - assert('$relationship->isShowAsReference() === true'); - $this->document->addReferenceToData($parent, $relationship); - break; case ParserReplyInterface::REPLY_TYPE_NULL_RESOURCE_STARTED: $this->document->addNullRelationshipToData($parent, $relationship); break; @@ -197,10 +193,6 @@ private function addRelationshipToIncluded(ParserReplyInterface $reply, Frame $c $parent = $previous->getResource(); switch($reply->getReplyType()) { - case ParserReplyInterface::REPLY_TYPE_REFERENCE_STARTED: - assert('$relationship->isShowAsReference() === true'); - $this->document->addReferenceToIncluded($parent, $relationship); - break; case ParserReplyInterface::REPLY_TYPE_NULL_RESOURCE_STARTED: $this->document->addNullRelationshipToIncluded($parent, $relationship); break; @@ -252,6 +244,6 @@ private function isRelationshipInFieldSet(Frame $current, Frame $previous) return true; } - return (in_array($current->getRelationship()->getName(), $fieldSet) === true); + return (in_array($current->getRelationship()->getName(), $fieldSet, true) === true); } } diff --git a/src/Encoder/JsonEncodeOptions.php b/src/Encoder/JsonEncodeOptions.php deleted file mode 100644 index 7629a93b..00000000 --- a/src/Encoder/JsonEncodeOptions.php +++ /dev/null @@ -1,61 +0,0 @@ -options = $options; - $this->depth = $depth; - } - - /** - * @return int - */ - public function getOptions() - { - return $this->options; - } - - /** - * @return int - */ - public function getDepth() - { - return $this->depth; - } -} diff --git a/src/Encoder/Parser/Parser.php b/src/Encoder/Parser/Parser.php index f4474634..a2922ae6 100644 --- a/src/Encoder/Parser/Parser.php +++ b/src/Encoder/Parser/Parser.php @@ -128,8 +128,6 @@ private function parseData($data) if (empty($data) === true) { yield $this->createReplyForEmptyData($data); - } elseif ($this->isRefFrame()) { - yield $this->createReplyForRef(); } else { if (is_array($data) === true) { $isOriginallyArrayed = true; @@ -143,8 +141,8 @@ private function parseData($data) // duplicated are allowed in data however they shouldn't be in includes $isDupAllowed = $curFrame->getLevel() < 2; + $fieldSet = $this->getFieldSet($schema->getResourceType()); foreach ($data as $resource) { - $fieldSet = $this->getFieldSet($schema->getResourceType()); $resourceObject = $schema->createResourceObject($resource, $isOriginallyArrayed, $fieldSet); $isCircular = $this->checkCircular($resourceObject); @@ -190,16 +188,6 @@ private function createReplyForEmptyData($data) return $this->parserFactory->createEmptyReply($replyType, $this->stack); } - /** - * @return ParserReplyInterface - */ - private function createReplyForRef() - { - $replyType = ParserReplyInterface::REPLY_TYPE_REFERENCE_STARTED; - - return $this->parserFactory->createEmptyReply($replyType, $this->stack); - } - /** * @return ParserReplyInterface */ @@ -246,18 +234,6 @@ private function checkCircular(ResourceObjectInterface $resourceObject) return false; } - /** - * If current stack frame should be shown as a reference. - * - * @return bool - */ - private function isRefFrame() - { - /** @var RelationshipObjectInterface $curRelObject */ - $curRelObject = $this->stack->end()->getRelationship(); - return ($curRelObject !== null && $curRelObject->isShowAsReference() === true); - } - /** * @param string $resourceType * diff --git a/src/Encoder/Parser/ParserEmptyReply.php b/src/Encoder/Parser/ParserEmptyReply.php index 0fb9f551..67852dbc 100644 --- a/src/Encoder/Parser/ParserEmptyReply.php +++ b/src/Encoder/Parser/ParserEmptyReply.php @@ -24,17 +24,14 @@ class ParserEmptyReply extends BaseReply { /** - * @param int $replyType - * @param StackReadOnlyInterface $stack + * @param int $replyType + * @param StackReadOnlyInterface $stack */ - public function __construct( - $replyType, - StackReadOnlyInterface $stack - ) { + public function __construct($replyType, StackReadOnlyInterface $stack) + { assert( '$replyType === ' . self::REPLY_TYPE_NULL_RESOURCE_STARTED . ' || '. - '$replyType === ' . self::REPLY_TYPE_EMPTY_RESOURCE_STARTED . ' || '. - '$replyType === ' . self::REPLY_TYPE_REFERENCE_STARTED + '$replyType === ' . self::REPLY_TYPE_EMPTY_RESOURCE_STARTED ); parent::__construct($replyType, $stack); diff --git a/src/Encoder/Parser/ParserReply.php b/src/Encoder/Parser/ParserReply.php index 87af8910..2c1986e3 100644 --- a/src/Encoder/Parser/ParserReply.php +++ b/src/Encoder/Parser/ParserReply.php @@ -24,8 +24,8 @@ class ParserReply extends BaseReply { /** - * @param int $replyType - * @param StackReadOnlyInterface $stack + * @param int $replyType + * @param StackReadOnlyInterface $stack */ public function __construct($replyType, StackReadOnlyInterface $stack) { diff --git a/src/Exceptions/RenderContainer.php b/src/Exceptions/RenderContainer.php index 4fee6555..9ae45fb4 100644 --- a/src/Exceptions/RenderContainer.php +++ b/src/Exceptions/RenderContainer.php @@ -20,7 +20,7 @@ use \Exception; use \Neomerx\JsonApi\Encoder\Encoder; use \Neomerx\JsonApi\Responses\Responses; -use \Neomerx\JsonApi\Encoder\JsonEncodeOptions; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\JsonApi\Contracts\Document\ErrorInterface; use \Neomerx\JsonApi\Contracts\Responses\ResponsesInterface; use \Neomerx\JsonApi\Contracts\Exceptions\RenderContainerInterface; @@ -163,12 +163,12 @@ protected function getHttpCodeRender($statusCode) protected function getErrorsRender($statusCode) { /** - * @param ErrorInterface[] $errors - * @param JsonEncodeOptions $encodeOptions + * @param ErrorInterface[] $errors + * @param EncoderOptions $encodeOptions * * @return mixed */ - return function (array $errors, JsonEncodeOptions $encodeOptions = null) use ($statusCode) { + return function (array $errors, EncoderOptions $encodeOptions = null) use ($statusCode) { $extensionsClosure = $this->extensionsClosure; /** @var SupportedExtensionsInterface $supportedExtensions */ $supportedExtensions = $extensionsClosure(); diff --git a/src/Parameters/Parameters.php b/src/Parameters/Parameters.php index 9db7942b..8622a2aa 100644 --- a/src/Parameters/Parameters.php +++ b/src/Parameters/Parameters.php @@ -133,4 +133,17 @@ public function getUnrecognizedParameters() { return $this->unrecognizedParams; } + + /** + * Returns true if inclusion, field set, sorting, paging, filtering and unrecognized parameters are empty. + * + * @return bool + */ + public function isEmpty() + { + return + empty($this->getFieldSets()) === true && empty($this->getIncludePaths()) === true && + empty($this->getSortParameters()) === true && empty($this->getPaginationParameters()) === true && + empty($this->getFilteringParameters()) === true && empty($this->getUnrecognizedParameters()) === true; + } } diff --git a/src/Parameters/ParametersParser.php b/src/Parameters/ParametersParser.php index 55ef5d5a..55c3a72b 100644 --- a/src/Parameters/ParametersParser.php +++ b/src/Parameters/ParametersParser.php @@ -32,21 +32,6 @@ */ class ParametersParser implements ParametersParserInterface { - /** Parameter name */ - const PARAM_INCLUDE = 'include'; - - /** Parameter name */ - const PARAM_FIELDS = 'fields'; - - /** Parameter name */ - const PARAM_PAGE = 'page'; - - /** Parameter name */ - const PARAM_FILTER = 'filter'; - - /** Parameter name */ - const PARAM_SORT = 'sort'; - /** * @var ParametersFactoryInterface */ @@ -76,8 +61,9 @@ public function parse(CurrentRequestInterface $request, ExceptionThrowerInterfac $contentTypeHeader = null; try { + $contentType = $request->getHeader(HeaderInterface::HEADER_CONTENT_TYPE); $contentTypeHeader = Header::parse( - $request->getHeader(HeaderInterface::HEADER_CONTENT_TYPE), + empty($contentType) === true ? MediaTypeInterface::JSON_API_MEDIA_TYPE : $contentType, HeaderInterface::HEADER_CONTENT_TYPE ); } catch (InvalidArgumentException $exception) { diff --git a/src/Parameters/RestrictiveParameterChecker.php b/src/Parameters/RestrictiveParameterChecker.php index ac1589a1..865b18b5 100644 --- a/src/Parameters/RestrictiveParameterChecker.php +++ b/src/Parameters/RestrictiveParameterChecker.php @@ -20,7 +20,6 @@ use \Neomerx\JsonApi\Contracts\Parameters\ParametersInterface; use \Neomerx\JsonApi\Contracts\Parameters\SortParameterInterface; use \Neomerx\JsonApi\Contracts\Parameters\ParameterCheckerInterface; -use \Neomerx\JsonApi\Contracts\Parameters\Headers\MediaTypeInterface; use \Neomerx\JsonApi\Contracts\Integration\ExceptionThrowerInterface; /** @@ -68,11 +67,6 @@ class RestrictiveParameterChecker implements ParameterCheckerInterface */ private $filteringParameters; - /** - * @var bool - */ - private $allowExtensionsSupport; - /** * @param ExceptionThrowerInterface $exceptionThrower * @param CodecMatcherInterface $codecMatcher @@ -82,7 +76,6 @@ class RestrictiveParameterChecker implements ParameterCheckerInterface * @param array|null $sortParameters * @param array|null $pagingParameters * @param array|null $filteringParameters - * @param bool $allowExtSupport If JSON API extensions support is allowed. */ public function __construct( ExceptionThrowerInterface $exceptionThrower, @@ -92,18 +85,16 @@ public function __construct( array $fieldSetTypes = null, array $sortParameters = null, array $pagingParameters = null, - array $filteringParameters = null, - $allowExtSupport = false + array $filteringParameters = null ) { - $this->exceptionThrower = $exceptionThrower; - $this->codecMatcher = $codecMatcher; - $this->includePaths = $includePaths; - $this->allowUnrecognized = $allowUnrecognized; - $this->fieldSetTypes = $fieldSetTypes; - $this->sortParameters = $this->flip($sortParameters); - $this->pagingParameters = $this->flip($pagingParameters); - $this->filteringParameters = $this->flip($filteringParameters); - $this->allowExtensionsSupport = $allowExtSupport; + $this->exceptionThrower = $exceptionThrower; + $this->codecMatcher = $codecMatcher; + $this->includePaths = $includePaths; + $this->allowUnrecognized = $allowUnrecognized; + $this->fieldSetTypes = $fieldSetTypes; + $this->sortParameters = $this->flip($sortParameters); + $this->pagingParameters = $this->flip($pagingParameters); + $this->filteringParameters = $this->flip($filteringParameters); } /** @@ -132,16 +123,13 @@ protected function checkAcceptHeader(ParametersInterface $parameters) { $this->codecMatcher->matchEncoder($parameters->getAcceptHeader()); - // From spec: Servers MUST return a 406 Not Acceptable status code if - // the application/vnd.api+json media type is modified by the ext parameter - // in the Accept header of a request. + // From spec: Servers MUST respond with a 406 Not Acceptable status code + // if a request's Accept header contains the JSON API media type and all + // instances of that media type are modified with media type parameters. - // We return 406 if no match found for encoder or - // if 'allowExtensionsSupport' set to false (and match found) we check 'ext' **parameter** to be not set. - // Thus it can be configured whether we support extensions or not. - - $inputMediaType = $this->codecMatcher->getEncoderHeaderMatchedType(); - if ($this->isBadMediaType($inputMediaType)) { + // We return 406 if no match found for encoder (media type with or wo parameters) + // If no encoders were configured for media types with parameters we return 406 anyway + if ($this->codecMatcher->getEncoderHeaderMatchedType() === null) { $this->exceptionThrower->throwNotAcceptable(); } } @@ -160,16 +148,13 @@ protected function checkContentTypeHeader(ParametersInterface $parameters) $this->codecMatcher->findDecoder($parameters->getContentTypeHeader()); - // From spec: servers MUST return a 415 Unsupported Media Type status code if - // the application/vnd.api+json media type is modified by the ext parameter - // in the Content-Type header of a request. - - // We return 415 if no match found for decoder or - // if 'allowExtensionsSupport' set to false (and match found) we check 'ext' **parameter** to be not set. - // Thus it can be configured whether we support extensions or not. + // From spec: Servers MUST respond with a 415 Unsupported Media Type status code + // if a request specifies the header Content-Type: application/vnd.api+json with + // any media type parameters. - $inputMediaType = $this->codecMatcher->getDecoderHeaderMatchedType(); - if ($this->isBadMediaType($inputMediaType)) { + // We return 415 if no match found for decoder (media type with or wo parameters) + // If no decoders were configured for media types with parameters we return 415 anyway + if ($this->codecMatcher->getDecoderHeaderMatchedType() === null) { $this->exceptionThrower->throwUnsupportedMediaType(); } } @@ -266,20 +251,6 @@ private function flip(array $array = null) return $array === null ? null : array_flip($array); } - /** - * @param MediaTypeInterface|null $mediaType - * - * @return bool - */ - private function isBadMediaType(MediaTypeInterface $mediaType = null) - { - return $mediaType === null || ( - $this->allowExtensionsSupport === false && - $mediaType->getMediaType() === MediaTypeInterface::JSON_API_MEDIA_TYPE && - $mediaType->getParameters() !== null && - array_key_exists(MediaTypeInterface::PARAM_EXT, $mediaType->getParameters()) === true); - } - /** * Check input fields against allowed. * diff --git a/src/Schema/Link.php b/src/Schema/Link.php index 743d0ff1..c9eb9837 100644 --- a/src/Schema/Link.php +++ b/src/Schema/Link.php @@ -33,16 +33,25 @@ class Link implements LinkInterface */ private $meta; + /** + * @var bool + */ + private $treatAsHref; + /** * @param string $subHref * @param array|object|null $meta + * @param bool $treatAsHref If $subHref is a full URL and must not be concatenated with other URLs. */ - public function __construct($subHref, $meta = null) + public function __construct($subHref, $meta = null, $treatAsHref = false) { - assert('is_string($subHref) && (is_null($meta) || is_object($meta) || is_array($meta))'); + assert( + 'is_string($subHref) && (is_null($meta) || is_object($meta) || is_array($meta)) && is_bool($treatAsHref)' + ); - $this->subHref = $subHref; - $this->meta = $meta; + $this->subHref = $subHref; + $this->meta = $meta; + $this->treatAsHref = $treatAsHref; } /** @@ -60,4 +69,12 @@ public function getMeta() { return $this->meta; } + + /** + * @inheritdoc + */ + public function isTreatAsHref() + { + return $this->treatAsHref; + } } diff --git a/src/Schema/RelationshipObject.php b/src/Schema/RelationshipObject.php index 47b5575f..92e814a8 100644 --- a/src/Schema/RelationshipObject.php +++ b/src/Schema/RelationshipObject.php @@ -16,7 +16,6 @@ * limitations under the License. */ -use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Schema\RelationshipObjectInterface; /** @@ -35,19 +34,14 @@ class RelationshipObject implements RelationshipObjectInterface private $data; /** - * @var bool + * @var array */ - private $isShowAsReference; + private $links; /** - * @var bool + * @var mixed */ - private $isShowSelf; - - /** - * @var bool - */ - private $isShowRelated; + private $meta; /** * @var bool @@ -55,79 +49,28 @@ class RelationshipObject implements RelationshipObjectInterface private $isShowData; /** - * @var LinkInterface - */ - private $selfLink; - - /** - * @var LinkInterface - */ - private $relatedLink; - - /** - * @var bool - */ - private $isShowMeta; - - /** - * @var bool - */ - private $isShowPagination; - - /** - * @var LinkInterface[]|null - */ - private $pagination; - - /** - * @param string $name - * @param object|array|null $data - * @param LinkInterface $selfLink - * @param LinkInterface $relatedLink - * @param bool $isShowAsRef - * @param bool $isShowSelf - * @param bool $isShowRelated - * @param bool $isShowData - * @param bool $isShowMeta - * @param bool $isShowPagination - * @param LinkInterface[]|null $pagination + * @param string $name + * @param object|array|null $data + * @param array $links + * @param mixed $meta + * @param bool $isShowData */ public function __construct( $name, $data, - LinkInterface $selfLink, - LinkInterface $relatedLink, - $isShowAsRef, - $isShowSelf, - $isShowRelated, - $isShowData, - $isShowMeta, - $isShowPagination, - $pagination + $links, + $meta, + $isShowData ) { assert( - 'is_string($name) &&'. - '(is_object($data) || is_array($data) || is_null($data)) &&'. - 'is_bool($isShowAsRef) && is_bool($isShowSelf) && is_bool($isShowRelated) && is_bool($isShowMeta) &&'. - 'is_bool($isShowPagination) &&'. - '(is_null($pagination) || is_array($pagination))' - ); - assert( - '$isShowSelf || $isShowRelated || $isShowData || $isShowMeta', - 'Specification requires at least one of them to be shown' + 'is_string($name) && (is_object($data) || is_array($data) || is_null($data)) && is_array($links)' ); - $this->name = $name; - $this->data = $data; - $this->selfLink = $selfLink; - $this->relatedLink = $relatedLink; - $this->isShowAsReference = $isShowAsRef; - $this->isShowSelf = $isShowSelf; - $this->isShowRelated = $isShowRelated; - $this->isShowData = $isShowData; - $this->isShowMeta = $isShowMeta; - $this->isShowPagination = $isShowPagination; - $this->pagination = $pagination; + $this->name = $name; + $this->data = $data; + $this->links = $links; + $this->meta = $meta; + $this->isShowData = $isShowData; } /** @@ -141,33 +84,25 @@ public function getName() /** * @inheritdoc */ - public function isShowSelf() - { - return $this->isShowSelf; - } - - /** - * @inheritdoc - */ - public function getSelfLink() + public function getData() { - return $this->selfLink; + return $this->data; } /** * @inheritdoc */ - public function isShowAsReference() + public function getLinks() { - return $this->isShowAsReference; + return $this->links; } /** * @inheritdoc */ - public function isShowRelated() + public function getMeta() { - return $this->isShowRelated; + return $this->meta; } /** @@ -177,44 +112,4 @@ public function isShowData() { return $this->isShowData; } - - /** - * @inheritdoc - */ - public function getRelatedLink() - { - return $this->relatedLink; - } - - /** - * @inheritdoc - */ - public function isShowMeta() - { - return $this->isShowMeta; - } - - /** - * @inheritdoc - */ - public function isShowPagination() - { - return $this->isShowPagination; - } - - /** - * @inheritdoc - */ - public function getData() - { - return $this->data; - } - - /** - * @inheritdoc - */ - public function getPagination() - { - return $this->pagination; - } } diff --git a/src/Schema/ResourceObject.php b/src/Schema/ResourceObject.php index dee784ed..3ce9551a 100644 --- a/src/Schema/ResourceObject.php +++ b/src/Schema/ResourceObject.php @@ -16,18 +16,15 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Schema\ResourceObjectInterface; +use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface; /** * @package Neomerx\JsonApi */ class ResourceObject implements ResourceObjectInterface { - /** - * @var string - */ - private $type; - /** * @var string */ @@ -41,94 +38,104 @@ class ResourceObject implements ResourceObjectInterface /** * @var mixed */ - private $meta; + private $primaryMeta; /** * @var bool */ - private $isShowSelf; + private $isPrimaryMetaSet = false; /** - * @var string + * @var LinkInterface */ - private $selfUrl; + private $selfSubLink; /** * @var bool */ - private $isShowMeta; + private $isInArray; + + /** + * @var SchemaProviderInterface + */ + private $schema; + + /** + * @var object + */ + private $resource; + + /** + * @var array|null + */ + private $attributeKeysFilter; /** * @var bool */ - private $isShowSelfInIncluded; + private $isSelfSubLinkSet = false; /** * @var bool */ - private $isShowRelationshipsInIncluded; + private $isRelationshipMetaSet = false; + + /** + * @var mixed + */ + private $relationshipMeta; /** * @var bool */ - private $isShowMetaInIncluded; + private $isInclusionMetaSet = false; + + /** + * @var mixed + */ + private $inclusionMeta; /** * @var bool */ - private $isShowMetaInRlShips; + private $isRelPrimaryMetaSet = false; + + /** + * @var mixed + */ + private $relPrimaryMeta; /** * @var bool */ - private $isInArray; + private $isRelIncMetaSet = false; /** - * @param bool $isInArray - * @param string $type - * @param string $idx - * @param array $attributes - * @param mixed $meta - * @param string $selfUrl - * @param bool $isShowSelf - * @param bool $isShowMeta - * @param bool $isShowSelfInIncluded - * @param bool $isShowRelShipsInIncluded - * @param bool $isShowMetaInIncluded - * @param bool $isShowMetaInRlShips + * @var mixed + */ + private $relInclusionMeta; + + /** + * @param SchemaProviderInterface $schema + * @param object $resource + * @param bool $isInArray + * @param array|null $attributeKeysFilter */ public function __construct( + SchemaProviderInterface $schema, + $resource, $isInArray, - $type, - $idx, - array $attributes, - $meta, - $selfUrl, - $isShowSelf, - $isShowMeta, - $isShowSelfInIncluded, - $isShowRelShipsInIncluded, - $isShowMetaInIncluded, - $isShowMetaInRlShips + array $attributeKeysFilter = null ) { assert( - 'is_bool($isInArray) && is_string($type) && is_string($idx) && is_array($attributes) &&'. - 'is_string($selfUrl) && is_bool($isShowSelf) && is_bool($isShowMeta) && is_bool($isShowMetaInRlShips) &&'. - 'is_bool($isShowSelfInIncluded) && is_bool($isShowRelShipsInIncluded) && is_bool($isShowMetaInIncluded)' + 'is_bool($isInArray) && is_object($resource) && '. + '($attributeKeysFilter === null || is_array($attributeKeysFilter))' ); - $this->isInArray = $isInArray; - $this->type = $type; - $this->idx = $idx; - $this->attributes = $attributes; - $this->meta = $meta; - $this->isShowSelf = $isShowSelf; - $this->selfUrl = $selfUrl; - $this->isShowMeta = $isShowMeta; - $this->isShowSelfInIncluded = $isShowSelfInIncluded; - $this->isShowRelationshipsInIncluded = $isShowRelShipsInIncluded; - $this->isShowMetaInIncluded = $isShowMetaInIncluded; - $this->isShowMetaInRlShips = $isShowMetaInRlShips; + $this->schema = $schema; + $this->resource = $resource; + $this->isInArray = $isInArray; + $this->attributeKeysFilter = $attributeKeysFilter; } /** @@ -136,7 +143,7 @@ public function __construct( */ public function getType() { - return $this->type; + return $this->schema->getResourceType(); } /** @@ -144,7 +151,7 @@ public function getType() */ public function getId() { - return $this->idx; + return $this->idx === null ? $this->idx = (string)$this->schema->getId($this->resource) : $this->idx; } /** @@ -152,78 +159,132 @@ public function getId() */ public function getAttributes() { + if ($this->attributes === null) { + $attributes = $this->schema->getAttributes($this->resource); + if ($this->attributeKeysFilter !== null) { + $attributes = array_intersect_key($attributes, $this->attributeKeysFilter); + } + $this->attributes = $attributes; + } + return $this->attributes; } /** * @inheritdoc */ - public function getMeta() + public function getSelfSubLink() { - return $this->meta; + if ($this->isSelfSubLinkSet === false) { + $this->selfSubLink = $this->schema->getSelfSubLink($this->resource); + $this->isSelfSubLinkSet = true; + } + + return $this->selfSubLink; } /** * @inheritdoc */ - public function getSelfUrl() + public function isShowSelf() { - return $this->selfUrl; + return $this->schema->isShowSelf(); } /** * @inheritdoc */ - public function isShowSelf() + public function isShowSelfInIncluded() { - return $this->isShowSelf; + return $this->schema->isShowSelfInIncluded(); } /** * @inheritdoc */ - public function isShowMeta() + public function isShowAttributesInIncluded() { - return $this->isShowMeta; + return $this->schema->isShowAttributesInIncluded(); } /** * @inheritdoc */ - public function isShowSelfInIncluded() + public function isShowRelationshipsInIncluded() { - return $this->isShowSelfInIncluded; + return $this->schema->isShowRelationshipsInIncluded(); } /** * @inheritdoc */ - public function isShowMetaInIncluded() + public function isInArray() { - return $this->isShowMetaInIncluded; + return $this->isInArray; } /** * @inheritdoc */ - public function isShowMetaInRelationships() + public function getPrimaryMeta() { - return $this->isShowMetaInRlShips; + if ($this->isPrimaryMetaSet === false) { + $this->primaryMeta = $this->schema->getPrimaryMeta($this->resource); + $this->isPrimaryMetaSet = true; + } + + return $this->primaryMeta; } /** * @inheritdoc */ - public function isShowRelationshipsInIncluded() + public function getInclusionMeta() { - return $this->isShowRelationshipsInIncluded; + if ($this->isInclusionMetaSet === false) { + $this->inclusionMeta = $this->schema->getInclusionMeta($this->resource); + $this->isInclusionMetaSet = true; + } + + return $this->inclusionMeta; } /** * @inheritdoc */ - public function isInArray() + public function getRelationshipsPrimaryMeta() { - return $this->isInArray; + if ($this->isRelPrimaryMetaSet === false) { + $this->relPrimaryMeta = $this->schema->getRelationshipsPrimaryMeta($this->resource); + $this->isRelPrimaryMetaSet = true; + } + + return $this->relPrimaryMeta; + } + + /** + * @inheritdoc + */ + public function getRelationshipsInclusionMeta() + { + if ($this->isRelIncMetaSet === false) { + $this->relInclusionMeta = $this->schema->getRelationshipsInclusionMeta($this->resource); + $this->isRelIncMetaSet = true; + } + + return $this->relInclusionMeta; + } + + /** + * @inheritdoc + */ + public function getLinkageMeta() + { + if ($this->isRelationshipMetaSet === false) { + $this->relationshipMeta = $this->schema->getLinkageMeta($this->resource); + $this->isRelationshipMetaSet = true; + } + + return $this->relationshipMeta; } } diff --git a/src/Schema/SchemaFactory.php b/src/Schema/SchemaFactory.php index 98a1abc7..238374c3 100644 --- a/src/Schema/SchemaFactory.php +++ b/src/Schema/SchemaFactory.php @@ -16,8 +16,8 @@ * limitations under the License. */ -use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Schema\SchemaFactoryInterface; +use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface; /** * @package Neomerx\JsonApi @@ -36,64 +36,20 @@ public function createContainer(array $providers = []) * @inheritdoc */ public function createResourceObject( + SchemaProviderInterface $schema, + $resource, $isInArray, - $type, - $idx, - array $attributes, - $meta, - $selfUrl, - $isShowSelf, - $isShowMeta, - $isShowSelfInIncluded, - $isShowRelShipsInIncluded, - $isShowMetaInIncluded, - $isShowMetaInRlShips + $attributeKeysFilter = null ) { - return new ResourceObject( - $isInArray, - $type, - $idx, - $attributes, - $meta, - $selfUrl, - $isShowSelf, - $isShowMeta, - $isShowSelfInIncluded, - $isShowRelShipsInIncluded, - $isShowMetaInIncluded, - $isShowMetaInRlShips - ); + return new ResourceObject($schema, $resource, $isInArray, $attributeKeysFilter); } /** * @inheritdoc */ - public function createRelationshipObject( - $name, - $data, - LinkInterface $selfLink, - LinkInterface $relatedLink, - $isShowAsRef, - $isShowSelf, - $isShowRelated, - $isShowData, - $isShowMeta, - $isShowPagination, - $pagination - ) { - return new RelationshipObject( - $name, - $data, - $selfLink, - $relatedLink, - $isShowAsRef, - $isShowSelf, - $isShowRelated, - $isShowData, - $isShowMeta, - $isShowPagination, - $pagination - ); + public function createRelationshipObject($name, $data, $links, $meta, $isShowData) + { + return new RelationshipObject($name, $data, $links, $meta, $isShowData); } /** diff --git a/src/Schema/SchemaProvider.php b/src/Schema/SchemaProvider.php index 40344579..920a223a 100644 --- a/src/Schema/SchemaProvider.php +++ b/src/Schema/SchemaProvider.php @@ -19,6 +19,7 @@ use \Closure; use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Schema\ContainerInterface; +use \Neomerx\JsonApi\Contracts\Document\DocumentInterface; use \Neomerx\JsonApi\Contracts\Schema\SchemaFactoryInterface; use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface; @@ -27,35 +28,32 @@ */ abstract class SchemaProvider implements SchemaProviderInterface { - /** Linked data key. */ - const DATA = 'data'; + /** Links information */ + const LINKS = DocumentInterface::KEYWORD_LINKS; - /** If link should be shown as reference. */ - const SHOW_AS_REF = 'asRef'; + /** Linked data key. */ + const DATA = DocumentInterface::KEYWORD_DATA; - /** If meta information should be shown. */ - const SHOW_META = 'showMeta'; + /** Relationship meta */ + const META = DocumentInterface::KEYWORD_META; - /** If 'self' URL should be shown. Requires 'self' controller to be set. */ + /** If 'self' URL should be shown. */ const SHOW_SELF = 'showSelf'; - /** If 'related' URL should be shown. Requires 'related' controller to be set. */ + /** If 'related' URL should be shown. */ const SHOW_RELATED = 'related'; /** If data should be shown in relationships. */ - const SHOW_DATA_IN_RELATIONSHIPS = 'showDataInRelationships'; - - /** If link pagination information should be shown. */ - const SHOW_PAGINATION = 'showPagination'; + const SHOW_DATA = 'showData'; - /** Link pagination information */ - const PAGINATION = 'pagination'; + /** Property name */ + const ATTRIBUTES = DocumentInterface::KEYWORD_ATTRIBUTES; - /** Default 'self' sub-URL could be changed with this key */ - const SELF_SUB_URL = 'selfSubUrl'; + /** Property name */ + const RELATIONSHIPS = DocumentInterface::KEYWORD_RELATIONSHIPS; - /** Default 'related' sub-URL could be changed with this key */ - const RELATED_SUB_URL = 'relatedSubUrl'; + /** Property name */ + const INCLUDED = DocumentInterface::KEYWORD_INCLUDED; /** * @var string @@ -65,23 +63,13 @@ abstract class SchemaProvider implements SchemaProviderInterface /** * @var string */ - protected $baseSelfUrl; + protected $selfSubUrl; /** * @var bool */ protected $isShowSelf = true; - /** - * @var bool - */ - protected $isShowMeta = false; - - /** - * @var bool - */ - protected $isShowMetaInRelationships = false; - /** * @var bool */ @@ -90,12 +78,12 @@ abstract class SchemaProvider implements SchemaProviderInterface /** * @var bool */ - protected $isShowRelShipsInIncluded = false; + protected $isShowAttributesInIncluded = true; /** * @var bool */ - protected $isShowMetaInIncluded = false; + protected $isShowRelShipsInIncluded = false; /** * @var SchemaFactoryInterface @@ -113,14 +101,10 @@ abstract class SchemaProvider implements SchemaProviderInterface */ public function __construct(SchemaFactoryInterface $factory, ContainerInterface $container) { - assert('is_string($this->resourceType) && empty($this->resourceType) === false', 'Resource type not set.'); - assert( - 'is_bool($this->isShowSelfInIncluded) &&'. - 'is_bool($this->isShowRelShipsInIncluded) &&'. - 'is_bool($this->isShowMetaInIncluded)' - ); - - assert('is_string($this->baseSelfUrl) && empty($this->baseSelfUrl) === false', 'Base \'self\' not set.'); + assert('is_string($this->resourceType) && empty($this->resourceType) === false', 'Resource type not set'); + assert('is_bool($this->isShowSelfInIncluded) && is_bool($this->isShowRelShipsInIncluded)'); + assert('is_string($this->selfSubUrl) && empty($this->selfSubUrl) === false', '\'self\' sub-URL not set'); + assert('substr($this->selfSubUrl, -1) === \'/\'', 'Sub-url should end with \'/\' separator'); $this->factory = $factory; $this->container = $container; @@ -137,15 +121,15 @@ public function getResourceType() /** * @inheritdoc */ - public function getSelfUrl($resource) + public function getSelfSubLink($resource) { - return $this->getBaseSelfUrl($resource).$this->getId($resource); + return new Link($this->selfSubUrl . $this->getId($resource)); } /** * @inheritdoc */ - public function getMeta($resource) + public function getPrimaryMeta($resource) { return null; } @@ -153,49 +137,65 @@ public function getMeta($resource) /** * @inheritdoc */ - public function isShowSelf() + public function getLinkageMeta($resource) { - return $this->isShowSelf; + return null; } /** * @inheritdoc */ - public function isShowMeta() + public function getInclusionMeta($resource) { - return $this->isShowMeta; + return null; } /** * @inheritdoc */ - public function isShowSelfInIncluded() + public function getRelationshipsPrimaryMeta($resource) { - return $this->isShowSelfInIncluded; + return null; } /** * @inheritdoc */ - public function isShowRelationshipsInIncluded() + public function getRelationshipsInclusionMeta($resource) { - return $this->isShowRelShipsInIncluded; + return null; } /** * @inheritdoc */ - public function isShowMetaInIncluded() + public function isShowSelf() { - return $this->isShowMetaInIncluded; + return $this->isShowSelf; } /** * @inheritdoc */ - public function isShowMetaInRelationships() + public function isShowSelfInIncluded() { - return $this->isShowMetaInRelationships; + return $this->isShowSelfInIncluded; + } + + /** + * @inheritdoc + */ + public function isShowAttributesInIncluded() + { + return $this->isShowAttributesInIncluded; + } + + /** + * @inheritdoc + */ + public function isShowRelationshipsInIncluded() + { + return $this->isShowRelShipsInIncluded; } /** @@ -214,60 +214,26 @@ public function getRelationships($resource) /** * @inheritdoc */ - public function getRelationshipObjectIterator($resource) + public function createResourceObject($resource, $isOriginallyArrayed, $attributeKeysFilter = null) { - foreach ($this->getRelationships($resource) as $name => $desc) { - $data = $this->readData($desc); - $isShowMeta = ($this->getValue($desc, self::SHOW_META, false) === true); - $isShowSelf = ($this->getValue($desc, self::SHOW_SELF, false) === true); - $isShowAsRef = ($this->getValue($desc, self::SHOW_AS_REF, false) === true); - $isShowRelated = ($this->getValue($desc, self::SHOW_RELATED, false) === true); - $isShowLinkage = ($this->getValue($desc, self::SHOW_DATA_IN_RELATIONSHIPS, true) === true); - - list($isShowPagination, $pagination) = $this->readPagination($desc); - - $selfLink = $this->getSelfLink($name, $desc, $data); - $relatedLink = $this->getRelatedLink($name, $desc, $data); - - yield $this->factory->createRelationshipObject( - $name, - $data, - $selfLink, - $relatedLink, - $isShowAsRef, - $isShowSelf, - $isShowRelated, - $isShowLinkage, - $isShowMeta, - $isShowPagination, - $pagination - ); - } + return $this->factory->createResourceObject($this, $resource, $isOriginallyArrayed, $attributeKeysFilter); } /** * @inheritdoc */ - public function createResourceObject($resource, $isOriginallyArrayed, array $attributeKeysFilter = null) + public function getRelationshipObjectIterator($resource) { - $attributes = $this->getAttributes($resource); - if ($attributeKeysFilter !== null) { - $attributes = array_intersect_key($attributes, $attributeKeysFilter); + foreach ($this->getRelationships($resource) as $name => $desc) { + $data = $this->readData($desc); + $meta = $this->getValue($desc, self::META, null); + $isShowSelf = ($this->getValue($desc, self::SHOW_SELF, false) === true); + $isShowRelated = ($this->getValue($desc, self::SHOW_RELATED, false) === true); + $isShowData = ($this->getValue($desc, self::SHOW_DATA, true) === true); + $links = $this->readLinks($name, $desc, $isShowSelf, $isShowRelated); + + yield $this->factory->createRelationshipObject($name, $data, $links, $meta, $isShowData); } - return $this->factory->createResourceObject( - $isOriginallyArrayed, - $this->getResourceType(), - (string)$this->getId($resource), - $attributes, - $this->getMeta($resource), - $this->getSelfUrl($resource), - $this->isShowSelf(), - $this->isShowMeta(), - $this->isShowSelfInIncluded(), - $this->isShowRelationshipsInIncluded(), - $this->isShowMetaInIncluded(), - $this->isShowMetaInRelationships() - ); } /** @@ -279,53 +245,24 @@ public function getIncludePaths() } /** - * Get the base self URL - * - * @param object $resource - * - * @return string - */ - protected function getBaseSelfUrl($resource) - { - $resource ?: null; - - substr($this->baseSelfUrl, -1) === '/' ?: $this->baseSelfUrl .= '/'; - - return $this->baseSelfUrl; - } - - /** - * Get link for 'self' relationship url. - * - * @param string $relationshipName - * @param array $description - * @param mixed $relationshipData - * @param null|array|object $meta + * @param string $relationshipName + * @param array $description + * @param bool $isShowSelf + * @param bool $isShowRelated * - * @return LinkInterface + * @return array */ - protected function getSelfLink($relationshipName, array $description, $relationshipData, $meta = null) + protected function readLinks($relationshipName, array $description, $isShowSelf, $isShowRelated) { - $relationshipData ?: null; - $subHref = $this->getValue($description, self::SELF_SUB_URL, '/relationships/'.$relationshipName); - return $this->factory->createLink($subHref, $meta); - } + $links = $this->getValue($description, self::LINKS, []); + if ($isShowSelf === true && isset($links[LinkInterface::SELF]) === false) { + $links[LinkInterface::SELF] = $this->factory->createLink('relationships/'.$relationshipName); + } + if ($isShowRelated === true && isset($links[LinkInterface::RELATED]) === false) { + $links[LinkInterface::RELATED] = $this->factory->createLink($relationshipName); + } - /** - * Get link for 'self' relationship url. - * - * @param string $relationshipName - * @param array $description - * @param mixed $relationshipData - * @param null|array|object $meta - * - * @return LinkInterface - */ - protected function getRelatedLink($relationshipName, array $description, $relationshipData, $meta = null) - { - $relationshipData ?: null; - $href = $this->getValue($description, self::RELATED_SUB_URL, '/'.$relationshipName); - return $this->factory->createLink($href, $meta); + return $links; } /** @@ -353,26 +290,4 @@ private function readData(array $description) } return $data; } - - /** - * @param array $description - * - * @return array - */ - private function readPagination(array $description) - { - $pagination = null; - $isShowPagination = $this->getValue($description, self::SHOW_PAGINATION, false); - - if ($isShowPagination === true && - isset($description[self::PAGINATION]) === true && - empty($description[self::PAGINATION]) === false - ) { - $pagination = $description[self::PAGINATION]; - } - - $isShowPagination = ($isShowPagination === true && $pagination !== null); - - return [$isShowPagination, $pagination]; - } } diff --git a/tests/Codec/CodecMatcherTest.php b/tests/Codec/CodecMatcherTest.php index 89a6346b..bdb32e26 100644 --- a/tests/Codec/CodecMatcherTest.php +++ b/tests/Codec/CodecMatcherTest.php @@ -265,6 +265,36 @@ public function testMatchWithZeroQ() $this->assertNull($matcher->getEncoderRegisteredMatchedType()); } + /** + * Test encoder. + */ + public function testSetEncoder() + { + $matcher = $this->getTestCodecMatcher(); + + $foo = 'foo'; + $matcher->setEncoder(function () use ($foo) { + return $foo; + }); + + $this->assertEquals($foo, $matcher->getEncoder()); + } + + /** + * Test decoder. + */ + public function testSetDecoder() + { + $matcher = $this->getTestCodecMatcher(); + + $foo = 'foo'; + $matcher->setDecoder(function () use ($foo) { + return $foo; + }); + + $this->assertEquals($foo, $matcher->getDecoder()); + } + /** * @return CodecMatcherInterface */ diff --git a/tests/Data/AuthorSchema.php b/tests/Data/AuthorSchema.php index d2ebb269..52b76bb0 100644 --- a/tests/Data/AuthorSchema.php +++ b/tests/Data/AuthorSchema.php @@ -29,7 +29,7 @@ class AuthorSchema extends DevSchemaProvider /** * @inheritdoc */ - protected $baseSelfUrl = 'http://example.com/people/'; + protected $selfSubUrl = '/people/'; /** * @inheritdoc diff --git a/tests/Data/CommentSchema.php b/tests/Data/CommentSchema.php index b6835aee..849cf2c7 100644 --- a/tests/Data/CommentSchema.php +++ b/tests/Data/CommentSchema.php @@ -34,7 +34,7 @@ class CommentSchema extends DevSchemaProvider /** * @inheritdoc */ - protected $baseSelfUrl = 'http://example.com/comments/'; + protected $selfSubUrl = '/comments/'; /** * @inheritdoc diff --git a/tests/Data/DevSchemaProvider.php b/tests/Data/DevSchemaProvider.php index c70e503c..77976986 100644 --- a/tests/Data/DevSchemaProvider.php +++ b/tests/Data/DevSchemaProvider.php @@ -46,9 +46,33 @@ abstract class DevSchemaProvider extends SchemaProvider private $includePaths = []; /** - * @var array + * @var mixed + */ + private $relationshipsMeta; + + /** + * @inheritdoc */ - private $relationshipMeta; + public function getRelationshipsPrimaryMeta($resource) + { + return $this->relationshipsMeta ?: parent::getRelationshipsPrimaryMeta($resource); + } + + /** + * @inheritdoc + */ + public function getRelationshipsInclusionMeta($resource) + { + return $this->relationshipsMeta ?: parent::getRelationshipsInclusionMeta($resource); + } + + /** + * @param array $relationshipMeta + */ + public function setRelationshipsMeta($relationshipMeta) + { + $this->relationshipsMeta = $relationshipMeta; + } /** * Add to 'add to link' list. @@ -112,14 +136,6 @@ public function setIncludePaths($includePaths) $this->includePaths = $includePaths; } - /** - * @param array $relationshipMeta - */ - public function setRelationshipMeta($relationshipMeta) - { - $this->relationshipMeta = $relationshipMeta; - } - /** * Add/remove values in input array. * @@ -139,17 +155,4 @@ protected function fixLinks(array &$links) unset($links[$key]); } } - - /** - * @param string $relationshipName - * @param array $description - * @param mixed $relationshipData - * @param null $meta - * - * @return \Neomerx\JsonApi\Contracts\Schema\LinkInterface - */ - protected function getSelfLink($relationshipName, array $description, $relationshipData, $meta = null) - { - return parent::getSelfLink($relationshipName, $description, $relationshipData, $this->relationshipMeta); - } } diff --git a/tests/Data/DummySchema.php b/tests/Data/DummySchema.php index 9dcff54a..f1feadc2 100644 --- a/tests/Data/DummySchema.php +++ b/tests/Data/DummySchema.php @@ -29,7 +29,7 @@ class DummySchema extends DevSchemaProvider /** * @inheritdoc */ - protected $baseSelfUrl = 'dummyUrl'; + protected $selfSubUrl = '/dummyUrl/'; /** * @inheritdoc diff --git a/tests/Data/PostSchema.php b/tests/Data/PostSchema.php index f44e21fc..a6824a77 100644 --- a/tests/Data/PostSchema.php +++ b/tests/Data/PostSchema.php @@ -29,7 +29,7 @@ class PostSchema extends DevSchemaProvider /** * @inheritdoc */ - protected $baseSelfUrl = 'http://example.com/posts'; + protected $selfSubUrl = '/posts/'; /** * @inheritdoc diff --git a/tests/Data/SiteSchema.php b/tests/Data/SiteSchema.php index 0b855bd1..83606c0a 100644 --- a/tests/Data/SiteSchema.php +++ b/tests/Data/SiteSchema.php @@ -32,7 +32,7 @@ class SiteSchema extends DevSchemaProvider /** * @inheritdoc */ - protected $baseSelfUrl = 'http://example.com/sites'; + protected $selfSubUrl = '/sites/'; /** * @param SchemaFactoryInterface $factory diff --git a/tests/Document/DocumentTest.php b/tests/Document/DocumentTest.php index e43b407e..e7025cc2 100644 --- a/tests/Document/DocumentTest.php +++ b/tests/Document/DocumentTest.php @@ -16,6 +16,7 @@ * limitations under the License. */ +use \Mockery; use \stdClass; use \Neomerx\JsonApi\Schema\Link; use \Neomerx\Tests\JsonApi\BaseTestCase; @@ -23,8 +24,8 @@ use \Neomerx\JsonApi\Document\DocumentFactory; use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Document\DocumentInterface; -use \Neomerx\JsonApi\Document\Presenters\ElementPresenter; use \Neomerx\JsonApi\Contracts\Schema\SchemaFactoryInterface; +use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface; use \Neomerx\JsonApi\Contracts\Document\DocumentFactoryInterface; /** @@ -121,20 +122,14 @@ public function testSetMetaToDocument() */ public function testAddToDataArrayedShowMembers() { - $this->document->addToData($resource = $this->schemaFactory->createResourceObject( - true, + $this->document->addToData($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'meta'], - 'selfUrl', - true, + new Link('selfUrl'), true, - false, - false, - false, - false - )); + ['some' => 'meta'] + ), new stdClass(), true)); $this->document->setResourceCompleted($resource); $expected = <<document->addToData($resource = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'meta'], - 'selfUrl', - false, - false, - true, - true, - true, - true - )); + null, // self url + false, // show self + null // meta + ), new stdClass(), false)); + $this->document->setResourceCompleted($resource); $expected = <<document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - false, - false, - false, - false - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('peopleSelfUrl'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'commentsSelfUrl/', - false, + null, // attributes + new Link('commentsSelfUrl/'), + true, // show self + ['this meta' => 'wont be included'], false, false, - false, - false, - false - ); + null, + ['some' => 'comment meta'] + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - true, - true, - true, - true, - true, - [Link::FIRST => new Link('/first')] + [ + LinkInterface::SELF => $this->createLink('selfSubUrl'), + LinkInterface::RELATED => $this->createLink('relatedSubUrl'), + LinkInterface::FIRST => new Link('/first', null, true), + ], + ['some' => 'relationship meta'], + true ); $this->document->addRelationshipToData($parent, $link, $resource); $this->document->setResourceCompleted($parent); @@ -286,13 +268,13 @@ public function testAddLinkToDataShowLinkMembers() }, "relationships" : { "comments-relationship" : { + "data" : { "type" : "comments", "id" : "321", "meta" : { "some" : "comment meta" } }, + "meta" : { "some" : "relationship meta" }, "links" : { "self" : "peopleSelfUrl/selfSubUrl", "related" : "peopleSelfUrl/relatedSubUrl", "first" : "/first" - }, - "data" : { "type" : "comments", "id" : "321" }, - "meta" : { "some" : "comment meta" } + } } } } @@ -302,50 +284,38 @@ public function testAddLinkToDataShowLinkMembers() } /** - * Test add link to 'data' section. Hide link members except linkage. + * Test add link to 'data' section. Hide link members except relationships. */ - public function testAddLinkToDataHideLinkMembersExceptLinkage() + public function testAddLinkToDataHideLinkMembersExceptRelationships() { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'selfUrl/', - false, - false, - false, - false, - false, - false - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('selfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'selfUrl/', - true, - true, - true, - true, - true, - true - ); + null, // attributes + new Link('commentsSelfUrl/'), + true, // show self + ['this meta' => 'wont be shown'], // meta when resource is primary + false, + false, + ['this meta' => 'wont be shown'], // meta when resource within 'included' + ['some' => 'comment meta'] // meta when resource is in relationship + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('/selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - true, - false, - false, - null + [], // links + null, // relationship meta + true // show data ); $this->document->addRelationshipToData($parent, $link, $resource); $this->document->setResourceCompleted($parent); @@ -361,7 +331,7 @@ public function testAddLinkToDataHideLinkMembersExceptLinkage() }, "relationships" : { "comments-relationship" : { - "data" : { "type" : "comments", "id" : "321", "meta" : {"some" : "comment meta"} } + "data" : { "type" : "comments", "id" : "321", "meta" : { "some" : "comment meta" } } } } } @@ -371,50 +341,38 @@ public function testAddLinkToDataHideLinkMembersExceptLinkage() } /** - * Test add multiple links to 'data' section. Hide link members except linkage. + * Test add multiple items to relationship's 'data' section. Hide link members except linkage. */ - public function testAddMultipleLinksToData() + public function testAddMultipleRelationshipItemsToData() { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'selfUrl/', - false, - false, - false, - false, - false, - false - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('selfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'selfUrl/', - true, - true, - true, - true, - true, - true - ); + null, // attributes + new Link('selfUrlWillBeHidden/'), + true, // show self + ['this meta' => 'wont be shown'], // meta when resource is primary + false, // show 'self' in 'included' + false, // show relationships in 'included' + ['this meta' => 'wont be shown'], // meta when resource within 'included' + ['some' => 'comment meta'] // meta when resource is in relationship + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('/selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - true, - false, - false, - null + [], // links + null, // relationship meta + true // show data ); $this->document->addRelationshipToData($parent, $link, $resource); $this->document->addRelationshipToData($parent, $link, $resource); @@ -448,47 +406,36 @@ public function testAddMultipleLinksToData() */ public function testAddLinkToDataHideLinkMembersExceptMeta() { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'selfUrl', - false, - false, - false, - false, - false, - false - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('selfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'selfUrl/', - true, - true, - true, - true, - true, - true - ); + null, // attributes + new Link('selfUrlWillBeHidden/'), + true, // show self + ['this meta' => 'wont be shown'], // meta when resource is primary + false, // show 'self' in 'included' + false, // show relationships in 'included' + ['this meta' => 'wont be shown'], // meta when resource within 'included' + ['some' => 'comment meta'] // meta when resource is in relationship + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - false, - true, - false, - null + [], // links + ['some' => 'relationship meta'], // relationship meta + false // show data ); + $this->document->addRelationshipToData($parent, $link, $resource); $this->document->setResourceCompleted($parent); @@ -503,7 +450,7 @@ public function testAddLinkToDataHideLinkMembersExceptMeta() }, "relationships" : { "comments-relationship" : { - "meta" : { "some" : "comment meta" } + "meta" : { "some" : "relationship meta" } } } } @@ -512,105 +459,28 @@ public function testAddLinkToDataHideLinkMembersExceptMeta() $this->check($expected); } - /** - * Test add link as reference to 'data' section. - */ - public function testAddReferenceToData() - { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, - 'people', - '123', - ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl', - false, - false, - false, - false, - false, - false - )); - $resource = $this->schemaFactory->createResourceObject( - false, - 'comments', - '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'commentsSelfUrl', - false, - false, - false, - false, - false, - false - ); - $link = $this->schemaFactory->createRelationshipObject( - 'relationship-name', - new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - true, - true, - true, - true, - true, - false, - null - ); - $this->document->addReferenceToData($parent, $link, $resource); - $this->document->setResourceCompleted($parent); - - $expected = <<check($expected); - } - /** * Test add empty (empty array) link to 'data' section. */ public function testAddEmptyLinkToData() { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'selfUrl', - false, - false, - false, - false, - false, - false - )); + new Link('peopleSelfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + $link = $this->schemaFactory->createRelationshipObject( 'relationship-name', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - false, - true, - false, - null + [], // links + ['this meta' => 'wont be shown'], // relationship meta + true // show data ); + $this->document->addEmptyRelationshipToData($parent, $link); $this->document->setResourceCompleted($parent); @@ -637,33 +507,23 @@ public function testAddEmptyLinkToData() */ public function testAddNullLinkToData() { - $this->document->addToData($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'selfUrl', - false, - false, - false, - false, - false, - false - )); + new Link('peopleSelfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + $link = $this->schemaFactory->createRelationshipObject( 'relationship-name', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - false, - true, - false, - null + [], // links + null, // relationship meta + true // show data ); + $this->document->addNullRelationshipToData($parent, $link); $this->document->setResourceCompleted($parent); @@ -690,20 +550,18 @@ public function testAddNullLinkToData() */ public function testAddToIncludedShowMembers() { - $this->document->addToIncluded($resource = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'meta'], - 'selfUrl', - false, - false, - true, - true, - true, - true - )); + new Link('peopleSelfUrl/'), // self url + false, // show self + null, // meta + true, // show 'self' in 'included' + false, // show 'relationships' in 'included' + ['some' => 'meta'] // meta when resource within 'included' + ), new stdClass(), false)); + $this->document->setResourceCompleted($resource); $expected = <<document->addToIncluded($resource = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'meta'], - 'selfUrl', - true, - true, - false, - false, - false, - false - )); + new Link('peopleSelfUrl/'), // self url + false, // show self + null // meta + ), new stdClass(), false)); + $this->document->setResourceCompleted($resource); $expected = <<document->addToIncluded($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - true, - true, - true, - true - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('peopleSelfUrl'), // self url + false, // show self + ['this meta' => 'wont be shown'], // meta when primary resource + true, // show 'self' in 'included' + false, // show 'relationships' in 'included' + ['some' => 'author meta'] // meta when resource within 'included' + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'commentsSelfUrl/', - true, - true, - true, - true, - true, - true - ); + null, // attributes + new Link('selfUrlWillBeHidden/'), + true, // show self + ['this meta' => 'wont be shown'], // meta when resource is primary + false, // show 'self' in 'included' + false, // show relationships in 'included' + ['this meta' => 'wont be shown'], // meta when resource within 'included' + ['some' => 'comment meta'] // meta when resource is in relationship + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - true, - true, - true, - true, - false, - null + [ + LinkInterface::SELF => new Link('selfSubUrl'), + LinkInterface::RELATED => new Link('relatedSubUrl'), + ], + ['some' => 'relationship meta'], // relationship meta + true // show data ); + $this->document->addRelationshipToIncluded($parent, $link, $resource); $this->document->setResourceCompleted($parent); @@ -830,16 +678,16 @@ public function testAddLinkToIncludedShowLinkMembers() }, "relationships" : { "comments-relationship" : { + "data" : { "type" : "comments", "id" : "321", "meta" : {"some" : "comment meta"} }, + "meta" : { "some" : "relationship meta" }, "links" : { "self" : "peopleSelfUrl/selfSubUrl", "related" : "peopleSelfUrl/relatedSubUrl" - }, - "data" : { "type" : "comments", "id" : "321", "meta" : {"some" : "comment meta"} }, - "meta" : { "some" : "comment meta" } + } } }, "links" : { - "self" : "peopleSelfUrl/" + "self" : "peopleSelfUrl" }, "meta" : { "some" : "author meta" @@ -855,47 +703,39 @@ public function testAddLinkToIncludedShowLinkMembers() */ public function testAddLinkToIncludedHideMembersForLinkedResource() { - $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - true, - true, - true, - true - )); - $resource = $this->schemaFactory->createResourceObject( - false, + new Link('peopleSelfUrl/'), // self url + false, // show self + ['this meta' => 'wont be shown'], // meta when primary resource + true, // show 'self' in 'included' + false, // show 'relationships' in 'included' + ['some' => 'author meta'] // meta when resource within 'included' + ), new stdClass(), false)); + + $resource = $this->schemaFactory->createResourceObject($this->getSchema( 'comments', '321', - ['title' => 'some title', 'body' => 'some body'], - ['some' => 'comment meta'], - 'commentsSelfUrl/', - true, - true, - true, - true, - true, - true - ); + null, // attributes + new Link('selfUrlWillBeHidden/'), + true, // show self + ['this meta' => 'wont be shown'], // meta when resource is primary + false, // show 'self' in 'included' + false, // show relationships in 'included' + ['this meta' => 'wont be shown'], // meta when resource within 'included' + ['some' => 'comment meta'] // meta when resource is in relationship + ), new stdClass(), false); + $link = $this->schemaFactory->createRelationshipObject( 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - false, - false, - true, - false, - false, - null + [], // links + null, // relationship meta + true // show data ); + $this->document->addRelationshipToIncluded($parent, $link, $resource); $this->document->setResourceCompleted($parent); @@ -931,33 +771,26 @@ public function testAddLinkToIncludedHideMembersForLinkedResource() */ public function testAddEmptyLinkToIncluded() { - $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - true, - true, - true, - true - )); + new Link('peopleSelfUrl/'), // self url + false, // show self + ['this meta' => 'wont be shown'], // meta when primary resource + true, // show 'self' in 'included' + false, // show 'relationships' in 'included' + ['some' => 'author meta'] // meta when resource within 'included' + ), new stdClass(), false)); + $link = $this->schemaFactory->createRelationshipObject( - 'link-name', + 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - true, - true, - true, - true, - false, - null + [], // links + null, // relationship meta + true // show data ); + $this->document->addEmptyRelationshipToIncluded($parent, $link); $this->document->setResourceCompleted($parent); @@ -972,7 +805,7 @@ public function testAddEmptyLinkToIncluded() "lastName" : "Dow" }, "relationships" : { - "link-name" : [] + "comments-relationship" : [] }, "links" : { "self" : "peopleSelfUrl/" @@ -991,94 +824,27 @@ public function testAddEmptyLinkToIncluded() */ public function testAddNullLinkToIncluded() { - $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject( - false, + $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - true, - true, - true, - true - )); - $link = $this->schemaFactory->createRelationshipObject( - 'link-name', - new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - false, - true, - true, - true, - true, - false, - null - ); - $this->document->addNullRelationshipToIncluded($parent, $link); - $this->document->setResourceCompleted($parent); + new Link('peopleSelfUrl/'), // self url + false, // show self + ['this meta' => 'wont be shown'], // meta when primary resource + true, // show 'self' in 'included' + false, // show 'relationships' in 'included' + ['some' => 'author meta'] // meta when resource within 'included' + ), new stdClass(), false)); - $expected = <<check($expected); - } - - /** - * Test add reference link to 'included' section. - */ - public function testAddReferenceLinkToIncluded() - { - $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject( - false, - 'people', - '123', - ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'author meta'], - 'peopleSelfUrl/', - false, - false, - true, - true, - true, - true - )); $link = $this->schemaFactory->createRelationshipObject( - 'relationship-name', + 'comments-relationship', new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from - $this->createLink('selfSubUrl'), - $this->createLink('relatedSubUrl'), - true, - true, - true, - true, - true, - false, - null + [], // links + null, // relationship meta + true // show data ); - $this->document->addReferenceToIncluded($parent, $link); + + $this->document->addNullRelationshipToIncluded($parent, $link); $this->document->setResourceCompleted($parent); $expected = <<document->addToData($resource = $this->schemaFactory->createResourceObject( - false, + $this->document->addToData($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', - [], - null, - '', - false, - false, - false, - false, - false, - false - )); + null, // attributes + new Link('peopleSelfUrl/'), // self url + false, // show self + null // meta when primary resource + ), new stdClass(), false)); $this->document->setResourceCompleted($resource); $expected = <<document->addError($this->documentFactory->createError( 'some-id', - 'some-href', + new Link('about-link'), 'some-status', 'some-code', 'some-title', @@ -1161,7 +921,7 @@ public function testAddError() { "errors":[{ "id" : "some-id", - "href" : "some-href", + "links" : {"about" : "about-link"}, "status" : "some-status", "code" : "some-code", "title" : "some-title", @@ -1175,16 +935,22 @@ public function testAddError() } /** - * Test URL concatenation. + * Test add JSON API version info. */ - public function testConcatUrls() + public function testAddVersion() { - $presenter = new ElementPresenter(); + $this->document->addJsonApiVersion('1.0', ['some' => 'meta']); + $this->document->unsetData(); - $this->assertEquals('url/subUrl', $presenter->concatUrls('url', $this->createLink('subUrl'))); - $this->assertEquals('url/subUrl', $presenter->concatUrls('url/', $this->createLink('subUrl'))); - $this->assertEquals('url/subUrl', $presenter->concatUrls('url', $this->createLink('/subUrl'))); - $this->assertEquals('url/subUrl', $presenter->concatUrls('url/', $this->createLink('/subUrl'))); + $expected = <<check($expected); } /** @@ -1196,20 +962,14 @@ public function testUnsetData() "some" => "values", ]); - $this->document->addToData($resource = $this->schemaFactory->createResourceObject( - true, + $this->document->addToData($resource = $this->schemaFactory->createResourceObject($this->getSchema( 'people', '123', - ['firstName' => 'John', 'lastName' => 'Dow'], - ['some' => 'meta'], - 'selfUrl', - true, - true, - false, - false, - false, - false - )); + null, // attributes + new Link('peopleSelfUrl/'), // self url + false, // show self + null // meta when primary resource + ), new stdClass(), false)); $this->document->setResourceCompleted($resource); $this->document->unsetData(); @@ -1222,6 +982,110 @@ public function testUnsetData() $this->check($expected); } + /** + * Test add meta information to relationships. + */ + public function testRelationshipsPrimaryMeta() + { + $this->document->addToData($parent = $this->schemaFactory->createResourceObject($this->getSchema( + 'people', + '123', + ['firstName' => 'John', 'lastName' => 'Dow'], + new Link('peopleSelfUrl/'), // self url + false, // show self + null, // meta + false, // show self in included + false, // show relationships in included + null, // inclusion meta + null, // relationship meta + [], // include paths + true, // show attributes in included + ['some' => 'relationships meta'] // relationships primary meta + ), new stdClass(), false)); + + $link = $this->schemaFactory->createRelationshipObject( + 'relationship-name', + new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from + [], // links + null, // relationship meta + true // show data + ); + + $this->document->addNullRelationshipToData($parent, $link); + $this->document->setResourceCompleted($parent); + + $expected = <<check($expected); + } + + /** + * Test add meta information to relationships. + */ + public function testRelationshipsInclusionMeta() + { + $this->document->addToIncluded($parent = $this->schemaFactory->createResourceObject($this->getSchema( + 'people', + '123', + ['firstName' => 'John', 'lastName' => 'Dow'], + new Link('peopleSelfUrl/'), // self url + false, // show self + null, // meta + false, // show self in included + false, // show relationships in included + null, // inclusion meta + null, // relationship meta + [], // include paths + true, // show attributes in included + null, // relationships primary meta + ['some' => 'relationships meta'] // relationships inclusion meta + ), new stdClass(), false)); + + $link = $this->schemaFactory->createRelationshipObject( + 'relationship-name', + new stdClass(), // in reality it will be a Comment class instance where $resource properties were taken from + [], // links + null, // relationship meta + true // show data + ); + + $this->document->addNullRelationshipToIncluded($parent, $link); + $this->document->setResourceCompleted($parent); + + $expected = <<check($expected); + } + /** * @param string $subHref * @@ -1242,4 +1106,58 @@ private function check($expected) $actual = json_encode($this->document->getDocument()); $this->assertEquals($expected, $actual); } + + /** + * @param string $type + * @param string $idx + * @param array|null $attributes + * @param LinkInterface|null $selfLink + * @param bool $showSelfUrl + * @param mixed $primaryMeta + * @param bool $showSelfInIncluded + * @param bool $relShipsInIncluded + * @param mixed $inclusionMeta + * @param mixed $relationshipMeta + * @param array $includePaths + * @param bool $showAttributesInIncluded + * @param mixed $relPrimaryMeta + * @param mixed $relIncMeta + * + * @return SchemaProviderInterface + */ + private function getSchema( + $type, + $idx, + $attributes, + $selfLink, + $showSelfUrl, + $primaryMeta, + $showSelfInIncluded = false, + $relShipsInIncluded = false, + $inclusionMeta = null, + $relationshipMeta = null, + $includePaths = [], + $showAttributesInIncluded = true, + $relPrimaryMeta = null, + $relIncMeta = null + ) { + $schema = Mockery::mock(SchemaProviderinterface::class); + + $schema->shouldReceive('getResourceType')->zeroOrMoreTimes()->andReturn($type); + $schema->shouldReceive('getId')->zeroOrMoreTimes()->andReturn($idx); + $schema->shouldReceive('getSelfSubLink')->zeroOrMoreTimes()->andReturn($selfLink); + $schema->shouldReceive('getAttributes')->zeroOrMoreTimes()->andReturn($attributes); + $schema->shouldReceive('isShowSelf')->zeroOrMoreTimes()->andReturn($showSelfUrl); + $schema->shouldReceive('isShowSelfInIncluded')->zeroOrMoreTimes()->andReturn($showSelfInIncluded); + $schema->shouldReceive('isShowAttributesInIncluded')->zeroOrMoreTimes()->andReturn($showAttributesInIncluded); + $schema->shouldReceive('isShowRelationshipsInIncluded')->zeroOrMoreTimes()->andReturn($relShipsInIncluded); + $schema->shouldReceive('getIncludePaths')->zeroOrMoreTimes()->andReturn($includePaths); + $schema->shouldReceive('getPrimaryMeta')->zeroOrMoreTimes()->andReturn($primaryMeta); + $schema->shouldReceive('getLinkageMeta')->zeroOrMoreTimes()->andReturn($relationshipMeta); + $schema->shouldReceive('getInclusionMeta')->zeroOrMoreTimes()->andReturn($inclusionMeta); + $schema->shouldReceive('getRelationshipsPrimaryMeta')->zeroOrMoreTimes()->andReturn($relPrimaryMeta); + $schema->shouldReceive('getRelationshipsInclusionMeta')->zeroOrMoreTimes()->andReturn($relIncMeta); + + return $schema; + } } diff --git a/tests/Document/FactoryTest.php b/tests/Document/FactoryTest.php index ca8bdcd0..8b838136 100644 --- a/tests/Document/FactoryTest.php +++ b/tests/Document/FactoryTest.php @@ -16,8 +16,10 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Schema\Link; use \Neomerx\Tests\JsonApi\BaseTestCase; use \Neomerx\JsonApi\Document\DocumentFactory; +use \Neomerx\JsonApi\Contracts\Document\DocumentInterface; use \Neomerx\JsonApi\Contracts\Document\DocumentFactoryInterface; /** @@ -55,7 +57,7 @@ public function testCreateError() { $this->assertNotNull($error = $this->factory->createError( $idx = 'some-id', - $href = 'some-href', + $link = new Link('about-link'), $status = 'some-status', $code = 'some-code', $title = 'some-title', @@ -65,7 +67,7 @@ public function testCreateError() )); $this->assertEquals($idx, $error->getId()); - $this->assertEquals($href, $error->getHref()); + $this->assertEquals([DocumentInterface::KEYWORD_ERRORS_ABOUT => $link], $error->getLinks()); $this->assertEquals($status, $error->getStatus()); $this->assertEquals($code, $error->getCode()); $this->assertEquals($title, $error->getTitle()); diff --git a/tests/Encoder/EncodeErrorsTest.php b/tests/Encoder/EncodeErrorsTest.php index cb22685b..f4368a43 100644 --- a/tests/Encoder/EncodeErrorsTest.php +++ b/tests/Encoder/EncodeErrorsTest.php @@ -16,6 +16,7 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Schema\Link; use \Neomerx\JsonApi\Document\Error; use \Neomerx\JsonApi\Encoder\Encoder; use \Neomerx\Tests\JsonApi\Data\Author; @@ -34,7 +35,7 @@ public function testEncodeError() { $error = new Error( 'some-id', - 'some-href', + new Link('about-link'), 'some-status', 'some-code', 'some-title', @@ -51,7 +52,7 @@ public function testEncodeError() { "errors":[{ "id" : "some-id", - "href" : "some-href", + "links" : {"about" : "about-link"}, "status" : "some-status", "code" : "some-code", "title" : "some-title", @@ -74,7 +75,7 @@ public function testEncodeErrors() { $error = new Error( 'some-id', - 'some-href', + new Link('about-link'), 'some-status', 'some-code', 'some-title', @@ -93,7 +94,7 @@ public function testEncodeErrors() { "errors":[{ "id" : "some-id", - "href" : "some-href", + "links" : {"about" : "about-link"}, "status" : "some-status", "code" : "some-code", "title" : "some-title", diff --git a/tests/Encoder/EncodeIncludedObjectsTest.php b/tests/Encoder/EncodeIncludedObjectsTest.php index 9945d0a6..3530afdb 100644 --- a/tests/Encoder/EncodeIncludedObjectsTest.php +++ b/tests/Encoder/EncodeIncludedObjectsTest.php @@ -25,6 +25,7 @@ use \Neomerx\Tests\JsonApi\Data\Comment; use \Neomerx\Tests\JsonApi\Data\PostSchema; use \Neomerx\Tests\JsonApi\Data\SiteSchema; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\Tests\JsonApi\Data\AuthorSchema; use \Neomerx\Tests\JsonApi\Data\CommentSchema; use \Neomerx\JsonApi\Parameters\EncodingParameters; @@ -54,6 +55,11 @@ class EncodeIncludedObjectsTest extends BaseTestCase */ private $site; + /** + * @var EncoderOptions + */ + private $encoderOptions; + /** * Set up. */ @@ -74,6 +80,7 @@ protected function setUp() $this->comments ); $this->site = Site::instance(2, 'site name', [$this->post]); + $this->encoderOptions = new EncoderOptions(0, 'http://example.com'); } /** @@ -93,7 +100,7 @@ public function testEncodeWithIncludedObjects() $schema->setIncludePaths([Post::LINK_COMMENTS]); return $schema; }, - ])->encode($this->post); + ], $this->encoderOptions)->encode($this->post); $expected = << CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class, - ])->encode($this->site, null, null, new EncodingParameters( + ], $this->encoderOptions)->encode($this->site, null, null, new EncodingParameters( // include only this relation (according to the spec intermediate will be included as well) [Site::LINK_POSTS . '.' . Post::LINK_COMMENTS], // include only these attributes and links @@ -238,7 +245,7 @@ public function testEncodeWithNullAndEmptyLinks() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class, - ])->encode($this->site); + ], $this->encoderOptions)->encode($this->site); $expected = << CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class, - ])->encode($this->site); + ], $this->encoderOptions)->encode($this->site); $expected = <<assertEquals($expected, $actual); } - /** - * Test encode included objects with reference links. - */ - public function testEncodeLinksAsRefs() - { - $actual = Encoder::instance([ - Author::class => AuthorSchema::class, - Comment::class => CommentSchema::class, - Post::class => function ($factory, $container) { - $schema = new PostSchema($factory, $container); - $schema->linkAddTo(Post::LINK_AUTHOR, PostSchema::SHOW_AS_REF, true); - $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_AS_REF, true); - return $schema; - }, - Site::class => SiteSchema::class, - ])->encode($this->site); - - $expected = <<assertEquals($expected, $actual); - } - /** * Test link objects that should not be included but these objects link to others that should. * Parser should stop parsing even if deeper objects exist. @@ -411,7 +361,7 @@ public function testEncodeLinkNonIncludableWithIncludableLinks() $schema->setIncludePaths([Site::LINK_POSTS]); return $schema; }, - ])->encode($this->site); + ], $this->encoderOptions)->encode($this->site); $expected = <<linkAddTo( Post::LINK_COMMENTS, - PostSchema::PAGINATION, - [Link::FIRST => new Link('/first')] + PostSchema::LINKS, + [Link::FIRST => new Link('comments/first')] ); - $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_PAGINATION, true); return $schema; }, - ])->encode($this->post); + ], $this->encoderOptions)->encode($this->post); $expected = <<encoderOptions = new EncoderOptions(0, 'http://example.com'); + } + /** * Test encode null. */ @@ -84,7 +96,7 @@ public function testEncodeObjectWithAttributesOnly() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ]); + ], $this->encoderOptions); $actual = $endcoder->encode($author); @@ -121,7 +133,7 @@ public function testEncodeObjectWithAttributesOnlyInArray() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ]); + ], $this->encoderOptions); $actual = $endcoder->encode([$author]); @@ -158,7 +170,7 @@ public function testEncodeObjectWithAttributesOnlyPrettyPrinted() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ], new JsonEncodeOptions(JSON_PRETTY_PRINT)); + ], new EncoderOptions(JSON_PRETTY_PRINT, 'http://example.com')); $actual = $endcoder->encode($author); @@ -194,7 +206,7 @@ public function testEncodeArrayOfObjectsWithAttributesOnly() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ]); + ], $this->encoderOptions); $actual = $endcoder->encode([$author1, $author2]); @@ -238,7 +250,7 @@ public function testEncodeArrayOfObjectsWithAttributesOnly() public function testEncodeMetaAndtopLinksForSimpleObject() { $author = Author::instance(9, 'Dan', 'Gebhardt'); - $links = [Link::SELF => new Link('http://example.com/people/9')]; + $links = [Link::SELF => new Link('/people/9')]; $meta = [ "copyright" => "Copyright 2015 Example Corp.", "authors" => [ @@ -254,7 +266,7 @@ public function testEncodeMetaAndtopLinksForSimpleObject() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ])->encode($author, $links, $meta); + ], $this->encoderOptions)->encode($author, $links, $meta); $expected = <<assertEquals($expected, $actual); } + + public function testEncodeJsonApiVersion() + { + $endcoder = Encoder::instance([], new EncoderOptions(0, null, true, ['some' => 'meta'])); + + $actual = $endcoder->encode(null); + + $expected = <<assertEquals($expected, $actual); + } } diff --git a/tests/Encoder/EncodeSparseAndFieldSetsTest.php b/tests/Encoder/EncodeSparseAndFieldSetsTest.php index 1af0e655..8dadaf64 100644 --- a/tests/Encoder/EncodeSparseAndFieldSetsTest.php +++ b/tests/Encoder/EncodeSparseAndFieldSetsTest.php @@ -24,6 +24,7 @@ use \Neomerx\Tests\JsonApi\Data\Comment; use \Neomerx\Tests\JsonApi\Data\PostSchema; use \Neomerx\Tests\JsonApi\Data\SiteSchema; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\Tests\JsonApi\Data\AuthorSchema; use \Neomerx\Tests\JsonApi\Data\CommentSchema; use \Neomerx\JsonApi\Parameters\EncodingParameters; @@ -53,6 +54,11 @@ class EncodeSparseAndFieldSetsTest extends BaseTestCase */ private $site; + /** + * @var EncoderOptions + */ + private $encoderOptions; + /** * Set up. */ @@ -73,6 +79,7 @@ protected function setUp() $this->comments ); $this->site = Site::instance(2, 'site name', [$this->post]); + $this->encoderOptions = new EncoderOptions(0, 'http://example.com'); } /** @@ -87,7 +94,7 @@ public function testEncodeWithRecursiveIncludedObjects() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class, - ])->encode($this->site, null, null, new EncodingParameters( + ], $this->encoderOptions)->encode($this->site, null, null, new EncodingParameters( [ // include only this relations Site::LINK_POSTS, @@ -183,7 +190,7 @@ public function testEncodeOnlyFieldSets() Comment::class => CommentSchema::class, Post::class => PostSchema::class, Site::class => SiteSchema::class, - ])->encode($this->site, null, null, new EncodingParameters( + ], $this->encoderOptions)->encode($this->site, null, null, new EncodingParameters( null, // include only these attributes and links [ diff --git a/tests/Encoder/EncoderTest.php b/tests/Encoder/EncoderTest.php index 5c333098..98ca69a6 100644 --- a/tests/Encoder/EncoderTest.php +++ b/tests/Encoder/EncoderTest.php @@ -16,21 +16,39 @@ * limitations under the License. */ +use \Neomerx\JsonApi\Schema\Link; use \Neomerx\JsonApi\Encoder\Encoder; use \Neomerx\Tests\JsonApi\Data\Post; use \Neomerx\Tests\JsonApi\Data\Author; use \Neomerx\Tests\JsonApi\Data\Comment; use \Neomerx\Tests\JsonApi\BaseTestCase; use \Neomerx\Tests\JsonApi\Data\PostSchema; +use \Neomerx\JsonApi\Encoder\EncoderOptions; use \Neomerx\Tests\JsonApi\Data\AuthorSchema; use \Neomerx\Tests\JsonApi\Data\CommentSchema; use \Neomerx\JsonApi\Parameters\EncodingParameters; +use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; /** * @package Neomerx\Tests\JsonApi */ class EncoderTest extends BaseTestCase { + /** + * @var EncoderOptions + */ + private $encoderOptions; + + /** + * Set up. + */ + protected function setUp() + { + parent::setUp(); + + $this->encoderOptions = new EncoderOptions(0, 'http://example.com'); + } + /** * Test encode array of simple objects with attributes only. */ @@ -43,7 +61,7 @@ public function testEncodeArrayOfDuplicateObjectsWithAttributesOnly() $schema->linkRemove(Author::LINK_COMMENTS); return $schema; } - ]); + ], $this->encoderOptions); $actual = $endcoder->encode([$author, $author]); @@ -98,7 +116,7 @@ public function testEncodeDuplicatesWithCircularReferencesInData() $schema->setIncludePaths([]); return $schema; }, - ]); + ], $this->encoderOptions); $actual = $endcoder->encode([$author, $author]); @@ -158,7 +176,7 @@ public function testEncodeDuplicatesWithRelationFieldSetFilter() $endcoder = Encoder::instance([ Author::class => AuthorSchema::class, Comment::class => CommentSchema::class, - ]); + ], $this->encoderOptions); $author->{Author::LINK_COMMENTS} = $comments; @@ -210,7 +228,7 @@ public function testEncodeSimpleLinks() Author::class => AuthorSchema::class, Comment::class => CommentSchema::class, Post::class => PostSchema::class, - ])->encode($this->getStandardPost()); + ], $this->encoderOptions)->encode($this->getStandardPost()); $expected = <<assertEquals($expected, $actual); } - /** - * Test encode resource object links as references. - */ - public function testEncodeLinkAsReference() - { - $actual = Encoder::instance([ - Author::class => AuthorSchema::class, - Comment::class => CommentSchema::class, - Post::class => function ($factory, $container) { - $schema = new PostSchema($factory, $container); - $schema->linkAddTo(Post::LINK_AUTHOR, PostSchema::SHOW_AS_REF, true); - $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_AS_REF, true); - return $schema; - }, - ])->encode($this->getStandardPost()); - - $expected = <<assertEquals($expected, $actual); - } - /** * Test encode resource object links as references. */ @@ -299,7 +276,7 @@ public function testEncodeEmptyLinks() $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::DATA, []); return $schema; }, - ])->encode($this->getStandardPost()); + ], $this->encoderOptions)->encode($this->getStandardPost()); $expected = <<linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_RELATED, true); return $schema; }, - ])->encode($this->getStandardPost()); + ], $this->encoderOptions)->encode($this->getStandardPost()); $expected = << function ($factory, $container) { $schema = new AuthorSchema($factory, $container); - $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_SELF, true); - $schema->setRelationshipMeta(['some' => 'meta']); + $schema->linkAddTo(Author::LINK_COMMENTS, AuthorSchema::SHOW_SELF, true); + $schema->linkAddTo( + Author::LINK_COMMENTS, + AuthorSchema::LINKS, + [LinkInterface::SELF => new Link('relationships/comments', ['some' => 'meta'])] + ); return $schema; }, Comment::class => CommentSchema::class, - ])->encode($author); + ], $this->encoderOptions)->encode($author); $expected = <<assertEquals($expected, $actual); + } + + /** + * Test relationships meta. + */ + public function testRelationshipsMeta() + { + $actual = Encoder::instance([ + Author::class => AuthorSchema::class, + Comment::class => CommentSchema::class, + Post::class => function ($factory, $container) { + $schema = new PostSchema($factory, $container); + $schema->setRelationshipsMeta(['some' => 'meta']); + return $schema; + }, + ], $this->encoderOptions)->encode($this->getStandardPost()); + + $expected = <<assertEquals($expected, $actual); } + /** + * Test get encoder options. + */ + public function testGetEncoderOptions() + { + $endoder = Encoder::instance([], $this->encoderOptions); + $this->assertSame($this->encoderOptions, $endoder->getEncoderOptions()); + } + /** * @return Post */ diff --git a/tests/Encoder/Parser/ParserTest.php b/tests/Encoder/Parser/ParserTest.php index 1252a357..5c49ce25 100644 --- a/tests/Encoder/Parser/ParserTest.php +++ b/tests/Encoder/Parser/ParserTest.php @@ -83,12 +83,7 @@ protected function setUp() $schemas = [ Author::class => AuthorSchema::class, Comment::class => CommentSchema::class, - Post::class => function ($factory, $container) { - $schema = new PostSchema($factory, $container); - $schema->linkAddTo(Post::LINK_AUTHOR, PostSchema::SHOW_AS_REF, true); - $schema->linkAddTo(Post::LINK_COMMENTS, PostSchema::SHOW_AS_REF, true); - return $schema; - }, + Post::class => PostSchema::class, ]; $container = (new SchemaFactory())->createContainer($schemas); $this->parser = (new EncoderFactory())->createParser($container); @@ -204,33 +199,6 @@ public function testParseObjectWithCircularReferences() $this->assertEquals($expected, $allReplies); } - /** - * Test parse link as reference. - */ - public function testParseLinkReferences() - { - $this->post->{Post::LINK_AUTHOR} = null; - - $start = ParserReplyInterface::REPLY_TYPE_RESOURCE_STARTED; - $startRef = ParserReplyInterface::REPLY_TYPE_REFERENCE_STARTED; - $startNull = ParserReplyInterface::REPLY_TYPE_NULL_RESOURCE_STARTED; - $complete = ParserReplyInterface::REPLY_TYPE_RESOURCE_COMPLETED; - $expected = [ - // level link name type id attributes meta - [$start, 1, '', 'posts', 1, $this->postAttr, null], - [$startNull, 2, 'author', '', null, null, null], - [$startRef, 2, 'comments', '', null, null, null], - [$complete, 1, '', 'posts', 1, $this->postAttr, null], - ]; - - $allReplies = []; - foreach ($this->parser->parse($this->post) as $reply) { - /** @var ParserReplyInterface $reply */ - $allReplies[] = $this->replyToArray($reply); - } - $this->assertEquals($expected, $allReplies); - } - /** * @param ParserReplyInterface $reply * @@ -248,7 +216,7 @@ private function replyToArray(ParserReplyInterface $reply) $resource === null ? null : $resource->getType(), $resource === null ? null : $resource->getId(), $resource === null ? null : $resource->getAttributes(), - $resource === null ? null : $resource->getMeta(), + $resource === null ? null : $resource->getPrimaryMeta(), ]; } } diff --git a/tests/Parameters/ParameterParserTest.php b/tests/Parameters/ParameterParserTest.php index 4b7a0267..57c36d4a 100644 --- a/tests/Parameters/ParameterParserTest.php +++ b/tests/Parameters/ParameterParserTest.php @@ -84,6 +84,8 @@ public function testHeadersWithNoExtensionsAndParameters() $this->assertNull($parameters->getSortParameters()); $this->assertNull($parameters->getFilteringParameters()); $this->assertNull($parameters->getPaginationParameters()); + + $this->assertTrue($parameters->isEmpty()); } /** diff --git a/tests/Parameters/RestrictiveParameterCheckerTest.php b/tests/Parameters/RestrictiveParameterCheckerTest.php index 5e394ba3..71353aa5 100644 --- a/tests/Parameters/RestrictiveParameterCheckerTest.php +++ b/tests/Parameters/RestrictiveParameterCheckerTest.php @@ -52,11 +52,11 @@ class RestrictiveParameterCheckerTest extends BaseTestCase * @var array */ private $requestParams = [ - 'fields' => ['type1' => 'fields1,fields2'], - 'include' => 'author,comments,comments.author', - 'sort' => '-created,+title,name.with.dots', - 'filter' => ['some' => 'filter'], - 'page' => ['size' => 10, 'offset' => 4], + ParametersParserInterface::PARAM_FIELDS => ['type1' => 'fields1,fields2'], + ParametersParserInterface::PARAM_INCLUDE => 'author,comments,comments.author', + ParametersParserInterface::PARAM_SORT => '-created,+title,name.with.dots', + ParametersParserInterface::PARAM_FILTER => ['some' => 'filter'], + ParametersParserInterface::PARAM_PAGE => ['size' => 10, 'offset' => 4], ]; /** @@ -410,56 +410,6 @@ public function testTooManyMediaTypesInContentType() $checker->check($parameters); } - /** - * Test it should throw exception if 'ext' param is set but extensions are not allowed. - */ - public function testExtentionsNotAllowed1() - { - $checker = new RestrictiveParameterChecker( - $this->prepareExceptions(), - $this->prepareCodecMatcher( - [[self::TYPE, self::SUB_TYPE, [MediaTypeInterface::PARAM_EXT => 'foo']],], - [[self::TYPE, self::SUB_TYPE, null],] - ) - ); - - $parameters = $this->parser->parse( - $this->prepareRequest( - self::JSON_API_TYPE . ';' . MediaTypeInterface::PARAM_EXT . '=foo', - self::JSON_API_TYPE, - $this->requestParams - ), - $this->prepareExceptions('throwUnsupportedMediaType') - ); - - $checker->check($parameters); - } - - /** - * Test it should throw exception if 'ext' param is set but extensions are not allowed. - */ - public function testExtentionsNotAllowed2() - { - $checker = new RestrictiveParameterChecker( - $this->prepareExceptions(), - $this->prepareCodecMatcher( - [[self::TYPE, self::SUB_TYPE, null],], - [[self::TYPE, self::SUB_TYPE, [MediaTypeInterface::PARAM_EXT => 'foo']],] - ) - ); - - $parameters = $this->parser->parse( - $this->prepareRequest( - self::JSON_API_TYPE, - self::JSON_API_TYPE . ';' . MediaTypeInterface::PARAM_EXT . '=foo', - $this->requestParams - ), - $this->prepareExceptions('throwNotAcceptable') - ); - - $checker->check($parameters); - } - /** * @param string $contentType * @param string $accept @@ -541,14 +491,7 @@ private function getCheckerWithExtensions($exceptionMethod = null) [self::TYPE, self::SUB_TYPE, null], [self::TYPE, self::SUB_TYPE, ['ext' => 'ext1,ext3']], ] - ), - false, - null, - null, - null, - null, - null, - true + ) ); return $checker; diff --git a/tests/Schema/FactoryTest.php b/tests/Schema/FactoryTest.php index faeaf87d..2d3c9828 100644 --- a/tests/Schema/FactoryTest.php +++ b/tests/Schema/FactoryTest.php @@ -22,6 +22,7 @@ use \Neomerx\JsonApi\Schema\SchemaFactory; use \Neomerx\JsonApi\Contracts\Schema\LinkInterface; use \Neomerx\JsonApi\Contracts\Schema\SchemaFactoryInterface; +use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface; /** * @package Neomerx\Tests\JsonApi @@ -55,64 +56,39 @@ public function testCreateContainer() */ public function testCreateResourceObject() { + $schema = Mockery::mock(SchemaProviderInterface::class); + $schema->shouldReceive('getResourceType')->once()->andReturn('some-type'); + + /** @var SchemaProviderInterface $schema */ + $this->assertNotNull($resource = $this->factory->createResourceObject( + $schema, + $resource = new stdClass(), $isInArray = false, - $type = 'people', - $idx = '123', - $attributes = ['firstName' => 'John', 'lastName' => 'Dow'], - $meta = ['some' => 'author meta'], - $selfUrl = 'peopleSelfUrl/', - $isShowSelf = false, - $isShowMeta = false, - $isShowSelfInIncluded = true, - $isShowLinksInIncluded = true, - $isShowMetaInIncluded = true, - $isShowMetaInRelShips = true + $attributeKeysFilter = ['field1', 'field2'] )); $this->assertEquals($isInArray, $resource->isInArray()); - $this->assertEquals($type, $resource->getType()); - $this->assertEquals($idx, $resource->getId()); - $this->assertEquals($attributes, $resource->getAttributes()); - $this->assertEquals($meta, $resource->getMeta()); - $this->assertEquals($selfUrl, $resource->getSelfUrl()); - $this->assertEquals($isShowSelf, $resource->isShowSelf()); - $this->assertEquals($isShowMeta, $resource->isShowMeta()); - $this->assertEquals($isShowSelfInIncluded, $resource->isShowSelfInIncluded()); - $this->assertEquals($isShowLinksInIncluded, $resource->isShowRelationshipsInIncluded()); - $this->assertEquals($isShowMetaInIncluded, $resource->isShowMetaInIncluded()); - $this->assertEquals($isShowMetaInRelShips, $resource->isShowMetaInRelationships()); + $this->assertSame('some-type', $resource->getType()); } /** - * Test create link object. + * Test create relationship object. */ - public function testCreateLinkObject() + public function testCreateRelationshipObject() { - $this->assertNotNull($link = $this->factory->createRelationshipObject( - $name = 'link-name', - $data = new stdClass(), - $selfSubUrl = $this->factory->createLink('selfSubUrl'), - $relatedSubUrl = $this->factory->createLink('relatedSubUrl'), - $isShowAsRef = false, - $isShowSelf = true, - $isShowRelated = true, - $isShowData = true, - $isShowMeta = true, - $isShowPagination = true, - $pagination = [Mockery::mock(LinkInterface::class)] + $this->assertNotNull($relationship = $this->factory->createRelationshipObject( + $name = 'link-name', + $data = new stdClass(), + $links = [LinkInterface::SELF => $this->factory->createLink('selfSubUrl')], + $meta = ['some' => 'meta'], + $isShowData = true )); - $this->assertEquals($name, $link->getName()); - $this->assertEquals($data, $link->getData()); - $this->assertEquals($selfSubUrl, $link->getSelfLink()); - $this->assertEquals($relatedSubUrl, $link->getRelatedLink()); - $this->assertEquals($isShowAsRef, $link->isShowAsReference()); - $this->assertEquals($isShowSelf, $link->isShowSelf()); - $this->assertEquals($isShowRelated, $link->isShowRelated()); - $this->assertEquals($isShowData, $link->isShowData()); - $this->assertEquals($isShowMeta, $link->isShowMeta()); - $this->assertEquals($isShowPagination, $link->isShowPagination()); - $this->assertSame($pagination, $link->getPagination()); + $this->assertEquals($name, $relationship->getName()); + $this->assertEquals($data, $relationship->getData()); + $this->assertEquals($links, $relationship->getLinks()); + $this->assertEquals($meta, $relationship->getMeta()); + $this->assertEquals($isShowData, $relationship->isShowData()); } }