[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

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

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


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7