Projet

Général

Profil

Paste
Télécharger (63,4 ko) Statistiques
| Branche: | Révision:

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

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 (empty($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="' . check_plain($title) . '">' . $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['title'] = array(
190
      'title' => $style_title,
191
      'attributes' => array('class' => array('panels-text')),
192
    );
193

    
194
    $style_links['change'] = 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['settings'] = 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['top']['disabled'] = 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['top']['enable'] = 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['top']['panels-set-title'] = array(
326
        'title' => t('&#x2713;Panel title'),
327
        'html' => TRUE,
328
      );
329
    }
330
    else {
331
      $links['top']['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['top']['settings'] = 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['top']['css'] = 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['style'] = $this->get_style_links('pane', $pane->pid);
358
    }
359

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

    
367
      $visibility_links = array();
368

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
513
    return $url;
514
  }
515

    
516
  /**
517
   * AJAX command to show a pane.
518
   */
519
  function ajax_show($pid = NULL) {
520
    if (empty($this->display->content[$pid])) {
521
      ctools_ajax_render_error(t('Invalid pane id.'));
522
    }
523

    
524
    $this->display->content[$pid]->shown = TRUE;
525
    panels_edit_cache_set($this->cache);
526

    
527
    $this->command_update_pane($pid);
528
  }
529

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

    
538
    $this->display->content[$pid]->shown = FALSE;
539
    panels_edit_cache_set($this->cache);
540

    
541
    $this->command_update_pane($pid);
542
  }
543

    
544
  /**
545
   * AJAX command to present a dialog with a list of available content.
546
   */
547
  function ajax_select_content($region = NULL, $category = NULL) {
548
    if (!array_key_exists($region, $this->plugins['layout']['regions'])) {
549
      ctools_modal_render(t('Error'), t('Invalid input'));
550
    }
551

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

    
554
    $categories = $this->get_categories($this->cache->content_types);
555

    
556
    if (empty($categories)) {
557
      $output = t('There are no content types you may add to this display.');
558
    }
559
    else {
560
      $output = theme('panels_add_content_modal', array('renderer' => $this, 'categories' => $categories, 'category' => $category, 'region' => $region));
561
    }
562
    $this->commands[] = ctools_modal_command_display($title, $output);
563
  }
564

    
565
  /**
566
   * Return the category name and the category key of a given content
567
   * type.
568
   *
569
   * @todo -- this should be in CTools.
570
   */
571
  function get_category($content_type) {
572
    if (!empty($content_type['top level'])) {
573
      $category = 'root';
574
    }
575
    else if (isset($content_type['category'])) {
576
      if (is_array($content_type['category'])) {
577
        list($category, $weight) = $content_type['category'];
578
      }
579
      else {
580
        $category = $content_type['category'];
581
      }
582
    }
583
    else {
584
      $category = t('Uncategorized');
585
    }
586

    
587
    return array(preg_replace('/[^a-z0-9]/', '-', strtolower($category)), $category);
588
  }
589

    
590

    
591
  /**
592
   * Create a list of categories from all of the content type.
593
   *
594
   * @return array
595
   *   An array of categories. Each entry in the array will also be an array
596
   *   with 'title' as the printable title of the category, and 'content'
597
   *   being an array of all content in the category. Each item in the 'content'
598
   *   array contain the array plugin definition so that it can be later
599
   *   found in the content array. They will be keyed by the title so that they
600
   *   can be sorted.
601
   */
602
  function get_categories($content_types) {
603
    $categories = array();
604
    $category_names = array();
605

    
606
    foreach ($content_types as $type_name => $subtypes) {
607
      foreach ($subtypes as $subtype_name => $content_type) {
608
        list($category_key, $category) = $this->get_category($content_type);
609

    
610
        if (empty($categories[$category_key])) {
611
          $categories[$category_key] = array(
612
            'title' => $category,
613
            'content' => array(),
614
          );
615
          $category_names[$category_key] = $category;
616
        }
617

    
618
        $content_title = filter_xss_admin($content_type['title']);
619

    
620
        // Ensure content with the same title doesn't overwrite each other.
621
        while (isset($categories[$category_key]['content'][$content_title])) {
622
          $content_title .= '-';
623
        }
624

    
625
        $categories[$category_key]['content'][$content_title] = $content_type;
626
        $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;
627
        $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;
628
      }
629
    }
630

    
631
    // Now sort
632
    natcasesort($category_names);
633
    foreach ($category_names as $category => $name) {
634
      $output[$category] = $categories[$category];
635
    }
636

    
637
    return $output;
638
  }
639

    
640
  /**
641
   * AJAX entry point to add a new pane.
642
   */
643
  function ajax_add_pane($region = NULL, $type_name = NULL, $subtype_name = NULL, $step = NULL) {
644
    $content_type = ctools_get_content_type($type_name);
645
    $subtype = ctools_content_get_subtype($content_type, $subtype_name);
646

    
647
    // Determine if we are adding a different pane than previously cached. This
648
    // is used to load the different pane into cache so that multistep forms
649
    // have the correct context instead of a previously cached version that
650
    // does not match the pane currently being added.
651
    $is_different_pane = FALSE;
652
    if (isset($this->cache) && isset($this->cache->new_pane)) {
653
      $diff_type = $type_name != $this->cache->new_pane->type;
654
      $diff_subtype = $subtype_name != $this->cache->new_pane->subtype;
655

    
656
      $is_different_pane = $diff_type || $diff_subtype;
657
    }
658

    
659
    if (!isset($step) || !isset($this->cache->new_pane) || $is_different_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
      // Conditionally overwrite the context for this panel if present in the form state.
761
      if (!empty($form_state['display_cache']->display->context)) {
762
        $this->cache->display->context = $form_state['display_cache']->display->context;
763
      }
764

    
765
      panels_edit_cache_set($this->cache);
766
      $this->command_update_pane($pid);
767
      $this->commands[] = ctools_modal_command_dismiss();
768
    }
769
    else {
770
      // This overwrites any previous commands.
771
      $this->commands = ctools_modal_form_render($form_state, $output);
772
    }
773
  }
