Skip to content

Commit eaf0697

Browse files
authored
Refactoring & clean up tests & Global search. (#172)
* Remove apple repository * Apply fixes from StyleCI (#171)
1 parent 591c452 commit eaf0697

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+572
-721
lines changed

routes/api.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
<?php
22

3+
use Binaryk\LaravelRestify\Http\Controllers\GlobalSearchController;
34
use Binaryk\LaravelRestify\Http\Controllers\RepositoryDestroyController;
45
use Binaryk\LaravelRestify\Http\Controllers\RepositoryIndexController;
56
use Binaryk\LaravelRestify\Http\Controllers\RepositoryShowController;
67
use Binaryk\LaravelRestify\Http\Controllers\RepositoryStoreController;
78
use Binaryk\LaravelRestify\Http\Controllers\RepositoryUpdateController;
9+
use Illuminate\Support\Facades\Route;
810

11+
// Global Search...
12+
Route::get('/search', '\\'.GlobalSearchController::class);
13+
14+
// API CRUD
915
Route::get('/{repository}', '\\'.RepositoryIndexController::class);
1016
Route::post('/{repository}', '\\'.RepositoryStoreController::class);
1117
Route::get('/{repository}/{repositoryId}', '\\'.RepositoryShowController::class);

src/Fields/Field.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ protected function resolveDefaultValue(RestifyRequest $request)
435435
* @param callable $resolveCallback
436436
* @return $this
437437
*/
438-
public function resolveUsing(callable $resolveCallback)
438+
public function resolveCallback(callable $resolveCallback)
439439
{
440440
$this->resolveCallback = $resolveCallback;
441441

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Http\Controllers;
4+
5+
use Binaryk\LaravelRestify\Http\Requests\GlobalSearchRequest;
6+
use Binaryk\LaravelRestify\Restify;
7+
use Binaryk\LaravelRestify\Services\Search\GlobalSearch;
8+
9+
class GlobalSearchController extends RepositoryController
10+
{
11+
public function __invoke(GlobalSearchRequest $request)
12+
{
13+
$results = (new GlobalSearch(
14+
$request, Restify::globallySearchableRepositories($request)
15+
))->get();
16+
17+
return $this->response()->data($results);
18+
}
19+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Http\Requests;
4+
5+
class GlobalSearchRequest extends RestifyRequest
6+
{
7+
}

src/Repositories/Repository.php

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,27 @@ abstract class Repository implements RestifySearchable, JsonSerializable
7676
*/
7777
public static $sort;
7878

79+
/**
80+
* Attribute that should be used for displaying single model.
81+
*
82+
* @var string
83+
*/
84+
public static $title = 'id';
85+
86+
/**
87+
* Indicates if the repository should be globally searchable.
88+
*
89+
* @var bool
90+
*/
91+
public static $globallySearchable = true;
92+
93+
/**
94+
* The number of results to display in the global search.
95+
*
96+
* @var int
97+
*/
98+
public static $globalSearchResults = 5;
99+
79100
/**
80101
* Get the underlying model instance for the resource.
81102
*
@@ -106,6 +127,42 @@ public static function uriKey()
106127
return Str::plural($kebabWithoutRepository);
107128
}
108129

130+
/**
131+
* Get the label for the resource.
132+
*
133+
* @return string
134+
*/
135+
public static function label()
136+
{
137+
if (property_exists(static::class, 'label') && is_string(static::$label)) {
138+
return static::$label;
139+
}
140+
141+
$title = Str::title(Str::replaceLast('Repository', '', class_basename(get_called_class())));
142+
143+
return Str::plural($title);
144+
}
145+
146+
/**
147+
* Get the value that should be displayed to represent the repository.
148+
*
149+
* @return string
150+
*/
151+
public function title()
152+
{
153+
return $this->{static::$title};
154+
}
155+
156+
/**
157+
* Get the search result subtitle for the repository.
158+
*
159+
* @return string|null
160+
*/
161+
public function subtitle()
162+
{
163+
//
164+
}
165+
109166
/**
110167
* Get a fresh instance of the model represented by the resource.
111168
*
@@ -435,10 +492,8 @@ public function index(RestifyRequest $request)
435492
* Apply all of the query: search, match, sort, related.
436493
* @var AbstractPaginator $paginator
437494
*/
438-
$paginator = RepositorySearchService::instance()->search($request, $this)->tap(function ($query) use ($request) {
439-
// Call the local definition of the query
440-
static::indexQuery($request, $query);
441-
})->paginate($request->perPage ?? (static::$defaultPerPage ?? RestifySearchable::DEFAULT_PER_PAGE));
495+
$paginator = RepositorySearchService::instance()->search($request, $this)
496+
->paginate($request->perPage ?? (static::$defaultPerPage ?? RestifySearchable::DEFAULT_PER_PAGE));
442497

443498
$items = $paginator->getCollection()->map(function ($value) {
444499
return static::resolveWith($value);

src/Restify.php

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Binaryk\LaravelRestify\Events\RestifyBeforeEach;
66
use Binaryk\LaravelRestify\Events\RestifyStarting;
7+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
78
use Binaryk\LaravelRestify\Repositories\Repository;
89
use Binaryk\LaravelRestify\Traits\AuthorizesRequests;
910
use Illuminate\Database\Eloquent\Model;
@@ -15,6 +16,7 @@
1516
class Restify
1617
{
1718
use AuthorizesRequests;
19+
1820
/**
1921
* The registered repository names.
2022
*
@@ -39,7 +41,7 @@ class Restify
3941
/**
4042
* Get the repository class name for a given key.
4143
*
42-
* @param string $key
44+
* @param string $key
4345
* @return string
4446
*/
4547
public static function repositoryForKey($key)
@@ -52,7 +54,7 @@ public static function repositoryForKey($key)
5254
/**
5355
* Get the repository class name for a given key.
5456
*
55-
* @param string $model
57+
* @param string $model
5658
* @return string
5759
*/
5860
public static function repositoryForModel($model)
@@ -69,7 +71,7 @@ public static function repositoryForModel($model)
6971
/**
7072
* Register the given repositories.
7173
*
72-
* @param array $repositories
74+
* @param array $repositories
7375
* @return static
7476
*/
7577
public static function repositories(array $repositories)
@@ -84,7 +86,7 @@ public static function repositories(array $repositories)
8486
/**
8587
* Register all of the repository classes in the given directory.
8688
*
87-
* @param string $directory
89+
* @param string $directory
8890
* @return void
8991
* @throws \ReflectionException
9092
*/
@@ -114,7 +116,7 @@ public static function repositoriesFrom($directory)
114116
/**
115117
* Get the URI path prefix utilized by Restify.
116118
*
117-
* @param null $plus
119+
* @param null $plus
118120
* @return string
119121
*/
120122
public static function path($plus = null)
@@ -131,7 +133,7 @@ public static function path($plus = null)
131133
*
132134
* This listener is added in the RestifyApplicationServiceProvider
133135
*
134-
* @param \Closure|string $callback
136+
* @param \Closure|string $callback
135137
* @return void
136138
*/
137139
public static function starting($callback)
@@ -140,7 +142,7 @@ public static function starting($callback)
140142
}
141143

142144
/**
143-
* @param \Closure|string $callback
145+
* @param \Closure|string $callback
144146
*/
145147
public static function beforeEach($callback)
146148
{
@@ -150,10 +152,26 @@ public static function beforeEach($callback)
150152
/**
151153
* Set the callback used for intercepting any request exception.
152154
*
153-
* @param \Closure|string $callback
155+
* @param \Closure|string $callback
154156
*/
155157
public static function exceptionHandler($callback)
156158
{
157159
static::$renderCallback = $callback;
158160
}
161+
162+
public static function globallySearchableRepositories(RestifyRequest $request)
163+
{
164+
return collect(static::$repositories)
165+
->filter(fn ($repository) => $repository::authorizedToUseRepository($request))
166+
->filter(fn ($repository) => $repository::$globallySearchable)
167+
->sortBy(static::sortResourcesWith())
168+
->all();
169+
}
170+
171+
public static function sortResourcesWith()
172+
{
173+
return function ($resource) {
174+
return $resource::label();
175+
};
176+
}
159177
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Services\Search;
4+
5+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
6+
use Illuminate\Support\Collection;
7+
8+
class GlobalSearch
9+
{
10+
/**
11+
* The request instance.
12+
*
13+
* @var RestifyRequest
14+
*/
15+
public $request;
16+
17+
/**
18+
* The repository class names that should be searched.
19+
*
20+
* @var Collection
21+
*/
22+
public $repositories;
23+
24+
/**
25+
* Create a new global search instance.
26+
*
27+
* @param RestifyRequest $request
28+
* @param \Illuminate\Support\Collection repositories
29+
* @return void
30+
*/
31+
public function __construct(RestifyRequest $request, $repositories)
32+
{
33+
$this->request = $request;
34+
$this->repositories = $repositories;
35+
}
36+
37+
/**
38+
* Get the matching repositories.
39+
*
40+
* @return array
41+
*/
42+
public function get()
43+
{
44+
$formatted = [];
45+
46+
foreach ($this->getSearchResults() as $repository => $models) {
47+
foreach ($models as $model) {
48+
$instance = $repository::resolveWith($model);
49+
50+
$formatted[] = [
51+
'repositoryName' => $repository::uriKey(),
52+
'repositoryTitle' => $repository::label(),
53+
'title' => $instance->title(),
54+
'subTitle' => $instance->subtitle(),
55+
'repositoryId' => $model->getKey(),
56+
];
57+
}
58+
}
59+
60+
return $formatted;
61+
}
62+
63+
/**
64+
* Get the search results for the repositories.
65+
*
66+
* @return array
67+
*/
68+
protected function getSearchResults()
69+
{
70+
$results = [];
71+
72+
foreach ($this->repositories as $repository) {
73+
$query = RepositorySearchService::instance()->search($this->request, $repository::resolveWith($repository::newModel()));
74+
75+
if (count($models = $query->limit($repository::$globalSearchResults)->get()) > 0) {
76+
$results[$repository] = $models;
77+
}
78+
}
79+
80+
return collect($results)->sortKeys()->all();
81+
}
82+
}

src/Services/Search/RepositorySearchService.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function search(RestifyRequest $request, Repository $repository)
1717

1818
$query = $this->prepareMatchFields($request, $this->prepareSearchFields($request, $repository::query(), $this->fixedInput), $this->fixedInput);
1919

20-
return $this->prepareRelations($request, $this->prepareOrders($request, $query), $this->fixedInput);
20+
return tap($this->prepareRelations($request, $this->prepareOrders($request, $query), $this->fixedInput), $this->applyIndexQuery($request, $repository));
2121
}
2222

2323
public function prepareMatchFields(RestifyRequest $request, $query, $extra = [])
@@ -113,7 +113,7 @@ public function prepareSearchFields(RestifyRequest $request, $query, $extra = []
113113
$canSearchPrimaryKey = is_numeric($search) &&
114114
in_array($query->getModel()->getKeyType(), ['int', 'integer']) &&
115115
($connectionType != 'pgsql' || $search <= PHP_INT_MAX) &&
116-
in_array($query->getModel()->getKeyName(), $model::getSearchableFields());
116+
in_array($query->getModel()->getKeyName(), $this->repository->getSearchableFields());
117117

118118
if ($canSearchPrimaryKey) {
119119
$query->orWhere($query->getModel()->getQualifiedKeyName(), $search);
@@ -170,4 +170,9 @@ public function setOrder($query, $param)
170170

171171
return $query;
172172
}
173+
174+
protected function applyIndexQuery(RestifyRequest $request, Repository $repository)
175+
{
176+
return fn ($query) => $repository::indexQuery($request, $query);
177+
}
173178
}

0 commit comments

Comments
 (0)