Projet

Général

Profil

Paste
Télécharger (60,1 ko) Statistiques
| Branche: | Révision:

root / htmltest / sites / all / modules / panels / plugins / display_renderers / panels_renderer_editor.class.php @ c12e7e6a

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
  /**
18
   * Set to true if edit links (for panes and regions) should not be displayed.
19
   * This can be used for special edit modes such as layout change and layout
20
   * builder that do not actually have real content.
21
   */
22
  var $no_edit_links = FALSE;
23
  // -------------------------------------------------------------------------
24
  // Display edit rendering.
25

    
26
  function edit() {
27
    $form_state = array(
28
      'display' => &$this->display,
29
      'renderer' => &$this,
30
      'content_types' => $this->cache->content_types,
31
      'no_redirect' => TRUE,
32
      'display_title' => !empty($this->cache->display_title),
33
      'cache key' => $this->display->cache_key,
34
    );
35

    
36
    $output = drupal_build_form('panels_edit_display_form', $form_state);
37
    if (empty($form_state['executed']) || !empty($form_state['clicked_button']['preview'])) {
38
      return $output;
39
    }
40

    
41
    if (!empty($form_state['clicked_button']['#save-display'])) {
42
      drupal_set_message(t('Panel content has been updated.'));
43
      panels_save_display($this->display);
44
    }
45
    else {
46
      drupal_set_message(t('Your changes have been discarded.'));
47
    }
48

    
49
    panels_cache_clear('display', $this->display->did);
50
    return $this->display;
51
  }
52

    
53
  function add_meta() {
54
    parent::add_meta();
55
    if ($this->admin) {
56
      ctools_include('ajax');
57
      ctools_include('modal');
58
      ctools_modal_add_js();
59

    
60
      ctools_add_js('panels-base', 'panels');
61
      ctools_add_js('display_editor', 'panels');
62
      ctools_add_css('panels_dnd', 'panels');
63
      ctools_add_css('panels_admin', 'panels');
64
    }
65
  }
66

    
67
  function render() {
68
    // Pass through to normal rendering if not in admin mode.
69
    if (!$this->admin) {
70
      return parent::render();
71
    }
72

    
73
    $this->add_meta();
74

    
75
    $output = '<div class="panels-dnd" id="panels-dnd-main">';
76
    $output .= $this->render_layout();
77
    $output .= '</div>';
78

    
79
    return $output;
80
  }
81

    
82
  function render_region($region_id, $panes) {
83
    // Pass through to normal rendering if not in admin mode.
84
    if (!$this->admin) {
85
      return parent::render_region($region_id, $panes);
86
    }
87

    
88
    $content = implode('', $panes);
89

    
90
    $panel_buttons = $this->get_region_links($region_id);
91

    
92
    $output = "<div class='panel-region' id='panel-region-$region_id'>";
93
    $output .= $panel_buttons;
94
    $output .= "<h2 class='label'>" . check_plain($this->plugins['layout']['regions'][$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
    $grabber_class = 'grab-title grabber';
132
    // If there are region locks, add them.
133
    if (!empty($pane->locks['type'])) {
134
      if ($pane->locks['type'] == 'regions') {
135
        $settings['Panels']['RegionLock'][$pane->pid] = $pane->locks['regions'];
136
        drupal_add_js($settings, 'setting');
137
      }
138
      else if ($pane->locks['type'] == 'immovable') {
139
        $grabber_class = 'grab-title not-grabber';
140
      }
141
    }
142

    
143
    $output = '';
144
    $class = 'panel-pane';
145

    
146
    if (empty($pane->shown)) {
147
      $class .= ' hidden-pane';
148
    }
149

    
150
    if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
151
      $class .= ' panel-pane-is-title';
152
    }
153

    
154
    $output = '<div class="' . $class . '" id="panel-pane-' . $pane->pid . '">';
155

    
156
    if (!$block->title) {
157
      $block->title = t('No title');
158
    }
159

    
160
    $output .= '<div class="' . $grabber_class . '">';
161
    if ($buttons) {
162
      $output .= '<span class="buttons">' . $buttons . '</span>';
163
    }
164
    $output .= '<span class="text">' . $title . '</span>';
165
    $output .= '</div>'; // grabber
166

    
167
    $output .= '<div class="panel-pane-collapsible">';
168
    $output .= '<div class="pane-title">' . $block->title . '</div>';
169
    $output .= '<div class="pane-content">' . filter_xss_admin(render($block->content)) . '</div>';
170
    $output .= '</div>'; // panel-pane-collapsible
171

    
172
    $output .= '</div>'; // panel-pane
173

    
174
    return $output;
175
  }
176

    
177
  /**
178
   * Get the style links.
179
   *
180
   * This is abstracted out since we have styles on both panes and regions.
181
   */
182
  function get_style_links($type, $id = NULL) {
183
    $info = $this->get_style($type, $id);
184
    $style = $info[0];
185
    $conf = $info[1];
186

    
187
    $style_title = isset($style['title']) ? $style['title'] : t('Default');
188

    
189
    $style_links[] = array(
190
      'title' => $style_title,
191
      'attributes' => array('class' => array('panels-text')),
192
    );
193

    
194
    $style_links[] = array(
195
      'title' => t('Change'),
196
      'href' => $this->get_url('style-type', $type, $id),
197
      'attributes' => array('class' => array('ctools-use-modal')),
198
    );
199

    
200
    $function = $type != 'pane' ? 'settings form' : 'pane settings form';
201
    if (panels_plugin_get_function('styles', $style, $function)) {
202
      $style_links[] = array(
203
        'title' => t('Settings'),
204
        'href' => $this->get_url('style-settings', $type, $id),
205
        'attributes' => array('class' => array('ctools-use-modal')),
206
      );
207
    }
208

    
209
    return $style_links;
210
  }
211

    
212
  /**
213
   * Get the links for a panel display.
214
   *
215
   * This is abstracted out for easy ajax replacement.
216
   */
217
  function get_display_links() {
218
    $links = array();
219

    
220
    if (user_access('administer panels styles')) {
221
      $style_links = $this->get_style_links('display');
222
      $links[] = array(
223
        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),
224
        'html' => TRUE,
225
        'attributes' => array('class' => array('panels-sub-menu')),
226
      );
227
    }
228

    
229
    if (user_access('use panels caching features')) {
230
      $links[] = array(
231
        'title' => '<hr />',
232
        'html' => TRUE,
233
      );
234

    
235
      $method = isset($this->display->cache['method']) ? $this->display->cache['method'] : 0;
236
      $info = panels_get_cache($method);
237
      $cache_method = isset($info['title']) ? $info['title'] : t('No caching');
238

    
239
      $cache_links[] = array(
240
        'title' => $cache_method,
241
        'attributes' => array('class' => array('panels-text')),
242
      );
243
      $cache_links[] = array(
244
        'title' => t('Change'),
245
        'href' => $this->get_url('cache-method', 'display'),
246
        'attributes' => array('class' => array('ctools-use-modal')),
247
      );
248
      if (panels_plugin_get_function('cache', $info, 'settings form')) {
249
        $cache_links[] = array(
250
          'title' => t('Settings'),
251
          'href' => $this->get_url('cache-settings', 'display'),
252
          'attributes' => array('class' => array('ctools-use-modal')),
253
        );
254
      }
255

    
256
      $links[] = array(
257
        'title' => '<span class="dropdown-header">' . t('Caching') . '</span>' . theme_links(array('links' => $cache_links, 'attributes' => array(), 'heading' => array())),
258
        'html' => TRUE,
259
        'attributes' => array('class' => array('panels-sub-menu')),
260
      );
261
    }
262

    
263
    return theme('ctools_dropdown', array('title' => t('Display settings'), 'links' => $links, 'class' => 'panels-display-links'));
264
  }
