Skip to content

Commit fd7498b

Browse files
committed
Merge branch 'release/1.0.0-beta.1' into main
2 parents c82f217 + 523e91b commit fd7498b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+987
-267
lines changed

CHANGELOG.md

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,39 @@
33
All notable changes to this project will be documented in this file. This project adheres to
44
[Semantic Versioning](http://semver.org/) and [this changelog format](http://keepachangelog.com/).
55

6+
## [1.0.0-beta.1] - 2021-03-30
7+
8+
### Added
9+
10+
- [#18](https://github.com/laravel-json-api/laravel/issues/18) Added a `withCount` query parameter. For Eloquent
11+
resources, this allows a client to request the relationship count for the primary data's relationships. Refer to
12+
documentation for implementation details.
13+
- [#55](https://github.com/laravel-json-api/laravel/pull/55) Encoding and decoding of resource IDs is now supported.
14+
The `ID` field needs to implement the `LaravelJsonApi\Contracts\Schema\IdEncoder` interface for this to work.
15+
- [#41](https://github.com/laravel-json-api/laravel/issues/41) Hash IDs are now supported by installing the
16+
`laravel-json-api/hashids` package and using the `HashId` field instead of the standard Eloquent `ID` field. Refer to
17+
documentation for details.
18+
- [#30](https://github.com/laravel-json-api/laravel/issues/30) Non-Eloquent resources are no supported via the
19+
`laravel-json-api/non-eloquent` package. Refer to documentation for implementation details.
20+
- There is now a `Core\Reponses\RelatedResponse` class for returning the result for a related resources endpoint. For
21+
example, the `/api/v1/posts/1/comments` endpoint. Previously the `DataResponse` class was used. While this class can
22+
still be used, the new `RelatedResponse` class merges relationship meta into the top-level `meta` member of the
23+
response document. For *to-many* relationships that are countable, this will mean the top-level `meta` member will
24+
contain the count of the relationship.
25+
- The schema generator Artisan command now has a `--non-eloquent` option to generate a schema for a non-Eloquent
26+
resource.
27+
28+
### Changed
29+
30+
- The `LaravelJsonApi::registerQuery()`, `LaravelJsonApi::registerCollectionQuery()` and
31+
`LaravelJsonApi::registerRequest()` methods must now be used to register custom HTTP request classes for specified
32+
resource types. Previously methods could be called on the `RequestResolver` classes, but these have now been removed.
33+
34+
### Fixed
35+
36+
- Relationship endpoints that return resource identifiers now correctly include page meta in the top-level meta member
37+
of the document, if the results are paginated. Previously the page meta was incorrectly omitted.
38+
639
## [1.0.0-alpha.5] - 2021-03-12
740

841
### Added

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ composer require laravel-json-api/laravel
1919

2020
See our documentation for further installation instructions.
2121

22+
## Example Application
23+
24+
To view an example Laravel application that uses this package, see the
25+
[Dummy Application](https://github.com/laravel-json-api/laravel/tree/main/tests/dummy) within the tests folder.
26+
2227
## License
2328

2429
Laravel JSON:API is open-sourced software licensed under the [Apache 2.0 License](./LICENSE).

composer.json

+8-7
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525
"require": {
2626
"php": "^7.4|^8.0",
2727
"ext-json": "*",
28-
"laravel-json-api/core": "^1.0.0-alpha.5",
29-
"laravel-json-api/eloquent": "^1.0.0-alpha.5",
30-
"laravel-json-api/encoder-neomerx": "^1.0.0-alpha.4",
31-
"laravel-json-api/exceptions": "^1.0.0-alpha.2",
32-
"laravel-json-api/spec": "^1.0.0-alpha.4",
33-
"laravel-json-api/validation": "^1.0.0-alpha.5",
28+
"laravel-json-api/core": "^1.0.0-beta.1",
29+
"laravel-json-api/eloquent": "^1.0.0-beta.1",
30+
"laravel-json-api/encoder-neomerx": "^1.0.0-beta.1",
31+
"laravel-json-api/exceptions": "^1.0.0-beta.1",
32+
"laravel-json-api/spec": "^1.0.0-beta.1",
33+
"laravel-json-api/validation": "^1.0.0-beta.1",
3434
"laravel/framework": "^8.0"
3535
},
3636
"require-dev": {
37-
"laravel-json-api/testing": "^1.0.0-alpha.1",
37+
"laravel-json-api/hashids": "^1.0.0-beta.1",
38+
"laravel-json-api/testing": "^1.0.0-beta.1",
3839
"orchestra/testbench": "^6.9",
3940
"phpunit/phpunit": "^9.5"
4041
},

src/Console/MakeQuery.php

+31
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
namespace LaravelJsonApi\Laravel\Console;
2121

22+
use LaravelJsonApi\Core\Query\Custom\ExtendedQueryParameters;
2223
use Symfony\Component\Console\Input\InputOption;
2324

2425
class MakeQuery extends GeneratorCommand
@@ -82,6 +83,36 @@ protected function getClassType(): string
8283
return 'Query';
8384
}
8485

86+
/**
87+
* @inheritDoc
88+
*/
89+
protected function buildClass($name)
90+
{
91+
$stub = parent::buildClass($name);
92+
93+
return $this->replaceAdditional($stub);
94+
}
95+
96+
/**
97+
* Replace additional placeholders.
98+
*
99+
* @param string $stub
100+
* @return string
101+
*/
102+
protected function replaceAdditional(string $stub): string
103+
{
104+
$withCount = ExtendedQueryParameters::withCount();
105+
106+
$replace = [
107+
'{{ withCount }}' => $withCount,
108+
'{{withCount}}' => $withCount,
109+
];
110+
111+
return str_replace(
112+
array_keys($replace), array_values($replace), $stub
113+
);
114+
}
115+
85116
/**
86117
* @inheritDoc
87118
*/

src/Console/MakeSchema.php

+5
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ class MakeSchema extends GeneratorCommand
5353
*/
5454
protected function getStub()
5555
{
56+
if ($this->option('non-eloquent')) {
57+
return $this->resolveStubPath('non-eloquent-schema.stub');
58+
}
59+
5660
return $this->resolveStubPath('schema.stub');
5761
}
5862

@@ -108,6 +112,7 @@ protected function getOptions()
108112
return [
109113
['force', null, InputOption::VALUE_NONE, 'Create the class even if the schema already exists'],
110114
['model', 'm', InputOption::VALUE_REQUIRED, 'The model that the schema applies to.'],
115+
['non-eloquent', null, InputOption::VALUE_NONE, 'Create a schema for a non-Eloquent resource.'],
111116
['proxy', 'p', InputOption::VALUE_NONE, 'Create a schema for an Eloquent model proxy.'],
112117
['server', 's', InputOption::VALUE_REQUIRED, 'The JSON:API server the schema exists in.'],
113118
];

src/Http/Controllers/Actions/FetchRelated.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
use Illuminate\Http\Response;
2424
use LaravelJsonApi\Contracts\Routing\Route;
2525
use LaravelJsonApi\Contracts\Store\Store as StoreContract;
26-
use LaravelJsonApi\Core\Responses\DataResponse;
26+
use LaravelJsonApi\Core\Responses\RelatedResponse;
2727
use LaravelJsonApi\Core\Support\Str;
2828
use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery;
2929

@@ -76,6 +76,10 @@ public function showRelated(Route $route, StoreContract $store)
7676
$response = $this->{$hook}($model, $data, $request);
7777
}
7878

79-
return $response ?: new DataResponse($data);
79+
return $response ?: new RelatedResponse(
80+
$model,
81+
$relation->name(),
82+
$data,
83+
);
8084
}
8185
}

src/Http/Requests/AnonymousCollectionQuery.php

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace LaravelJsonApi\Laravel\Http\Requests;
1919

20+
use LaravelJsonApi\Core\Query\Custom\ExtendedQueryParameters;
2021
use LaravelJsonApi\Validation\Rule as JsonApiRule;
2122

2223
class AnonymousCollectionQuery extends ResourceQuery
@@ -55,6 +56,11 @@ public function rules()
5556
'string',
5657
JsonApiRule::sort(),
5758
],
59+
ExtendedQueryParameters::withCount() => [
60+
'nullable',
61+
'string',
62+
JsonApiRule::countable(),
63+
],
5864
];
5965
}
6066
}

src/Http/Requests/AnonymousQuery.php

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace LaravelJsonApi\Laravel\Http\Requests;
1919

20+
use LaravelJsonApi\Core\Query\Custom\ExtendedQueryParameters;
2021
use LaravelJsonApi\Validation\Rule as JsonApiRule;
2122

2223
class AnonymousQuery extends ResourceQuery
@@ -47,6 +48,11 @@ public function rules()
4748
],
4849
'page' => JsonApiRule::notSupported(),
4950
'sort' => JsonApiRule::notSupported(),
51+
ExtendedQueryParameters::withCount() => [
52+
'nullable',
53+
'string',
54+
JsonApiRule::countable(),
55+
],
5056
];
5157
}
5258
}

src/Http/Requests/RequestResolver.php

+18-30
Original file line numberDiff line numberDiff line change
@@ -30,47 +30,37 @@
3030
class RequestResolver
3131
{
3232

33+
public const QUERY = 'Query';
34+
public const COLLECTION_QUERY = 'CollectionQuery';
35+
public const REQUEST = 'Request';
36+
3337
/**
3438
* @var array
3539
*/
3640
private static array $custom = [];
3741

3842
/**
39-
* @var string
43+
* @var array
4044
*/
41-
private string $type;
45+
private static array $defaults = [
46+
self::QUERY => AnonymousQuery::class,
47+
self::COLLECTION_QUERY => AnonymousCollectionQuery::class,
48+
];
4249

4350
/**
44-
* Register a custom binding for a query.
45-
*
46-
* @param string $resourceType
47-
* @param string $class
48-
*/
49-
public static function registerQuery(string $resourceType, string $class): void
50-
{
51-
self::register('Query', $resourceType, $class);
52-
}
53-
54-
/**
55-
* Register a custom binding for a collection query.
56-
*
57-
* @param string $resourceType
58-
* @param string $class
51+
* @var string
5952
*/
60-
public static function registerCollectionQuery(string $resourceType, string $class): void
61-
{
62-
self::register('CollectionQuery', $resourceType, $class);
63-
}
53+
private string $type;
6454

6555
/**
66-
* Register a custom binding for a resource request.
56+
* Use the provided class as the default class for the specified request type.
6757
*
68-
* @param string $resourceType
58+
* @param string $type
6959
* @param string $class
7060
*/
71-
public static function registerRequest(string $resourceType, string $class): void
61+
public static function useDefault(string $type, string $class): void
7262
{
73-
self::register('Request', $resourceType, $class);
63+
self::$defaults[$type] = $class;
7464
}
7565

7666
/**
@@ -80,7 +70,7 @@ public static function registerRequest(string $resourceType, string $class): voi
8070
* @param string $resourceType
8171
* @param string $class
8272
*/
83-
private static function register(string $type, string $resourceType, string $class): void
73+
public static function register(string $type, string $resourceType, string $class): void
8474
{
8575
self::$custom[$type] = self::$custom[$type] ?? [];
8676
self::$custom[$type][$resourceType] = $class;
@@ -113,10 +103,8 @@ public function __invoke(string $resourceType, bool $allowNull = false): ?FormRe
113103
if (!class_exists($fqn) && !$app->bound($fqn)) {
114104
if (true === $allowNull) {
115105
return null;
116-
} else if ('CollectionQuery' === $this->type) {
117-
$fqn = AnonymousCollectionQuery::class;
118-
} else if ('Query' === $this->type) {
119-
$fqn = AnonymousQuery::class;
106+
} else if (isset(self::$defaults[$this->type])) {
107+
$fqn = self::$defaults[$this->type];
120108
}
121109
}
122110

src/Http/Requests/ResourceQuery.php

+19-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use LaravelJsonApi\Contracts\Query\QueryParameters;
2626
use LaravelJsonApi\Core\Exceptions\JsonApiException;
2727
use LaravelJsonApi\Core\Query\FieldSets;
28+
use LaravelJsonApi\Core\Query\FilterParameters;
2829
use LaravelJsonApi\Core\Query\IncludePaths;
2930
use LaravelJsonApi\Core\Query\SortFields;
3031
use Symfony\Component\HttpKernel\Exception\HttpException;
@@ -70,7 +71,7 @@ public static function guessQueryManyUsing(callable $resolver): void
7071
*/
7172
public static function queryMany(string $resourceType): QueryParameters
7273
{
73-
$resolver = self::$queryManyResolver ?: new RequestResolver('CollectionQuery');
74+
$resolver = self::$queryManyResolver ?: new RequestResolver(RequestResolver::COLLECTION_QUERY);
7475

7576
return $resolver($resourceType);
7677
}
@@ -94,7 +95,7 @@ public static function guessQueryOneUsing(callable $resolver): void
9495
*/
9596
public static function queryOne(string $resourceType): QueryParameters
9697
{
97-
$resolver = self::$queryManyResolver ?: new RequestResolver('Query');
98+
$resolver = self::$queryManyResolver ?: new RequestResolver(RequestResolver::QUERY);
9899

99100
return $resolver($resourceType);
100101
}
@@ -196,17 +197,31 @@ public function page(): ?array
196197
/**
197198
* @inheritDoc
198199
*/
199-
public function filter(): ?array
200+
public function filter(): ?FilterParameters
200201
{
201202
$data = $this->validated();
202203

203204
if (array_key_exists('filter', $data)) {
204-
return $data['filter'];
205+
return FilterParameters::fromArray($data['filter'] ?? []);
205206
}
206207

207208
return null;
208209
}
209210

211+
/**
212+
* @inheritDoc
213+
*/
214+
public function unrecognisedParameters(): array
215+
{
216+
return collect($this->validated())->forget([
217+
'include',
218+
'fields',
219+
'sort',
220+
'page',
221+
'filter',
222+
])->all();
223+
}
224+
210225
/**
211226
* @return void
212227
*/

src/Http/Requests/ResourceRequest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static function guessResourceRequestUsing(callable $resolver): void
6969
*/
7070
public static function forResource(string $resourceType): ResourceRequest
7171
{
72-
$resolver = self::$requestResolver ?: new RequestResolver('Request');
72+
$resolver = self::$requestResolver ?: new RequestResolver(RequestResolver::REQUEST);
7373

7474
return $resolver($resourceType);
7575
}
@@ -82,7 +82,7 @@ public static function forResource(string $resourceType): ResourceRequest
8282
*/
8383
public static function forResourceIfExists(string $resourceType): ?ResourceRequest
8484
{
85-
$resolver = self::$requestResolver ?: new RequestResolver('Request');
85+
$resolver = self::$requestResolver ?: new RequestResolver(RequestResolver::REQUEST);
8686

8787
return $resolver($resourceType, true);
8888
}

0 commit comments

Comments
 (0)