774

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

    
786
    $pane = &$this->display->content[$pid];
787

    
788
    $old_title = !empty($this->display->title_pane) ? $this->display->title_pane : NULL;
789
    $this->display->title_pane = $pid;
790

    
791
    panels_edit_cache_set($this->cache);
792

    
793
    $this->command_update_pane($pane);
794

    
795
    if ($old_title && !empty($this->cache->display->content[$old_title])) {
796
      $this->command_update_pane($this->cache->display->content[$old_title]);
797
    }
798
  }
799

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

    
825
    $form_state = array(
826
      'display' => &$this->display,
827
      'conf' => &$conf,
828
      'title' => $title,
829
      'ajax' => TRUE,
830
    );
831

    
832
    $output = ctools_modal_form_wrapper('panels_edit_cache_method_form', $form_state);
833
    if (empty($form_state['executed'])) {
834
      $this->commands = $output;
835
      return;
836
    }
837

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

    
847
      $this->commands[] = ctools_modal_command_dismiss();
848

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

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

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

    
884
      $conf = &$pane->cache;
885
      $title = t('Cache settings for !subtype_title', array('!subtype_title' => $subtype['title']));
886
    }
887
    else {
888
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
889
    }
890

    
891
    if (isset($this->cache->method) && (empty($conf['method']) || $conf['method'] != $this->cache->method)) {
892
      $conf['method'] = $this->cache->method;
893
      $info = panels_get_cache($conf['method']);
894
      $conf['settings'] = isset($info['defaults']) ? $info['defaults'] : array();
895
    }
896

    
897
    $form_state = array(
898
      'display' => &$this->display,
899
      'pid' => $pid,
900
      'conf' => &$conf,
901
      'ajax' => TRUE,
902
      'title' => $title,
903
      'url' => url($this->get_url('cache-settings', $pid), array('absolute' => TRUE)),
904
    );
905

    
906
    $output = ctools_modal_form_wrapper('panels_edit_cache_settings_form', $form_state);
907
    if (empty($form_state['executed'])) {
908
      $this->commands = $output;
909
      return;
910
    }
911

    
912
    panels_edit_cache_set($this->cache);
913

    
914
    $this->commands[] = ctools_modal_command_dismiss();
915

    
916
    if ($pid != 'display') {
917
      $this->command_update_pane($pane);
918
    }
919
    else {
920
      $this->command_update_display_links();
921
    }
922
  }
923

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

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

    
946
      case 'pane':
947
        ctools_include('content');
948
        $pane = &$this->display->content[$pid];
949
        $style = isset($pane->style['style']) ? $pane->style['style'] : 'default';
950
        $title = ctools_content_admin_title($pane->type, $pane->subtype, $pane->configuration, $this->display->context);
951
        if (!$title) {
952
          $title = $pane->type;
953
        }
954
        $title = t('Pane style for "!title"', array('!title' => $title));
955
        break;
956

    
957
      default:
958
        ctools_modal_render(t('Error'), t('Invalid pane id.'));
959
    }
960
    $info = $this->get_style($type, $pid);
961
    $style_plugin = $info[0];
962
    $style_settings = $info[1];
963

    
964
    // Backward compatibility: Translate old-style stylizer to new style
965
    // stylizer.
966
    if ($style == 'stylizer' && !empty($style_settings['style']) && $style_settings['style'] != '$') {
967
      $style = 'stylizer:' . $style_settings['style'];
968
    }
969

    
970
    $form_state = array(
971
      'display' => &$this->display,
972
      'style' => $style,
973
      'pane' => ($type == 'pane') ? $this->display->content[$pid] : NULL,
974
      'title' => $title,
975
      'ajax' => TRUE,
976
      'type' => $type,
977
    );
978

    
979
    $output = ctools_modal_form_wrapper('panels_edit_style_type_form', $form_state);
980
    if (empty($form_state['executed'])) {
981
      $this->commands = $output;
982
      return;
983
    }
984

    
985
    // Preserve this; this way we don't actually change the method until they
986
    // have saved the form.
987
    $style = panels_get_style($form_state['style']);
988
    $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');
989
    if (!$function) {
990
      if (isset($this->cache->style)) {
991
        unset($this->cache->style);
992
      }
993

    
994
      // If there's no settings form, just change the style and exit.
995
      switch($type) {
996
        case 'display':
997
          $this->display->panel_settings['style'] = $form_state['style'];
998
          if (isset($this->display->panel_settings['style_settings']['default'])) {
999
            unset($this->display->panel_settings['style_settings']['default']);
1000
          }
1001
          break;
1002

    
1003
        case 'region':
1004
          $this->display->panel_settings[$pid]['style'] = $form_state['style'];
1005
          if (isset($this->display->panel_settings['style_settings'][$pid])) {
1006
            unset($this->display->panel_settings['style_settings'][$pid]);
1007
          }
1008
          break;
1009

    
1010
        case 'pane':
1011
          $pane->style['style'] = $form_state['style'];
1012
          if (isset($pane->style['settings'])) {
1013
            unset($pane->style['settings']);
1014
          }
1015

    
1016
          break;
1017
      }
1018
      panels_edit_cache_set($this->cache);
1019

    
1020
      $this->commands[] = ctools_modal_command_dismiss();
1021

    
1022
      if ($type == 'pane') {
1023
        $this->command_update_pane($pane);
1024
      }
1025
      else if ($type == 'region') {
1026
        $this->command_update_region_links($pid);
1027
      }
1028
      else {
1029
        $this->command_update_display_links();
1030
      }
1031
    }
1032
    else {
1033
      if ($form_state['style'] != $form_state['old_style']) {
1034
        $this->cache->style = $form_state['style'];
1035
        panels_edit_cache_set($this->cache);
1036
      }
1037

    
1038
      // send them to next form.
1039
      return $this->ajax_style_settings($type, $pid);
1040
    }
1041
  }
1042

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

    
1061
        case 'region':
1062
          $this->display->panel_settings[$pid]['style'] = $this->cache->style;
1063
          $this->display->panel_settings['style_settings'][$pid] = $defaults;
1064
          break;
1065

    
1066
        case 'pane':
1067
          $pane = &$this->display->content[$pid];
1068
          $pane->style['style'] = $this->cache->style;
1069
          $pane->style['settings'] = $defaults;
1070
          $conf = &$pane->style['settings'];
1071
          break;
1072
      }
1073
    }
1074
    else {
1075
      switch ($type) {
1076
        case 'display':
1077
          $style = panels_get_style((!empty($this->display->panel_settings['style'])) ? $this->display->panel_settings['style'] : 'default');
1078
          break;
1079

    
1080
        case 'region':
1081
          $style = panels_get_style((!empty($this->display->panel_settings[$pid]['style'])) ? $this->display->panel_settings[$pid]['style'] : '-1');
1082
          break;
1083

    
1084
        case 'pane':
1085
          $pane = &$this->display->content[$pid];
1086
          $style = panels_get_style(!empty($pane->style['style']) ? $pane->style['style'] : 'default');
1087
          break;
1088
      }
1089
    }
1090

    
1091
    // Set up our $conf reference.
1092
    switch ($type) {
1093
      case 'display':
1094
        $conf = &$this->display->panel_settings['style_settings']['default'];
1095
        break;
1096

    
1097
      case 'region':
1098
        $conf = &$this->display->panel_settings['style_settings'][$pid];
1099
        break;
1100

    
1101
      case 'pane':
1102
        ctools_include('content');
1103
        $pane = &$this->display->content[$pid];
1104
        $conf = &$pane->style['settings'];
1105
        break;
1106
    }
1107

    
1108
    // Backward compatibility: Translate old-style stylizer to new style
1109
    // stylizer.
1110
    if ($style['name'] == 'stylizer' && !empty($conf['style']) && $conf['style'] != '$') {
1111
      $style = panels_get_style('stylizer:' . $conf['style']);
1112
    }
1113

    
1114
    return array($style, &$conf);
1115
  }
1116

    
1117
  /**
1118
   * AJAX entry point to configure the style for a display, region or pane.
1119
   *
1120
   * @param string $type
1121
   *   Either display, region or pane
1122
   * @param $pid
1123
   *   The pane id, if a pane. The region id, if a region.
1124
   */
1125
  function ajax_style_settings($type, $pid = '') {
1126
    $info = $this->get_style($type, $pid);
1127
    $style = $info[0];
1128
    $conf = &$info[1];
1129

    
1130
    switch ($type) {
1131
      case 'display':
1132
        $title = t('Style settings for @style (display)', array('@style' => $style['title']));
1133
        break;
1134

    
1135
      case 'region':
1136
        $title = t('Style settings for style @style (Region "!region")', array('@style' => $style['title'], '!region' => $this->plugins['layout']['regions'][$pid]));
1137
        break;
1138

    
1139
      case 'pane':
1140
        ctools_include('content');
1141
        $pane = &$this->display->content[$pid];
1142
        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1143
        $title = t('Style settings for style @style (Pane "!pane")', array('@style' => $style['title'], '!pane' => $subtype['title']));
1144
        break;
1145
    }
1146

    
1147
    $form_state = array(
1148
      'display' => &$this->display,
1149
      'type' => $type,
1150
      'pid' => $pid,
1151
      'conf' => &$conf,
1152
      'style' => $style,
1153
      'ajax' => TRUE,
1154
      'title' => $title,
1155
      'url' => url($this->get_url('style-settings', $type, $pid), array('absolute' => TRUE)),
1156
      'renderer' => &$this,
1157
    );
1158

    
1159
    $output = ctools_modal_form_wrapper('panels_edit_style_settings_form', $form_state);
1160
    if (empty($form_state['executed'])) {
1161
      $this->commands = $output;
1162
      return;
1163
    }
1164

    
1165
    if (isset($this->cache->style)) {
1166
      unset($this->cache->style);
1167
    }
1168

    
1169
    if (!empty($form_state['cancel'])) {
1170
      // The cache must be saved prior to dismissing the modal.
1171
      panels_edit_cache_set($this->cache);
1172
      $this->commands[] = ctools_modal_command_dismiss();
1173
      return;
1174
    }
1175

    
1176
    // Copy settings from form state back into the cache.
1177
    if(!empty($form_state['values']['settings'])) {
1178
      if ($type == 'pane') {
1179
        $this->cache->display->content[$pid]->style['settings'] = $form_state['values']['settings'];
1180
      }
1181
      else if($type == 'region') {
1182
        $this->cache->display->panel_settings['style_settings'][$pid] = $form_state['values']['settings'];
1183
      }
1184
    }
1185

    
1186
    panels_edit_cache_set($this->cache);
1187

    
1188
    $this->commands[] = ctools_modal_command_dismiss();
1189

    
1190
    if ($type == 'pane') {
1191
      $this->command_update_pane($pane);
1192
    }
1193
    else if ($type == 'region') {
1194
      $this->command_update_region_links($pid);
1195
    }
1196
    else {
1197
      $this->command_update_display_links();
1198
    }
1199
  }
1200

    
1201
  /**
1202
   * AJAX entry point to configure CSS for a pane.
1203
   *
1204
   * @param $pid
1205
   *   The pane id to edit.
1206
   */