265

    
266
  /**
267
   * Render the links to display when editing a region.
268
   */
269
  function get_region_links($region_id) {
270
    if (!empty($this->no_edit_links)) {
271
      return '';
272
    }
273
    $links = array();
274
    $links[] = array(
275
      'title' => t('Add content'),
276
      'href' => $this->get_url('select-content', $region_id),
277
      'attributes' => array(
278
        'class' => array('ctools-use-modal'),
279
      ),
280
    );
281

    
282
    if (user_access('administer panels styles')) {
283
      $links[] = array(
284
        'title' => '<hr />',
285
        'html' => TRUE,
286
      );
287

    
288
      $style_links = $this->get_style_links('region', $region_id);
289

    
290
      $links[] = array(
291
        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),
292
        'html' => TRUE,
293
        'attributes' => array('class' => array('panels-sub-menu')),
294
      );
295
    }
296

    
297
    return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-addcontent.png', 'panels'))), 'links' => $links, 'image' => TRUE, 'class' => 'pane-add-link panels-region-links-' . $region_id));
298
  }
299

    
300
  /**
301
   * Render the links to display when editing a pane.
302
   */
303
  function get_pane_links($pane, $content_type) {
304
    if (!empty($this->no_edit_links)) {
305
      return '';
306
    }
307
    $links = array();
308

    
309
    if (!empty($pane->shown)) {
310
      $links[] = array(
311
        'title' => t('Disable this pane'),
312
        'href' => $this->get_url('hide', $pane->pid),
313
        'attributes' => array('class' => array('use-ajax')),
314
      );
315
    }
316
    else {
317
      $links[] = array(
318
        'title' => t('Enable this pane'),
319
        'href' => $this->get_url('show', $pane->pid),
320
        'attributes' => array('class' => array('use-ajax')),
321
      );
322
    }
323

    
324
    if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
325
      $links['panels-set-title'] = array(
326
        'title' => t('&#x2713;Panel title'),
327
        'html' => TRUE,
328
      );
329
    }
330
    else {
331
      $links['panels-set-title'] = array(
332
        'title' => t('Panel title'),
333
        'href' => $this->get_url('panel-title', $pane->pid),
334
        'attributes' => array('class' => array('use-ajax')),
335
      );
336
    }
337

    
338
    $subtype = ctools_content_get_subtype($content_type, $pane->subtype);
339

    
340
    if (ctools_content_editable($content_type, $subtype, $pane->configuration)) {
341
      $links[] = array(
342
        'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),
343
        'href' => $this->get_url('edit-pane', $pane->pid),
344
        'attributes' => array('class' => array('ctools-use-modal')),
345
      );
346
    }
347

    
348
    if (user_access('administer advanced pane settings')) {
349
      $links[] = array(
350
        'title' => t('CSS properties'),
351
        'href' => $this->get_url('pane-css', $pane->pid),
352
        'attributes' => array('class' => array('ctools-use-modal')),
353
      );
354
    }
355

    
356
    if (user_access('administer panels styles')) {
357
      $links[] = array(
358
        'title' => '<hr />',
359
        'html' => TRUE,
360
      );
361

    
362
      $style_links = $this->get_style_links('pane', $pane->pid);
363

    
364
      $links[] = array(
365
        'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),
366
        'html' => TRUE,
367
        'attributes' => array('class' => array('panels-sub-menu')),
368
      );
369
    }
370

    
371
    if (user_access('administer pane access')) {
372
      $links[] = array(
373
        'title' => '<hr />',
374
        'html' => TRUE,
375
      );
376

    
377
      $contexts = $this->display->context;
378
      // Make sure we have the logged in user context
379
      if (!isset($contexts['logged-in-user'])) {
380
        $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
381
      }
382

    
383
      $visibility_links = array();
384

    
385
      if (!empty($pane->access['plugins'])) {
386
        foreach ($pane->access['plugins'] as $id => $test) {
387
          $plugin = ctools_get_access_plugin($test['name']);
388
          $access_title  = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));
389
          $access_description = ctools_access_summary($plugin, $contexts, $test);
390

    
391
          $visibility_links[] = array(
392
            'title' => $access_description,
393
            'href' => $this->get_url('access-configure-test', $pane->pid, $id),
394
            'attributes' => array('class' => array('ctools-use-modal', 'panels-italic')),
395
          );
396
        }
397
      }
398
      if (empty($visibility_links)) {
399
        $visibility_links[] = array(
400
          'title' => t('No rules'),
401
          'attributes' => array('class' => array('panels-text')),
402
        );
403
      }
404

    
405
      $visibility_links[] = array(
406
        'title' => t('Add new rule'),
407
        'href' => $this->get_url('access-add-test', $pane->pid),
408
        'attributes' => array('class' => array('ctools-use-modal')),
409
      );
