Projet

Général

Profil

Paste
Télécharger (64,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / panels / plugins / display_renderers / panels_renderer_editor.class.php @ 08475715

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
      drupal_add_library('system', 'ui');
65
    }
66
  }
67

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

    
74
    $this->add_meta();
75

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

    
80
    return $output;
81
  }
82

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

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

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

    
93
    $output = "<div class='panel-region' id='panel-region-$region_id'>";
94
    $output .= $panel_buttons;
95
    $output .= "<h2 class='label'>" . check_plain($this->plugins['layout']['regions'][$region_id]) . "</h2>";
96
    $output .= $content;
97
    $output .= "</div>";
98

    
99
    return $output;
100
  }
101

    
102
  function render_pane(&$pane) {
103
    // Pass through to normal rendering if not in admin mode.
104
    if (!$this->admin) {
105
      return parent::render_pane($pane);
106
    }
107

    
108
    ctools_include('content');
109
    $content_type = ctools_get_content_type($pane->type);
110

    
111
    // This is just used for the title bar of the pane, not the content itself.
112
    // If we know the content type, use the appropriate title for that type,
113
    // otherwise, set the title using the content itself.
114
    $title = ctools_content_admin_title($content_type, $pane->subtype, $pane->configuration, $this->display->context);
115
    if (!$title) {
116
      $title = t('Deleted/missing content type @type', array('@type' => $pane->type));
117
    }
118

    
119
    $buttons = $this->get_pane_links($pane, $content_type);
120

    
121
    // Render administrative buttons for the pane.
122

    
123
    $block = new stdClass();
124
    if (empty($content_type)) {
125
      $block->title = '<em>' . t('Missing content type') . '</em>';
126
      $block->content = t('This pane\'s content type is either missing or has been deleted. This pane will not render.');
127
    }
128
    else {
129
      $block = ctools_content_admin_info($content_type, $pane->subtype, $pane->configuration, $this->display->context);
130
    }
131

    
132
    $grabber_class = 'grab-title grabber';
133
    // If there are region locks, add them.
134
    if (!empty($pane->locks['type'])) {
135
      if ($pane->locks['type'] == 'regions') {
136
        $settings['Panels']['RegionLock'][$pane->pid] = $pane->locks['regions'];
137
        drupal_add_js($settings, 'setting');
138
      }
139
      else if ($pane->locks['type'] == 'immovable') {
140
        $grabber_class = 'grab-title not-grabber';
141
      }
142
    }
143

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

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

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

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

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

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

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

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

    
175
    return $output;
176
  }
177

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

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

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

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

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

    
210
    return $style_links;
211
  }
212

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

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

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

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

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

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

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

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

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

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

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

    
298
    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));
299
  }
300

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

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

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

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

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

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

    
357
    if (user_access('administer panels styles')) {
358
      $links['style'] = $this->get_style_links('pane', $pane->pid);
359
    }
360

    
361
    if (user_access('administer pane access')) {
362
      $contexts = $this->display->context;
363
      // Make sure we have the logged in user context
364
      if (!isset($contexts['logged-in-user'])) {
365
        $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
366
      }
367

    
368
      $visibility_links = array();
369

    
370
      if (!empty($pane->access['plugins'])) {
371
        foreach ($pane->access['plugins'] as $id => $test) {
372
          $plugin = ctools_get_access_plugin($test['name']);
373
          $access_title = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));
374
          $access_description = ctools_access_summary($plugin, $contexts, $test);
375

    
376
          $visibility_links[] = array(
377
            'title' => $access_description,
378
            'href' => $this->get_url('access-configure-test', $pane->pid, $id),
379
            'attributes' => array('class' => array('ctools-use-modal', 'panels-italic')),
380
          );
381
        }
382
      }
383
      if (empty($visibility_links)) {
384
        $visibility_links['no_rules'] = array(
385
          'title' => t('No rules'),
386
          'attributes' => array('class' => array('panels-text')),
387
        );
388
      }
389

    
390
      $visibility_links['add_rule'] = array(
391
        'title' => t('Add new rule'),
392
        'href' => $this->get_url('access-add-test', $pane->pid),
393
        'attributes' => array('class' => array('ctools-use-modal')),
394
      );
395

    
396
      $visibility_links['settings'] = array(
397
        'title' => t('Settings'),
398
        'href' => $this->get_url('access-settings', $pane->pid),
399
        'attributes' => array('class' => array('ctools-use-modal')),
400
      );
401

    
402
      $links['visibility'] = $visibility_links;
403
    }
404

    
405
    if (user_access('use panels locks')) {
406
      $lock_type = !empty($pane->locks['type']) ? $pane->locks['type'] : 'none';
407
      switch ($lock_type) {
408
        case 'immovable':
409
          $lock_method = t('Immovable');
410
          break;
411
        case 'regions':
412
          $lock_method = t('Regions');
413
          break;
414
        case 'none':
415
        default:
416
          $lock_method = t('No lock');
417
          break;
418
      }
419

    
420
      $lock_links['lock'] = array(
421
        'title' => $lock_method,
422
        'attributes' => array('class' => array('panels-text')),
423
      );
424
      $lock_links['change'] = array(
425
        'title' => t('Change'),
426
        'href' => $this->get_url('lock', $pane->pid),
427
        'attributes' => array('class' => array('ctools-use-modal')),
428
      );
429

    
430
      $links['lock'] = $lock_links;
431
    }
432

    
433
    if (panels_get_caches() && user_access('use panels caching features')) {
434
      $method = isset($pane->cache['method']) ? $pane->cache['method'] : 0;
435
      $info = panels_get_cache($method);
436
      $cache_method = isset($info['title']) ? $info['title'] : t('No caching');
437
      $cache_links['title'] = array(
438
        'title' => $cache_method,
439
        'attributes' => array('class' => array('panels-text')),
440
      );
441
      $cache_links['change'] = array(
442
        'title' => t('Change'),
443
        'href' => $this->get_url('cache-method', $pane->pid),
444
        'attributes' => array('class' => array('ctools-use-modal')),
445
      );
446
      if (panels_plugin_get_function('cache', $info, 'settings form')) {
447
        $cache_links['settings'] = array(
448
          'title' => t('Settings'),
449
          'href' => $this->get_url('cache-settings', $pane->pid),
450
          'attributes' => array('class' => array('ctools-use-modal')),
451
        );
452
      }
453

    
454
      $links['cache'] = $cache_links;
455
    }
456

    
457
    $links['bottom']['remove'] = array(
458
      'title' => t('Remove'),
459
      'href' => '#',
460
      'attributes' => array(
461
        'class' => array('pane-delete'),
462
        'id' => "pane-delete-panel-pane-$pane->pid",
463
      ),
464
    );
465

    
466
    // Allow others to add/remove links from pane context menu.
467
    // Grouped by 'top', 'style', 'visibility', 'lock', 'cache' and 'bottom'
468
    drupal_alter('get_pane_links', $links, $pane, $content_type);
469

    
470
    $dropdown_links = $links['top'];
471
    $category_labels = array(
472
      'style' => 'Style',
473
      'visibility' => 'Visibility rules',
474
      'lock' => 'Locking',
475
      'cache' => 'Caching',
476
    );
477
    foreach ($category_labels as $category => $label) {
478
      if (array_key_exists($category, $links)) {
479
        $dropdown_links[] = array(
480
          'title' => '<hr />',
481
          'html' => TRUE,
482
        );
483
        $dropdown_links[] = array(
484
          'title' => '<span class="dropdown-header">' . t($label) . '</span>' . theme_links(array('links' => $links[$category], 'attributes' => array(), 'heading' => array())),
485
          'html' => TRUE,
486
          'attributes' => array('class' => array('panels-sub-menu')),
487
        );
488
      }
489
    }
490

    
491
    $dropdown_links[] = array(
492
      'title' => '<hr />',
493
      'html' => TRUE,
494
    );
