order items alphabetically if weights are the same
[civicrm-core.git] / CRM / Utils / Sort.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 *
38 * Base class to provide generic sort functionality. Note that some ideas
39 * have been borrowed from the drupal tablesort.inc code. Also note that
40 * since the Pager and Sort class are similar, do match the function names
41 * if introducing additional functionality
42 *
43 * @package CRM
06b69b18 44 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
45 * $Id$
46 *
47 */
48class CRM_Utils_Sort {
49
50 /**
51 * constants to determine what direction each variable
52 * is to be sorted
53 *
54 * @var int
55 */
56 CONST ASCENDING = 1, DESCENDING = 2, DONTCARE = 4,
57
58 /**
59 * the name for the sort GET/POST param
60 *
61 * @var string
62 */
63 SORT_ID = 'crmSID', SORT_DIRECTION = 'crmSortDirection', SORT_ORDER = 'crmSortOrder';
64
65 /**
66 * name of the sort function. Used to isolate session variables
67 * @var string
68 */
69 protected $_name;
70
71 /**
72 * array of variables that influence the query
73 *
74 * @var array
75 */
76 public $_vars;
77
78 /**
79 * the newly formulated base url to be used as links
80 * for various table elements
81 *
82 * @var string
83 */
84 protected $_link;
85
86 /**
87 * what's the name of the sort variable in a REQUEST
88 *
89 * @var string
90 */
91 protected $_urlVar;
92
93 /**
94 * What variable are we currently sorting on
95 *
96 * @var string
97 */
98 protected $_currentSortID;
99
100 /**
101 * What direction are we sorting on
102 *
103 * @var string
104 */
105 protected $_currentSortDirection;
106
107 /**
108 * The output generated for the current form
109 *
110 * @var array
111 */
112 public $_response;
113
114 /**
115 * The constructor takes an assoc array
116 * key names of variable (which should be the same as the column name)
117 * value: ascending or descending
118 *
f4aaa82a 119 * @param mixed $vars - assoc array as described above
6a488035
TO
120 * @param string $defaultSortOrder - order to sort
121 *
f4aaa82a
EM
122 * @return \CRM_Utils_Sort
123 @access public
450f494d 124 */
6a488035
TO
125 function __construct(&$vars, $defaultSortOrder = NULL) {
126 $this->_vars = array();
127 $this->_response = array();
128
129 foreach ($vars as $weight => $value) {
130 $this->_vars[$weight] = array(
131 'name' => $value['sort'],
132 'direction' => CRM_Utils_Array::value('direction', $value),
133 'title' => $value['name'],
134 );
135 }
136
137 $this->_currentSortID = 1;
138 if (isset($this->_vars[$this->_currentSortID])) {
139 $this->_currentSortDirection = $this->_vars[$this->_currentSortID]['direction'];
140 }
141 $this->_urlVar = self::SORT_ID;
5340376b 142 $this->_link = CRM_Utils_System::makeURL($this->_urlVar, TRUE);
6a488035
TO
143
144 $this->initialize($defaultSortOrder);
145 }
146
147 /**
148 * Function returns the string for the order by clause
149 *
150 * @return string the order by clause
151 * @access public
152 */
153 function orderBy() {
a7488080 154 if (empty($this->_vars[$this->_currentSortID])) {
6a488035
TO
155 return '';
156 }
157
158 if ($this->_vars[$this->_currentSortID]['direction'] == self::ASCENDING ||
159 $this->_vars[$this->_currentSortID]['direction'] == self::DONTCARE
160 ) {
161 $this->_vars[$this->_currentSortID]['name'] = str_replace(' ', '_', $this->_vars[$this->_currentSortID]['name']);
162 return $this->_vars[$this->_currentSortID]['name'] . ' asc';
163 }
164 else {
165 $this->_vars[$this->_currentSortID]['name'] = str_replace(' ', '_', $this->_vars[$this->_currentSortID]['name']);
166 return $this->_vars[$this->_currentSortID]['name'] . ' desc';
167 }
168 }
169
170 /**
171 * create the sortID string to be used in the GET param
172 *
173 * @param int $index the field index
174 * @param int $dir the direction of the sort
175 *
176 * @return string the string to append to the url
177 * @static
178 * @access public
179 */
180 static function sortIDValue($index, $dir) {
181 return ($dir == self::DESCENDING) ? $index . '_d' : $index . '_u';
182 }
183
184 /**
185 * init the sort ID values in the object
186 *
187 * @param string $defaultSortOrder the sort order to use by default
188 *
189 * @return returns null if $url- (sort url) is not found
190 * @access public
191 */
192 function initSortID($defaultSortOrder) {
193 $url = CRM_Utils_Array::value(self::SORT_ID, $_GET, $defaultSortOrder);
194
195 if (empty($url)) {
196 return;
197 }
198
199 list($current, $direction) = explode('_', $url);
200
201 // if current is wierd and does not exist in the vars array, skip
202 if (!array_key_exists($current, $this->_vars)) {
203 return;
204 }
205
206 if ($direction == 'u') {
207 $direction = self::ASCENDING;
208 }
209 elseif ($direction == 'd') {
210 $direction = self::DESCENDING;
211 }
212 else {
213 $direction = self::DONTCARE;
214 }
215
216 $this->_currentSortID = $current;
217 $this->_currentSortDirection = $direction;
218 $this->_vars[$current]['direction'] = $direction;
219 }
220
221 /**
222 * init the object
223 *
224 * @param string $defaultSortOrder the sort order to use by default
225 *
226 * @return void
227 * @access public
228 */
229 function initialize($defaultSortOrder) {
230 $this->initSortID($defaultSortOrder);
231
232 $this->_response = array();
233
234 $current = $this->_currentSortID;
235 foreach ($this->_vars as $index => $item) {
236 $name = $item['name'];
237 $this->_response[$name] = array();
238
239 $newDirection = ($item['direction'] == self::ASCENDING) ? self::DESCENDING : self::ASCENDING;
240
241 if ($current == $index) {
242 if ($item['direction'] == self::ASCENDING) {
243 $class = 'sorting_asc';
244 }
245 else {
246 $class = 'sorting_desc';
247 }
248 }
249 else {
250 $class = 'sorting';
251 }
252
253 $this->_response[$name]['link'] = '<a href="' . $this->_link . $this->sortIDValue($index, $newDirection) . '" class="' . $class . '">' . $item['title'] . '</a>';
254 }
255 }
256
257 /**
258 * getter for currentSortID
259 *
260 * @return int returns of the current sort id
261 * @acccess public
262 */
263 function getCurrentSortID() {
264 return $this->_currentSortID;
265 }
266
267 /**
268 * getter for currentSortDirection
269 *
270 * @return int returns of the current sort direction
271 * @acccess public
272 */
273 function getCurrentSortDirection() {
274 return $this->_currentSortDirection;
275 }
276
277 /**
278 * Universal callback function for sorting by weight
279 *
f4aaa82a
EM
280 * @param $a
281 * @param $b
282 *
6a488035
TO
283 * @return array of items sorted by weight
284 * @access public
285 */
286 static function cmpFunc($a, $b) {
e39d4fad
NB
287 if($a['weight'] == $b['weight']) {
288 return strcmp($a['title'], $b['title']);
289 }
6a488035
TO
290 return ($a['weight'] <= $b['weight']) ? -1 : 1;
291 }
292}