Simpletest Coverage - includes/tablesort.inc

1 <?php
2 // $Id: tablesort.inc,v 1.51 2009/05/22 11:33:17 dries Exp $
3
4 /**
5 * @file
6 * Functions to aid in the creation of sortable tables.
7 *
8 * All tables created with a call to theme('table') have the option of having
9 * column headers that the user can click on to sort the table by that column.
10 */
11
12
13 /**
14 * Query extender class for tablesort queries.
15 */
16 class TableSort extends SelectQueryExtender {
17
18 /**
19 * The array of fields that can be sorted by.
20 *
21 * @var array
22 */
23 protected $header = array();
24
25 public function execute() {
26 return $this->query->execute();
27 }
28
29 public function orderByHeader(Array $header) {
30 $this->header = $header;
31 $ts = $this->init();
32 if (!empty($ts['sql'])) {
33 // Based on code from db_escape_table(), but this can also contain a dot.
34 $field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']);
35
36 // Sort order can only be ASC or DESC.
37 $sort = drupal_strtoupper($ts['sort']);
38 $sort = in_array($sort, array('ASC', 'DESC')) ? $sort : '';
39 $this->orderBy($field, $sort);
40 }
41 return $this;
42 }
43
44 /**
45 * Initialize the table sort context.
46 */
47 protected function init() {
48 $ts = $this->order();
49 $ts['sort'] = $this->getSort();
50 $ts['query_string'] = $this->getQueryString();
51 return $ts;
52 }
53
54 /**
55 * Determine the current sort direction.
56 *
57 * @param $headers
58 * An array of column headers in the format described in theme_table().
59 * @return
60 * The current sort direction ("asc" or "desc").
61 */
62 protected function getSort() {
63 if (isset($_GET['sort'])) {
64 return ($_GET['sort'] == 'desc') ? 'desc' : 'asc';
65 }
66 // User has not specified a sort. Use default if specified; otherwise use "asc".
67 else {
68 foreach ($this->header as $header) {
69 if (is_array($header) && array_key_exists('sort', $header)) {
70 return $header['sort'];
71 }
72 }
73 }
74 return 'asc';
75 }
76
77 /**
78 * Compose a query string to append to table sorting requests.
79 *
80 * @return
81 * A query string that consists of all components of the current page request
82 * except for those pertaining to table sorting.
83 */
84 protected function getQueryString() {
85 return drupal_query_string_encode($_REQUEST, array_merge(array('q', 'sort', 'order'), array_keys($_COOKIE)));
86 }
87
88 /**
89 * Determine the current sort criterion.
90 *
91 * @param $headers
92 * An array of column headers in the format described in theme_table().
93 * @return
94 * An associative array describing the criterion, containing the keys:
95 * - "name": The localized title of the table column.
96 * - "sql": The name of the database field to sort on.
97 */
98 protected function order() {
99 $order = isset($_GET['order']) ? $_GET['order'] : '';
100 foreach ($this->header as $header) {
101 if (isset($header['data']) && $order == $header['data']) {
102 return array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
103 }
104
105 if (isset($header['sort']) && ($header['sort'] == 'asc' || $header['sort'] == 'desc')) {
106 $default = array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
107 }
108 }
109
110 if (isset($default)) {
111 return $default;
112 }
113 else {
114 // The first column specified is initial 'order by' field unless otherwise specified
115 if (is_array($this->header[0])) {
116 $this->header[0] += array('data' => NULL, 'field' => NULL);
117 return array('name' => $this->header[0]['data'], 'sql' => $this->header[0]['field']);
118 }
119 else {
120 return array('name' => $this->header[0]);
121 }
122 }
123 }
124 }
125
126 /**
127 * Initialize the table sort context.
128 */
129 function tablesort_init($header) {
130 $ts = tablesort_get_order($header);
131 $ts['sort'] = tablesort_get_sort($header);
132 $ts['query_string'] = tablesort_get_querystring();
133 return $ts;
134 }
135
136 /**
137 * Create an SQL sort clause.
138 *
139 * This function produces the ORDER BY clause to insert in your SQL queries,
140 * assuring that the returned database table rows match the sort order chosen
141 * by the user.
142 *
143 * @param $header
144 * An array of column headers in the format described in theme_table().
145 * @param $before
146 * An SQL string to insert after ORDER BY and before the table sorting code.
147 * Useful for sorting by important attributes like "sticky" first.
148 * @return
149 * An SQL string to append to the end of a query.
150 *
151 * @ingroup database
152 */
153 function tablesort_sql($header, $before = '') {
154 $ts = tablesort_init($header);
155 if ($ts['sql']) {
156 // Based on code from db_escape_table(), but this can also contain a dot.
157 $field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']);
158
159 // Sort order can only be ASC or DESC.
160 $sort = drupal_strtoupper($ts['sort']);
161 $sort = in_array($sort, array('ASC', 'DESC')) ? $sort : '';
162
163 return " ORDER BY $before $field $sort";
164 }
165 }
166
167 /**
168 * Format a column header.
169 *
170 * If the cell in question is the column header for the current sort criterion,
171 * it gets special formatting. All possible sort criteria become links.
172 *
173 * @param $cell
174 * The cell to format.
175 * @param $header
176 * An array of column headers in the format described in theme_table().
177 * @param $ts
178 * The current table sort context as returned from tablesort_init().
179 * @return
180 * A properly formatted cell, ready for _theme_table_cell().
181 */
182 function tablesort_header($cell, $header, $ts) {
183 // Special formatting for the currently sorted column header.
184 if (is_array($cell) && isset($cell['field'])) {
185 $title = t('sort by @s', array('@s' => $cell['data']));
186 if ($cell['data'] == $ts['name']) {
187 $ts['sort'] = (($ts['sort'] == 'asc') ? 'desc' : 'asc');
188 if (isset($cell['class'])) {
189 $cell['class'] .= ' active';
190 }
191 else {
192 $cell['class'] = 'active';
193 }
194 $image = theme('tablesort_indicator', $ts['sort']);
195 }
196 else {
197 // If the user clicks a different header, we want to sort ascending initially.
198 $ts['sort'] = 'asc';
199 $image = '';
200 }
201
202 if (!empty($ts['query_string'])) {
203 $ts['query_string'] = '&' . $ts['query_string'];
204 }
205 $cell['data'] = l($cell['data'] . $image, $_GET['q'], array('attributes' => array('title' => $title), 'query' => 'sort=' . $ts['sort'] . '&order=' . urlencode($cell['data']) . $ts['query_string'], 'html' => TRUE));
206
207 unset($cell['field'], $cell['sort']);
208 }
209 return $cell;
210 }
211
212 /**
213 * Format a table cell.
214 *
215 * Adds a class attribute to all cells in the currently active column.
216 *
217 * @param $cell
218 * The cell to format.
219 * @param $header
220 * An array of column headers in the format described in theme_table().
221 * @param $ts
222 * The current table sort context as returned from tablesort_init().
223 * @param $i
224 * The index of the cell's table column.
225 * @return
226 * A properly formatted cell, ready for _theme_table_cell().
227 */
228 function tablesort_cell($cell, $header, $ts, $i) {
229 if (isset($header[$i]['data']) && $header[$i]['data'] == $ts['name'] && !empty($header[$i]['field'])) {
230 if (is_array($cell)) {
231 if (isset($cell['class'])) {
232 $cell['class'] .= ' active';
233 }
234 else {
235 $cell['class'] = 'active';
236 }
237 }
238 else {
239 $cell = array('data' => $cell, 'class' => 'active');
240 }
241 }
242 return $cell;
243 }
244
245 /**
246 * Compose a query string to append to table sorting requests.
247 *
248 * @return
249 * A query string that consists of all components of the current page request
250 * except for those pertaining to table sorting.
251 */
252 function tablesort_get_querystring() {
253 return drupal_query_string_encode($_REQUEST, array_merge(array('q', 'sort', 'order'), array_keys($_COOKIE)));
254 }
255
256 /**
257 * Determine the current sort criterion.
258 *
259 * @param $headers
260 * An array of column headers in the format described in theme_table().
261 * @return
262 * An associative array describing the criterion, containing the keys:
263 * - "name": The localized title of the table column.
264 * - "sql": The name of the database field to sort on.
265 */
266 function tablesort_get_order($headers) {
267 $order = isset($_GET['order']) ? $_GET['order'] : '';
268 foreach ($headers as $header) {
269 if (isset($header['data']) && $order == $header['data']) {
270 return array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
271 }
272
273 if (isset($header['sort']) && ($header['sort'] == 'asc' || $header['sort'] == 'desc')) {
274 $default = array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
275 }
276 }
277
278 if (isset($default)) {
279 return $default;
280 }
281 else {
282 // The first column specified is the initial 'order by' field unless otherwise specified.
283 $first = current($headers);
284 if (is_array($first)) {
285 $first += array('data' => NULL, 'field' => NULL);
286 return array('name' => $first['data'], 'sql' => $first['field']);
287 }
288 else {
289 return array('name' => $first, 'sql' => '');
290 }
291 }
292 }
293
294 /**
295 * Determine the current sort direction.
296 *
297 * @param $headers
298 * An array of column headers in the format described in theme_table().
299 * @return
300 * The current sort direction ("asc" or "desc").
301 */
302 function tablesort_get_sort($headers) {
303 if (isset($_GET['sort'])) {
304 return ($_GET['sort'] == 'desc') ? 'desc' : 'asc';
305 }
306 // User has not specified a sort. Use default if specified; otherwise use "asc".
307 else {
308 foreach ($headers as $header) {
309 if (is_array($header) && array_key_exists('sort', $header)) {
310 return $header['sort'];
311 }
312 }
313 }
314 return 'asc';
315 }
316

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.