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