1207
  function ajax_pane_css($pid = NULL) {
1208
    if (empty($this->display->content[$pid])) {
1209
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1210
    }
1211

    
1212
    $pane = &$this->display->content[$pid];
1213
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1214

    
1215
    $form_state = array(
1216
      'display' => &$this->display,
1217
      'pane' => &$pane,
1218
      'ajax' => TRUE,
1219
      'title' => t('Configure CSS on !subtype_title', array('!subtype_title' => $subtype['title'])),
1220
    );
1221

    
1222
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_css_form', $form_state);
1223
    if (empty($form_state['executed'])) {
1224
      $this->commands = $output;
1225
      return;
1226
    }
1227

    
1228
    panels_edit_cache_set($this->cache);
1229
    $this->command_update_pane($pid);
1230
    $this->commands[] = ctools_modal_command_dismiss();
1231
  }
1232

    
1233
  /**
1234
   * AJAX entry point to configure CSS for a pane.
1235
   *
1236
   * @param $pid
1237
   *   The pane id to edit.
1238
   */
1239
  function ajax_lock($pid = NULL) {
1240
    if (empty($this->display->content[$pid])) {
1241
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1242
    }
1243

    
1244
    $pane = &$this->display->content[$pid];
1245
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1246

    
1247
    $form_state = array(
1248
      'display' => &$this->display,
1249
      'pane' => &$pane,
1250
      'ajax' => TRUE,
1251
      'title' => t('Configure lock on !subtype_title', array('!subtype_title' => $subtype['title'])),
1252
    );
1253

    
1254
    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_lock_form', $form_state);
1255
    if (empty($form_state['executed'])) {
1256
      $this->commands = $output;
1257
      return;
1258
    }
1259

    
1260
    panels_edit_cache_set($this->cache);
1261
    $this->command_update_pane($pid);
1262
    $this->commands[] = ctools_modal_command_dismiss();
1263
  }
1264

    
1265
  /**
1266
   * AJAX entry point to configure access settings for a pane.
1267
   *
1268
   * @param $pid
1269
   *   The pane id to edit.
1270
   */
1271
  function ajax_access_settings($pid = NULL) {
1272
    if (empty($this->display->content[$pid])) {
1273
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1274
    }
1275

    
1276
    $pane = &$this->display->content[$pid];
1277
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1278

    
1279
    $form_state = array(
1280
      'display' => &$this->display,
1281
      'pane' => &$pane,
1282
      'ajax' => TRUE,
1283
      'title' => t('Access settings on !subtype_title', array('!subtype_title' => $subtype['title'])),
1284
    );
1285

    
1286
    $output = ctools_modal_form_wrapper('panels_edit_configure_access_settings_form', $form_state);
1287
    if (empty($form_state['executed'])) {
1288
      $this->commands = $output;
1289
      return;
1290
    }
1291

    
1292
    panels_edit_cache_set($this->cache);
1293
    $this->command_update_pane($pid);
1294
    $this->commands[] = ctools_modal_command_dismiss();
1295
  }
1296

    
1297
  /**
1298
   * AJAX entry point for to add a visibility rule.
1299
   */