495
    $dropdown_links = array_merge($dropdown_links, $links['bottom']);
496

    
497
    return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-configure.png', 'panels'))), 'links' => $dropdown_links, 'image' => TRUE));
498
  }
499

    
500
  // -----------------------------------------------------------------------
501
  // Display edit AJAX callbacks and helpers.
502

    
503
  /**
504
   * Generate a URL path for the AJAX editor.
505
   */
506
  function get_url() {
507
    $args = func_get_args();
508
    $command = array_shift($args);
509
    $url = 'panels/ajax/' . $this->plugin['name'] . '/' . $command . '/' . $this->display->cache_key;
510
    if ($args) {
511
      $url .= '/' . implode('/', $args);
512
    }
513

    
514
    return $url;
515
  }
516

    
517
  /**
518
   * Get the Panels storage oparation for a given renderer AJAX method.
519
   *
520
   * @param string $method
521
   *   The method name.
522
   *
523
   * @return string
524
   *   The Panels storage op.
525
   */
526
  function get_panels_storage_op_for_ajax($method) {
527
    switch ($method) {
528
      case 'ajax_show':
529
      case 'ajax_hide':
530
      case 'ajax_select_content':
531
      case 'ajax_add_pane':
532
      case 'ajax_edit_pane':
533
      case 'ajax_panel_title':
534
      case 'ajax_cache_method':
535
      case 'ajax_cache_settings':
536
      case 'ajax_style_type':
537
      case 'ajax_style_settings':
538
      case 'ajax_pane_css':
539
      case 'ajax_lock':
540
      case 'ajax_access_settings':
541
      case 'ajax_access_add_test':
542
      case 'ajax_access_configure_test':
543
      case 'ajax_layout':
544
      case 'ajax_style':
545
        return 'update';
546
    }
547

    
548
    return parent::get_panels_storage_op_for_ajax($method);
549
  }
550

    
551
  /**
552
   * AJAX command to show a pane.
553
   */
554
  function ajax_show($pid = NULL) {
555
    if (empty($this->display->content[$pid])) {
556
      ctools_ajax_render_error(t('Invalid pane id.'));
557
    }
558

    
559
    $this->display->content[$pid]->shown = TRUE;
560
    panels_edit_cache_set($this->cache);
561

    
562
    $this->command_update_pane($pid);
563
  }
564

    
565
  /**
566
   * AJAX command to show a pane.
567
   */
568
  function ajax_hide($pid = NULL) {
569
    if (empty($this->display->content[$pid])) {
570
      ctools_ajax_render_error(t('Invalid pane id.'));
571
    }
572

    
573
    $this->display->content[$pid]->shown = FALSE;
574
    panels_edit_cache_set($this->cache);
575

    
576
    $this->command_update_pane($pid);
577
  }
578

    
579
  /**
580
   * AJAX command to present a dialog with a list of available content.
581
   */
582
  function ajax_select_content($region = NULL, $category = NULL) {
583
    if (!array_key_exists($region, $this->plugins['layout']['regions'])) {
584
      ctools_modal_render(t('Error'), t('Invalid input'));
585
    }
586

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

    
589
    $categories = $this->get_categories($this->cache->content_types);
590

    
591
    if (empty($categories)) {
592
      $output = t('There are no content types you may add to this display.');
593
    }
594
    else {
595
      $output = theme('panels_add_content_modal', array('renderer' => $this, 'categories' => $categories, 'category' => $category, 'region' => $region));
596
    }
597
    $this->commands[] = ctools_modal_command_display($title, $output);
598

    
599
    // Give keybord focus to the first item in the category we just loaded.
600
    if (!empty($category)) {
601
      $this->commands[] = ajax_command_invoke(".panels-add-content-modal .panels-section-columns :focusable:first", 'focus');
602
    }
603
  }
604

    
605
  /**
606
   * Return the category name and the category key of a given content
607
   * type.
608
   *
609
   * @todo -- this should be in CTools.
610
   */
611
  function get_category($content_type) {
612
    if (!empty($content_type['top level'])) {
613
      $category = 'root';
614
    }
615
    else if (isset($content_type['category'])) {
616
      if (is_array($content_type['category'])) {
617
        list($category, $weight) = $content_type['category'];
618
      }
619
      else {
620
        $category = $content_type['category'];
621
      }
622
    }
623
    else {
624
      $category = t('Uncategorized');
625
    }
626

    
627
    return array(preg_replace('/[^a-z0-9]/', '-', strtolower($category)), $category);
628
  }
629

    
630

    
631
  /**
632
   * Create a list of categories from all of the content type.
633
   *
634
   * @return array
635
   *   An array of categories. Each entry in the array will also be an array
636
   *   with 'title' as the printable title of the category, and 'content'
637
   *   being an array of all content in the category. Each item in the 'content'
638
   *   array contain the array plugin definition so that it can be later
639
   *   found in the content array. They will be keyed by the title so that they
640
   *   can be sorted.
641
   */
642
  function get_categories($content_types) {
643
    $categories = array();
644
    $category_names = array();
645

    
646
    foreach ($content_types as $type_name => $subtypes) {
647
      foreach ($subtypes as $subtype_name => $content_type) {
648
        list($category_key, $category) = $this->get_category($content_type);
649

    
650
        if (empty($categories[$category_key])) {
651
          $categories[$category_key] = array(
652
            'title' => $category,
653
            'content' => array(),
654
          );
655
          $category_names[$category_key] = $category;
656
        }
657

    
658
        $content_title = filter_xss_admin($content_type['title']);
659

    
660
        // Ensure content with the same title doesn't overwrite each other.
661
        while (isset($categories[$category_key]['content'][$content_title])) {
662
          $content_title .= '-';
663
        }
664

    
665
        $categories[$category_key]['content'][$content_title] = $content_type;
666
        $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
667
        $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
668
      }
669
    }
670

    
671
    // Now sort
672
    natcasesort($category_names);
673
    foreach ($category_names as $category => $name) {
674
      $output[$category] = $categories[$category];
675
    }
676

    
677
    return $output;
678
  }
679

    
680
  /**
681
   * AJAX entry point to add a new pane.
682
   */
683
  function ajax_add_pane($region = NULL, $type_name = NULL, $subtype_name = NULL, $step = NULL) {
684
    $content_type = ctools_get_content_type($type_name);
685
    $subtype = ctools_content_get_subtype($content_type, $subtype_name);
686

    
687
    // Determine if we are adding a different pane than previously cached. This
688
    // is used to load the different pane into cache so that multistep forms
689
    // have the correct context instead of a previously cached version that
690
    // does not match the pane currently being added.
691
    $is_different_pane = FALSE;
692
    if (isset($this->cache) && isset($this->cache->new_pane)) {
693
      $diff_type = $type_name != $this->cache->new_pane->type;
694
      $diff_subtype = $subtype_name != $this->cache->new_pane->subtype;
695

    
696
      $is_different_pane = $diff_type || $diff_subtype;
697
    }
698

    
699
    if (!isset($step) || !isset($this->cache->new_pane) || $is_different_pane) {
700
      $pane = panels_new_pane($type_name, $subtype_name, TRUE);
701
      $this->cache->new_pane = &$pane;
702
    }
703
    else {
704
      $pane = &$this->cache->new_pane;
705
    }
706

    
707
    $form_state = array(
708
      'display' => &$this->cache->display,
709
      'contexts' => $this->cache->display->context,
710
      'pane' => &$pane,
711
      'cache_key' => $this->display->cache_key,
712
      'display cache' => &$this->cache,
713
      'ajax' => TRUE,
714
      'modal' => TRUE,
715
      // This will force the system to not automatically render.
716
      'modal return' => TRUE,
717
      'commands' => array(),
718
    );
719

    
720
    $form_info = array(
721
      'path' => $this->get_url('add-pane', $region, $type_name, $subtype_name, '%step'),
722
      'show cancel' => TRUE,
723
      'next callback' => 'panels_ajax_edit_pane_next',
724
      'finish callback' => 'panels_ajax_edit_pane_finish',
725
      'cancel callback' => 'panels_ajax_edit_pane_cancel',
726
    );
727

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

    
730
    // If $rc is FALSE, there was no actual form.
731
    if ($output === FALSE || !empty($form_state['complete'])) {
732
      // References get blown away with AJAX caching. This will fix that.
733
      $pane = $form_state['pane'];
734
      unset($this->cache->new_pane);
735

    
736
      // Add the pane to the display
737
      $this->display->add_pane($pane, $region);
738
      panels_edit_cache_set($this->cache);
739

    
740
      // Tell the client to draw the pane
741
      $this->command_add_pane($pane);
742

    
743
      // Dismiss the modal.
744
      $this->commands[] = ctools_modal_command_dismiss();
745
    }
746
    else if (!empty($form_state['cancel'])) {
747
      // If cancelling, return to the activity.
748
      list($category_key, $category) = $this->get_category($subtype);
749
      $this->ajax_select_content($region, $category_key);
750
    }
751
    else {
752
      // This overwrites any previous commands.
753
      $this->commands = ctools_modal_form_render($form_state, $output);
754
    }
755
  }
756

    
757
  /**
758
   * AJAX entry point to edit a pane.
759
   */
760
  function ajax_edit_pane($pid = NULL, $step = NULL) {
761
    if (empty($this->cache->display->content[$pid])) {
762
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
763
    }
764

    
765
    $pane = &$this->cache->display->content[$pid];
766

    
767
    $content_type = ctools_get_content_type($pane->type);
768
    $subtype = ctools_content_get_subtype($content_type, $pane->subtype);
769

    
770
    $form_state = array(
771
      'display' => &$this->cache->display,
772
      'contexts' => $this->cache->display->context,
773
      'pane' => &$pane,
774
      'display cache' => &$this->cache,
775
      'ajax' => TRUE,
776
      'modal' => TRUE,
777
      'modal return' => TRUE,
778
      'commands' => array(),
779
    );
780

    
781
    $form_info = array(
782
      'path' => $this->get_url('edit-pane', $pid, '%step'),
783
      'show cancel' => TRUE,
784
      'next callback' => 'panels_ajax_edit_pane_next',
785
      'finish callback' => 'panels_ajax_edit_pane_finish',
786
      'cancel callback' => 'panels_ajax_edit_pane_cancel',
787
    );
788

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

    
791
    // If $rc is FALSE, there was no actual form.
792
    if ($output === FALSE || !empty($form_state['cancel'])) {
793
      // Dismiss the modal.
794
      $this->commands[] = ctools_modal_command_dismiss();
795
    }
796
    else if (!empty($form_state['complete'])) {
797
      // References get blown away with AJAX caching. This will fix that.
798
      $this->cache->display->content[$pid] = $form_state['pane'];
799

    
800
      // Conditionally overwrite the context for this panel if present in the form state.
801
      if (!empty($form_state['display_cache']->display->context)) {
802
        $this->cache->display->context = $form_state['display_cache']->display->context;
803
      }
804

    
805
      panels_edit_cache_set($this->cache);
806
      $this->command_update_pane($pid);
807
      $this->commands[] = ctools_modal_command_dismiss();
808
    }
809
    else {
810
      // This overwrites any previous commands.
811
      $this->commands = ctools_modal_form_render($form_state, $output);
812
    }
813
  }
814

    
815
  /**
816
   * AJAX entry point to select which pane is currently the title.
817
   *
818
   * @param string $pid
819
   *   The pane id for the pane object whose title state we're setting.
820
   */
821
  function ajax_panel_title($pid = NULL) {
822
    if (empty($this->display->content[$pid])) {
823
      ctools_ajax_render_error(t('Invalid pane id.'));
824
    }
825

    
826
    $pane = &$this->display->content[$pid];
827

    
828
    $old_title = !empty($this->display->title_pane) ? $this->display->title_pane : NULL;
829
    $this->display->title_pane = $pid;
830

    
831
    panels_edit_cache_set($this->cache);
832

    
833
    $this->command_update_pane($pane);
834

    
835
    if ($old_title && !empty($this->cache->display->content[$old_title])) {
836
      $this->command_update_pane($this->cache->display->content[$old_title]);
837
    }
838
  }
839

    
840
  /**
841
   * AJAX entry point to configure the cache method for a pane or the display.
842
   *
843
   * @param string $pid
844
   *   Either a pane id for a pane in the display, or 'display' to edit the
845
   *   display cache settings.
846
   */
847
  function ajax_cache_method($pid = NULL) {
848
    ctools_include('content');
849
    // This lets us choose whether we're doing the display's cache or
850
    // a pane's.
851
    if ($pid == 'display') {
852
      $conf = &$this->display->cache;
853
      $title = t('Cache method for this display');
854
    }
855
    else if (!empty($this->display->content[$pid])) {
856
      $pane = &$this->display->content[$pid];
857
      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
858
      $conf = &$pane->cache;
859
      $title = t('Cache method for !subtype_title', array('!subtype_title' => $subtype['title']));
860
    }
861
    else {
862
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
863
    }
864

    
865
    $form_state = array(
866
      'display' => &$this->display,
867
      'conf' => &$conf,
868
      'title' => $title,
869
      'ajax' => TRUE,
870
    );
871

    
872
    $output = ctools_modal_form_wrapper('panels_edit_cache_method_form', $form_state);
873
    if (empty($form_state['executed'])) {
874
      $this->commands = $output;
875
      return;
876
    }
877

    
878
    // Preserve this; this way we don't actually change the method until they
879
    // have saved the form.
880
    $info = panels_get_cache($form_state['method']);
881
    $function = panels_plugin_get_function('cache', $info, 'settings form');
882
    if (!$function) {
883
      $conf['method'] = $form_state['method'];
884
      $conf['settings'] = array();
885
      panels_edit_cache_set($this->cache);
886

    
887
      $this->commands[] = ctools_modal_command_dismiss();
888

    
889
      if ($pid != 'display') {
890
        $this->command_update_pane($pane);
891
      }
892
      else {
893
        $this->command_update_display_links();
894
      }
895
    }
896
    else {
897
      $this->cache->method = $form_state['method'];
898
      panels_edit_cache_set($this->cache);
899
      // send them to next form.
900
      return $this->ajax_cache_settings($pid);
901
    }
902
  }
903

    
904
  /**
905
   * AJAX entry point to configure the cache settings for a pane or the display.
906
   *
907
   * @param string $pid
908
   *   Either a pane id for a pane in the display, or 'display' to edit the
909
   *   display cache settings.
910
   */
911
  function ajax_cache_settings($pid = 0) {
912
    ctools_include('content');
913

    
914
    // This lets us choose whether we're doing the display's cache or
915
    // a pane's.
916
    if ($pid == 'display') {
917
      $conf = &$this->display->cache;
918
      $title = t('Cache settings for this display');
919
    }
920
    else if (!empty($this->display->content[$pid])) {
921
      $pane = &$this->display->content[$pid];
922
      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
923

    
924
      $conf = &$pane->cache;
925
      $title = t('Cache settings for !subtype_title', array('!subtype_title' => $subtype['title']));
926
    }
927
    else {
928
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
929
    }
930

    
931
    if (isset($this->cache->method) && (empty($conf['method']) || $conf['method'] != $this->cache->method)) {
932
      $conf['method'] = $this->cache->method;
933
      $info = panels_get_cache($conf['method']);
934
      $conf['settings'] = isset($info['defaults']) ? $info['defaults'] : array();
935
    }
936

    
937
    $form_state = array(
938
      'display' => &$this->display,
939
      'pid' => $pid,
940
      'conf' => &$conf,
941
      'ajax' => TRUE,
942
      'title' => $title,
943
      'url' => url($this->get_url('cache-settings', $pid), array('absolute' => TRUE)),
944
    );
945

    
946
    $output = ctools_modal_form_wrapper('panels_edit_cache_settings_form', $form_state);
947
    if (empty($form_state['executed'])) {
948
      $this->commands = $output;
949
      return;
950
    }
951

    
952
    panels_edit_cache_set($this->cache);
953

    
954
    $this->commands[] = ctools_modal_command_dismiss();
955

    
956
    if ($pid != 'display') {
957
      $this->command_update_pane($pane);
958
    }
959
    else {
960
      $this->command_update_display_links();
961
    }
962
  }
