wip
This commit is contained in:
parent
adc388e149
commit
0d43544adc
|
|
@ -57,9 +57,11 @@ trait IncludesData
|
||||||
throw new BadRequestException("Invalid include [{$path}{$name}]", 'include');
|
throw new BadRequestException("Invalid include [{$path}{$name}]", 'include');
|
||||||
}
|
}
|
||||||
|
|
||||||
$relatedResource = $this->api->getResource($schema->fields[$name]->resource);
|
if (is_string($schema->fields[$name]->resource)) {
|
||||||
|
$relatedResource = $this->api->getResource($schema->fields[$name]->resource);
|
||||||
|
|
||||||
$this->validateInclude($relatedResource, $nested, $name.'.');
|
$this->validateInclude($relatedResource, $nested, $name.'.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,17 +77,19 @@ trait IncludesData
|
||||||
$trails[] = [$relationship];
|
$trails[] = [$relationship];
|
||||||
}
|
}
|
||||||
|
|
||||||
$relatedResource = $this->api->getResource($relationship->resource);
|
if (is_string($schema->fields[$name]->resource)) {
|
||||||
|
$relatedResource = $this->api->getResource($relationship->resource);
|
||||||
|
|
||||||
$trails = array_merge(
|
$trails = array_merge(
|
||||||
$trails,
|
$trails,
|
||||||
array_map(
|
array_map(
|
||||||
function ($trail) use ($relationship) {
|
function ($trail) use ($relationship) {
|
||||||
return array_merge([$relationship], $trail);
|
return array_merge([$relationship], $trail);
|
||||||
},
|
},
|
||||||
$this->buildRelationshipTrails($relatedResource, $nested)
|
$this->buildRelationshipTrails($relatedResource, $nested)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $trails;
|
return $trails;
|
||||||
|
|
@ -101,13 +105,21 @@ trait IncludesData
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$adapter->loadIds($models, $field);
|
if ($field->loader) {
|
||||||
|
($field->loader)($models, true);
|
||||||
|
} else {
|
||||||
|
$adapter->loadIds($models, $field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$trails = $this->buildRelationshipTrails($this->resource, $include);
|
$trails = $this->buildRelationshipTrails($this->resource, $include);
|
||||||
|
|
||||||
foreach ($trails as $relationships) {
|
foreach ($trails as $relationships) {
|
||||||
$adapter->load($models, $relationships);
|
if ($loader = end($relationships)->loader) {
|
||||||
|
($loader)($models, false);
|
||||||
|
} else {
|
||||||
|
$adapter->load($models, $relationships);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Tobscure\JsonApiServer\Api;
|
use Tobscure\JsonApiServer\Api;
|
||||||
use Tobscure\JsonApiServer\Exception\BadRequestException;
|
use Tobscure\JsonApiServer\Exception\BadRequestException;
|
||||||
|
use Tobscure\JsonApiServer\Exception\ForbiddenException;
|
||||||
use Tobscure\JsonApiServer\JsonApiResponse;
|
use Tobscure\JsonApiServer\JsonApiResponse;
|
||||||
use Tobscure\JsonApiServer\ResourceType;
|
use Tobscure\JsonApiServer\ResourceType;
|
||||||
use Tobscure\JsonApiServer\Schema;
|
use Tobscure\JsonApiServer\Schema;
|
||||||
|
|
@ -37,6 +38,10 @@ class Index implements RequestHandlerInterface
|
||||||
$adapter = $this->resource->getAdapter();
|
$adapter = $this->resource->getAdapter();
|
||||||
$schema = $this->resource->getSchema();
|
$schema = $this->resource->getSchema();
|
||||||
|
|
||||||
|
if (! ($schema->isVisible)($request)) {
|
||||||
|
throw new ForbiddenException('You cannot view this resource');
|
||||||
|
}
|
||||||
|
|
||||||
$query = $adapter->query();
|
$query = $adapter->query();
|
||||||
|
|
||||||
foreach ($schema->scopes as $scope) {
|
foreach ($schema->scopes as $scope) {
|
||||||
|
|
@ -219,7 +224,7 @@ class Index implements RequestHandlerInterface
|
||||||
$attribute = $schema->fields[$name];
|
$attribute = $schema->fields[$name];
|
||||||
|
|
||||||
if ($attribute->sorter) {
|
if ($attribute->sorter) {
|
||||||
($attribute->sorter)($query, $direction, $request);
|
($attribute->sorter)($request, $query, $direction);
|
||||||
} else {
|
} else {
|
||||||
$adapter->sortByAttribute($query, $attribute, $direction);
|
$adapter->sortByAttribute($query, $attribute, $direction);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Tobscure\JsonApiServer\Api;
|
use Tobscure\JsonApiServer\Api;
|
||||||
|
use Tobscure\JsonApiServer\Exception\ForbiddenException;
|
||||||
use Tobscure\JsonApiServer\JsonApiResponse;
|
use Tobscure\JsonApiServer\JsonApiResponse;
|
||||||
use Tobscure\JsonApiServer\ResourceType;
|
use Tobscure\JsonApiServer\ResourceType;
|
||||||
use Tobscure\JsonApiServer\Serializer;
|
use Tobscure\JsonApiServer\Serializer;
|
||||||
|
|
@ -28,6 +29,12 @@ class Show implements RequestHandlerInterface
|
||||||
|
|
||||||
public function handle(Request $request): Response
|
public function handle(Request $request): Response
|
||||||
{
|
{
|
||||||
|
$schema = $this->resource->getSchema();
|
||||||
|
|
||||||
|
if (! ($schema->isVisible)($request)) {
|
||||||
|
throw new ForbiddenException('You cannot view this resource');
|
||||||
|
}
|
||||||
|
|
||||||
$include = $this->getInclude($request);
|
$include = $this->getInclude($request);
|
||||||
|
|
||||||
$this->loadRelationships([$this->model], $include, $request);
|
$this->loadRelationships([$this->model], $include, $request);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ class Builder
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
$this->visible();
|
||||||
$this->notCreatable();
|
$this->notCreatable();
|
||||||
$this->notUpdatable();
|
$this->notUpdatable();
|
||||||
$this->notDeletable();
|
$this->notDeletable();
|
||||||
|
|
@ -40,7 +41,7 @@ class Builder
|
||||||
return $this->field(Attribute::class, $name, $property);
|
return $this->field(Attribute::class, $name, $property);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasOne(string $name, string $resource = null, string $property = null): HasOne
|
public function hasOne(string $name, $resource = null, string $property = null): HasOne
|
||||||
{
|
{
|
||||||
$field = $this->field(HasOne::class, $name, $property);
|
$field = $this->field(HasOne::class, $name, $property);
|
||||||
|
|
||||||
|
|
@ -51,7 +52,7 @@ class Builder
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasMany(string $name, string $resource = null, string $property = null): HasMany
|
public function hasMany(string $name, $resource = null, string $property = null): HasMany
|
||||||
{
|
{
|
||||||
$field = $this->field(HasMany::class, $name, $property);
|
$field = $this->field(HasMany::class, $name, $property);
|
||||||
|
|
||||||
|
|
@ -107,6 +108,34 @@ class Builder
|
||||||
$this->singleScopes[] = $callback;
|
$this->singleScopes[] = $callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function visibleIf(Closure $condition)
|
||||||
|
{
|
||||||
|
$this->isVisible = $condition;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function visible()
|
||||||
|
{
|
||||||
|
return $this->visibleIf(function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notVisibleIf(Closure $condition)
|
||||||
|
{
|
||||||
|
return $this->visibleIf(function (...$args) use ($condition) {
|
||||||
|
return ! $condition(...$args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notVisible()
|
||||||
|
{
|
||||||
|
return $this->notVisibleIf(function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function creatableIf(Closure $condition)
|
public function creatableIf(Closure $condition)
|
||||||
{
|
{
|
||||||
$this->isCreatable = $condition;
|
$this->isCreatable = $condition;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ abstract class Relationship extends Field
|
||||||
public $linkage;
|
public $linkage;
|
||||||
public $hasLinks = true;
|
public $hasLinks = true;
|
||||||
public $loadable = true;
|
public $loadable = true;
|
||||||
|
public $loader;
|
||||||
public $included = false;
|
public $included = false;
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
|
|
@ -70,6 +71,13 @@ abstract class Relationship extends Field
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function load(Closure $callback)
|
||||||
|
{
|
||||||
|
$this->loader = $callback;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function included()
|
public function included()
|
||||||
{
|
{
|
||||||
$this->included = true;
|
$this->included = true;
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,17 @@ class Serializer
|
||||||
|
|
||||||
private function addRelated(Schema\Relationship $field, $model, array $include): JsonApi\ResourceIdentifier
|
private function addRelated(Schema\Relationship $field, $model, array $include): JsonApi\ResourceIdentifier
|
||||||
{
|
{
|
||||||
$relatedResource = $this->api->getResource($field->resource);
|
if (is_array($field->resource)) {
|
||||||
|
foreach ($field->resource as $class => $resource) {
|
||||||
|
if ($model instanceof $class) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$resource = $field->resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
$relatedResource = $this->api->getResource($resource);
|
||||||
|
|
||||||
return $this->resourceIdentifier(
|
return $this->resourceIdentifier(
|
||||||
$this->addToMap($relatedResource, $model, $include)
|
$this->addToMap($relatedResource, $model, $include)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue