Skip to content

Commit 480a0fa

Browse files
committed
wip
1 parent ca9cd62 commit 480a0fa

File tree

11 files changed

+66
-57
lines changed

11 files changed

+66
-57
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,6 @@ You should indicate to the server if the consumer is authenticated using the `au
507507
$api->authenticated();
508508
```
509509

510-
## Examples
511-
512-
- [Forust](https://github.com/forust/core/tree/master/schema) is forum software that uses tobyz/json-api-server to power its API.
513-
514510
## Contributing
515511

516512
Feel free to send pull requests or create issues if you come across problems or have great ideas. See the [Contributing Guide](https://github.com/tobyz/json-api-server/blob/master/CONTRIBUTING.md) for more information.

src/Adapter/AdapterInterface.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,27 +150,20 @@ public function getAttribute($model, Attribute $attribute);
150150
*
151151
* @param $model
152152
* @param HasOne $relationship
153+
* @param array $fields
153154
* @return mixed|null
154155
*/
155-
public function getHasOne($model, HasOne $relationship);
156-
157-
/**
158-
* Get the ID of the related resource for a has-one relationship.
159-
*
160-
* @param $model
161-
* @param HasOne $relationship
162-
* @return mixed|null
163-
*/
164-
public function getHasOneId($model, HasOne $relationship): ?string;
156+
public function getHasOne($model, HasOne $relationship, array $fields = null);
165157

166158
/**
167159
* Get a list of models for a has-many relationship for the model.
168160
*
169161
* @param $model
170162
* @param HasMany $relationship
163+
* @param array $fields
171164
* @return array
172165
*/
173-
public function getHasMany($model, HasMany $relationship): array;
166+
public function getHasMany($model, HasMany $relationship, array $fields = null): array;
174167

175168
/**
176169
* Apply an attribute value to the model.

src/Adapter/EloquentAdapter.php

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,28 +69,25 @@ public function getAttribute($model, Attribute $attribute)
6969
return $model->{$this->getAttributeProperty($attribute)};
7070
}
7171

72-
public function getHasOneId($model, HasOne $relationship): ?string
72+
public function getHasOne($model, HasOne $relationship, array $fields = null)
7373
{
74-
$relation = $this->getRelation($model, $relationship);
74+
$relation = $this->getEloquentRelation($model, $relationship);
7575

76-
// If this is a belongs-to relation, we can simply return the value of
77-
// the foreign key on the model. Otherwise we will have to fetch the
78-
// full related model and return its key.
79-
if ($relation instanceof BelongsTo) {
80-
return $model->{$relation->getForeignKeyName()};
81-
}
76+
// comment
77+
if ($fields === ['id'] && $relation instanceof BelongsTo) {
78+
if ($key = $model->{$relation->getForeignKeyName()}) {
79+
$related = $relation->getRelated();
8280

83-
$related = $this->getRelationValue($model, $relationship);
81+
return $related->newInstance()->forceFill([$related->getKeyName() => $key]);
82+
}
8483

85-
return $related ? $related->getKey() : null;
86-
}
84+
return null;
85+
}
8786

88-
public function getHasOne($model, HasOne $relationship)
89-
{
9087
return $this->getRelationValue($model, $relationship);
9188
}
9289

93-
public function getHasMany($model, HasMany $relationship): array
90+
public function getHasMany($model, HasMany $relationship, array $fields = null): array
9491
{
9592
$collection = $this->getRelationValue($model, $relationship);
9693

@@ -104,7 +101,7 @@ public function setAttribute($model, Attribute $attribute, $value): void
104101

105102
public function setHasOne($model, HasOne $relationship, $related): void
106103
{
107-
$this->getRelation($model, $relationship)->associate($related);
104+
$this->getEloquentRelation($model, $relationship)->associate($related);
108105
}
109106

110107
public function save($model): void
@@ -114,7 +111,7 @@ public function save($model): void
114111

115112
public function saveHasMany($model, HasMany $relationship, array $related): void
116113
{
117-
$this->getRelation($model, $relationship)->sync(new Collection($related));
114+
$this->getEloquentRelation($model, $relationship)->sync(new Collection($related));
118115
}
119116

120117
public function delete($model): void
@@ -165,15 +162,15 @@ public function filterByAttribute($query, Attribute $attribute, $value): void
165162

166163
public function filterByHasOne($query, HasOne $relationship, array $ids): void
167164
{
168-
$relation = $this->getRelation($query->getModel(), $relationship);
165+
$relation = $this->getEloquentRelation($query->getModel(), $relationship);
169166

170167
$query->whereIn($relation->getQualifiedForeignKeyName(), $ids);
171168
}
172169

173170
public function filterByHasMany($query, HasMany $relationship, array $ids): void
174171
{
175172
$property = $this->getRelationshipProperty($relationship);
176-
$relation = $this->getRelation($query->getModel(), $relationship);
173+
$relation = $this->getEloquentRelation($query->getModel(), $relationship);
177174
$relatedKey = $relation->getRelated()->getQualifiedKeyName();
178175

179176
$query->whereHas($property, function ($query) use ($relatedKey, $ids) {
@@ -239,7 +236,7 @@ private function getRelationshipPath(array $trail): string
239236
return implode('.', array_map([$this, 'getRelationshipProperty'], $trail));
240237
}
241238

242-
private function getRelation($model, Relationship $relationship)
239+
private function getEloquentRelation($model, Relationship $relationship)
243240
{
244241
return $model->{$this->getRelationshipProperty($relationship)}();
245242
}

src/Handler/Concerns/SavesData.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use function Tobyz\JsonApiServer\evaluate;
77
use function Tobyz\JsonApiServer\get_value;
88
use function Tobyz\JsonApiServer\has_value;
9+
use function Tobyz\JsonApiServer\set_value;
910
use Tobyz\JsonApiServer\Exception\BadRequestException;
1011
use Tobyz\JsonApiServer\Exception\UnprocessableEntityException;
1112
use function Tobyz\JsonApiServer\run_callbacks;
@@ -44,7 +45,7 @@ private function parseData($body): array
4445
);
4546
}
4647

47-
private function getModelForIdentifier(Request $request, $identifier)
48+
private function getModelForIdentifier(Request $request, $identifier, array $validTypes = null)
4849
{
4950
if (! isset($identifier['type'])) {
5051
throw new BadRequestException('type not specified');
@@ -54,6 +55,10 @@ private function getModelForIdentifier(Request $request, $identifier)
5455
throw new BadRequestException('id not specified');
5556
}
5657

58+
if ($validTypes !== null && ! in_array($identifier['type'], $validTypes)) {
59+
throw new BadRequestException("type [{$identifier['type']}] not allowed");
60+
}
61+
5762
$resource = $this->api->getResource($identifier['type']);
5863

5964
return $this->findResource($request, $resource, $identifier['id']);
@@ -94,16 +99,20 @@ private function loadRelatedResources(array &$data, Request $request)
9499
continue;
95100
}
96101

97-
$value = &get_value($data, $field);
102+
$value = get_value($data, $field);
98103

99104
if (isset($value['data'])) {
105+
$allowedTypes = $field->getAllowedTypes();
106+
100107
if ($field instanceof HasOne) {
101-
$value = $this->getModelForIdentifier($request, $value['data']);
108+
set_value($data, $field, $this->getModelForIdentifier($request, $value['data'], $allowedTypes));
102109
} elseif ($field instanceof HasMany) {
103-
$value = array_map(function ($identifier) use ($request) {
104-
return $this->getModelForIdentifier($request, $identifier);
105-
}, $value['data']);
110+
set_value($data, $field, array_map(function ($identifier) use ($request, $allowedTypes) {
111+
return $this->getModelForIdentifier($request, $identifier, $allowedTypes);
112+
}, $value['data']));
106113
}
114+
} else {
115+
set_value($data, $field, null);
107116
}
108117
}
109118
}

src/Handler/Create.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ public function handle(Request $request): Response
4343
$this->assertDataValid($data, $model, $request, true);
4444
$this->setValues($data, $model, $request);
4545

46-
run_callbacks($schema->getListeners('creating'), [$request, $model]);
46+
run_callbacks($schema->getListeners('creating'), [$model, $request]);
4747

4848
$this->save($data, $model, $request);
4949

50-
run_callbacks($schema->getListeners('created'), [$request, $model]);
50+
run_callbacks($schema->getListeners('created'), [$model, $request]);
5151

5252
return (new Show($this->api, $this->resource, $model))
5353
->handle($request)

src/Handler/Delete.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ public function handle(Request $request): Response
2626
{
2727
$schema = $this->resource->getSchema();
2828

29-
if (! evaluate($schema->getDeletable(), [$request, $this->model])) {
29+
if (! evaluate($schema->getDeletable(), [$this->model, $request])) {
3030
throw new ForbiddenException;
3131
}
3232

33-
run_callbacks($schema->getListeners('deleting'), [$request, $this->model]);
33+
run_callbacks($schema->getListeners('deleting'), [$this->model, $request]);
3434

3535
$this->resource->getAdapter()->delete($this->model);
3636

37-
run_callbacks($schema->getListeners('deleted'), [$request, $this->model]);
37+
run_callbacks($schema->getListeners('deleted'), [$this->model, $request]);
3838

3939
return new EmptyResponse;
4040
}

src/Handler/Update.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function handle(Request $request): Response
3030
{
3131
$schema = $this->resource->getSchema();
3232

33-
if (! evaluate($schema->getUpdatable(), [$request, $this->model])) {
33+
if (! evaluate($schema->getUpdatable(), [$this->model, $request])) {
3434
throw new ForbiddenException;
3535
}
3636

@@ -41,11 +41,11 @@ public function handle(Request $request): Response
4141
$this->assertDataValid($data, $this->model, $request, false);
4242
$this->setValues($data, $this->model, $request);
4343

44-
run_callbacks($schema->getListeners('updating'), [$request, $this->model]);
44+
run_callbacks($schema->getListeners('updating'), [$this->model, $request]);
4545

4646
$this->save($data, $this->model, $request);
4747

48-
run_callbacks($schema->getListeners('updated'), [$request, $this->model]);
48+
run_callbacks($schema->getListeners('updated'), [$this->model, $request]);
4949

5050
return (new Show($this->api, $this->resource, $this->model))->handle($request);
5151
}

src/Schema/Relationship.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
abstract class Relationship extends Field
99
{
1010
private $type;
11+
private $allowedTypes;
1112
private $linkage = false;
1213
private $links = true;
1314
private $loadable = true;
@@ -20,9 +21,10 @@ public function type($type)
2021
return $this;
2122
}
2223

23-
public function polymorphic()
24+
public function polymorphic(array $types = null)
2425
{
2526
$this->type = null;
27+
$this->allowedTypes = $types;
2628

2729
return $this;
2830
}
@@ -69,11 +71,16 @@ public function notIncludable()
6971
return $this;
7072
}
7173

72-
public function getType()
74+
public function getType(): ?string
7375
{
7476
return $this->type;
7577
}
7678

79+
public function getAllowedTypes(): ?array
80+
{
81+
return $this->allowedTypes;
82+
}
83+
7784
public function links()
7885
{
7986
$this->links = true;

src/Serializer.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private function toOne(Schema\HasOne $field, $model, AdapterInterface $adapter,
125125
{
126126
$links = $this->getRelationshipLinks($field, $resourceUrl);
127127

128-
$value = $isIncluded ? (($getter = $field->getGetter()) ? $getter($model, $this->request) : $adapter->getHasOne($model, $field)) : ($isLinkage && $field->getLoadable() ? $adapter->getHasOneId($model, $field) : null);
128+
$value = $isIncluded ? (($getter = $field->getGetter()) ? $getter($model, $this->request) : $adapter->getHasOne($model, $field)) : ($isLinkage && $field->getLoadable() ? $adapter->getHasOne($model, $field, ['id']) : null);
129129

130130
if (! $value) {
131131
return new Structure\ToNull(
@@ -207,7 +207,7 @@ private function addRelated(Relationship $field, $model, array $include): Resour
207207
private function resourceForModel($model)
208208
{
209209
foreach ($this->api->getResources() as $resource) {
210-
if ($resource->getAdapter()->handles($model)) {
210+
if ($resource->getAdapter()->represents($model)) {
211211
return $resource;
212212
}
213213
}
@@ -270,11 +270,13 @@ private function resourceIdentifier(array $data): Structure\ResourceIdentifier
270270

271271
private function relatedResourceIdentifier(Schema\Relationship $field, $model)
272272
{
273-
$relatedResource = $this->api->getResource($type = $field->getType());
273+
$type = $field->getType();
274+
275+
$relatedResource = $type ? $this->api->getResource($type) : $this->resourceForModel($model);
274276

275277
return $this->resourceIdentifier([
276-
'type' => $type,
277-
'id' => is_string($model) ? $model : $relatedResource->getAdapter()->getId($model)
278+
'type' => $relatedResource->getType(),
279+
'id' => $relatedResource->getAdapter()->getId($model)
278280
]);
279281
}
280282
}

src/functions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ function has_value(array $data, Field $field)
4040
return isset($data[$field->getLocation()][$field->getName()]);
4141
}
4242

43-
function &get_value(array $data, Field $field)
43+
function get_value(array $data, Field $field)
4444
{
45-
return $data[$field->getLocation()][$field->getName()];
45+
return $data[$field->getLocation()][$field->getName()] ?? null;
4646
}
4747

4848
function set_value(array &$data, Field $field, $value)

0 commit comments

Comments
 (0)