Skip to content

Commit

Permalink
[7.x] Add runway:count tag (#583)
Browse files Browse the repository at this point in the history
Co-authored-by: Joey van Zwieten <joey.van.zwieten@ihomer.nl>
Co-authored-by: Duncan McClean <duncan@duncanmcclean.com>
  • Loading branch information
3 people authored Aug 14, 2024
1 parent 76fad0d commit 9b979f7
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
14 changes: 14 additions & 0 deletions docs/templating.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ As [with the collection tag](https://statamic.dev/tags/collection#scope), you ma
{{ /runway:post }}
```

## Count Tag

When you just want to know how many results you have, you can use the `{{ runway:count }}` tag.

```antlers
{{ runway:count from="posts" }}
```

You can use the `where` parameter to filter the results:

```antlers
{{ runway:count from="posts" where="author_name:duncan" }}
```

## Publish State

By default, when you're using Runway's [Publish States](/resources#publish-states) feature, only published models are included. Models can be queried against `published` or `draft` status with conditions on `status` like this:
Expand Down
60 changes: 43 additions & 17 deletions src/Tags/RunwayTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace StatamicRadPack\Runway\Tags;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Statamic\Extensions\Pagination\LengthAwarePaginator;
Expand All @@ -14,20 +15,40 @@
class RunwayTag extends Tags
{
protected static $handle = 'runway';
protected $resource;

public function wildcard($resourceHandle = null): array
protected function parseResource(?string $resourceHandle = null): Resource
{
$from = $resourceHandle ?? $this->params->get(['from', 'in', 'resource']);

try {
$resource = Runway::findResource(
$this->params->has('resource') ? Str::studly($this->params->get('resource')) : Str::studly($resourceHandle)
);
return Runway::findResource(Str::studly($from));
} catch (ResourceNotFound) {
$resource = Runway::findResource(
$this->params->has('resource') ? Str::lower($this->params->get('resource')) : Str::lower($resourceHandle)
);
try {
return Runway::findResource(Str::lower($from));
} catch (ResourceNotFound) {
return Runway::findResource($from);
}
}
}

public function wildcard(?string $resourceHandle = null): array
{
$this->resource = $this->parseResource($resourceHandle);

return $this->results($this->query());
}

$query = $resource->model()->query()
public function count(): int
{
$this->resource = $this->parseResource();

return $this->query()->count();
}

protected function query(): Builder
{
$query = $this->resource->model()->query()
->when(
$this->params->get('status'),
fn ($query, $status) => $query->whereStatus($status),
Expand All @@ -36,7 +57,7 @@ public function wildcard($resourceHandle = null): array
->when(
$this->params->get('with'),
fn ($query) => $query->with(explode('|', (string) $this->params->get('with'))),
fn ($query) => $query->with($resource->eagerLoadingRelationships())
fn ($query) => $query->with($this->resource->eagerLoadingRelationships())
);

if ($select = $this->params->get('select')) {
Expand Down Expand Up @@ -70,12 +91,12 @@ public function wildcard($resourceHandle = null): array
$key = explode(':', (string) $where)[0];
$value = explode(':', (string) $where)[1];

if ($resource->eloquentRelationships()->has($key)) {
if ($this->resource->eloquentRelationships()->has($key)) {
// eloquentRelationships() returns a Collection of keys/values, the keys are the field names
// & the values are the Eloquent relationship names. We need to get the relationship name
// for the whereHas query.
$relationshipName = $resource->eloquentRelationships()->get($key);
$relationshipResource = Runway::findResource($resource->blueprint()->field($key)->config()['resource']);
$relationshipName = $this->resource->eloquentRelationships()->get($key);
$relationshipResource = Runway::findResource($this->resource->blueprint()->field($key)->config()['resource']);

$query->whereHas($relationshipName, function ($query) use ($value, $relationshipResource) {
$query->whereIn($relationshipResource->databaseTable().'.'.$relationshipResource->primaryKey(), Arr::wrap($value));
Expand All @@ -97,6 +118,11 @@ public function wildcard($resourceHandle = null): array
$query->orderBy($sortColumn, $sortDirection);
}

return $query;
}

protected function results($query)
{
if ($this->params->get('paginate') || $this->params->get('limit')) {
$paginator = $query->paginate($this->params->get('limit'));

Expand All @@ -114,21 +140,21 @@ public function wildcard($resourceHandle = null): array
}

if (! $this->params->has('as')) {
return $this->augmentModels($results, $resource);
return $this->augmentModels($results);
}

return [
$this->params->get('as') => $this->augmentModels($results, $resource),
$this->params->get('as') => $this->augmentModels($results),
'paginate' => isset($paginator) ? $this->getPaginationData($paginator) : null,
'no_results' => collect($results)->isEmpty(),
];
}

protected function augmentModels($query, Resource $resource): array
protected function augmentModels($query): array
{
return collect($query)
->map(function ($model, $key) use ($resource) {
return Blink::once("Runway::Tag::AugmentModels::{$resource->handle()}::{$model->{$resource->primaryKey()}}", function () use ($model) {
->map(function ($model, $key) {
return Blink::once("Runway::Tag::AugmentModels::{$this->resource->handle()}::{$model->{$this->resource->primaryKey()}}", function () use ($model) {
return $model->toAugmentedArray();
});
})
Expand Down
16 changes: 16 additions & 0 deletions tests/Tags/RunwayTagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,20 @@ public function it_fires_an_augmented_hook()

$this->assertEquals(1, $augmentedCount);
}

#[Test]
public function it_can_count_models()
{
Post::factory()->count(3)->create();
Post::factory()->count(2)->create(['title' => 'Foo Bar']);

$count = $this->tag
->setParameters([
'from' => 'post',
'where' => 'title:Foo Bar',
])
->count();

$this->assertEquals(2, $count);
}
}

0 comments on commit 9b979f7

Please sign in to comment.