963

    
964
  /**
965
   * AJAX entry point to select the style for a display, region or pane.
966
   *
967
   * @param string $type
968
   *   Either display, region or pane
969
   * @param $pid
970
   *   The pane id, if a pane. The region id, if a region.
971
   */
972
  function ajax_style_type($type, $pid = NULL) {
973
    // This lets us choose whether we're doing the display's cache or
974
    // a pane's.
975
    switch ($type) {
976
      case 'display':
977
        $style = isset($this->display->panel_settings['style']) ? $this->display->panel_settings['style'] : 'default';
978
        $title = t('Default style for this display');
979
        break;
980

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

    
986
      case 'pane':
987
        ctools_include('content');
988
        $pane = &$this->display->content[$pid];
989
        $style = isset($pane->style['style']) ? $pane->style['style'] : 'default';
990
        $title = ctools_content_admin_title($pane->type, $pane->subtype, $pane->configuration, $this->display->context);
991
        if (!$title) {
992
          $title = $pane->type;
993
        }
994
        $title = t('Pane style for "!title"', array('!title' => $title));
995
        break;
996

    
997
      default:
998
        ctools_modal_render(t('Error'), t('Invalid pane id.'));
999
    }
1000
    $info = $this->get_style($type, $pid);
1001
    $style_plugin = $info[0];
1002
    $style_settings = $info[1];
1003

    
1004
    // Backward compatibility: Translate old-style stylizer to new style
1005
    // stylizer.
1006
    if ($style == 'stylizer' && !empty($style_settings['style']) && $style_settings['style'] != '$') {
1007
      $style = 'stylizer:' . $style_settings['style'];
1008
    }
1009

    
1010
    $form_state = array(
1011
      'display' => &$this->display,
1012
      'style' => $style,
1013
      'pane' => ($type == 'pane') ? $this->display->content[$pid] : NULL,
1014
      'title' => $title,
1015
      'ajax' => TRUE,
1016
      'type' => $type,
1017
    );
1018

    
1019
    $output = ctools_modal_form_wrapper('panels_edit_style_type_form', $form_state);
1020
    if (empty($form_state['executed'])) {
1021
      $this->commands = $output;
1022
      return;
1023
    }
1024

    
1025
    // Preserve this; this way we don't actually change the method until they
1026
    // have saved the form.
1027
    $style = panels_get_style($form_state['style']);
1028
    $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
1029
    if (!$function) {
1030
      if (isset($this->cache->style)) {
1031
        unset($this->cache->style);
1032
      }
1033

    
1034
      // If there's no settings form, just change the style and exit.
1035
      switch($type) {
1036
        case 'display':
1037
          $this->display->panel_settings['style'] = $form_state['style'];
1038
          if (isset($this->display->panel_settings['style_settings']['default'])) {
1039
            unset($this->display->panel_settings['style_settings']['default']);
1040
          }
1041
          break;
1042

    
1043
        case 'region':
1044
          $this->display->panel_settings[$pid]['style'] = $form_state['style'];
1045
          if (isset($this->display->panel_settings['style_settings'][$pid])) {
1046
            unset($this->display->panel_settings['style_settings'][$pid]);
1047
          }
1048
          break;
1049

    
1050
        case 'pane':
1051
          $pane->style['style'] = $form_state['style'];
1052
          if (isset($pane->style['settings'])) {
1053
            unset($pane->style['settings']);
1054
          }
1055

    
1056
          break;
1057
      }
1058
      panels_edit_cache_set($this->cache);
1059

    
1060
      $this->commands[] = ctools_modal_command_dismiss();
1061

    
1062
      if ($type == 'pane') {
1063
        $this->command_update_pane($pane);
1064
      }
1065
      else if ($type == 'region') {
1066
        $this->command_update_region_links($pid);
1067
      }
1068
      else {
1069
        $this->command_update_display_links();
1070
      }
1071
    }
1072
    else {
1073
      if ($form_state['style'] != $form_state['old_style']) {
1074
        $this->cache->style = $form_state['style'];
1075
        panels_edit_cache_set($this->cache);
1076
      }
1077

    
1078
      // send them to next form.
1079
      return $this->ajax_style_settings($type, $pid);
1080
    }
1081
  }
1082

    
1083
  /**
1084
   * Get the appropriate style from the panel in the cache.
1085
   *
1086
   * Since we have styles for regions, panes and the display itself, and
1087
   * they are stored differently, we use this method to simplify getting
1088
   * style information into a way that's easy to cope with.
1089
   */
1090
  function get_style($type, $pid = '') {
1091
    if (isset($this->cache->style)) {
1092
      $style = panels_get_style($this->cache->style);
1093
      $defaults = isset($style['defaults']) ? $style['defaults'] : array();
1094
      // Get the &$conf variable based upon whose style we're editing.
1095
      switch ($type) {
1096
        case 'display':
1097
          $this->display->panel_settings['style'] = $this->cache->style;
1098
          $this->display->panel_settings['style_settings']['default'] = $defaults;
1099
          break;
1100

    
1101
        case 'region':
1102
          $this->display->panel_settings[$pid]['style'] = $this->cache->style;
1103
          $this->display->panel_settings['style_settings'][$pid] = $defaults;
1104
          break;
1105

    
1106
        case 'pane':
1107
          $pane = &$this->display->content[$pid];
1108
          $pane->style['style'] = $this->cache->style;
1109
          $pane->style['settings'] = $defaults;
1110
          $conf = &$pane->style['settings'];
1111
          break;
1112
      }
1113
    }
1114
    else {
1115
      switch ($type) {
1116
        case 'display':
1117
          $style = panels_get_style((!empty($this->display->panel_settings['style'])) ? $this->display->panel_settings['style'] : 'default');
1118
          break;
1119

    
1120
        case 'region':
1121
          $style = panels_get_style((!empty($this->display->panel_settings[$pid]['style'])) ? $this->display->panel_settings[$pid]['style'] : '-1');
1122
          break;
1123

    
1124
        case 'pane':
1125
          $pane = &$this->display->content[$pid];
1126
          $style = panels_get_style(!empty($pane->style['style']) ? $pane->style['style'] : 'default');
1127
          break;
1128
      }
1129
    }
1130

    
1131
    // Set up our $conf reference.
1132
    switch ($type) {
1133
      case 'display':
1134
        $conf = &$this->display->panel_settings['style_settings']['default'];
1135
        break;
1136

    
1137
      case 'region':
1138
        $conf = &$this->display->panel_settings['style_settings'][$pid];
1139
        break;
1140

    
1141
      case 'pane':
1142
        ctools_include('content');
1143
        $pane = &$this->display->content[$pid];
1144
        $conf = &$pane->style['settings'];
1145
        break;
1146
    }
1147

    
1148
    // Backward compatibility: Translate old-style stylizer to new style
1149
    // stylizer.
1150
    if ($style['name'] == 'stylizer' && !empty($conf['style']) && $conf['style'] != '$') {
1151
      $style = panels_get_style('stylizer:' . $conf['style']);
1152
    }
1153

    
1154
    return array($style, &$conf);
1155
  }
1156

    
1157
  /**
1158
   * AJAX entry point to configure the style for a display, region or pane.
1159
   *
1160
   * @param string $type
1161
   *   Either display, region or pane
1162
   * @param $pid
1163
   *   The pane id, if a pane. The region id, if a region.
1164
   */
1165
  function ajax_style_settings($type, $pid = '') {
1166
    $info = $this->get_style($type, $pid);
1167
    $style = $info[0];
1168
    $conf = &$info[1];
1169

    
1170
    switch ($type) {
1171
      case 'display':
1172
        $title = t('Style settings for @style (display)', array('@style' => $style['title']));
1173
        break;
1174

    
1175
      case 'region':
1176
        $title = t('Style settings for style @style (Region "!region")', array('@style' => $style['title'], '!region' => $this->plugins['layout']['regions'][$pid]));
1177
        break;
1178

    
1179
      case 'pane':
1180
        ctools_include('content');
1181
        $pane = &$this->display->content[$pid];
1182
        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1183
        $title = t('Style settings for style @style (Pane "!pane")', array('@style' => $style['title'], '!pane' => $subtype['title']));
1184
        break;
1185
    }
1186

    
1187
    $form_state = array(
1188
      'display' => &$this->display,
1189
      'type' => $type,
1190
      'pid' => $pid,
1191
      'conf' => &$conf,
1192
      'style' => $style,
1193
      'ajax' => TRUE,
1194
      'title' => $title,
1195
      'url' => url($this->get_url('style-settings', $type, $pid), array('absolute' => TRUE)),
1196
      'renderer' => &$this,
1197
    );
1198

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

    
1205
    if (isset($this->cache->style)) {
1206
      unset($this->cache->style);
1207
    }
1208

    
1209
    if (!empty($form_state['cancel'])) {
1210
      // The cache must be saved prior to dismissing the modal.
1211
      panels_edit_cache_set($this->cache);
1212
      $this->commands[] = ctools_modal_command_dismiss();
1213
      return;
1214
    }
1215

    
1216
    // Copy settings from form state back into the cache.
1217
    if(!empty($form_state['values']['settings'])) {
1218
      if ($type == 'pane') {
1219
        $this->cache->display->content[$pid]->style['settings'] = $form_state['values']['settings'];
1220
      }
1221
      else if($type == 'region') {
1222
        $this->cache->display->panel_settings['style_settings'][$pid] = $form_state['values']['settings'];
1223
      }
1224
    }
1225

    
1226
    panels_edit_cache_set($this->cache);
1227

    
1228
    $this->commands[] = ctools_modal_command_dismiss();
1229

    
1230
    if ($type == 'pane') {
1231
      $this->command_update_pane($pane);
1232
    }
1233
    else if ($type == 'region') {
1234
      $this->command_update_region_links($pid);
1235
    }
1236
    else {
1237
      $this->command_update_display_links();
1238
    }
1239
  }
1240

    
1241
  /**
1242
   * AJAX entry point to configure CSS for a pane.
1243
   *
1244
   * @param $pid
1245
   *   The pane id to edit.
1246
   */
1247
  function ajax_pane_css($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('Configure CSS on !subtype_title', array('!subtype_title' => $subtype['title'])),
1260
    );
1261

    
1262
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_css_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 to configure CSS for a pane.
1275
   *
1276
   * @param $pid
1277
   *   The pane id to edit.
1278
   */
1279
  function ajax_lock($pid = NULL) {
1280
    if (empty($this->display->content[$pid])) {
1281
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1282
    }
1283

    
1284
    $pane = &$this->display->content[$pid];
1285
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1286

    
1287
    $form_state = array(
1288
      'display' => &$this->display,
1289
      'pane' => &$pane,
1290
      'ajax' => TRUE,
1291
      'title' => t('Configure lock on !subtype_title', array('!subtype_title' => $subtype['title'])),
1292
    );
1293

    
1294
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_lock_form', $form_state);
1295
    if (empty($form_state['executed'])) {
1296
      $this->commands = $output;
1297
      return;
1298
    }
1299

    
1300
    panels_edit_cache_set($this->cache);
1301
    $this->command_update_pane($pid);
1302
    $this->commands[] = ctools_modal_command_dismiss();
1303
  }
1304

    
1305
  /**
1306
   * AJAX entry point to configure access settings for a pane.
1307
   *
1308
   * @param $pid
1309
   *   The pane id to edit.
1310
   */
1311
  function ajax_access_settings($pid = NULL) {
1312
    if (empty($this->display->content[$pid])) {
1313
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1314
    }
1315

    
1316
    $pane = &$this->display->content[$pid];
1317
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1318

    
1319
    $form_state = array(
1320
      'display' => &$this->display,
1321
      'pane' => &$pane,
1322
      'ajax' => TRUE,
1323
      'title' => t('Access settings on !subtype_title', array('!subtype_title' => $subtype['title'])),
1324
    );
1325

    
1326
    $output = ctools_modal_form_wrapper('panels_edit_configure_access_settings_form', $form_state);
1327
    if (empty($form_state['executed'])) {
1328
      $this->commands = $output;
1329
      return;
1330
    }
1331

    
1332
    panels_edit_cache_set($this->cache);
1333
    $this->command_update_pane($pid);
1334
    $this->commands[] = ctools_modal_command_dismiss();
1335
  }
1336

    
1337
  /**
1338
   * AJAX entry point for to add a visibility rule.
1339
   */
