Skip to content

Commit

Permalink
Merge pull request #47 from binaryk/search-service
Browse files Browse the repository at this point in the history
Search service
  • Loading branch information
Lupacescu Eduard authored Dec 22, 2019
2 parents 563f560 + 16740c3 commit 867974f
Show file tree
Hide file tree
Showing 18 changed files with 1,036 additions and 56 deletions.
56 changes: 56 additions & 0 deletions src/Contracts/RestifySearchable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Binaryk\LaravelRestify\Contracts;

use Illuminate\Http\Request;

/**
* @author Eduard Lupacescu <[email protected]>
*/
interface RestifySearchable
{
const DEFAULT_PER_PAGE = 15;

const MATCH_TEXT = 'text';
const MATCH_BOOL = 'bool';
const MATCH_INTEGER = 'integer';

/**
* @param Request $request
* @param array $fields
* @return array
*/
public function serializeForIndex(Request $request, array $fields = []);

/**
* @return array
*/
public static function getSearchableFields();

/**
* @return array
*/
public static function getWiths();

/**
* @return array
*/
public static function getInFields();

/**
* Find matches in the table by given value
* Returns an array like:
* [ 'table_column_name' => 'type' ], type can be: text, bool, boolean, int, integer, number
* e.g. [ 'id' => 'int' ].
*
* To use this filter we have to send in query:
* [ 'match' => [ 'id' => 1 ] ]
* @return array
*/
public static function getMatchByFields();

/**
* @return array
*/
public static function getOrderByFields();
}
59 changes: 47 additions & 12 deletions src/Controllers/RestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

namespace Binaryk\LaravelRestify\Controllers;

use Binaryk\LaravelRestify\Contracts\RestifySearchable;
use Binaryk\LaravelRestify\Exceptions\Guard\EntityNotFoundException;
use Binaryk\LaravelRestify\Exceptions\Guard\GatePolicy;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use Binaryk\LaravelRestify\Services\Search\SearchService;
use Binaryk\LaravelRestify\Traits\PerformsQueries;
use Illuminate\Config\Repository;
use Illuminate\Config\Repository as Config;
use Illuminate\Container\Container;
use Illuminate\Contracts\Auth\Access\Gate;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
Expand All @@ -15,7 +20,6 @@
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Password;

Expand All @@ -30,7 +34,7 @@
*/
abstract class RestController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests, DispatchesJobs, ValidatesRequests, PerformsQueries;

/**
* @var RestResponse
Expand All @@ -43,7 +47,7 @@ abstract class RestController extends BaseController
protected $gate;

/**
* @var Request
* @var RestifyRequest
*/
protected $request;

Expand All @@ -58,13 +62,15 @@ abstract class RestController extends BaseController
protected $guard;