410

    
411
      $visibility_links[] = array(
412
        'title' => t('Settings'),
413
        'href' => $this->get_url('access-settings', $pane->pid),
414
        'attributes' => array('class' => array('ctools-use-modal')),
415
      );
416

    
417
      $links[] = array(
418
        'title' => '<span class="dropdown-header">' . t('Visibility rules') . '</span>' . theme_links(array('links' => $visibility_links, 'attributes' => array(), 'heading' => array())),
419
        'html' => TRUE,
420
        'attributes' => array('class' => array('panels-sub-menu')),
421
      );
422
    }
423

    
424
    if (user_access('use panels locks')) {
425
      $links[] = array(
426
        'title' => '<hr />',
427
        'html' => TRUE,
428
      );
429

    
430
      $lock_type = !empty($pane->locks['type']) ? $pane->locks['type'] : 'none';
431
      switch ($lock_type) {
432
        case 'immovable':
433
          $lock_method = t('Immovable');
434
          break;
435
        case 'regions':
436
          $lock_method = t('Regions');
437
          break;
438
        case 'none':
439
        default:
440
          $lock_method = t('No lock');
441
          break;
442
      }
443

    
444
      $lock_links[] = array(
445
        'title' => $lock_method,
446
        'attributes' => array('class' => array('panels-text')),
447
      );
448
      $lock_links[] = array(
449
        'title' => t('Change'),
450
        'href' => $this->get_url('lock', $pane->pid),
451
        'attributes' => array('class' => array('ctools-use-modal')),
452
      );
453

    
454
      $links[] = array(
455
        'title' => '<span class="dropdown-header">' . t('Locking') . '</span>' . theme_links(array('links' => $lock_links, 'attributes' => array(), 'heading' => array())),
456
        'html' => TRUE,
457
        'attributes' => array('class' => array('panels-sub-menu')),
458
      );
459
    }
460

    
461
    if (panels_get_caches() && user_access('use panels caching features')) {
462
      $links[] = array(
463
        'title' => '<hr />',
464
        'html' => TRUE,
465
      );
466

    
467
      $method = isset($pane->cache['method']) ? $pane->cache['method'] : 0;
468
      $info = panels_get_cache($method);
469
      $cache_method = isset($info['title']) ? $info['title'] : t('No caching');
470
      $cache_links[] = array(
471
        'title' => $cache_method,
472
        'attributes' => array('class' => array('panels-text')),
473
      );
474
      $cache_links[] = array(
475
        'title' => t('Change'),
476
        'href' => $this->get_url('cache-method', $pane->pid),
477
        'attributes' => array('class' => array('ctools-use-modal')),
478
      );
479
      if (panels_plugin_get_function('cache', $info, 'settings form')) {
480
        $cache_links[] = array(
481
          'title' => t('Settings'),
482
          'href' => $this->get_url('cache-settings', $pane->pid),
483
          'attributes' => array('class' => array('ctools-use-modal')),
484
        );
485
      }
486

    
487
      $links[] = array(
488
        'title' => '<span class="dropdown-header">' . t('Caching') . '</span>' . theme_links(array('links' => $cache_links, 'attributes' => array(), 'heading' => array())),
489
        'html' => TRUE,
490
        'attributes' => array('class' => array('panels-sub-menu')),
491
      );
492
    }
493

    
494
    $links[] = array(
495
      'title' => '<hr />',
496
      'html' => TRUE,
497
    );
498

    
499
    $links[] = array(
500
      'title' => t('Remove'),
501
      'href' => '#',
502
      'attributes' => array(
503
        'class' => array('pane-delete'),
504
        'id' => "pane-delete-panel-pane-$pane->pid",
505
      ),
506
    );
507

    
508
    return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-configure.png', 'panels'))), 'links' => $links, 'image' => TRUE));
509
  }
510

    
511
  // -----------------------------------------------------------------------
512
  // Display edit AJAX callbacks and helpers.
513

    
514
  /**
515
   * Generate a URL path for the AJAX editor.
516
   */
517
  function get_url() {
518
    $args = func_get_args();
519
    $command = array_shift($args);
520
    $url = 'panels/ajax/' . $this->plugin['name'] . '/' . $command . '/' . $this->display->cache_key;
521
    if ($args) {
522
      $url .= '/' . implode('/', $args);
523
    }
524

    
525
    return $url;
526
  }
527

    
528
  /**
529
   * AJAX command to show a pane.
530
   */
531
  function ajax_show($pid = NULL) {
532
    if (empty($this->display->content[$pid])) {
533
      ctools_ajax_render_error(t('Invalid pane id.'));
534
    }
535

    
536
    $this->display->content[$pid]->shown = TRUE;
537
    panels_edit_cache_set($this->cache);
538

    
539
    $this->command_update_pane($pid);
540
  }
541

    
542
  /**
543
   * AJAX command to show a pane.
544
   */
545
  function ajax_hide($pid = NULL) {
546
    if (empty($this->display->content[$pid])) {
547
      ctools_ajax_render_error(t('Invalid pane id.'));
548
    }
549

    
550
    $this->display->content[$pid]->shown = FALSE;
551
    panels_edit_cache_set($this->cache);
552

    
553
    $this->command_update_pane($pid);
554
  }
555

    
556
  /**
557
   * AJAX command to present a dialog with a list of available content.
558
   */
559
  function ajax_select_content($region = NULL, $category = NULL) {
560
    if (!array_key_exists($region, $this->plugins['layout']['regions'])) {
561
      ctools_modal_render(t('Error'), t('Invalid input'));
562
    }
563

    
564
    $title = t('Add content to !s', array('!s' => $this->plugins['layout']['regions'][$region]));
565

    
566
    $categories = $this->get_categories($this->cache->content_types);
567

    
568
    if (empty($categories)) {
569
      $output = t('There are no content types you may add to this display.');
570
    }
571
    else {
572
      $output = theme('panels_add_content_modal', array('renderer' => $this, 'categories' => $categories, 'category' => $category, 'region' => $region));
573
    }
574
    $this->commands[] = ctools_modal_command_display($title, $output);
575
  }
