Skip to content

Commit

Permalink
Merge pull request #64 from Kyslik/ft/left-join
Browse files Browse the repository at this point in the history
Fix #59; Laravel 5.4
  • Loading branch information
Kyslik authored Aug 31, 2017
2 parents a43a5a5 + 8b0775d commit e2ae9da
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 64 deletions.
17 changes: 3 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@ php:
- 7.0
- 7.1

env:
global:
- setup=basic

matrix:
allow_failures:
- php: 7.1
fast_finish: true
include:
- php: 5.6
env: setup=stable
git:
depth: 3

sudo: false

Expand All @@ -28,9 +19,7 @@ before_install:
- travis_retry composer self-update

install:
- if [[ $setup = 'basic' ]]; then travis_retry composer install --no-interaction --prefer-dist --no-suggest; fi
- if [[ $setup = 'stable' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --no-suggest; fi
- if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable --no-suggest; fi
- travis_retry composer install --no-interaction --prefer-dist --no-suggest;

script: vendor/bin/phpunit

Expand Down
48 changes: 18 additions & 30 deletions src/ColumnSortable/Sortable.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public function scopeSortable($query, $defaultSortParameters = null)
}
}


/**
* @param \Illuminate\Database\Query\Builder $query
* @param array $sortParameters
Expand All @@ -51,18 +50,14 @@ public function scopeSortable($query, $defaultSortParameters = null)
private function queryOrderBuilder($query, array $sortParameters)
{
$model = $this;

list($column, $direction) = $this->parseSortParameters($sortParameters);

if (is_null($column)) {
return $query;
}

$explodeResult = SortableLink::explodeSortParameter($column);
if ( ! empty($explodeResult)) {
$relationName = $explodeResult[0];
$column = $explodeResult[1];

try {
$relation = $query->getRelation($relationName);
$query = $this->queryJoinBuilder($query, $relation);
Expand All @@ -71,25 +66,19 @@ private function queryOrderBuilder($query, array $sortParameters)
} catch (\Exception $e) {
throw new ColumnSortableException($relationName, 2, $e);
}

$model = $relation->getRelated();
}

if (method_exists($model, camel_case($column).'Sortable')) {
return call_user_func_array([$model, camel_case($column).'Sortable'], [$query, $direction]);
}

if (isset($model->sortableAs) && in_array($column, $model->sortableAs)) {
$query = $query->orderBy($column, $direction);
} elseif ($this->columnExists($model, $column)) {
$column = $model->getTable().'.'.$column;
$query = $query->orderBy($column, $direction);
}

return $query;
}


/**
* @param array $sortParameters
*
Expand All @@ -101,16 +90,12 @@ private function parseSortParameters(array $sortParameters)
if (empty($column)) {
return [null, null];
}

$direction = array_get($sortParameters, 'order', []);
if ( ! in_array($direction, ['asc', 'desc'])) {
$direction = Config::get('columnsortable.default_direction', 'asc');
}

return [$column, $direction];
}


/**
* @param \Illuminate\Database\Query\Builder $query
* @param $relation
Expand All @@ -123,29 +108,23 @@ private function queryJoinBuilder($query, $relation)
{
$relatedTable = $relation->getRelated()->getTable();
$parentTable = $relation->getParent()->getTable();

if ($parentTable === $relatedTable) {
$query = $query->from($parentTable.' as parent_'.$parentTable);
$parentTable = 'parent_'.$parentTable;
$relation->getParent()->setTable($parentTable);
}

if ($relation instanceof HasOne) {
$relatedPrimaryKey = $relation->getQualifiedForeignKeyName();
$parentPrimaryKey = $relation->getQualifiedParentKeyName();

return $query->select($parentTable.'.*')->join($relatedTable, $parentPrimaryKey, '=', $relatedPrimaryKey);
return $this->formJoin($query, $parentTable, $relatedTable, $parentPrimaryKey, $relatedPrimaryKey);
} elseif ($relation instanceof BelongsTo) {
$relatedPrimaryKey = $relation->getQualifiedOwnerKeyName();
$parentPrimaryKey = $relation->getQualifiedForeignKey();

return $query->select($parentTable.'.*')->join($relatedTable, $parentPrimaryKey, '=', $relatedPrimaryKey);
return $this->formJoin($query, $parentTable, $relatedTable, $parentPrimaryKey, $relatedPrimaryKey);
} else {
throw new \Exception();
}
}


/**
* @param $model
* @param $column
Expand All @@ -157,8 +136,6 @@ private function columnExists($model, $column)
return (isset($model->sortable)) ? in_array($column, $model->sortable) :
Schema::hasColumn($model->getTable(), $column);
}


/**
* @param array|string $sort
*
Expand All @@ -169,19 +146,30 @@ private function formatToSortParameters($sort)
if (empty($sort)) {
return [];
}

$configDefaultOrder = Config::get('columnsortable.default_direction', 'asc');

if (is_string($sort)) {
return ['sort' => $sort, 'order' => $configDefaultOrder];
}

reset($sort);
$each = each($sort);

return ($each[0] === 0) ? ['sort' => $each[1], 'order' => $configDefaultOrder] : [
'sort' => $each[0],
'order' => $each[1],
];
}
}
/**
* @param $query
* @param $parentTable
* @param $relatedTable
* @param $parentPrimaryKey
* @param $relatedPrimaryKey
*
* @return mixed
*/
private function formJoin($query, $parentTable, $relatedTable, $parentPrimaryKey, $relatedPrimaryKey)
{
$joinType = Config::get('columnsortable.join_type', 'join');

return $query->select($parentTable.'.*')->{$joinType}($relatedTable, $parentPrimaryKey, '=', $relatedPrimaryKey);
}
}
46 changes: 26 additions & 20 deletions src/config/columnsortable.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,56 @@
/*
spec columns
*/
'columns' => [
'alpha' => [
'rows' => ['description', 'email', 'name', 'slug'],
'columns' => [
'alpha' => [
'rows' => ['description', 'email', 'name', 'slug'],
'class' => 'fa fa-sort-alpha',
],
'amount' => [
'rows' => ['amount', 'price'],
'class' => 'fa fa-sort-amount'
'amount' => [
'rows' => ['amount', 'price'],
'class' => 'fa fa-sort-amount',
],
'numeric' => [
'rows' => ['created_at', 'updated_at', 'level', 'id', 'phone_number'],
'class' => 'fa fa-sort-numeric'
'rows' => ['created_at', 'updated_at', 'level', 'id', 'phone_number'],
'class' => 'fa fa-sort-numeric',
],
],

/*
defines icon set to use when sorted data is none above (alpha nor amount nor numeric)
*/
'default_icon_set' => 'fa fa-sort',
'default_icon_set' => 'fa fa-sort',

/*
icon that shows when generating sortable link while column is not sorted
*/
'sortable_icon' => 'fa fa-sort',
'sortable_icon' => 'fa fa-sort',

/*
generated icon is clickable non-clickable (default)
*/
'clickable_icon' => false,
'clickable_icon' => false,

/*
icon and text separator (any string)
in case of 'clickable_icon' => true; separator creates possibility to style icon and anchor-text properly
*/
'icon_text_separator' => ' ',
'icon_text_separator' => ' ',

/*
suffix class that is appended when ascending order is applied
*/
'asc_suffix' => '-asc',
'asc_suffix' => '-asc',

/*
suffix class that is appended when descending order is applied
*/
'desc_suffix' => '-desc',
'desc_suffix' => '-desc',

/*
default anchor class, if value is null none is added
*/
'anchor_class' => null,
'anchor_class' => null,

/*
relation - column separator ex: detail.phone_number means relation "detail" and column "phone_number"
Expand All @@ -64,26 +64,32 @@
/*
formatting function applied to name of column, use null to turn formatting off
*/
'formatting_function' => 'ucfirst',
'formatting_function' => 'ucfirst',

/*
inject title parameter in query strings, use null to turn injection off
example: 'inject_title' => 't' will result in ..user/?t="formatted title of sorted column"
*/
'inject_title_as' => null,
'inject_title_as' => null,

/*
allow request modification, when default sorting is set but is not in URI (first load)
*/
'allow_request_modification' => true,
'allow_request_modification' => true,

/*
default order for: $user->sortable('id') usage
*/
'default_direction' => 'asc',
'default_direction' => 'asc',

/*
default order for non-sorted columns
*/
'default_direction_unsorted' => 'asc'
'default_direction_unsorted' => 'asc',

/*
join type: join vs leftJoin (default join)
for more information see https://github.com/Kyslik/column-sortable/issues/59
*/
'join_type' => 'join',
];

0 comments on commit e2ae9da

Please sign in to comment.