Skip to content

Add support for newer eloquent versions and datatable regex search #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "livecontrol/eloquent-datatable",
"name": "schoppax/eloquent-datatable",
"description": "Eloquent DataTable plugin for server side ajax call handling.",
"keywords": [
"eloquent",
Expand All @@ -15,7 +15,7 @@
],
"require": {
"php": ">=5.4.0",
"illuminate/database": "5.*"
"illuminate/database": ">=5.7.5"
},
"require-dev": {
"phpspec/phpspec": "~2.1"
Expand Down
99 changes: 74 additions & 25 deletions src/LiveControl/EloquentDataTable/DataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression as raw;
use Illuminate\Database\Query\Grammars\Grammar;
use Illuminate\Support\Str;
use LiveControl\EloquentDataTable\VersionTransformers\Version110Transformer;
use LiveControl\EloquentDataTable\VersionTransformers\VersionTransformerContract;

Expand All @@ -13,6 +15,7 @@ class DataTable
{
protected $builder;
protected $columns;
protected $orderPossibilities;
protected $formatRowFunction;

/**
Expand All @@ -22,22 +25,29 @@ class DataTable

protected $rawColumns;
protected $columnNames;
protected $orderNames;

protected $total = 0;
protected $filtered = 0;

protected $rows = [];

protected $mySqlAggFncs = [
"AVG(","BIT_AND(","BIT_OR(","BIT_XOR(","COUNT(","GROUP_CONCAT(","JSON_ARRAYAGG(","JSON_OBJECTAGG(","MAX(",
"MIN(","STD(","STDDEV(","STDDEV_POP(","STDDEV_SAMP(","SUM(","VAR_POP(","VAR_SAMP(","VARIANCE("
];

/**
* @param Builder|Model $builder
* @param array $columns
* @param null|callable $formatRowFunction
* @throws Exception
*/
public function __construct($builder, $columns, $formatRowFunction = null)
public function __construct($builder, $columns, $orderPossibilities = null, $formatRowFunction = null)
{
$this->setBuilder($builder);
$this->setColumns($columns);
$this->setOrderPossibilities($orderPossibilities);

if ($formatRowFunction !== null) {
$this->setFormatRowFunction($formatRowFunction);
Expand Down Expand Up @@ -69,6 +79,20 @@ public function setColumns($columns)
return $this;
}

/**
* @param mixed $columns
* @return $this
*/
public function setOrderPossibilities($columns)
{
if ( $columns !== null ) {
$this->orderPossibilities = $columns;
} else {
$this->orderPossibilities = $this->columns;
}
return $this;
}

/**
* @param callable $function
* @return $this
Expand Down Expand Up @@ -97,7 +121,8 @@ public function setVersionTransformer(VersionTransformerContract $versionTransfo
public function make()
{
$this->rawColumns = $this->getRawColumns($this->columns);
$this->columnNames = $this->getColumnNames();
$this->columnNames = $this->getColumnNames($this->columns);
$this->orderNames = $this->getColumnNames($this->orderPossibilities);

$this->addSelect();

Expand Down Expand Up @@ -142,7 +167,7 @@ protected function count()
$countStatement = $pdo->prepare('SELECT count(*) as totalCount FROM ('.$query->toSql().') subQuery');
$countStatement->execute($query->getBindings());
}

$result = $countStatement->fetch();
return $result['totalCount'];
}
Expand Down Expand Up @@ -186,10 +211,10 @@ protected function formatRowIndexes($data)
/**
* @return array
*/
protected function getColumnNames()
protected function getColumnNames($columns)
{
$names = [];
foreach ($this->columns as $index => $column) {
foreach ($columns as $index => $column) {
if ($column instanceof ExpressionWithName) {
$names[] = $column->getName();
continue;
Expand Down Expand Up @@ -224,7 +249,8 @@ protected function getRawColumns($columns)
protected function getRawColumnQuery($column)
{
if ($column instanceof ExpressionWithName) {
return $column->getExpression();
$gramma = new Grammar();
return $column->getExpression()->getValue($gramma);
}

if (is_array($column)) {
Expand Down Expand Up @@ -276,7 +302,22 @@ protected function arrayToCamelcase($array, $inForeach = false)
$result[] = $value;
}

return (! $inForeach ? camel_case(implode('_', $result)) : $result);
return (! $inForeach ? Str::camel(implode('_', $result)) : $result);
}

/**
* Checks if the query includes aggregate functions
* @return bool
*/
protected function hasAggregateFunction()
{
$query = $this->builder->toSql() ?? $this->builder->getQuery()->toSql();
foreach($this->mySqlAggFncs as $aggFnc) {
if (stripos($query, $aggFnc) !== false) {
return true;
}
}
return false;
}

/**
Expand All @@ -286,26 +327,31 @@ protected function arrayToCamelcase($array, $inForeach = false)
protected function addFilters()
{
$search = static::$versionTransformer->getSearchValue();
$regex = static::$versionTransformer->isSearchRegex();
$aggregate = $this->hasAggregateFunction();
if ($search != '') {
$this->addAllFilter($search);
$this->addAllFilter($search, $regex, $aggregate);
}
$this->addColumnFilters();
$this->addColumnFilters($aggregate);
return $this;
}

/**
* Searches in all the columns.
* @param $search
* @param $regex
*/
protected function addAllFilter($search)
protected function addAllFilter($search, $regex, $aggregate)
{
$this->builder = $this->builder->where(
function ($query) use ($search) {
foreach ($this->columns as $column) {
$query->orWhere(
new raw($this->getRawColumnQuery($column)),
'like',
'%' . $search . '%'
$method = $aggregate ? 'Having' : 'Where';
$columns = $aggregate ? $this->columnNames : $this->columns;
$this->builder = $this->builder->{strtolower($method)}(
function ($query) use ($search, $regex, $method, $columns, $aggregate) {
foreach ($columns as $column) {
$query->{"or$method"}(
new raw($aggregate ? $column : $this->getRawColumnQuery($column)),
$regex ? 'rlike' : 'like',
$regex ? $search : '%' . $search . '%'
);
}
}
Expand All @@ -315,14 +361,17 @@ function ($query) use ($search) {
/**
* Add column specific filters.
*/
protected function addColumnFilters()
protected function addColumnFilters($aggregate)
{
foreach ($this->columns as $i => $column) {
$columns = $aggregate ? $this->columnNames : $this->columns;
foreach ($columns as $i => $column) {
if (static::$versionTransformer->isColumnSearched($i)) {
$this->builder->where(
new raw($this->getRawColumnQuery($column)),
'like',
'%' . static::$versionTransformer->getColumnSearchValue($i) . '%'
$regex = static::$versionTransformer->isColumnSearchRegex($i);
$method = $aggregate ? 'having' : 'where';
$this->builder->{$method}(
new raw($aggregate ? $column : $this->getRawColumnQuery($column)),
$regex ? 'rlike' : 'like',
$regex ? static::$versionTransformer->getColumnSearchValue($i) : '%' . static::$versionTransformer->getColumnSearchValue($i) . '%'
);
}
}
Expand All @@ -335,9 +384,9 @@ protected function addOrderBy()
{
if (static::$versionTransformer->isOrdered()) {
foreach (static::$versionTransformer->getOrderedColumns() as $index => $direction) {
if (isset($this->columnNames[$index])) {
if (isset($this->orderNames[$index])) {
$this->builder->orderBy(
$this->columnNames[$index],
$this->orderNames[$index],
$direction
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,43 @@ class Version109Transformer implements VersionTransformerContract

];

public function transform($name)
public function transform($name): string
{
return (isset($this->translate[$name]) ? $this->translate[$name] : $name);
}

public function getSearchValue()
public function isSearchRegex(): bool
{
return false;
}
public function getSearchValue(): string
{
if(isset($_POST['sSearch']))
return $_POST['sSearch'];
return '';
}

public function isColumnSearched($i)
public function isColumnSearched($i): bool
{
return (isset($_POST['bSearchable_' . $i]) && $_POST['bSearchable_' . $i] == 'true' && $_POST['sSearch_' . $i] != '');
}

public function getColumnSearchValue($i)
public function isColumnSearchRegex($columnIndex): bool
{
return false;
}

public function getColumnSearchValue($i): string
{
return $_POST['sSearch_' . $i];
}

public function isOrdered()
public function isOrdered(): bool
{
return isset($_POST['iSortCol_0']);
}

public function getOrderedColumns()
public function getOrderedColumns(): array
{
$columns = [];
for ($i = 0; $i < (int) $_POST['iSortingCols']; $i ++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@

class Version110Transformer implements VersionTransformerContract
{
public function transform($name)
public function transform($name): string
{
return $name; // we use the same as the requested name
}

public function getSearchValue()
public function isSearchRegex(): bool
{
if(isset($_POST['search']) && isset($_POST['search']['regex']))
return filter_var($_POST['search']['regex'], FILTER_VALIDATE_BOOLEAN);
return false;
}

public function getSearchValue(): string
{
if(isset($_POST['search']) && isset($_POST['search']['value']))
return $_POST['search']['value'];
return '';
}

public function isColumnSearched($columnIndex)
public function isColumnSearched($columnIndex): bool
{
return (
isset($_POST['columns'])
Expand All @@ -30,17 +37,24 @@ public function isColumnSearched($columnIndex)
);
}

public function getColumnSearchValue($columnIndex)
public function isColumnSearchRegex($columnIndex): bool
{
if (isset($_POST['columns'][$columnIndex]['search']['regex']))
return filter_var($_POST['columns'][$columnIndex]['search']['regex'], FILTER_VALIDATE_BOOLEAN);
return false;
}

public function getColumnSearchValue($columnIndex): string
{
return $_POST['columns'][$columnIndex]['search']['value'];
}

public function isOrdered()
public function isOrdered(): bool
{
return (isset($_POST['order']) && isset($_POST['order'][0]));
}

public function getOrderedColumns()
public function getOrderedColumns(): array
{
$columns = [];
foreach($_POST['order'] as $i => $order)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@

interface VersionTransformerContract
{
public function transform($name);
public function transform($name): string;

public function getSearchValue();
public function isSearchRegex(): bool;
public function getSearchValue(): string;

public function isColumnSearched($columnIndex);
public function getColumnSearchValue($columnIndex);
public function isColumnSearched($columnIndex): bool;
public function isColumnSearchRegex($columnIndex): bool;
public function getColumnSearchValue($columnIndex): string;


public function isOrdered();
public function getOrderedColumns();
public function isOrdered(): bool;
public function getOrderedColumns(): array;
}