[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/panels/plugins/display_renderers/ -> panels_renderer_editor.class.php (source)

   1  <?php
   2  // $Id: panels_renderer_editor.class.php,v 1.1.2.12 2010/10/29 19:05:21 merlinofchaos Exp $
   3  
   4  /**
   5   * @file
   6   * Class file to control the main Panels editor.
   7   */
   8  
   9  class panels_renderer_editor extends panels_renderer_standard {
  10  
  11    /**
  12     * An array of AJAX commands to return. If populated it will automatically
  13     * be used by the AJAX router.
  14     */
  15    var $commands = array();
  16    var $admin = TRUE;
  17    // -------------------------------------------------------------------------
  18    // Display edit rendering.
  19  
  20    function edit() {
  21      ctools_include('form');
  22      $form_state = array(
  23        'display' => &$this->display,
  24        'renderer' => &$this,
  25        'content_types' => $this->cache->content_types,
  26        're_render' => FALSE,
  27        'no_redirect' => TRUE,
  28        'display_title' => !empty($this->cache->display_title),
  29        'cache key' => $this->display->cache_key,
  30      );
  31  
  32      $output = ctools_build_form('panels_edit_display_form', $form_state);
  33      if ($output) {
  34        return $output;
  35      }
  36  
  37      // no output == submit
  38      if (!$output) {
  39        if (!empty($form_state['clicked_button']['#save-display'])) {
  40          drupal_set_message(t('Panel content has been updated.'));
  41          panels_save_display($this->display);
  42        }
  43        else {
  44          drupal_set_message(t('Your changes have been discarded.'));
  45        }
  46  
  47        panels_cache_clear('display', $this->display->did);
  48        return $this->display;
  49      }
  50    }
  51  
  52    function add_meta() {
  53      parent::add_meta();
  54      if ($this->admin) {
  55        ctools_include('ajax');
  56        ctools_include('modal');
  57        ctools_modal_add_js();
  58  
  59        ctools_add_js('panels-base', 'panels');
  60        ctools_add_js('display_editor', 'panels');
  61        ctools_add_css('panels_dnd', 'panels');
  62        ctools_add_css('panels_admin', 'panels');
  63      }
  64    }
  65  
  66    function render() {
  67      // Pass through to normal rendering if not in admin mode.
  68      if (!$this->admin) {
  69        return parent::render();
  70      }
  71  
  72      $this->add_meta();
  73  
  74      $output = '<div class="panels-dnd" id="panels-dnd-main">';
  75      $output .= $this->render_layout();
  76      $output .= '</div>';
  77  
  78      return $output;
  79    }
  80  
  81    function render_region($region_id, $panes) {
  82      // Pass through to normal rendering if not in admin mode.
  83      if (!$this->admin) {
  84        return parent::render_region($region_id, $panes);
  85      }
  86  
  87      $content = implode('', $panes);
  88  
  89      $panel_buttons = $this->get_region_links($region_id);
  90  
  91      // @todo this should be panel-region not panels-display -- but CSS and .js has to be updated.
  92      $output = "<div class='panels-display' id='panel-pane-$region_id'>";
  93      $output .= $panel_buttons;
  94      $output .= "<h2 class='label'>" . $this->plugins['layout']['panels'][$region_id] . "</h2>";
  95      $output .= $content;
  96      $output .= "</div>";
  97  
  98      return $output;
  99    }
 100  
 101    function render_pane(&$pane) {
 102      // Pass through to normal rendering if not in admin mode.
 103      if (!$this->admin) {
 104        return parent::render_pane($pane);
 105      }
 106  
 107      ctools_include('content');
 108      $content_type = ctools_get_content_type($pane->type);
 109  
 110      // This is just used for the title bar of the pane, not the content itself.
 111      // If we know the content type, use the appropriate title for that type,
 112      // otherwise, set the title using the content itself.
 113      $title = ctools_content_admin_title($content_type, $pane->subtype, $pane->configuration, $this->display->context);
 114      if (!$title) {
 115        $title = t('Deleted/missing content type @type', array('@type' => $pane->type));
 116      }
 117  
 118      $buttons = $this->get_pane_links($pane, $content_type);
 119  
 120      // Render administrative buttons for the pane.
 121  
 122      $block = new stdClass();
 123      if (empty($content_type)) {
 124        $block->title = '<em>' . t('Missing content type') . '</em>';
 125        $block->content = t('This pane\'s content type is either missing or has been deleted. This pane will not render.');
 126      }
 127      else {
 128        $block = ctools_content_admin_info($content_type, $pane->subtype, $pane->configuration, $this->display->context);
 129      }
 130  
 131      $output = '';
 132      $class = 'panel-pane';
 133  
 134      if (empty($pane->shown)) {
 135        $class .= ' hidden-pane';
 136      }
 137  
 138      if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
 139        $class .= ' panel-pane-is-title';
 140      }
 141  
 142      $output = '<div class="' . $class . '" id="panel-pane-' . $pane->pid . '">';
 143  
 144      if (!$block->title) {
 145        $block->title = t('No title');
 146      }
 147  
 148      $output .= '<div class="grabber">';
 149      if ($buttons) {
 150        $output .= '<span class="buttons">' . $buttons . '</span>';
 151      }
 152      $output .= '<span class="text">' . $title . '</span>';
 153      $output .= '</div>'; // grabber
 154  
 155      $output .= '<div class="panel-pane-collapsible">';
 156      $output .= '<div class="pane-title">' . $block->title . '</div>';
 157      $output .= '<div class="pane-content">' . filter_xss_admin($block->content) . '</div>';
 158      $output .= '</div>'; // panel-pane-collapsible
 159  
 160      $output .= '</div>'; // panel-pane
 161  
 162      return $output;
 163    }
 164  
 165    /**
 166     * Get the style links.
 167     *
 168     * This is abstracted out since we have styles on both panes and regions.
 169     */
 170    function get_style_links($type, $id = NULL) {
 171      $info = $this->get_style($type, $id);
 172      $style = $info[0];
 173      $conf = $info[1];
 174  
 175      $style_title = isset($style['title']) ? $style['title'] : t('Default');
 176  
 177      $style_links[] = array(
 178        'title' => $style_title,
 179        'attributes' => array('class' => 'panels-text'),
 180      );
 181  
 182      $style_links[] = array(
 183        'title' => t('Change'),
 184        'href' => $this->get_url('style-type', $type, $id),
 185        'attributes' => array('class' => 'ctools-use-modal'),
 186      );
 187  
 188      $function = $type != 'pane' ? 'settings form' : 'pane settings form';
 189      if (panels_plugin_get_function('styles', $style, $function)) {
 190        $style_links[] = array(
 191          'title' => t('Settings'),
 192          'href' => $this->get_url('style-settings', $type, $id),
 193          'attributes' => array('class' => 'ctools-use-modal'),
 194        );
 195      }
 196  
 197      return $style_links;
 198    }
 199  
 200    /**
 201     * Get the links for a panel display.
 202     *
 203     * This is abstracted out for easy ajax replacement.
 204     */
 205    function get_display_links() {
 206      $links = array();
 207      $style_links = $this->get_style_links('display');
 208  
 209      $links[] = array(
 210        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links($style_links),
 211        'html' => TRUE,
 212        'attributes' => array('class' => 'panels-sub-menu'),
 213      );
 214  
 215      if (user_access('use panels caching features')) {
 216        $links[] = array(
 217          'title' => '<hr />',
 218          'html' => TRUE,
 219        );
 220  
 221        $method = isset($this->display->cache['method']) ? $this->display->cache['method'] : 0;
 222        $info = panels_get_cache($method);
 223        $cache_method = isset($info['title']) ? $info['title'] : t('No caching');
 224  
 225        $cache_links[] = array(
 226          'title' => $cache_method,
 227          'attributes' => array('class' => 'panels-text'),
 228        );
 229        $cache_links[] = array(
 230          'title' => t('Change'),
 231          'href' => $this->get_url('cache-method', 'display'),
 232          'attributes' => array('class' => 'ctools-use-modal'),
 233        );
 234        if (panels_plugin_get_function('cache', $info, 'settings form')) {
 235          $cache_links[] = array(
 236            'title' => t('Settings'),
 237            'href' => $this->get_url('cache-settings', 'display'),
 238            'attributes' => array('class' => 'ctools-use-modal'),
 239          );
 240        }
 241  
 242        $links[] = array(
 243          'title' => '<span class="dropdown-header">' . t('Caching') . '</span>' . theme_links($cache_links),
 244          'html' => TRUE,
 245          'attributes' => array('class' => 'panels-sub-menu'),
 246        );
 247      }
 248  
 249      return theme('ctools_dropdown', t('Display settings'), $links, FALSE, 'panels-display-links');
 250    }
 251  
 252    /**
 253     * Render the links to display when editing a region.
 254     */
 255    function get_region_links($region_id) {
 256      $links = array();
 257      $links[] = array(
 258        'title' => t('Add content'),
 259        'href' => $this->get_url('select-content', $region_id),
 260        'attributes' => array(
 261          'class' => 'ctools-use-modal',
 262        ),
 263      );
 264  
 265      $links[] = array(
 266        'title' => '<hr />',
 267        'html' => TRUE,
 268      );
 269  
 270      $style_links = $this->get_style_links('region', $region_id);
 271  
 272      $links[] = array(
 273        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links($style_links),
 274        'html' => TRUE,
 275        'attributes' => array('class' => 'panels-sub-menu'),
 276      );
 277  
 278      return theme('ctools_dropdown', theme('image', ctools_image_path('icon-addcontent.png', 'panels')), $links, TRUE, 'pane-add-link panels-region-links-' . $region_id);
 279    }
 280  
 281    /**
 282     * Render the links to display when editing a pane.
 283     */
 284    function get_pane_links($pane, $content_type) {
 285      $links = array();
 286  
 287      if (!empty($pane->shown)) {
 288        $links[] = array(
 289          'title' => t('Disable this pane'),
 290          'href' => $this->get_url('hide', $pane->pid),
 291          'attributes' => array('class' => 'ctools-use-ajax'),
 292        );
 293      }
 294      else {
 295        $links[] = array(
 296          'title' => t('Enable this pane'),
 297          'href' => $this->get_url('show', $pane->pid),
 298          'attributes' => array('class' => 'ctools-use-ajax'),
 299        );
 300      }
 301  
 302      if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
 303        $links['panels-set-title'] = array(
 304          'title' => t('&#x2713;Panel title'),
 305          'html' => TRUE,
 306        );
 307      }
 308      else {
 309        $links['panels-set-title'] = array(
 310          'title' => t('Panel title'),
 311          'href' => $this->get_url('panel-title', $pane->pid),
 312          'attributes' => array('class' => 'ctools-use-ajax'),
 313        );
 314      }
 315  
 316      $subtype = ctools_content_get_subtype($content_type, $pane->subtype);
 317  
 318      if (ctools_content_editable($content_type, $subtype, $pane->configuration)) {
 319        $links[] = array(
 320          'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),
 321          'href' => $this->get_url('edit-pane', $pane->pid),
 322          'attributes' => array('class' => 'ctools-use-modal'),
 323        );
 324      }
 325  
 326      if (user_access('administer advanced pane settings')) {
 327        $links[] = array(
 328          'title' => t('CSS properties'),
 329          'href' => $this->get_url('pane-css', $pane->pid),
 330          'attributes' => array('class' => 'ctools-use-modal'),
 331        );
 332      }
 333  
 334      $links[] = array(
 335        'title' => '<hr />',
 336        'html' => TRUE,
 337      );
 338  
 339      $style_links = $this->get_style_links('pane', $pane->pid);
 340  
 341      $links[] = array(
 342        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links($style_links),
 343        'html' => TRUE,
 344        'attributes' => array('class' => 'panels-sub-menu'),
 345      );
 346  
 347      if (user_access('administer pane access')) {
 348        $links[] = array(
 349          'title' => '<hr />',
 350          'html' => TRUE,
 351        );
 352  
 353        $contexts = $this->display->context;
 354        // Make sure we have the logged in user context
 355        if (!isset($contexts['logged-in-user'])) {
 356          $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
 357        }
 358  
 359        $visibility_links = array();
 360  
 361        if (!empty($pane->access['plugins'])) {
 362          foreach ($pane->access['plugins'] as $id => $test) {
 363            $plugin = ctools_get_access_plugin($test['name']);
 364            $access_title  = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));
 365            $access_description = ctools_access_summary($plugin, $contexts, $test);
 366  
 367            $visibility_links[] = array(
 368              'title' => $access_description,
 369              'href' => $this->get_url('access-configure-test', $pane->pid, $id),
 370              'attributes' => array('class' => 'ctools-use-modal panels-italic'),
 371            );
 372          }
 373        }
 374        if (empty($visibility_links)) {
 375          $visibility_links[] = array(
 376            'title' => t('No rules'),
 377            'attributes' => array('class' => 'panels-text'),
 378          );
 379        }
 380  
 381        $visibility_links[] = array(
 382          'title' => t('Add new rule'),
 383          'href' => $this->get_url('access-add-test', $pane->pid),
 384          'attributes' => array('class' => 'ctools-use-modal'),
 385        );
 386  
 387        $visibility_links[] = array(
 388          'title' => t('Settings'),
 389          'href' => $this->get_url('access-settings', $pane->pid),
 390          'attributes' => array('class' => 'ctools-use-modal'),
 391        );
 392  
 393        $links[] = array(
 394          'title' => '<span class="dropdown-header">' . t('Visibility rules') . '</span>' . theme_links($visibility_links),
 395          'html' => TRUE,
 396          'attributes' => array('class' => 'panels-sub-menu'),
 397        );
 398      }
 399  
 400      if (panels_get_caches() && user_access('use panels caching features')) {
 401        $links[] = array(
 402          'title' => '<hr />',
 403          'html' => TRUE,
 404        );
 405  
 406        $method = isset($pane->cache['method']) ? $pane->cache['method'] : 0;
 407        $info = panels_get_cache($method);
 408        $cache_method = isset($info['title']) ? $info['title'] : t('No caching');
 409        $cache_links[] = array(
 410          'title' => $cache_method,
 411          'attributes' => array('class' => 'panels-text'),
 412        );
 413        $cache_links[] = array(
 414          'title' => t('Change'),
 415          'href' => $this->get_url('cache-method', $pane->pid),
 416          'attributes' => array('class' => 'ctools-use-modal'),
 417        );
 418        if (panels_plugin_get_function('cache', $info, 'settings form')) {
 419          $cache_links[] = array(
 420            'title' => t('Settings'),
 421            'href' => $this->get_url('cache-settings', $pane->pid),
 422            'attributes' => array('class' => 'ctools-use-modal'),
 423          );
 424        }
 425  
 426        $links[] = array(
 427          'title' => '<span class="dropdown-header">' . t('Caching') . '</span>' . theme_links($cache_links),
 428          'html' => TRUE,
 429          'attributes' => array('class' => 'panels-sub-menu'),
 430        );
 431      }
 432  
 433      $links[] = array(
 434        'title' => '<hr />',
 435        'html' => TRUE,
 436      );
 437  
 438      $links[] = array(
 439        'title' => t('Remove'),
 440        'href' => '#',
 441        'attributes' => array(
 442          'class' => 'pane-delete',
 443          'id' => "pane-delete-panel-pane-$pane->pid",
 444        ),
 445      );
 446  
 447      return theme('ctools_dropdown', theme('image', ctools_image_path('icon-configure.png', 'panels')), $links, TRUE);
 448    }
 449  
 450    // -----------------------------------------------------------------------
 451    // Display edit AJAX callbacks and helpers.
 452  
 453    /**
 454     * Generate a URL path for the AJAX editor.
 455     */
 456    function get_url() {
 457      $args = func_get_args();
 458      $command = array_shift($args);
 459      $url = 'panels/ajax/' . $this->plugin['name'] . '/' . $command . '/' . $this->display->cache_key;
 460      if ($args) {
 461        $url .= '/' . implode('/', $args);
 462      }
 463  
 464      return $url;
 465    }
 466  
 467    /**
 468     * AJAX command to show a pane.
 469     */
 470    function ajax_show($pid = NULL) {
 471      if (empty($this->display->content[$pid])) {
 472        ctools_ajax_render_error(t('Invalid pane id.'));
 473      }
 474  
 475      $this->display->content[$pid]->shown = TRUE;
 476      panels_edit_cache_set($this->cache);
 477  
 478      $this->command_update_pane($pid);
 479    }
 480  
 481    /**
 482     * AJAX command to show a pane.
 483     */
 484    function ajax_hide($pid = NULL) {
 485      if (empty($this->display->content[$pid])) {
 486        ctools_ajax_render_error(t('Invalid pane id.'));
 487      }
 488  
 489      $this->display->content[$pid]->shown = FALSE;
 490      panels_edit_cache_set($this->cache);
 491  
 492      $this->command_update_pane($pid);
 493    }
 494  
 495    /**
 496     * AJAX command to present a dialog with a list of available content.
 497     */
 498    function ajax_select_content($region = NULL, $category = NULL) {
 499      if (!array_key_exists($region, $this->plugins['layout']['panels'])) {
 500        ctools_modal_render(t('Error'), t('Invalid input'));
 501      }
 502  
 503      $title = t('Add content to !s', array('!s' => $this->plugins['layout']['panels'][$region]));
 504  
 505      $categories = $this->get_categories($this->cache->content_types);
 506  
 507      if (empty($categories)) {
 508        $output = t('There are no content types you may add to this display.');
 509      }
 510      else {
 511        $output = '<div class="panels-add-content-modal">';
 512        $selector = $this->render_category_selector($categories, $category, $region);
 513  
 514        $content = !empty($categories[$category]['content']) ? $categories[$category]['content'] : array();
 515        $center = $this->render_category($content, $category, $region);
 516  
 517        $output .= '<div class="panels-section-column panels-section-column-categories">'
 518          . '<div class="inside">' . $selector . '</div></div>';
 519        $output .= $center;
 520        $output .= '</div>'; // panels-add-content-modal
 521      }
 522  
 523      $this->commands[] = ctools_modal_command_display($title, $output);
 524    }
 525  
 526    /**
 527     * Return the category name and the category key of a given content
 528     * type.
 529     *
 530     * @todo -- this should be in CTools.
 531     */
 532    function get_category($content_type) {
 533      if (isset($content_type['top level'])) {
 534        $category = 'root';
 535      }
 536      else if (isset($content_type['category'])) {
 537        if (is_array($content_type['category'])) {
 538          list($category, $weight) = $content_type['category'];
 539        }
 540        else {
 541          $category = $content_type['category'];
 542        }
 543      }
 544      else {
 545        $category = t('Uncategorized');
 546      }
 547  
 548      return array(preg_replace('/[^a-z0-9]/', '-', strtolower($category)), $category);
 549    }
 550  
 551  
 552    /**
 553     * Create a list of categories from all of the content type.
 554     *
 555     * @return array
 556     *   An array of categories. Each entry in the array will also be an array
 557     *   with 'title' as the printable title of the category, and 'content'
 558     *   being an array of all content in the category. Each item in the 'content'
 559     *   array contain the array plugin definition so that it can be later
 560     *   found in the content array. They will be keyed by the title so that they
 561     *   can be sorted.
 562     */
 563    function get_categories($content_types) {
 564      $categories = array();
 565      $category_names = array();
 566  
 567      foreach ($content_types as $type_name => $subtypes) {
 568        foreach ($subtypes as $subtype_name => $content_type) {
 569          list($category_key, $category) = $this->get_category($content_type);
 570  
 571          if (empty($categories[$category_key])) {
 572            $categories[$category_key] = array(
 573              'title' => $category,
 574              'content' => array(),
 575            );
 576            $category_names[$category_key] = $category;
 577          }
 578  
 579          $content_title = filter_xss_admin($content_type['title']);
 580  
 581          // Ensure content with the same title doesn't overwrite each other.
 582          while (isset($categories[$category_key]['content'][$content_title])) {
 583            $content_title .= '-';
 584          }
 585  
 586          $categories[$category_key]['content'][$content_title] = $content_type;
 587          $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
 588          $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
 589        }
 590      }
 591  
 592      // Now sort
 593      natcasesort($category_names);
 594      foreach ($category_names as $category => $name) {
 595        $output[$category] = $categories[$category];
 596      }
 597  
 598      return $output;
 599    }
 600  
 601    /**
 602     * Render a single link to add a content type.
 603     */
 604    function render_add_content_link($region, $content_type) {
 605      $title = filter_xss_admin($content_type['title']);
 606      $description = isset($content_type['description']) ? $content_type['description'] : $title;
 607      $icon = ctools_content_admin_icon($content_type);
 608      $url = $this->get_url('add-pane', $region, $content_type['type_name'], $content_type['subtype_name']);
 609  
 610      $output = '<div class="content-type-button clear-block">';
 611      $output .= ctools_ajax_image_button($icon, $url, $description, 'panels-modal-add-config');
 612      $output .= '<div>' . ctools_ajax_text_button($title, $url, $description, 'panels-modal-add-config') . '</div>';
 613      $output .= '</div>';
 614  
 615      return $output;
 616    }
 617  
 618    /**
 619     * Render the selector widget in the add content modal to select categories.
 620     */
 621    function render_category_selector($categories, $category, $region) {
 622      $output = '<div class="panels-categories-box">';
 623  
 624      // Render our list of categories in column 0.
 625      foreach ($categories as $key => $category_info) {
 626        if ($key == 'root') {
 627          continue;
 628        }
 629  
 630        $class = 'panels-modal-add-category';
 631        if ($key == $category) {
 632          $class .= ' active';
 633        }
 634  
 635        $url = $this->get_url('select-content', $region, $key);
 636        $output .= ctools_ajax_text_button($category_info['title'], $url, '', $class);
 637      }
 638  
 639      $output .= '</div>'; // panels-categories-box
 640  
 641      if (!empty($categories['root'])) {
 642        foreach ($categories['root']['content'] as $content_type) {
 643          $output .= $this->render_add_content_link($region, $content_type);
 644        }
 645      }
 646  
 647      return $output;
 648    }
 649  
 650    /**
 651     * Render all of the content links in a category.
 652     */
 653    function render_category($content, $category, $region) {
 654      if (empty($category) || empty($content) || $category == 'root') {
 655        $output = '<div class="panels-categories-description">';
 656        $output .= t('Content options are divided by category. Please select a category from the left to proceed.');
 657        $output .= '</div>';
 658      }
 659      else {
 660        $titles = array_keys($content);
 661        natcasesort($titles);
 662  
 663        // Fill out the info for our current category.
 664        $columns = 2;
 665        $col[1] = '';
 666        $col[2] = '';
 667  
 668        $col_size = count($titles) / $columns;
 669        $count = 0;
 670        foreach ($titles as $title) {
 671          $which = floor($count++ / $col_size) + 1; // we leave 0 for the categories.
 672          $col[$which] .= $this->render_add_content_link($region, $content[$title]);
 673        }
 674  
 675        $output = '<div class="panels-section-columns">';
 676        foreach ($col as $id => $column) {
 677          $output .= '<div class="panels-section-column panels-section-column-' . $id . '">'
 678          . '<div class="inside">' . $column . '</div></div>';
 679        }
 680        $output .= '</div>'; // columns
 681      }
 682  
 683      if ($messages = theme('status_messages')) {
 684        $output = '<div class="messages">' . $messages . '</div>' . $output;
 685      }
 686      return $output;
 687    }
 688  
 689    /**
 690     * AJAX entry point to add a new pane.
 691     */
 692    function ajax_add_pane($region = NULL, $type_name = NULL, $subtype_name = NULL, $step = NULL) {
 693      $content_type = ctools_get_content_type($type_name);
 694      $subtype = ctools_content_get_subtype($content_type, $subtype_name);
 695  
 696      if (!isset($step) || !isset($this->cache->new_pane)) {
 697        $pane = panels_new_pane($type_name, $subtype_name, TRUE);
 698        $this->cache->new_pane = &$pane;
 699      }
 700      else {
 701        $pane = &$this->cache->new_pane;
 702      }
 703  
 704      $form_state = array(
 705        'display' => &$this->cache->display,
 706        'contexts' => $this->cache->display->context,
 707        'pane' => &$pane,
 708        'cache_key' => $this->display->cache_key,
 709        'cache' => &$this->cache,
 710        'ajax' => TRUE,
 711        'modal' => TRUE,
 712        // This will force the system to not automatically render.
 713        'modal return' => TRUE,
 714        'commands' => array(),
 715      );
 716  
 717      $form_info = array(
 718        'path' => $this->get_url('add-pane', $region, $type_name, $subtype_name, '%step'),
 719        'show cancel' => TRUE,
 720        'next callback' => 'panels_ajax_edit_pane_next',
 721        'finish callback' => 'panels_ajax_edit_pane_finish',
 722        'cancel callback' => 'panels_ajax_edit_pane_cancel',
 723      );
 724  
 725      $output = ctools_content_form('add', $form_info, $form_state, $content_type, $pane->subtype, $subtype, $pane->configuration, $step);
 726  
 727      // If $rc is FALSE, there was no actual form.
 728      if ($output === FALSE || !empty($form_state['complete'])) {
 729        $pane = $this->cache->new_pane;
 730        unset($this->cache->new_pane);
 731  
 732        // Add the pane to the display
 733        $this->display->add_pane($pane, $region);
 734        panels_edit_cache_set($this->cache);
 735  
 736        // Tell the client to draw the pane
 737        $this->command_add_pane($pane);
 738  
 739        // Dismiss the modal.
 740        $this->commands[] = ctools_modal_command_dismiss();
 741      }
 742      else if (!empty($form_state['cancel'])) {
 743        // If cancelling, return to the activity.
 744        list($category_key, $category) = $this->get_category($subtype);
 745        $this->ajax_select_content($region, $category_key);
 746      }
 747      else {
 748        // This overwrites any previous commands.
 749        $this->commands = ctools_modal_form_render($form_state, $output);
 750      }
 751    }
 752  
 753    /**
 754     * AJAX entry point to edit a pane.
 755     */
 756    function ajax_edit_pane($pid = NULL, $step = NULL) {
 757      if (empty($this->cache->display->content[$pid])) {
 758        ctools_modal_render(t('Error'), t('Invalid pane id.'));
 759      }
 760  
 761      $pane = &$this->cache->display->content[$pid];
 762  
 763      $content_type = ctools_get_content_type($pane->type);
 764      $subtype = ctools_content_get_subtype($content_type, $pane->subtype);
 765  
 766      $form_state = array(
 767        'display' => &$this->cache->display,
 768        'contexts' => $this->cache->display->context,
 769        'pane' => &$pane,
 770        'cache' => &$this->cache,
 771        'ajax' => TRUE,
 772        'modal' => TRUE,
 773        'modal return' => TRUE,
 774        'commands' => array(),
 775      );
 776  
 777      $form_info = array(
 778        'path' => $this->get_url('edit-pane', $pid, '%step'),
 779        'show cancel' => TRUE,
 780        'next callback' => 'panels_ajax_edit_pane_next',
 781        'finish callback' => 'panels_ajax_edit_pane_finish',
 782        'cancel callback' => 'panels_ajax_edit_pane_cancel',
 783      );
 784  
 785      $output = ctools_content_form('edit', $form_info, $form_state, $content_type, $pane->subtype,  $subtype, $pane->configuration, $step);
 786  
 787      // If $rc is FALSE, there was no actual form.
 788      if ($output === FALSE || !empty($form_state['cancel'])) {
 789        // Dismiss the modal.
 790        $this->commands[] = ctools_modal_command_dismiss();
 791      }
 792      else if (!empty($form_state['complete'])) {
 793        panels_edit_cache_set($this->cache);
 794        $this->command_update_pane($pid);
 795        $this->commands[] = ctools_modal_command_dismiss();
 796      }
 797      else {
 798        // This overwrites any previous commands.
 799        $this->commands = ctools_modal_form_render($form_state, $output);
 800      }
 801    }
 802  
 803    /**
 804     * AJAX entry point to select which pane is currently the title.
 805     *
 806     * @param string $pid
 807     *   The pane id for the pane object whose title state we're setting.
 808     */
 809    function ajax_panel_title($pid = NULL) {
 810      if (empty($this->display->content[$pid])) {
 811        ctools_ajax_render_error(t('Invalid pane id.'));
 812      }
 813  
 814      $pane = &$this->display->content[$pid];
 815  
 816      $old_title = !empty($this->display->title_pane) ? $this->display->title_pane : NULL;
 817      $this->display->title_pane = $pid;
 818  
 819      panels_edit_cache_set($this->cache);
 820  
 821      $this->command_update_pane($pane);
 822  
 823      if ($old_title && !empty($this->cache->display->content[$old_title])) {
 824        $this->command_update_pane($this->cache->display->content[$old_title]);
 825      }
 826    }
 827  
 828    /**
 829     * AJAX entry point to configure the cache method for a pane or the display.
 830     *
 831     * @param string $pid
 832     *   Either a pane id for a pane in the display, or 'display' to edit the
 833     *   display cache settings.
 834     */
 835    function ajax_cache_method($pid = NULL) {
 836      ctools_include('content');
 837      // This lets us choose whether we're doing the display's cache or
 838      // a pane's.
 839      if ($pid == 'display') {
 840        $conf = &$this->display->cache;
 841        $title = t('Cache method for this display');
 842      }
 843      else if (!empty($this->display->content[$pid])) {
 844        $pane = &$this->display->content[$pid];
 845        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
 846        $conf = &$pane->cache;
 847        $title = t('Cache method for !subtype_title', array('!subtype_title' => $subtype['title']));
 848      }
 849      else {
 850        ctools_modal_render(t('Error'), t('Invalid pane id.'));
 851      }
 852  
 853      $form_state = array(
 854        'display' => &$this->display,
 855        'conf' => &$conf,
 856        'title' => $title,
 857        'ajax' => TRUE,
 858      );
 859  
 860      $output = ctools_modal_form_wrapper('panels_edit_cache_method_form', $form_state);
 861      if (!empty($output)) {
 862        $this->commands = $output;
 863        return;
 864      }
 865  
 866      // Preserve this; this way we don't actually change the method until they
 867      // have saved the form.
 868      $info = panels_get_cache($form_state['method']);
 869      $function = panels_plugin_get_function('cache', $info, 'settings form');
 870      if (!$function) {
 871        $conf['method'] = $form_state['method'];
 872        $conf['settings'] = array();
 873        panels_edit_cache_set($this->cache);
 874  
 875        $this->commands[] = ctools_modal_command_dismiss();
 876  
 877        if ($pid != 'display') {
 878          $this->command_update_pane($pane);
 879        }
 880        else {
 881          $this->command_update_display_links();
 882        }
 883      }
 884      else {
 885        $this->cache->method = $form_state['method'];
 886        panels_edit_cache_set($this->cache);
 887        // send them to next form.
 888        return $this->ajax_cache_settings($pid);
 889      }
 890    }
 891  
 892    /**
 893     * AJAX entry point to configure the cache settings for a pane or the display.
 894     *
 895     * @param string $pid
 896     *   Either a pane id for a pane in the display, or 'display' to edit the
 897     *   display cache settings.
 898     */
 899    function ajax_cache_settings($pid = 0) {
 900      ctools_include('content');
 901  
 902      // This lets us choose whether we're doing the display's cache or
 903      // a pane's.
 904      if ($pid == 'display') {
 905        $conf = &$this->display->cache;
 906        $title = t('Cache settings for this display');
 907      }
 908      else if (!empty($this->display->content[$pid])) {
 909        $pane = &$this->display->content[$pid];
 910        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
 911  
 912        $conf = &$pane->cache;
 913        $title = t('Cache settings for !subtype_title', array('!subtype_title' => $subtype['title']));
 914      }
 915      else {
 916        ctools_modal_render(t('Error'), t('Invalid pane id.'));
 917      }
 918  
 919      if (isset($this->cache->method) && (empty($conf['method']) || $conf['method'] != $this->cache->method)) {
 920        $conf['method'] = $this->cache->method;
 921        $info = panels_get_cache($conf['method']);
 922        $conf['settings'] = isset($info['defaults']) ? $info['defaults'] : array();
 923      }
 924  
 925      $form_state = array(
 926        'display' => &$this->display,
 927        'pid' => $pid,
 928        'conf' => &$conf,
 929        'ajax' => TRUE,
 930        'title' => $title,
 931        'url' => url($this->get_url('cache-settings', $pid), array('absolute' => TRUE)),
 932      );
 933  
 934      $output = ctools_modal_form_wrapper('panels_edit_cache_settings_form', $form_state);
 935      if (!empty($output)) {
 936        $this->commands = $output;
 937        return;
 938      }
 939  
 940      panels_edit_cache_set($this->cache);
 941  
 942      $this->commands[] = ctools_modal_command_dismiss();
 943  
 944      if ($pid != 'display') {
 945        $this->command_update_pane($pane);
 946      }
 947      else {
 948        $this->command_update_display_links();
 949      }
 950    }
 951  
 952    /**
 953     * AJAX entry point to select the style for a display, region or pane.
 954     *
 955     * @param string $type
 956     *   Either display, region or pane
 957     * @param $pid
 958     *   The pane id, if a pane. The region id, if a region.
 959     */
 960    function ajax_style_type($type, $pid = NULL) {
 961      // This lets us choose whether we're doing the display's cache or
 962      // a pane's.
 963      switch ($type) {
 964        case 'display':
 965          $style = isset($this->display->panel_settings['style']) ? $this->display->panel_settings['style'] : 'default';
 966          $title = t('Default style for this display');
 967          break;
 968  
 969        case 'region':
 970          $style = isset($this->display->panel_settings[$pid]['style']) ? $this->display->panel_settings[$pid]['style'] : '-1'; // -1 signifies to use the default setting.
 971          $title = t('Panel style for region "!region"', array('!region' => $this->plugins['layout']['panels'][$pid]));
 972          break;
 973  
 974        case 'pane':
 975          ctools_include('content');
 976          $pane = &$this->display->content[$pid];
 977          $style = isset($pane->style['style']) ? $pane->style['style'] : 'default';
 978          $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
 979          $title = t('Pane style for "!pane"', array('!pane' => $subtype['title']));
 980          break;
 981  
 982        default:
 983          ctools_modal_render(t('Error'), t('Invalid pane id.'));
 984      }
 985      $info = $this->get_style($type, $pid);
 986      $style_plugin = $info[0];
 987      $style_settings = $info[1];
 988  
 989      // Backward compatibility: Translate old-style stylizer to new style
 990      // stylizer.
 991      if ($style == 'stylizer' && !empty($style_settings['style']) && $style_settings['style'] != '$') {
 992        $style = 'stylizer:' . $style_settings['style'];
 993      }
 994  
 995      $form_state = array(
 996        'display' => &$this->display,
 997        'style' => $style,
 998        'title' => $title,
 999        'ajax' => TRUE,
1000        'type' => $type,
1001      );
1002  
1003      $output = ctools_modal_form_wrapper('panels_edit_style_type_form', $form_state);
1004      if (!empty($output)) {
1005        $this->commands = $output;
1006        return;
1007      }
1008  
1009      // Preserve this; this way we don't actually change the method until they
1010      // have saved the form.
1011      $style = panels_get_style($form_state['style']);
1012      $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
1013      if (!$function) {
1014        if (isset($this->cache->style)) {
1015          unset($this->cache->style);
1016        }
1017  
1018        // If there's no settings form, just change the style and exit.
1019        switch($type) {
1020          case 'display':
1021            $this->display->panel_settings['style'] = $form_state['style'];
1022            if (isset($this->display->panel_settings['style_settings']['default'])) {
1023              unset($this->display->panel_settings['style_settings']['default']);
1024            }
1025            break;
1026  
1027          case 'region':
1028            $this->display->panel_settings[$pid]['style'] = $form_state['style'];
1029            if (isset($this->display->panel_settings['style_settings'][$pid])) {
1030              unset($this->display->panel_settings['style_settings'][$pid]);
1031            }
1032            break;
1033  
1034          case 'pane':
1035            $pane->style['style'] = $form_state['style'];
1036            if (isset($pane->style['settings'])) {
1037              unset($pane->style['settings']);
1038            }
1039  
1040            break;
1041        }
1042        panels_edit_cache_set($this->cache);
1043  
1044        $this->commands[] = ctools_modal_command_dismiss();
1045  
1046        if ($type == 'pane') {
1047          $this->command_update_pane($pane);
1048        }
1049        else if ($type == 'region') {
1050          $this->command_update_region_links($pid);
1051        }
1052        else {
1053          $this->command_update_display_links();
1054        }
1055      }
1056      else {
1057        if ($form_state['style'] != $form_state['old_style']) {
1058          $this->cache->style = $form_state['style'];
1059          panels_edit_cache_set($this->cache);
1060        }
1061  
1062        // send them to next form.
1063        return $this->ajax_style_settings($type, $pid);
1064      }
1065    }
1066  
1067    /**
1068     * Get the appropriate style from the panel in the cache.
1069     *
1070     * Since we have styles for regions, panes and the display itself, and
1071     * they are stored differently, we use this method to simplify getting
1072     * style information into a way that's easy to cope with.
1073     */
1074    function get_style($type, $pid = '') {
1075      if (isset($this->cache->style)) {
1076        $style = panels_get_style($this->cache->style);
1077        $defaults = isset($style['defaults']) ? $style['defaults'] : array();
1078        // Get the &$conf variable based upon whose style we're editing.
1079        switch ($type) {
1080          case 'display':
1081            $this->display->panel_settings['style'] = $this->cache->style;
1082            $this->display->panel_settings['style_settings']['default'] = $defaults;
1083            break;
1084  
1085          case 'region':
1086            $this->display->panel_settings[$pid]['style'] = $this->cache->style;
1087            $this->display->panel_settings['style_settings'][$pid] = $defaults;
1088            break;
1089  
1090          case 'pane':
1091            $pane = &$this->display->content[$pid];
1092            $pane->style['style'] = $this->cache->style;
1093            $pane->style['settings'] = $defaults;
1094            $conf = &$pane->style['settings'];
1095            break;
1096        }
1097      }
1098      else {
1099        switch ($type) {
1100          case 'display':
1101            $style = panels_get_style((!empty($this->display->panel_settings['style'])) ? $this->display->panel_settings['style'] : 'default');
1102            break;
1103  
1104          case 'region':
1105            $style = panels_get_style((!empty($this->display->panel_settings[$pid]['style'])) ? $this->display->panel_settings[$pid]['style'] : '-1');
1106            break;
1107  
1108          case 'pane':
1109            $pane = &$this->display->content[$pid];
1110            $style = panels_get_style(!empty($pane->style['style']) ? $pane->style['style'] : 'default');
1111            break;
1112        }
1113      }
1114  
1115      // Set up our $conf reference.
1116      switch ($type) {
1117        case 'display':
1118          $conf = &$this->display->panel_settings['style_settings']['default'];
1119          break;
1120  
1121        case 'region':
1122          $conf = &$this->display->panel_settings['style_settings'][$pid];
1123          break;
1124  
1125        case 'pane':
1126          ctools_include('content');
1127          $pane = &$this->display->content[$pid];
1128          $conf = &$pane->style['settings'];
1129          break;
1130      }
1131  
1132      // Backward compatibility: Translate old-style stylizer to new style
1133      // stylizer.
1134      if ($style['name'] == 'stylizer' && !empty($conf['style']) && $conf['style'] != '$') {
1135        $style = panels_get_style('stylizer:' . $conf['style']);
1136      }
1137  
1138      return array($style, &$conf);
1139    }
1140  
1141    /**
1142     * AJAX entry point to configure the style for a display, region or pane.
1143     *
1144     * @param string $type
1145     *   Either display, region or pane
1146     * @param $pid
1147     *   The pane id, if a pane. The region id, if a region.
1148     */
1149    function ajax_style_settings($type, $pid = '') {
1150      $info = $this->get_style($type, $pid);
1151      $style = $info[0];
1152      $conf = &$info[1];
1153  
1154      switch ($type) {
1155        case 'display':
1156          $title = t('Style settings for @style (display)', array('@style' => $style['title']));
1157          break;
1158  
1159        case 'region':
1160          $title = t('Style settings for style @style (Region "!region")', array('@style' => $style['title'], '!region' => $this->plugins['layout']['panels'][$pid]));
1161          break;
1162  
1163        case 'pane':
1164          ctools_include('content');
1165          $pane = &$this->display->content[$pid];
1166          $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1167          $title = t('Style settings for style @style (Pane "!pane")', array('@style' => $style['title'], '!pane' => $subtype['title']));
1168          break;
1169      }
1170  
1171      $form_state = array(
1172        'display' => &$this->display,
1173        'type' => $type,
1174        'pid' => $pid,
1175        'conf' => &$conf,
1176        'style' => $style,
1177        'ajax' => TRUE,
1178        'title' => $title,
1179        'url' => url($this->get_url('style-settings', $type, $pid), array('absolute' => TRUE)),
1180        'renderer' => &$this,
1181      );
1182  
1183      $output = ctools_modal_form_wrapper('panels_edit_style_settings_form', $form_state);
1184      if (!empty($output)) {
1185        $this->commands = $output;
1186        return;
1187      }
1188  
1189      if (isset($this->cache->style)) {
1190        unset($this->cache->style);
1191      }
1192  
1193      // $conf was a reference so it should just modify.
1194      panels_edit_cache_set($this->cache);
1195  
1196      $this->commands[] = ctools_modal_command_dismiss();
1197  
1198      if ($type == 'pane') {
1199        $this->command_update_pane($pane);
1200      }
1201      else if ($type == 'region') {
1202        $this->command_update_region_links($pid);
1203      }
1204      else {
1205        $this->command_update_display_links();
1206      }
1207    }
1208  
1209    /**
1210     * AJAX entry point to configure CSS for a pane.
1211     *
1212     * @param $pid
1213     *   The pane id to edit.
1214     */
1215    function ajax_pane_css($pid = NULL) {
1216      if (empty($this->display->content[$pid])) {
1217        ctools_modal_render(t('Error'), t('Invalid pane id.'));
1218      }
1219  
1220      $pane = &$this->display->content[$pid];
1221      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1222  
1223      $form_state = array(
1224        'display' => &$this->display,
1225        'pane' => &$pane,
1226        'ajax' => TRUE,
1227        'title' => t('Configure CSS on !subtype_title', array('!subtype_title' => $subtype['title'])),
1228      );
1229  
1230      $output = ctools_modal_form_wrapper('panels_edit_configure_pane_css_form', $form_state);
1231      if (!empty($output)) {
1232        $this->commands = $output;
1233        return;
1234      }
1235  
1236      panels_edit_cache_set($this->cache);
1237      $this->command_update_pane($pid);
1238      $this->commands[] = ctools_modal_command_dismiss();
1239    }
1240  
1241    /**
1242     * AJAX entry point to configure access settings for a pane.
1243     *
1244     * @param $pid
1245     *   The pane id to edit.
1246     */
1247    function ajax_access_settings($pid = NULL) {
1248      if (empty($this->display->content[$pid])) {
1249        ctools_modal_render(t('Error'), t('Invalid pane id.'));
1250      }
1251  
1252      $pane = &$this->display->content[$pid];
1253      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1254  
1255      $form_state = array(
1256        'display' => &$this->display,
1257        'pane' => &$pane,
1258        'ajax' => TRUE,
1259        'title' => t('Access settings on !subtype_title', array('!subtype_title' => $subtype['title'])),
1260      );
1261  
1262      $output = ctools_modal_form_wrapper('panels_edit_configure_access_settings_form', $form_state);
1263      if (!empty($output)) {
1264        $this->commands = $output;
1265        return;
1266      }
1267  
1268      panels_edit_cache_set($this->cache);
1269      $this->command_update_pane($pid);
1270      $this->commands[] = ctools_modal_command_dismiss();
1271    }
1272  
1273    /**
1274     * AJAX entry point for to add a visibility rule.
1275     */
1276    function ajax_access_add_test($pid = NULL) {
1277      if (empty($this->display->content[$pid])) {
1278        ctools_modal_render(t('Error'), t('Invalid pane id.'));
1279      }
1280  
1281      $pane = &$this->display->content[$pid];
1282      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1283  
1284      $form_state = array(
1285        'display' => &$this->display,
1286        'pane' => &$pane,
1287        'ajax' => TRUE,
1288        'title' => t('Add visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1289      );
1290  
1291      $output = ctools_modal_form_wrapper('panels_edit_add_access_test_form', $form_state);
1292      if (empty($output)) {
1293        // Set up the plugin in cache
1294        $plugin = ctools_get_access_plugin($form_state['values']['type']);
1295        $this->cache->new_plugin = ctools_access_new_test($plugin);
1296        panels_edit_cache_set($this->cache);
1297  
1298        // go to the next step.
1299        return $this->ajax_access_configure_test($pid, 'add');
1300      }
1301  
1302      ctools_ajax_render($output);
1303    }
1304  
1305    /**
1306     * AJAX entry point for to configure vsibility rule.
1307     */
1308    function ajax_access_configure_test($pid = NULL, $id = NULL) {
1309      if (empty($this->display->content[$pid])) {
1310        ctools_modal_render(t('Error'), t('Invalid pane id.'));
1311      }
1312  
1313      $pane = &$this->display->content[$pid];
1314      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1315  
1316      // Set this up here because $id gets changed later.
1317      $url = $this->get_url('access-configure-test', $pid, $id);
1318  
1319      // If we're adding a new one, get the stored data from cache and
1320      // add it. It's stored as a cache so that if this is closed
1321      // we don't accidentally add an unconfigured plugin.
1322      if ($id == 'add') {
1323        $pane->access['plugins'][] = $this->cache->new_plugin;
1324        $id = max(array_keys($pane->access['plugins']));
1325      }
1326      else if (empty($pane->access['plugins'][$id])) {
1327        ctools_modal_render(t('Error'), t('Invalid test id.'));
1328      }
1329  
1330      $form_state = array(
1331        'display' => &$this->display,
1332        'pane' => &$pane,
1333        'ajax' => TRUE,
1334        'title' => t('Configure visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1335        'test' => &$pane->access['plugins'][$id],
1336        'plugin' => ctools_get_access_plugin($pane->access['plugins'][$id]['name']),
1337        'url' => url($url, array('absolute' => TRUE)),
1338      );
1339  
1340      $output = ctools_modal_form_wrapper('panels_edit_configure_access_test_form', $form_state);
1341      if (!empty($output)) {
1342        $this->commands = $output;
1343        return;
1344      }
1345  
1346      // Unset the new plugin
1347      if (isset($this->cache->new_plugin)) {
1348        unset($this->cache->new_plugin);
1349      }
1350  
1351      if (!empty($form_state['remove'])) {
1352        unset($pane->access['plugins'][$id]);
1353      }
1354  
1355      panels_edit_cache_set($this->cache);
1356      $this->command_update_pane($pid);
1357      $this->commands[] = ctools_modal_command_dismiss();
1358    }
1359  
1360    /**
1361     * AJAX Router function for layout owned AJAX calls.
1362     *
1363     * Layouts like the flexible layout builder need callbacks of their own.
1364     * This allows those layouts to simply declare their callbacks and use
1365     * them with $this->get_url('layout', $command).
1366     */
1367    function ajax_layout() {
1368      $args = func_get_args();
1369      if (empty($args)) {
1370        return MENU_NOT_FOUND;
1371      }
1372  
1373      $command = array_shift($args);
1374      if (empty($this->plugins['layout']['ajax'][$command]) || !function_exists($this->plugins['layout']['ajax'][$command])) {
1375        return MENU_NOT_FOUND;
1376      }
1377  
1378      // Make sure the this is always available to the called functions.
1379      array_unshift($args, $this);
1380      return call_user_func_array($this->plugins['layout']['ajax'][$command], $args);
1381    }
1382  
1383    /**
1384     * AJAX Router function for style owned AJAX calls.
1385     *
1386     * Styles like the stylizer need AJAX callbacks of their own. This
1387     * allows the system to figure out which style is being referenced,
1388     * load it, and execute the callback.
1389     *
1390     * This allows those layouts to simply declare their callbacks and use
1391     * them using $this->get_url('style', $command, $type, $pid).
1392     */
1393    function ajax_style() {
1394      $args = func_get_args();
1395      if (count($args) < 3) {
1396        return MENU_NOT_FOUND;
1397      }
1398  
1399      $command = array_shift($args);
1400      $type = array_shift($args);
1401      $pid = array_shift($args);
1402  
1403      $info = $this->get_style($type, $pid);
1404  
1405      $style = $info[0];
1406      $conf = &$info[1];
1407  
1408      if (empty($style['ajax'][$command]) || !function_exists($style['ajax'][$command])) {
1409        return MENU_NOT_FOUND;
1410      }
1411  
1412      // Make sure the this is always available to the called functions.
1413      $args = array_merge(array(&$this, $style, &$conf, $type, $pid), $args);
1414      return call_user_func_array($style['ajax'][$command], $args);
1415    }
1416  
1417    // ------------------------------------------------------------------------
1418    // AJAX command generators
1419    //
1420    // These are used to make sure that child implementations can control their
1421    // own AJAX commands as needed.
1422  
1423    /**
1424     * Create a command array to redraw a pane.
1425     */
1426    function command_update_pane($pid) {
1427      if (is_object($pid)) {
1428        $pane = $pid;
1429      }
1430      else {
1431        $pane = $this->display->content[$pid];
1432      }
1433  
1434      $this->commands[] = ctools_ajax_command_replace("#panel-pane-$pane->pid", $this->render_pane($pane));
1435      $this->commands[] = ctools_ajax_command_changed("#panel-pane-$pane->pid", "div.grabber span.text");
1436    }
1437  
1438    /**
1439     * Create a command array to add a new pane.
1440     */
1441    function command_add_pane($pid) {
1442      if (is_object($pid)) {
1443        $pane = $pid;
1444      }
1445      else {
1446        $pane = $this->display->content[$pid];
1447      }
1448  
1449      $this->commands[] = ctools_ajax_command_append("#panel-pane-$pane->panel", $this->render_pane($pane));
1450      $this->commands[] = ctools_ajax_command_changed("#panel-pane-$pane->pid", "div.grabber span.text");
1451    }
1452  
1453    /**
1454     * Create a command to update the links on a display after a change was made.
1455     */
1456    function command_update_display_links() {
1457      $this->commands[] = ctools_ajax_command_replace('.panels-display-links', $this->get_display_links());
1458    }
1459  
1460    /**
1461     * Create a command to update the links on a region after a change was made.
1462     */
1463    function command_update_region_links($id) {
1464      $this->commands[] = ctools_ajax_command_replace('.panels-region-links-' . $id, $this->get_region_links($id));
1465    }
1466  }
1467  
1468  /**
1469   * Handle the 'next' click on the add/edit pane form wizard.
1470   *
1471   * All we need to do is store the updated pane in the cache.
1472   */
1473  function panels_ajax_edit_pane_next(&$form_state) {
1474    $form_state['cache']->new_pane = $form_state['pane'];
1475    panels_edit_cache_set($form_state['cache']);
1476  }
1477  
1478  /**
1479   * Handle the 'finish' click on teh add/edit pane form wizard.
1480   *
1481   * All we need to do is set a flag so the return can handle adding
1482   * the pane.
1483   */
1484  function panels_ajax_edit_pane_finish(&$form_state) {
1485    $form_state['complete'] = TRUE;
1486    return;
1487  }
1488  
1489  /**
1490   * Handle the 'cancel' click on the add/edit pane form wizard.
1491   */
1492  function panels_ajax_edit_pane_cancel(&$form_state) {
1493    $form_state['cancel'] = TRUE;
1494    return;
1495  }
1496  
1497  // --------------------------------------------------------------------------
1498  // Forms for the editor object
1499  
1500  /**
1501   * Choose cache method form
1502   */
1503  function panels_edit_cache_method_form(&$form_state) {
1504    $display = &$form_state['display'];
1505    $conf = &$form_state['conf'];
1506  
1507    // Set to 0 to ensure we get a selected radio.
1508    if (!isset($conf['method'])) {
1509      $conf['method'] = 0;
1510    }
1511  
1512    $caches = panels_get_caches();
1513    if (empty($caches)) {
1514      $form['markup'] = array('#value' => t('No caching options are available at this time. Please enable a panels caching module in order to use caching options.'));
1515      return $form;
1516    }
1517  
1518    $options[0] = t('No caching');
1519    foreach ($caches as $cache => $info) {
1520      $options[$cache] = check_plain($info['title']);
1521    }
1522  
1523    $form['method'] = array(
1524      '#prefix' => '<div class="no-float">',
1525      '#suffix' => '</div>',
1526      '#type' => 'radios',
1527      '#title' => t('Method'),
1528      '#options' => $options,
1529      '#default_value' => $conf['method'],
1530    );
1531  
1532    $form['submit'] = array(
1533      '#type' => 'submit',
1534      '#value' => t('Next'),
1535    );
1536    return $form;
1537  }
1538  
1539  /**
1540   * Submit callback for panels_edit_cache_method_form.
1541   *
1542   * All this needs to do is return the method.
1543   */
1544  function panels_edit_cache_method_form_submit($form, &$form_state) {
1545    $form_state['method'] = $form_state['values']['method'];
1546  }
1547  
1548  /**
1549   * Cache settings form
1550   */
1551  function panels_edit_cache_settings_form(&$form_state) {
1552    $display = &$form_state['display'];
1553    $conf = &$form_state['conf'];
1554    $pid = $form_state['pid'];
1555    $info = panels_get_cache($conf['method']);
1556  
1557    $form['#action'] = $form_state['url'];
1558  
1559    $form['description'] = array(
1560      '#prefix' => '<div class="description">',
1561      '#suffix' => '</div>',
1562      '#value' => check_plain($info['description']),
1563    );
1564  
1565    $function = panels_plugin_get_function('cache', $conf['method'], 'settings form');
1566  
1567    $form['settings'] = $function($conf['settings'], $display, $pid);
1568    $form['settings']['#tree'] = TRUE;
1569  
1570    $form['display'] = array(
1571      '#type' => 'value',
1572      '#value' => $display,
1573    );
1574  
1575    $form['pid'] = array(
1576      '#type' => 'value',
1577      '#value' => $pid,
1578    );
1579  
1580    $form['submit'] = array(
1581      '#type' => 'submit',
1582      '#value' => t('Save'),
1583    );
1584  
1585    return $form;
1586  }
1587  
1588  /**
1589   * Validate cache settings.
1590   */
1591  function panels_edit_cache_settings_form_validate($form, &$form_state) {
1592    if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form validate')) {
1593      $function($form, $form_state['values']['settings']);
1594    }
1595  }
1596  
1597  /**
1598   * Allows panel styles to validate their style settings.
1599   */
1600  function panels_edit_cache_settings_form_submit($form, &$form_state) {
1601    if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form submit')) {
1602      $function($form_state['values']['settings']);
1603    }
1604  
1605    $form_state['conf']['settings'] = $form_state['values']['settings'];
1606  }
1607  
1608  /**
1609   * Choose style form
1610   */
1611  function panels_edit_style_type_form(&$form_state) {
1612    $display = &$form_state['display'];
1613    $style = $form_state['style'];
1614    $type = $form_state['type'];
1615  
1616    $styles = panels_get_styles();
1617  
1618    $function = ($type == 'pane' ? 'render pane' : (variable_get('panels_legacy_rendering_mode', TRUE) ? 'render panel' : 'render region'));
1619    $options = array();
1620    if ($type == 'region') {
1621      $options[-1] = t('Use display default style');
1622    }
1623  
1624    uasort($styles, 'ctools_plugin_sort');
1625  
1626    foreach ($styles as $id => $info) {
1627      if (empty($info['hidden']) && (!empty($info[$function]) || $id == 'default')) {
1628        $options[$id] = check_plain($info['title']);
1629      }
1630    }
1631  
1632    $form['style'] = array(
1633      '#prefix' => '<div class="no-float">',
1634      '#suffix' => '</div>',
1635      '#type' => 'radios',
1636      '#title' => t('Style'),
1637      '#options' => $options,
1638      '#default_value' => $style,
1639    );
1640  
1641    $form['submit'] = array(
1642      '#type' => 'submit',
1643      '#value' => t('Next'),
1644    );
1645    return $form;
1646  }
1647  
1648  /**
1649   * Submit callback for panels_edit_style_type_form.
1650   *
1651   * All this needs to do is return the method.
1652   */
1653  function panels_edit_style_type_form_submit($form, &$form_state) {
1654    $form_state['old_style'] = $form_state['style'];
1655    $form_state['style'] = $form_state['values']['style'];
1656  }
1657  
1658  /**
1659   * Style settings form
1660   */
1661  function panels_edit_style_settings_form(&$form_state) {
1662    $display = &$form_state['display'];
1663    $conf = &$form_state['conf'];
1664    $pid = $form_state['pid'];
1665    $style = $form_state['style'];
1666    $type = $form_state['type'];
1667  
1668    $form['#action'] = $form_state['url'];
1669  
1670    $form['description'] = array(
1671      '#prefix' => '<div class="description">',
1672      '#suffix' => '</div>',
1673      '#value' => check_plain($style['description']),
1674    );
1675  
1676    $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
1677  
1678    $form['settings'] = $function($conf, $display, $pid, $type, $form_state);
1679    $form['settings']['#tree'] = TRUE;
1680  
1681    $form['submit'] = array(
1682      '#type' => 'submit',
1683      '#value' => t('Save'),
1684    );
1685  
1686    return $form;
1687  }
1688  
1689  /**
1690   * Validate style settings.
1691   */
1692  function panels_edit_style_settings_form_validate($form, &$form_state) {
1693    $name = $form_state['type'] == 'pane' ? 'pane settings form validate' : 'settings form validate';
1694    if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1695      $function($form, $form_state['values']['settings'], $form_state);
1696    }
1697  }
1698  
1699  /**
1700   * Allows panel styles to validate their style settings.
1701   */
1702  function panels_edit_style_settings_form_submit($form, &$form_state) {
1703    $name = $form_state['type'] == 'pane' ? 'pane settings form submit' : 'settings form submit';
1704    if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1705      $function($form, $form_state['values']['settings'], $form_state);
1706    }
1707  
1708    $form_state['conf'] = $form_state['values']['settings'];
1709  }
1710  
1711  
1712  /**
1713   * Configure CSS on a pane form.
1714   */
1715  function panels_edit_configure_pane_css_form(&$form_state) {
1716    $display = &$form_state['display'];
1717    $pane = &$form_state['pane'];
1718  
1719    $form['css_id'] = array(
1720      '#type' => 'textfield',
1721      '#default_value' => isset($pane->css['css_id']) ? $pane->css['css_id'] : '',
1722      '#title' => t('CSS ID'),
1723      '#description' => t('CSS ID to apply to this pane. This may be blank.'),
1724    );
1725    $form['css_class'] = array(
1726      '#type' => 'textfield',
1727      '#default_value' => isset($pane->css['css_class']) ? $pane->css['css_class'] : '',
1728      '#title' => t('CSS class'),
1729      '#description' => t('CSS class to apply to this pane. This may be blank.'),
1730    );
1731  
1732    $form['next'] = array(
1733      '#type' => 'submit',
1734      '#value' => t('Save'),
1735    );
1736  
1737    return $form;
1738  }
1739  
1740  /**
1741   * FAPI submission function for the CSS configure form.
1742   *
1743   * All this does is set up $pane properly. The caller is responsible for
1744   * actually storing this somewhere.
1745   */
1746  function panels_edit_configure_pane_css_form_submit($form, &$form_state) {
1747    $pane = &$form_state['pane'];
1748    $display = $form_state['display'];
1749  
1750    $pane->css['css_id'] = $form_state['values']['css_id'];
1751    $pane->css['css_class'] = $form_state['values']['css_class'];
1752  }
1753  
1754  /**
1755   * Form to control basic visibility settings.
1756   */
1757  function panels_edit_configure_access_settings_form(&$form_state) {
1758    $display = &$form_state['display'];
1759    $pane = &$form_state['pane'];
1760  
1761    $form['logic'] = array(
1762      '#type' => 'radios',
1763      '#options' => array(
1764        'and' => t('All criteria must pass.'),
1765        'or' => t('Only one criterion must pass.'),
1766      ),
1767      '#default_value' => isset($pane->access['logic']) ? $pane->access['logic'] : 'and',
1768    );
1769  
1770    $form['next'] = array(
1771      '#type' => 'submit',
1772      '#value' => t('Save'),
1773    );
1774  
1775    return $form;
1776  }
1777  
1778  /**
1779   * FAPI submission function for the edit access settings form.
1780   *
1781   * All this does is set up $pane properly. The caller is responsible for
1782   * actually storing this somewhere.
1783   */
1784  function panels_edit_configure_access_settings_form_submit($form, &$form_state) {
1785    $pane = &$form_state['pane'];
1786    $display = $form_state['display'];
1787  
1788    $pane->access['logic'] = $form_state['values']['logic'];
1789  }
1790  
1791  /**
1792   * Form to add a visibility rule.
1793   */
1794  function panels_edit_add_access_test_form(&$form_state) {
1795    $display = &$form_state['display'];
1796    $pane = &$form_state['pane'];
1797  
1798    $plugins = ctools_get_relevant_access_plugins($display->context);
1799    $options = array();
1800    foreach ($plugins as $id => $plugin) {
1801      $options[$id] = $plugin['title'];
1802    }
1803  
1804    asort($options);
1805  
1806    $form['type'] = array(
1807      // This ensures that the form item is added to the URL.
1808      '#type' => 'radios',
1809      '#options' => $options,
1810    );
1811  
1812    $form['next'] = array(
1813      '#type' => 'submit',
1814      '#value' => t('Next'),
1815    );
1816  
1817    return $form;
1818  }
1819  
1820  /**
1821   * Form to configure a visibility rule.
1822   */
1823  function panels_edit_configure_access_test_form(&$form_state) {
1824    $display = &$form_state['display'];
1825    $test = &$form_state['test'];
1826    $plugin = &$form_state['plugin'];
1827  
1828    $form['#action'] = $form_state['url'];
1829  
1830    $contexts = $display->context;
1831    if (!isset($contexts['logged-in-user'])) {
1832      $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1833    }
1834  
1835    if (isset($plugin['required context'])) {
1836      $form['context'] = ctools_context_selector($contexts, $plugin['required context'], $test['context']);
1837    }
1838  
1839    $form['settings'] = array('#tree' => TRUE);
1840    if ($function = ctools_plugin_get_function($plugin, 'settings form')) {
1841      $function($form, $form_state, $test['settings']);
1842    }
1843  
1844    $form['not'] = array(
1845      '#type' => 'checkbox',
1846      '#title' => t('Reverse (NOT)'),
1847      '#default_value' => !empty($test['not']),
1848    );
1849  
1850    $form['save'] = array(
1851      '#type' => 'submit',
1852      '#value' => t('Save'),
1853    );
1854  
1855    $form['remove'] = array(
1856      '#type' => 'submit',
1857      '#value' => t('Remove'),
1858      '#remove' => TRUE,
1859    );
1860  
1861    return $form;
1862  }
1863  
1864  /**
1865   * Validate handler for visibility rule settings
1866   */
1867  function panels_edit_configure_access_test_form_validate(&$form, &$form_state) {
1868    if (!empty($form_state['clicked_button']['#remove'])) {
1869      return;
1870    }
1871  
1872    if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
1873      $function($form, $form_state);
1874    }
1875  }
1876  
1877  /**
1878   * Submit handler for visibility rule settings
1879   */
1880  function panels_edit_configure_access_test_form_submit(&$form, &$form_state) {
1881    if (!empty($form_state['clicked_button']['#remove'])) {
1882      $form_state['remove'] = TRUE;
1883      return;
1884    }
1885  
1886    if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
1887      $function($form, $form_state);
1888    }
1889  
1890    $form_state['test']['settings'] = $form_state['values']['settings'];
1891    if (isset($form_state['values']['context'])) {
1892      $form_state['test']['context'] = $form_state['values']['context'];
1893    }
1894    $form_state['test']['not'] = !empty($form_state['values']['not']);
1895  }
1896  


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7