1300
  function ajax_access_add_test($pid = NULL) {
1301
    if (empty($this->display->content[$pid])) {
1302
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1303
    }
1304

    
1305
    $pane = &$this->display->content[$pid];
1306
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1307

    
1308
    $form_state = array(
1309
      'display' => &$this->display,
1310
      'pane' => &$pane,
1311
      'ajax' => TRUE,
1312
      'title' => t('Add visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1313
    );
1314

    
1315
    $output = ctools_modal_form_wrapper('panels_edit_add_access_test_form', $form_state);
1316
    if (!empty($form_state['executed'])) {
1317
      // Set up the plugin in cache
1318
      $plugin = ctools_get_access_plugin($form_state['values']['type']);
1319
      $this->cache->new_plugin = ctools_access_new_test($plugin);
1320
      panels_edit_cache_set($this->cache);
1321

    
1322
      // go to the next step.
1323
      return $this->ajax_access_configure_test($pid, 'add');
1324
    }
1325

    
1326
    $this->commands = $output;
1327
  }
1328

    
1329
  /**
1330
   * AJAX entry point for to configure vsibility rule.
1331
   */
1332
  function ajax_access_configure_test($pid = NULL, $id = NULL) {
1333
    if (empty($this->display->content[$pid])) {
1334
      ctools_modal_render(t('Error'), t('Invalid pane id.'));
1335
    }
1336

    
1337
    $pane = &$this->display->content[$pid];
1338
    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);
1339

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

    
1343
    // If we're adding a new one, get the stored data from cache and
1344
    // add it. It's stored as a cache so that if this is closed
1345
    // we don't accidentally add an unconfigured plugin.
1346
    if ($id == 'add') {
1347
      $pane->access['plugins'][] = $this->cache->new_plugin;
1348
      $id = max(array_keys($pane->access['plugins']));
1349
    }
1350
    else if (empty($pane->access['plugins'][$id])) {
1351
      ctools_modal_render(t('Error'), t('Invalid test id.'));
1352
    }
1353

    
1354
    $form_state = array(
1355
      'display' => &$this->display,
1356
      'pane' => &$pane,
1357
      'ajax' => TRUE,
1358
      'title' => t('Configure visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),
1359
      'test' => &$pane->access['plugins'][$id],
1360
      'plugin' => ctools_get_access_plugin($pane->access['plugins'][$id]['name']),
1361
      'url' => url($url, array('absolute' => TRUE)),
1362
    );
1363

    
1364
    $output = ctools_modal_form_wrapper('panels_edit_configure_access_test_form', $form_state);
1365
    if (empty($form_state['executed'])) {
1366
      $this->commands = $output;
1367
      return;
1368
    }
1369

    
1370
    // Unset the new plugin
1371
    if (isset($this->cache->new_plugin)) {
1372
      unset($this->cache->new_plugin);
1373
    }
1374

    
1375
    if (!empty($form_state['remove'])) {
1376
      unset($pane->access['plugins'][$id]);
1377
    }
1378

    
1379
    panels_edit_cache_set($this->cache);
1380
    $this->command_update_pane($pid);
1381
    $this->commands[] = ctools_modal_command_dismiss();
1382
  }
1383

    
1384
  /**
1385
   * AJAX Router function for layout owned AJAX calls.
1386
   *
1387
   * Layouts like the flexible layout builder need callbacks of their own.
1388
   * This allows those layouts to simply declare their callbacks and use
1389
   * them with $this->get_url('layout', $command).
1390
   */
1391
  function ajax_layout() {
1392
    $args = func_get_args();
1393
    if (empty($args)) {
1394
      return MENU_NOT_FOUND;
1395
    }
1396

    
1397
    $command = array_shift($args);
1398
    if (empty($this->plugins['layout']['ajax'][$command]) || !function_exists($this->plugins['layout']['ajax'][$command])) {
1399
      return MENU_NOT_FOUND;
1400
    }
1401

    
1402
    // Make sure the this is always available to the called functions.
1403
    array_unshift($args, $this);
1404
    return call_user_func_array($this->plugins['layout']['ajax'][$command], $args);
1405
  }
1406

    
1407
  /**
1408
   * AJAX Router function for style owned AJAX calls.
1409
   *
1410
   * Styles like the stylizer need AJAX callbacks of their own. This
1411
   * allows the system to figure out which style is being referenced,
1412
   * load it, and execute the callback.
1413
   *
1414
   * This allows those layouts to simply declare their callbacks and use
1415
   * them using $this->get_url('style', $command, $type, $pid).
1416
   */
1417
  function ajax_style() {
1418
    $args = func_get_args();
1419
    if (count($args) < 3) {
1420
      return MENU_NOT_FOUND;
1421
    }
1422

    
1423
    $command = array_shift($args);
1424
    $type = array_shift($args);
1425
    $pid = array_shift($args);
1426

    
1427
    $info = $this->get_style($type, $pid);
1428

    
1429
    $style = $info[0];
1430
    $conf = &$info[1];
1431

    
1432
    if (empty($style['ajax'][$command]) || !function_exists($style['ajax'][$command])) {
1433
      return MENU_NOT_FOUND;
1434
    }
1435

    
1436
    // Make sure the this is always available to the called functions.
1437
    $args = array_merge(array(&$this, $style, &$conf, $type, $pid), $args);
1438
    return call_user_func_array($style['ajax'][$command], $args);
1439
  }
1440

    
1441
  // ------------------------------------------------------------------------
1442
  // AJAX command generators
1443
  //
1444
  // These are used to make sure that child implementations can control their
1445
  // own AJAX commands as needed.
1446

    
1447
  /**
1448
   * Create a command array to redraw a pane.
1449
   */
1450
  function command_update_pane($pid) {
1451
    if (is_object($pid)) {
1452
      $pane = $pid;
1453
    }
1454
    else {
1455
      $pane = $this->display->content[$pid];
1456
    }
1457

    
1458
    $this->commands[] = ajax_command_replace("#panel-pane-$pane->pid", $this->render_pane($pane));
1459
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title span.text");
1460
  }
1461

    
1462
  /**
1463
   * Create a command array to add a new pane.
1464
   */
1465
  function command_add_pane($pid) {
1466
    if (is_object($pid)) {
1467
      $pane = $pid;
1468
    }
1469
    else {
1470
      $pane = $this->display->content[$pid];
1471
    }
1472

    
1473
    $this->commands[] = ajax_command_append("#panel-region-$pane->panel", $this->render_pane($pane));
1474
    $this->commands[] = ajax_command_changed("#panel-pane-$pane->pid", "div.grab-title span.text");
1475
  }
1476

    
1477
  /**
1478
   * Create a command to update the links on a display after a change was made.
1479
   */
1480
  function command_update_display_links() {
1481
    $this->commands[] = ajax_command_replace('.panels-display-links', $this->get_display_links());
1482
  }
1483

    
1484
  /**
1485
   * Create a command to update the links on a region after a change was made.
1486
   */
1487
  function command_update_region_links($id) {
1488
    $this->commands[] = ajax_command_replace('.panels-region-links-' . $id, $this->get_region_links($id));
1489
  }
1490
}
1491

    
1492
/**
1493
 * Handle the 'next' click on the add/edit pane form wizard.
1494
 *
1495
 * All we need to do is store the updated pane in the cache.
1496
 */
1497
function panels_ajax_edit_pane_next(&$form_state) {
1498
  $form_state['display cache']->new_pane = $form_state['pane'];
1499
  panels_edit_cache_set($form_state['display cache']);
1500
}
1501

    
1502
/**
1503
 * Handle the 'finish' click on teh add/edit pane form wizard.
1504
 *
1505
 * All we need to do is set a flag so the return can handle adding
1506
 * the pane.
1507
 */
1508
function panels_ajax_edit_pane_finish(&$form_state) {
1509
  $form_state['complete'] = TRUE;
1510
  return;
1511
}
1512

    
1513
/**
1514
 * Handle the 'cancel' click on the add/edit pane form wizard.
1515
 */
1516
function panels_ajax_edit_pane_cancel(&$form_state) {
1517
  $form_state['cancel'] = TRUE;
1518
  return;
1519
}
1520

    
1521
// --------------------------------------------------------------------------
1522
// Forms for the editor object
1523

    
1524
/**
1525
 * Choose cache method form
1526
 */
