Skip to content

Commit

Permalink
edited namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
hamidrezarj committed Feb 2, 2024
1 parent 42253b7 commit ef7df68
Show file tree
Hide file tree
Showing 24 changed files with 847 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/DataTableInput.php
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;
}


}
110 changes: 110 additions & 0 deletions src/DataTableService.php
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);

Check failure on line 102 in src/DataTableService.php

View workflow job for this annotation

GitHub Actions / phpstan

Call to an undefined method Illuminate\Contracts\Database\Query\Builder::with().
}

return $query;
}

// (later) define mapping of relation names to prevent relation name expose.
// (later) define mapping of column names to prevent column name expose.
}
14 changes: 14 additions & 0 deletions src/Enums/DataType.php
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');
}
}
19 changes: 19 additions & 0 deletions src/Enums/SearchType.php
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');
}
}
21 changes: 21 additions & 0 deletions src/Exceptions/InvalidFilterException.php
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;
}
}
7 changes: 7 additions & 0 deletions src/Exceptions/InvalidParameterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace HamidRrj\LaravelDatatable\Exceptions;

interface InvalidParameterInterface
{
}
21 changes: 21 additions & 0 deletions src/Exceptions/InvalidRelationException.php
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;
}
}
21 changes: 21 additions & 0 deletions src/Exceptions/InvalidSortingException.php
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;
}
}
84 changes: 84 additions & 0 deletions src/Filter/ApplyFilter.php
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) {

Check failure on line 74 in src/Filter/ApplyFilter.php

View workflow job for this annotation

GitHub Actions / phpstan

Call to an undefined method Illuminate\Contracts\Database\Query\Builder::whereHas().
$this->filter->removeRelationFromId();
$this->applyFilter($query, $this->filter);
});
}

private function applyFilter(Builder $query, Filter $filter): Builder
{
return (new ApplyFilter($query, $filter))->apply();
}
}
Loading

0 comments on commit ef7df68

Please sign in to comment.