576

    
577
  /**
578
   * Return the category name and the category key of a given content
579
   * type.
580
   *
581
   * @todo -- this should be in CTools.
582
   */
583
  function get_category($content_type) {
584
    if (isset($content_type['top level'])) {
585
      $category = 'root';
586
    }
587
    else if (isset($content_type['category'])) {
588
      if (is_array($content_type['category'])) {
589
        list($category, $weight) = $content_type['category'];
590
      }
591
      else {
592
        $category = $content_type['category'];
593
      }
594
    }
595
    else {
596
      $category = t('Uncategorized');
597
    }
598

    
599
    return array(preg_replace('/[^a-z0-9]/', '-', strtolower($category)), $category);
600
  }
601

    
602

    
603
  /**
604
   * Create a list of categories from all of the content type.
605
   *
606
   * @return array
607
   *   An array of categories. Each entry in the array will also be an array
608
   *   with 'title' as the printable title of the category, and 'content'
609
   *   being an array of all content in the category. Each item in the 'content'
610
   *   array contain the array plugin definition so that it can be later
611
   *   found in the content array. They will be keyed by the title so that they
612
   *   can be sorted.
613
   */
614
  function get_categories($content_types) {
615
    $categories = array();
616
    $category_names = array();
617

    
618
    foreach ($content_types as $type_name => $subtypes) {
619
      foreach ($subtypes as $subtype_name => $content_type) {
620
        list($category_key, $category) = $this->get_category($content_type);
621

    
622
        if (empty($categories[$category_key])) {
623
          $categories[$category_key] = array(
624
            'title' => $category,
625
            'content' => array(),
626
          );
627
          $category_names[$category_key] = $category;
628
        }
629

    
630
        $content_title = filter_xss_admin($content_type['title']);
631

    
632
        // Ensure content with the same title doesn't overwrite each other.
633
        while (isset($categories[$category_key]['content'][$content_title])) {
634
          $content_title .= '-';
635
        }
636

    
637
        $categories[$category_key]['content'][$content_title] = $content_type;
638
        $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
639
        $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
640
      }
641
    }
642

    
643
    // Now sort
644
    natcasesort($category_names);
645
    foreach ($category_names as $category => $name) {
646
      $output[$category] = $categories[$category];
647
    }
648

    
649
    return $output;
650
  }
651

    
652
  /**
653
   * AJAX entry point to add a new pane.
654
   */
655
  function ajax_add_pane($region = NULL, $type_name = NULL, $subtype_name = NULL, $step = NULL) {
656
    $content_type = ctools_get_content_type($type_name);
657
    $subtype = ctools_content_get_subtype($content_type, $subtype_name);
658

    
659
    if (!isset($step) || !isset($this->cache->new_pane)) {
660
      $pane = panels_new_pane($type_name, $subtype_name, TRUE);
661
      $this->cache->new_pane = &$pane;
662
    }
663
    else {
664
      $pane = &$this->cache->new_pane;
665
    }
666

    
667
    $form_state = array(
668
      'display' => &$this->cache->display,
669
      'contexts' => $this->cache->display->context,
670
      'pane' => &$pane,
671
      'cache_key' => $this->display->cache_key,
672
      'display cache' => &$this->cache,
673
      'ajax' => TRUE,
674
      'modal' => TRUE,
675
      // This will force the system to not automatically render.
676
      'modal return' => TRUE,
677
      'commands' => array(),
678
    );
679

    
680
    $form_info = array(
681
      'path' => $this->get_url('add-pane', $region, $type_name, $subtype_name, '%step'),
682
      'show cancel' => TRUE,
683
      'next callback' => 'panels_ajax_edit_pane_next',
684
      'finish callback' => 'panels_ajax_edit_pane_finish',
685
      'cancel callback' => 'panels_ajax_edit_pane_cancel',
686
    );
687

    
688
    $output = ctools_content_form('add', $form_info, $form_state, $content_type, $pane->subtype, $subtype, $pane->configuration, $step);
689

    
690
    // If $rc is FALSE, there was no actual form.
691
    if ($output === FALSE || !empty($form_state['complete'])) {
692
      // References get blown away with AJAX caching. This will fix that.
693
      $pane = $form_state['pane'];
694
      unset($this->cache->new_pane);
695

    
696
      // Add the pane to the display
697
      $this->display->add_pane($pane, $region);
698
      panels_edit_cache_set($this->cache);
699

    
700
      // Tell the client to draw the pane
701
      $this->command_add_pane($pane);
702

    
703
      // Dismiss the modal.
704
      $this->commands[] = ctools_modal_command_dismiss();
705
    }
706
    else if (!empty($form_state['cancel'])) {
707
      // If cancelling, return to the activity.
708
      list($category_key, $category) = $this->get_category($subtype);
709
      $this->ajax_select_content($region, $category_key);
710
    }
711
    else {
712
      // This overwrites any previous commands.
713
      $this->commands = ctools_modal_form_render($form_state, $output);
714
    }
715
  }
716

    
717
  /**
718
   * AJAX entry point to edit a pane.
719
   */
720
  function ajax_edit_pane($pid = NULL, $step = NULL) {
721
    if (empty($this->cache->display->content[$pid])) {
722
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
723
    }
724

    
725
    $pane = &$this->cache->display->content[$pid];
726

    
727
    $content_type = ctools_get_content_type($pane->type);
728
    $subtype = ctools_content_get_subtype($content_type, $pane->subtype);
729

    
730
    $form_state = array(
731
      'display' => &$this->cache->display,
732
      'contexts' => $this->cache->display->context,
733
      'pane' => &$pane,
734
      'display cache' => &$this->cache,
735
      'ajax' => TRUE,
736
      'modal' => TRUE,
737
      'modal return' => TRUE,
738
      'commands' => array(),
739
    );
740

    
741
    $form_info = array(
742
      'path' => $this->get_url('edit-pane', $pid, '%step'),
743
      'show cancel' => TRUE,
744
      'next callback' => 'panels_ajax_edit_pane_next',
745
      'finish callback' => 'panels_ajax_edit_pane_finish',
746
      'cancel callback' => 'panels_ajax_edit_pane_cancel',
747
    );
748

    
749
    $output = ctools_content_form('edit', $form_info, $form_state, $content_type, $pane->subtype,  $subtype, $pane->configuration, $step);
750

    
751
    // If $rc is FALSE, there was no actual form.
752
    if ($output === FALSE || !empty($form_state['cancel'])) {
753
      // Dismiss the modal.
754
      $this->commands[] = ctools_modal_command_dismiss();
755
    }
756
    else if (!empty($form_state['complete'])) {
757
      // References get blown away with AJAX caching. This will fix that.
758
      $this->cache->display->content[$pid] = $form_state['pane'];
759

    
760
      panels_edit_cache_set($this->cache);
761
      $this->command_update_pane($pid);
762
      $this->commands[] = ctools_modal_command_dismiss();
763
    }
764
    else {
765
      // This overwrites any previous commands.
766
      $this->commands = ctools_modal_form_render($form_state, $output);
767
    }
768
  }