1340
  function ajax_access_add_test($pid = NULL) {
1341
    if (empty($this->display->content[$pid])) {
1342
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1343
    }
1344

    
1345
    $pane = &$this->display->content[$pid];
1346
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1347

    
1348
    $form_state = array(
1349
      'display' => &$this->display,
1350
      'pane' => &$pane,
1351
      'ajax' => TRUE,
1352
      'title' => t('Add visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1353
    );
1354

    
1355
    $output = ctools_modal_form_wrapper('panels_edit_add_access_test_form', $form_state);
1356
    if (!empty($form_state['executed'])) {
1357
      // Set up the plugin in cache
1358
      $plugin = ctools_get_access_plugin($form_state['values']['type']);
1359
      $this->cache->new_plugin = ctools_access_new_test($plugin);
1360
      panels_edit_cache_set($this->cache);
1361

    
1362
      // go to the next step.
1363
      return $this->ajax_access_configure_test($pid, 'add');
1364
    }
1365

    
1366
    $this->commands = $output;
1367
  }
1368

    
1369
  /**
1370
   * AJAX entry point for to configure vsibility rule.
1371
   */
1372
  function ajax_access_configure_test($pid = NULL, $id = NULL) {
1373
    if (empty($this->display->content[$pid])) {
1374
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1375
    }
1376

    
1377
    $pane = &$this->display->content[$pid];
1378
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1379

    
1380
    // Set this up here because $id gets changed later.
1381
    $url = $this->get_url('access-configure-test', $pid, $id);
1382

    
1383
    // If we're adding a new one, get the stored data from cache and
1384
    // add it. It's stored as a cache so that if this is closed
1385
    // we don't accidentally add an unconfigured plugin.
1386
    if ($id == 'add') {
1387
      $pane->access['plugins'][] = $this->cache->new_plugin;
1388
      $id = max(array_keys($pane->access['plugins']));
1389
    }
1390
    else if (empty($pane->access['plugins'][$id])) {
1391
      ctools_modal_render(t('Error'), t('Invalid test id.'));
1392
    }
1393

    
1394
    $form_state = array(
1395
      'display' => &$this->display,
1396
      'pane' => &$pane,
1397
      'ajax' => TRUE,
1398
      'title' => t('Configure visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1399
      'test' => &$pane->access['plugins'][$id],
1400
      'plugin' => ctools_get_access_plugin($pane->access['plugins'][$id]['name']),
1401
      'url' => url($url, array('absolute' => TRUE)),
1402
    );
1403

    
1404
    $output = ctools_modal_form_wrapper('panels_edit_configure_access_test_form', $form_state);
1405
    if (empty($form_state['executed'])) {
1406
      $this->commands = $output;
1407
      return;
1408
    }
1409

    
1410
    // Unset the new plugin
1411
    if (isset($this->cache->new_plugin)) {
1412
      unset($this->cache->new_plugin);
1413
    }
1414

    
1415
    if (!empty($form_state['remove'])) {
1416
      unset($pane->access['plugins'][$id]);
1417
    }
1418

    
1419
    panels_edit_cache_set($this->cache);
1420
    $this->command_update_pane($pid);
1421
    $this->commands[] = ctools_modal_command_dismiss();
1422
  }
1423

    
1424
  /**
1425
   * AJAX Router function for layout owned AJAX calls.
1426
   *
1427
   * Layouts like the flexible layout builder need callbacks of their own.
1428
   * This allows those layouts to simply declare their callbacks and use
1429
   * them with $this->get_url('layout', $command).
1430
   */
1431
  function ajax_layout() {
1432
    $args = func_get_args();
1433
    if (empty($args)) {
1434
      return MENU_NOT_FOUND;
1435
    }
1436

    
1437
    $command = array_shift($args);
1438
    if (empty($this->plugins['layout']['ajax'][$command]) || !function_exists($this->plugins['layout']['ajax'][$command])) {
1439
      return MENU_NOT_FOUND;
1440
    }
1441

    
1442
    // Make sure the this is always available to the called functions.
1443
    array_unshift($args, $this);
1444
    return call_user_func_array($this->plugins['layout']['ajax'][$command], $args);
1445
  }
1446

    
1447
  /**
1448
   * AJAX Router function for style owned AJAX calls.
1449
   *
1450
   * Styles like the stylizer need AJAX callbacks of their own. This
1451
   * allows the system to figure out which style is being referenced,
1452
   * load it, and execute the callback.
1453
   *
1454
   * This allows those layouts to simply declare their callbacks and use
1455
   * them using $this->get_url('style', $command, $type, $pid).
1456
   */
1457
  function ajax_style() {
1458
    $args = func_get_args();
1459
    if (count($args) < 3) {
1460
      return MENU_NOT_FOUND;
1461
    }
1462

    
1463
    $command = array_shift($args);
1464
    $type = array_shift($args);
1465
    $pid = array_shift($args);
1466

    
1467
    $info = $this->get_style($type, $pid);
1468

    
1469
    $style = $info[0];
1470
    $conf = &$info[1];
1471

    
1472
    if (empty($style['ajax'][$command]) || !function_exists($style['ajax'][$command])) {
1473
      return MENU_NOT_FOUND;
1474
    }
1475

    
1476
    // Make sure the this is always available to the called functions.
1477
    $args = array_merge(array(&$this, $style, &$conf, $type, $pid), $args);
1478
    return call_user_func_array($style['ajax'][$command], $args);
1479
  }
1480

    
1481
  // ------------------------------------------------------------------------
1482
  // AJAX command generators
1483
  //
1484
  // These are used to make sure that child implementations can control their
1485
  // own AJAX commands as needed.
1486

    
1487
  /**
1488
   * Create a command array to redraw a pane.
1489
   */
1490
  function command_update_pane($pid) {
1491
    if (is_object($pid)) {
1492
      $pane = $pid;
1493
    }
1494
    else {
1495
      $pane = $this->display->content[$pid];
1496
    }
1497

    
1498
    $this->commands[] = ajax_command_replace("#panel-pane-$pane->pid", $this->render_pane($pane));
1499
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title span.text");
1500
  }
1501

    
1502
  /**
1503
   * Create a command array to add a new pane.
1504
   */
1505
  function command_add_pane($pid) {
1506
    if (is_object($pid)) {
1507
      $pane = $pid;
1508
    }
1509
    else {
1510
      $pane = $this->display->content[$pid];
1511
    }
1512

    
1513
    $this->commands[] = ajax_command_append("#panel-region-$pane->panel", $this->render_pane($pane));
1514
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title span.text");
1515
  }
1516

    
1517
  /**
1518
   * Create a command to update the links on a display after a change was made.
1519
   */
1520
  function command_update_display_links() {
1521
    $this->commands[] = ajax_command_replace('.panels-display-links', $this->get_display_links());
1522
  }
1523

    
1524
  /**
1525
   * Create a command to update the links on a region after a change was made.
1526
   */
1527
  function command_update_region_links($id) {
1528
    $this->commands[] = ajax_command_replace('.panels-region-links-' . $id, $this->get_region_links($id));
1529
  }
1530
}
1531

    
1532
/**
1533
 * Handle the 'next' click on the add/edit pane form wizard.
1534
 *
1535
 * All we need to do is store the updated pane in the cache.
1536
 */
1537
function panels_ajax_edit_pane_next(&$form_state) {
1538
  $form_state['display cache']->new_pane = $form_state['pane'];
1539
  panels_edit_cache_set($form_state['display cache']);
1540
}
1541

    
1542
/**
1543
 * Handle the 'finish' click on the add/edit pane form wizard.
1544
 *
1545
 * All we need to do is set a flag so the return can handle adding
1546
 * the pane.
1547
 */
1548
function panels_ajax_edit_pane_finish(&$form_state) {
1549
  $form_state['complete'] = TRUE;
1550
  return;
1551
}
1552

    
1553
/**
1554
 * Handle the 'cancel' click on the add/edit pane form wizard.
1555
 */
1556
function panels_ajax_edit_pane_cancel(&$form_state) {
1557
  $form_state['cancel'] = TRUE;
1558
  return;
1559
}
1560

    
1561
// --------------------------------------------------------------------------
1562
// Forms for the editor object
1563

    
1564
/**
1565
 * Choose cache method form
1566
 */
1567
function panels_edit_cache_method_form($form, &$form_state) {
1568
  ctools_form_include($form_state, 'plugins', 'panels');
1569
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1570
  $display = &$form_state['display'];
1571
  $conf = &$form_state['conf'];
1572

    
1573
  // Set to 0 to ensure we get a selected radio.
1574
  if (!isset($conf['method'])) {
1575
    $conf['method'] = 0;
1576
  }
1577

    
1578
  $caches = panels_get_caches();
1579
  if (empty($caches)) {
1580
    $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.'));
1581
    return $form;
1582
  }
1583

    
1584
  $options[0] = t('No caching');
1585
  foreach ($caches as $cache => $info) {
1586
    $options[$cache] = check_plain($info['title']);
1587
  }
1588

    
1589
  $form['method'] = array(
1590
    '#prefix' => '<div class="no-float">',
1591
    '#suffix' => '</div>',
1592
    '#type' => 'radios',
1593
    '#title' => t('Method'),
1594
    '#options' => $options,
1595
    '#default_value' => $conf['method'],
1596
  );
1597

    
1598
  $form['submit'] = array(
1599
    '#type' => 'submit',
1600
    '#value' => t('Next'),
1601
  );
1602
  return $form;
1603
}
1604

    
1605
/**
1606
 * Submit callback for panels_edit_cache_method_form.
1607
 *
1608
 * All this needs to do is return the method.
1609
 */
1610
function panels_edit_cache_method_form_submit($form, &$form_state) {
1611
  $form_state['method'] = $form_state['values']['method'];
1612
}
1613

    
1614
/**
1615
 * Cache settings form
1616
 */
1617
function panels_edit_cache_settings_form($form, &$form_state) {
1618
  ctools_form_include($form_state, 'plugins', 'panels');
1619
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1620
  $display = &$form_state['display'];
1621
  $conf = &$form_state['conf'];
1622
  $pid = $form_state['pid'];
1623
  $info = panels_get_cache($conf['method']);
1624

    
1625
  $form['#action'] = $form_state['url'];
1626

    
1627
  $form['description'] = array(
1628
    '#prefix' => '<div class="description">',
1629
    '#suffix' => '</div>',
1630
    '#value' => check_plain($info['description']),
1631
  );
1632

    
1633
  $function = panels_plugin_get_function('cache', $conf['method'], 'settings form');
1634

    
1635
  $form['settings'] = $function($conf['settings'], $display, $pid);
1636
  $form['settings']['#tree'] = TRUE;
1637

    
1638
  $form['display'] = array(
1639
    '#type' => 'value',
1640
    '#value' => $display,
1641
  );
1642

    
1643
  $form['pid'] = array(
1644
    '#type' => 'value',
1645
    '#value' => $pid,
1646
  );
1647

    
1648
  $form['submit'] = array(
1649
    '#type' => 'submit',
1650
    '#value' => t('Save'),
1651
  );
1652

    
1653
  return $form;
1654
}
1655

    
1656
/**
1657
 * Validate cache settings.
1658
 */
1659
function panels_edit_cache_settings_form_validate($form, &$form_state) {
1660
  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form validate')) {
1661
    $function($form, $form_state['values']['settings']);
1662
  }
1663
}
1664

    
1665
/**
1666
 * Allows panel styles to validate their style settings.
1667
 */
1668
function panels_edit_cache_settings_form_submit($form, &$form_state) {
1669
  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form submit')) {
1670
    $function($form_state['values']['settings']);
1671
  }
1672

    
1673
  $form_state['conf']['settings'] = $form_state['values']['settings'];
1674
}
1675

    
1676
/**
1677
 * Choose style form
1678
 */
1679
function panels_edit_style_type_form($form, &$form_state) {
1680
  ctools_form_include($form_state, 'plugins', 'panels');
1681
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1682
  $display = &$form_state['display'];
1683
  $style = $form_state['style'];
1684
  $type = $form_state['type'];
1685

    
1686
  $styles = panels_get_styles();
1687

    
1688
  $function = ($type == 'pane' ? 'render pane' : 'render region');
1689
  $options = array();
1690
  if ($type == 'region') {
1691
    $options[-1] = t('Use display default style');
1692
  }
1693

    
1694
  uasort($styles, 'ctools_plugin_sort');
1695

    
1696
  foreach ($styles as $id => $info) {
1697
    if (empty($info['hidden']) && (!empty($info[$function]) || $id == 'default')) {
1698
      $options[$id] = check_plain($info['title']);
1699
    }
1700
  }
1701

    
1702
  $form['style'] = array(
1703
    '#prefix' => '<div class="no-float">',
1704
    '#suffix' => '</div>',
1705
    '#type' => 'radios',
1706
    '#title' => t('Style'),
1707
    '#options' => $options,
1708
    '#default_value' => $style,
1709
  );
1710

    
1711
  $form['submit'] = array(
1712
    '#type' => 'submit',
1713
    '#value' => t('Next'),
1714
  );
1715
  return $form;
1716
}
1717

    
1718
/**
1719
 * Submit callback for panels_edit_style_type_form.
1720
 *
1721
 * All this needs to do is return the method.
1722
 */
1723
function panels_edit_style_type_form_submit($form, &$form_state) {
1724
  $form_state['old_style'] = $form_state['style'];
1725
  $form_state['style'] = $form_state['values']['style'];
1726
}
1727

    
1728
/**
1729
 * Style settings form
1730
 */
1731
function panels_edit_style_settings_form($form, &$form_state) {
1732
  ctools_form_include($form_state, 'plugins', 'panels');
1733
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1734
  $display = &$form_state['display'];
1735
  $conf = &$form_state['conf'];
1736
  $pid = $form_state['pid'];
1737
  $style = $form_state['style'];
1738
  $type = $form_state['type'];
1739

    
1740
  $form['#action'] = $form_state['url'];
1741

    
1742
  $form['description'] = array(
1743
    '#prefix' => '<div class="description">',
1744
    '#suffix' => '</div>',
1745
    '#value' => check_plain($style['description']),
1746
  );
1747

    
1748
  $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
1749

    
1750
  $form['settings'] = $function($conf, $display, $pid, $type, $form_state);
1751
  $form['settings']['#tree'] = TRUE;
1752

    
1753
  $form['submit'] = array(
1754
    '#type' => 'submit',
1755
    '#value' => t('Save'),
1756
  );
1757

    
1758

    
1759
  // Need a cancel button since the style cache can persist and impact the wrong
1760
  // pane (or region, or display).
1761
  $form['cancel_style'] = array(
1762
    '#type' => 'submit',
1763
    '#value' => t('Cancel'),
1764
    '#submit' => array('panels_edit_style_settings_form_cancel'),
1765
  );
1766

    
1767
  return $form;
1768
}
1769

    
1770
/**
1771
 * Cancel style settings form.
1772
 *
1773
 * Clears the editing cache to prevent styles being applied to incorrect regions
1774
 * or panes.
1775
 */
1776
function panels_edit_style_settings_form_cancel($form, &$form_state) {
1777
  $form_state['cancel'] = TRUE;
1778
}
1779

    
1780
/**
1781
 * Validate style settings.
1782
 */
1783
function panels_edit_style_settings_form_validate($form, &$form_state) {
1784
  $name = $form_state['type'] == 'pane' ? 'pane settings form validate' : 'settings form validate';
1785
  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1786
    $function($form, $form_state['values']['settings'], $form_state);
1787
  }
1788
}
1789

    
1790
/**
1791
 * Allows panel styles to validate their style settings.
1792
 */
1793
function panels_edit_style_settings_form_submit($form, &$form_state) {
1794
  $name = $form_state['type'] == 'pane' ? 'pane settings form submit' : 'settings form submit';
1795
  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1796
    $function($form, $form_state['values']['settings'], $form_state);
1797
  }
1798

    
1799
  $form_state['conf'] = $form_state['values']['settings'];
1800
}
1801

    
1802

    
1803
/**
1804
 * Configure CSS on a pane form.
1805
 */
1806
function panels_edit_configure_pane_css_form($form, &$form_state) {
1807
  ctools_form_include($form_state, 'plugins', 'panels');
1808
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1809
  $display = &$form_state['display'];
1810
  $pane = &$form_state['pane'];
1811

    
1812
  $form['css_id'] = array(
1813
    '#type' => 'textfield',
1814
    '#default_value' => isset($pane->css['css_id']) ? $pane->css['css_id'] : '',
1815
    '#title' => t('CSS ID'),
1816
    '#description' => t('CSS ID to apply to this pane. This may be blank. Keywords from context are allowed.'),
1817
  );
1818
  $form['css_class'] = array(
1819
    '#type' => 'textfield',
1820
    '#default_value' => isset($pane->css['css_class']) ? $pane->css['css_class'] : '',
1821
    '#title' => t('CSS class'),
1822
    '#description' => t('CSS class to apply to this pane. This may be blank. Keywords from context are allowed.'),
1823
  );
1824

    
1825
  $form['next'] = array(
1826
    '#type' => 'submit',
1827
    '#value' => t('Save'),
1828
  );
1829

    
1830
  return $form;
1831
}
1832

    
1833
/**
1834
 * FAPI submission function for the CSS configure form.
1835
 *
1836
 * All this does is set up $pane properly. The caller is responsible for
1837
 * actually storing this somewhere.
1838
 */
1839
function panels_edit_configure_pane_css_form_submit($form, &$form_state) {
1840
  $pane = &$form_state['pane'];
1841
  $display = $form_state['display'];
1842

    
1843
  $pane->css['css_id'] = $form_state['values']['css_id'];
1844
  $pane->css['css_class'] = $form_state['values']['css_class'];
1845
}
1846

    
1847
/**
1848
 * Configure lock on a pane form.
1849
 */