1527
function panels_edit_cache_method_form($form, &$form_state) {
1528
  ctools_form_include($form_state, 'plugins', 'panels');
1529
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1530
  $display = &$form_state['display'];
1531
  $conf = &$form_state['conf'];
1532

    
1533
  // Set to 0 to ensure we get a selected radio.
1534
  if (!isset($conf['method'])) {
1535
    $conf['method'] = 0;
1536
  }
1537

    
1538
  $caches = panels_get_caches();
1539
  if (empty($caches)) {
1540
    $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.'));
1541
    return $form;
1542
  }
1543

    
1544
  $options[0] = t('No caching');
1545
  foreach ($caches as $cache => $info) {
1546
    $options[$cache] = check_plain($info['title']);
1547
  }
1548

    
1549
  $form['method'] = array(
1550
    '#prefix' => '<div class="no-float">',
1551
    '#suffix' => '</div>',
1552
    '#type' => 'radios',
1553
    '#title' => t('Method'),
1554
    '#options' => $options,
1555
    '#default_value' => $conf['method'],
1556
  );
1557

    
1558
  $form['submit'] = array(
1559
    '#type' => 'submit',
1560
    '#value' => t('Next'),
1561
  );
1562
  return $form;
1563
}
1564

    
1565
/**
1566
 * Submit callback for panels_edit_cache_method_form.
1567
 *
1568
 * All this needs to do is return the method.
1569
 */
1570
function panels_edit_cache_method_form_submit($form, &$form_state) {
1571
  $form_state['method'] = $form_state['values']['method'];
1572
}
1573

    
1574
/**
1575
 * Cache settings form
1576
 */
1577
function panels_edit_cache_settings_form($form, &$form_state) {
1578
  ctools_form_include($form_state, 'plugins', 'panels');
1579
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1580
  $display = &$form_state['display'];
1581
  $conf = &$form_state['conf'];
1582
  $pid = $form_state['pid'];
1583
  $info = panels_get_cache($conf['method']);
1584

    
1585
  $form['#action'] = $form_state['url'];
1586

    
1587
  $form['description'] = array(
1588
    '#prefix' => '<div class="description">',
1589
    '#suffix' => '</div>',
1590
    '#value' => check_plain($info['description']),
1591
  );
1592

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

    
1595
  $form['settings'] = $function($conf['settings'], $display, $pid);
1596
  $form['settings']['#tree'] = TRUE;
1597

    
1598
  $form['display'] = array(
1599
    '#type' => 'value',
1600
    '#value' => $display,
1601
  );
1602

    
1603
  $form['pid'] = array(
1604
    '#type' => 'value',
1605
    '#value' => $pid,
1606
  );
1607

    
1608
  $form['submit'] = array(
1609
    '#type' => 'submit',
1610
    '#value' => t('Save'),
1611
  );
1612

    
1613
  return $form;
1614
}
1615

    
1616
/**
1617
 * Validate cache settings.
1618
 */
1619
function panels_edit_cache_settings_form_validate($form, &$form_state) {
1620
  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form validate')) {
1621
    $function($form, $form_state['values']['settings']);
1622
  }
1623
}
1624

    
1625
/**
1626
 * Allows panel styles to validate their style settings.
1627
 */
1628
function panels_edit_cache_settings_form_submit($form, &$form_state) {
1629
  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form submit')) {
1630
    $function($form_state['values']['settings']);
1631
  }
1632

    
1633
  $form_state['conf']['settings'] = $form_state['values']['settings'];
1634
}
1635

    
1636
/**
1637
 * Choose style form
1638
 */
1639
function panels_edit_style_type_form($form, &$form_state) {
1640
  ctools_form_include($form_state, 'plugins', 'panels');
1641
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1642
  $display = &$form_state['display'];
1643
  $style = $form_state['style'];
1644
  $type = $form_state['type'];
1645

    
1646
  $styles = panels_get_styles();
1647

    
1648
  $function = ($type == 'pane' ? 'render pane' : 'render region');
1649
  $options = array();
1650
  if ($type == 'region') {
1651
    $options[-1] = t('Use display default style');
1652
  }
1653

    
1654
  uasort($styles, 'ctools_plugin_sort');
1655

    
1656
  foreach ($styles as $id => $info) {
1657
    if (empty($info['hidden']) && (!empty($info[$function]) || $id == 'default')) {
1658
      $options[$id] = check_plain($info['title']);
1659
    }
1660
  }
1661

    
1662
  $form['style'] = array(
1663
    '#prefix' => '<div class="no-float">',
1664
    '#suffix' => '</div>',
1665
    '#type' => 'radios',
1666
    '#title' => t('Style'),
1667
    '#options' => $options,
1668
    '#default_value' => $style,
1669
  );
1670

    
1671
  $form['submit'] = array(
1672
    '#type' => 'submit',
1673
    '#value' => t('Next'),
1674
  );
1675
  return $form;
1676
}
1677

    
1678
/**
1679
 * Submit callback for panels_edit_style_type_form.
1680
 *
1681
 * All this needs to do is return the method.
1682
 */
1683
function panels_edit_style_type_form_submit($form, &$form_state) {
1684
  $form_state['old_style'] = $form_state['style'];
1685
  $form_state['style'] = $form_state['values']['style'];
1686
}
1687

    
1688
/**
1689
 * Style settings form
1690
 */