769

    
770
  /**
771
   * AJAX entry point to select which pane is currently the title.
772
   *
773
   * @param string $pid
774
   *   The pane id for the pane object whose title state we're setting.
775
   */
776
  function ajax_panel_title($pid = NULL) {
777
    if (empty($this->display->content[$pid])) {
778
      ctools_ajax_render_error(t('Invalid pane id.'));
779
    }
780

    
781
    $pane = &$this->display->content[$pid];
782

    
783
    $old_title = !empty($this->display->title_pane) ? $this->display->title_pane : NULL;
784
    $this->display->title_pane = $pid;
785

    
786
    panels_edit_cache_set($this->cache);
787

    
788
    $this->command_update_pane($pane);
789

    
790
    if ($old_title && !empty($this->cache->display->content[$old_title])) {
791
      $this->command_update_pane($this->cache->display->content[$old_title]);
792
    }
793
  }
794

    
795
  /**
796
   * AJAX entry point to configure the cache method for a pane or the display.
797
   *
798
   * @param string $pid
799
   *   Either a pane id for a pane in the display, or 'display' to edit the
800
   *   display cache settings.
801
   */
802
  function ajax_cache_method($pid = NULL) {
803
    ctools_include('content');
804
    // This lets us choose whether we're doing the display's cache or
805
    // a pane's.
806
    if ($pid == 'display') {
807
      $conf = &$this->display->cache;
808
      $title = t('Cache method for this display');
809
    }
810
    else if (!empty($this->display->content[$pid])) {
811
      $pane = &$this->display->content[$pid];
812
      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
813
      $conf = &$pane->cache;
814
      $title = t('Cache method for !subtype_title', array('!subtype_title' => $subtype['title']));
815
    }
816
    else {
817
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
818
    }
819

    
820
    $form_state = array(
821
      'display' => &$this->display,
822
      'conf' => &$conf,
823
      'title' => $title,
824
      'ajax' => TRUE,
825
    );
826

    
827
    $output = ctools_modal_form_wrapper('panels_edit_cache_method_form', $form_state);
828
    if (empty($form_state['executed'])) {
829
      $this->commands = $output;
830
      return;
831
    }
832

    
833
    // Preserve this; this way we don't actually change the method until they
834
    // have saved the form.
835
    $info = panels_get_cache($form_state['method']);
836
    $function = panels_plugin_get_function('cache', $info, 'settings form');
837
    if (!$function) {
838
      $conf['method'] = $form_state['method'];
839
      $conf['settings'] = array();
840
      panels_edit_cache_set($this->cache);
841

    
842
      $this->commands[] = ctools_modal_command_dismiss();
843

    
844
      if ($pid != 'display') {
845
        $this->command_update_pane($pane);
846
      }
847
      else {
848
        $this->command_update_display_links();
849
      }
850
    }
851
    else {
852
      $this->cache->method = $form_state['method'];
853
      panels_edit_cache_set($this->cache);
854
      // send them to next form.
855
      return $this->ajax_cache_settings($pid);
856
    }
857
  }
858

    
859
  /**
860
   * AJAX entry point to configure the cache settings for a pane or the display.
861
   *
862
   * @param string $pid
863
   *   Either a pane id for a pane in the display, or 'display' to edit the
864
   *   display cache settings.
865
   */
866
  function ajax_cache_settings($pid = 0) {
867
    ctools_include('content');
868

    
869
    // This lets us choose whether we're doing the display's cache or
870
    // a pane's.
871
    if ($pid == 'display') {
872
      $conf = &$this->display->cache;
873
      $title = t('Cache settings for this display');
874
    }
875
    else if (!empty($this->display->content[$pid])) {
876
      $pane = &$this->display->content[$pid];
877
      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
878

    
879
      $conf = &$pane->cache;
880
      $title = t('Cache settings for !subtype_title', array('!subtype_title' => $subtype['title']));
881
    }
882
    else {
883
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
884
    }
885

    
886
    if (isset($this->cache->method) && (empty($conf['method']) || $conf['method'] != $this->cache->method)) {
887
      $conf['method'] = $this->cache->method;
888
      $info = panels_get_cache($conf['method']);
889
      $conf['settings'] = isset($info['defaults']) ? $info['defaults'] : array();
890
    }
891

    
892
    $form_state = array(
893
      'display' => &$this->display,
894
      'pid' => $pid,
895
      'conf' => &$conf,
896
      'ajax' => TRUE,
897
      'title' => $title,
898
      'url' => url($this->get_url('cache-settings', $pid), array('absolute' => TRUE)),
899
    );
900

    
901
    $output = ctools_modal_form_wrapper('panels_edit_cache_settings_form', $form_state);
902
    if (empty($form_state['executed'])) {
903
      $this->commands = $output;
904
      return;
905
    }
906

    
907
    panels_edit_cache_set($this->cache);
908

    
909
    $this->commands[] = ctools_modal_command_dismiss();
910

    
911
    if ($pid != 'display') {
912
      $this->command_update_pane($pane);
913
    }
914
    else {
915
      $this->command_update_display_links();
916
    }
917
  }
918

    
919
  /**
920
   * AJAX entry point to select the style for a display, region or pane.
921
   *
922
   * @param string $type
923
   *   Either display, region or pane
924
   * @param $pid
925
   *   The pane id, if a pane. The region id, if a region.
926
   */
