json-api-server/src/Adapter/EloquentBuffer.php

83 lines
2.8 KiB
PHP

<?php
/*
* This file is part of tobyz/json-api-server.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Tobyz\JsonApiServer\Adapter;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Schema\Relationship;
use function Tobyz\JsonApiServer\run_callbacks;
abstract class EloquentBuffer
{
private static $buffer = [];
public static function add(Model $model, string $relation): void
{
static::$buffer[get_class($model)][$relation][] = $model;
}
public static function load(Model $model, string $relation, Relationship $relationship, Context $context): void
{
if (! $models = static::$buffer[get_class($model)][$relation] ?? null) {
return;
}
Collection::make($models)->loadMissing([
$relation => function ($query) use ($model, $relation, $relationship, $context) {
// As we're loading the relationship, we need to scope the query
// using the scopes defined in the related API resources. We
// start by getting the resource types this relationship
// could contain.
$resourceTypes = $context->getApi()->getResourceTypes();
if ($type = $relationship->getType()) {
if (is_string($type)) {
$resourceTypes = [$resourceTypes[$type]];
} else {
$resourceTypes = array_intersect_key($resourceTypes, array_flip($type));
}
}
$constrain = [];
foreach ($resourceTypes as $resourceType) {
if ($model = $resourceType->getAdapter()->model()) {
$constrain[get_class($model)] = function ($query) use ($resourceType, $context) {
run_callbacks(
$resourceType->getSchema()->getListeners('scope'),
[$query, $context]
);
};
}
}
if ($query instanceof MorphTo) {
$query->constrain($constrain);
} else {
reset($constrain)($query->getQuery());
}
// Also apply relationship scopes to the query.
run_callbacks(
$relationship->getListeners('scope'),
[$query->getQuery(), $context]
);
}
]);
static::$buffer[get_class($model)][$relation] = [];
}
}