Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/phpcsfixer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Format with PHP CS Fixer

on: [pull_request, workflow_dispatch]

jobs:
php-cs-fixer:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: zip
coverage: none

- name: Install Dependencies
run: composer install --no-ansi --no-interaction --no-scripts --prefer-dist

- run: composer run format

- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Apply php-cs-fixer changes
22 changes: 22 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Perform static analysis with PHPStan

on: [pull_request, workflow_dispatch]

jobs:
phpstan:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: zip
coverage: none

- name: Install Dependencies
run: composer install --no-ansi --no-interaction --no-scripts --prefer-dist

- run: composer run phpstan
13 changes: 4 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ on: [pull_request, workflow_dispatch]

jobs:
test:
# not self-hosted, because it's a public repo
runs-on: ubuntu-latest

# we want to run it on combination of Laravel 8.12+ and PHP 8+
# we want to run it on supported combination of Laravel and PHP versions
strategy:
fail-fast: false
matrix:
php: ['8.0', '8.1']
laravel: ['^8.12', '^9.0', '^10.0']
exclude:
# minimum php version for Laravel 10 is PHP 8.1 so we need to exclude (php 8.0 and laravel 10) combination
- php: '8.0'
laravel: '^10.0'
php: ['8.1', '8.2']
laravel: ['^9.0', '^10.0']

steps:
- name: Checkout the repo
Expand All @@ -35,4 +30,4 @@ jobs:
run: composer require laravel/framework $LARAVEL_VERSION --no-interaction --no-scripts --prefer-dist

- name: Execute tests
run: vendor/bin/phpunit
run: composer run test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
composer.lock
.idea
.phpunit.result.cache
.phpunit.cache
.phpunit.cache
.php-cs-fixer.cache
25 changes: 25 additions & 0 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use PhpCsFixer\Config;
use PhpCsFixer\Finder;

/** @var Config $config */
$config = require_once join(DIRECTORY_SEPARATOR, [__DIR__, 'vendor', 'netsells', 'code-standards-laravel', 'phpcsfixer', 'config.php']);

$rules = array_merge_recursive($config->getRules(), [
// set project specific rules here
]);

$finder = Finder::create()
->in([
__DIR__ . '/src',
__DIR__ . '/tests',
])
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return $config
->setFinder($finder)
->setRules($rules);
15 changes: 11 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,25 @@
}
],
"require": {
"php": ">=8.0",
"php": "^8.1 || ^8.2",
"ext-json": "*",
"laravel/framework": "^8.12 || ^9.0 || ^10.0"
"laravel/framework": "^9.0 || ^10.0"
},
"require-dev": {
"orchestra/testbench": "^6.0 || ^7.0 || ^8.0",
"tmarsteel/mockery-callable-mock": "~2.1"
"orchestra/testbench": "^7.0 || ^8.0",
"tmarsteel/mockery-callable-mock": "~2.1",
"netsells/code-standards-laravel": "^1.1"
},
"autoload": {
"psr-4": {
"Netsells\\Http\\Resources\\": "src/",
"Netsells\\Http\\Resources\\Tests\\": "tests/"
}
},
"scripts": {
"phpstan": "vendor/bin/phpstan",
"lint": "vendor/bin/php-cs-fixer fix --dry-run --diff",
"format": "vendor/bin/php-cs-fixer fix",
"test": "vendor/bin/phpunit"
}
}
15 changes: 15 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
includes:
- ./vendor/netsells/code-standards-laravel/phpstan/extension.neon

parameters:
paths:
- src
- tests

# The level 9 is the highest level
level: 5

ignoreErrors:
excludePaths:

checkMissingIterableValueType: false
8 changes: 5 additions & 3 deletions src/Eloquent/EloquentDeferredValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Netsells\Http\Resources\Eloquent;

use Illuminate\Support\Collection;
use Netsells\Http\Resources\DeferredValue;
use Netsells\Http\Resources\Json\JsonResource;
use Netsells\Http\Resources\Json\ResourceCollection;
Expand All @@ -26,12 +27,12 @@ public static function resolve(array $deferredValues): void
{
static::loadEloquentRelations($deferredValues);

collect($deferredValues)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is collect() deprecated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not and is still available. I thought that it would be nice not to depend on a global function included from the Laravel helpers file, so I switched to using Collection class directly. However it was a bit of a 'half assed' attempt because there are still calls to data_get (which is only available as such global helper, and not a class I can hook into). So all in all, not a massive improvement and probably a bit of a useless change :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Illuminate\Support\Arr::get() not cut the mustard?

Copy link
Contributor Author

@kubatek94 kubatek94 Apr 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to say. Arr::get passes the tests, but looking at the implementation of both, I am not sure if Arr::get covers all the use cases that data_get does. The 'relation' string is controlled by the users of this package, so I can't be sure that it never gets called with e.g. '*' which is valid segment for data_get but not for Arr:get. In theory it shouldn't be, and the only supported 'relation' strings should be compatible with the Laravel Eloquent relation syntax. I think this change would require a new major version of this package just in case, and then I would also like to look at improved handling of the relation string in general - so would prefer to leave it as is, and then do the switch to Arr::get as part of this work. However, thanks for throwing that excellent suggestion, as I would definitely want to switch to that in the future! :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, they do look a little different.

Collection::make($deferredValues)
->filter(function (EloquentDeferredValue $deferredValue) {
return $deferredValue->resolver;
return (bool) $deferredValue->resolver;
})
->each(function (EloquentDeferredValue $deferredValue) {
$relations = collect($deferredValue->relations)->map(function ($relation) use ($deferredValue) {
$relations = Collection::make($deferredValue->relations)->map(function ($relation) use ($deferredValue) {
return data_get($deferredValue->resource, $relation);
})->all();

Expand All @@ -41,6 +42,7 @@ public static function resolve(array $deferredValues): void

/**
* Begins eager loading eloquent model relations.
*
* @param static[] $deferredValues
*/
abstract protected static function loadEloquentRelations(array $deferredValues): void;
Expand Down
4 changes: 2 additions & 2 deletions src/Eloquent/Load.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class Load extends EloquentDeferredValue
{
/**
* @inheritDoc
* {@inheritDoc}
*/
protected static function loadEloquentRelations(array $deferredValues): void
{
collect($deferredValues)->groupBy('relations')
Collection::make($deferredValues)->groupBy('relations')
->each(function (Collection $collection, $relation) {
EloquentCollection::make($collection->pluck('resource.resource'))
->load($relation);
Expand Down
4 changes: 2 additions & 2 deletions src/Eloquent/LoadCount.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class LoadCount extends EloquentDeferredValue
{
/**
* @inheritDoc
* {@inheritDoc}
*/
protected static function loadEloquentRelations(array $deferredValues): void
{
collect($deferredValues)->groupBy('relations')
Collection::make($deferredValues)->groupBy('relations')
->each(function (Collection $collection, $relation) {
EloquentCollection::make($collection->pluck('resource.resource'))
->loadCount($relation);
Expand Down
4 changes: 2 additions & 2 deletions src/Eloquent/LoadMissing.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class LoadMissing extends EloquentDeferredValue
{
/**
* @inheritDoc
* {@inheritDoc}
*/
protected static function loadEloquentRelations(array $deferredValues): void
{
collect($deferredValues)->groupBy('relations')
Collection::make($deferredValues)->groupBy('relations')
->each(function (Collection $collection, $relation) {
EloquentCollection::make($collection->pluck('resource.resource'))
->loadMissing($relation);
Expand Down
19 changes: 1 addition & 18 deletions src/Eloquent/ResolvesEloquentResources.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

namespace Netsells\Http\Resources\Eloquent;

use Netsells\Http\Resources\DeferredValue;
use Netsells\Http\Resources\Json\JsonResource;

trait ResolvesEloquentResources
{
/**
* @var class-string<DeferredValue>
* @var class-string<EloquentDeferredValue>
*/
protected string $defaultDeferredValueClass = LoadMissing::class;

/**
* @param string|string[] $relations
* @param callable|null $fn
* @return EloquentDeferredValue
*/
protected function load(string|array $relations, ?callable $fn = null): EloquentDeferredValue
{
Expand All @@ -24,8 +21,6 @@ protected function load(string|array $relations, ?callable $fn = null): Eloquent

/**
* @param string|string[] $relations
* @param callable|null $fn
* @return EloquentDeferredValue
*/
protected function loadMissing(string|array $relations, ?callable $fn = null): EloquentDeferredValue
{
Expand All @@ -34,8 +29,6 @@ protected function loadMissing(string|array $relations, ?callable $fn = null): E

/**
* @param string|string[] $relations
* @param callable|null $fn
* @return EloquentDeferredValue
*/
protected function loadCount(string|array $relations, ?callable $fn = null): EloquentDeferredValue
{
Expand All @@ -44,27 +37,19 @@ protected function loadCount(string|array $relations, ?callable $fn = null): Elo

/**
* @param string|string[] $relations
* @param callable|null $fn
* @return EloquentDeferredValue
*/
protected function use(string|array $relations, ?callable $fn = null): EloquentDeferredValue
{
return new $this->defaultDeferredValueClass($this, (array) $relations, $fn);
}

/**
* @param string ...$relations
* @return EloquentDeferredValue
*/
protected function preload(string ...$relations): EloquentDeferredValue
{
return new $this->defaultDeferredValueClass($this, $relations);
}

/**
* @param string $relation
* @param class-string<JsonResource> $resourceClass
* @return EloquentDeferredValue
*/
protected function many(string $relation, string $resourceClass): EloquentDeferredValue
{
Expand All @@ -74,9 +59,7 @@ protected function many(string $relation, string $resourceClass): EloquentDeferr
}

/**
* @param string $relation
* @param class-string<JsonResource> $resourceClass
* @return EloquentDeferredValue
*/
protected function one(string $relation, string $resourceClass): EloquentDeferredValue
{
Expand Down
7 changes: 7 additions & 0 deletions src/Json/AnonymousResourceCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

class AnonymousResourceCollection extends ResourceCollection
{
/**
* Indicates if the collection keys should be preserved.
*
* @var bool
*/
public $preserveKeys = false;

public function __construct(mixed $resource, string $collects)
{
$this->collects = $collects;
Expand Down
19 changes: 9 additions & 10 deletions src/Json/JsonResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Netsells\Http\Resources\DeferredValue;
use Netsells\Http\Resources\Eloquent\ResolvesEloquentResources;
use Netsells\Http\Resources\ResolvesResources;

Expand All @@ -14,18 +13,13 @@ class JsonResource extends \Illuminate\Http\Resources\Json\JsonResource
use ResolvesEloquentResources;

/**
* @return DeferredValue|DeferredValue[]
* @deprecated This method can be removed when dropping support for Laravel 9.
*/
public function preloads(/** @param Request $request */)
public static function collection($resource)
{
return [];
}

public static function collection(mixed $resource): AnonymousResourceCollection
{
return tap(new AnonymousResourceCollection($resource, static::class), function ($collection) {
return tap(static::newCollection($resource), function ($collection) { // @phpstan-ignore-line
if (property_exists(static::class, 'preserveKeys')) {
$collection->preserveKeys = (new static([]))->preserveKeys === true;
$collection->preserveKeys = (new static([]))->preserveKeys === true; // @phpstan-ignore-line
}
});
}
Expand All @@ -34,4 +28,9 @@ protected function beforeResolveRoot(Request $request): void
{
$this->collectAndResolvePreloads($request, Collection::make([$this]));
}

protected static function newCollection(mixed $resource): AnonymousResourceCollection
{
return new AnonymousResourceCollection($resource, static::class);
}
}
Loading