927
  function ajax_style_type($type, $pid = NULL) {
928
    // This lets us choose whether we're doing the display's cache or
929
    // a pane's.
930
    switch ($type) {
931
      case 'display':
932
        $style = isset($this->display->panel_settings['style']) ? $this->display->panel_settings['style'] : 'default';
933
        $title = t('Default style for this display');
934
        break;
935

    
936
      case 'region':
937
        $style = isset($this->display->panel_settings[$pid]['style']) ? $this->display->panel_settings[$pid]['style'] : '-1'; // -1 signifies to use the default setting.
938
        $title = t('Panel style for region "!region"', array('!region' => $this->plugins['layout']['regions'][$pid]));
939
        break;
940

    
941
      case 'pane':
942
        ctools_include('content');
943
        $pane = &$this->display->content[$pid];
944
        $style = isset($pane->style['style']) ? $pane->style['style'] : 'default';
945
        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
946
        $title = t('Pane style for "!pane"', array('!pane' => $subtype['title']));
947
        break;
948

    
949
      default:
950
        ctools_modal_render(t('Error'), t('Invalid pane id.'));
951
    }
952
    $info = $this->get_style($type, $pid);
953
    $style_plugin = $info[0];
954
    $style_settings = $info[1];
955

    
956
    // Backward compatibility: Translate old-style stylizer to new style
957
    // stylizer.
958
    if ($style == 'stylizer' && !empty($style_settings['style']) && $style_settings['style'] != '$') {
959
      $style = 'stylizer:' . $style_settings['style'];
960
    }
961

    
962
    $form_state = array(
963
      'display' => &$this->display,
964
      'style' => $style,
965
      'pane' => ($type == 'pane') ? $this->display->content[$pid] : NULL,
966
      'title' => $title,
967
      'ajax' => TRUE,
968
      'type' => $type,
969
    );
970

    
971
    $output = ctools_modal_form_wrapper('panels_edit_style_type_form', $form_state);
972
    if (empty($form_state['executed'])) {
973
      $this->commands = $output;
974
      return;
975
    }
976

    
977
    // Preserve this; this way we don't actually change the method until they
978
    // have saved the form.
979
    $style = panels_get_style($form_state['style']);
980
    $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
981
    if (!$function) {
982
      if (isset($this->cache->style)) {
983
        unset($this->cache->style);
984
      }
985

    
986
      // If there's no settings form, just change the style and exit.
987
      switch($type) {
988
        case 'display':
989
          $this->display->panel_settings['style'] = $form_state['style'];
990
          if (isset($this->display->panel_settings['style_settings']['default'])) {
991
            unset($this->display->panel_settings['style_settings']['default']);
992
          }
993
          break;
994

    
995
        case 'region':
996
          $this->display->panel_settings[$pid]['style'] = $form_state['style'];
997
          if (isset($this->display->panel_settings['style_settings'][$pid])) {
998
            unset($this->display->panel_settings['style_settings'][$pid]);
999
          }
1000
          break;
1001

    
1002
        case 'pane':
1003
          $pane->style['style'] = $form_state['style'];
1004
          if (isset($pane->style['settings'])) {
1005
            unset($pane->style['settings']);
1006
          }
1007

    
1008
          break;
1009
      }
1010
      panels_edit_cache_set($this->cache);
1011

    
1012
      $this->commands[] = ctools_modal_command_dismiss();
1013

    
1014
      if ($type == 'pane') {
1015
        $this->command_update_pane($pane);
1016
      }
1017
      else if ($type == 'region') {
1018
        $this->command_update_region_links($pid);
1019
      }
1020
      else {
1021
        $this->command_update_display_links();
1022
      }
1023
    }
1024
    else {
1025
      if ($form_state['style'] != $form_state['old_style']) {
1026
        $this->cache->style = $form_state['style'];
1027
        panels_edit_cache_set($this->cache);
1028
      }
1029

    
1030
      // send them to next form.
1031
      return $this->ajax_style_settings($type, $pid);
1032
    }
1033
  }
1034

    
1035
  /**
1036
   * Get the appropriate style from the panel in the cache.
1037
   *
1038
   * Since we have styles for regions, panes and the display itself, and
1039
   * they are stored differently, we use this method to simplify getting
1040
   * style information into a way that's easy to cope with.
1041
   */
1042
  function get_style($type, $pid = '') {
1043
    if (isset($this->cache->style)) {
1044
      $style = panels_get_style($this->cache->style);
1045
      $defaults = isset($style['defaults']) ? $style['defaults'] : array();
1046
      // Get the &$conf variable based upon whose style we're editing.
1047
      switch ($type) {
1048
        case 'display':
1049
          $this->display->panel_settings['style'] = $this->cache->style;
1050
          $this->display->panel_settings['style_settings']['default'] = $defaults;
1051
          break;
1052

    
1053
        case 'region':
1054
          $this->display->panel_settings[$pid]['style'] = $this->cache->style;
1055
          $this->display->panel_settings['style_settings'][$pid] = $defaults;
1056
          break;
1057

    
1058
        case 'pane':
1059
          $pane = &$this->display->content[$pid];
1060
          $pane->style['style'] = $this->cache->style;
1061
          $pane->style['settings'] = $defaults;
1062
          $conf = &$pane->style['settings'];
1063
          break;
1064
      }
1065
    }
1066
    else {
1067
      switch ($type) {
1068
        case 'display':
1069
          $style = panels_get_style((!empty($this->display->panel_settings['style'])) ? $this->display->panel_settings['style'] : 'default');
1070
          break;
1071

    
1072
        case 'region':
1073
          $style = panels_get_style((!empty($this->display->panel_settings[$pid]['style'])) ? $this->display->panel_settings[$pid]['style'] : '-1');
1074
          break;
1075

    
1076
        case 'pane':
1077
          $pane = &$this->display->content[$pid];
1078
          $style = panels_get_style(!empty($pane->style['style']) ? $pane->style['style'] : 'default');
1079
          break;
1080
      }
1081
    }
1082

    
1083
    // Set up our $conf reference.
1084
    switch ($type) {
1085
      case 'display':
1086
        $conf = &$this->display->panel_settings['style_settings']['default'];
1087
        break;
1088

    
1089
      case 'region':
1090
        $conf = &$this->display->panel_settings['style_settings'][$pid];
1091
        break;
1092

    
1093
      case 'pane':
1094
        ctools_include('content');
1095
        $pane = &$this->display->content[$pid];
1096
        $conf = &$pane->style['settings'];
1097
        break;
1098
    }
1099

    
1100
    // Backward compatibility: Translate old-style stylizer to new style
1101
    // stylizer.
1102
    if ($style['name'] == 'stylizer' && !empty($conf['style']) && $conf['style'] != '$') {
1103
      $style = panels_get_style('stylizer:' . $conf['style']);
1104
    }
1105

    
1106
    return array($style, &$conf);
1107
  }