1691
function panels_edit_style_settings_form($form, &$form_state) {
1692
  ctools_form_include($form_state, 'plugins', 'panels');
1693
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1694
  $display = &$form_state['display'];
1695
  $conf = &$form_state['conf'];
1696
  $pid = $form_state['pid'];
1697
  $style = $form_state['style'];
1698
  $type = $form_state['type'];
1699

    
1700
  $form['#action'] = $form_state['url'];
1701

    
1702
  $form['description'] = array(
1703
    '#prefix' => '<div class="description">',
1704
    '#suffix' => '</div>',
1705
    '#value' => check_plain($style['description']),
1706
  );
1707

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

    
1710
  $form['settings'] = $function($conf, $display, $pid, $type, $form_state);
1711
  $form['settings']['#tree'] = TRUE;
1712

    
1713
  $form['submit'] = array(
1714
    '#type' => 'submit',
1715
    '#value' => t('Save'),
1716
  );
1717

    
1718

    
1719
  // Need a cancel button since the style cache can persist and impact the wrong
1720
  // pane (or region, or display).
1721
  $form['cancel_style'] = array(
1722
    '#type' => 'submit',
1723
    '#value' => t('Cancel'),
1724
    '#submit' => array('panels_edit_style_settings_form_cancel'),
1725
  );
1726

    
1727
  return $form;
1728
}
1729

    
1730
/**
1731
 * Cancel style settings form.
1732
 *
1733
 * Clears the editing cache to prevent styles being applied to incorrect regions
1734
 * or panes.
1735
 */
1736
function panels_edit_style_settings_form_cancel($form, &$form_state) {
1737
  $form_state['cancel'] = TRUE;
1738
}
1739

    
1740
/**
1741
 * Validate style settings.
1742
 */
1743
function panels_edit_style_settings_form_validate($form, &$form_state) {
1744
  $name = $form_state['type'] == 'pane' ? 'pane settings form validate' : 'settings form validate';
1745
  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1746
    $function($form, $form_state['values']['settings'], $form_state);
1747
  }
1748
}
1749

    
1750
/**
1751
 * Allows panel styles to validate their style settings.
1752
 */
1753
function panels_edit_style_settings_form_submit($form, &$form_state) {
1754
  $name = $form_state['type'] == 'pane' ? 'pane settings form submit' : 'settings form submit';
1755
  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {
1756
    $function($form, $form_state['values']['settings'], $form_state);
1757
  }
1758

    
1759
  $form_state['conf'] = $form_state['values']['settings'];
1760
}
1761

    
1762

    
1763
/**
1764
 * Configure CSS on a pane form.
1765
 */
1766
function panels_edit_configure_pane_css_form($form, &$form_state) {
1767
  ctools_form_include($form_state, 'plugins', 'panels');
1768
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1769
  $display = &$form_state['display'];
1770
  $pane = &$form_state['pane'];
1771

    
1772
  $form['css_id'] = array(
1773
    '#type' => 'textfield',
1774
    '#default_value' => isset($pane->css['css_id']) ? $pane->css['css_id'] : '',
1775
    '#title' => t('CSS ID'),
1776
    '#description' => t('CSS ID to apply to this pane. This may be blank.'),
1777
  );
1778
  $form['css_class'] = array(
1779
    '#type' => 'textfield',
1780
    '#default_value' => isset($pane->css['css_class']) ? $pane->css['css_class'] : '',
1781
    '#title' => t('CSS class'),
1782
    '#description' => t('CSS class to apply to this pane. This may be blank.'),
1783
  );
1784

    
1785
  $form['next'] = array(
1786
    '#type' => 'submit',
1787
    '#value' => t('Save'),
1788
  );
1789

    
1790
  return $form;
1791
}
1792

    
1793
/**
1794
 * FAPI submission function for the CSS configure form.
1795
 *
1796
 * All this does is set up $pane properly. The caller is responsible for
1797
 * actually storing this somewhere.
1798
 */
1799
function panels_edit_configure_pane_css_form_submit($form, &$form_state) {
1800
  $pane = &$form_state['pane'];
1801
  $display = $form_state['display'];
1802

    
1803
  $pane->css['css_id'] = $form_state['values']['css_id'];
1804
  $pane->css['css_class'] = $form_state['values']['css_class'];
1805
}
1806

    
1807
/**
1808
 * Configure lock on a pane form.
1809
 */
1810
function panels_edit_configure_pane_lock_form($form, &$form_state) {
1811
  ctools_form_include($form_state, 'plugins', 'panels');
1812
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1813
  $display = &$form_state['display'];
1814
  $pane = &$form_state['pane'];
1815

    
1816
  if (empty($pane->locks)) {
1817
    $pane->locks = array('type' => 'none', 'regions' => array());
1818
  }
1819

    
1820
  $form['type'] = array(
1821
    '#type' => 'radios',
1822
    '#title' => t('Lock type'),
1823
    '#options' => array(
1824
      'none' => t('No lock'),
1825
      'immovable' => t('Immovable'),
1826
      'regions' => t('Regions'),
1827
    ),
1828
    '#default_value' => $pane->locks['type'],
1829
  );
1830

    
1831
  $layout = panels_get_layout($display->layout);
1832
  $regions = panels_get_regions($layout, $display);
1833

    
1834
  $form['regions'] = array(
1835
    '#type' => 'checkboxes',
1836
    '#title' => t('Regions'),
1837
    '#options' => $regions,
1838
    '#description' => t('Select which regions this pane can be moved to.'),
1839
    '#dependency' => array(
1840
      'radio:type' => array('regions'),
1841
    ),
1842
    '#default_value' => $pane->locks['regions'],
1843
  );
1844

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

    
1851
  return $form;
1852
}
1853

    
1854
function panels_edit_configure_pane_lock_form_after_build($element, $form_state) {
1855
  $region = $form_state['pane']->panel;
1856
  $element['regions'][$region]['#required'] = TRUE;
1857
  $element['regions'][$region]['#disabled'] = TRUE;
1858
  $element['regions'][$region]['#value'] = TRUE;
1859
  $element['regions'][$region]['#checked'] = TRUE;
1860
  $element['regions'][$region]['#attributes']['disabled'] = TRUE;
1861
  return $element;
1862
}
1863

    
1864
/**
1865
 * FAPI submission function for the lock configure form.
1866
 *
1867
 * All this does is set up $pane properly. The caller is responsible for
1868
 * actually storing this somewhere.
1869
 */
