tablesort.inc 5.81 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
2
// $Id$
Dries's avatar
 
Dries committed
3

4
5
6
7
8
9
10
11
12
13
14
/**
 * @file
 * Functions to aid in the creation of sortable tables.
 *
 * All tables created with a call to theme('table') have the option of having
 * column headers that the user can click on to sort the table by that column.
 */

/**
 * Initialize the table sort context.
 */
Dries's avatar
Dries committed
15
16
17
18
function tablesort_init($header) {
  $ts = tablesort_get_order($header);
  $ts['sort'] = tablesort_get_sort($header);
  $ts['query_string'] = tablesort_get_querystring();
Dries's avatar
 
Dries committed
19
20
21
  return $ts;
}

22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * Create an SQL sort clause.
 *
 * This function produces the ORDER BY clause to insert in your SQL queries,
 * assuring that the returned database table rows match the sort order chosen
 * by the user.
 *
 * @param $header
 *   An array of column headers in the format described in theme_table().
 * @param $before
 *   An SQL string to insert after ORDER BY and before the table sorting code.
 *   Useful for sorting by important attributes like "sticky" first.
 * @return
 *   An SQL string to append to the end of a query.
Dries's avatar
   
Dries committed
36
37
 *
 * @ingroup database
38
 */
Dries's avatar
Dries committed
39
40
function tablesort_sql($header, $before = '') {
  $ts = tablesort_init($header);
41
  if ($ts['sql']) {
Dries's avatar
   
Dries committed
42
    $sql = db_escape_string($ts['sql']);
43
    $sort = drupal_strtoupper(db_escape_string($ts['sort']));
Dries's avatar
   
Dries committed
44
    return " ORDER BY $before $sql $sort";
45
  }
Dries's avatar
 
Dries committed
46
47
}

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
 * Format a column header.
 *
 * If the cell in question is the column header for the current sort criterion,
 * it gets special formatting. All possible sort criteria become links.
 *
 * @param $cell
 *   The cell to format.
 * @param $header
 *   An array of column headers in the format described in theme_table().
 * @param $ts
 *   The current table sort context as returned from tablesort_init().
 * @return
 *   A properly formatted cell, ready for _theme_table_cell().
 */
63
function tablesort_header($cell, $header, $ts) {
64
  // Special formatting for the currently sorted column header.
65
  if (is_array($cell) && isset($cell['field'])) {
66
    $title = t('sort by @s', array('@s' => $cell['data']));
67
68
    if ($cell['data'] == $ts['name']) {
      $ts['sort'] = (($ts['sort'] == 'asc') ? 'desc' : 'asc');
69
70
71
72
73
74
      if (isset($cell['class'])) {
        $cell['class'] .= ' active';
      }
      else {
        $cell['class'] = 'active';
      }
75
      $image = theme('tablesort_indicator', $ts['sort']);
76
77
78
79
    }
    else {
      // If the user clicks a different header, we want to sort ascending initially.
      $ts['sort'] = 'asc';
80
      $image = '';
81
    }
82
83
84
85

    if (!empty($ts['query_string'])) {
      $ts['query_string'] = '&'. $ts['query_string'];
    }
86
    $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));
Dries's avatar
   
Dries committed
87

88
89
90
91
    unset($cell['field'], $cell['sort']);
  }
  return $cell;
}
Dries's avatar
   
Dries committed
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
 * Format a table cell.
 *
 * Adds a class attribute to all cells in the currently active column.
 *
 * @param $cell
 *   The cell to format.
 * @param $header
 *   An array of column headers in the format described in theme_table().
 * @param $ts
 *   The current table sort context as returned from tablesort_init().
 * @param $i
 *   The index of the cell's table column.
 * @return
 *   A properly formatted cell, ready for _theme_table_cell().
 */
109
function tablesort_cell($cell, $header, $ts, $i) {
110
  if (isset($header[$i]['data']) && $header[$i]['data'] == $ts['name'] && !empty($header[$i]['field'])) {
111
    if (is_array($cell)) {
112
113
114
115
116
117
      if (isset($cell['class'])) {
        $cell['class'] .= ' active';
      }
      else {
        $cell['class'] = 'active';
      }
118
119
120
121
122
    }
    else {
      $cell = array('data' => $cell, 'class' => 'active');
    }
  }
Dries's avatar
 
Dries committed
123
124
125
  return $cell;
}

126
127
128
129
130
131
132
/**
 * Compose a query string to append to table sorting requests.
 *
 * @return
 *   A query string that consists of all components of the current page request
 *   except for those pertaining to table sorting.
 */
Dries's avatar
Dries committed
133
134
function tablesort_get_querystring() {
  return drupal_query_string_encode($_REQUEST, array_merge(array('q', 'sort', 'order'), array_keys($_COOKIE)));
Dries's avatar
 
Dries committed
135
136
}

137
138
139
140
141
142
143
144
145
146
/**
 * Determine the current sort criterion.
 *
 * @param $headers
 *   An array of column headers in the format described in theme_table().
 * @return
 *   An associative array describing the criterion, containing the keys:
 *   - "name": The localized title of the table column.
 *   - "sql": The name of the database field to sort on.
 */
Dries's avatar
Dries committed
147
148
function tablesort_get_order($headers) {
  $order = isset($_GET['order']) ? $_GET['order'] : '';
Dries's avatar
   
Dries committed
149
  foreach ($headers as $header) {
150
    if (isset($header['data']) && $order == $header['data']) {
151
      return array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
Dries's avatar
   
Dries committed
152
153
    }

154
    if (isset($header['sort']) && ($header['sort'] == 'asc' || $header['sort'] == 'desc')) {
155
      $default = array('name' => $header['data'], 'sql' => isset($header['field']) ? $header['field'] : '');
Dries's avatar
   
Dries committed
156
157
158
    }
  }

159
  if (isset($default)) {
Dries's avatar
   
Dries committed
160
    return $default;
Dries's avatar
 
Dries committed
161
162
  }
  else {
Dries's avatar
   
Dries committed
163
    // The first column specified is initial 'order by' field unless otherwise specified
Dries's avatar
   
Dries committed
164
    if (is_array($headers[0])) {
165
      $headers[0] += array('data' => NULL, 'field' => NULL);
166
      return array('name' => $headers[0]['data'], 'sql' => $headers[0]['field']);
Dries's avatar
   
Dries committed
167
168
169
    }
    else {
      return array('name' => $headers[0]);
Dries's avatar
 
Dries committed
170
171
172
173
    }
  }
}

174
175
176
177
178
179
180
181
/**
 * Determine the current sort direction.
 *
 * @param $headers
 *   An array of column headers in the format described in theme_table().
 * @return
 *   The current sort direction ("asc" or "desc").
 */
Dries's avatar
Dries committed
182
183
184
function tablesort_get_sort($headers) {
  if (isset($_GET['sort'])) {
    return ($_GET['sort'] == 'desc') ? 'desc' : 'asc';
Dries's avatar
 
Dries committed
185
  }
186
  // User has not specified a sort. Use default if specified; otherwise use "asc".
Dries's avatar
 
Dries committed
187
188
  else {
    foreach ($headers as $header) {
189
      if (is_array($header) && array_key_exists('sort', $header)) {
Dries's avatar
   
Dries committed
190
        return $header['sort'];
Dries's avatar
 
Dries committed
191
192
193
194
195
      }
    }
  }
  return 'asc';
}