generated from spatie/package-skeleton-laravel
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
42253b7
commit ef7df68
Showing
24 changed files
with
847 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable; | ||
|
||
use HamidRrj\LaravelDatatable\Filter\Filter; | ||
use HamidRrj\LaravelDatatable\Sort\Sort; | ||
|
||
class DataTableInput | ||
{ | ||
/** | ||
* @param int $start | ||
* @param int $size | ||
* @param array $filters | ||
* @param array $sorting | ||
* @param array $rels | ||
*/ | ||
public function __construct( | ||
private int $start, | ||
private ?int $size, | ||
private array $filters, | ||
private array $sorting, | ||
private array $rels, | ||
private array $allowedFilters, | ||
private array $allowedSortings, | ||
) | ||
{ | ||
} | ||
|
||
public function getStart(): int | ||
{ | ||
return $this->start; | ||
} | ||
|
||
public function getSize(): ?int | ||
{ | ||
return $this->size; | ||
} | ||
|
||
/** | ||
* @return array returns an array of Filter objects | ||
*/ | ||
public function getFilters(): array | ||
{ | ||
$filters = array(); | ||
|
||
foreach ($this->filters as $filter) { | ||
$filters[] = new Filter( | ||
$filter->id, | ||
$filter->value, | ||
$filter->fn, | ||
$filter->datatype, | ||
$this->allowedFilters | ||
); | ||
} | ||
|
||
return $filters; | ||
} | ||
|
||
/** | ||
* @return Sort|null | ||
*/ | ||
public function getSorting(): ?Sort | ||
{ | ||
return !empty($this->sorting) ? | ||
new Sort($this->sorting[0]->id, $this->sorting[0]->desc, $this->allowedSortings) : null; | ||
} | ||
|
||
public function getRelations(): array | ||
{ | ||
return $this->rels; | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable; | ||
|
||
use HamidRrj\LaravelDatatable\Filter\ApplyFilter; | ||
use HamidRrj\LaravelDatatable\Sort\ApplySort; | ||
use Illuminate\Contracts\Database\Query\Builder; | ||
|
||
class DataTableService | ||
{ | ||
|
||
protected array $allowedFilters; | ||
protected array $allowedRelations; | ||
protected array $allowedSortings; | ||
protected array $allowedSelects; | ||
private int $totalRowCount; | ||
|
||
public function __construct( | ||
protected Builder $query, | ||
private DataTableInput $dataTableInput | ||
) | ||
{ | ||
} | ||
|
||
public function setAllowedFilters(array $allowedFilters): DataTableService | ||
{ | ||
$this->allowedFilters = $allowedFilters; | ||
return $this; | ||
} | ||
|
||
public function setAllowedRelations(array $allowedRelations): DataTableService | ||
{ | ||
$this->allowedRelations = $allowedRelations; | ||
return $this; | ||
} | ||
|
||
public function setAllowedSortings(array $allowedSortings): DataTableService | ||
{ | ||
$this->allowedSortings = $allowedSortings; | ||
return $this; | ||
} | ||
|
||
public function setAllowedSelects(array $allowedSelects): DataTableService | ||
{ | ||
$this->allowedSelects = $allowedSelects; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Handle 'getData' operations | ||
* @return array | ||
*/ | ||
public function getData(): array | ||
{ | ||
$query = $this->buildQuery(); | ||
$data = $query->get(); | ||
|
||
return array( | ||
'data' => $data, | ||
'meta' => [ | ||
'totalRowCount' => $this->totalRowCount | ||
] | ||
); | ||
} | ||
|
||
protected function buildQuery(): Builder | ||
{ | ||
$query = $this->query; | ||
|
||
foreach ($this->dataTableInput->getFilters() as $filter) { | ||
$query = (new ApplyFilter($query, $filter))->apply(); | ||
} | ||
|
||
$query = $this->applySelect($query, $this->allowedSelects); | ||
$query = $this->includeRelationsInQuery($query, $this->allowedRelations); | ||
|
||
$this->totalRowCount = $query->count(); | ||
|
||
$query->offset($this->dataTableInput->getStart()); | ||
|
||
if(!is_null($this->dataTableInput->getSize())){ | ||
$query->limit($this->dataTableInput->getSize()); | ||
} | ||
|
||
$sorting = $this->dataTableInput->getSorting(); | ||
$query = (new ApplySort($query, $sorting))->apply(); | ||
return $query; | ||
} | ||
|
||
protected function applySelect(Builder $query, array $selectedFields): Builder | ||
{ | ||
if (!empty($selectedFields)) { | ||
$query->select($selectedFields); | ||
} | ||
|
||
return $query; | ||
} | ||
|
||
protected function includeRelationsInQuery(Builder $query, array $rels): Builder | ||
{ | ||
if (!empty($rels)) { | ||
$query->with($rels); | ||
} | ||
|
||
return $query; | ||
} | ||
|
||
// (later) define mapping of relation names to prevent relation name expose. | ||
// (later) define mapping of column names to prevent column name expose. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Enums; | ||
enum DataType: string | ||
{ | ||
case NUMERIC = 'numeric'; | ||
case TEXT = 'text'; | ||
case DATE = 'date'; | ||
|
||
public static function values(): array | ||
{ | ||
return array_column(self::cases(), 'value'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Enums; | ||
|
||
enum SearchType: string | ||
{ | ||
case CONTAINS = 'contains'; | ||
case EQUALS = 'equals'; | ||
case NOT_EQUALS = 'notEquals'; | ||
case BETWEEN = 'between'; | ||
case GREATER_THAN = 'greaterThan'; | ||
case LESS_THAN = 'lessThan'; | ||
case FUZZY = 'fuzzy'; | ||
|
||
public static function values(): array | ||
{ | ||
return array_column(self::cases(), 'value'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Exceptions; | ||
|
||
use Exception; | ||
|
||
class InvalidFilterException extends Exception implements InvalidParameterInterface | ||
{ | ||
protected $fieldName; | ||
|
||
public function __construct($fieldName, $message = "", $code = 400, \Throwable $previous = null) | ||
{ | ||
$this->fieldName = $fieldName; | ||
parent::__construct($message, $code, $previous); | ||
} | ||
|
||
public function getFieldName() | ||
{ | ||
return $this->fieldName; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Exceptions; | ||
|
||
interface InvalidParameterInterface | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Exceptions; | ||
|
||
use Exception; | ||
|
||
class InvalidRelationException extends Exception implements InvalidParameterInterface | ||
{ | ||
protected $fieldName; | ||
|
||
public function __construct($fieldName, $message = "", $code = 400, \Throwable $previous = null) | ||
{ | ||
$this->fieldName = $fieldName; | ||
parent::__construct($message, $code, $previous); | ||
} | ||
|
||
public function getFieldName() | ||
{ | ||
return $this->fieldName; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Exceptions; | ||
|
||
use Exception; | ||
|
||
class InvalidSortingException extends Exception implements InvalidParameterInterface | ||
{ | ||
protected $fieldName; | ||
|
||
public function __construct($fieldName, $message = "", $code = 400, \Throwable $previous = null) | ||
{ | ||
$this->fieldName = $fieldName; | ||
parent::__construct($message, $code, $previous); | ||
} | ||
|
||
public function getFieldName() | ||
{ | ||
return $this->fieldName; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
namespace HamidRrj\LaravelDatatable\Filter; | ||
|
||
use HamidRrj\LaravelDatatable\Enums\SearchType; | ||
use HamidRrj\LaravelDatatable\Exceptions\InvalidFilterException; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterBetween; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterContains; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterEquals; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterGreaterThan; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterLessThan; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\FilterNotEquals; | ||
use HamidRrj\LaravelDatatable\Filter\SearchFunctions\SearchFilter; | ||
use Illuminate\Contracts\Database\Query\Builder; | ||
|
||
class ApplyFilter | ||
{ | ||
private SearchFilter $searchFilter; | ||
|
||
/** | ||
* @param Builder $query | ||
* @param Filter $filter | ||
*/ | ||
public function __construct( | ||
private Builder $query, | ||
private Filter $filter, | ||
) | ||
{ | ||
} | ||
|
||
public function apply(): Builder | ||
{ | ||
$filter = $this->filter; | ||
$query = $this->query; | ||
|
||
$searchType = SearchType::from($filter->getFn()); | ||
switch ($searchType) { | ||
case SearchType::CONTAINS: | ||
$this->searchFilter = new FilterContains($query, $filter); | ||
break; | ||
|
||
case SearchType::EQUALS: | ||
$this->searchFilter = new FilterEquals($query, $filter); | ||
break; | ||
|
||
case SearchType::NOT_EQUALS: | ||
$this->searchFilter = new FilterNotEquals($query, $filter); | ||
break; | ||
|
||
case SearchType::BETWEEN: | ||
$this->searchFilter = new FilterBetween($query, $filter); | ||
break; | ||
|
||
case SearchType::GREATER_THAN: | ||
$this->searchFilter = new FilterGreaterThan($query, $filter); | ||
break; | ||
|
||
case SearchType::LESS_THAN: | ||
$this->searchFilter = new FilterLessThan($query, $filter); | ||
break; | ||
|
||
default: | ||
$searchFunction = $filter->getFn(); | ||
throw new InvalidFilterException($searchFunction, "search function `$searchFunction` is invalid."); | ||
|
||
} | ||
|
||
$relation = $this->filter->getRelation(); | ||
return $relation ? $this->applyFilterToRelation($relation) : $this->searchFilter->apply(); | ||
} | ||
|
||
protected function applyFilterToRelation(string $relation): Builder | ||
{ | ||
return $this->query->whereHas($relation, function (Builder $query) { | ||
$this->filter->removeRelationFromId(); | ||
$this->applyFilter($query, $this->filter); | ||
}); | ||
} | ||
|
||
private function applyFilter(Builder $query, Filter $filter): Builder | ||
{ | ||
return (new ApplyFilter($query, $filter))->apply(); | ||
} | ||
} |
Oops, something went wrong.