mirror of
https://github.com/flarum/core.git
synced 2025-10-18 18:26:07 +02:00
Eager loading extender (#2724)
* Eager loading extender * Add tests for the eager loading extender
This commit is contained in:
@@ -11,6 +11,8 @@ namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Api\JsonApiResponse;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
@@ -84,6 +86,11 @@ abstract class AbstractSerializeController implements RequestHandlerInterface
|
||||
*/
|
||||
protected static $beforeSerializationCallbacks = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $loadRelations = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -139,6 +146,47 @@ abstract class AbstractSerializeController implements RequestHandlerInterface
|
||||
*/
|
||||
abstract protected function createElement($data, SerializerInterface $serializer);
|
||||
|
||||
/**
|
||||
* Eager loads the required relationships.
|
||||
*
|
||||
* @param Collection $models
|
||||
* @param array $relations
|
||||
* @return void
|
||||
*/
|
||||
protected function loadRelations(Collection $models, array $relations): void
|
||||
{
|
||||
$addedRelations = [];
|
||||
|
||||
foreach (array_reverse(array_merge([static::class], class_parents($this))) as $class) {
|
||||
if (isset(static::$loadRelations[$class])) {
|
||||
$addedRelations = array_merge($addedRelations, static::$loadRelations[$class]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($addedRelations)) {
|
||||
usort($addedRelations, function ($a, $b) {
|
||||
return substr_count($a, '.') - substr_count($b, '.');
|
||||
});
|
||||
|
||||
foreach ($addedRelations as $relation) {
|
||||
if (strpos($relation, '.') !== false) {
|
||||
$parentRelation = Str::beforeLast($relation, '.');
|
||||
|
||||
if (! in_array($parentRelation, $relations, true)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$relations[] = $relation;
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($relations)) {
|
||||
$relations = array_unique($relations);
|
||||
$models->loadMissing($relations);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return array
|
||||
@@ -348,4 +396,13 @@ abstract class AbstractSerializeController implements RequestHandlerInterface
|
||||
|
||||
static::$beforeSerializationCallbacks[$controllerClass][] = $callback;
|
||||
}
|
||||
|
||||
public static function setLoadRelations(string $controllerClass, array $relations)
|
||||
{
|
||||
if (! isset(static::$loadRelations[$controllerClass])) {
|
||||
static::$loadRelations[$controllerClass] = [];
|
||||
}
|
||||
|
||||
static::$loadRelations[$controllerClass] = array_merge(static::$loadRelations[$controllerClass], $relations);
|
||||
}
|
||||
}
|
||||
|
@@ -121,7 +121,9 @@ class ListDiscussionsController extends AbstractListController
|
||||
}
|
||||
}
|
||||
|
||||
$results = $results->getResults()->load($include);
|
||||
$results = $results->getResults();
|
||||
|
||||
$this->loadRelations($results, $include);
|
||||
|
||||
if ($relations = array_intersect($include, ['firstPost', 'lastPost', 'mostRelevantPost'])) {
|
||||
foreach ($results as $discussion) {
|
||||
|
@@ -28,6 +28,10 @@ class ListGroupsController extends AbstractListController
|
||||
{
|
||||
$actor = $request->getAttribute('actor');
|
||||
|
||||
return Group::whereVisibleTo($actor)->get();
|
||||
$results = Group::whereVisibleTo($actor)->get();
|
||||
|
||||
$this->loadRelations($results, []);
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
@@ -76,9 +76,11 @@ class ListNotificationsController extends AbstractListController
|
||||
$include[] = 'subject';
|
||||
}
|
||||
|
||||
$notifications = $this->notifications->findByUser($actor, $limit + 1, $offset)
|
||||
->load(array_diff($include, ['subject.discussion']))
|
||||
->all();
|
||||
$notifications = $this->notifications->findByUser($actor, $limit + 1, $offset);
|
||||
|
||||
$this->loadRelations($notifications, array_diff($include, ['subject.discussion']));
|
||||
|
||||
$notifications = $notifications->all();
|
||||
|
||||
$areMoreResults = false;
|
||||
|
||||
|
@@ -104,7 +104,11 @@ class ListPostsController extends AbstractListController
|
||||
$include[] = 'user.groups';
|
||||
}
|
||||
|
||||
return $results->getResults()->load($include);
|
||||
$results = $results->getResults();
|
||||
|
||||
$this->loadRelations($results, $include);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -105,6 +105,10 @@ class ListUsersController extends AbstractListController
|
||||
$results->areMoreResults() ? null : 0
|
||||
);
|
||||
|
||||
return $results->getResults()->load($include);
|
||||
$results = $results->getResults();
|
||||
|
||||
$this->loadRelations($results, $include);
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user