Skip to content

Commit

Permalink
[5.x] Models Fieldtype Filter (#313)
Browse files Browse the repository at this point in the history
* Models Fieldtype Filter

* Refactor to work when querying entries
  • Loading branch information
duncanmcclean authored Aug 7, 2023
1 parent a9477f7 commit e2ee228
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Fieldtypes/BaseFieldtype.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace DoubleThreeDigital\Runway\Fieldtypes;

use DoubleThreeDigital\Runway\Actions\DeleteModel;
use DoubleThreeDigital\Runway\Query\Scopes\Filters\Fields\Models;
use DoubleThreeDigital\Runway\Runway;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -346,4 +347,9 @@ protected function makeTitle($record, $resource): string

return Parse::template($titleFormat, $record);
}

public function filter()
{
return new Models($this);
}
}
13 changes: 13 additions & 0 deletions src/Query/Scopes/Filters/Fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,17 @@ protected function getFields()

return $resource->blueprint()->fields()->all()->filter->isFilterable();
}

public function apply($query, $values)
{
$this->getFields()
->filter(function ($field, $handle) use ($values) {
return isset($values[$handle]);
})
->each(function ($field, $handle) use ($query, $values) {
$filter = $field->fieldtype()->filter();
$values = $filter->fields()->addValues($values[$handle])->process()->values();
$filter->apply($query, $handle, $values);
});
}
}
91 changes: 91 additions & 0 deletions src/Query/Scopes/Filters/Fields/Models.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace DoubleThreeDigital\Runway\Query\Scopes\Filters\Fields;

use DoubleThreeDigital\Runway\Runway;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Statamic\Query\Scopes\Filters\Fields\FieldtypeFilter;
use Statamic\Support\Arr;
use Statamic\Support\Str;

class Models extends FieldtypeFilter
{
public function fieldItems()
{
$resource = Runway::findResource($this->fieldtype->config('resource'));

return [
'field' => [
'type' => 'select',
'options' => [
$resource->primaryKey() => __(Str::upper($resource->primaryKey())),
$resource->titleField() => $resource->blueprint()->field($resource->titleField())->display(),
],
'default' => $resource->titleField(),
],
'operator' => [
'type' => 'select',
'options' => [
'like' => __('Contains'),
'not like' => __('Doesn\'t contain'),
'=' => __('Is'),
'!=' => __('Isn\'t'),
],
'default' => 'like',
],
'value' => [
'type' => 'text',
'placeholder' => __('Value'),
'if' => [
'operator' => 'not empty',
],
],
];
}

public function apply($query, $handle, $values)
{
$field = $values['field'];
$operator = $values['operator'];
$value = $values['value'];

if ($operator === 'like' || $operator === 'not like') {
$value = Str::ensureLeft($value, '%');
$value = Str::ensureRight($value, '%');
}

$relatedResource = Runway::findResource($this->fieldtype->config('resource'));

$ids = $relatedResource->model()->query()
->where($field, $operator, $value)
->select($relatedResource->primaryKey())
->get()
->pluck($relatedResource->primaryKey())
->toArray();

// When we're dealing with an Eloquent query builder, we can take advantage of `whereHas` to filter.
// Otherwise, we'll just filter the IDs directly.
if (method_exists($query, 'getModel')) {
// This is the resource of the Eloquent model that the filter is querying.
$queryingResource = Runway::findResourceByModel($query->getModel());

$query->whereHas($queryingResource->eagerLoadingRelations()->get($this->fieldtype->field()->handle()), function (Builder $query) use ($relatedResource, $ids) {
$query->whereIn($relatedResource->primaryKey(), $ids);
});
} else {
$query->whereIn($this->fieldtype->field()->handle(), $ids);
}
}

public function badge($values)
{
$field = $this->fieldtype->field()->display();
$selectedField = $values['field'];
$operator = $values['operator'];
$translatedField = Arr::get($this->fieldItems(), "field.options.{$selectedField}");
$translatedOperator = Arr::get($this->fieldItems(), "operator.options.{$operator}");
$value = $values['value'];

return $field.' '.$translatedField.' '.strtolower($translatedOperator).' '.$value;
}
}

0 comments on commit e2ee228

Please sign in to comment.