<?php use Admin\Libraries\ModelHelper; use Admin\Libraries\Fields\Field; use Admin\Libraries\Column; use Admin\Libraries\Sort; //View Composers //admin index view View::composer('administrator::index', function ($view) { //get a model instance that we'll use for constructing stuff $modelInstance = ModelHelper::getModel($view->modelName); $columns = Column::getColumns($modelInstance); $editFields = Field::getEditFields($modelInstance); $bundleConfig = Bundle::get('administrator'); //add the view fields $view->modelTitle = Config::get('administrator::administrator.models.' . $view->modelName . '.title', $view->modelName); $view->modelSingle = Config::get('administrator::administrator.models.' . $view->modelName . '.single', $view->modelTitle); $view->columns = $columns['columns']; $view->includedColumns = $columns['includedColumns']; $view->primaryKey = $modelInstance::$key; $view->sort = Sort::get($modelInstance)->toArray(); $view->rows = ModelHelper::getRows($modelInstance, $view->sort); $view->editFields = $editFields['arrayFields']; $view->dataModel = $editFields['dataModel']; $view->filters = ModelHelper::getFilters($modelInstance); $view->baseUrl = URL::to_route('admin_index'); $view->bundleHandles = $bundleConfig['handles']; $view->expandWidth = ModelHelper::getExpandWidth($modelInstance); $view->modelInstance = $modelInstance; $view->model = isset($view->model) ? $view->model : false; });
/** * Helper that builds a results array (with results and pagination info) * * @param object $model * @param array $sortOptions (with 'field' and 'direction' keys) * @param array $filters (see getFilters helper for the value types) */ public static function getRows($model, $sortOptions, $filters = null) { //get the columns and sort options $columns = Column::getColumns($model, false); $sort = Sort::get($model, $sortOptions['field'], $sortOptions['direction']); //get things going by grouping the set $query = $model::group_by($model->table() . '.' . $model::$key); //set up initial array states for the selects $selects = array(DB::raw($model->table() . '.' . $model::$key), DB::raw($model->table() . '.*')); //then we set the filters if ($filters && is_array($filters)) { foreach ($filters as $filter) { if (!($fieldObject = Field::get($filter['field'], $filter, $model))) { continue; } $fieldObject->filterQuery($query, $model); } } //determines if the sort should have the table prefixed to it $sortOnTable = true; //iterate over the columns to check if we need to join any values or add any extra columns foreach ($columns['columns'] as $field => $column) { //if this is a related column, we'll need to add some joins $column->filterQuery($query, $selects, $model); //if this is a related field or if (($column->isRelated || $column->select) && $column->field === $sort->field) { $sortOnTable = false; } } //if the sort is on the model's table, prefix the table name to it if ($sortOnTable) { $sort->field = $model->table() . '.' . $sort->field; } //if there is a global per page limit set, make sure the paginator uses that $per_page = $model->per_page() ? $model->per_page() : 20; $global_per_page = Config::get('administrator::administrator.global_per_page', NULL); if ($global_per_page && is_numeric($global_per_page)) { $per_page = $global_per_page; } /** * We need to do our own pagination since there is a bug (!!!!!!!!!!!!!!) in the L3 paginator when using groupings :( * When L4 is released, this problem will go away and we'll be able to use the paginator again * Trust me, I understand how ghetto this is. I also understand that it may not work too well on other drivers. Let me know... */ //first get the sql sans selects $sql = $query->table->grammar->select($query->table); //then we need to round out the inner select $sql = "SELECT {$model->table()}.{$model::$key} " . $sql; //then wrap the inner table and perform the count $sql = "SELECT COUNT({$model::$key}) AS aggregate FROM ({$sql}) AS agg"; //then perform the count query $results = $query->table->connection->query($sql, $query->table->bindings); $num_rows = $results[0]->aggregate; $page = (int) \Input::get('page', 1); $last = (int) ceil($num_rows / $per_page); //if the current page is greater than the last page, set the current page to the last page $page = $page > $last ? $last : $page; //now we need to limit and offset the rows in remembrance of our dear lost friend paginate() $query->take($per_page); $query->skip($per_page * ($page === 0 ? $page : $page - 1)); //order the set by the model table's id $query->order_by($sort->field, $sort->direction); //then retrieve the rows $rows = $query->distinct()->get($selects); $results = array(); //convert the resulting set into arrays foreach ($rows as $item) { //iterate over the included and related columns $onTableColumns = array_merge($columns['includedColumns'], $columns['relatedColumns']); $arr = array(); foreach ($onTableColumns as $field => $col) { $arr[$field] = $item->get_attribute($field); } //then grab the computed, unsortable columns foreach ($columns['computedColumns'] as $col) { $arr[$col] = $item->{$col}; } $results[] = $arr; } return array('page' => $page, 'last' => $last, 'total' => $num_rows, 'results' => $results); }
/** * The constructor takes a field, column array, and the associated Eloquent model * * @param array $config //the array of options provide in each model's config */ public function __construct($config) { //set the class properties for the items which we know to exist $this->title = array_get($config, 'title'); $this->single = array_get($config, 'single'); $this->model = array_get($config, 'model'); $this->columns = array_get($config, 'columns'); $this->actions = array_get($config, 'actions'); $this->edit = array_get($config, 'edit_fields'); $this->filters = array_get($config, 'filters', array()); $this->name = array_get($config, 'model_name'); //fetch the meaningful information for columns and actions //we won't do the same for edit fields and filters because that information is not always persistent across a request $this->columns = Column::getColumns($this); $this->actions = Action::getActions($this); //copy $this->model because of php syntax issues $model = $this->model; //now set the properties for other items //form width option $formWidth = array_get($config, 'form_width', $this->formWidth); if (!is_int($formWidth) || $formWidth < $this->formWidth) { $formWidth = $this->formWidth; } $this->formWidth = $formWidth; //sort options $this->sort = array_get($config, 'sort', array()); $this->setSort(); //get the rows per page $this->setRowsPerPage(); //grab the model link callback $linkCallback = array_get($config, 'link'); $this->linkCallback = is_callable($linkCallback) ? $linkCallback : null; //grab the action permissions, if supplied $actionPermissions = array_get($config, 'action_permissions', array()); $create = array_get($actionPermissions, 'create'); $delete = array_get($actionPermissions, 'delete'); $update = array_get($actionPermissions, 'update'); $this->actionPermissions['create'] = is_callable($create) ? $create() : true; $this->actionPermissions['delete'] = is_callable($delete) ? $delete() : true; $this->actionPermissions['update'] = is_callable($update) ? $update() : true; }