Skip to content

Commit 0d43544

Browse files
committed
wip
1 parent adc388e commit 0d43544

File tree

6 files changed

+90
-19
lines changed

6 files changed

+90
-19
lines changed

src/Handler/Concerns/IncludesData.php

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ private function validateInclude(ResourceType $resource, array $include, string
5757
throw new BadRequestException("Invalid include [{$path}{$name}]", 'include');
5858
}
5959

60-
$relatedResource = $this->api->getResource($schema->fields[$name]->resource);
60+
if (is_string($schema->fields[$name]->resource)) {
61+
$relatedResource = $this->api->getResource($schema->fields[$name]->resource);
6162

62-
$this->validateInclude($relatedResource, $nested, $name.'.');
63+
$this->validateInclude($relatedResource, $nested, $name.'.');
64+
}
6365
}
6466
}
6567

@@ -75,17 +77,19 @@ private function buildRelationshipTrails(ResourceType $resource, array $include)
7577
$trails[] = [$relationship];
7678
}
7779

78-
$relatedResource = $this->api->getResource($relationship->resource);
79-
80-
$trails = array_merge(
81-
$trails,
82-
array_map(
83-
function ($trail) use ($relationship) {
84-
return array_merge([$relationship], $trail);
85-
},
86-
$this->buildRelationshipTrails($relatedResource, $nested)
87-
)
88-
);
80+
if (is_string($schema->fields[$name]->resource)) {
81+
$relatedResource = $this->api->getResource($relationship->resource);
82+
83+
$trails = array_merge(
84+
$trails,
85+
array_map(
86+
function ($trail) use ($relationship) {
87+
return array_merge([$relationship], $trail);
88+
},
89+
$this->buildRelationshipTrails($relatedResource, $nested)
90+
)
91+
);
92+
}
8993
}
9094

9195
return $trails;
@@ -101,13 +105,21 @@ private function loadRelationships(array $models, array $include, Request $reque
101105
continue;
102106
}
103107

104-
$adapter->loadIds($models, $field);
108+
if ($field->loader) {
109+
($field->loader)($models, true);
110+
} else {
111+
$adapter->loadIds($models, $field);
112+
}
105113
}
106114

107115
$trails = $this->buildRelationshipTrails($this->resource, $include);
108116

109117
foreach ($trails as $relationships) {
110-
$adapter->load($models, $relationships);
118+
if ($loader = end($relationships)->loader) {
119+
($loader)($models, false);
120+
} else {
121+
$adapter->load($models, $relationships);
122+
}
111123
}
112124
}
113125
}

src/Handler/Index.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Psr\Http\Server\RequestHandlerInterface;
1111
use Tobscure\JsonApiServer\Api;
1212
use Tobscure\JsonApiServer\Exception\BadRequestException;
13+
use Tobscure\JsonApiServer\Exception\ForbiddenException;
1314
use Tobscure\JsonApiServer\JsonApiResponse;
1415
use Tobscure\JsonApiServer\ResourceType;
1516
use Tobscure\JsonApiServer\Schema;
@@ -37,6 +38,10 @@ public function handle(Request $request): Response
3738
$adapter = $this->resource->getAdapter();
3839
$schema = $this->resource->getSchema();
3940

41+
if (! ($schema->isVisible)($request)) {
42+
throw new ForbiddenException('You cannot view this resource');
43+
}
44+
4045
$query = $adapter->query();
4146

