| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * @file 4 * Contains the base display plugin. 5 */ 6 7 /** 8 * @defgroup views_display_plugins Views' display plugins 9 * @{ 10 * Display plugins control how Views interact with the rest of Drupal. 11 * 12 * They can handle creating Views from a Drupal page hook; they can 13 * handle creating Views from a Drupal block hook. They can also 14 * handle creating Views from an external module source, such as 15 * a Panels pane, or an insert view, or a CCK field type. 16 * 17 * @see hook_views_plugins 18 */ 19 20 /** 21 * The default display plugin handler. Display plugins handle options and 22 * basic mechanisms for different output methods. 23 * 24 * @ingroup views_display_plugins 25 */ 26 class views_plugin_display extends views_plugin { 27 var $handlers = array(); 28 29 function init(&$view, &$display, $options = NULL) { 30 $this->view = &$view; 31 $this->display = &$display; 32 33 // Make some modifications: 34 if (!isset($options)) { 35 $options = $display->display_options; 36 } 37 38 if ($this->is_default_display() && isset($options['defaults'])) { 39 unset($options['defaults']); 40 } 41 42 $this->unpack_options($this->options, $options); 43 } 44 45 function destroy() { 46 parent::destroy(); 47 48 foreach ($this->handlers as $type => $handlers) { 49 foreach ($handlers as $id => $handler) { 50 if (is_object($handler)) { 51 $this->handlers[$type][$id]->destroy(); 52 } 53 } 54 } 55 56 if (isset($this->default_display)) { 57 unset($this->default_display); 58 } 59 } 60 61 /** 62 * Determine if this display is the 'default' display which contains 63 * fallback settings 64 */ 65 function is_default_display() { return FALSE; } 66 67 /** 68 * Determine if this display uses exposed filters, so the view 69 * will know whether or not to build them. 70 */ 71 function uses_exposed() { 72 if (!isset($this->has_exposed)) { 73 foreach (array('field', 'filter') as $type) { 74 foreach ($this->view->$type as $key => $handler) { 75 if ($handler->is_exposed()) { 76 // one is all we need; if we find it, return true. 77 $this->has_exposed = TRUE; 78 return TRUE; 79 } 80 } 81 } 82 $this->has_exposed = FALSE; 83 } 84 85 return $this->has_exposed; 86 } 87 88 /** 89 * Determine if this display should display the exposed 90 * filters widgets, so the view will know whether or not 91 * to render them. 92 * 93 * Regardless of what this function 94 * returns, exposed filters will not be used nor 95 * displayed unless uses_exposed() returns TRUE. 96 */ 97 function displays_exposed() { 98 return TRUE; 99 } 100 101 /** 102 * Does the display use AJAX? 103 */ 104 function use_ajax() { 105 if (!empty($this->definition['use ajax'])) { 106 return $this->get_option('use_ajax'); 107 } 108 return FALSE; 109 } 110 111 /** 112 * Does the display have a pager enabled? 113 */ 114 function use_pager() { 115 if (!empty($this->definition['use pager'])) { 116 return $this->get_option('use_pager'); 117 } 118 return FALSE; 119 } 120 121 /** 122 * Does the display render the pager if it has it enabled? 123 */ 124 function render_pager() { 125 return $this->use_pager(); 126 } 127 128 /** 129 * Does the display have a more link enabled? 130 */ 131 function use_more() { 132 if (!empty($this->definition['use more'])) { 133 return $this->get_option('use_more'); 134 } 135 return FALSE; 136 } 137 138 /** 139 * Should the enabled display more link be shown when no more items? 140 */ 141 function use_more_always() { 142 if (!empty($this->definition['use more'])) { 143 return $this->get_option('use_more_always'); 144 } 145 return FALSE; 146 } 147 148 /** 149 * Does the display have custom link text? 150 */ 151 function use_more_text() { 152 if (!empty($this->definition['use more'])) { 153 return $this->get_option('use_more_text'); 154 } 155 return FALSE; 156 } 157 158 /** 159 * Can this display accept attachments? 160 */ 161 function accept_attachments() { 162 return !empty($this->definition['accept attachments']); 163 } 164 165 /** 166 * Allow displays to attach to other views. 167 */ 168 function attach_to($display_id) { } 169 170 /** 171 * Static member function to list which sections are defaultable 172 * and what items each section contains. 173 */ 174 function defaultable_sections($section = NULL) { 175 $sections = array( 176 'access' => array('access'), 177 'cache' => array('cache'), 178 'title' => array('title'), 179 'css_class' => array('css_class'), 180 'header' => array('header', 'header_format', 'header_empty'), 181 'footer' => array('footer', 'footer_format', 'footer_empty'), 182 'empty' => array('empty', 'empty_format'), 183 'use_ajax' => array('use_ajax'), 184 'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'), 185 'use_pager' => array('items_per_page', 'offset', 'use_pager', 'pager_element'), 186 'use_more' => array('use_more', 'use_more_always', 'use_more_text'), 187 'link_display' => array('link_display'), 188 'distinct' => array('distinct'), 189 'exposed_block' => array('exposed_block'), 190 191 // Force these to cascade properly. 192 'style_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'), 193 'style_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'), 194 'row_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'), 195 'row_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'), 196 197 // These guys are special 198 'relationships' => array('relationships'), 199 'fields' => array('fields'), 200 'sorts' => array('sorts'), 201 'arguments' => array('arguments'), 202 'filters' => array('filters'), 203 ); 204 if ($section) { 205 if (!empty($sections[$section])) { 206 return $sections[$section]; 207 } 208 } 209 else { 210 return $sections; 211 } 212 } 213 214 /** 215 * Set default options. 216 * 217 * Displays put their options in a different place than everything else; also 218 * displays spread their options out. We don't want to set defaults for 219 * items that are normally defaulted elsewhere. 220 */ 221 function _set_option_defaults(&$storage, $options, $level = 0) { 222 foreach ($options as $option => $definition) { 223 // If defaulted to elsewhere and we're not the default display, skip. 224 if ($level == 0 && !$this->is_default_display() && !empty($options['defaults']['default'][$option])) { 225 continue; 226 } 227 228 if (isset($definition['contains']) && is_array($definition['contains'])) { 229 $storage[$option] = array(); 230 $this->_set_option_defaults($storage[$option], $definition['contains'], $level++); 231 } 232 else { 233 $storage[$option] = isset($definition['default']) ? $definition['default'] : NULL; 234 } 235 } 236 } 237 238 function option_definition() { 239 $options = array( 240 'defaults' => array( 241 'default' => array( 242 'access' => TRUE, 243 'cache' => TRUE, 244 'title' => TRUE, 245 'css_class' => TRUE, 246 'header' => TRUE, 247 'header_format' => TRUE, 248 'header_empty' => TRUE, 249 'footer' => TRUE, 250 'footer_format' => TRUE, 251 'footer_empty' => TRUE, 252 'empty' => TRUE, 253 'empty_format' => TRUE, 254 255 'use_ajax' => TRUE, 256 'items_per_page' => TRUE, 257 'offset' => TRUE, 258 'use_pager' => TRUE, 259 'pager_element' => TRUE, 260 'use_more' => TRUE, 261 'use_more_always' => TRUE, 262 'use_more_text' => TRUE, 263 'distinct' => TRUE, 264 'exposed_block' => TRUE, 265 266 'link_display' => TRUE, 267 268 'style_plugin' => TRUE, 269 'style_options' => TRUE, 270 'row_plugin' => TRUE, 271 'row_options' => TRUE, 272 273 'relationships' => TRUE, 274 'fields' => TRUE, 275 'sorts' => TRUE, 276 'arguments' => TRUE, 277 'filters' => TRUE, 278 ), 279 ), 280 'relationships' => array( 281 'default' => array(), 282 'export' => 'export_item', 283 ), 284 'fields' => array( 285 'default' => array(), 286 'export' => 'export_item', 287 ), 288 'sorts' => array( 289 'default' => array(), 290 'export' => 'export_item', 291 ), 292 'arguments' => array( 293 'default' => array(), 294 'export' => 'export_item', 295 ), 296 'filters' => array( 297 'default' => array(), 298 'export' => 'export_item', 299 ), 300 'access' => array( 301 'contains' => array( 302 'type' => array('default' => 'none'), 303 ), 304 ), 305 'cache' => array( 306 'contains' => array( 307 'type' => array('default' => 'none'), 308 ), 309 ), 310 'title' => array( 311 'default' => '', 312 'translatable' => TRUE, 313 ), 314 'css_class' => array( 315 'default' => '', 316 'translatable' => FALSE, 317 ), 318 'header' => array( 319 'default' => '', 320 'translatable' => TRUE, 321 ), 322 'header_format' => array( 323 'default' => FILTER_FORMAT_DEFAULT, 324 ), 325 'header_empty' => array( 326 'default' => FALSE, 327 ), 328 'footer' => array( 329 'default' => '', 330 'translatable' => TRUE, 331 ), 332 'footer_format' => array( 333 'default' => FILTER_FORMAT_DEFAULT, 334 ), 335 'footer_empty' => array( 336 'default' => FALSE, 337 ), 338 'empty' => array( 339 'default' => '', 340 'translatable' => TRUE, 341 ), 342 'empty_format' => array( 343 'default' => FILTER_FORMAT_DEFAULT, 344 ), 345 'use_ajax' => array( 346 'default' => FALSE, 347 ), 348 'items_per_page' => array( 349 'default' => 10, 350 ), 351 'offset' => array( 352 'default' => 0, 353 ), 354 'use_pager' => array( 355 'default' => FALSE, 356 ), 357 'pager_element' => array( 358 'default' => 0, 359 ), 360 'use_more' => array( 361 'default' => FALSE, 362 ), 363 'use_more_always' => array( 364 'default' => FALSE, 365 ), 366 'use_more_text' => array( 367 'default' => 'more', 368 'translatable' => TRUE, 369 ), 370 'link_display' => array( 371 'default' => '', 372 ), 373 'distinct' => array( 374 'default' => FALSE, 375 ), 376 377 'style_plugin' => array( 378 'default' => 'default', 379 ), 380 'style_options' => array( 381 'default' => array(), 382 ), 383 'row_plugin' => array( 384 'default' => 'fields', 385 ), 386 'row_options' => array( 387 'default' => array(), 388 ), 389 390 'exposed_block' => array( 391 'default' => FALSE, 392 ), 393 ); 394 395 if ($this->is_default_display()) { 396 unset($options['defaults']); 397 } 398 return $options; 399 } 400 401 /** 402 * Check to see if the display has a 'path' field. 403 * 404 * This is a pure function and not just a setting on the definition 405 * because some displays (such as a panel pane) may have a path based 406 * upon configuration. 407 * 408 * By default, displays do not have a path. 409 */ 410 function has_path() { return FALSE; } 411 412 /** 413 * Check to see if the display has some need to link to another display. 414 * 415 * For the most part, displays without a path will use a link display. However, 416 * sometimes displays that have a path might also need to link to another display. 417 * This is true for feeds. 418 */ 419 function uses_link_display() { return !$this->has_path(); } 420 421 /** 422 * Check to see which display to use when creating links within 423 * a view using this display. 424 */ 425 function get_link_display() { 426 $display_id = $this->get_option('link_display'); 427 // If unknown, pick the first one. 428 if (empty($display_id) || empty($this->view->display[$display_id])) { 429 foreach ($this->view->display as $display_id => $display) { 430 if (!empty($display->handler) && $display->handler->has_path()) { 431 return $display_id; 432 } 433 } 434 } 435 else { 436 return $display_id; 437 } 438 // fall-through returns NULL 439 } 440 441 /** 442 * Return the base path to use for this display. 443 * 444 * This can be overridden for displays that do strange things 445 * with the path. 446 */ 447 function get_path() { 448 if ($this->has_path()) { 449 return $this->get_option('path'); 450 } 451 452 $display_id = $this->get_link_display(); 453 if ($display_id && !empty($this->view->display[$display_id]) && is_object($this->view->display[$display_id]->handler)) { 454 return $this->view->display[$display_id]->handler->get_path(); 455 } 456 } 457 458 /** 459 * Check to see if the display needs a breadcrumb 460 * 461 * By default, displays do not need breadcrumbs 462 */ 463 function uses_breadcrumb() { return FALSE; } 464 465 /** 466 * Determine if a given option is set to use the default display or the 467 * current display 468 * 469 * @return 470 * TRUE for the default display 471 */ 472 function is_defaulted($option) { 473 return !$this->is_default_display() && !empty($this->default_display) && !empty($this->options['defaults'][$option]); 474 } 475 476 /** 477 * Intelligently get an option either from this display or from the 478 * default display, if directed to do so. 479 */ 480 function get_option($option) { 481 if ($this->is_defaulted($option)) { 482 return $this->default_display->get_option($option); 483 } 484 485 if (array_key_exists($option, $this->options)) { 486 return $this->options[$option]; 487 } 488 } 489 490 /** 491 * Determine if the display's style uses fields. 492 */ 493 function uses_fields() { 494 $plugin = $this->get_plugin(); 495 if ($plugin) { 496 return $plugin->uses_fields(); 497 } 498 } 499 500 /** 501 * Get the display or row plugin, if it exists. 502 */ 503 function get_plugin($type = 'style', $name = NULL) { 504 if (!$name) { 505 $name = $this->get_option($type . '_plugin'); 506 } 507 508 $plugin = views_get_plugin($type, $name); 509 if ($plugin) { 510 $options = $this->get_option($type . '_options'); 511 $plugin->init($this->view, $this->display, $options); 512 return $plugin; 513 } 514 } 515 516 /** 517 * Get the access plugin 518 */ 519 function get_access_plugin($name = NULL) { 520 if (!$name) { 521 $access = $this->get_option('access'); 522 $name = $access['type']; 523 } 524 525 $plugin = views_get_plugin('access', $name); 526 if ($plugin) { 527 $plugin->init($this->view, $this->display); 528 return $plugin; 529 } 530 } 531 532 /** 533 * Get the cache plugin 534 */ 535 function get_cache_plugin($name = NULL) { 536 if (!$name) { 537 $cache = $this->get_option('cache'); 538 $name = $cache['type']; 539 } 540 541 $plugin = views_get_plugin('cache', $name); 542 if ($plugin) { 543 $plugin->init($this->view, $this->display); 544 return $plugin; 545 } 546 } 547 548 /** 549 * Get the handler object for a single handler. 550 */ 551 function &get_handler($type, $id) { 552 if (!isset($this->handlers[$type])) { 553 $this->get_handlers($type); 554 } 555 556 if (isset($this->handlers[$type][$id])) { 557 return $this->handlers[$type][$id]; 558 } 559 560 // So we can return a reference. 561 $null = NULL; 562 return $null; 563 } 564 565 /** 566 * Get a full array of handlers for $type. This caches them. 567 */ 568 function get_handlers($type) { 569 if (!isset($this->handlers[$type])) { 570 $this->handlers[$type] = array(); 571 $types = views_object_types(); 572 $plural = $types[$type]['plural']; 573 foreach ($this->get_option($plural) as $id => $info) { 574 if ($info['id'] != $id) { 575 $info['id'] = $id; 576 } 577 578 $handler = views_get_handler($info['table'], $info['field'], $type); 579 if ($handler) { 580 $handler->init($this->view, $info); 581 $this->handlers[$type][$id] = &$handler; 582 } 583 584 // Prevent reference problems. 585 unset($handler); 586 } 587 } 588 589 return $this->handlers[$type]; 590 } 591 592 /** 593 * Retrieve a list of fields for the current display with the 594 * relationship associated if it exists. 595 */ 596 function get_field_labels() { 597 $options = array(); 598 foreach ($this->get_handlers('relationship') as $relationship => $handler) { 599 if ($label = $handler->label()) { 600 $relationships[$relationship] = $label; 601 } 602 else { 603 $relationships[$relationship] = $handler->ui_name(); 604 } 605 } 606 607 foreach ($this->get_handlers('field') as $id => $handler) { 608 if ($label = $handler->label()) { 609 $options[$id] = $label; 610 } 611 else { 612 $options[$id] = $handler->ui_name(); 613 } 614 if (!empty($handler->options['relationship']) && !empty($relationships[$handler->options['relationship']])) { 615 $options[$id] = '(' . $relationships[$handler->options['relationship']] . ') ' . $options[$id]; 616 } 617 } 618 return $options; 619 } 620 621 /** 622 * Intelligently set an option either from this display or from the 623 * default display, if directed to do so. 624 */ 625 function set_option($option, $value) { 626 if ($this->is_defaulted($option)) { 627 return $this->default_display->set_option($option, $value); 628 } 629 630 // Set this in two places: On the handler where we'll notice it 631 // but also on the display object so it gets saved. This should 632 // only be a temporary fix. 633 $this->display->display_options[$option] = $value; 634 return $this->options[$option] = $value; 635 } 636 637 /** 638 * Set an option and force it to be an override. 639 */ 640 function override_option($option, $value) { 641 $this->set_override($option, FALSE); 642 $this->set_option($option, $value); 643 } 644 645 /** 646 * Because forms may be split up into sections, this provides 647 * an easy URL to exactly the right section. Don't override this. 648 */ 649 function option_link($text, $section, $class = '', $title = '') { 650 if (!empty($class)) { 651 $text = '<span>' . $text . '</span>'; 652 } 653 654 if (!trim($text)) { 655 $text = t('Broken field'); 656 } 657 658 if (empty($title)) { 659 $title = $text; 660 } 661 662 return l($text, 'admin/build/views/nojs/display/' . $this->view->name . '/' . $this->display->id . '/' . $section, array('attributes' => array('class' => 'views-ajax-link ' . $class, 'title' => $title), 'html' => TRUE)); 663 } 664 665 /** 666 * Provide the default summary for options in the views UI. 667 * 668 * This output is returned as an array. 669 */ 670 function options_summary(&$categories, &$options) { 671 $categories['basic'] = array( 672 'title' => t('Basic settings'), 673 ); 674 675 $options['display_title'] = array( 676 'category' => 'basic', 677 'title' => t('Name'), 678 'value' => check_plain($this->display->display_title), 679 'desc' => t('Change the name of this display.'), 680 ); 681 682 $title = strip_tags($this->get_option('title')); 683 if (!$title) { 684 $title = t('None'); 685 } 686 687 $options['title'] = array( 688 'category' => 'basic', 689 'title' => t('Title'), 690 'value' => $title, 691 'desc' => t('Change the title that this display will use.'), 692 ); 693 694 $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin')); 695 $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin['title']; 696 697 $style = ''; 698 699 $options['style_plugin'] = array( 700 'category' => 'basic', 701 'title' => t('Style'), 702 'value' => $style_title, 703 'desc' => t('Change the style plugin.'), 704 ); 705 706 // This adds a 'Settings' link to the style_options setting if the style has options. 707 if (!empty($style_plugin['uses options'])) { 708 $options['style_plugin']['links']['style_options'] = t('Change settings for this style'); 709 } 710 711 if (!empty($style_plugin['uses row plugin'])) { 712 $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin')); 713 $row_title = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin['title']; 714 715 $options['row_plugin'] = array( 716 'category' => 'basic', 717 'title' => t('Row style'), 718 'value' => $row_title, 719 'desc' => t('Change the row plugin.'), 720 ); 721 // This adds a 'Settings' link to the row_options setting if the row style has options. 722 if (!empty($row_plugin['uses options'])) { 723 $options['row_plugin']['links']['row_options'] = t('Change settings for this style'); 724 } 725 } 726 if (!empty($this->definition['use ajax'])) { 727 $options['use_ajax'] = array( 728 'category' => 'basic', 729 'title' => t('Use AJAX'), 730 'value' => $this->get_option('use_ajax') ? t('Yes') : t('No'), 731 'desc' => t('Change whether or not this display will use AJAX.'), 732 ); 733 } 734 735 if (!empty($this->definition['use pager'])) { 736 $options['use_pager'] = array( 737 'category' => 'basic', 738 'title' => t('Use pager'), 739 'value' => $this->get_option('use_pager') ? ($this->get_option('use_pager') === 'mini' ? t('Mini') : t('Yes')) : t('No'), 740 'desc' => t("Change this display's pager setting."), 741 ); 742 } 743 744 $items = intval($this->get_option('items_per_page')); 745 $options['items_per_page'] = array( 746 'category' => 'basic', 747 'title' => $this->use_pager() ? t('Items per page') : t('Items to display'), 748 'value' => $items ? $items : t('Unlimited'), 749 'desc' => t('Change how many items to display.'), 750 ); 751 752 if (!empty($this->definition['use more'])) { 753 $options['use_more'] = array( 754 'category' => 'basic', 755 'title' => t('More link'), 756 'value' => $this->get_option('use_more') ? t('Yes') : t('No'), 757 'desc' => t('Specify whether this display will provide a "more" link.'), 758 ); 759 } 760 761 $options['distinct'] = array( 762 'category' => 'basic', 763 'title' => t('Distinct'), 764 'value' => $this->get_option('distinct') ? t('Yes') : t('No'), 765 'desc' => t('Display only distinct items, without duplicates.'), 766 ); 767 768 $access_plugin = $this->get_access_plugin(); 769 if (!$access_plugin) { 770 // default to the no access control plugin. 771 $access_plugin = views_get_plugin('access', 'none'); 772 } 773 774 $access_str = $access_plugin->summary_title(); 775 776 $options['access'] = array( 777 'category' => 'basic', 778 'title' => t('Access'), 779 'value' => $access_str, 780 'desc' => t('Specify access control type for this display.'), 781 ); 782 783 if (!empty($access_plugin->definition['uses options'])) { 784 $options['access']['links']['access_options'] = t('Change settings for this access type.'); 785 } 786 787 $cache_plugin = $this->get_cache_plugin(); 788 if (!$cache_plugin) { 789 // default to the no cache control plugin. 790 $cache_plugin = views_get_plugin('cache', 'none'); 791 } 792 793 $cache_str = $cache_plugin->summary_title(); 794 795 $options['cache'] = array( 796 'category' => 'basic', 797 'title' => t('Caching'), 798 'value' => $cache_str, 799 'desc' => t('Specify caching type for this display.'), 800 ); 801 802 if (!empty($cache_plugin->definition['uses options'])) { 803 $options['cache']['links']['cache_options'] = t('Change settings for this caching type.'); 804 } 805 806 if ($this->uses_link_display()) { 807 // Only show the 'link display' if there is more than one option. 808 $count = 0; 809 foreach ($this->view->display as $display_id => $display) { 810 if (is_object($display->handler) && $display->handler->has_path()) { 811 $count++; 812 } 813 if ($count > 1) { 814 break; 815 } 816 } 817 818 if ($count > 1) { 819 $display_id = $this->get_link_display(); 820 $link_display = empty($this->view->display[$display_id]) ? t('None') : check_plain($this->view->display[$display_id]->display_title); 821 $options['link_display'] = array( 822 'category' => 'basic', 823 'title' => t('Link display'), 824 'value' => $link_display, 825 'desc' => t('Specify which display this display will link to.'), 826 ); 827 } 828 } 829 830 $options['exposed_block'] = array( 831 'category' => 'basic', 832 'title' => t('Exposed form in block'), 833 'value' => $this->get_option('exposed_block') ? t('Yes') : t('No'), 834 'desc' => t('Allow the exposed form to appear in a block instead of the view.'), 835 ); 836 837 foreach (array('header' => t('Header'), 'footer' => t('Footer'), 'empty' => t('Empty text')) as $type => $name) { 838 if (!$this->get_option($type)) { 839 $field = t('None'); 840 } 841 else { 842 // A lot of code to get the name of the filter format. 843 $fmt_string = $this->get_option($type . '_format'); 844 if (empty($fmt_string)) { 845 $fmt_string = FILTER_FORMAT_DEFAULT; 846 } 847 $format_val = filter_resolve_format($fmt_string); 848 $format = filter_formats($format_val); 849 if ($format) { 850 $field = check_plain($format->name); 851 } 852 else { 853 $field = t('Unknown/missing format'); 854 } 855 } 856 857 $options[$type] = array( 858 'category' => 'basic', 859 'title' => $name, 860 'value' => $field, 861 'desc' => t("Change this display's !name.", array('!name' => strtolower($name))), 862 ); 863 } 864 865 $css_class = check_plain(trim($this->get_option('css_class'))); 866 if (!$css_class) { 867 $css_class = t('None'); 868 } 869 870 $options['css_class'] = array( 871 'category' => 'basic', 872 'title' => t('CSS class'), 873 'value' => $css_class, 874 'desc' => t('Change the CSS class name(s) that will be added to this display.'), 875 ); 876 877 $options['analyze-theme'] = array( 878 'category' => 'basic', 879 'title' => t('Theme'), 880 'value' => t('Information'), 881 'desc' => t('Get information on how to theme this display'), 882 ); 883 } 884 885 /** 886 * Provide the default form for setting options. 887 */ 888 function options_form(&$form, &$form_state) { 889 if ($this->defaultable_sections($form_state['section'])) { 890 $this->add_override_button($form, $form_state, $form_state['section']); 891 } 892 $form['#title'] = check_plain($this->display->display_title) . ': '; 893 894 // Set the 'section' to hilite on the form. 895 // If it's the item we're looking at is pulling from the default display, 896 // reflect that. Don't use is_defaulted since we want it to show up even 897 // on the default display. 898 if (!empty($this->options['defaults'][$form_state['section']])) { 899 $form['#section'] = 'default-' . $form_state['section']; 900 } 901 else { 902 $form['#section'] = $this->display->id . '-' . $form_state['section']; 903 } 904 905 switch ($form_state['section']) { 906 case 'display_title': 907 $form['#title'] .= t('The name of this display'); 908 $form['display_title'] = array( 909 '#type' => 'textfield', 910 '#description' => t('This title will appear only in the administrative interface for the View.'), 911 '#default_value' => $this->display->display_title, 912 ); 913 break; 914 case 'title': 915 $form['#title'] .= t('The title of this view'); 916 $form['title'] = array( 917 '#type' => 'textfield', 918 '#description' => t('This title will be displayed with the view, wherever titles are normally displayed; i.e, as the page title, block title, etc.'), 919 '#default_value' => $this->get_option('title'), 920 ); 921 break; 922 case 'css_class': 923 $form['#title'] .= t('CSS class'); 924 $form['css_class'] = array( 925 '#type' => 'textfield', 926 '#description' => t('The CSS class names will be added to the view. This enables you to use specific CSS code for each view. You may define multiples classes separated by spaces.'), 927 '#default_value' => $this->get_option('css_class'), 928 ); 929 break; 930 case 'use_ajax': 931 $form['#title'] .= t('Use AJAX when available to load this view'); 932 $form['description'] = array( 933 '#prefix' => '<div class="description form-item">', 934 '#suffix' => '</div>', 935 '#value' => t('If set, this view will use an AJAX mechanism for paging, table sorting and exposed filters. This means the entire page will not refresh. It is not recommended that you use this if this view is the main content of the page as it will prevent deep linking to specific pages, but it is very useful for side content.'), 936 ); 937 $form['use_ajax'] = array( 938 '#type' => 'radios', 939 '#options' => array(1 => t('Yes'), 0 => t('No')), 940 '#default_value' => $this->get_option('use_ajax') ? 1 : 0, 941 ); 942 break; 943 case 'use_pager': 944 $form['#title'] .= t('Use a pager for this view'); 945 $form['use_pager'] = array( 946 '#type' => 'radios', 947 '#options' => array(TRUE => t('Full pager'), 'mini' => t('Mini pager'), 0 => t('No')), 948 '#default_value' => $this->get_option('use_pager'), 949 ); 950 $form['pager_element'] = array( 951 '#type' => 'textfield', 952 '#title' => t('Pager element'), 953 '#description' => t("Unless you're experiencing problems with pagers related to this view, you should leave this at 0. If using multiple pagers on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add a lot of commas to your URLs, so avoid if possible."), 954 '#default_value' => intval($this->get_option('pager_element')), 955 ); 956 break; 957 case 'items_per_page': 958 $form['#title'] .= $this->use_pager() ? t('Items per page') : t('Items to display'); 959 960 $form['items_per_page'] = array( 961 '#type' => 'textfield', 962 '#description' => t('The number of items to display per page. Enter 0 for no limit.'), 963 '#default_value' => intval($this->get_option('items_per_page')), 964 ); 965 $form['offset'] = array( 966 '#type' => 'textfield', 967 '#title' => t('Offset'), 968 '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed. Offset can not be used if items to display is 0; instead use a very large number there.'), 969 '#default_value' => intval($this->get_option('offset')), 970 ); 971 break; 972 case 'use_more': 973 $form['#title'] .= t('Add a more link to the bottom of the display.'); 974 $form['use_more'] = array( 975 '#type' => 'checkbox', 976 '#title' => t('Create more link'), 977 '#description' => t("This will add a more link to the bottom of this view, which will link to the page view. If you have more than one page view, the link will point to the display specified in 'Link display' above."), 978 '#default_value' => $this->get_option('use_more'), 979 ); 980 $form['use_more_always'] = array( 981 '#type' => 'checkbox', 982 '#title' => t('Always display more link'), 983 '#description' => t("This will display the more link even if there are no more items to display."), 984 '#default_value' => $this->get_option('use_more_always'), 985 ); 986 $form['use_more_text'] = array( 987 '#type' => 'textfield', 988 '#title' => t('More link text'), 989 '#description' => t("The text to display for the more link."), 990 '#default_value' => $this->get_option('use_more_text'), 991 ); 992 break; 993 case 'distinct': 994 $form['#title'] .= t('Display only distinct items, without duplicates.'); 995 $form['distinct'] = array( 996 '#type' => 'checkbox', 997 '#title' => t('Distinct'), 998 '#description' => t('This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution.'), 999 '#default_value' => $this->get_option('distinct'), 1000 ); 1001 break; 1002 case 'access': 1003 $form['#title'] .= t('Access restrictions'); 1004 $form['access'] = array( 1005 '#prefix' => '<div class="clear-block">', 1006 '#suffix' => '</div>', 1007 '#tree' => TRUE, 1008 ); 1009 1010 $access = $this->get_option('access'); 1011 $form['access']['type'] = array( 1012 '#type' => 'radios', 1013 '#options' => views_fetch_plugin_names('access'), 1014 '#default_value' => $access['type'], 1015 ); 1016 1017 $access_plugin = views_fetch_plugin_data('access', $access['type']); 1018 if (!empty($access_plugin['uses options'])) { 1019 $form['markup'] = array( 1020 '#prefix' => '<div class="form-item description">', 1021 '#suffix' => '</div>', 1022 '#value' => t('You may also adjust the !settings for the currently selected access restriction by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'access_options'))), 1023 ); 1024 } 1025 1026 break; 1027 case 'access_options': 1028 $access = $this->get_option('access'); 1029 $plugin = $this->get_access_plugin(); 1030 $form['#title'] .= t('Access options'); 1031 if ($plugin) { 1032 $form['#help_topic'] = $plugin->definition['help topic']; 1033 $form['#help_module'] = $plugin->definition['module']; 1034 1035 $form['access_options'] = array( 1036 '#tree' => TRUE, 1037 ); 1038 $form['access_options']['type'] = array( 1039 '#type' => 'value', 1040 '#value' => $access['type'], 1041 ); 1042 $plugin->options_form($form['access_options'], $form_state); 1043 } 1044 break; 1045 case 'cache': 1046 $form['#title'] .= t('Caching'); 1047 $form['cache'] = array( 1048 '#prefix' => '<div class="clear-block">', 1049 '#suffix' => '</div>', 1050 '#tree' => TRUE, 1051 ); 1052 1053 $cache = $this->get_option('cache'); 1054 $form['cache']['type'] = array( 1055 '#type' => 'radios', 1056 '#options' => views_fetch_plugin_names('cache'), 1057 '#default_value' => $cache['type'], 1058 ); 1059 1060 $cache_plugin = views_fetch_plugin_data('cache', $cache['type']); 1061 if (!empty($cache_plugin['uses options'])) { 1062 $form['markup'] = array( 1063 '#prefix' => '<div class="form-item description">', 1064 '#suffix' => '</div>', 1065 '#value' => t('You may also adjust the !settings for the currently selected cache mechanism by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'cache_options'))), 1066 ); 1067 } 1068 break; 1069 case 'cache_options': 1070 $cache = $this->get_option('cache'); 1071 $plugin = $this->get_cache_plugin(); 1072 $form['#title'] .= t('Caching options'); 1073 if ($plugin) { 1074 $form['#help_topic'] = $plugin->definition['help topic']; 1075 $form['#help_module'] = $plugin->definition['module']; 1076 1077 $form['cache_options'] = array( 1078 '#tree' => TRUE, 1079 ); 1080 $form['cache_options']['type'] = array( 1081 '#type' => 'value', 1082 '#value' => $cache['type'], 1083 ); 1084 $plugin->options_form($form['cache_options'], $form_state); 1085 } 1086 break; 1087 case 'header': 1088 $form['#title'] .= t('Header'); 1089 $form['header_empty'] = array( 1090 '#type' => 'checkbox', 1091 '#title' => t('Display even if view has no result'), 1092 '#default_value' => $this->get_option('header_empty'), 1093 ); 1094 $form['header'] = array( 1095 '#type' => 'textarea', 1096 '#default_value' => $this->get_option('header'), 1097 '#rows' => 6, 1098 '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'), 1099 ); 1100 1101 $form['header_format'] = filter_form($this->get_option('header_format'), NULL, array('header_format')); 1102 break; 1103 case 'footer': 1104 $form['#title'] .= t('Footer'); 1105 $form['footer_empty'] = array( 1106 '#type' => 'checkbox', 1107 '#title' => t('Display even if view has no result'), 1108 '#default_value' => $this->get_option('footer_empty'), 1109 ); 1110 $form['footer'] = array( 1111 '#type' => 'textarea', 1112 '#default_value' => $this->get_option('footer'), 1113 '#rows' => 6, 1114 '#description' => t('Text to display beneath the view. May contain an explanation or links or whatever you like. Optional.'), 1115 ); 1116 1117 $form['footer_format'] = filter_form($this->get_option('footer_format'), NULL, array('footer_format')); 1118 break; 1119 case 'empty': 1120 $form['#title'] .= t('Empty text'); 1121 $form['empty'] = array( 1122 '#type' => 'textarea', 1123 '#default_value' => $this->get_option('empty'), 1124 '#rows' => 6, 1125 '#description' => t('Text to display if the view has no results. Optional.'), 1126 ); 1127 1128 $form['empty_format'] = filter_form($this->get_option('empty_format'), NULL, array('empty_format')); 1129 break; 1130 case 'style_plugin': 1131 $form['#title'] .= t('How should this view be styled'); 1132 $form['#help_topic'] = 'style'; 1133 $form['style_plugin'] = array( 1134 '#type' => 'radios', 1135 '#options' => views_fetch_plugin_names('style', $this->get_style_type(), array($this->view->base_table)), 1136 '#default_value' => $this->get_option('style_plugin'), 1137 '#description' => t('If the style you choose has settings, be sure to click the settings button that will appear next to it in the View summary.'), 1138 ); 1139 1140 $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin')); 1141 if (!empty($style_plugin['uses options'])) { 1142 $form['markup'] = array( 1143 '#prefix' => '<div class="form-item description">', 1144 '#suffix' => '</div>', 1145 '#value' => t('You may also adjust the !settings for the currently selected style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'style_options'))), 1146 ); 1147 } 1148 1149 break; 1150 case 'style_options': 1151 $form['#title'] .= t('Style options'); 1152 $style = TRUE; 1153 $type = 'style_plugin'; 1154 $name = $this->get_option('style_plugin'); 1155 1156 case 'row_options': 1157 if (!isset($name)) { 1158 $name = $this->get_option('row_plugin'); 1159 } 1160 // if row, $style will be empty. 1161 if (empty($style)) { 1162 $form['#title'] .= t('Row style options'); 1163 $type = 'row_plugin'; 1164 } 1165 $plugin = $this->get_plugin(empty($style) ? 'row' : 'style'); 1166 if ($plugin) { 1167 if (isset($plugin->definition['help topic'])) { 1168 $form['#help_topic'] = $plugin->definition['help topic']; 1169 $form['#help_module'] = $plugin->definition['module']; 1170 } 1171 $form[$form_state['section']] = array( 1172 '#tree' => TRUE, 1173 ); 1174 $plugin->options_form($form[$form_state['section']], $form_state); 1175 } 1176 break; 1177 case 'row_plugin': 1178 $form['#title'] .= t('How should each row in this view be styled'); 1179 $form['#help_topic'] = 'style-row'; 1180 $form['row_plugin'] = array( 1181 '#type' => 'radios', 1182 '#options' => views_fetch_plugin_names('row', $this->get_style_type(), array($this->view->base_table)), 1183 '#default_value' => $this->get_option('row_plugin'), 1184 ); 1185 1186 $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin')); 1187 if (!empty($row_plugin['uses options'])) { 1188 $form['markup'] = array( 1189 '#prefix' => '<div class="form-item description">', 1190 '#suffix' => '</div>', 1191 '#value' => t('You may also adjust the !settings for the currently selected row style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'row_options'))), 1192 ); 1193 } 1194 1195 break; 1196 case 'link_display': 1197 $form['#title'] .= t('Which display to use for path'); 1198 foreach ($this->view->display as $display_id => $display) { 1199 if ($display->handler->has_path()) { 1200 $options[$display_id] = $display->display_title; 1201 } 1202 } 1203 $form['link_display'] = array( 1204 '#type' => 'radios', 1205 '#options' => $options, 1206 '#description' => t("Which display to use to get this display's path for things like summary links, rss feed links, more links, etc."), 1207 '#default_value' => $this->get_link_display(), 1208 ); 1209 break; 1210 case 'analyze-theme': 1211 $form['#title'] .= t('Theming information'); 1212 $form['#help_topic'] = 'analyze-theme'; 1213 1214 if (isset($_POST['theme'])) { 1215 $this->view->theme = $_POST['theme']; 1216 } 1217 else if (empty($this->view->theme)) { 1218 $this->view->theme = variable_get('theme_default', 'garland'); 1219 } 1220 1221 global $custom_theme; 1222 $custom_theme = $this->view->theme; 1223 init_theme(); 1224 1225 $funcs = array(); 1226 // Get theme functions for the display. Note that some displays may 1227 // not have themes. The 'feed' display, for example, completely 1228 // delegates to the style. 1229 if (!empty($this->definition['theme'])) { 1230 $funcs[] = $this->option_link(t('Display output'), 'analyze-theme-display') . ': ' . $this->format_themes($this->theme_functions()); 1231 $themes = $this->additional_theme_functions(); 1232 if ($themes) { 1233 foreach ($themes as $theme) { 1234 $funcs[] = $this->option_link(t('Alternative display output'), 'analyze-theme-display') . ': ' . $this->format_themes($theme); 1235 } 1236 } 1237 } 1238 1239 $plugin = $this->get_plugin(); 1240 if ($plugin) { 1241 $funcs[] = $this->option_link(t('Style output'), 'analyze-theme-style') . ': ' . $this->format_themes($plugin->theme_functions(), $plugin->additional_theme_functions()); 1242 $themes = $plugin->additional_theme_functions(); 1243 if ($themes) { 1244 foreach ($themes as $theme) { 1245 $funcs[] = $this->option_link(t('Alternative style'), 'analyze-theme-style') . ': ' . $this->format_themes($theme); 1246 } 1247 } 1248 1249 if ($plugin->uses_row_plugin()) { 1250 $row_plugin = $this->get_plugin('row'); 1251 if ($row_plugin) { 1252 $funcs[] = $this->option_link(t('Row style output'), 'analyze-theme-row') . ': ' . $this->format_themes($row_plugin->theme_functions()); 1253 $themes = $row_plugin->additional_theme_functions(); 1254 if ($themes) { 1255 foreach ($themes as $theme) { 1256 $funcs[] = $this->option_link(t('Alternative row style'), 'analyze-theme-row') . ': ' . $this->format_themes($theme); 1257 } 1258 } 1259 } 1260 } 1261 1262 if ($plugin->uses_fields()) { 1263 foreach ($this->get_handlers('field') as $id => $handler) { 1264 $funcs[] = $this->option_link(t('Field @field (ID: @id)', array('@field' => $handler->ui_name(), '@id' => $id)), 'analyze-theme-field') . ': ' . $this->format_themes($handler->theme_functions()); 1265 } 1266 } 1267 } 1268 1269 $form['important'] = array( 1270 '#prefix' => '<div class="form-item description">', 1271 '#suffix' => '</div>', 1272 '#value' => '<p>' . t('This section lists all possible templates for the display plugin and for the style plugins, ordered roughly from the least specific to the most specific. The active template for each plugin -- which is the most specific template found on the system -- is highlighted in bold.') . '</p>', 1273 ); 1274 1275 foreach (list_themes() as $key => $theme) { 1276 $options[$key] = $theme->info['name']; 1277 } 1278 1279 $form['box'] = array( 1280 '#prefix' => '<div class="container-inline">', 1281 '#suffix' => '</div>', 1282 ); 1283 $form['box']['theme'] = array( 1284 '#type' => 'select', 1285 '#options' => $options, 1286 '#default_value' => $this->view->theme, 1287 ); 1288 1289 $form['box']['change'] = array( 1290 '#type' => 'submit', 1291 '#value' => t('Change theme'), 1292 '#submit' => array('views_ui_edit_display_form_change_theme'), 1293 ); 1294 1295 $form['analysis'] = array( 1296 '#prefix' => '<div class="form-item">', 1297 '#suffix' => '</div>', 1298 '#value' => theme('item_list', $funcs), 1299 ); 1300 1301 $form['rescan_button'] = array( 1302 '#prefix' => '<div class="form-item">', 1303 '#suffix' => '</div>', 1304 ); 1305 $form['rescan_button']['button'] = array( 1306 '#type' => 'submit', 1307 '#value' => t('Rescan template files'), 1308 '#submit' => array('views_ui_config_item_form_rescan'), 1309 ); 1310 $form['rescan_button']['markup'] = array( 1311 '#prefix' => '<div class="description">', 1312 '#suffix' => '</div>', 1313 '#value' => t("<strong>Important!</strong> When adding, removing, or renaming template files, it is necessary to make Drupal aware of the changes by making it rescan the files on your system. By clicking this button you clear Drupal's theme registry and thereby trigger this rescanning process. The highlighted templates above will then reflect the new state of your system."), 1314 ); 1315 1316 $form_state['ok_button'] = TRUE; 1317 break; 1318 case 'analyze-theme-display': 1319 $form['#title'] .= t('Theming information (display)'); 1320 $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>'; 1321 1322 if (empty($this->definition['theme'])) { 1323 $output .= t('This display has no theming information'); 1324 } 1325 else { 1326 $output .= '<p>' . t('This is the default theme template used for this display.') . '</p>'; 1327 $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($this->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>'; 1328 } 1329 1330 if (!empty($this->definition['additional themes'])) { 1331 foreach ($this->definition['additional themes'] as $theme => $type) { 1332 $output .= '<p>' . t('This is an alternative template for this display.') . '</p>'; 1333 $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>'; 1334 } 1335 } 1336 1337 $form['analysis'] = array( 1338 '#prefix' => '<div class="form-item">', 1339 '#suffix' => '</div>', 1340 '#value' => $output, 1341 ); 1342 1343 $form_state['ok_button'] = TRUE; 1344 break; 1345 case 'analyze-theme-style': 1346 $form['#title'] .= t('Theming information (style)'); 1347 $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>'; 1348 1349 $plugin = $this->get_plugin(); 1350 1351 if (empty($plugin->definition['theme'])) { 1352 $output .= t('This display has no style theming information'); 1353 } 1354 else { 1355 $output .= '<p>' . t('This is the default theme template used for this style.') . '</p>'; 1356 $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>'; 1357 } 1358 1359 if (!empty($plugin->definition['additional themes'])) { 1360 foreach ($plugin->definition['additional themes'] as $theme => $type) { 1361 $output .= '<p>' . t('This is an alternative template for this style.') . '</p>'; 1362 $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>'; 1363 } 1364 } 1365 1366 $form['analysis'] = array( 1367 '#prefix' => '<div class="form-item">', 1368 '#suffix' => '</div>', 1369 '#value' => $output, 1370 ); 1371 1372 $form_state['ok_button'] = TRUE; 1373 break; 1374 case 'analyze-theme-row': 1375 $form['#title'] .= t('Theming information (row style)'); 1376 $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>'; 1377 1378 $plugin = $this->get_plugin('row'); 1379 1380 if (empty($plugin->definition['theme'])) { 1381 $output .= t('This display has no row style theming information'); 1382 } 1383 else { 1384 $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>'; 1385 $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>'; 1386 } 1387 1388 if (!empty($plugin->definition['additional themes'])) { 1389 foreach ($plugin->definition['additional themes'] as $theme => $type) { 1390 $output .= '<p>' . t('This is an alternative template for this row style.') . '</p>'; 1391 $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>'; 1392 } 1393 } 1394 1395 $form['analysis'] = array( 1396 '#prefix' => '<div class="form-item">', 1397 '#suffix' => '</div>', 1398 '#value' => $output, 1399 ); 1400 1401 $form_state['ok_button'] = TRUE; 1402 break; 1403 case 'analyze-theme-field': 1404 $form['#title'] .= t('Theming information (row style)'); 1405 $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>'; 1406 1407 $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>'; 1408 1409 // Field templates aren't registered the normal way...and they're always 1410 // this one, anyhow. 1411 $output .= '<pre>' . check_plain(file_get_contents(drupal_get_path('module', 'views') . '/theme/views-view-field.tpl.php')) . '</pre>'; 1412 1413 $form['analysis'] = array( 1414 '#prefix' => '<div class="form-item">', 1415 '#suffix' => '</div>', 1416 '#value' => $output, 1417 ); 1418 $form_state['ok_button'] = TRUE; 1419 break; 1420 1421 case 'exposed_block': 1422 $form['#title'] .= t('Put the exposed form in a block'); 1423 $form['description'] = array( 1424 '#prefix' => '<div class="description form-item">', 1425 '#suffix' => '</div>', 1426 '#value' => t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.'), 1427 ); 1428 $form['exposed_block'] = array( 1429 '#type' => 'radios', 1430 '#options' => array(1 => t('Yes'), 0 => t('No')), 1431 '#default_value' => $this->get_option('exposed_block') ? 1 : 0, 1432 ); 1433 break; 1434 } 1435 } 1436 1437 /** 1438 * Format a list of theme templates for output by the theme info helper. 1439 */ 1440 function format_themes($themes) { 1441 $registry = theme_get_registry(); 1442 1443 // Run through the theme engine variables, if necessary 1444 global $theme_engine; 1445 $extension = '.tpl.php'; 1446 if (isset($theme_engine)) { 1447 $extension_function = $theme_engine . '_extension'; 1448 if (function_exists($extension_function)) { 1449 $extension = $extension_function(); 1450 } 1451 } 1452 1453 $output = ''; 1454 $picked = FALSE; 1455 foreach ($themes as $theme) { 1456 $template = strtr($theme, '_', '-') . $extension; 1457 if (!$picked && !empty($registry[$theme])) { 1458 $template_path = isset($registry[$theme]['path']) ? $registry[$theme]['path'] . '/' : './'; 1459 if (file_exists($template_path . $template)) { 1460 $hint = t('File found in folder @template-path', array('@template-path' => $template_path)); 1461 $template = '<strong title="'. $hint .'">' . $template . '</strong>'; 1462 } 1463 else { 1464 $template = '<strong class="error">' . $template . ' ' . t('(File not found, in folder @template-path)', array('@template-path' => $template_path)) . '</strong>'; 1465 } 1466 $picked = TRUE; 1467 } 1468 $fixed[] = $template; 1469 } 1470 1471 return implode(', ', array_reverse($fixed)); 1472 } 1473 1474 /** 1475 * Validate the options form. 1476 */ 1477 function options_validate(&$form, &$form_state) { 1478 switch ($form_state['section']) { 1479 case 'display_title': 1480 if (empty($form_state['values']['display_title'])) { 1481 form_error($form['display_title'], t('Display title may not be empty.')); 1482 } 1483 break; 1484 case 'css_class': 1485 $css_class = $form_state['values']['css_class']; 1486 if (preg_match('/[^a-zA-Z0-9- ]/', $css_class)) { 1487 form_error($form['css_class'], t('CSS classes must be alphanumeric or dashes only.')); 1488 } 1489 break; 1490 case 'style_options': 1491 $style = TRUE; 1492 case 'row_options': 1493 // if row, $style will be empty. 1494 $plugin = $this->get_plugin(empty($style) ? 'row' : 'style'); 1495 if ($plugin) { 1496 $plugin->options_validate($form[$form_state['section']], $form_state); 1497 } 1498 break; 1499 case 'access_options': 1500 $plugin = $this->get_access_plugin(); 1501 if ($plugin) { 1502 $plugin->options_validate($form['access_options'], $form_state); 1503 } 1504 break; 1505 case 'cache_options': 1506 $plugin = $this->get_cache_plugin(); 1507 if ($plugin) { 1508 $plugin->options_validate($form['cache_options'], $form_state); 1509 } 1510 break; 1511 } 1512 } 1513 1514 /** 1515 * Perform any necessary changes to the form values prior to storage. 1516 * There is no need for this function to actually store the data. 1517 */ 1518 function options_submit(&$form, &$form_state) { 1519 // Not sure I like this being here, but it seems (?) like a logical place. 1520 $cache_plugin = $this->get_cache_plugin(); 1521 if ($cache_plugin) { 1522 $cache_plugin->cache_flush(); 1523 } 1524 1525 $section = $form_state['section']; 1526 switch ($section) { 1527 case 'display_title': 1528 $this->display->display_title = $form_state['values']['display_title']; 1529 break; 1530 case 'access': 1531 $access = $this->get_option('access'); 1532 if ($access['type'] != $form_state['values']['access']['type']) { 1533 $plugin = views_get_plugin('access', $form_state['values']['access']['type']); 1534 if ($plugin) { 1535 $access = array('type' => $form_state['values']['access']['type']); 1536 $plugin->option_defaults($access); 1537 $this->set_option('access', $access); 1538 if (!empty($plugin->definition['uses options'])) { 1539 views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('access_options')); 1540 } 1541 } 1542 } 1543 1544 break; 1545 case 'access_options': 1546 $plugin = views_get_plugin('access', $form_state['values'][$section]['type']); 1547 if ($plugin) { 1548 $plugin->options_submit($form['access_options'], $form_state); 1549 $this->set_option('access', $form_state['values'][$section]); 1550 } 1551 break; 1552 case 'cache': 1553 $cache = $this->get_option('cache'); 1554 if ($cache['type'] != $form_state['values']['cache']['type']) { 1555 $plugin = views_get_plugin('cache', $form_state['values']['cache']['type']); 1556 if ($plugin) { 1557 $cache = array('type' => $form_state['values']['cache']['type']); 1558 $plugin->option_defaults($cache); 1559 $this->set_option('cache', $cache); 1560 if (!empty($plugin->definition['uses options'])) { 1561 views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('cache_options')); 1562 } 1563 } 1564 } 1565 1566 break; 1567 case 'cache_options': 1568 $plugin = views_get_plugin('cache', $form_state['values'][$section]['type']); 1569 if ($plugin) { 1570 $plugin->options_submit($form['cache_options'], $form_state); 1571 $this->set_option('cache', $form_state['values'][$section]); 1572 } 1573 break; 1574 case 'title': 1575 case 'css_class': 1576 case 'link_display': 1577 $this->set_option($section, $form_state['values'][$section]); 1578 break; 1579 case 'use_ajax': 1580 $this->set_option($section, (bool)$form_state['values'][$section]); 1581 break; 1582 case 'use_pager': 1583 $this->set_option($section, $form_state['values'][$section]); 1584 $this->set_option('pager_element', intval($form_state['values']['pager_element'])); 1585 break; 1586 case 'items_per_page': 1587 $this->set_option($section, intval($form_state['values'][$section])); 1588 $this->set_option('offset', intval($form_state['values']['offset'])); 1589 break; 1590 case 'use_more': 1591 $this->set_option($section, intval($form_state['values'][$section])); 1592 $this->set_option('use_more_always', intval($form_state['values']['use_more_always'])); 1593 $this->set_option('use_more_text', $form_state['values']['use_more_text']); 1594 case 'distinct': 1595 $this->set_option($section, $form_state['values'][$section]); 1596 break; 1597 case 'row_plugin': 1598 // This if prevents resetting options to default if they don't change 1599 // the plugin. 1600 if ($this->get_option($section) != $form_state['values'][$section]) { 1601 $plugin = views_get_plugin('row', $form_state['values'][$section]); 1602 if ($plugin) { 1603 $this->set_option($section, $form_state['values'][$section]); 1604 $this->set_option('row_options', array()); 1605 1606 // send ajax form to options page if we use it. 1607 if (!empty($plugin->definition['uses options'])) { 1608 views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('row_options')); 1609 } 1610 } 1611 } 1612 break; 1613 case 'style_plugin': 1614 // This if prevents resetting options to default if they don't change 1615 // the plugin. 1616 if ($this->get_option($section) != $form_state['values'][$section]) { 1617 $plugin = views_get_plugin('style', $form_state['values'][$section]); 1618 if ($plugin) { 1619 $this->set_option($section, $form_state['values'][$section]); 1620 $this->set_option('style_options', array()); 1621 // send ajax form to options page if we use it. 1622 if (!empty($plugin->definition['uses options'])) { 1623 views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('style_options')); 1624 } 1625 } 1626 } 1627 break; 1628 case 'style_options': 1629 $style = TRUE; 1630 case 'row_options': 1631 // if row, $style will be empty. 1632 $plugin = $this->get_plugin(empty($style) ? 'row' : 'style'); 1633 if ($plugin) { 1634 $plugin->options_submit($form[$section], $form_state); 1635 } 1636 $this->set_option($section, $form_state['values'][$section]); 1637 break; 1638 case 'header': 1639 case 'footer': 1640 case 'empty': 1641 $this->set_option($section, $form_state['values'][$section]); 1642 $this->set_option($section . '_format', $form_state['values'][$section . '_format']); 1643 if ($section != 'empty') { 1644 $this->set_option($section . '_empty', $form_state['values'][$section . '_empty']); 1645 } 1646 break; 1647 case 'exposed_block': 1648 $this->set_option($section, (bool) $form_state['values'][$section]); 1649 break; 1650 } 1651 } 1652 1653 /** 1654 * Add an override button for a given section, allowing the user to 1655 * change whether this info is stored on the default display or on 1656 * the current display. 1657 */ 1658 function add_override_button(&$form, &$form_state, $section) { 1659 if ($this->is_default_display()) { 1660 return; 1661 } 1662 1663 $form['override'] = array( 1664 '#prefix' => '<div class="views-override clear-block">', 1665 '#suffix' => '</div>', 1666 ); 1667 if ($this->is_defaulted($section)) { 1668 $form['override']['button'] = array( 1669 '#type' => 'submit', 1670 '#value' => t('Override'), 1671 '#submit' => array('views_ui_edit_display_form_override'), 1672 ); 1673 $form['override']['markup'] = array( 1674 '#prefix' => '<div class="description">', 1675 '#value' => theme('advanced_help_topic', 'views', 'overrides') . t('Status: using default values.'), 1676 '#suffix' => '</div>', 1677 ); 1678 1679 $form_state['update_name'] = t('Update default display'); 1680 } 1681 else { 1682 $form['override']['button'] = array( 1683 '#type' => 'submit', 1684 '#value' => t('Use default'), 1685 '#submit' => array('views_ui_edit_display_form_override'), 1686 ); 1687 $form['override']['markup'] = array( 1688 '#prefix' => '<div class="description">', 1689 '#value' => theme('advanced_help_topic', 'views', 'overrides') . t('Status: using overridden values.'), 1690 '#suffix' => '</div>', 1691 ); 1692 1693 $form_state['update_name'] = NULL; 1694 } 1695 } 1696 1697 /** 1698 * If override/revert was clicked, perform the proper toggle. 1699 */ 1700 function options_override($form, &$form_state) { 1701 $this->set_override($form_state['section']); 1702 } 1703 1704 /** 1705 * Flip the override setting for the given section. 1706 */ 1707 function set_override($section, $new_state = NULL) { 1708 $options = $this->defaultable_sections($section); 1709 if (!$options) { 1710 return; 1711 } 1712 1713 if (!isset($new_state)) { 1714 $new_state = empty($this->options['defaults'][$section]); 1715 } 1716 1717 // For each option that is part of this group, fix our settings. 1718 foreach ($options as $option) { 1719 if ($new_state) { 1720 // Revert to defaults. 1721 unset($this->options[$option]); 1722 unset($this->display->display_options[$option]); 1723 } 1724 else { 1725 // copy existing values into our display. 1726 $this->options[$option] = $this->get_option($option); 1727 $this->display->display_options[$option] = $this->options[$option]; 1728 } 1729 $this->options['defaults'][$option] = $new_state; 1730 $this->display->display_options['defaults'][$option] = $new_state; 1731 } 1732 } 1733 1734 /** 1735 * Inject anything into the query that the display handler needs. 1736 */ 1737 function query() { 1738 // Make the query distinct if the option was set. 1739 if ($this->get_option('distinct')) { 1740 $this->view->query->set_distinct(); 1741 } 1742 } 1743 1744 /** 1745 * Not all display plugins will support filtering 1746 */ 1747 function render_filters() { } 1748 1749 /** 1750 * Render the 'more' link 1751 */ 1752 function render_more_link() { 1753 if ($this->use_more() && ($this->use_more_always() || !isset($this->view->total_rows) || $this->view->total_rows > $this->view->pager['items_per_page'])) { 1754 $path = $this->get_path(); 1755 if ($path) { 1756 $path = $this->view->get_url(NULL, $path); 1757 $url_options = array(); 1758 if (!empty($this->view->exposed_raw_input)) { 1759 $url_options['query'] = $this->view->exposed_raw_input; 1760 } 1761 $theme = views_theme_functions('views_more', $this->view, $this->display); 1762 $path = check_url(url($path, $url_options)); 1763 return theme($theme, $path, check_plain($this->use_more_text())); 1764 } 1765 } 1766 } 1767 1768 /** 1769 * Render a text area, using the proper format. 1770 */ 1771 function render_textarea($area) { 1772 static $formats = array(); 1773 1774 $value = $this->get_option($area); 1775 // Check to make sure the filter format exists; if not, we don't 1776 // display anything. 1777 $format = filter_resolve_format($this->get_option($area . '_format')); 1778 1779 if (!array_key_exists($format, $formats)) { 1780 $formats[$format] = db_result(db_query("SELECT name FROM {filter_formats} WHERE format = %d", $format)); 1781 } 1782 1783 if (!$formats[$format]) { 1784 return; 1785 } 1786 1787 if ($value) { 1788 return check_markup($value, $format, FALSE); 1789 } 1790 } 1791 1792 /** 1793 * Render the header of the view. 1794 */ 1795 function render_header() { 1796 if (!empty($this->view->result) || $this->get_option('header_empty')) { 1797 return $this->render_textarea('header'); 1798 } 1799 } 1800 1801 /** 1802 * Render the footer of the view. 1803 */ 1804 function render_footer() { 1805 if (!empty($this->view->result) || $this->get_option('footer_empty')) { 1806 return $this->render_textarea('footer'); 1807 } 1808 } 1809 1810 /** 1811 * Render the empty text of the view. 1812 */ 1813 function render_empty() { return $this->render_textarea('empty'); } 1814 /** 1815 * If this display creates a block, implement one of these. 1816 */ 1817 function hook_block($op = 'list', $delta = 0, $edit = array()) { return array(); } 1818 1819 /** 1820 * If this display creates a page with a menu item, implement it here. 1821 */ 1822 function hook_menu() { return array(); } 1823 1824 /** 1825 * Render this display. 1826 */ 1827 function render() { 1828 return theme($this->theme_functions(), $this->view); 1829 } 1830 1831 /** 1832 * Determine if the user has access to this display of the view. 1833 */ 1834 function access($account = NULL) { 1835 if (!isset($account)) { 1836 global $user; 1837 $account = $user; 1838 } 1839 1840 // Full override. 1841 if (user_access('access all views', $account)) { 1842 return TRUE; 1843 } 1844 1845 $plugin = $this->get_access_plugin(); 1846 if ($plugin) { 1847 return $plugin->access($account); 1848 } 1849 1850 // fallback to all access if no plugin. 1851 return TRUE; 1852 } 1853 1854 /** 1855 * Set up any variables on the view prior to execution. These are separated 1856 * from execute because they are extremely common and unlikely to be 1857 * overridden on an individual display. 1858 */ 1859 function pre_execute() { 1860 $this->view->set_use_ajax($this->use_ajax()); 1861 // Copy pager information from the display. 1862 $this->view->set_use_pager($this->use_pager()); 1863 $this->view->set_pager_element($this->get_option('pager_element')); 1864 $this->view->set_items_per_page($this->get_option('items_per_page')); 1865 $this->view->set_offset($this->get_option('offset')); 1866 if ($this->use_more() && !$this->use_more_always()) { 1867 $this->view->get_total_rows = TRUE; 1868 } 1869 } 1870 1871 /** 1872 * When used externally, this is how a view gets run and returns 1873 * data in the format required. 1874 * 1875 * The base class cannot be executed. 1876 */ 1877 function execute() { } 1878 1879 /** 1880 * Fully render the display for the purposes of a live preview or 1881 * some other AJAXy reason. 1882 */ 1883 function preview() { return $this->view->render(); } 1884 1885 /** 1886 * Displays can require a certain type of style plugin. By default, they will 1887 * be 'normal'. 1888 */ 1889 function get_style_type() { return 'normal'; } 1890 1891 /** 1892 * Make sure the display and all associated handlers are valid. 1893 * 1894 * @return 1895 * Empty array if the display is valid; an array of error strings if it is not. 1896 */ 1897 function validate() { 1898 $errors = array(); 1899 // Make sure displays that use fields HAVE fields. 1900 if ($this->uses_fields()) { 1901 $fields = FALSE; 1902 foreach ($this->get_handlers('field') as $field) { 1903 if (empty($field->options['exclude'])) { 1904 $fields = TRUE; 1905 } 1906 } 1907 1908 if (!$fields) { 1909 $errors[] = t('Display "@display" uses fields but there are none defined for it or all are excluded.', array('@display' => $this->display->display_title)); 1910 } 1911 } 1912 1913 if ($this->has_path() && !$this->get_option('path')) { 1914 $errors[] = t('Display "@display" uses a path but the path is undefined.', array('@display' => $this->display->display_title)); 1915 } 1916 1917 // Validate style plugin 1918 $style = $this->get_plugin(); 1919 if (empty($style)) { 1920 $errors[] = t('Display "@display" has an invalid style plugin.', array('@display' => $this->display->display_title)); 1921 } 1922 else { 1923 $result = $style->validate(); 1924 if (!empty($result) && is_array($result)) { 1925 $errors = array_merge($errors, $result); 1926 } 1927 } 1928 1929 // Validate handlers 1930 foreach (views_object_types() as $type => $info) { 1931 foreach ($this->get_handlers($type) as $handler) { 1932 $result = $handler->validate(); 1933 if (!empty($result) && is_array($result)) { 1934 $errors = array_merge($errors, $result); 1935 } 1936 } 1937 } 1938 1939 return $errors; 1940 } 1941 1942 /** 1943 * Check if the provided identifier is unique. 1944 */ 1945 function is_identifier_unique($id, $identifier) { 1946 foreach (views_object_types() as $type => $info) { 1947 foreach ($this->get_handlers($type) as $key => $handler) { 1948 if ($handler->can_expose() && $handler->is_exposed()) { 1949 if ($id != $key && $identifier == $handler->options['expose']['identifier']) { 1950 return FALSE; 1951 } 1952 } 1953 } 1954 } 1955 return TRUE; 1956 } 1957 1958 /** 1959 * Provide the block system with any exposed widget blocks for this display. 1960 */ 1961 function get_special_blocks() { 1962 $delta = '-exp-' . $this->view->name . '-' . $this->display->id; 1963 $desc = t('Exposed form: @view-@display_id', array('@view' => $this->view->name, '@display_id' => $this->display->id)); 1964 1965 return array( 1966 $delta => array( 1967 'info' => $desc, 1968 'cache' => BLOCK_NO_CACHE, 1969 ) 1970 ); 1971 } 1972 1973 /** 1974 * Render any special blocks provided for this display. 1975 */ 1976 function view_special_blocks($type) { 1977 if ($type == '-exp') { 1978 // avoid interfering with the admin forms. 1979 if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views') { 1980 return; 1981 } 1982 $this->view->init_handlers(); 1983 return array( 1984 'content' => $this->view->render_exposed_form(TRUE), 1985 ); 1986 } 1987 } 1988 1989 } 1990 1991 1992 /** 1993 * @} 1994 */ 1995
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |