diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..677e36e2
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 00000000..004297ab
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,13 @@
+daysUntilStale: 180
+daysUntilClose: 28
+exemptLabels:
+ - keep-open
+# Label to use when marking an issue as stale
+staleLabel: stale
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed after 4 weeks if no further activity occurs. Thank you
+ for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/.github/workflows/.editorconfig b/.github/workflows/.editorconfig
new file mode 100644
index 00000000..7bd3346f
--- /dev/null
+++ b/.github/workflows/.editorconfig
@@ -0,0 +1,2 @@
+[*.yml]
+indent_size = 2
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
new file mode 100644
index 00000000..f01fdbe3
--- /dev/null
+++ b/.github/workflows/run-tests.yml
@@ -0,0 +1,31 @@
+name: The PHP League Tests
+
+on: [push, pull_request]
+
+jobs:
+ ci:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: true
+ matrix:
+ os: [ubuntu-20.04]
+ php: [7.4, 8.0, 8.1]
+
+ name: League - PHP ${{ matrix.php }} on ${{ matrix.os }}
+
+ steps:
+
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: phpcs, phpunit
+
+ - name: Download dependencies
+ uses: ramsey/composer-install@v2
+
+ - name: Run Tests
+ run: vendor/bin/phpunit
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
new file mode 100644
index 00000000..328a6c8f
--- /dev/null
+++ b/.github/workflows/static.yml
@@ -0,0 +1,46 @@
+on: [ pull_request ]
+name: Static analysis
+
+jobs:
+ phpstan:
+ name: PHPStan
+ runs-on: ubuntu-20.04
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 8.1
+ extensions: apcu, redis
+ coverage: none
+ tools: phpstan:1.4.6, cs2pr
+
+ - name: Download dependencies
+ uses: ramsey/composer-install@v1
+
+ - name: PHPStan
+ run: phpstan analyze --no-progress --error-format=checkstyle | cs2pr
+
+ psalm:
+ name: Psalm
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 8.1
+ extensions: apcu, redis
+ coverage: none
+ tools: vimeo/psalm:4.22.0
+
+ - name: Download dependencies
+ uses: ramsey/composer-install@v1
+
+ - name: Psalm
+ run: psalm --no-progress --output-format=github
diff --git a/.github/workflows/style-checker.yml b/.github/workflows/style-checker.yml
new file mode 100644
index 00000000..68b72297
--- /dev/null
+++ b/.github/workflows/style-checker.yml
@@ -0,0 +1,32 @@
+name: The PHP League Style Checks
+
+on: [push, pull_request]
+
+jobs:
+ style:
+ runs-on: ubuntu-latest
+ name: The PHP League Style Checks
+ steps:
+
+ - name: Checkout Code
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '7.4'
+
+ - name: Cache Dependencies
+ id: composer-cache-style
+ uses: actions/cache@v2
+ with:
+ path: vendor
+ key: ubuntu-composer-cache-style-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ubuntu-php-style
+
+ - name: Install Dependencies
+ if: steps.composer-cache.outputs.cache-hit != 'true'
+ run: composer install --prefer-dist --no-progress --no-suggest
+
+ - name: Check Coding Style
+ run: vendor/bin/phpcs src/
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 458385ec..19906bc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,4 @@
composer.lock
build
vendor
-Gemfile.lock
-coverage
+.phpunit.result.cache
\ No newline at end of file
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
deleted file mode 100644
index 05e77e14..00000000
--- a/.scrutinizer.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-filter:
- excluded_paths: [tests, vendor]
-
-checks:
- php:
- remove_extra_empty_lines: true
- remove_php_closing_tag: true
- remove_trailing_whitespace: true
- fix_use_statements:
- remove_unused: true
- preserve_multiple: false
- preserve_blanklines: true
- order_alphabetically: true
- fix_php_opening_tag: true
- fix_linefeed: true
- fix_line_ending: true
- fix_identation_4spaces: true
- fix_doc_comments: true
-
-tools:
- external_code_coverage:
- timeout: 1800
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 137c4e40..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-language: php
-
-sudo: false
-
-matrix:
- include:
- - php: 7.2
- env: COLLECT_COVERAGE=true
- - php: 7.3
- - php: hhvm
- dist: trusty
-
- allow_failures:
- - php: hhvm
-
-install:
- - travis_retry composer install --no-interaction --prefer-source
-
-script:
- - if [[ "$COLLECT_COVERAGE" == "true" ]]; then vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover; else vendor/bin/phpunit --no-coverage; fi
-
-after_script:
- - if [[ "$COLLECT_COVERAGE" == "true" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b7b1171..83b2e97f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## Next
+
+### Enhancements
+- Add links for all available includes to `JsonApiSerializer` #331 - Thanks @matt-allan
+- Implement interface `\JsonSerializable` in Scopes to allow for direct usage with `json_encode()`
+
+
+
## 0.18.0 - 2019-05-09
### Enhancements
diff --git a/README.md b/README.md
index 4c6aaf98..a69cea2b 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,7 @@
[![Latest Version](https://img.shields.io/github/release/thephpleague/fractal.svg?style=flat-square)](https://github.com/thephpleague/fractal/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
-[![Build Status](https://img.shields.io/travis/thephpleague/fractal/1.0.x.svg?style=flat-square&label=tests)](https://travis-ci.org/thephpleague/fractal)
-[![Build Status](https://img.shields.io/circleci/build/gh/thephpleague/fractal/1.0.x.svg?style=flat-square&label=code+style)](https://circleci.com/gh/thephpleague/fractal)
-[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/fractal/1.0.x.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/fractal/code-structure)
-[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/fractal/1.0.x.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/fractal)
+![The PHP League Tests](https://github.com/thephpleague/fractal/workflows/The%20PHP%20League%20Tests/badge.svg)
[![Total Downloads](https://img.shields.io/packagist/dt/league/fractal.svg?style=flat-square)](https://packagist.org/packages/league/fractal)
Fractal provides a presentation and transformation layer for complex data output, the like found in
@@ -42,15 +39,9 @@ $ composer require league/fractal
## Requirements
-The following versions of PHP are supported by this version.
+The following versions of PHP are supported by this version:
-* PHP 5.4
-* PHP 5.5
-* PHP 5.6
-* PHP 7.0
-* PHP 7.1
-* PHP 7.2
-* HHVM
+>= PHP 7.4
## Documentation
@@ -72,6 +63,12 @@ $ phpunit
Please see [CONTRIBUTING](https://github.com/thephpleague/fractal/blob/master/CONTRIBUTING.md) and [CONDUCT](https://github.com/thephpleague/fractal/blob/master/CONDUCT.md) for details.
+
+## Maintainers
+
+- [Korvin Szanto](https://github.com/korvinszanto)
+- [Matt Trask](https://github.com/matthewtrask)
+
## Credits
- [Graham Daniels](https://github.com/greydnls)
diff --git a/composer.json b/composer.json
index e5d7eb21..83beee6e 100644
--- a/composer.json
+++ b/composer.json
@@ -21,13 +21,14 @@
"sort-packages": true
},
"require": {
- "php": ">=7.2"
+ "php": ">=7.4"
},
"require-dev": {
- "mockery/mockery": "~1.0",
- "phpstan/phpstan": "^0.11.8",
- "phpunit/phpunit": "~8.0",
- "squizlabs/php_codesniffer": "~3.4"
+ "mockery/mockery": ">=1.5",
+ "phpstan/phpstan": ">=1.5",
+ "phpunit/phpunit": ">=8|>=9",
+ "squizlabs/php_codesniffer": "~3.6",
+ "vimeo/psalm": "^4.22"
},
"suggest": {
"league/fractal-serializer-jsonapi": "JSON:API Serialization Support",
@@ -47,9 +48,14 @@
"League\\Fractal\\Test\\": "test"
}
},
+ "scripts": {
+ "check": "vendor/bin/phpcs src/",
+ "test": "vendor/bin/phpunit --testdox --colors=always",
+ "test:coverage": "vendor/bin/phpunit --coverage-html build/coverage"
+ },
"extra": {
"branch-alias": {
- "dev-master": "0.13-dev"
+ "dev-master": "0.20.x-dev"
}
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 12539b16..8419ff9c 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -10,11 +10,4 @@
-
-
-
-
-
-
-
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 00000000..eea23caa
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,6 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Parameter \\#1 \\$separator of function explode expects non\\-empty\\-string, string given\\.$#"
+ count: 1
+ path: src/Manager.php
\ No newline at end of file
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 00000000..1b347546
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,8 @@
+includes:
+ - ./phpstan-baseline.neon
+
+parameters:
+ level: 5
+ reportUnmatchedIgnoredErrors: false
+ paths:
+ - src
diff --git a/psalm.baseline.xml b/psalm.baseline.xml
new file mode 100644
index 00000000..c9e27b07
--- /dev/null
+++ b/psalm.baseline.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ getMeta
+
+
+ transform
+
+
+
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 00000000..e044bd6b
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Manager.php b/src/Manager.php
index e6cdf891..3366a78a 100644
--- a/src/Manager.php
+++ b/src/Manager.php
@@ -13,7 +13,7 @@
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\DataArraySerializer;
-use League\Fractal\Serializer\SerializerAbstract;
+use League\Fractal\Serializer\Serializer;
/**
* Manager
@@ -26,59 +26,40 @@ class Manager
{
/**
* Array of scope identifiers for resources to include.
- *
- * @var array
*/
- protected $requestedIncludes = [];
+ protected array $requestedIncludes = [];
/**
* Array of scope identifiers for resources to exclude.
- *
- * @var array
*/
- protected $requestedExcludes = [];
+ protected array $requestedExcludes = [];
/**
* Array of requested fieldsets.
- *
- * @var array
*/
- protected $requestedFieldsets = [];
+ protected array $requestedFieldsets = [];
/**
* Array containing modifiers as keys and an array value of params.
- *
- * @var array
*/
- protected $includeParams = [];
+ protected array $includeParams = [];
/**
* The character used to separate modifier parameters.
- *
- * @var string
*/
- protected $paramDelimiter = '|';
+ protected string $paramDelimiter = '|';
/**
* Upper limit to how many levels of included data are allowed.
- *
- * @var int
*/
- protected $recursionLimit = 10;
+ protected int $recursionLimit = 10;
- /**
- * Serializer.
- *
- * @var SerializerAbstract
- */
- protected $serializer;
+ protected ?Serializer $serializer = null;
/**
* Factory used to create new configured scopes.
- *
- * @var ScopeFactoryInterface
*/
- private $scopeFactory;
+ private ScopeFactoryInterface $scopeFactory;
public function __construct(ScopeFactoryInterface $scopeFactory = null)
{
@@ -86,18 +67,13 @@ public function __construct(ScopeFactoryInterface $scopeFactory = null)
}
/**
- * Create Data.
- *
* Main method to kick this all off. Make a resource then pass it over, and use toArray()
- *
- * @param ResourceInterface $resource
- * @param string $scopeIdentifier
- * @param Scope $parentScopeInstance
- *
- * @return Scope
*/
- public function createData(ResourceInterface $resource, $scopeIdentifier = null, Scope $parentScopeInstance = null)
- {
+ public function createData(
+ ResourceInterface $resource,
+ ?string $scopeIdentifier = null,
+ Scope $parentScopeInstance = null
+ ): Scope {
if ($parentScopeInstance !== null) {
return $this->scopeFactory->createChildScopeFor($this, $parentScopeInstance, $resource, $scopeIdentifier);
}
@@ -105,65 +81,40 @@ public function createData(ResourceInterface $resource, $scopeIdentifier = null,
return $this->scopeFactory->createScopeFor($this, $resource, $scopeIdentifier);
}
- /**
- * Get Include Params.
- *
- * @param string $include
- *
- * @return \League\Fractal\ParamBag
- */
- public function getIncludeParams($include)
+ public function getIncludeParams(string $include): ParamBag
{
$params = isset($this->includeParams[$include]) ? $this->includeParams[$include] : [];
return new ParamBag($params);
}
- /**
- * Get Requested Includes.
- *
- * @return array
- */
- public function getRequestedIncludes()
+ public function getRequestedIncludes(): array
{
return $this->requestedIncludes;
}
- /**
- * Get Requested Excludes.
- *
- * @return array
- */
- public function getRequestedExcludes()
+ public function getRequestedExcludes(): array
{
return $this->requestedExcludes;
}
- /**
- * Get Serializer.
- *
- * @return SerializerAbstract
- */
- public function getSerializer()
+ public function getSerializer(): Serializer
{
- if ($this->serializer === null) {
- $this->setSerializer(new DataArraySerializer());
+ if (! $this->serializer) {
+ $this->serializer = new DataArraySerializer();
}
return $this->serializer;
}
/**
- * Parse Include String.
- *
* @param array|string $includes Array or csv string of resources to include
- *
- * @return $this
*/
- public function parseIncludes($includes)
+ public function parseIncludes($includes): self
{
// Wipe these before we go again
$this->requestedIncludes = $this->includeParams = [];
+ $subRelations = '';
if (is_string($includes)) {
$includes = explode(',', $includes);
@@ -176,7 +127,9 @@ public function parseIncludes($includes)
}
foreach ($includes as $include) {
- list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, null);
+ list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, '');
+ $a = $allModifiersStr ? explode('.', $allModifiersStr, 2) : [''];
+ list($allModifiersStr, $subRelations) = array_pad($a, 2, null);
// Trim it down to a cool level of recursion
$includeName = $this->trimToAcceptableRecursionLevel($includeName);
@@ -212,6 +165,10 @@ public function parseIncludes($includes)
}
$this->includeParams[$includeName] = $modifierArr;
+
+ if ($subRelations) {
+ $this->requestedIncludes[] = $this->trimToAcceptableRecursionLevel($includeName . '.' . $subRelations);
+ }
}
// This should be optional and public someday, but without it includes would never show up
@@ -226,10 +183,8 @@ public function parseIncludes($includes)
* @param array $fieldsets Array of fields to include. It must be an array whose keys
* are resource types and values an array or a string
* of the fields to return, separated by a comma
- *
- * @return $this
*/
- public function parseFieldsets(array $fieldsets)
+ public function parseFieldsets(array $fieldsets): self
{
$this->requestedFieldsets = [];
foreach ($fieldsets as $type => $fields) {
@@ -242,25 +197,15 @@ public function parseFieldsets(array $fieldsets)
}
return $this;
}
-
- /**
- * Get requested fieldsets.
- *
- * @return array
- */
- public function getRequestedFieldsets()
+ public function getRequestedFieldsets(): array
{
return $this->requestedFieldsets;
}
/**
* Get fieldset params for the specified type.
- *
- * @param string $type
- *
- * @return \League\Fractal\ParamBag|null
*/
- public function getFieldset($type)
+ public function getFieldset(string $type): ?ParamBag
{
return !isset($this->requestedFieldsets[$type]) ?
null :
@@ -268,13 +213,9 @@ public function getFieldset($type)
}
/**
- * Parse Exclude String.
- *
* @param array|string $excludes Array or csv string of resources to exclude
- *
- * @return $this
*/
- public function parseExcludes($excludes)
+ public function parseExcludes($excludes): self
{
$this->requestedExcludes = [];
@@ -301,28 +242,14 @@ public function parseExcludes($excludes)
return $this;
}
- /**
- * Set Recursion Limit.
- *
- * @param int $recursionLimit
- *
- * @return $this
- */
- public function setRecursionLimit($recursionLimit)
+ public function setRecursionLimit(int $recursionLimit): self
{
$this->recursionLimit = $recursionLimit;
return $this;
}
- /**
- * Set Serializer
- *
- * @param SerializerAbstract $serializer
- *
- * @return $this
- */
- public function setSerializer(SerializerAbstract $serializer)
+ public function setSerializer(Serializer $serializer): self
{
$this->serializer = $serializer;
@@ -330,16 +257,12 @@ public function setSerializer(SerializerAbstract $serializer)
}
/**
- * Auto-include Parents
- *
* Look at the requested includes and automatically include the parents if they
* are not explicitly requested. E.g: [foo, bar.baz] becomes [foo, bar, bar.baz]
*
* @internal
- *
- * @return void
*/
- protected function autoIncludeParents()
+ protected function autoIncludeParents(): void
{
$parsed = [];
@@ -359,18 +282,12 @@ protected function autoIncludeParents()
}
/**
- * Trim to Acceptable Recursion Level
- *
* Strip off any requested resources that are too many levels deep, to avoid DiCaprio being chased
* by trains or whatever the hell that movie was about.
*
* @internal
- *
- * @param string $includeName
- *
- * @return string
*/
- protected function trimToAcceptableRecursionLevel($includeName)
+ protected function trimToAcceptableRecursionLevel(string $includeName): string
{
return implode('.', array_slice(explode('.', $includeName), 0, $this->recursionLimit));
}
diff --git a/src/Pagination/Cursor.php b/src/Pagination/Cursor.php
index 0b578dea..6156a61b 100644
--- a/src/Pagination/Cursor.php
+++ b/src/Pagination/Cursor.php
@@ -42,10 +42,8 @@ class Cursor implements CursorInterface
/**
* Items being held for the current cursor position.
- *
- * @var int|null
*/
- protected $count;
+ protected ?int $count;
/**
* Create a new Cursor instance.
@@ -53,11 +51,8 @@ class Cursor implements CursorInterface
* @param mixed $current
* @param mixed $prev
* @param mixed $next
- * @param int $count
- *
- * @return void
*/
- public function __construct($current = null, $prev = null, $next = null, $count = null)
+ public function __construct($current = null, $prev = null, $next = null, ?int $count = null)
{
$this->current = $current;
$this->prev = $prev;
@@ -66,10 +61,9 @@ public function __construct($current = null, $prev = null, $next = null, $count
}
/**
- * Get the current cursor value.
- *
- * @return mixed
+ * {@inheritDoc}
*/
+ #[\ReturnTypeWillChange]
public function getCurrent()
{
return $this->current;
@@ -78,11 +72,9 @@ public function getCurrent()
/**
* Set the current cursor value.
*
- * @param int $current
- *
- * @return Cursor
+ * @param mixed $current
*/
- public function setCurrent($current)
+ public function setCurrent($current): self
{
$this->current = $current;
@@ -90,10 +82,9 @@ public function setCurrent($current)
}
/**
- * Get the prev cursor value.
- *
- * @return mixed
+ * {@inheritDoc}
*/
+ #[\ReturnTypeWillChange]
public function getPrev()
{
return $this->prev;
@@ -102,11 +93,9 @@ public function getPrev()
/**
* Set the prev cursor value.
*
- * @param int $prev
- *
- * @return Cursor
+ * @param mixed $prev
*/
- public function setPrev($prev)
+ public function setPrev($prev): self
{
$this->prev = $prev;
@@ -114,10 +103,9 @@ public function setPrev($prev)
}
/**
- * Get the next cursor value.
- *
- * @return mixed
+ * {@inheritDoc}
*/
+ #[\ReturnTypeWillChange]
public function getNext()
{
return $this->next;
@@ -126,11 +114,9 @@ public function getNext()
/**
* Set the next cursor value.
*
- * @param int $next
- *
- * @return Cursor
+ * @param mixed $next
*/
- public function setNext($next)
+ public function setNext($next): self
{
$this->next = $next;
@@ -138,23 +124,17 @@ public function setNext($next)
}
/**
- * Returns the total items in the current cursor.
- *
- * @return int
+ * {@inheritDoc}
*/
- public function getCount()
+ public function getCount(): ?int
{
return (int) $this->count;
}
/**
* Set the total items in the current cursor.
- *
- * @param int $count
- *
- * @return Cursor
*/
- public function setCount($count)
+ public function setCount(int $count): self
{
$this->count = $count;
diff --git a/src/Pagination/CursorInterface.php b/src/Pagination/CursorInterface.php
index 9d6af130..12e1f114 100644
--- a/src/Pagination/CursorInterface.php
+++ b/src/Pagination/CursorInterface.php
@@ -23,6 +23,7 @@ interface CursorInterface
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getCurrent();
/**
@@ -30,6 +31,7 @@ public function getCurrent();
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getPrev();
/**
@@ -37,12 +39,11 @@ public function getPrev();
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getNext();
/**
* Returns the total items in the current cursor.
- *
- * @return int
*/
- public function getCount();
+ public function getCount(): ?int;
}
diff --git a/src/Pagination/PaginatorInterface.php b/src/Pagination/PaginatorInterface.php
index e56a2912..00aabc1a 100644
--- a/src/Pagination/PaginatorInterface.php
+++ b/src/Pagination/PaginatorInterface.php
@@ -20,45 +20,31 @@ interface PaginatorInterface
{
/**
* Get the current page.
- *
- * @return int
*/
- public function getCurrentPage();
+ public function getCurrentPage(): int;
/**
* Get the last page.
- *
- * @return int
*/
- public function getLastPage();
+ public function getLastPage(): int;
/**
* Get the total.
- *
- * @return int
*/
- public function getTotal();
+ public function getTotal(): int;
/**
* Get the count.
- *
- * @return int
*/
- public function getCount();
+ public function getCount(): int;
/**
* Get the number per page.
- *
- * @return int
*/
- public function getPerPage();
+ public function getPerPage(): int;
/**
* Get the url for the given page.
- *
- * @param int $page
- *
- * @return string
*/
- public function getUrl($page);
+ public function getUrl(int $page): string;
}
diff --git a/src/Pagination/SimplePaginationAdapter.php b/src/Pagination/SimplePaginationAdapter.php
index 3f8b630d..89c8b3ab 100644
--- a/src/Pagination/SimplePaginationAdapter.php
+++ b/src/Pagination/SimplePaginationAdapter.php
@@ -4,7 +4,6 @@
class SimplePaginationAdapter implements PaginatorInterface
{
-
/**
* @var int The total number of items in this list
*/
@@ -49,50 +48,40 @@ public function __construct(int $currentPage, int $itemCount, int $perPage, int
/**
* Get the current page.
- *
- * @return int
*/
- public function getCurrentPage()
+ public function getCurrentPage(): int
{
return $this->current;
}
/**
* Get the last page.
- *
- * @return int
*/
- public function getLastPage()
+ public function getLastPage(): int
{
- return $this->total / $this->perPage;
+ return (int) floor($this->total / $this->perPage);
}
/**
* Get the total.
- *
- * @return int
*/
- public function getTotal()
+ public function getTotal(): int
{
return $this->total;
}
/**
* Get the count.
- *
- * @return int
*/
- public function getCount()
+ public function getCount(): int
{
return $this->itemCount;
}
/**
* Get the number per page.
- *
- * @return int
*/
- public function getPerPage()
+ public function getPerPage(): int
{
return $this->perPage;
}
@@ -101,10 +90,8 @@ public function getPerPage()
* Get the url for the given page.
*
* @param int $page
- *
- * @return string
*/
- public function getUrl($page)
+ public function getUrl($page): string
{
return ($this->urlFactory)($page);
}
diff --git a/src/ParamBag.php b/src/ParamBag.php
index 0ddb7321..476fd5bf 100644
--- a/src/ParamBag.php
+++ b/src/ParamBag.php
@@ -16,17 +16,10 @@
*/
class ParamBag implements \ArrayAccess, \IteratorAggregate
{
- /**
- * @var array
- */
- protected $params = [];
+ protected array $params = [];
/**
* Create a new parameter bag instance.
- *
- * @param array $params
- *
- * @return void
*/
public function __construct(array $params)
{
@@ -36,11 +29,10 @@ public function __construct(array $params)
/**
* Get parameter values out of the bag.
*
- * @param string $key
- *
* @return mixed
*/
- public function get($key)
+ #[\ReturnTypeWillChange]
+ public function get(string $key)
{
return $this->__get($key);
}
@@ -48,23 +40,18 @@ public function get($key)
/**
* Get parameter values out of the bag via the property access magic method.
*
- * @param string $key
- *
* @return mixed
*/
- public function __get($key)
+ #[\ReturnTypeWillChange]
+ public function __get(string $key)
{
return isset($this->params[$key]) ? $this->params[$key] : null;
}
/**
* Check if a param exists in the bag via an isset() check on the property.
- *
- * @param string $key
- *
- * @return bool
*/
- public function __isset($key)
+ public function __isset(string $key): bool
{
return isset($this->params[$key]);
}
@@ -72,14 +59,11 @@ public function __isset($key)
/**
* Disallow changing the value of params in the data bag via property access.
*
- * @param string $key
* @param mixed $value
*
* @throws \LogicException
- *
- * @return void
*/
- public function __set($key, $value)
+ public function __set(string $key, $value): void
{
throw new \LogicException('Modifying parameters is not permitted');
}
@@ -87,13 +71,11 @@ public function __set($key, $value)
/**
* Disallow unsetting params in the data bag via property access.
*
- * @param string $key
- *
* @throws \LogicException
*
* @return void
*/
- public function __unset($key)
+ public function __unset(string $key): void
{
throw new \LogicException('Modifying parameters is not permitted');
}
@@ -102,10 +84,8 @@ public function __unset($key)
* Check if a param exists in the bag via an isset() and array access.
*
* @param string $key
- *
- * @return bool
*/
- public function offsetExists($key)
+ public function offsetExists($key): bool
{
return $this->__isset($key);
}
@@ -117,6 +97,7 @@ public function offsetExists($key)
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->__get($key);
@@ -129,10 +110,8 @@ public function offsetGet($key)
* @param mixed $value
*
* @throws \LogicException
- *
- * @return void
*/
- public function offsetSet($key, $value)
+ public function offsetSet($key, $value): void
{
throw new \LogicException('Modifying parameters is not permitted');
}
@@ -143,20 +122,16 @@ public function offsetSet($key, $value)
* @param string $key
*
* @throws \LogicException
- *
- * @return void
*/
- public function offsetUnset($key)
+ public function offsetUnset($key): void
{
throw new \LogicException('Modifying parameters is not permitted');
}
/**
* IteratorAggregate for iterating over the object like an array.
- *
- * @return \ArrayIterator
*/
- public function getIterator()
+ public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->params);
}
diff --git a/src/Resource/Collection.php b/src/Resource/Collection.php
index 610bb1ae..fd288e7f 100644
--- a/src/Resource/Collection.php
+++ b/src/Resource/Collection.php
@@ -30,82 +30,47 @@ class Collection extends ResourceAbstract
*/
protected $data;
- /**
- * The paginator instance.
- *
- * @var PaginatorInterface
- */
- protected $paginator;
+ protected ?PaginatorInterface $paginator = null;
- /**
- * The cursor instance.
- *
- * @var CursorInterface
- */
- protected $cursor;
+ protected ?CursorInterface $cursor = null;
- /**
- * Get the paginator instance.
- *
- * @return PaginatorInterface
- */
- public function getPaginator()
+ public function getPaginator(): ?PaginatorInterface
{
return $this->paginator;
}
/**
* Determine if the resource has a paginator implementation.
- *
- * @return bool
*/
- public function hasPaginator()
+ public function hasPaginator(): bool
{
- return $this->paginator instanceof PaginatorInterface;
+ return $this->paginator !== null;
}
/**
* Get the cursor instance.
- *
- * @return CursorInterface
*/
- public function getCursor()
+ public function getCursor(): ?CursorInterface
{
return $this->cursor;
}
/**
* Determine if the resource has a cursor implementation.
- *
- * @return bool
*/
- public function hasCursor()
+ public function hasCursor(): bool
{
- return $this->cursor instanceof CursorInterface;
+ return $this->cursor !== null;
}
- /**
- * Set the paginator instance.
- *
- * @param PaginatorInterface $paginator
- *
- * @return $this
- */
- public function setPaginator(PaginatorInterface $paginator)
+ public function setPaginator(PaginatorInterface $paginator): self
{
$this->paginator = $paginator;
return $this;
}
- /**
- * Set the cursor instance.
- *
- * @param CursorInterface $cursor
- *
- * @return $this
- */
- public function setCursor(CursorInterface $cursor)
+ public function setCursor(CursorInterface $cursor): self
{
$this->cursor = $cursor;
diff --git a/src/Resource/Item.php b/src/Resource/Item.php
index a1df70be..a1b05765 100644
--- a/src/Resource/Item.php
+++ b/src/Resource/Item.php
@@ -12,13 +12,10 @@
namespace League\Fractal\Resource;
/**
- * Item Resource
- *
* The Item Resource can store any mixed data, usually an ORM, ODM or
* other sort of intelligent result, DataMapper model, etc but could
* be a basic array, object, or whatever you like.
*/
class Item extends ResourceAbstract
{
- //
}
diff --git a/src/Resource/MetaDataInterface.php b/src/Resource/MetaDataInterface.php
index a9a2724a..9458f6ca 100644
--- a/src/Resource/MetaDataInterface.php
+++ b/src/Resource/MetaDataInterface.php
@@ -17,9 +17,8 @@ public function getMeta();
/**
* Get the meta data.
*
- * @param string $metaKey
- *
- * @return array
+ * @return mixed
*/
- public function getMetaValue($metaKey);
+ #[\ReturnTypeWillChange]
+ public function getMetaValue(string $metaKey);
}
diff --git a/src/Resource/NullResource.php b/src/Resource/NullResource.php
index c8396b75..d153584a 100644
--- a/src/Resource/NullResource.php
+++ b/src/Resource/NullResource.php
@@ -12,8 +12,6 @@
namespace League\Fractal\Resource;
/**
- * Null Resource
- *
* The Null Resource represents a resource that doesn't exist. This can be
* useful to indicate that a certain relationship is null in some output
* formats (e.g. JSON API), which require even a relationship that is null at
@@ -26,8 +24,10 @@ class NullResource extends ResourceAbstract
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getData()
{
// Null has no data associated with it.
+ return null;
}
}
diff --git a/src/Resource/Primitive.php b/src/Resource/Primitive.php
index c0bedd61..dd512733 100644
--- a/src/Resource/Primitive.php
+++ b/src/Resource/Primitive.php
@@ -19,5 +19,4 @@
*/
class Primitive extends ResourceAbstract
{
- //
}
diff --git a/src/Resource/ResourceAbstract.php b/src/Resource/ResourceAbstract.php
index e36bbe6b..b8cbb86b 100644
--- a/src/Resource/ResourceAbstract.php
+++ b/src/Resource/ResourceAbstract.php
@@ -24,17 +24,13 @@ abstract class ResourceAbstract implements ResourceInterface, MetaDataInterface
/**
* Array of meta data.
- *
- * @var array
*/
- protected $meta = [];
+ protected array $meta = [];
/**
* The resource key.
- *
- * @var string|null
*/
- protected $resourceKey;
+ protected ?string $resourceKey;
/**
* A callable to process the data attached to this resource.
@@ -44,13 +40,10 @@ abstract class ResourceAbstract implements ResourceInterface, MetaDataInterface
protected $transformer;
/**
- * Create a new resource instance.
- *
* @param mixed $data
* @param callable|TransformerAbstract|null $transformer
- * @param string $resourceKey
*/
- public function __construct($data = null, $transformer = null, $resourceKey = null)
+ public function __construct($data = null, $transformer = null, ?string $resourceKey = null)
{
$this->data = $data;
$this->transformer = $transformer;
@@ -62,6 +55,7 @@ public function __construct($data = null, $transformer = null, $resourceKey = nu
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getData()
{
return $this->data;
@@ -71,10 +65,8 @@ public function getData()
* Set the data.
*
* @param mixed $data
- *
- * @return $this
*/
- public function setData($data)
+ public function setData($data): self
{
$this->data = $data;
@@ -83,10 +75,8 @@ public function setData($data)
/**
* Get the meta data.
- *
- * @return array
*/
- public function getMeta()
+ public function getMeta(): array
{
return $this->meta;
}
@@ -94,23 +84,17 @@ public function getMeta()
/**
* Get the meta data.
*
- * @param string $metaKey
- *
- * @return array
+ * @return mixed
*/
- public function getMetaValue($metaKey)
+ #[\ReturnTypeWillChange]
+ public function getMetaValue(string $metaKey)
{
return $this->meta[$metaKey];
}
- /**
- * Get the resource key.
- *
- * @return string
- */
- public function getResourceKey()
+ public function getResourceKey(): string
{
- return (string) $this->resourceKey;
+ return $this->resourceKey ?? '';
}
/**
@@ -127,10 +111,8 @@ public function getTransformer()
* Set the transformer.
*
* @param callable|TransformerAbstract $transformer
- *
- * @return $this
*/
- public function setTransformer($transformer)
+ public function setTransformer($transformer): self
{
$this->transformer = $transformer;
@@ -139,12 +121,8 @@ public function setTransformer($transformer)
/**
* Set the meta data.
- *
- * @param array $meta
- *
- * @return $this
*/
- public function setMeta(array $meta)
+ public function setMeta(array $meta): self
{
$this->meta = $meta;
@@ -152,28 +130,18 @@ public function setMeta(array $meta)
}
/**
- * Set the meta data.
+ * Set one meta data value.
*
- * @param string $metaKey
* @param mixed $metaValue
- *
- * @return $this
*/
- public function setMetaValue($metaKey, $metaValue)
+ public function setMetaValue(string $metaKey, $metaValue): self
{
$this->meta[$metaKey] = $metaValue;
return $this;
}
- /**
- * Set the resource key.
- *
- * @param string $resourceKey
- *
- * @return $this
- */
- public function setResourceKey($resourceKey)
+ public function setResourceKey(string $resourceKey): self
{
$this->resourceKey = $resourceKey;
diff --git a/src/Resource/ResourceInterface.php b/src/Resource/ResourceInterface.php
index 4e0ef219..dc8b8751 100644
--- a/src/Resource/ResourceInterface.php
+++ b/src/Resource/ResourceInterface.php
@@ -15,16 +15,15 @@ interface ResourceInterface
{
/**
* Get the resource key.
- *
- * @return string
*/
- public function getResourceKey();
+ public function getResourceKey(): string;
/**
* Get the data.
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getData();
/**
@@ -38,17 +37,18 @@ public function getTransformer();
* Set the data.
*
* @param mixed $data
- *
- * @return $this
*/
- public function setData($data);
+ public function setData($data): self;
/**
* Set the transformer.
*
* @param callable|\League\Fractal\TransformerAbstract $transformer
- *
- * @return $this
*/
- public function setTransformer($transformer);
+ public function setTransformer($transformer): self;
+
+ /**
+ * Get the meta data.
+ */
+ public function getMeta(): array;
}
diff --git a/src/Scope.php b/src/Scope.php
index 0cee9404..5acae5d1 100644
--- a/src/Scope.php
+++ b/src/Scope.php
@@ -18,7 +18,7 @@
use League\Fractal\Resource\Primitive;
use League\Fractal\Resource\NullResource;
use League\Fractal\Resource\ResourceInterface;
-use League\Fractal\Serializer\SerializerAbstract;
+use League\Fractal\Serializer\Serializer;
/**
* Scope
@@ -27,43 +27,19 @@
* context. For example, the same resource could be attached to multiple scopes.
* There are root scopes, parent scopes and child scopes.
*/
-class Scope
+class Scope implements \JsonSerializable
{
- /**
- * @var array
- */
- protected $availableIncludes = [];
+ protected array $availableIncludes = [];
- /**
- * @var string|null
- */
- protected $scopeIdentifier;
+ protected ?string $scopeIdentifier;
- /**
- * @var \League\Fractal\Manager
- */
- protected $manager;
+ protected Manager $manager;
- /**
- * @var ResourceInterface
- */
- protected $resource;
+ protected ResourceInterface $resource;
- /**
- * @var array
- */
- protected $parentScopes = [];
+ protected array $parentScopes = [];
- /**
- * Create a new scope instance.
- *
- * @param Manager $manager
- * @param ResourceInterface $resource
- * @param string $scopeIdentifier
- *
- * @return void
- */
- public function __construct(Manager $manager, ResourceInterface $resource, $scopeIdentifier = null)
+ public function __construct(Manager $manager, ResourceInterface $resource, ?string $scopeIdentifier = null)
{
$this->manager = $manager;
$this->resource = $resource;
@@ -74,35 +50,24 @@ public function __construct(Manager $manager, ResourceInterface $resource, $scop
* Embed a scope as a child of the current scope.
*
* @internal
- *
- * @param string $scopeIdentifier
- * @param ResourceInterface $resource
- *
- * @return \League\Fractal\Scope
*/
- public function embedChildScope($scopeIdentifier, $resource)
+ public function embedChildScope(string $scopeIdentifier, ResourceInterface $resource): Scope
{
return $this->manager->createData($resource, $scopeIdentifier, $this);
}
/**
* Get the current identifier.
- *
- * @return string
*/
- public function getScopeIdentifier()
+ public function getScopeIdentifier(): ?string
{
return (string) $this->scopeIdentifier;
}
/**
* Get the unique identifier for this scope.
- *
- * @param string $appendIdentifier
- *
- * @return string
*/
- public function getIdentifier($appendIdentifier = null)
+ public function getIdentifier(?string $appendIdentifier = null): string
{
$identifierParts = array_merge($this->parentScopes, [$this->scopeIdentifier, $appendIdentifier]);
@@ -110,49 +75,34 @@ public function getIdentifier($appendIdentifier = null)
}
/**
- * Getter for parentScopes.
- *
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function getParentScopes()
{
return $this->parentScopes;
}
- /**
- * Getter for resource.
- *
- * @return ResourceInterface
- */
- public function getResource()
+ public function getResource(): ResourceInterface
{
return $this->resource;
}
- /**
- * Getter for manager.
- *
- * @return \League\Fractal\Manager
- */
- public function getManager()
+ public function getManager(): Manager
{
return $this->manager;
}
/**
- * Is Requested.
- *
* Check if - in relation to the current scope - this specific segment is allowed.
* That means, if a.b.c is requested and the current scope is a.b, then c is allowed. If the current
* scope is a then c is not allowed, even if it is there and potentially transformable.
*
* @internal
*
- * @param string $checkScopeSegment
- *
* @return bool Returns the new number of elements in the array.
*/
- public function isRequested($checkScopeSegment)
+ public function isRequested(string $checkScopeSegment): bool
{
if ($this->parentScopes) {
$scopeArray = array_slice($this->parentScopes, 1);
@@ -161,26 +111,20 @@ public function isRequested($checkScopeSegment)
$scopeArray = [$checkScopeSegment];
}
- $scopeString = implode('.', (array) $scopeArray);
+ $scopeString = implode('.', $scopeArray);
return in_array($scopeString, $this->manager->getRequestedIncludes());
}
/**
- * Is Excluded.
- *
* Check if - in relation to the current scope - this specific segment should
* be excluded. That means, if a.b.c is excluded and the current scope is a.b,
* then c will not be allowed in the transformation whether it appears in
* the list of default or available, requested includes.
*
* @internal
- *
- * @param string $checkScopeSegment
- *
- * @return bool
*/
- public function isExcluded($checkScopeSegment)
+ public function isExcluded(string $checkScopeSegment): bool
{
if ($this->parentScopes) {
$scopeArray = array_slice($this->parentScopes, 1);
@@ -189,7 +133,7 @@ public function isExcluded($checkScopeSegment)
$scopeArray = [$checkScopeSegment];
}
- $scopeString = implode('.', (array) $scopeArray);
+ $scopeString = implode('.', $scopeArray);
return in_array($scopeString, $this->manager->getRequestedExcludes());
}
@@ -201,11 +145,9 @@ public function isExcluded($checkScopeSegment)
*
* @internal
*
- * @param string $identifierSegment
- *
* @return int Returns the new number of elements in the array.
*/
- public function pushParentScope($identifierSegment)
+ public function pushParentScope(string $identifierSegment): int
{
return array_push($this->parentScopes, $identifierSegment);
}
@@ -216,10 +158,8 @@ public function pushParentScope($identifierSegment)
* @internal
*
* @param string[] $parentScopes Value to set.
- *
- * @return $this
*/
- public function setParentScopes($parentScopes)
+ public function setParentScopes(array $parentScopes): self
{
$this->parentScopes = $parentScopes;
@@ -228,10 +168,8 @@ public function setParentScopes($parentScopes)
/**
* Convert the current data for this scope to an array.
- *
- * @return array|null
*/
- public function toArray()
+ public function toArray(): ?array
{
list($rawData, $rawIncludedData) = $this->executeResourceTransformers();
@@ -296,14 +234,19 @@ public function toArray()
return $data + $meta;
}
+ /**
+ * @return mixed
+ */
+ #[\ReturnTypeWillChange]
+ public function jsonSerialize()
+ {
+ return $this->toArray();
+ }
+
/**
* Convert the current data for this scope to JSON.
- *
- * @param int $options
- *
- * @return string
*/
- public function toJson($options = 0)
+ public function toJson(int $options = 0): string
{
$result = json_encode($this->toArray(), $options);
return $result ?: '';
@@ -314,6 +257,7 @@ public function toJson($options = 0)
*
* @return mixed
*/
+ #[\ReturnTypeWillChange]
public function transformPrimitiveResource()
{
if (! ($this->resource instanceof Primitive)) {
@@ -341,10 +285,8 @@ public function transformPrimitiveResource()
* Execute the resources transformer and return the data and included data.
*
* @internal
- *
- * @return array
*/
- protected function executeResourceTransformers()
+ protected function executeResourceTransformers(): array
{
$transformer = $this->resource->getTransformer();
$data = $this->resource->getData();
@@ -375,21 +317,27 @@ protected function executeResourceTransformers()
*
* @internal
*
- * @param SerializerAbstract $serializer
- * @param mixed $data
- *
- * @return array|null
+ * @param mixed $data
*/
- protected function serializeResource(SerializerAbstract $serializer, $data)
+ protected function serializeResource(Serializer $serializer, $data): ?array
{
$resourceKey = $this->resource->getResourceKey();
if ($this->resource instanceof Collection) {
- return $serializer->collection($resourceKey, $data);
+ if (!empty($resourceKey)) {
+ return $serializer->collection($resourceKey, $data);
+ }
+
+ return $serializer->collection(null, $data);
}
if ($this->resource instanceof Item) {
- return $serializer->item($resourceKey, $data);
+ // this is where it breaks now.
+ if (!empty($resourceKey)) {
+ return $serializer->item($resourceKey, $data);
+ }
+
+ return $serializer->item(null, $data);
}
return $serializer->null();
@@ -402,10 +350,8 @@ protected function serializeResource(SerializerAbstract $serializer, $data)
*
* @param TransformerAbstract|callable|null $transformer
* @param mixed $data
- *
- * @return array
*/
- protected function fireTransformer($transformer, $data)
+ protected function fireTransformer($transformer, $data): array
{
$includedData = [];
@@ -438,10 +384,8 @@ protected function fireTransformer($transformer, $data)
*
* @param \League\Fractal\TransformerAbstract $transformer
* @param mixed $data
- *
- * @return array
*/
- protected function fireIncludedTransformers($transformer, $data)
+ protected function fireIncludedTransformers($transformer, $data): array
{
$this->availableIncludes = $transformer->getAvailableIncludes();
@@ -454,10 +398,8 @@ protected function fireIncludedTransformers($transformer, $data)
* @internal
*
* @param TransformerAbstract|callable $transformer
- *
- * @return bool
*/
- protected function transformerHasIncludes($transformer)
+ protected function transformerHasIncludes($transformer): bool
{
if (! $transformer instanceof TransformerAbstract) {
return false;
@@ -471,10 +413,8 @@ protected function transformerHasIncludes($transformer)
/**
* Check, if this is the root scope.
- *
- * @return bool
*/
- protected function isRootScope()
+ protected function isRootScope(): bool
{
return empty($this->parentScopes);
}
@@ -484,12 +424,8 @@ protected function isRootScope()
* the scope resource
*
* @internal
- *
- * @param array $data
- *
- * @return array
*/
- protected function filterFieldsets(array $data)
+ protected function filterFieldsets(array $data): array
{
if (!$this->hasFilterFieldset()) {
return $data;
@@ -511,10 +447,8 @@ protected function filterFieldsets(array $data)
* Return the requested filter fieldset for the scope resource
*
* @internal
- *
- * @return \League\Fractal\ParamBag|null
*/
- protected function getFilterFieldset()
+ protected function getFilterFieldset(): ?ParamBag
{
return $this->manager->getFieldset($this->getResourceType());
}
@@ -523,10 +457,8 @@ protected function getFilterFieldset()
* Check if there are requested filter fieldsets for the scope resource.
*
* @internal
- *
- * @return bool
*/
- protected function hasFilterFieldset()
+ protected function hasFilterFieldset(): bool
{
return $this->getFilterFieldset() !== null;
}
@@ -535,10 +467,8 @@ protected function hasFilterFieldset()
* Return the scope resource type.
*
* @internal
- *
- * @return string
*/
- protected function getResourceType()
+ protected function getResourceType(): string
{
return $this->resource->getResourceKey();
}
diff --git a/src/ScopeFactory.php b/src/ScopeFactory.php
index 1d173650..5e719321 100644
--- a/src/ScopeFactory.php
+++ b/src/ScopeFactory.php
@@ -15,31 +15,25 @@
class ScopeFactory implements ScopeFactoryInterface
{
- /**
- * @param Manager $manager
- * @param ResourceInterface $resource
- * @param string|null $scopeIdentifier
- * @return Scope
- */
- public function createScopeFor(Manager $manager, ResourceInterface $resource, $scopeIdentifier = null)
- {
+ public function createScopeFor(
+ Manager $manager,
+ ResourceInterface $resource,
+ ?string $scopeIdentifier = null
+ ): Scope {
return new Scope($manager, $resource, $scopeIdentifier);
}
- /**
- * @param Manager $manager
- * @param Scope $parentScopeInstance
- * @param ResourceInterface $resource
- * @param string|null $scopeIdentifier
- * @return Scope
- */
- public function createChildScopeFor(Manager $manager, Scope $parentScopeInstance, ResourceInterface $resource, $scopeIdentifier = null)
- {
+ public function createChildScopeFor(
+ Manager $manager,
+ Scope $parentScope,
+ ResourceInterface $resource,
+ ?string $scopeIdentifier = null
+ ): Scope {
$scopeInstance = $this->createScopeFor($manager, $resource, $scopeIdentifier);
// This will be the new children list of parents (parents parents, plus the parent)
- $scopeArray = $parentScopeInstance->getParentScopes();
- $scopeArray[] = $parentScopeInstance->getScopeIdentifier();
+ $scopeArray = $parentScope->getParentScopes();
+ $scopeArray[] = $parentScope->getScopeIdentifier();
$scopeInstance->setParentScopes($scopeArray);
diff --git a/src/ScopeFactoryInterface.php b/src/ScopeFactoryInterface.php
index 1175712b..fe4fa680 100644
--- a/src/ScopeFactoryInterface.php
+++ b/src/ScopeFactoryInterface.php
@@ -14,26 +14,20 @@
use League\Fractal\Resource\ResourceInterface;
/**
- * ScopeFactoryInterface
- *
* Creates Scope Instances for resources
*/
interface ScopeFactoryInterface
{
- /**
- * @param Manager $manager
- * @param ResourceInterface $resource
- * @param string|null $scopeIdentifier
- * @return Scope
- */
- public function createScopeFor(Manager $manager, ResourceInterface $resource, $scopeIdentifier = null);
+ public function createScopeFor(
+ Manager $manager,
+ ResourceInterface $resource,
+ ?string $scopeIdentifier = null
+ ): Scope;
- /**
- * @param Manager $manager
- * @param Scope $parentScope
- * @param ResourceInterface $resource
- * @param string|null $scopeIdentifier
- * @return Scope
- */
- public function createChildScopeFor(Manager $manager, Scope $parentScope, ResourceInterface $resource, $scopeIdentifier = null);
+ public function createChildScopeFor(
+ Manager $manager,
+ Scope $parentScope,
+ ResourceInterface $resource,
+ ?string $scopeIdentifier = null
+ ): Scope;
}
diff --git a/src/Serializer/ArraySerializer.php b/src/Serializer/ArraySerializer.php
index 52489603..1b620008 100644
--- a/src/Serializer/ArraySerializer.php
+++ b/src/Serializer/ArraySerializer.php
@@ -18,62 +18,41 @@
class ArraySerializer extends SerializerAbstract
{
/**
- * Serialize a collection.
- *
- * @param string $resourceKey
- * @param array $data
- *
- * @return array
+ * {@inheritDoc}
*/
- public function collection($resourceKey, array $data)
+ public function collection(?string $resourceKey, array $data): array
{
return [$resourceKey ?: 'data' => $data];
}
/**
- * Serialize an item.
- *
- * @param string $resourceKey
- * @param array $data
- *
- * @return array
+ * {@inheritDoc}
*/
- public function item($resourceKey, array $data)
+ public function item(?string $resourceKey, array $data): array
{
return $data;
}
/**
- * Serialize null resource.
- *
- * @return array
+ * {@inheritDoc}
*/
- public function null()
+ public function null(): ?array
{
return [];
}
/**
- * Serialize the included data.
- *
- * @param ResourceInterface $resource
- * @param array $data
- *
- * @return array
+ * {@inheritDoc}
*/
- public function includedData(ResourceInterface $resource, array $data)
+ public function includedData(ResourceInterface $resource, array $data): array
{
return $data;
}
/**
- * Serialize the meta.
- *
- * @param array $meta
- *
- * @return array
+ * {@inheritDoc}
*/
- public function meta(array $meta)
+ public function meta(array $meta): array
{
if (empty($meta)) {
return [];
@@ -83,21 +62,17 @@ public function meta(array $meta)
}
/**
- * Serialize the paginator.
- *
- * @param PaginatorInterface $paginator
- *
- * @return array
+ * {@inheritDoc}
*/
- public function paginator(PaginatorInterface $paginator)
+ public function paginator(PaginatorInterface $paginator): array
{
- $currentPage = (int) $paginator->getCurrentPage();
- $lastPage = (int) $paginator->getLastPage();
+ $currentPage = $paginator->getCurrentPage();
+ $lastPage = $paginator->getLastPage();
$pagination = [
- 'total' => (int) $paginator->getTotal(),
- 'count' => (int) $paginator->getCount(),
- 'per_page' => (int) $paginator->getPerPage(),
+ 'total' => $paginator->getTotal(),
+ 'count' => $paginator->getCount(),
+ 'per_page' => $paginator->getPerPage(),
'current_page' => $currentPage,
'total_pages' => $lastPage,
];
@@ -120,19 +95,15 @@ public function paginator(PaginatorInterface $paginator)
}
/**
- * Serialize the cursor.
- *
- * @param CursorInterface $cursor
- *
- * @return array
+ * {@inheritDoc}
*/
- public function cursor(CursorInterface $cursor)
+ public function cursor(CursorInterface $cursor): array
{
$cursor = [
'current' => $cursor->getCurrent(),
'prev' => $cursor->getPrev(),
'next' => $cursor->getNext(),
- 'count' => (int) $cursor->getCount(),
+ 'count' => $cursor->getCount(),
];
return ['cursor' => $cursor];
diff --git a/src/Serializer/DataArraySerializer.php b/src/Serializer/DataArraySerializer.php
index 70339833..2f382ef8 100644
--- a/src/Serializer/DataArraySerializer.php
+++ b/src/Serializer/DataArraySerializer.php
@@ -14,37 +14,25 @@
class DataArraySerializer extends ArraySerializer
{
/**
- * Serialize a collection.
- *
- * @param string $resourceKey
- * @param array $data
- *
- * @return array
+ * {@inheritDoc}
*/
- public function collection($resourceKey, array $data)
+ public function collection(?string $resourceKey, array $data): array
{
return ['data' => $data];
}
/**
- * Serialize an item.
- *
- * @param string $resourceKey
- * @param array $data
- *
- * @return array
+ * {@inheritDoc}
*/
- public function item($resourceKey, array $data)
+ public function item(?string $resourceKey, array $data): array
{
return ['data' => $data];
}
/**
- * Serialize null resource.
- *
- * @return array
+ * {@inheritDoc}
*/
- public function null()
+ public function null(): ?array
{
return ['data' => []];
}
diff --git a/src/Serializer/Serializer.php b/src/Serializer/Serializer.php
index e3252b08..434671e1 100644
--- a/src/Serializer/Serializer.php
+++ b/src/Serializer/Serializer.php
@@ -1,4 +1,5 @@
availableIncludes;
}
/**
* Getter for defaultIncludes.
- *
- * @return array
*/
- public function getDefaultIncludes()
+ public function getDefaultIncludes(): array
{
return $this->defaultIncludes;
}
/**
* Getter for currentScope.
- *
- * @return \League\Fractal\Scope
*/
- public function getCurrentScope()
+ public function getCurrentScope(): ?Scope
{
return $this->currentScope;
}
/**
* Figure out which includes we need.
- *
- * @internal
- *
- * @param Scope $scope
- *
- * @return array
*/
- private function figureOutWhichIncludes(Scope $scope)
+ private function figureOutWhichIncludes(Scope $scope): array
{
$includes = $this->getDefaultIncludes();
@@ -114,7 +94,6 @@ private function figureOutWhichIncludes(Scope $scope)
*
* @internal
*
- * @param Scope $scope
* @param mixed $data
*
* @return array|false
@@ -140,21 +119,14 @@ public function processIncludedResources(Scope $scope, $data)
/**
* Include a resource only if it is available on the method.
*
- * @internal
- *
- * @param Scope $scope
* @param mixed $data
- * @param array $includedData
- * @param string $include
- *
- * @return array
*/
private function includeResourceIfAvailable(
Scope $scope,
$data,
- $includedData,
- $include
- ) {
+ array $includedData,
+ string $include
+ ): array {
if ($resource = $this->callIncludeMethod($scope, $include, $data)) {
$childScope = $scope->embedChildScope($include, $resource);
@@ -173,21 +145,34 @@ private function includeResourceIfAvailable(
*
* @internal
*
- * @param Scope $scope
- * @param string $includeName
* @param mixed $data
*
* @throws \Exception
*
* @return \League\Fractal\Resource\ResourceInterface|false
*/
- protected function callIncludeMethod(Scope $scope, $includeName, $data)
+ protected function callIncludeMethod(Scope $scope, string $includeName, $data)
{
$scopeIdentifier = $scope->getIdentifier($includeName);
+
$params = $scope->getManager()->getIncludeParams($scopeIdentifier);
// Check if the method name actually exists
- $methodName = 'include' . str_replace(' ', '', ucwords(str_replace('_', ' ', str_replace('-', ' ', $includeName))));
+ $methodName = 'include' . str_replace(
+ ' ',
+ '',
+ ucwords(
+ str_replace(
+ '_',
+ ' ',
+ str_replace(
+ '-',
+ ' ',
+ $includeName
+ )
+ )
+ )
+ );
$resource = $this->{$methodName}($data, $params);
if ($resource === null) {
@@ -209,12 +194,8 @@ protected function callIncludeMethod(Scope $scope, $includeName, $data)
/**
* Setter for availableIncludes.
- *
- * @param array $availableIncludes
- *
- * @return $this
*/
- public function setAvailableIncludes($availableIncludes)
+ public function setAvailableIncludes(array $availableIncludes): self
{
$this->availableIncludes = $availableIncludes;
@@ -223,12 +204,8 @@ public function setAvailableIncludes($availableIncludes)
/**
* Setter for defaultIncludes.
- *
- * @param array $defaultIncludes
- *
- * @return $this
*/
- public function setDefaultIncludes($defaultIncludes)
+ public function setDefaultIncludes(array $defaultIncludes): self
{
$this->defaultIncludes = $defaultIncludes;
@@ -237,12 +214,8 @@ public function setDefaultIncludes($defaultIncludes)
/**
* Setter for currentScope.
- *
- * @param Scope $currentScope
- *
- * @return $this
*/
- public function setCurrentScope($currentScope)
+ public function setCurrentScope(Scope $currentScope): self
{
$this->currentScope = $currentScope;
@@ -254,11 +227,8 @@ public function setCurrentScope($currentScope)
*
* @param mixed $data
* @param callable|null $transformer
- * @param string $resourceKey
- *
- * @return Primitive
*/
- protected function primitive($data, $transformer = null, $resourceKey = null)
+ protected function primitive($data, ?callable $transformer = null, ?string $resourceKey = null): Primitive
{
return new Primitive($data, $transformer, $resourceKey);
}
@@ -268,11 +238,8 @@ protected function primitive($data, $transformer = null, $resourceKey = null)
*
* @param mixed $data
* @param TransformerAbstract|callable $transformer
- * @param string $resourceKey
- *
- * @return Item
*/
- protected function item($data, $transformer, $resourceKey = null)
+ protected function item($data, $transformer, ?string $resourceKey = null): Item
{
return new Item($data, $transformer, $resourceKey);
}
@@ -282,21 +249,16 @@ protected function item($data, $transformer, $resourceKey = null)
*
* @param mixed $data
* @param TransformerAbstract|callable $transformer
- * @param string $resourceKey
- *
- * @return Collection
*/
- protected function collection($data, $transformer, $resourceKey = null)
+ protected function collection($data, $transformer, ?string $resourceKey = null): Collection
{
return new Collection($data, $transformer, $resourceKey);
}
/**
* Create a new null resource object.
- *
- * @return NullResource
*/
- protected function null()
+ protected function null(): NullResource
{
return new NullResource();
}
diff --git a/test/ManagerTest.php b/test/ManagerTest.php
index f7b47f3d..1305e011 100755
--- a/test/ManagerTest.php
+++ b/test/ManagerTest.php
@@ -19,7 +19,7 @@ public function testParseIncludeSelfie()
public function testInvalidParseInclude()
{
- $this->expectException(InvalidArgumentException::class, 'The parseIncludes() method expects a string or an array. NULL given');
+ $this->expectExceptionObject(new InvalidArgumentException('The parseIncludes() method expects a string or an array. NULL given'));
$manager = new Manager();
@@ -28,7 +28,7 @@ public function testInvalidParseInclude()
public function testIceTParseInclude()
{
- $this->expectException(InvalidArgumentException::class, 'The parseIncludes() method expects a string or an array. integer given');
+ $this->expectExceptionObject(new InvalidArgumentException('The parseIncludes() method expects a string or an array. integer given'));
$manager = new Manager();
@@ -52,6 +52,10 @@ public function testParseIncludes()
$manager->parseIncludes(['foo', 'foo', 'bar']);
$this->assertSame(['foo', 'bar'], $manager->getRequestedIncludes());
+ $manager->parseIncludes(['foo.bar', 'foo:limit(10|1).bar']);
+ $this->assertSame(['foo', 'foo.bar'], $manager->getRequestedIncludes());
+ $this->assertSame(['10', '1'], $manager->getIncludeParams('foo')->get('limit'));
+
// Do requests for `baz.bart` also request `baz`?
$manager->parseIncludes(['foo.bar']);
$this->assertSame(['foo', 'foo.bar'], $manager->getRequestedIncludes());
@@ -70,6 +74,17 @@ public function testParseIncludes()
$this->assertSame([''], $params['anotherparam']);
$this->assertNull($params['totallymadeup']);
+
+ // Relation with params and sub relation
+ $manager->parseIncludes('foo:limit(5|1):order(name).bar,baz');
+
+ $params = $manager->getIncludeParams('foo');
+
+ $this->assertInstanceOf('League\Fractal\ParamBag', $params);
+
+ $this->assertSame(['5', '1'], $params['limit']);
+ $this->assertSame(['name'], $params['order']);
+ $this->assertSame(['foo', 'foo.bar', 'baz'], $manager->getRequestedIncludes());
}
public function testParseExcludeSelfie()
@@ -82,8 +97,7 @@ public function testParseExcludeSelfie()
public function testInvalidParseExclude()
{
- $this->expectException(InvalidArgumentException::class, 'The parseExcludes() method expects a string or an array. NULL given');
-
+ $this->expectExceptionObject(new InvalidArgumentException('The parseExcludes() method expects a string or an array. NULL given'));
$manager = new Manager();
@@ -92,7 +106,7 @@ public function testInvalidParseExclude()
public function testIceTParseExclude()
{
- $this->expectException(InvalidArgumentException::class, 'The parseExcludes() method expects a string or an array. integer given');
+ $this->expectExceptionObject(new InvalidArgumentException('The parseExcludes() method expects a string or an array. integer given'));
$manager = new Manager();
@@ -144,6 +158,24 @@ public function testRecursionLimiting()
$manager->getRequestedIncludes()
);
+ $manager->parseIncludes('a:limit(5|1).b.c.d.e.f.g.h.i.j.NEVER');
+
+ $this->assertSame(
+ [
+ 'a',
+ 'a.b',
+ 'a.b.c',
+ 'a.b.c.d',
+ 'a.b.c.d.e',
+ 'a.b.c.d.e.f',
+ 'a.b.c.d.e.f.g',
+ 'a.b.c.d.e.f.g.h',
+ 'a.b.c.d.e.f.g.h.i',
+ 'a.b.c.d.e.f.g.h.i.j',
+ ],
+ $manager->getRequestedIncludes()
+ );
+
// Try setting to 3 and see what happens
$manager->setRecursionLimit(3);
$manager->parseIncludes('a.b.c.NEVER');
@@ -156,6 +188,17 @@ public function testRecursionLimiting()
],
$manager->getRequestedIncludes()
);
+
+ $manager->parseIncludes('a:limit(5|1).b.c.NEVER');
+
+ $this->assertSame(
+ [
+ 'a',
+ 'a.b',
+ 'a.b.c',
+ ],
+ $manager->getRequestedIncludes()
+ );
}
public function testCreateDataWithCallback()
diff --git a/test/ParamBagTest.php b/test/ParamBagTest.php
index 304d5dcc..38b7bffd 100644
--- a/test/ParamBagTest.php
+++ b/test/ParamBagTest.php
@@ -35,7 +35,7 @@ public function testArrayAccess()
public function testArrayAccessSetFails()
{
- $this->expectException(LogicException::class, 'Modifying parameters is not permitted');
+ $this->expectExceptionObject(new LogicException('Modifying parameters is not permitted'));
$params = new ParamBag(['foo' => 'bar']);
@@ -44,7 +44,8 @@ public function testArrayAccessSetFails()
public function testArrayAccessUnsetFails()
{
- $this->expectException(LogicException::class, 'Modifying parameters is not permitted');
+ $this->expectExceptionObject(new LogicException('Modifying parameters is not permitted'));
+
$params = new ParamBag(['foo' => 'bar']);
unset($params['foo']);
@@ -62,7 +63,8 @@ public function testObjectAccess()
public function testObjectAccessSetFails()
{
- $this->expectException(LogicException::class, 'Modifying parameters is not permitted');
+ $this->expectExceptionObject(new LogicException('Modifying parameters is not permitted'));
+
$params = new ParamBag(['foo' => 'bar']);
$params->foo = 'someothervalue';
@@ -70,7 +72,8 @@ public function testObjectAccessSetFails()
public function testObjectAccessUnsetFails()
{
- $this->expectException(LogicException::class, 'Modifying parameters is not permitted');
+ $this->expectExceptionObject(new LogicException('Modifying parameters is not permitted'));
+
$params = new ParamBag(['foo' => 'bar']);
unset($params->foo);
diff --git a/test/ScopeTest.php b/test/ScopeTest.php
index 717a6b78..4b62de62 100755
--- a/test/ScopeTest.php
+++ b/test/ScopeTest.php
@@ -74,6 +74,23 @@ public function testToArray()
$this->assertSame(['data' => ['foo' => 'bar']], $scope->toArray());
}
+ /**
+ * @covers \League\Fractal\Scope::jsonSerialize()
+ */
+ public function testJsonSerializable()
+ {
+ $manager = new Manager();
+
+ $resource = new Item(['foo' => 'bar'], function ($data) {
+ return $data;
+ });
+
+ $scope = new Scope($manager, $resource);
+
+ $this->assertInstanceOf('\JsonSerializable', $scope);
+ $this->assertEquals($scope->jsonSerialize(), $scope->toArray());
+ }
+
public function testToJson()
{
$data = [
@@ -209,9 +226,9 @@ public function testIsExcluded()
public function testScopeRequiresConcreteImplementation()
{
- $this->expectException(InvalidArgumentException::class);
+ $this->expectException(InvalidArgumentException::class);
- $manager = new Manager();
+ $manager = new Manager();
$manager->parseIncludes('book');
$resource = Mockery::mock('League\Fractal\Resource\ResourceAbstract', [
@@ -317,7 +334,7 @@ public function testRunAppropriateTransformerWithPrimitive()
$transformer = Mockery::mock('League\Fractal\TransformerAbstract');
$transformer->shouldReceive('transform')->once()->andReturn('simple string');
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
+ $transformer->shouldReceive('setCurrentScope')->once()->andReturnSelf();
$transformer->shouldNotReceive('getAvailableIncludes');
$transformer->shouldNotReceive('getDefaultIncludes');
@@ -342,7 +359,7 @@ public function testRunAppropriateTransformerWithItem()
$transformer->shouldReceive('transform')->once()->andReturn($this->simpleItem);
$transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]);
$transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
+ $transformer->shouldReceive('setCurrentScope')->once()->andReturnSelf();
$resource = new Item($this->simpleItem, $transformer);
$scope = $manager->createData($resource);
@@ -358,7 +375,7 @@ public function testRunAppropriateTransformerWithCollection()
$transformer->shouldReceive('transform')->once()->andReturn(['foo' => 'bar']);
$transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]);
$transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
+ $transformer->shouldReceive('setCurrentScope')->once()->andReturnSelf();
$resource = new Collection([['foo' => 'bar']], $transformer);
$scope = $manager->createData($resource);
@@ -371,7 +388,7 @@ public function testRunAppropriateTransformerWithCollection()
*/
public function testCreateDataWithClassFuckKnows()
{
- $this->expectException(InvalidArgumentException::class, '$resource should be an instance of League\Fractal\Resource\Item or League\Fractal\Resource\Collection');
+ $this->expectExceptionObject(new InvalidArgumentException('Argument $resource should be an instance of League\Fractal\Resource\Item or League\Fractal\Resource\Collection'));
$manager = new Manager();
diff --git a/test/Serializer/CustomArraySerializerTest.php b/test/Serializer/CustomArraySerializerTest.php
new file mode 100644
index 00000000..f1b5b962
--- /dev/null
+++ b/test/Serializer/CustomArraySerializerTest.php
@@ -0,0 +1,76 @@
+parseIncludes('author');
+ $manager->setSerializer(new RootSerializer());
+
+ $bookData = [
+ 'title' => 'Foo',
+ 'year' => '1991',
+ '_author' => [
+ 'name' => 'Dave',
+ ],
+ ];
+
+ $resource = new Item($bookData, new GenericBookNoResourceKeyTransformer(), 'data');
+ $scope = new Scope($manager, $resource);
+
+ $expected = [
+ 'data' => [
+ 'title' => 'Foo',
+ 'year' => 1991,
+ 'author' => [
+ 'name' => 'Dave',
+ ],
+ ],
+ ];
+
+ $this->assertSame($expected, $scope->toArray());
+ }
+
+ public function testMismatchedResourceKey()
+ {
+ $manager = new Manager();
+ $manager->parseIncludes('author');
+ $manager->setSerializer(new RootSerializer());
+
+ $bookData = [
+ 'title' => 'Foo',
+ 'year' => '1991',
+ '_author' => [
+ 'name' => 'Dave',
+ ],
+ ];
+
+ $resource = new Item($bookData, new GenericBookNoResourceKeyTransformer(), 'data');
+ $scope = new Scope($manager, $resource);
+
+ $expected = [
+ 'data' => [
+ 'title' => 'Foo',
+ 'year' => 1991,
+ 'author' => [
+ 'data' => [
+ 'name' => 'Dave',
+ ]
+ ],
+ ],
+ ];
+
+ $this->assertNotSame($expected, $scope->toArray());
+ }
+}
diff --git a/test/Stub/ArraySerializerWithNull.php b/test/Stub/ArraySerializerWithNull.php
index 9943ae61..7b5074eb 100644
--- a/test/Stub/ArraySerializerWithNull.php
+++ b/test/Stub/ArraySerializerWithNull.php
@@ -7,12 +7,7 @@
class ArraySerializerWithNull extends ArraySerializer
{
- /**
- * Serialize null resource.
- *
- * @return null
- */
- public function null()
+ public function null(): ?array
{
return null;
}
diff --git a/test/Stub/Serializer/RootSerializer.php b/test/Stub/Serializer/RootSerializer.php
new file mode 100644
index 00000000..fe04c519
--- /dev/null
+++ b/test/Stub/Serializer/RootSerializer.php
@@ -0,0 +1,32 @@
+ $data];
+ }
+
+ /**
+ * Serialize an item.
+ *
+ * @param string $resourceKey
+ * @param array $data
+ * @return array
+ */
+ public function item($resourceKey, array $data): array
+ {
+ return is_null($resourceKey) ? $data : [$resourceKey => $data];
+ }
+}
diff --git a/test/Stub/Transformer/DefaultIncludeBookTransformer.php b/test/Stub/Transformer/DefaultIncludeBookTransformer.php
index 54ec2a19..b3e57096 100644
--- a/test/Stub/Transformer/DefaultIncludeBookTransformer.php
+++ b/test/Stub/Transformer/DefaultIncludeBookTransformer.php
@@ -5,11 +5,11 @@
class DefaultIncludeBookTransformer extends TransformerAbstract
{
- protected $defaultIncludes = [
+ protected array $defaultIncludes = [
'author',
];
- public function transform()
+ public function transform(): array
{
return ['a' => 'b'];
}
diff --git a/test/Stub/Transformer/GenericBookNoResourceKeyTransformer.php b/test/Stub/Transformer/GenericBookNoResourceKeyTransformer.php
new file mode 100644
index 00000000..b18e3a1a
--- /dev/null
+++ b/test/Stub/Transformer/GenericBookNoResourceKeyTransformer.php
@@ -0,0 +1,29 @@
+item($book['_author'], new GenericAuthorTransformer());
+ }
+}
diff --git a/test/Stub/Transformer/GenericBookTransformer.php b/test/Stub/Transformer/GenericBookTransformer.php
index 59734ac1..f8649c63 100644
--- a/test/Stub/Transformer/GenericBookTransformer.php
+++ b/test/Stub/Transformer/GenericBookTransformer.php
@@ -5,11 +5,11 @@
class GenericBookTransformer extends TransformerAbstract
{
- protected $availableIncludes = [
+ protected array $availableIncludes = [
'author',
];
- public function transform(array $book)
+ public function transform(array $book): array
{
$book['year'] = (int) $book['year'];
unset($book['_author']);
diff --git a/test/Stub/Transformer/NullIncludeBookTransformer.php b/test/Stub/Transformer/NullIncludeBookTransformer.php
index 35e61b3a..d20f7ef7 100644
--- a/test/Stub/Transformer/NullIncludeBookTransformer.php
+++ b/test/Stub/Transformer/NullIncludeBookTransformer.php
@@ -5,11 +5,11 @@
class NullIncludeBookTransformer extends TransformerAbstract
{
- protected $defaultIncludes = [
+ protected array $defaultIncludes = [
'author',
];
- public function transform()
+ public function transform(): array
{
return ['a' => 'b'];
}
diff --git a/test/Stub/Transformer/PrimitiveIncludeBookTransformer.php b/test/Stub/Transformer/PrimitiveIncludeBookTransformer.php
index 3bd0aea8..79d286d7 100644
--- a/test/Stub/Transformer/PrimitiveIncludeBookTransformer.php
+++ b/test/Stub/Transformer/PrimitiveIncludeBookTransformer.php
@@ -1,20 +1,21 @@
'b'];
}
- public function includePrice(array $book)
+ public function includePrice(array $book): Primitive
{
return $this->primitive($book['price'], function ($price) {
return (int) $price;
diff --git a/test/TransformerAbstractTest.php b/test/TransformerAbstractTest.php
index 3a31a990..96137b61 100755
--- a/test/TransformerAbstractTest.php
+++ b/test/TransformerAbstractTest.php
@@ -74,6 +74,16 @@ public function testGetCurrentScope()
$this->assertSame($transformer->getCurrentScope(), $scope);
}
+ /**
+ * @covers \League\Fractal\TransformerAbstract::getCurrentScope
+ */
+ public function testCanAccessScopeBeforeInitialization()
+ {
+ $transformer = $this->getMockForAbstractClass('League\Fractal\TransformerAbstract');
+ $currentScope = $transformer->getCurrentScope();
+ $this->assertNull($currentScope);
+ }
+
public function testProcessEmbeddedResourcesNoAvailableIncludes()
{
$transformer = m::mock('League\Fractal\TransformerAbstract')->makePartial();
@@ -102,7 +112,7 @@ public function testProcessEmbeddedResourcesNoDefaultIncludes()
*/
public function testProcessEmbeddedResourcesInvalidAvailableEmbed()
{
- $this->expectException(BadMethodCallException::class);
+ $this->expectException(BadMethodCallException::class);
$transformer = m::mock('League\Fractal\TransformerAbstract')->makePartial();
@@ -122,7 +132,7 @@ public function testProcessEmbeddedResourcesInvalidAvailableEmbed()
*/
public function testProcessEmbeddedResourcesInvalidDefaultEmbed()
{
- $this->expectException(BadMethodCallException::class);
+ $this->expectException(BadMethodCallException::class);
$transformer = m::mock('League\Fractal\TransformerAbstract')->makePartial();
@@ -235,7 +245,7 @@ public function testProcessIncludedAvailableResourcesEmptyEmbed()
*/
public function testCallEmbedMethodReturnsCrap()
{
- $this->expectException(Exception::class, 'Invalid return value from League\Fractal\TransformerAbstract::includeBook().');
+ $this->expectExceptionObject(new Exception('Invalid return value from League\Fractal\TransformerAbstract::includeBook().'));
$manager = new Manager();
$manager->parseIncludes('book');