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
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,4 @@ Here is a quick look at what you can do using API search method:

- Metrics support
- Refactor the response class
- Plain text search using Laravel Scout
- Alias for includes / aggregates
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"require-dev": {
"guzzlehttp/guzzle": "^6.0|^7.0",
"orchestra/testbench": "^8.5|^9.0",
"phpunit/phpunit": "^8.0|^9.0|^10.0|^11.0"
"phpunit/phpunit": "^8.0|^9.0|^10.0|^11.0",
"laravel/scout": "^10.0|^11.0"
},
"autoload": {
"psr-4": {
Expand Down
13 changes: 13 additions & 0 deletions src/Concerns/PerformsQueries.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ public function searchQuery(\Lomkit\Rest\Http\Requests\RestRequest $request, \Il
return $query;
}

/**
* Build a "search" scout query for fetching resource.
*
* @param \Lomkit\Rest\Http\Requests\RestRequest $request
* @param \Laravel\Scout\Builder $query
*
* @return \Laravel\Scout\Builder
*/
public function searchScoutQuery(\Lomkit\Rest\Http\Requests\RestRequest $request, \Laravel\Scout\Builder $query)
{
return $query;
}

/**
* Build a query for mutating resource.
*
Expand Down
5 changes: 4 additions & 1 deletion src/Concerns/PerformsRestOperations.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Lomkit\Rest\Http\Requests\OperateRequest;
use Lomkit\Rest\Http\Requests\RestoreRequest;
use Lomkit\Rest\Http\Requests\SearchRequest;
use Lomkit\Rest\Query\ScoutBuilder;

trait PerformsRestOperations
{
Expand Down Expand Up @@ -47,7 +48,9 @@ public function search(SearchRequest $request)

$this->beforeSearch($request);

$query = app()->make(QueryBuilder::class, ['resource' => $resource, 'query' => null])
$builder = $request->has('search.text') ? ScoutBuilder::class : QueryBuilder::class;

$query = app()->make($builder, ['resource' => $resource, 'query' => null])
->search($request->input('search', []));

$responsable = $resource->paginate($query, $request);
Expand Down
13 changes: 9 additions & 4 deletions src/Concerns/Resource/Paginable.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@

namespace Lomkit\Rest\Concerns\Resource;

use Illuminate\Database\Eloquent\Builder;
use Laravel\Scout\Builder;
use Lomkit\Rest\Http\Requests\RestRequest;

trait Paginable
{
/**
* Paginate the results of a query.
*
* @param Builder $query
* @param RestRequest $request
* @param Illuminate\Database\Eloquent\Builder|\Laravel\Scout\Builder $query
* @param RestRequest $request
*
* @return mixed
*/
public function paginate(Builder $query, RestRequest $request)
public function paginate($query, RestRequest $request)
{
// In case we have a scout builder
if ($query instanceof Builder) {
return $query->paginate($request->input('search.limit', 50), 'page', $request->input('search.page', 1));
}

return $query->paginate($request->input('search.limit', 50), ['*'], 'page', $request->input('search.page', 1));
}
}
94 changes: 94 additions & 0 deletions src/Concerns/Resource/Scoutable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Lomkit\Rest\Concerns\Resource;

use Lomkit\Rest\Http\Requests\RestRequest;
use Lomkit\Rest\Instructions\Instruction;

trait Scoutable
{
/**
* The calculated scout fields if already done in this request.
*
* @var array
*/
protected array $calculatedScoutFields;

/**
* The calculated scout instructions if already done in this request.
*
* @var array
*/
protected array $calculatedScoutInstructions;

/**
* The scout fields that could be provided.
*
* @param RestRequest $request
*
* @return array
*/
public function scoutFields(RestRequest $request): array
{
return [];
}

/**
* The scout instructions that could be provided.
*
* @param RestRequest $request
*
* @return array
*/
public function scoutInstructions(RestRequest $request): array
{
return [];
}

/**
* Get the resource's scout fields.
*
* @param \Lomkit\Rest\Http\Requests\RestRequest $request
*
* @return array
*/
public function getScoutFields(\Lomkit\Rest\Http\Requests\RestRequest $request): array
{
return $this->calculatedScoutFields ?? ($this->calculatedScoutFields = $this->scoutFields($request));
}

/**
* Get the resource's scout instructions.
*
* @param \Lomkit\Rest\Http\Requests\RestRequest $request
*
* @return array
*/
public function getScoutInstructions(\Lomkit\Rest\Http\Requests\RestRequest $request): array
{
return $this->calculatedScoutInstructions ?? ($this->calculatedScoutInstructions = $this->scoutInstructions($request));
}

/**
* Retrieve a specific scout instruction by its key.
*
* @param RestRequest $request The REST request instance.
* @param string $instructionKey The key of the instruction to retrieve.
*
* @return Instruction|null The instruction instance or null if not found.
*/
public function scoutInstruction(RestRequest $request, string $instructionKey)
{
$instruction = collect($this->getScoutInstructions($request))
->first(function (Instruction $instruction) use ($instructionKey) {
return $instruction->uriKey() === $instructionKey;
});

if (!is_null($instruction)) {
$instruction
->resource($this);
}

return $instruction;
}
}
2 changes: 1 addition & 1 deletion src/Contracts/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function search(array $parameters = []);
/**
* Convert the query builder to an Eloquent query builder.
*
* @return \Illuminate\Database\Eloquent\Builder
* @return \Illuminate\Database\Eloquent\Builder|\Laravel\Scout\Builder
*/
public function toBase();
}
24 changes: 17 additions & 7 deletions src/Http/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use Lomkit\Rest\Actions\Actionable;
use Lomkit\Rest\Concerns\Authorizable;
use Lomkit\Rest\Concerns\PerformsModelOperations;
Expand All @@ -13,6 +14,7 @@
use Lomkit\Rest\Concerns\Resource\Paginable;
use Lomkit\Rest\Concerns\Resource\Relationable;
use Lomkit\Rest\Concerns\Resource\Rulable;
use Lomkit\Rest\Concerns\Resource\Scoutable;
use Lomkit\Rest\Http\Requests\RestRequest;
use Lomkit\Rest\Instructions\Instructionable;

