Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgergo committed May 29, 2024
1 parent 459878c commit 1660734
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
50 changes: 46 additions & 4 deletions src/Fields/Relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ abstract class Relation extends Field implements Form
*/
protected ?Closure $queryResolver = null;

/**
* Determine if the field is computed.
*/
protected ?Closure $aggregateResolver = null;

/**
* Determine whether the relation values are aggregated.
*/
protected bool $aggregated = false;

/**
* The option group resolver.
*/
Expand Down Expand Up @@ -209,10 +219,6 @@ public function asSubResource(bool $value = true): static
{
$this->asSubResource = $value;

$this->format(function (Request $request, Model $model): ?int {
return $model->getAttribute(sprintf('%s_count', $this->getRelationName()));
});

return $this;
}

Expand Down Expand Up @@ -335,6 +341,10 @@ public function resolveDisplay(Model $related): ?string
*/
public function getValue(Model $model): mixed
{
if ($this->aggregated) {
return parent::getValue($model);
}

$name = $this->getRelationName();

if ($this->relation instanceof Closure && ! $model->relationLoaded($name)) {
Expand All @@ -353,6 +363,10 @@ public function resolveFormat(Request $request, Model $model): ?string
$this->formatResolver = function (Request $request, Model $model): mixed {
$default = $this->getValue($model);

if ($this->aggregated) {
return $default;
}

return Collection::wrap($default)->map(function (Model $related) use ($model, $request): mixed {
return $this->formatRelated($request, $model, $related);
})->filter()->join(', ');
Expand Down Expand Up @@ -465,6 +479,34 @@ public function resolveRelatableQuery(Request $request, Model $model): Builder
});
}

/**
* Aggregate relation values.
*/
public function aggregate(string $fn = 'count', string $column = '*'): static
{
$this->aggregateResolver = function (Request $request, Builder $query) use ($fn, $column): Builder {
$this->setModelAttribute(sprintf('%s_%s', $this->getRelationName(), $fn));

$this->aggregated = true;

return $query->withAggregate($this->getRelationName(), $column, $fn);
};

return $this;
}

/**
* Resolve the aggregate query.
*/
public function resolveAggregate(Request $request, Builder $query): Builder
{
if (! is_null($this->aggregateResolver)) {
$query = call_user_func_array($this->aggregateResolver, [$request, $query]);
}

return $query;
}

/**
* Set the group resolver attribute.
*/
Expand Down
20 changes: 19 additions & 1 deletion src/Resources/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

use Cone\Root\Actions\Action;
use Cone\Root\Exceptions\SaveFormDataException;
use Cone\Root\Fields\BelongsToMany;
use Cone\Root\Fields\Events;
use Cone\Root\Fields\Field;
use Cone\Root\Fields\Fields;
use Cone\Root\Fields\HasMany;
use Cone\Root\Fields\Meta;
use Cone\Root\Fields\MorphMany;
use Cone\Root\Fields\Relation;
use Cone\Root\Filters\Filter;
use Cone\Root\Filters\RenderableFilter;
Expand Down Expand Up @@ -403,6 +407,21 @@ public function getSortKey(): string
public function paginate(Request $request): LengthAwarePaginator
{
return $this->resolveFilteredQuery($request)
->tap(function (Builder $query) use ($request): void {
$this->resolveFields($request)
->authorized($request, $query->getModel())
->visible('index')
->filter(fn (Field $field): bool => $field instanceof Relation)
->each(static function (Relation $relation) use ($query, $request): void {
if ($relation instanceof BelongsToMany || $relation instanceof HasMany || $relation instanceof MorphMany) {
$relation->resolveAggregate($request, $query);
} elseif ($relation instanceof Meta) {
$query->with('metaData');
} else {
$query->with($relation->getRelationName());
}
});
})
->latest()
->paginate($request->input($this->getPerPageKey()))
->withQueryString()
Expand All @@ -422,7 +441,6 @@ public function mapModel(Request $request, Model $model): array
'model' => $model,
'abilities' => $this->mapModelAbilities($request, $model),
'fields' => $this->resolveFields($request)
->subResource(false)
->authorized($request, $model)
->visible('index')
->mapToDisplay($request, $model),
Expand Down

0 comments on commit 1660734

Please sign in to comment.