Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions docs/relationships.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ Written by {{ author:first_name }} {{ author:last_name }} ({{ author:location }}

### Options

| **Option** | **Description** |
|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). |
| `resource` | Specify the Runway Resource to be used for this field. |
| `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. |
| `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. |
| `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. |
| `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. |
| **Option** | **Description** |
|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). |
| `resource` | Specify the Runway Resource to be used for this field. |
| `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. |
| `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. |
| `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. |
| `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. |
| `query-scopes` | Allows you to specify a [query scope](https://statamic.dev/extending/query-scopes-and-filters#scopes) which should be applied when retrieving selectable models. You should specify the query scope's handle, which is usually the name of the class in snake case. For example: `MyAwesomeScope` would be `my_awesome_scope`. |

## Has Many

Expand Down Expand Up @@ -101,16 +102,18 @@ Loop through the models and do anything you want with the data.

### Options

| **Option** | **Description** |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). |
| `resource` | Specify the Runway Resource to be used for this field. |
| `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. |
| `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. |
| `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. |
| `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. |
| `reorderable` | Determines whether the models can be reordered. Defaults to `false`. |
| `order_column` | When reordering is enabled, this determines which column should be used for storing the sort order. When the relationship uses a pivot table, the order column must exist on the pivot table. |
| **Option** | **Description** |
|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). |
| `resource` | Specify the Runway Resource to be used for this field. |
| `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. |
| `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. |
| `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. |
| `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. |
| `reorderable` | Determines whether the models can be reordered. Defaults to `false`. |
| `order_column` | When reordering is enabled, this determines which column should be used for storing the sort order. When the relationship uses a pivot table, the order column must exist on the pivot table. |
| `query-scopes` | Allows you to specify a [query scope](https://statamic.dev/extending/query-scopes-and-filters#scopes) which should be applied when retrieving selectable models. You should specify the query scope's handle, which is usually the name of the class in snake case. For example: `MyAwesomeScope` would be `my_awesome_scope`. |


## Belongs To Many

Expand Down
34 changes: 30 additions & 4 deletions src/Fieldtypes/BaseFieldtype.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use Illuminate\Support\Facades\Schema;
use Statamic\CP\Column;
use Statamic\Facades\Blink;
use Statamic\Facades\Scope;
use Statamic\Fieldtypes\Relationship;
use Statamic\Query\Builder as BaseStatamicBuilder;
use Statamic\Query\Scopes\Filter;
use Statamic\Search\Result;
use StatamicRadPack\Runway\Http\Resources\CP\FieldtypeModel;
use StatamicRadPack\Runway\Http\Resources\CP\FieldtypeModels;
Expand Down Expand Up @@ -97,6 +99,16 @@ protected function configFieldItems(): array
'type' => 'text',
'width' => 50,
],
'query_scopes' => [
'display' => __('Query Scopes'),
'instructions' => __('Select which query fields should be applied when retrieving selectable models.'),
'type' => 'taggable',
'options' => Scope::all()
->reject(fn ($scope) => $scope instanceof Filter)
->map->handle()
->values()
->all(),
],
];
}

Expand Down Expand Up @@ -150,11 +162,9 @@ public function process($data)

public function getIndexItems($request)
{
$resource = Runway::findResource($this->config('resource'));
$resource = $this->resource();

$query = $resource->newEloquentQuery();

$query->when($query->hasNamedScope('runwayListing'), fn ($query) => $query->runwayListing());
$query = $this->getIndexQuery($request);

$searchQuery = $request->search ?? false;

Expand All @@ -181,6 +191,17 @@ public function getIndexItems($request)
return $paginate ? $results->setCollection($items) : $items;
}

protected function getIndexQuery($request)
{
$query = $this->resource()->newEloquentQuery();

$query->when($query->hasNamedScope('runwayListing'), fn ($query) => $query->runwayListing());

$this->applyIndexQueryScopes($query, $request->all());

return $query;
}

public function getResourceCollection($request, $items)
{
$resource = Runway::findResource($this->config('resource'));
Expand Down Expand Up @@ -361,4 +382,9 @@ private function applySearch(Resource $resource, Builder $query, string $searchQ

return $query->runwaySearch($searchQuery);
}

private function resource(): Resource
{
return Runway::findResource($this->config('resource'));
}
}
30 changes: 30 additions & 0 deletions tests/Fieldtypes/BelongsToFieldtypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use StatamicRadPack\Runway\Fieldtypes\BelongsToFieldtype;
use StatamicRadPack\Runway\Runway;
use StatamicRadPack\Runway\Tests\Fixtures\Models\Author;
use StatamicRadPack\Runway\Tests\Fixtures\Scopes\TheHoff;
use StatamicRadPack\Runway\Tests\TestCase;

class BelongsToFieldtypeTest extends TestCase
Expand Down Expand Up @@ -124,6 +125,35 @@ public function can_get_index_items_in_order_from_runway_listing_scope_when_user
$this->assertEquals($getIndexItems->all()[2]->name, 'Scully');
}

#[Test]
public function can_get_index_items_with_query_scopes()
{
TheHoff::register();

Author::factory()->count(10)->create();
$hasselhoff = Author::factory()->create(['name' => 'David Hasselhoff']);

$fieldtype = tap(new BelongsToFieldtype)
->setField(new Field('author', [
'max_items' => 1,
'mode' => 'stack',
'resource' => 'author',
'display' => 'Author',
'type' => 'belongs_to',
'query_scopes' => ['the_hoff'],
]));

$getIndexItems = $fieldtype->getIndexItems(
new FilteredRequest(['paginate' => true])
);

$this->assertIsObject($getIndexItems);
$this->assertTrue($getIndexItems instanceof Paginator);
$this->assertEquals($getIndexItems->count(), 1);

$this->assertEquals($getIndexItems->first()['id'], $hasselhoff->id);
}

#[Test]
public function can_get_index_items_and_search()
{
Expand Down
20 changes: 20 additions & 0 deletions tests/__fixtures__/app/Scopes/TheHoff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace StatamicRadPack\Runway\Tests\Fixtures\Scopes;

use Statamic\Query\Scopes\Scope;

class TheHoff extends Scope
{
/**
* Apply the scope.
*
* @param \Statamic\Query\Builder $query
* @param array $values
* @return void
*/
public function apply($query, $values)
{
$query->where('name', 'like', '%Hasselhoff%');
}
}