1108

    
1109
  /**
1110
   * AJAX entry point to configure the style for a display, region or pane.
1111
   *
1112
   * @param string $type
1113
   *   Either display, region or pane
1114
   * @param $pid
1115
   *   The pane id, if a pane. The region id, if a region.
1116
   */
1117
  function ajax_style_settings($type, $pid = '') {
1118
    $info = $this->get_style($type, $pid);
1119
    $style = $info[0];
1120
    $conf = &$info[1];
1121

    
1122
    switch ($type) {
1123
      case 'display':
1124
        $title = t('Style settings for @style (display)', array('@style' => $style['title']));
1125
        break;
1126

    
1127
      case 'region':
1128
        $title = t('Style settings for style @style (Region "!region")', array('@style' => $style['title'], '!region' => $this->plugins['layout']['regions'][$pid]));
1129
        break;
1130

    
1131
      case 'pane':
1132
        ctools_include('content');
1133
        $pane = &$this->display->content[$pid];
1134
        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1135
        $title = t('Style settings for style @style (Pane "!pane")', array('@style' => $style['title'], '!pane' => $subtype['title']));
1136
        break;
1137
    }
1138

    
1139
    $form_state = array(
1140
      'display' => &$this->display,
1141
      'type' => $type,
1142
      'pid' => $pid,
1143
      'conf' => &$conf,
1144
      'style' => $style,
1145
      'ajax' => TRUE,
1146
      'title' => $title,
1147
      'url' => url($this->get_url('style-settings', $type, $pid), array('absolute' => TRUE)),
1148
      'renderer' => &$this,
1149
    );
1150

    
1151
    $output = ctools_modal_form_wrapper('panels_edit_style_settings_form', $form_state);
1152
    if (empty($form_state['executed'])) {
1153
      $this->commands = $output;
1154
      return;
1155
    }
1156

    
1157
    if (isset($this->cache->style)) {
1158
      unset($this->cache->style);
1159
    }
1160

    
1161
    // $conf was a reference so it should just modify.
1162
    panels_edit_cache_set($this->cache);
1163

    
1164
    $this->commands[] = ctools_modal_command_dismiss();
1165

    
1166
    if ($type == 'pane') {
1167
      $this->command_update_pane($pane);
1168
    }
1169
    else if ($type == 'region') {
1170
      $this->command_update_region_links($pid);
1171
    }
1172
    else {
1173
      $this->command_update_display_links();
1174
    }
1175
  }
1176

    
1177
  /**
1178
   * AJAX entry point to configure CSS for a pane.
1179
   *
1180
   * @param $pid
1181
   *   The pane id to edit.
1182
   */
