| Commit | Line | Data |
|---|---|---|
| 013538bb EM |
1 | <?php |
| 2 | // $Id$ | |
| 3 | /** | |
| 4 | * @file handlers.inc | |
| 5 | * Defines the various handler objects to help build and display views. | |
| 6 | */ | |
| 7 | ||
| 8 | /** | |
| 9 | * @defgroup views_join_handlers Views' join handlers | |
| 10 | * @{ | |
| 11 | * Handlers to tell Views how to join tables together. | |
| 12 | ||
| 13 | * Here is how you do complex joins: | |
| 14 | * | |
| 15 | * @code | |
| 16 | * class views_join_complex extends views_join { | |
| 86ed07d8 EM |
17 | * // PHP 4 doesn't call constructors of the base class automatically from a |
| 18 | * // constructor of a derived class. It is your responsibility to propagate | |
| 013538bb | 19 | * // the call to constructors upstream where appropriate. |
| cffc1056 EM |
20 | * function construct($left_table, $left_field, $field, $extra = array(), $type = 'LEFT') { |
| 21 | * parent::construct($left_table, $left_field, $field, $extra, $type); | |
| 013538bb EM |
22 | * } |
| 23 | * | |
| 24 | * function join($table, &$query) { | |
| 25 | * $output = parent::join($table, $query); | |
| 26 | * } | |
| 27 | * $output .= "AND foo.bar = baz.boing"; | |
| 28 | * return $output; | |
| 29 | * } | |
| 30 | * @endcode | |
| 31 | */ | |
| 32 | /** | |
| 33 | * A function class to represent a join and create the SQL necessary | |
| 34 | * to implement the join. | |
| 86ed07d8 | 35 | * |
| 013538bb EM |
36 | * This is the Delegation pattern. If we had PHP5 exclusively, we would |
| 37 | * declare this an interface. | |
| 38 | * | |
| 39 | * Extensions of this class can be used to create more interesting joins. | |
| 40 | */ | |
| 41 | class views_join { | |
| 42 | /** | |
| 43 | * Construct the views_join object. | |
| 44 | */ | |
| cffc1056 | 45 | function construct($table, $left_table, $left_field, $field, $extra = array(), $type = 'LEFT') { |
| 013538bb EM |
46 | $this->table = $table; |
| 47 | $this->left_table = $left_table; | |
| 48 | $this->left_field = $left_field; | |
| 49 | $this->field = $field; | |
| 50 | $this->extra = $extra; | |
| 51 | $this->type = strtoupper($type); | |
| 52 | } | |
| 53 | ||
| 54 | /** | |
| 55 | * Build the SQL for the join this object represents. | |
| 56 | */ | |
| 57 | function join($table, &$query) { | |
| 58 | $left = $query->get_table_info($this->left_table); | |
| 59 | $output = " $this->type JOIN {" . $this->table . "} $table[alias] ON $left[alias].$this->left_field = $table[alias].$this->field"; | |
| 60 | ||
| 61 | // Tack on the extra. | |
| 62 | if (isset($extra)) { | |
| 63 | foreach ($extra as $field => $value) { | |
| 64 | $output .= " AND $table[alias].$this->field"; | |
| 65 | if (is_array($value) && !empty($value)) { | |
| 66 | $output .= " IN ('". implode("','", $value) ."')"; | |
| 67 | } | |
| 68 | else if ($value !== NULL) { | |
| 69 | $output .= " = '$value'"; | |
| 70 | } | |
| 71 | } | |
| 72 | } | |
| 86ed07d8 | 73 | return $output; |
| 013538bb EM |
74 | } |
| 75 | } | |
| 76 | ||
| 77 | /** | |
| 78 | * @} | |
| 79 | */ | |
| 80 | ||
| 81 | /** | |
| 86ed07d8 | 82 | * Base handler, from which all the other handlers are derived. |
| 013538bb EM |
83 | * It creates a common interface to create consistency amongst |
| 84 | * handlers and data. | |
| 85 | * | |
| 86 | * The default handler has no constructor, so there's no need to jank with | |
| 87 | * parent::views_handler() here. | |
| 88 | * | |
| 89 | * This class would be abstract in PHP5, but PHP4 doesn't understand that. | |
| 86ed07d8 | 90 | * |
| 013538bb | 91 | */ |
| cffc1056 | 92 | class views_handler extends views_object { |
| 013538bb | 93 | /** |
| 86ed07d8 | 94 | * init the handler with necessary data. |
| 013538bb EM |
95 | * @param $view |
| 96 | * The $view object this handler is attached to. | |
| 97 | * @param $data | |
| 98 | * The item from the database; the actual contents of this will vary | |
| 99 | * based upon the type of handler. | |
| 100 | */ | |
| 86ed07d8 | 101 | function init(&$view, &$data) { |
| 013538bb EM |
102 | $this->view = &$view; |
| 103 | $this->data = &$data; | |
| 104 | ||
| 105 | // Mostly this exists to make things easier to reference. $this->options['...'] | |
| 106 | // is a little easier than $this->data->options['...']; | |
| 107 | if (isset($data->options)) { | |
| 108 | $this->options = $data->options; | |
| 109 | } | |
| 110 | else { | |
| 111 | $this->options = array(); | |
| 112 | } | |
| 113 | ||
| 114 | // This exist on most handlers, but not all. So they are still optional. | |
| cffc1056 EM |
115 | if (isset($data->tablename)) { |
| 116 | $this->table = $data->tablename; | |
| 013538bb EM |
117 | } |
| 118 | ||
| 119 | if (isset($data->field)) { | |
| 120 | $this->field = $data->field; | |
| cffc1056 EM |
121 | if (!isset($this->real_field)) { |
| 122 | $this->real_field = $data->field; | |
| 123 | } | |
| 013538bb EM |
124 | } |
| 125 | ||
| 126 | if (isset($data->relationship)) { | |
| 127 | $this->relationship = $data->relationship; | |
| 128 | } | |
| 129 | ||
| 130 | if (!empty($view->query)) { | |
| 131 | $this->query = &$view->query; | |
| 132 | } | |
| 133 | } | |
| 134 | ||
| 135 | /** | |
| 136 | * Provide a form for setting options. | |
| 137 | */ | |
| 138 | function options_form(&$form) { } | |
| 86ed07d8 | 139 | |
| 013538bb EM |
140 | /** |
| 141 | * Validate the options form. | |
| 142 | */ | |
| 143 | function options_validate($form, &$form_state) { } | |
| 144 | ||
| 145 | /** | |
| 146 | * Perform any necessary changes to the form values prior to storage. | |
| 147 | * There is no need for this function to actually store the data. | |
| 148 | */ | |
| 149 | function options_submit($form, &$form_state) { } | |
| 150 | ||
| 151 | /** | |
| 152 | * Add this handler into the query. | |
| 153 | * | |
| 154 | * If we were using PHP5, this would be abstract. | |
| 155 | */ | |
| 156 | function query() { } | |
| cffc1056 EM |
157 | |
| 158 | /** | |
| 159 | * Ensure the main table for this handler is in the query. This is used | |
| 160 | * a lot. | |
| 161 | */ | |
| 162 | function ensure_my_table() { | |
| 163 | if (!isset($this->alias)) { | |
| 164 | $this->table_alias = $this->query->ensure_table($this->table, $this->relationship); | |
| 165 | } | |
| 166 | return $this->table_alias; | |
| 167 | } | |
| 013538bb EM |
168 | } |
| 169 | ||
| 170 | /** | |
| 171 | * @defgroup views_relationship_handlers Views' relationship handlers | |
| 172 | * @{ | |
| 173 | * Handlers to tell Views how to create alternate relationships. | |
| 174 | */ | |
| 175 | ||
| 176 | /** | |
| 177 | * Simple relationship handler that allows a new version of the primary table | |
| 178 | * to be linked in. | |
| 179 | */ | |
| 180 | class views_handler_relationship extends views_handler { | |
| 181 | /** | |
| 182 | * Called to implement a relationship in a query. | |
| 183 | */ | |
| 184 | function query() { | |
| 185 | $alias = $this->table . '_' . $this->field . '_' . $this->relationship; | |
| cffc1056 | 186 | return $this->query->add_relationship($alias, new views_join($this->view->primary_table, $this->table, $this->real_field, $this->primary_field), $this->relationship); |
| 013538bb EM |
187 | } |
| 188 | } | |
| 189 | ||
| 190 | /** | |
| 191 | * @} | |
| 192 | */ | |
| 193 | ||
| 194 | /** | |
| 195 | * @defgroup views_field_handlers Views' field handlers | |
| 196 | * @{ | |
| 197 | * Handlers to tell Views how to build and display fields. | |
| cffc1056 | 198 | * |
| 013538bb EM |
199 | */ |
| 200 | ||
| 201 | /** | |
| 202 | * Base field handler that has no options and renders an unformatted field. | |
| 203 | */ | |
| 204 | class views_handler_field extends views_handler { | |
| b06399e3 | 205 | var $field_alias = 'unknown'; |
| 013538bb EM |
206 | |
| 207 | /** | |
| 208 | * Construct a new field handler. | |
| 209 | */ | |
| cffc1056 | 210 | function construct($click_sortable = FALSE, $additional_fields = array()) { |
| 013538bb EM |
211 | $this->click_sortable = $click_sortable; |
| 212 | $this->additional_fields = $additional_fields; | |
| 213 | } | |
| 214 | ||
| 215 | /** | |
| 216 | * Called to add the field to a query. | |
| 217 | */ | |
| 218 | function query() { | |
| cffc1056 | 219 | $this->ensure_my_table(); |
| 013538bb | 220 | // Add the field. |
| cffc1056 | 221 | $this->field_alias = $this->query->add_field($this->table_alias, $this->real_field); |
| b06399e3 | 222 | |
| 013538bb EM |
223 | // Add any additional fields we are given. |
| 224 | if (!empty($this->additional_fields) && is_array($this->additional_fields)) { | |
| cffc1056 EM |
225 | foreach ($this->additional_fields as $field) { |
| 226 | $this->aliases[$field] = $this->query->add_field($this->table_alias, $field); | |
| 013538bb EM |
227 | } |
| 228 | } | |
| 229 | } | |
| 230 | ||
| 231 | /** | |
| 232 | * Called to determine what to tell the clicksorter. | |
| 233 | */ | |
| 234 | function click_sort() { | |
| cffc1056 | 235 | return "$this->field_alias"; |
| 013538bb EM |
236 | } |
| 237 | ||
| 238 | /** | |
| 239 | * Render the field. | |
| 240 | * | |
| 241 | * @param $values | |
| 242 | * The values retrieved from the database. | |
| 243 | */ | |
| 244 | function render($values) { | |
| 245 | $value = $values->{$this->field_alias}; | |
| 246 | return check_plain($value); | |
| 247 | } | |
| 248 | } | |
| 249 | ||
| 250 | /** | |
| 251 | * A handler to provide proper displays for dates. | |
| 252 | */ | |
| 253 | class views_handler_field_date extends views_handler_field { | |
| 254 | /** | |
| 255 | * Constructor; calls to base object constructor. | |
| 256 | */ | |
| cffc1056 EM |
257 | function construct($click_sortable = FALSE, $additional_fields = array()) { |
| 258 | parent::construct($click_sortable, $additional_fields); | |
| 013538bb EM |
259 | } |
| 260 | ||
| 261 | function options_form(&$form) { | |
| 262 | $form['date_format'] = array( | |
| 263 | '#type' => 'select', | |
| 264 | '#title' => t('Date format'), | |
| 265 | '#options' => array( | |
| 266 | 'small' => t('Small'), | |
| 267 | 'medium' => t('Medium'), | |
| 268 | 'large' => t('Large'), | |
| 269 | 'custom' => t('Custom'), | |
| 270 | 'time ago' => t('Time ago'), | |
| 271 | ), | |
| 272 | '#default_value' => isset($this->options['date_format']) ? $this->options['date_format'] : 'small', | |
| 273 | ); | |
| 274 | $form['custom_date_format'] = array( | |
| 275 | '#type' => 'textfield', | |
| 276 | '#title' => t('Custom date format'), | |
| 277 | '#description' => t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php">the PHP docs</a> for date formats. If "Time ago" this is the the number of different units to display, which defaults to two.'), | |
| 278 | '#default_value' => isset($this->options['custom_date_format']) ? $this->options['custom_date_format'] : '', | |
| 279 | ); | |
| 280 | } | |
| 281 | ||
| 282 | function render($values) { | |
| 283 | $value = $values->{$this->field_alias}; | |
| cffc1056 EM |
284 | $format = !empty($this->options['date_format']) ? $this->options['date_format'] : 'medium'; |
| 285 | if ($format == 'custom') { | |
| 286 | $custom_format = $this->options['custom_date_format']; | |
| 287 | } | |
| 013538bb EM |
288 | |
| 289 | switch ($format) { | |
| 290 | case 'time ago': | |
| 291 | return $value ? t('%time ago', array('%time' => format_interval(time() - $value, is_numeric($custom_format) ? $custom_format : 2))) : theme('views_nodate'); | |
| 292 | case 'custom': | |
| 293 | return $value ? format_date($value, $format, $custom_format) : theme('views_nodate'); | |
| 294 | default: | |
| 295 | return $value ? format_date($value, $format) : theme('views_nodate'); | |
| 296 | } | |
| 297 | } | |
| 298 | } | |
| 299 | ||
| 300 | /** | |
| 301 | * @} | |
| 302 | */ | |
| 303 | ||
| 304 | /** | |
| 305 | * @defgroup views_sort_handlers Views' sort handlers | |
| 306 | * @{ | |
| 307 | * Handlers to tell Views how to sort queries | |
| 308 | */ | |
| 309 | /** | |
| 310 | * Base sort handler that has no options and performs a simple sort | |
| 311 | */ | |
| 312 | class views_handler_sort extends views_handler { | |
| 313 | /** | |
| 314 | * Called to add the sort to a query. | |
| 315 | */ | |
| 316 | function query() { | |
| cffc1056 | 317 | $this->ensure_my_table(); |
| 013538bb | 318 | // Add the field. |
| cffc1056 | 319 | $this->query->add_orderby($this->table_alias, $this->real_field, $this->data->order); |
| 013538bb EM |
320 | } |
| 321 | } | |
| 322 | ||
| 323 | /** | |
| 324 | * Base sort handler that has no options and performs a simple sort | |
| 325 | */ | |
| 326 | class views_handler_sort_formula extends views_handler_sort { | |
| 327 | /** | |
| 328 | * Constructor to take the formula this sorts on. | |
| 329 | * | |
| 330 | * @param $formula | |
| 331 | * The formula used to sort. If an array, may be keyed by database type. If | |
| 332 | * used, 'default' MUST be defined. | |
| 333 | */ | |
| cffc1056 | 334 | function construct($formula) { |
| 013538bb EM |
335 | $this->formula = $formula; |
| 336 | if (is_array($formula) && !isset($formula['default'])) { | |
| 337 | $this->error = t('views_handler_sort_formula missing default: @formula', array('@formula' => var_export($formula, TRUE))); | |
| 338 | } | |
| 339 | } | |
| 340 | /** | |
| 341 | * Called to add the sort to a query. | |
| 342 | */ | |
| 343 | function query() { | |
| 344 | if (is_array($this->formula)) { | |
| 345 | global $db_type; | |
| 346 | if (isset($this->formula[$db_type])) { | |
| 347 | $formula = $this->formula[$db_type]; | |
| 348 | } | |
| 349 | else { | |
| 350 | $formula = $this->formula['default']; | |
| 351 | } | |
| 352 | } | |
| 353 | else { | |
| 354 | $formula = $this->formula; | |
| 355 | } | |
| cffc1056 | 356 | $this->ensure_my_table(); |
| 013538bb | 357 | // Add the field. |
| cffc1056 | 358 | $this->add_orderby(NULL, $this->formula, $this->data->order, $this->table_alias . '_' . $this->field); |
| 013538bb EM |
359 | } |
| 360 | } | |
| 361 | ||
| 362 | /** | |
| 363 | * @} | |
| 364 | */ | |
| 365 | ||
| 366 | /** | |
| 367 | * @defgroup views_filter_handlers Views' filter handlers | |
| 368 | * @{ | |
| 369 | * Handlers to tell Views how to filter queries. | |
| 370 | */ | |
| 371 | ||
| 372 | /** | |
| 373 | * Base class for filters. | |
| 374 | */ | |
| 375 | class views_handler_filter extends views_handler { | |
| 376 | /** | |
| 377 | * Provide a form for setting the operator. | |
| 378 | */ | |
| 379 | function operator_form(&$form) { } | |
| 86ed07d8 | 380 | |
| 013538bb EM |
381 | /** |
| 382 | * Validate the operator form. | |
| 383 | */ | |
| 384 | function operator_validate($form, &$form_state) { } | |
| 385 | ||
| 386 | /** | |
| 387 | * Perform any necessary changes to the form values prior to storage. | |
| 388 | * There is no need for this function to actually store the data. | |
| 389 | */ | |
| 390 | function operator_submit($form, &$form_state) { } | |
| 391 | ||
| 392 | /** | |
| 393 | * Provide a form for setting options. | |
| 394 | */ | |
| 395 | function value_form(&$form) { } | |
| 86ed07d8 | 396 | |
| 013538bb EM |
397 | /** |
| 398 | * Validate the options form. | |
| 399 | */ | |
| 400 | function value_validate($form, &$form_state) { } | |
| 401 | ||
| 402 | /** | |
| 403 | * Perform any necessary changes to the form values prior to storage. | |
| 404 | * There is no need for this function to actually store the data. | |
| 405 | */ | |
| 406 | function value_submit($form, &$form_state) { } | |
| 407 | ||
| 408 | /** | |
| 409 | * Add this filter to the query. | |
| 410 | */ | |
| 411 | function query() { | |
| cffc1056 EM |
412 | $this->ensure_my_table(); |
| 413 | $this->query->add_where($this->data->group, "$this->table_alias.$this->real_field " . $this->data->operator . " '%s'", $this->data->value); | |
| 013538bb EM |
414 | } |
| 415 | } | |
| 416 | ||
| 417 | /** | |
| 418 | * @} | |
| 419 | */ | |
| 420 | ||
| 421 | /** | |
| 422 | * @defgroup views_argument_handlers Handlers for arguments | |
| 423 | * @{ | |
| 424 | */ | |
| 425 | /** | |
| 86ed07d8 | 426 | * Base class for arguments. |
| 013538bb EM |
427 | * |
| 428 | * The basic argument works for very simple arguments such as nid and uid | |
| 429 | */ | |
| 430 | class views_handler_argument extends views_handler { | |
| 431 | /** | |
| 432 | * Constructor | |
| 433 | */ | |
| cffc1056 | 434 | function construct($name_field = NULL) { |
| 013538bb EM |
435 | $this->name_field = $name_field; |
| 436 | } | |
| 437 | ||
| 438 | /** | |
| 439 | * Build the info for the summary query. | |
| 440 | * | |
| 441 | * This must: | |
| 442 | * - add_groupby: group on this field in order to create summaries. | |
| 443 | * - add_field: add a 'num_nodes' field for the count. Usually it will | |
| 444 | * be a count on $view->primary_field | |
| 445 | * - set_count_field: Reset the count field so we get the right paging. | |
| 446 | * | |
| 86ed07d8 | 447 | * @return |
| 013538bb EM |
448 | * The alias used to get the number of records (count) for this entry. |
| 449 | */ | |
| 450 | function summary_query() { | |
| cffc1056 | 451 | $this->ensure_my_table(); |
| 013538bb | 452 | // Add the field. |
| 86ed07d8 EM |
453 | $this->base_alias = $this->query->add_field($this->table_alias, $this->real_field); |
| 454 | ||
| 013538bb EM |
455 | // Add the 'name' field. For example, if this is a uid argument, the |
| 456 | // name field would be 'name' (i.e, the username). | |
| 457 | if (isset($this->name_field)) { | |
| cffc1056 | 458 | $this->name_alias = $this->query->add_field($this->table_alias, $this->name_field); |
| 013538bb EM |
459 | } |
| 460 | else { | |
| 461 | $this->name_alias = $this->base_alias; | |
| 462 | } | |
| 86ed07d8 | 463 | |
| cffc1056 EM |
464 | return $this->summary_basics(); |
| 465 | } | |
| 013538bb | 466 | |
| cffc1056 EM |
467 | /** |
| 468 | * Some basic summary behavior that doesn't need to be repeated as much as | |
| 469 | * code that goes into summary_query() | |
| 470 | */ | |
| 471 | function summary_basics($count_field = TRUE) { | |
| 013538bb EM |
472 | // Add the number of nodes counter |
| 473 | $count_alias = $this->query->add_field(NULL, 'COUNT(' . $this->query->primary_field . ')', 'num_records'); | |
| 474 | $this->query->add_groupby($this->base_alias); | |
| 475 | ||
| cffc1056 EM |
476 | if ($count_field) { |
| 477 | $this->query->set_count_field($this->table_alias, $this->real_field); | |
| 478 | } | |
| 013538bb | 479 | |
| 86ed07d8 | 480 | $this->count_alias = $count_alias; |
| 013538bb EM |
481 | } |
| 482 | ||
| 483 | /** | |
| 484 | * Sorts the summary based upon the user's selection. The base variant of | |
| 485 | * this is usually adequte. | |
| 86ed07d8 | 486 | * |
| 013538bb EM |
487 | * @param $order |
| 488 | * The order selected in the UI. | |
| 489 | */ | |
| 490 | function summary_sort($order) { | |
| 491 | $query->add_orderby(NULL, NULL, $order, $this->base_alias); | |
| 492 | } | |
| 493 | ||
| 494 | /** | |
| 495 | * Provides a link from the summary to the next level; this will be called | |
| 496 | * once per row of a summary. | |
| 497 | * | |
| 498 | * @param $data | |
| 499 | * The query results for the row. | |
| 500 | * @param $url | |
| 501 | * The base URL to use. | |
| 502 | */ | |
| 503 | function summary_link($data, $url) { | |
| cffc1056 | 504 | $value = $data->{$this->base_alias}; |
| 86ed07d8 | 505 | return url("$url/$value"); |
| 013538bb EM |
506 | } |
| 507 | ||
| 508 | /** | |
| 509 | * Provide a list of default behaviors for this argument if the argument | |
| 510 | * is not present. | |
| 511 | * | |
| 512 | * Override this method to provide additional (or fewer) default behaviors. | |
| 513 | */ | |
| 514 | function defaults() { | |
| 515 | return array( | |
| 516 | 'ignore' => t('Display all values'), | |
| 517 | 'not found' => t('Display page not found'), | |
| 518 | 'empty' => t('Display empty text'), | |
| 519 | 'summary asc' => t('Summary, sorted ascending'), | |
| 520 | 'summary desc' => t('Summary, sorted descending'), | |
| 521 | ); | |
| 522 | } | |
| 523 | ||
| 524 | /** | |
| 525 | * Handle the default action, which means our argument wasn't present. | |
| 526 | * | |
| 527 | * Override this method only with extreme care. | |
| 528 | * | |
| 529 | * @return | |
| 530 | * A boolean value; if TRUE, continue building this view. If FALSE, | |
| 531 | * building the view will be aborted here. | |
| 532 | */ | |
| 533 | function default_action() { | |
| 534 | $action = $this->data->default_action; | |
| 535 | switch ($action) { | |
| 536 | default: | |
| 537 | case 'ignore': | |
| 538 | // Do nothing at all. | |
| 539 | return TRUE; | |
| 540 | case 'not found': | |
| 541 | // Set a failure condition and let the display manager handle it. | |
| 542 | $this->view->build_info['fail'] = TRUE; | |
| 543 | return FALSE; | |
| 544 | case 'empty': | |
| 545 | // We return with no query; this will force the empty text. | |
| 546 | $this->view->built = TRUE; | |
| 547 | return FALSE; | |
| 548 | case 'summary': | |
| 549 | case 'summary asc': | |
| 550 | case 'summary desc': | |
| 551 | $this->view->build_info['summary'] = TRUE; | |
| 552 | $this->view->build_info['summary_level'] = $this->data->position; | |
| 553 | ||
| 86ed07d8 EM |
554 | // Change the display style to the summary style for this |
| 555 | // argument. | |
| 556 | $this->view->style_plugin = isset($this->options['style_plugin']) ? $this->options['style_plugin'] : 'default_summary'; | |
| 557 | ||
| 558 | // Give it the style's options, too. | |
| 559 | // @todo | |
| 560 | ||
| 561 | ||
| 013538bb EM |
562 | // Clear out the normal primary field and whatever else may have |
| 563 | // been added and let the summary do the work. | |
| 564 | $this->query->clear_fields(); | |
| 565 | $this->summary_query(); | |
| 566 | ||
| 86ed07d8 EM |
567 | // Allow the new style to add additional fields if it wants. |
| 568 | // @todo | |
| 569 | ||
| 013538bb EM |
570 | // Cut 'summary' out of our action to see how, if at all, we should |
| 571 | // sort. | |
| 572 | $order = trim(str_replace($action, 'summary', '')); | |
| 573 | if ($order) { | |
| 574 | $argument->handler->summary_sort($order); | |
| 575 | } | |
| 576 | ||
| 577 | // DISTINCT can cause the summaries to fail. | |
| 86ed07d8 | 578 | // @todo: This may not be true anymore. |
| 013538bb EM |
579 | // $this->query->no_distinct = TRUE; |
| 580 | ||
| 86ed07d8 | 581 | |
| 013538bb EM |
582 | // Summaries have their own sorting and fields, so tell the View not |
| 583 | // to build these. | |
| 584 | $this->view->build_sort = $this->view->build_fields = FALSE; | |
| cffc1056 | 585 | return TRUE; |
| 013538bb EM |
586 | } |
| 587 | } | |
| 588 | ||
| 589 | /** | |
| 590 | * Set up the query for this argument. | |
| 591 | * | |
| 592 | * The argument sent may be found at $this->argument. | |
| 593 | */ | |
| 594 | function query() { | |
| cffc1056 EM |
595 | $this->ensure_my_table(); |
| 596 | $this->query->add_where(0, "$this->table_alias.$this->real_field = '%s'", $this->argument); | |
| 013538bb EM |
597 | } |
| 598 | ||
| 599 | /** | |
| 600 | * Get the title this argument will assign the view, given the argument. | |
| 601 | * | |
| 602 | * This usually needs to be overridden to provide a proper title. | |
| 603 | */ | |
| cffc1056 EM |
604 | function title() { |
| 605 | return check_plain($this->argument); | |
| 013538bb | 606 | } |
| b06399e3 EM |
607 | |
| 608 | /** | |
| 609 | * Validate that this argument works. By default, all arguments are valid. | |
| 610 | */ | |
| 611 | function validate($arg) { | |
| 612 | return TRUE; | |
| 613 | } | |
| 013538bb EM |
614 | } |
| 615 | ||
| 616 | /** | |
| cffc1056 EM |
617 | * Abstract argument handler for simple formulae. |
| 618 | * | |
| 619 | * Child classes of this object should implement summary_link, at least. | |
| 013538bb | 620 | */ |
| cffc1056 EM |
621 | class views_handler_argument_formula extends views_handler_argument { |
| 622 | /** | |
| 623 | * Constructor | |
| 624 | */ | |
| 625 | function construct($formula) { | |
| 626 | $this->formula = $formula; | |
| 627 | } | |
| 628 | ||
| 629 | /** | |
| 630 | * Build the summary query based on a formula | |
| 631 | */ | |
| 632 | function summary_query() { | |
| 633 | $this->ensure_my_table(); | |
| 634 | $field_alias = $alias . '_' . $this->field; | |
| 635 | // Add the field. | |
| 86ed07d8 | 636 | $this->base_alias = $this->query->add_field(NULL, $this->formula, $field_alias); |
| cffc1056 | 637 | $this->query->set_count_field(NULL, $this->formula, $field_alias); |
| 86ed07d8 | 638 | |
| cffc1056 EM |
639 | return $this->summary_basics(FALSE); |
| 640 | } | |
| 641 | ||
| 642 | /** | |
| 643 | * Build the query based upon the formula | |
| 644 | */ | |
| 645 | function query() { | |
| 646 | $this->ensure_my_table(); | |
| 647 | $field_alias = $alias . '_' . $this->field; | |
| 648 | // Add the field. | |
| 86ed07d8 | 649 | $this->name_alias = $this->query->add_field(NULL, $this->formula, $field_alias); |
| cffc1056 EM |
650 | $this->query->add_where(0, "$field = '%s'", $this->argument); |
| 651 | } | |
| 652 | } | |
| 653 | ||
| 654 | /** | |
| 655 | * Argument handler for a year (CCYY) | |
| 656 | */ | |
| 657 | class views_handler_argument_date_year extends views_handler_argument_formula { | |
| 658 | /** | |
| 659 | * Constructor implementation | |
| 660 | */ | |
| 661 | function construct() { | |
| 662 | $timezone = views_get_timezone(); | |
| 663 | $this->formula = "YEAR(FROM_UNIXTIME(node.created+$timezone))"; | |
| 664 | } | |
| 665 | ||
| 666 | /** | |
| 667 | * Provide a link to the next level of the view | |
| 668 | */ | |
| 669 | function summary_link($data, $url) { | |
| 670 | $value = $data->{$this->base_alias}; | |
| 671 | return l($value, "$url/$value"); | |
| 672 | } | |
| 673 | } | |
| 674 | ||
| 675 | /** | |
| 676 | * Argument handler for a year plus month (CCYYMM) | |
| 677 | */ | |
| 678 | class views_handler_argument_date_year_month extends views_handler_argument_formula { | |
| 679 | /** | |
| 680 | * Constructor implementation | |
| 681 | */ | |
| 682 | function construct() { | |
| 683 | $timezone = views_get_timezone(); | |
| 684 | $this->formula = "DATE_FORMAT(FROM_UNIXTIME(node.created+$timezone), '%Y%m')"; | |
| 685 | $this->format = 'F, Y'; | |
| 686 | } | |
| 687 | ||
| 688 | /** | |
| 689 | * Provide a link to the next level of the view | |
| 690 | */ | |
| 691 | function summary_link($data, $url) { | |
| 692 | $value = $data->{$this->base_alias}; | |
| 693 | $created = $data->{$this->name_alias}; | |
| 694 | return l(format_date($created, 'custom', $this->format), "$url/$value"); | |
| 695 | } | |
| 696 | ||
| 697 | /** | |
| 698 | * Provide a link to the next level of the view | |
| 699 | */ | |
| 700 | function title($data, $url) { | |
| 701 | return format_date(strtotime($this->argument . "15"), 'custom', $this->format, 0); | |
| 702 | } | |
| 703 | } | |
| 704 | ||
| 705 | /** | |
| 706 | * Argument handler for a month (MM) | |
| 707 | */ | |
| 708 | class views_handler_argument_date_month extends views_handler_argument_formula { | |
| 709 | /** | |
| 710 | * Constructor implementation | |
| 711 | */ | |
| 712 | function construct() { | |
| 713 | $timezone = views_get_timezone(); | |
| 714 | $this->formula = "MONTH(FROM_UNIXTIME(node.created+$timezone))"; | |
| 715 | $this->format = 'F'; | |
| 716 | } | |
| 717 | ||
| 718 | /** | |
| 719 | * Provide a link to the next level of the view | |
| 720 | */ | |
| 721 | function summary_link($data, $url) { | |
| 722 | $value = $data->{$this->base_alias}; | |
| 723 | $created = $data->{$this->name_alias}; | |
| 724 | return l(format_date($created, 'custom', $this->format), "$url/$value"); | |
| 725 | } | |
| 726 | ||
| 727 | /** | |
| 728 | * Provide a link to the next level of the view | |
| 729 | */ | |
| 730 | function title($data, $url) { | |
| 731 | return format_date(strtotime("2005" . $this->argument . "15"), 'custom', $this->format, 0); | |
| 732 | } | |
| 013538bb EM |
733 | } |
| 734 | ||
| 735 | /** | |
| 736 | * @} | |
| 737 | */ |