1850
function panels_edit_configure_pane_lock_form($form, &$form_state) {
1851
  ctools_form_include($form_state, 'plugins', 'panels');
1852
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1853
  $display = &$form_state['display'];
1854
  $pane = &$form_state['pane'];
1855

    
1856
  if (empty($pane->locks)) {
1857
    $pane->locks = array('type' => 'none', 'regions' => array());
1858
  }
1859

    
1860
  $form['type'] = array(
1861
    '#type' => 'radios',
1862
    '#title' => t('Lock type'),
1863
    '#options' => array(
1864
      'none' => t('No lock'),
1865
      'immovable' => t('Immovable'),
1866
      'regions' => t('Regions'),
1867
    ),
1868
    '#default_value' => $pane->locks['type'],
1869
  );
1870

    
1871
  $layout = panels_get_layout($display->layout);
1872
  $regions = panels_get_regions($layout, $display);
1873

    
1874
  $form['regions'] = array(
1875
    '#type' => 'checkboxes',
1876
    '#title' => t('Regions'),
1877
    '#options' => $regions,
1878
    '#description' => t('Select which regions this pane can be moved to.'),
1879
    '#dependency' => array(
1880
      'radio:type' => array('regions'),
1881
    ),
1882
    '#default_value' => $pane->locks['regions'],
1883
  );
1884

    
1885
  $form['#after_build'][] = 'panels_edit_configure_pane_lock_form_after_build';
1886
  $form['next'] = array(
1887
    '#type' => 'submit',
1888
    '#value' => t('Save'),
1889
  );
1890

    
1891
  return $form;
1892
}
1893

    
1894
function panels_edit_configure_pane_lock_form_after_build($element, $form_state) {
1895
  $region = $form_state['pane']->panel;
1896
  $element['regions'][$region]['#required'] = TRUE;
1897
  $element['regions'][$region]['#disabled'] = TRUE;
1898
  $element['regions'][$region]['#value'] = TRUE;
1899
  $element['regions'][$region]['#checked'] = TRUE;
1900
  $element['regions'][$region]['#attributes']['disabled'] = TRUE;
1901
  return $element;
1902
}
1903

    
1904
/**
1905
 * FAPI submission function for the lock configure form.
1906
 *
1907
 * All this does is set up $pane properly. The caller is responsible for
1908
 * actually storing this somewhere.
1909
 */
1910
function panels_edit_configure_pane_lock_form_submit($form, &$form_state) {
1911
  $pane = &$form_state['pane'];
1912
  $display = $form_state['display'];
1913

    
1914
  // We set this to true but forms do not submit disabled checkboxes
1915
  // and fapi is ignoring the #value directive probably because it
1916
  // is checkboxes:
1917
  $region = $form_state['pane']->panel;
1918
  $form_state['values']['regions'][$region] = $region;
1919

    
1920
  $pane->locks['type'] = $form_state['values']['type'];
1921
  $pane->locks['regions'] = array_filter($form_state['values']['regions']);
1922
}
1923

    
1924
/**
1925
 * Form to control basic visibility settings.
1926
 */
1927
function panels_edit_configure_access_settings_form($form, &$form_state) {
1928
  ctools_form_include($form_state, 'plugins', 'panels');
1929
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1930
  $display = &$form_state['display'];
1931
  $pane = &$form_state['pane'];
1932

    
1933
  $form['logic'] = array(
1934
    '#type' => 'radios',
1935
    '#options' => array(
1936
      'and' => t('All criteria must pass.'),
1937
      'or' => t('Only one criterion must pass.'),
1938
    ),
1939
    '#default_value' => isset($pane->access['logic']) ? $pane->access['logic'] : 'and',
1940
  );
1941

    
1942
  $form['next'] = array(
1943
    '#type' => 'submit',
1944
    '#value' => t('Save'),
1945
  );
1946

    
1947
  return $form;
1948
}
1949

    
1950
/**
1951
 * FAPI submission function for the edit access settings form.
1952
 *
1953
 * All this does is set up $pane properly. The caller is responsible for
1954
 * actually storing this somewhere.
1955
 */
1956
function panels_edit_configure_access_settings_form_submit($form, &$form_state) {
1957
  $pane = &$form_state['pane'];
1958
  $display = $form_state['display'];
1959

    
1960
  $pane->access['logic'] = $form_state['values']['logic'];
1961
}
1962

    
1963
/**
1964
 * Form to add a visibility rule.
1965
 */
1966
function panels_edit_add_access_test_form($form, &$form_state) {
1967
  ctools_form_include($form_state, 'plugins', 'panels');
1968
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1969
  $display = &$form_state['display'];
1970
  $pane = &$form_state['pane'];
1971

    
1972
  $plugins = ctools_get_relevant_access_plugins($display->context);
1973
  $options = array();
1974
  foreach ($plugins as $id => $plugin) {
1975
    $options[$id] = $plugin['title'];
1976
  }
1977

    
1978
  asort($options);
1979

    
1980
  $form['type'] = array(
1981
    // This ensures that the form item is added to the URL.
1982
    '#type' => 'radios',
1983
    '#options' => $options,
1984
  );
1985

    
1986
  $form['next'] = array(
1987
    '#type' => 'submit',
1988
    '#value' => t('Next'),
1989
  );
1990

    
1991
  return $form;
1992
}
1993

    
1994
/**
1995
 * Form to configure a visibility rule.
1996
 */
1997
function panels_edit_configure_access_test_form($form, &$form_state) {
1998
  ctools_form_include($form_state, 'plugins', 'panels');
1999
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
2000
  $display = &$form_state['display'];
2001
  $test = &$form_state['test'];
2002
  $plugin = &$form_state['plugin'];
2003

    
2004
  $form['#action'] = $form_state['url'];
2005

    
2006
  $contexts = $display->context;
2007
  if (!isset($contexts['logged-in-user'])) {
2008
    $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
2009
  }
2010

    
2011
  if (isset($plugin['required context'])) {
2012
    $form['context'] = ctools_context_selector($contexts, $plugin['required context'], $test['context']);
2013
  }
2014

    
2015
  $form['settings'] = array('#tree' => TRUE);
2016
  if ($function = ctools_plugin_get_function($plugin, 'settings form')) {
2017
    $form = $function($form, $form_state, $test['settings']);
2018
  }
2019

    
2020
  $form['not'] = array(
2021
    '#type' => 'checkbox',
2022
    '#title' => t('Reverse (NOT)'),
2023
    '#default_value' => !empty($test['not']),
2024
  );
2025

    
2026
  $form['save'] = array(
2027
    '#type' => 'submit',
2028
    '#value' => t('Save'),
2029
  );
2030

    
2031
  $form['remove'] = array(
2032
    '#type' => 'submit',
2033
    '#value' => t('Remove'),
2034
    '#remove' => TRUE,
2035
  );
2036

    
2037
  return $form;
2038
}
2039

    
2040
/**
2041
 * Validate handler for visibility rule settings
2042
 */
2043
function panels_edit_configure_access_test_form_validate(&$form, &$form_state) {
2044
  if (!empty($form_state['clicked_button']['#remove'])) {
2045
    return;
2046
  }
2047

    
2048
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
2049
    $function($form, $form_state);
2050
  }
2051
}
2052

    
2053
/**
2054
 * Submit handler for visibility rule settings
2055
 */
2056
function panels_edit_configure_access_test_form_submit(&$form, &$form_state) {
2057
  if (!empty($form_state['clicked_button']['#remove'])) {
2058
    $form_state['remove'] = TRUE;
2059
    return;
2060
  }
2061

    
2062
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
2063
    $function($form, $form_state);
2064
  }
2065

    
2066
  $form_state['test']['settings'] = $form_state['values']['settings'];
2067
  if (isset($form_state['values']['context'])) {
2068
    $form_state['test']['context'] = $form_state['values']['context'];
2069
  }
2070
  $form_state['test']['not'] = !empty($form_state['values']['not']);
2071
}
2072