Expand All @@ -22,6 +24,7 @@ class Resource implements \JsonSerializable
use PerformsModelOperations;
use Relationable;
use Paginable;
use Scoutable;
use Rulable;
use ConfiguresRestParameters;
use Authorizable;
Expand Down Expand Up @@ -142,6 +145,11 @@ public function cacheAuthorizationFor()
return now()->addMinutes(config('rest.authorizations.cache.default', 5));
}

public function isModelSearchable()
{
return in_array(Searchable::class, class_uses_recursive(static::$model));
}

/**
* Serialize the resource into a JSON-serializable format.
*
Expand All @@ -152,13 +160,15 @@ public function jsonSerialize(): mixed
$request = app(RestRequest::class);

return [
'actions' => collect($this->getActions($request))->map->jsonSerialize()->toArray(),
'instructions' => collect($this->getInstructions($request))->map->jsonSerialize()->toArray(),
'fields' => $this->getFields($request),
'limits' => $this->getLimits($request),
'scopes' => $this->getScopes($request),
'relations' => collect($this->getRelations($request))->map->jsonSerialize()->toArray(),
'rules' => [
'actions' => collect($this->getActions($request))->map->jsonSerialize()->toArray(),
'instructions' => collect($this->getInstructions($request))->map->jsonSerialize()->toArray(),
'scout_instructions' => collect($this->getScoutInstructions($request))->map->jsonSerialize()->toArray(),
'fields' => $this->getFields($request),
'scout_fields' => $this->getScoutFields($request),
'limits' => $this->getLimits($request),
'scopes' => $this->getScopes($request),
'relations' => collect($this->getRelations($request))->map->jsonSerialize()->toArray(),
'rules' => [
'all' => $this->rules($request),
'create' => $this->createRules($request),
'update' => $this->updateRules($request),
Expand Down
14 changes: 14 additions & 0 deletions src/Instructions/Instruction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Lomkit\Rest\Instructions;

use http\Exception\RuntimeException;
use Illuminate\Support\Str;
use Lomkit\Rest\Concerns\Fieldable;
use Lomkit\Rest\Concerns\Makeable;
Expand Down Expand Up @@ -72,4 +73,17 @@ public function handle(array $fields, \Illuminate\Database\Eloquent\Builder $que
{
// ...
}

/**
* Perform the instruction on the scout query.
*
* @param array $fields
* @param \Laravel\Scout\Builder $query
*
* @return void
*/
public function handleScout(array $fields, \Laravel\Scout\Builder $query)
{
throw new RuntimeException('Not implemented');
}
}
Loading