Added automagic filtering capability to the app controller. Also, lumped all items needing serialization into a single 'post' item, instead of continuing to piecemeal each added post item. There will be some changes required to some controllers, since custom post data has changed location, but it should be minor. To make use of the new filtering methods, each view will have to set the 'filter' parameter at the time of grid setup.
git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@365 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -185,25 +185,21 @@ class AppController extends Controller {
|
||||
|
||||
// Unserialize our complex structure of fields
|
||||
// This SHOULD always be set, except when debugging
|
||||
if (isset($params['fields']))
|
||||
$params['fields'] = unserialize($params['fields']);
|
||||
else
|
||||
$params['fields'] = array($this->{$this->modelClass}->alias
|
||||
.'.'.
|
||||
$this->{$this->modelClass}->primarKey);
|
||||
if (isset($params['post']))
|
||||
$params['post'] = unserialize($params['post']);
|
||||
|
||||
// Unserialize the list of ids, if present.
|
||||
if (isset($params['custom']))
|
||||
$params['custom'] = unserialize($params['custom']);
|
||||
|
||||
// This SHOULD always be set, except when debugging
|
||||
if (!isset($params['post']['fields']))
|
||||
$params['post']['fields'] = array($this->{$this->modelClass}->alias
|
||||
.'.'.
|
||||
$this->{$this->modelClass}->primaryKey);
|
||||
|
||||
// Make sure the action parameter at least exists, and
|
||||
// promote it to the top level (since it drives the operation).
|
||||
if (isset($params['post']['action']))
|
||||
$params['action'] = $params['post']['action'];
|
||||
else
|
||||
$params['custom'] = null;
|
||||
|
||||
// Unserialize the list of ids, if present.
|
||||
if (isset($params['idlist']))
|
||||
$params['idlist'] = unserialize($params['idlist']);
|
||||
|
||||
// Make sure the action parameter at least exists
|
||||
if (!isset($params['action']))
|
||||
$params['action'] = null;
|
||||
}
|
||||
|
||||
@@ -227,12 +223,14 @@ class AppController extends Controller {
|
||||
|
||||
function gridDataCount(&$params, &$model) {
|
||||
// Establish the tables and conditions for counting
|
||||
$query = array_intersect_key($this->gridDataCountTables($params, $model),
|
||||
$query = array_intersect_key($this->gridDataCountTableSet($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Add in the conditions and grouping
|
||||
$query['conditions'] = $this->gridDataCountConditions($params, $model);
|
||||
$query['group'] = $this->gridDataCountGroup($params, $model);
|
||||
// Conditions for the count
|
||||
$query['conditions'] = $this->gridDataCountConditionSet($params, $model);
|
||||
|
||||
// Grouping (which would not be typical)
|
||||
$query['group'] = $this->gridDataCountGroup($params, $model);
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
$params['count_query'] = $query;
|
||||
@@ -250,11 +248,29 @@ class AppController extends Controller {
|
||||
return $this->gridDataTables($params, $model);
|
||||
}
|
||||
|
||||
function gridDataCountTableSet(&$params, &$model) {
|
||||
// Preliminary set of tables
|
||||
$query = array_intersect_key($this->gridDataCountTables($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
}
|
||||
|
||||
function gridDataCountConditions(&$params, &$model) {
|
||||
// Same conditions for counting as for retreiving
|
||||
return $this->gridDataConditions($params, $model);
|
||||
}
|
||||
|
||||
function gridDataCountConditionSet(&$params, &$model) {
|
||||
// Conditions for the count
|
||||
$conditions = $this->gridDataCountConditions($params, $model);
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||
}
|
||||
|
||||
function gridDataCountGroup(&$params, &$model) {
|
||||
// Grouping will screw up the count, since it
|
||||
// causes the results to be split into chunks
|
||||
@@ -265,6 +281,101 @@ class AppController extends Controller {
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData FILTERING
|
||||
*/
|
||||
|
||||
function gridDataFilterTables(&$params, &$model, $query) {
|
||||
if (isset($query['link']))
|
||||
$link = 'link';
|
||||
else
|
||||
$link = 'contain';
|
||||
|
||||
if (empty($params['post']['filter']))
|
||||
return $query;
|
||||
|
||||
foreach ($params['post']['filter'] AS $filter => $value) {
|
||||
if (preg_match("/\./", $filter)) {
|
||||
list($tbl, $id) = explode(".", $filter);
|
||||
}
|
||||
elseif (preg_match('/^(.*)_(id)$/', $filter, $matches)) {
|
||||
list($tbl, $id) = array_slice($matches, 1);
|
||||
}
|
||||
else {
|
||||
$tbl = $filter;
|
||||
$id = null;
|
||||
}
|
||||
|
||||
$table = $this->gridDataFilterTable($params, $model, $tbl);
|
||||
if (!$table || $table == $model->alias)
|
||||
continue;
|
||||
|
||||
// If the table is already part of the query, don't replace it
|
||||
if (isset($query[$link][$table]))
|
||||
continue;
|
||||
|
||||
$query[$link][$table]
|
||||
= $this->gridDataFilterTableConfig($params, $model, $table);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
function gridDataFilterConditions(&$params, &$model, $conditions) {
|
||||
if (empty($params['post']['filter']))
|
||||
return $conditions;
|
||||
|
||||
foreach ($params['post']['filter'] AS $filter => $value) {
|
||||
if (preg_match("/\./", $filter)) {
|
||||
list($tbl, $id) = explode(".", $filter);
|
||||
}
|
||||
elseif (preg_match('/^(.*)_(id)$/', $filter, $matches)) {
|
||||
list($tbl, $id) = array_slice($matches, 1);
|
||||
}
|
||||
else {
|
||||
$tbl = $filter;
|
||||
$id = null;
|
||||
}
|
||||
|
||||
$table = $this->gridDataFilterTable($params, $model, $tbl);
|
||||
if (!$table)
|
||||
continue;
|
||||
|
||||
$key = $this->gridDataFilterTableKey($params, $model, $table, $id);
|
||||
if (!$key)
|
||||
continue;
|
||||
|
||||
$conditions[]
|
||||
= $this->gridDataFilterTableCondition($params, $model, $table, $key, $value);
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataFilterTable(&$params, &$model, $table) {
|
||||
return Inflector::camelize($table);
|
||||
}
|
||||
|
||||
function gridDataFilterTableConfig(&$params, &$model, $table) {
|
||||
return array('fields' => array());
|
||||
}
|
||||
|
||||
function gridDataFilterTableKey(&$params, &$model, $table, $id) {
|
||||
// REVISIT <AP>: 20090722
|
||||
// When $id is null, we could instantiate the table,
|
||||
// and use the _actual_ primary key. However, I don't
|
||||
// expect that functionality to be used, and will just
|
||||
// stick with 'id' for now.
|
||||
return $id ? $id : 'id';
|
||||
}
|
||||
|
||||
function gridDataFilterTableCondition(&$params, &$model, $table, $key, $value) {
|
||||
return array("{$table}.{$key}" => $value);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData PAGINATION
|
||||
@@ -282,6 +393,7 @@ class AppController extends Controller {
|
||||
return compact('record_count', 'limit', 'page', 'start', 'total');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData RETREIVAL
|
||||
@@ -289,19 +401,25 @@ class AppController extends Controller {
|
||||
|
||||
function gridDataRecords(&$params, &$model, $pagination) {
|
||||
// Establish the tables for this query
|
||||
$query = array_intersect_key($this->gridDataTables($params, $model),
|
||||
$query = array_intersect_key($this->gridDataTableSet($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Add in the conditions and grouping
|
||||
$query['conditions'] = $this->gridDataConditions($params, $model);
|
||||
$query['group'] = $this->gridDataGroup($params, $model);
|
||||
// Specify the fields for the query
|
||||
$query['fields'] = $this->gridDataFields($params, $model);
|
||||
|
||||
// Grab the actual records taking pagination into account
|
||||
// Conditions of the query
|
||||
$query['conditions'] = $this->gridDataConditionSet($params, $model);
|
||||
|
||||
// Data record grouping
|
||||
$query['group'] = $this->gridDataGroup($params, $model);
|
||||
|
||||
// The subset of data based on pagination
|
||||
$query['limit'] = $this->gridDataLimit($params, $model, $pagination['start'], $pagination['limit']);
|
||||
|
||||
// Ordering based on user request
|
||||
$query['order'] = $this->gridDataOrder($params, $model,
|
||||
isset($params['sidx']) ? $params['sidx'] : null,
|
||||
isset($params['sord']) ? $params['sord'] : null);
|
||||
$query['limit'] = $this->gridDataLimit($params, $model, $pagination['start'], $pagination['limit']);
|
||||
$query['fields'] = $this->gridDataFields($params, $model);
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
$params['query'] = $query;
|
||||
@@ -317,6 +435,19 @@ class AppController extends Controller {
|
||||
return array('contain' => false);
|
||||
}
|
||||
|
||||
function gridDataTableSet(&$params, &$model) {
|
||||
// Preliminary set of tables
|
||||
$query = array_intersect_key($this->gridDataTables($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
$query = array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$searches = array();
|
||||
|
||||
@@ -368,6 +499,14 @@ class AppController extends Controller {
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataConditionSet(&$params, &$model) {
|
||||
// Conditions for record retrieval
|
||||
$conditions = $this->gridDataConditions($params, $model);
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
return null;
|
||||
}
|
||||
@@ -436,7 +575,7 @@ class AppController extends Controller {
|
||||
// in SQL. But, it works for now, so what the heck...
|
||||
|
||||
$subtotals = array();
|
||||
foreach ($params['fields'] AS $field) {
|
||||
foreach ($params['post']['fields'] AS $field) {
|
||||
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
||||
$subtotals[] = array('field' => $matches[1],
|
||||
'name' => $field,
|
||||
@@ -541,7 +680,7 @@ class AppController extends Controller {
|
||||
$id_field = 'grid_id';
|
||||
foreach ($records AS $record) {
|
||||
$this->gridDataOutputRecord($params, $model, $record,
|
||||
$record[$id_field], $params['fields']);
|
||||
$record[$id_field], $params['post']['fields']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,36 +69,30 @@ $url = $html->url(array('controller' => $controller,
|
||||
// Create extra parameters that jqGrid will pass to our
|
||||
// controller whenever data is requested.
|
||||
// 'fields' will allow the controller to return only the
|
||||
// requested fields, and in the right order. Since fields
|
||||
// is a complex structure (an array), we'll need to
|
||||
// serialize it first for transport over HTTP.
|
||||
// requested fields, and in the right order.
|
||||
$postData = array();
|
||||
$postData['fields'] = serialize(array_map(create_function('$col',
|
||||
'return $col["index"];'),
|
||||
array_values($jqGridColumns)));
|
||||
$postData['fields'] = array_map(create_function('$col',
|
||||
'return $col["index"];'),
|
||||
array_values($jqGridColumns));
|
||||
|
||||
// Determine if we're to be using a custom list, or if
|
||||
// the data will simply be action based.
|
||||
if (isset($custom_ids)) {
|
||||
if (!isset($action))
|
||||
$action = 'idlist';
|
||||
$postData['idlist'] = serialize($custom_ids);
|
||||
}
|
||||
elseif (!isset($action)) {
|
||||
$action = null;
|
||||
$postData['idlist'] = $custom_ids;
|
||||
}
|
||||
|
||||
if (isset($custom_post_data)) {
|
||||
$postData['custom'] = serialize($custom_post_data);
|
||||
}
|
||||
|
||||
// 'action' will ensure that the controller provides the
|
||||
// correct subset of data
|
||||
$postData['action'] = $action;
|
||||
|
||||
if (isset($nolinks)) {
|
||||
if (isset($nolinks))
|
||||
$postData['nolinks'] = true;
|
||||
}
|
||||
|
||||
// 'action' will ensure that the controller does the right thing
|
||||
// 'filter' allows the app controller to automagic filter
|
||||
// 'custom' is for use solely by derived controllers
|
||||
$postData['action'] = isset($action) ? $action : null;
|
||||
$postData['filter'] = isset($filter) ? $filter : null;
|
||||
$postData['custom'] = isset($custom_post_data) ? $custom_post_data : null;
|
||||
|
||||
|
||||
// Perform column customizations.
|
||||
// This will largely be based off of the 'formatter' parameter,
|
||||
@@ -196,7 +190,9 @@ $jqGrid_setup = array_merge
|
||||
(array('mtype' => 'GET',
|
||||
'datatype' => 'xml',
|
||||
'url' => $url,
|
||||
'postData' => $postData,
|
||||
// Since postData is a complex structure (an array), we'll
|
||||
// need to serialize it first for transport over HTTP.
|
||||
'postData' => array('post' => serialize($postData)),
|
||||
'colNames' => array_keys($jqGridColumns),
|
||||
'colModel' => array('--special' => $jqGridColumns),
|
||||
'height' => $height,
|
||||
|
||||
Reference in New Issue
Block a user