1870
function panels_edit_configure_pane_lock_form_submit($form, &$form_state) {
1871
  $pane = &$form_state['pane'];
1872
  $display = $form_state['display'];
1873

    
1874
  // We set this to true but forms do not submit disabled checkboxes
1875
  // and fapi is ignoring the #value directive probably because it
1876
  // is checkboxes:
1877
  $region = $form_state['pane']->panel;
1878
  $form_state['values']['regions'][$region] = $region;
1879

    
1880
  $pane->locks['type'] = $form_state['values']['type'];
1881
  $pane->locks['regions'] = array_filter($form_state['values']['regions']);
1882
}
1883

    
1884
/**
1885
 * Form to control basic visibility settings.
1886
 */
1887
function panels_edit_configure_access_settings_form($form, &$form_state) {
1888
  ctools_form_include($form_state, 'plugins', 'panels');
1889
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1890
  $display = &$form_state['display'];
1891
  $pane = &$form_state['pane'];
1892

    
1893
  $form['logic'] = array(
1894
    '#type' => 'radios',
1895
    '#options' => array(
1896
      'and' => t('All criteria must pass.'),
1897
      'or' => t('Only one criterion must pass.'),
1898
    ),
1899
    '#default_value' => isset($pane->access['logic']) ? $pane->access['logic'] : 'and',
1900
  );
1901

    
1902
  $form['next'] = array(
1903
    '#type' => 'submit',
1904
    '#value' => t('Save'),
1905
  );
1906

    
1907
  return $form;
1908
}
1909

    
1910
/**
1911
 * FAPI submission function for the edit access settings form.
1912
 *
1913
 * All this does is set up $pane properly. The caller is responsible for
1914
 * actually storing this somewhere.
1915
 */
1916
function panels_edit_configure_access_settings_form_submit($form, &$form_state) {
1917
  $pane = &$form_state['pane'];
1918
  $display = $form_state['display'];
1919

    
1920
  $pane->access['logic'] = $form_state['values']['logic'];
1921
}
1922

    
1923
/**
1924
 * Form to add a visibility rule.
1925
 */
1926
function panels_edit_add_access_test_form($form, &$form_state) {
1927
  ctools_form_include($form_state, 'plugins', 'panels');
1928
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1929
  $display = &$form_state['display'];
1930
  $pane = &$form_state['pane'];
1931

    
1932
  $plugins = ctools_get_relevant_access_plugins($display->context);
1933
  $options = array();
1934
  foreach ($plugins as $id => $plugin) {
1935
    $options[$id] = $plugin['title'];
1936
  }
1937

    
1938
  asort($options);
1939

    
1940
  $form['type'] = array(
1941
    // This ensures that the form item is added to the URL.
1942
    '#type' => 'radios',
1943
    '#options' => $options,
1944
  );
1945

    
1946
  $form['next'] = array(
1947
    '#type' => 'submit',
1948
    '#value' => t('Next'),
1949
  );
1950

    
1951
  return $form;
1952
}
1953

    
1954
/**
1955
 * Form to configure a visibility rule.
1956
 */
1957
function panels_edit_configure_access_test_form($form, &$form_state) {
1958
  ctools_form_include($form_state, 'plugins', 'panels');
1959
  form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
1960
  $display = &$form_state['display'];
1961
  $test = &$form_state['test'];
1962
  $plugin = &$form_state['plugin'];
1963

    
1964
  $form['#action'] = $form_state['url'];
1965

    
1966
  $contexts = $display->context;
1967
  if (!isset($contexts['logged-in-user'])) {
1968
    $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1969
  }
1970

    
1971
  if (isset($plugin['required context'])) {
1972
    $form['context'] = ctools_context_selector($contexts, $plugin['required context'], $test['context']);
1973
  }
1974

    
1975
  $form['settings'] = array('#tree' => TRUE);
1976
  if ($function = ctools_plugin_get_function($plugin, 'settings form')) {
1977
    $form = $function($form, $form_state, $test['settings']);
1978
  }
1979

    
1980
  $form['not'] = array(
1981
    '#type' => 'checkbox',
1982
    '#title' => t('Reverse (NOT)'),
1983
    '#default_value' => !empty($test['not']),
1984
  );
1985

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

    
1991
  $form['remove'] = array(
1992
    '#type' => 'submit',
1993
    '#value' => t('Remove'),
1994
    '#remove' => TRUE,
1995
  );
1996

    
1997
  return $form;
1998
}
1999

    
2000
/**
2001
 * Validate handler for visibility rule settings
2002
 */
2003
function panels_edit_configure_access_test_form_validate(&$form, &$form_state) {
2004
  if (!empty($form_state['clicked_button']['#remove'])) {
2005
    return;
2006
  }
2007

    
2008
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
2009
    $function($form, $form_state);
2010
  }
2011
}
2012

    
2013
/**
2014
 * Submit handler for visibility rule settings
2015
 */
2016
function panels_edit_configure_access_test_form_submit(&$form, &$form_state) {
2017
  if (!empty($form_state['clicked_button']['#remove'])) {
2018
    $form_state['remove'] = TRUE;
2019
    return;
2020
  }
2021

    
2022
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
2023
    $function($form, $form_state);
2024
  }
2025

    
2026
  $form_state['test']['settings'] = $form_state['values']['settings'];
2027
  if (isset($form_state['values']['context'])) {
2028
    $form_state['test']['context'] = $form_state['values']['context'];
2029
  }
2030
  $form_state['test']['not'] = !empty($form_state['values']['not']);
2031
}
2032