4247
foreach ($schema->scopes as $scope) {
@@ -219,7 +224,7 @@ private function sort($query, array $sort, Request $request)
219224
$attribute = $schema->fields[$name];
220225

221226
if ($attribute->sorter) {
222-
($attribute->sorter)($query, $direction, $request);
227+
($attribute->sorter)($request, $query, $direction);
223228
} else {
224229
$adapter->sortByAttribute($query, $attribute, $direction);
225230
}

src/Handler/Show.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Psr\Http\Message\ServerRequestInterface as Request;
88
use Psr\Http\Server\RequestHandlerInterface;
99
use Tobscure\JsonApiServer\Api;
10+
use Tobscure\JsonApiServer\Exception\ForbiddenException;
1011
use Tobscure\JsonApiServer\JsonApiResponse;
1112
use Tobscure\JsonApiServer\ResourceType;
1213
use Tobscure\JsonApiServer\Serializer;
@@ -28,6 +29,12 @@ public function __construct(Api $api, ResourceType $resource, $model)
2829

2930
public function handle(Request $request): Response
3031
{
32+
$schema = $this->resource->getSchema();
33+
34+
if (! ($schema->isVisible)($request)) {
35+
throw new ForbiddenException('You cannot view this resource');
36+
}
37+
3138
$include = $this->getInclude($request);
3239

3340
$this->loadRelationships([$this->model], $include, $request);

src/Schema/Builder.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class Builder
3030

3131
public function __construct()
3232
{
33+
$this->visible();
3334
$this->notCreatable();
3435
$this->notUpdatable();
3536
$this->notDeletable();
@@ -40,7 +41,7 @@ public function attribute(string $name, string $property = null): Attribute
4041
return $this->field(Attribute::class, $name, $property);
4142
}
4243

43-
public function hasOne(string $name, string $resource = null, string $property = null): HasOne
44+
public function hasOne(string $name, $resource = null, string $property = null): HasOne
4445
{
4546
$field = $this->field(HasOne::class, $name, $property);
4647

@@ -51,7 +52,7 @@ public function hasOne(string $name, string $resource = null, string $property =
5152
return $field;
5253
}
5354

54-
public function hasMany(string $name, string $resource = null, string $property = null): HasMany
55+
public function hasMany(string $name, $resource = null, string $property = null): HasMany
5556
{
5657
$field = $this->field(HasMany::class, $name, $property);
5758

@@ -107,6 +108,34 @@ public function scopeSingle(Closure $callback)
107108
$this->singleScopes[] = $callback;
108109
}
109110

111+
public function visibleIf(Closure $condition)
112+
{
113+
$this->isVisible = $condition;
114+
115+
return $this;
116+
}
117+
118+
public function visible()
119+
{
120+
return $this->visibleIf(function () {
121+
return true;
122+
});
123+
}
124+
125+
public function notVisibleIf(Closure $condition)
126+
{
127+
return $this->visibleIf(function (...$args) use ($condition) {
128+
return ! $condition(...$args);
129+
});
130+
}
131+
132+
public function notVisible()
133+
{
134+
return $this->notVisibleIf(function () {
135+
return true;
136+
});
137+
}
138+
110139
public function creatableIf(Closure $condition)
111140
{
112141
$this->isCreatable = $condition;

src/Schema/Relationship.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ abstract class Relationship extends Field
1111
public $linkage;
1212
public $hasLinks = true;
1313
public $loadable = true;
14+
public $loader;
1415
public $included = false;
1516
public $resource;
1617

@@ -70,6 +71,13 @@ public function notLoadable()
7071
return $this;
7172
}
7273

74+
public function load(Closure $callback)
75+
{
76+
$this->loader = $callback;
77+
78+
return $this;
79+
}
80+
7381
public function included()
7482
{
7583
$this->included = true;

src/Serializer.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,17 @@ private function getRelationshipLinks(Schema\Relationship $field, string $resour
184184

185185
private function addRelated(Schema\Relationship $field, $model, array $include): JsonApi\ResourceIdentifier
186186
{
187-
$relatedResource = $this->api->getResource($field->resource);
187+
if (is_array($field->resource)) {
188+
foreach ($field->resource as $class => $resource) {
189+
if ($model instanceof $class) {
190+
break;
191+
}
192+
}
193+
} else {
194+
$resource = $field->resource;
195+
}
196+
197+
$relatedResource = $this->api->getResource($resource);
188198

189199
return $this->resourceIdentifier(
190200
$this->addToMap($relatedResource, $model, $include)

0 commit comments

Comments
 (0)