Index: DataGrid/Core.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/Core.php,v retrieving revision 1.29 diff -r1.29 Core.php 64a65,79 > * An array of the fields sorted by > */ > var $sortBy = array(); > > /** > * An array of the sort directions, keys correspond to keys in sortBy > */ > var $sortDir = array(); > > /** > * An array of fields to group by > */ > var $groups = array(); > > /** 322a338,349 > if (is_array($sortBy)) { > $this->sortBy = $sortBy; > $sortBy = $sortBy[0]; > } else { > $this->sortBy = array($sortBy); > } > if (is_array($direction)) { > $this->sortDir = $direction; > $direction = $direction[0]; > } else { > $this->sortDir = array($direction); > } 387a415,423 > > /** > * Add a field to the group list > * > * @param string the field to group by > */ > function addGroup($group) { > $this->groups[] = $group; > } Index: DataGrid/DataSource.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/DataSource.php,v retrieving revision 1.5 diff -r1.5 DataSource.php 407a408 > Index: DataGrid/Renderer.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/Renderer.php,v retrieving revision 1.22 diff -r1.22 Renderer.php 76a77,81 > > $sortBy = $this->sortBy; > if ($this->groups) { > $sortBy = array_merge($this->groups, $this->sortBy); > } 81,82c86,88 < $this->rowLimit, $this->sortArray[0], < $this->sortArray[1]); --- > $this->rowLimit, > $sortBy, > $this->sortDir); 142c148 < $arrayKeys = array_keys($this->recordSet[0]); --- > $arrayKeys = $this->_dataSource->_options['fields']; Index: DataGrid/DataSource/Array.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/DataSource/Array.php,v retrieving revision 1.14 diff -r1.14 Array.php 98,99c98,99 < $records =& $this->staticFetch($this->_ar, $this->_options['fields'], < $offset, $len, $sortField, $sortDir); --- > $records =& $this->staticFetch($this->_ar, $offset, > $len, $sortField, $sortDir); 109a110 > * @param array $ar The array to slice 116c117 < function &staticFetch($ar, $fieldList, $offset=0, $len=null, --- > function &staticFetch($ar, $offset=0, $len=null, 121,122c122 < Structures_DataGrid_DataSource_Array::sort($sortField, $sortDir, < $ar); --- > $this->sort($sortField, $sortDir, $ar); 132,148c132 < // Filter out fields that are to not be rendered < // < // With the new array_intersect_key() the following would be : < // $records = array_intersect_key($slice, array_flip ($fieldList)); < // One line... And faster... But this function is cvs-only. < $records = array(); < foreach ($slice as $rec) { < $buf = array(); < foreach ($rec as $key => $val) { < if (in_array($key, $fieldList)) { < $buf[$key] = $val; < } < } < $records[] = $buf; < } < < return $records; --- > return $slice; 160c144 < function sort($sortField, $sortDir, $ar = array()) --- > function sort($sortFields, $sortDirs, $ar = array()) 161a146,151 > if (!is_array($sortFields)) { > $sortFields = array($sortFields); > } > if (!is_array($sortDirs)) { > $sortDirs = array($sortDirs); > } 166,169c156,195 < < $sortAr = array(); < for ($i = 0; $i < $numRows; $i++) { < $sortAr[$i] = $ar[$i][$sortField]; --- > > $sorted = array(); > $this->_sortColumn = $sortColumn = array_shift($sortFields); > if ($sortDirs) { > $this->_sortDir = $sortDir = array_shift($sortDirs); > } else { > $this->_sortDir = $sortDir = 'ASC'; > } > usort($ar, array(&$this, '_compare')); > if (!$sortFields) { > return $ar; > } > $toSort = array(); > $lastValue = null; > foreach ($ar as $rec) { > if ($lastValue != $rec[$sortColumn] && $toSort) { > $sorted = array_merge($sorted, $this->sort($sortFields, $sortDirs, $toSort)); > $toSort = array(); > } > $toSort[] = $rec; > $lastValue = $rec[$sortColumn]; > } > if ($toSort) { > $sorted = array_merge($sorted, $this->sort($sortFields, $sortDirs, $toSort)); > } > return $sorted; > } > > /** > * Internal function used to sort an array by a certain column > * > * @var Array a record > * @var Array a record > * @return int same as strnatcasecmp for the sorting column in the records > */ > function _compare($a, $b) { > if ($this->_sortDir == 'ASC') { > return strnatcasecmp($a[$this->_sortColumn], $b[$this->_sortColumn]); > } else { > return strnatcasecmp($b[$this->_sortColumn], $a[$this->_sortColumn]); 171,172d196 < $sortDir = strtoupper($sortDir) == 'ASC' ? SORT_ASC : SORT_DESC; < array_multisort($sortAr, $sortDir, $ar); Index: DataGrid/DataSource/DB.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/DataSource/DB.php,v retrieving revision 1.13 diff -r1.13 DB.php 36c36 < class Structures_DataGrid_DataSource_DB extends Structures_DataGrid_DataSource --- > class Structures_DataGrid_DataSource_DB extends Structures_DataGrid_DataSource_Array 53c53 < parent::Structures_DataGrid_DataSource(); --- > parent::Structures_DataGrid_DataSource_Array(); 103,105c103,104 < $recordSet =& Structures_DataGrid_DataSource_Array::staticFetch( < $recordSet, $this->_options['fields'], $offset, < $limit, $sortField, $sortDir); --- > $recordSet =& $this->staticFetch($recordSet, $offset, > $limit, $sortField, $sortDir); Index: DataGrid/DataSource/DataObject.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/DataSource/DataObject.php,v retrieving revision 1.21 diff -r1.21 DataObject.php 141,144c141,143 < and $labelsVar = $this->_options['labels_property'] < and isset($this->_dataobject->$labelsVar)) { < < $mergeOptions['labels'] = $this->_dataobject->$labelsVar; --- > && $this->_options['labels_property'] > && isset($this->_dataobject->{$this->_options['labels_property']})) { > $mergeOptions['labels'] = $this->_dataobject->{$this->_options['labels_property']}; 208,219c207,214 < while ($this->_dataobject->fetch()) { < // Determine Fields < if (!$this->_options['fields']) { < if ($this->_options['use_private_vars']) { < $this->_options['fields'] = < array_keys(get_object_vars($this->_dataobject)); < } else { < $this->_options['fields'] = < array_keys($this->_dataobject->toArray()); < } < //$this->_options['fields'] = < // array_filter(array_keys(get_object_vars($this->_dataobject)), array(&$this, '_fieldsFilter')); --- > // Determine Fields > if (!$this->_options['fields']) { > if ($this->_options['use_private_vars']) { > $this->_options['fields'] = > array_keys(get_object_vars($this->_dataobject)); > } else { > $this->_options['fields'] = > array_keys($this->_dataobject->toArray()); 221c216,221 < $fieldList = $this->_options['fields']; --- > //$this->_options['fields'] = > // array_filter(array_keys(get_object_vars($this->_dataobject)), array(&$this, '_fieldsFilter')); > } > $this->_options['getFields'] = array_filter(array_keys(get_object_vars($this->_dataobject)), > array(&$this, '_fieldsFilter')); > while ($this->_dataobject->fetch()) { 224c224 < foreach ($fieldList as $fName) { --- > foreach ($this->_options['getFields'] as $fName) { 285c285 < function sort($sortField, $sortDir = null) --- > function sort($sortFields, $sortDirs = null) 287,288c287,303 < if ($sortDir === null) { < $this->_dataobject->orderBy($sortField); --- > if (is_array($sortFields)) { > $sort = ''; > foreach ($sortFields as $sortField) { > if ($sort) { > $sort .= ', '; > } > if ($sortDirs) { > if (is_array($sortDirs)) { > $sortDir = ' '.array_shift($sortDirs); > } else { > $sortDir = ' '.$sortDirs; > } > } else { > $sortDir = ''; > } > $sort .= $sortField.$sortDir; > } 290c305,309 < $this->_dataobject->orderBy($sortField . ' ' . $sortDir); --- > if ($sortDirs === null) { > $sort = $sortFields; > } else { > $sort = $sortFields . ' ' . $sortDirs; > } 291a311,312 > $this->_dataobject->orderBy(); > $this->_dataobject->orderBy($sort); Index: DataGrid/Renderer/HTMLTable.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/Renderer/HTMLTable.php,v retrieving revision 1.50 diff -r1.50 HTMLTable.php 246c246 < return $table->toHTML(); --- > return $this->getJs().$table->toHTML(); 247a248,426 > > function getJs() { > static $firstCall = true; > if ($firstCall) { > $firstCall = false; > return ' > > '; > } else { > return ''; > } > } 310c489,490 < $cnt = 0; --- > //start at group count, first cells of records will start at this column due to vertical group spacers > $cnt = count($this->_dg->groups); 366,367d545 < $iconVar = "sortIcon" . < ($this->_dg->sortArray[1] ? $this->_dg->sortArray[1] : 'ASC'); 369,371c547,561 < if (($this->$iconVar != '') && < ($this->_dg->sortArray[0] == $column->orderBy)) { < $str .= ' ' . $this->$iconVar; --- > > //if this column is sorted on > $pos = array_search($column->orderBy, $this->_dg->sortBy); > if ($pos !== false) { > > //if a direction is set use it, otherwise assume ascending > $iconVar = 'sortIcon' . > (isset($this->_dg->sortDir[$pos]) ? $this->_dg->sortDir[$pos] : 'ASC'); > > //if we have an icon > if (isset($this->$iconVar) && $this->$iconVar !== '') { > > //set up the icon, if we're sorting by multiple columns then put the # of the sort in the sequence in parens > $str .= ' ' . $this->$iconVar.(sizeof($this->_dg->sortBy) > 1 ? '('.($pos + 1).')' : ''); > } 380,381c570,577 < $this->_table->setHeaderContents(0, $cnt, $str); < $this->_table->setCellAttributes(0, $cnt, $column->attribs); --- > if ($cnt == count($this->_dg->groups) && $cnt > 0) { > $this->_table->setHeaderContents(0, 0, $str); > $this->_table->setCellAttributes(0, 0, $column->attribs); > $this->_table->updateCellAttributes(0, 0, array('colspan' => count($this->_dg->groups) + 1)); > } else { > $this->_table->setHeaderContents(0, $cnt, $str); > $this->_table->setCellAttributes(0, $cnt, $column->attribs); > } 417a614,617 > if ($this->_dg->groups) { > $oldVal = array(); > } > 418a619 > $groupHeaders = array(); 422c623,638 < $cnt = 0; --- > if ($this->_dg->groups) { > foreach ($this->_dg->groups as $num => $group) { > if (!isset($oldVal[$group]) || $oldVal[$group] !== $this->_dg->recordSet[$i][$group]) { > $this->_table->setHeaderContents($rowCnt, $num, $this->_dg->recordSet[$i][$group]); > $this->_table->updateCellAttributes($rowCnt, $num, array('onclick' => 'collapseGroup(this)', > 'style' => 'cursor: pointer; cursor: hand;', > 'colspan' => count($this->_dg->columnSet) - $num + count($this->_dg->groups))); > $this->_table->updateRowAttributes($rowCnt, array('class' => 'groupHeader'.$num), > false); > $groupHeaders[$rowCnt] = $num; > ++$rowCnt; > $oldVal[$group] = $this->_dg->recordSet[$i][$group]; > } > } > } > $cnt = count($this->_dg->groups); 468a685,697 > foreach ($groupHeaders as $row => $num) { > $end = $rowCnt; > foreach ($groupHeaders as $row2 => $num2) { > if ($row2 > $row && $num2 <= $num) { > $end = $row2; > break; > } > } > $this->_table->setCellAttributes($row + 1, $num, array('rowspan' => $end - $row - 1, > 'class' => 'groupHeader'.$num)); > $this->_table->setCellContents($row + 1, $num, ' ', 'TH'); > } > //$this->_table->setColCount($cnt);