1183
  function ajax_pane_css($pid = NULL) {
1184
    if (empty($this->display->content[$pid])) {
1185
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1186
    }
1187

    
1188
    $pane = &$this->display->content[$pid];
1189
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1190

    
1191
    $form_state = array(
1192
      'display' => &$this->display,
1193
      'pane' => &$pane,
1194
      'ajax' => TRUE,
1195
      'title' => t('Configure CSS on !subtype_title', array('!subtype_title' => $subtype['title'])),
1196
    );
1197

    
1198
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_css_form', $form_state);
1199
    if (empty($form_state['executed'])) {
1200
      $this->commands = $output;
1201
      return;
1202
    }
1203

    
1204
    panels_edit_cache_set($this->cache);
1205
    $this->command_update_pane($pid);
1206
    $this->commands[] = ctools_modal_command_dismiss();
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_lock($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 lock on !subtype_title', array('!subtype_title' => $subtype['title'])),
1228
    );
1229

    
1230
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_lock_form', $form_state);
1231
    if (empty($form_state['executed'])) {
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($form_state['executed'])) {
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($form_state['executed'])) {
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
    $this->commands = $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($form_state['executed'])) {
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[] = ajax_command_replace("#panel-pane-$pane->pid", $this->render_pane($pane));
1435
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title 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[] = ajax_command_append("#panel-region-$pane->panel", $this->render_pane($pane));
1450
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title 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[] = 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[] = 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['display cache']->new_pane = $form_state['pane'];
1475
  panels_edit_cache_set($form_state['display 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, &$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, &$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, &$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' : '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, &$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, &$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
 * Configure lock on a pane form.
1756
 */
1757
function panels_edit_configure_pane_lock_form($form, &$form_state) {
1758
  $display = &$form_state['display'];
1759
  $pane = &$form_state['pane'];
1760

    
1761
  if (empty($pane->locks)) {
1762
    $pane->locks = array('type' => 'none', 'regions' => array());
1763
  }
1764

    
1765
  $form['type'] = array(
1766
    '#type' => 'radios',
1767
    '#title' => t('Lock type'),
1768
    '#options' => array(
1769
      'none' => t('No lock'),
1770
      'immovable' => t('Immovable'),
1771
      'regions' => t('Regions'),
1772
    ),
1773
    '#default_value' => $pane->locks['type'],
1774
  );
1775

    
1776
  $layout = panels_get_layout($display->layout);
1777
  $regions = panels_get_regions($layout, $display);
1778

    
1779
  $form['regions'] = array(
1780
    '#type' => 'checkboxes',
1781
    '#title' => t('Regions'),
1782
    '#options' => $regions,
1783
    '#description' => t('Select which regions this pane can be moved to.'),
1784
    '#dependency' => array(
1785
      'radio:type' => array('regions'),
1786
    ),
1787
    '#default_value' => $pane->locks['regions'],
1788
  );
1789

    
1790
  $form['#after_build'][] = 'panels_edit_configure_pane_lock_form_after_build';
1791
  $form['next'] = array(
1792
    '#type' => 'submit',
1793
    '#value' => t('Save'),
1794
  );
1795

    
1796
  return $form;
1797
}
1798

    
1799
function panels_edit_configure_pane_lock_form_after_build($element, $form_state) {
1800
  $region = $form_state['pane']->panel;
1801
  $element['regions'][$region]['#required'] = TRUE;
1802
  $element['regions'][$region]['#disabled'] = TRUE;
1803
  $element['regions'][$region]['#value'] = TRUE;
1804
  $element['regions'][$region]['#checked'] = TRUE;
1805
  $element['regions'][$region]['#attributes']['disabled'] = TRUE;
1806
  return $element;
1807
}
1808

    
1809
/**
1810
 * FAPI submission function for the lock configure form.
1811
 *
1812
 * All this does is set up $pane properly. The caller is responsible for
1813
 * actually storing this somewhere.
1814
 */
1815
function panels_edit_configure_pane_lock_form_submit($form, &$form_state) {
1816
  $pane = &$form_state['pane'];
1817
  $display = $form_state['display'];
1818

    
1819
  // We set this to true but forms do not submit disabled checkboxes
1820
  // and fapi is ignoring the #value directive probably because it
1821
  // is checkboxes:
1822
  $region = $form_state['pane']->panel;
1823
  $form_state['values']['regions'][$region] = $region;
1824

    
1825
  $pane->locks['type'] = $form_state['values']['type'];
1826
  $pane->locks['regions'] = array_filter($form_state['values']['regions']);
1827
}
1828

    
1829
/**
1830
 * Form to control basic visibility settings.
1831
 */
1832
function panels_edit_configure_access_settings_form($form, &$form_state) {
1833
  $display = &$form_state['display'];
1834
  $pane = &$form_state['pane'];
1835

    
1836
  $form['logic'] = array(
1837
    '#type' => 'radios',
1838
    '#options' => array(
1839
      'and' => t('All criteria must pass.'),
1840
      'or' => t('Only one criterion must pass.'),
1841
    ),
1842
    '#default_value' => isset($pane->access['logic']) ? $pane->access['logic'] : 'and',
1843
  );
1844

    
1845
  $form['next'] = array(
1846
    '#type' => 'submit',
1847
    '#value' => t('Save'),
1848
  );
1849

    
1850
  return $form;
1851
}
1852

    
1853
/**
1854
 * FAPI submission function for the edit access settings form.
1855
 *
1856
 * All this does is set up $pane properly. The caller is responsible for
1857
 * actually storing this somewhere.
1858
 */
1859
function panels_edit_configure_access_settings_form_submit($form, &$form_state) {
1860
  $pane = &$form_state['pane'];
1861
  $display = $form_state['display'];
1862

    
1863
  $pane->access['logic'] = $form_state['values']['logic'];
1864
}
1865

    
1866
/**
1867
 * Form to add a visibility rule.
1868
 */
1869
function panels_edit_add_access_test_form($form, &$form_state) {
1870
  $display = &$form_state['display'];
1871
  $pane = &$form_state['pane'];
1872

    
1873
  $plugins = ctools_get_relevant_access_plugins($display->context);
1874
  $options = array();
1875
  foreach ($plugins as $id => $plugin) {
1876
    $options[$id] = $plugin['title'];
1877
  }
1878

    
1879
  asort($options);
1880

    
1881
  $form['type'] = array(
1882
    // This ensures that the form item is added to the URL.
1883
    '#type' => 'radios',
1884
    '#options' => $options,
1885
  );
1886

    
1887
  $form['next'] = array(
1888
    '#type' => 'submit',
1889
    '#value' => t('Next'),
1890
  );
1891

    
1892
  return $form;
1893
}
1894

    
1895
/**
1896
 * Form to configure a visibility rule.
1897
 */
1898
function panels_edit_configure_access_test_form($form, &$form_state) {
1899
  $display = &$form_state['display'];
1900
  $test = &$form_state['test'];
1901
  $plugin = &$form_state['plugin'];
1902

    
1903
  $form['#action'] = $form_state['url'];
1904

    
1905
  $contexts = $display->context;
1906
  if (!isset($contexts['logged-in-user'])) {
1907
    $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1908
  }
1909

    
1910
  if (isset($plugin['required context'])) {
1911
    $form['context'] = ctools_context_selector($contexts, $plugin['required context'], $test['context']);
1912
  }
1913

    
1914
  $form['settings'] = array('#tree' => TRUE);
1915
  if ($function = ctools_plugin_get_function($plugin, 'settings form')) {
1916
    $form = $function($form, $form_state, $test['settings']);
1917
  }
1918

    
1919
  $form['not'] = array(
1920
    '#type' => 'checkbox',
1921
    '#title' => t('Reverse (NOT)'),
1922
    '#default_value' => !empty($test['not']),
1923
  );
1924

    
1925
  $form['save'] = array(
1926
    '#type' => 'submit',
1927
    '#value' => t('Save'),
1928
  );
1929

    
1930
  $form['remove'] = array(
1931
    '#type' => 'submit',
1932
    '#value' => t('Remove'),
1933
    '#remove' => TRUE,
1934
  );
1935

    
1936
  return $form;
1937
}
1938

    
1939
/**
1940
 * Validate handler for visibility rule settings
1941
 */
1942
function panels_edit_configure_access_test_form_validate(&$form, &$form_state) {
1943
  if (!empty($form_state['clicked_button']['#remove'])) {
1944
    return;
1945
  }
1946

    
1947
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
1948
    $function($form, $form_state);
1949
  }
1950
}
1951

    
1952
/**
1953
 * Submit handler for visibility rule settings
1954
 */
1955
function panels_edit_configure_access_test_form_submit(&$form, &$form_state) {
1956
  if (!empty($form_state['clicked_button']['#remove'])) {
1957
    $form_state['remove'] = TRUE;
1958
    return;
1959
  }
1960

    
1961
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
1962
    $function($form, $form_state);
1963
  }
1964

    
1965
  $form_state['test']['settings'] = $form_state['values']['settings'];
1966
  if (isset($form_state['values']['context'])) {
1967
    $form_state['test']['context'] = $form_state['values']['context'];
1968
  }
1969
  $form_state['test']['not'] = !empty($form_state['values']['not']);
1970
}
1971