From 919c7127e772cf590c79e0c0d7477e6807e307cf Mon Sep 17 00:00:00 2001 From: Joseph Cohen Date: Tue, 23 Feb 2016 13:34:22 -0600 Subject: [PATCH] Fixes API sorting and filtering. Closes #1489 --- .../Controllers/Api/AbstractApiController.php | 6 --- .../Controllers/Api/ComponentController.php | 10 ++++- .../Api/ComponentGroupController.php | 10 ++++- .../Controllers/Api/IncidentController.php | 10 ++++- app/Http/Controllers/Api/MetricController.php | 10 ++++- app/Models/Component.php | 17 +++++++- app/Models/ComponentGroup.php | 15 ++++++- app/Models/Incident.php | 16 +++++++- app/Models/Metric.php | 16 +++++++- app/Models/Traits/SortableTrait.php | 40 +++++++++++++++++++ 10 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 app/Models/Traits/SortableTrait.php diff --git a/app/Http/Controllers/Api/AbstractApiController.php b/app/Http/Controllers/Api/AbstractApiController.php index cbfb0686..4b871c5b 100644 --- a/app/Http/Controllers/Api/AbstractApiController.php +++ b/app/Http/Controllers/Api/AbstractApiController.php @@ -161,12 +161,6 @@ abstract class AbstractApiController extends Controller $items = $paginator->getCollection(); - if ($sortBy = $request->get('sort')) { - $direction = $request->has('order') && $request->get('order') == 'desc'; - - $items = $items->sortBy($sortBy, SORT_REGULAR, $direction); - } - return $this->setMetaData($pagination)->setData(AutoPresenter::decorate($items->values()))->respond(); } diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index 3cd33223..84ba8fc6 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -37,7 +37,15 @@ class ComponentController extends AbstractApiController $components = Component::enabled(); } - return $this->paginator($components->paginate(Binput::get('per_page', 20)), Request::instance()); + if ($sortBy = Binput::get('sort')) { + $direction = Binput::has('order') && Binput::get('order') == 'desc'; + + $components->sort($sortBy, $direction); + } + + $components = $components->paginate(Binput::get('per_page', 20)); + + return $this->paginator($components, Request::instance()); } /** diff --git a/app/Http/Controllers/Api/ComponentGroupController.php b/app/Http/Controllers/Api/ComponentGroupController.php index 989bd131..f0969d5d 100644 --- a/app/Http/Controllers/Api/ComponentGroupController.php +++ b/app/Http/Controllers/Api/ComponentGroupController.php @@ -29,7 +29,15 @@ class ComponentGroupController extends AbstractApiController */ public function getGroups() { - $groups = ComponentGroup::paginate(Binput::get('per_page', 20)); + $groups = ComponentGroup::whereRaw('1=1'); + + if ($sortBy = Binput::get('sort')) { + $direction = Binput::has('order') && Binput::get('order') == 'desc'; + + $groups->sort($sortBy, $direction); + } + + $groups = $groups->paginate(Binput::get('per_page', 20)); return $this->paginator($groups, Request::instance()); } diff --git a/app/Http/Controllers/Api/IncidentController.php b/app/Http/Controllers/Api/IncidentController.php index 9d715610..e0c60c88 100644 --- a/app/Http/Controllers/Api/IncidentController.php +++ b/app/Http/Controllers/Api/IncidentController.php @@ -32,7 +32,15 @@ class IncidentController extends AbstractApiController { $incidentVisibility = app(Guard::class)->check() ? 0 : 1; - $incidents = Incident::where('visible', '>=', $incidentVisibility)->paginate(Binput::get('per_page', 20)); + $incidents = Incident::where('visible', '>=', $incidentVisibility); + + if ($sortBy = Binput::get('sort')) { + $direction = Binput::has('order') && Binput::get('order') == 'desc'; + + $incidents->sort($sortBy, $direction); + } + + $incidents = $incidents->paginate(Binput::get('per_page', 20)); return $this->paginator($incidents, Request::instance()); } diff --git a/app/Http/Controllers/Api/MetricController.php b/app/Http/Controllers/Api/MetricController.php index dbf4b065..acab4c79 100644 --- a/app/Http/Controllers/Api/MetricController.php +++ b/app/Http/Controllers/Api/MetricController.php @@ -29,7 +29,15 @@ class MetricController extends AbstractApiController */ public function getMetrics() { - $metrics = Metric::paginate(Binput::get('per_page', 20)); + $metrics = Metric::whereRaw('1=1'); + + if ($sortBy = Binput::get('sort')) { + $direction = Binput::has('order') && Binput::get('order') == 'desc'; + + $metrics->sort($sortBy, $direction); + } + + $metrics = $metrics->paginate(Binput::get('per_page', 20)); return $this->paginator($metrics, Request::instance()); } diff --git a/app/Models/Component.php b/app/Models/Component.php index fed0292f..1d9d2d87 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -12,6 +12,7 @@ namespace CachetHQ\Cachet\Models; use AltThree\Validator\ValidatingTrait; +use CachetHQ\Cachet\Models\Traits\SortableTrait; use CachetHQ\Cachet\Presenters\ComponentPresenter; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; @@ -20,7 +21,7 @@ use McCool\LaravelAutoPresenter\HasPresenter; class Component extends Model implements HasPresenter { - use SoftDeletes, ValidatingTrait; + use SoftDeletes, SortableTrait, ValidatingTrait; /** * List of attributes that have default values. @@ -76,6 +77,20 @@ class Component extends Model implements HasPresenter 'link' => 'url', ]; + /** + * The sortable fields. + * + * @var string[] + */ + protected $sortable = [ + 'id', + 'name', + 'status', + 'order', + 'group_id', + 'enabled', + ]; + /** * Components can belong to a group. * diff --git a/app/Models/ComponentGroup.php b/app/Models/ComponentGroup.php index 034b5641..72a192eb 100644 --- a/app/Models/ComponentGroup.php +++ b/app/Models/ComponentGroup.php @@ -12,13 +12,14 @@ namespace CachetHQ\Cachet\Models; use AltThree\Validator\ValidatingTrait; +use CachetHQ\Cachet\Models\Traits\SortableTrait; use CachetHQ\Cachet\Presenters\ComponentGroupPresenter; use Illuminate\Database\Eloquent\Model; use McCool\LaravelAutoPresenter\HasPresenter; class ComponentGroup extends Model implements HasPresenter { - use ValidatingTrait; + use SortableTrait, ValidatingTrait; /** * The attributes that should be casted to native types. @@ -49,6 +50,18 @@ class ComponentGroup extends Model implements HasPresenter 'collapsed' => 'bool', ]; + /** + * The sortable fields. + * + * @var string[] + */ + protected $sortable = [ + 'id', + 'name', + 'order', + 'collapsed', + ]; + /** * The relations to eager load on every query. * diff --git a/app/Models/Incident.php b/app/Models/Incident.php index 3633b221..694d32f9 100644 --- a/app/Models/Incident.php +++ b/app/Models/Incident.php @@ -12,6 +12,7 @@ namespace CachetHQ\Cachet\Models; use AltThree\Validator\ValidatingTrait; +use CachetHQ\Cachet\Models\Traits\SortableTrait; use CachetHQ\Cachet\Presenters\IncidentPresenter; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; @@ -20,7 +21,7 @@ use McCool\LaravelAutoPresenter\HasPresenter; class Incident extends Model implements HasPresenter { - use SoftDeletes, ValidatingTrait; + use SoftDeletes, SortableTrait, ValidatingTrait; /** * The attributes that should be casted to native types. @@ -62,6 +63,19 @@ class Incident extends Model implements HasPresenter 'message' => 'required', ]; + /** + * The sortable fields. + * + * @var string[] + */ + protected $sortable = [ + 'id', + 'name', + 'status', + 'visible', + 'message', + ]; + /** * Finds all visible incidents. * diff --git a/app/Models/Metric.php b/app/Models/Metric.php index c61a979a..5a14c9c4 100644 --- a/app/Models/Metric.php +++ b/app/Models/Metric.php @@ -12,13 +12,14 @@ namespace CachetHQ\Cachet\Models; use AltThree\Validator\ValidatingTrait; +use CachetHQ\Cachet\Models\Traits\SortableTrait; use CachetHQ\Cachet\Presenters\MetricPresenter; use Illuminate\Database\Eloquent\Model; use McCool\LaravelAutoPresenter\HasPresenter; class Metric extends Model implements HasPresenter { - use ValidatingTrait; + use SortableTrait, ValidatingTrait; /** * The calculation type of sum. @@ -92,6 +93,19 @@ class Metric extends Model implements HasPresenter 'default_view' => 'numeric|between:0,3', ]; + /** + * The sortable fields. + * + * @var string[] + */ + protected $sortable = [ + 'id', + 'name', + 'display_chart', + 'default_value', + 'calc_type', + ]; + /** * Metrics contain many metric points. * diff --git a/app/Models/Traits/SortableTrait.php b/app/Models/Traits/SortableTrait.php new file mode 100644 index 00000000..7c579ce5 --- /dev/null +++ b/app/Models/Traits/SortableTrait.php @@ -0,0 +1,40 @@ + + */ +trait SortableTrait +{ + /** + * Adds a sort scope. + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $column + * @param string $direction + * + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeSort(Builder $query, $column, $direction) + { + if (!in_array($column, $this->sortable)) { + return $query; + } + + return $query->orderBy($column, $direction); + } +}