/**
* @return Request
* @return RestifyRequest
* @throws BindingResolutionException
*/
public function request()
{
if (($this->request instanceof Request) === false) {
$this->request = app()->make(Request::class);
$container = Container::getInstance();

if (($this->request instanceof RestifyRequest) === false) {
$this->request = $container->make(RestifyRequest::class);
}

return $this->request;
Expand All @@ -76,8 +82,10 @@ public function request()
*/
public function config()
{
$container = Container::getInstance();

if (($this->config instanceof Repository) === false) {
$this->config = app()->make(Repository::class);
$this->config = $container->make(Repository::class);
}

return $this->config;
Expand All @@ -86,10 +94,11 @@ public function config()
/**
* Returns a generic response to the client.
*
* @param mixed $data
* @param int $httpCode
* @param mixed $data
* @param int $httpCode
*
* @return JsonResponse
* @throws BindingResolutionException
*/
protected function respond($data = null, $httpCode = 200)
{
Expand All @@ -102,9 +111,9 @@ protected function respond($data = null, $httpCode = 200)
/**
* Get Response object.
*
* @param null $data
* @param int $status
* @param array $headers
* @param null $data
* @param int $status
* @param array $headers
* @return RestResponse
*/
protected function response($data = null, $status = 200, array $headers = [])
Expand All @@ -116,6 +125,29 @@ protected function response($data = null, $status = 200, array $headers = [])
return $this->response;
}

/**
* @param $modelClass
* @param array $filters
* @return array
* @throws BindingResolutionException
*/
public function search($modelClass, $filters = [])
{
$results = SearchService::instance()
->setPredefinedFilters($filters)
->search($this->request(), new $modelClass);
$results->tap(function ($query) {
static::indexQuery($this->request(), $query);
});

$paginator = $results->paginate($this->request()->get('perPage') ?? ($modelClass::$defaultPerPage ?? RestifySearchable::DEFAULT_PER_PAGE));
$items = $paginator->getCollection()->map->serializeForIndex($this->request());

return array_merge($paginator->toArray(), [
'data' => $items,
]);
}

/**
* @param $policy
* @param $objects
Expand Down Expand Up @@ -172,6 +204,7 @@ public function broker()
* Returns with a message.
* @param $msg
* @return JsonResponse
* @throws BindingResolutionException
*/
public function message($msg)
{
Expand All @@ -183,7 +216,9 @@ public function message($msg)
/**
* Returns with a list of errors.
*
* @param array $errors
* @return JsonResponse
* @throws BindingResolutionException
*/
protected function errors(array $errors)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Controllers/RestIndexController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Binaryk\LaravelRestify\Controllers;

/**
* @author Eduard Lupacescu <[email protected]>
*/
trait RestIndexController
{
}
2 changes: 2 additions & 0 deletions src/Exceptions/RestifyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Binaryk\LaravelRestify\Restify;
use Closure;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
Expand Down Expand Up @@ -93,6 +94,7 @@ public function render($request, Exception $exception)
case $exception instanceof UnauthorizedHttpException:
case $exception instanceof UnauthenticateException:
case $exception instanceof ActionUnauthorizedException:
case $exception instanceof AuthorizationException:
case $exception instanceof GatePolicy:
case $exception instanceof AuthenticationException:
$response->addError($exception->getMessage())->auth();
Expand Down
9 changes: 8 additions & 1 deletion src/Http/Controllers/RepositoryIndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@
*/
class RepositoryIndexController extends RepositoryController
{
/**
* @param RestifyRequest $request
* @return \Illuminate\Http\JsonResponse
* @throws \Binaryk\LaravelRestify\Exceptions\Eloquent\EntityNotFoundException
* @throws \Binaryk\LaravelRestify\Exceptions\UnauthorizedException
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function handle(RestifyRequest $request)
{
$resource = $request->repository();

$data = $resource::query()->get();
$data = $this->search($resource::newModel());

return $this->respond($data);
}
Expand Down
66 changes: 66 additions & 0 deletions src/Http/Requests/InteractWithRepositories.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Binaryk\LaravelRestify\Http\Requests;

use Binaryk\LaravelRestify\Exceptions\Eloquent\EntityNotFoundException;
use Binaryk\LaravelRestify\Exceptions\UnauthorizedException;
use Binaryk\LaravelRestify\Repositories\Repository;
use Binaryk\LaravelRestify\Restify;
use Illuminate\Database\Eloquent\Model;

/**
* @author Eduard Lupacescu <[email protected]>
*/
trait InteractWithRepositories
{
/**
* @var Model
*/
public $model;

/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}

/**
* Get the class name of the repository being requested.
*
* @return Repository
* @throws EntityNotFoundException
* @throws UnauthorizedException
*/
public function repository()
{
return tap(Restify::repositoryForKey($this->route('repository')), function ($repository) {
if (is_null($repository)) {
throw new EntityNotFoundException(__('Repository :name not found.', [
'name' => $repository,
]), 404);
}

if (! $repository::authorizedToViewAny($this)) {
throw new UnauthorizedException(__('Unauthorized to view repository :name.', [
'name' => $repository,
]), 403);
}
});
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
37 changes: 1 addition & 36 deletions src/Http/Requests/RestifyRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,12 @@

namespace Binaryk\LaravelRestify\Http\Requests;

use Binaryk\LaravelRestify\Exceptions\Eloquent\EntityNotFoundException;
use Binaryk\LaravelRestify\Exceptions\UnauthorizedException;
use Binaryk\LaravelRestify\Restify;
use Illuminate\Foundation\Http\FormRequest;

/**
* @author Eduard Lupacescu <[email protected]>
*/
class RestifyRequest extends FormRequest
{
/**
* Get the class name of the repository being requested.
*
* @return mixed
*/
public function repository()
{
return tap(Restify::repositoryForKey($this->route('repository')), function ($repository) {
if (is_null($repository)) {
throw new EntityNotFoundException(__('Repository :name not found.', [
'name' => $repository,
]), 404);
}

if (! $repository::authorizedToViewAny($this)) {
throw new UnauthorizedException(__('Unauthorized to view repository :name.', [
'name' => $repository,
]), 403);
}
});
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
use InteractWithRepositories;
}
6 changes: 3 additions & 3 deletions src/Repositories/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ abstract class Repository
/**
* @var Model
*/
public $resource;
public $modelInstance;

/**
* Create a new resource instance.
Expand All @@ -27,7 +27,7 @@ abstract class Repository
*/
public function __construct($resource)
{
$this->resource = $resource;
$this->modelInstance = $resource;
}

/**
Expand All @@ -45,7 +45,7 @@ abstract public function fields(Request $request);
*/
public function model()
{
return $this->resource;
return $this->modelInstance;
}

/**
Expand Down
Loading

0 comments on commit 867974f

Please sign in to comment.