codespell: CRM/*
[civicrm-core.git] / CRM / Utils / Sort.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
e7112fa7 31 * @copyright CiviCRM LLC (c) 2004-2015
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
e7112fa7 44 * @copyright CiviCRM LLC (c) 2004-2015
6a488035
TO
45 * $Id$
46 *
47 */
48class CRM_Utils_Sort {
49
50 /**
100fef9d 51 * Constants to determine what direction each variable
6a488035
TO
52 * is to be sorted
53 *
54 * @var int
55 */
7da04cde 56 const ASCENDING = 1, DESCENDING = 2, DONTCARE = 4,
6a488035 57
353ffa53
TO
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';
6a488035
TO
64
65 /**
100fef9d 66 * Name of the sort function. Used to isolate session variables
6a488035
TO
67 * @var string
68 */
69 protected $_name;
70
71 /**
100fef9d 72 * Array of variables that influence the query
6a488035
TO
73 *
74 * @var array
75 */
76 public $_vars;
77
78 /**
100fef9d 79 * The newly formulated base url to be used as links
6a488035
TO
80 * for various table elements
81 *
82 * @var string
83 */
84 protected $_link;
85
86 /**
100fef9d 87 * What's the name of the sort variable in a REQUEST
6a488035
TO
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 *
77855840
TO
119 * @param mixed $vars
120 * Assoc array as described above.
121 * @param string $defaultSortOrder
122 * Order to sort.
6a488035 123 *
f4aaa82a 124 * @return \CRM_Utils_Sort
450f494d 125 */
00be9182 126 public function __construct(&$vars, $defaultSortOrder = NULL) {
6a488035
TO
127 $this->_vars = array();
128 $this->_response = array();
129
130 foreach ($vars as $weight => $value) {
131 $this->_vars[$weight] = array(
132 'name' => $value['sort'],
133 'direction' => CRM_Utils_Array::value('direction', $value),
134 'title' => $value['name'],
135 );
136 }
137
138 $this->_currentSortID = 1;
139 if (isset($this->_vars[$this->_currentSortID])) {
140 $this->_currentSortDirection = $this->_vars[$this->_currentSortID]['direction'];
141 }
142 $this->_urlVar = self::SORT_ID;
5340376b 143 $this->_link = CRM_Utils_System::makeURL($this->_urlVar, TRUE);
6a488035
TO
144
145 $this->initialize($defaultSortOrder);
146 }
147
148 /**
fe482240 149 * Function returns the string for the order by clause.
6a488035 150 *
a6c01b45
CW
151 * @return string
152 * the order by clause
6a488035 153 */
00be9182 154 public function orderBy() {
a7488080 155 if (empty($this->_vars[$this->_currentSortID])) {
6a488035
TO
156 return '';
157 }
158
159 if ($this->_vars[$this->_currentSortID]['direction'] == self::ASCENDING ||
160 $this->_vars[$this->_currentSortID]['direction'] == self::DONTCARE
161 ) {
162 $this->_vars[$this->_currentSortID]['name'] = str_replace(' ', '_', $this->_vars[$this->_currentSortID]['name']);
163 return $this->_vars[$this->_currentSortID]['name'] . ' asc';
164 }
165 else {
166 $this->_vars[$this->_currentSortID]['name'] = str_replace(' ', '_', $this->_vars[$this->_currentSortID]['name']);
167 return $this->_vars[$this->_currentSortID]['name'] . ' desc';
168 }
169 }
170
171 /**
fe482240 172 * Create the sortID string to be used in the GET param.
6a488035 173 *
77855840
TO
174 * @param int $index
175 * The field index.
176 * @param int $dir
177 * The direction of the sort.
6a488035 178 *
a6c01b45
CW
179 * @return string
180 * the string to append to the url
6a488035 181 */
00be9182 182 public static function sortIDValue($index, $dir) {
6a488035
TO
183 return ($dir == self::DESCENDING) ? $index . '_d' : $index . '_u';
184 }
185
186 /**
fe482240 187 * Init the sort ID values in the object.
6a488035 188 *
77855840
TO
189 * @param string $defaultSortOrder
190 * The sort order to use by default.
6a488035 191 *
72b3a70c 192 * @return void
6a488035 193 */
00be9182 194 public function initSortID($defaultSortOrder) {
6a488035
TO
195 $url = CRM_Utils_Array::value(self::SORT_ID, $_GET, $defaultSortOrder);
196
197 if (empty($url)) {
198 return;
199 }
200
201 list($current, $direction) = explode('_', $url);
202
b44e3f84 203 // if current is weird and does not exist in the vars array, skip
6a488035
TO
204 if (!array_key_exists($current, $this->_vars)) {
205 return;
206 }
207
208 if ($direction == 'u') {
209 $direction = self::ASCENDING;
210 }
211 elseif ($direction == 'd') {
212 $direction = self::DESCENDING;
213 }
214 else {
215 $direction = self::DONTCARE;
216 }
217
218 $this->_currentSortID = $current;
219 $this->_currentSortDirection = $direction;
220 $this->_vars[$current]['direction'] = $direction;
221 }
222
223 /**
fe482240 224 * Init the object.
6a488035 225 *
77855840
TO
226 * @param string $defaultSortOrder
227 * The sort order to use by default.
6a488035
TO
228 *
229 * @return void
6a488035 230 */
00be9182 231 public function initialize($defaultSortOrder) {
6a488035
TO
232 $this->initSortID($defaultSortOrder);
233
234 $this->_response = array();
235
236 $current = $this->_currentSortID;
237 foreach ($this->_vars as $index => $item) {
238 $name = $item['name'];
239 $this->_response[$name] = array();
240
241 $newDirection = ($item['direction'] == self::ASCENDING) ? self::DESCENDING : self::ASCENDING;
242
243 if ($current == $index) {
244 if ($item['direction'] == self::ASCENDING) {
245 $class = 'sorting_asc';
246 }
247 else {
248 $class = 'sorting_desc';
249 }
250 }
251 else {
252 $class = 'sorting';
253 }
254
255 $this->_response[$name]['link'] = '<a href="' . $this->_link . $this->sortIDValue($index, $newDirection) . '" class="' . $class . '">' . $item['title'] . '</a>';
256 }
257 }
258
259 /**
fe482240 260 * Getter for currentSortID.
6a488035 261 *
a6c01b45
CW
262 * @return int
263 * returns of the current sort id
6a488035
TO
264 * @acccess public
265 */
00be9182 266 public function getCurrentSortID() {
6a488035
TO
267 return $this->_currentSortID;
268 }
269
270 /**
fe482240 271 * Getter for currentSortDirection.
6a488035 272 *
a6c01b45
CW
273 * @return int
274 * returns of the current sort direction
6a488035
TO
275 * @acccess public
276 */
00be9182 277 public function getCurrentSortDirection() {
6a488035
TO
278 return $this->_currentSortDirection;
279 }
280
281 /**
ac51fa38 282 * Universal callback function for sorting by weight, id, title or name
6a488035 283 *
f4aaa82a
EM
284 * @param $a
285 * @param $b
286 *
a6c01b45
CW
287 * @return int
288 * (-1 or 1)
6a488035 289 */
00be9182 290 public static function cmpFunc($a, $b) {
ac51fa38 291 $cmp_order = array('weight', 'id', 'title', 'name');
292 foreach ($cmp_order as $attribute) {
293 if (isset($a[$attribute]) && isset($b[$attribute])) {
294 if ($a[$attribute] < $b[$attribute]) {
295 return -1;
0db6c3e1
TO
296 }
297 elseif ($a[$attribute] > $b[$attribute]) {
ac51fa38 298 return 1;
299 } // else: $a and $b are equal wrt to this attribute, try next...
1d45f936 300 }
e39d4fad 301 }
ac51fa38 302 // if we get here, $a and $b es equal for all we know
303 // however, as I understand we don't want equality here:
304 return -1;
6a488035 305 }
96025800 306
6a488035 307}