Projet

Général

Profil

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

root / drupal7 / sites / all / modules / panels / plugins / task_handlers / panel_context.inc @ 64156087

1
<?php
2

    
3
/**
4
 * @file
5
 * This is the task handler plugin to handle attaching a panel to any
6
 * task that advertises itself as a 'context' type, which all of the
7
 * basic page tasks provided by page_manager.module do by default.
8
 */
9

    
10
// Plugin definition.
11
$plugin = array(
12
  // Is a 'context' handler type, meaning it supports the API of the
13
  // context handlers provided by ctools context plugins.
14
  'handler type' => 'context',
15
  'visible' => TRUE, // may be added up front.
16

    
17
  // Administrative fields.
18
  'title' => t('Panel'),
19
  'admin summary' => 'panels_panel_context_admin_summary',
20
  'admin title' => 'panels_panel_context_title',
21
  'operations' => array(
22
    'settings' => array(
23
      'title' => t('General'),
24
      'description' => t('Change general settings about this variant.'),
25
      'form' => 'panels_panel_context_edit_settings',
26
    ),
27
    'criteria' => array(
28
      'title' => t('Selection rules'),
29
      'description' => t('Control the criteria used to decide whether or not this variant is used.'),
30
      'ajax' => FALSE,
31
      'form' => array(
32
        'order' => array(
33
          'form' => t('Selection rules'),
34
        ),
35
        'forms' => array(
36
          'form' => array(
37
            'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
38
            'form id' => 'ctools_context_handler_edit_criteria',
39
          ),
40
        ),
41
      ),
42
    ),
43
    'context' => array(
44
      'title' => t('Contexts'),
45
      'ajax' => FALSE,
46
      'description' => t('Add additional context objects to this variant that can be used by the content.'),
47
      'form' => array(
48
        'order' => array(
49
          'form' => t('Context'),
50
        ),
51
        'forms' => array(
52
          'form' => array(
53
            'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
54
            'form id' => 'ctools_context_handler_edit_context',
55
          ),
56
        ),
57
      ),
58
    ),
59
    'layout' => array(
60
      'title' => t('Layout'),
61
      'description' => t('Change the layout of this panel.'),
62
      // No AJAX so we get our CSS loaded.
63
      'ajax' => FALSE,
64
      'form' => array(
65
        'order' => array(
66
          'choose' => t('Change layout'),
67
          'move' => t('Move content from old layout'),
68
        ),
69
        'forms' => array(
70
          'choose' => array(
71
            'form id' => 'panels_panel_context_edit_layout',
72
          ),
73
          'move' => array(
74
            'include' => array(
75
              drupal_get_path('module', 'panels') . '/includes/display-layout.inc',
76
            ),
77
            'form id' => 'panels_panel_context_edit_move',
78
            'submit' => 'panels_change_layout_submit',
79
          ),
80
        ),
81
      ),
82
    ),
83
    'content' => array(
84
      'title' => t('Content'),
85
      'description' => t('Add content items and change their location with a drag and drop interface.'),
86
      'ajax' => FALSE,
87
      'form' => array(
88
        'order' => array(
89
          'form' => t('Content'),
90
        ),
91
        'forms' => array(
92
          'form' => array(
93
            'include' => array(
94
              drupal_get_path('module', 'panels') . '/includes/display-edit.inc',
95
            ),
96
            'form id' => 'panels_panel_context_edit_content',
97
            'no blocks' => TRUE,
98
          ),
99
        ),
100
      ),
101
    ),
102
    'preview' => array(
103
      'title' => t('Preview'),
104
      'description' => t('Get a preview of what this variant will look like.'),
105
      'form' => 'panels_panel_context_edit_preview',
106
      'ajax' => FALSE,
107
      'silent' => TRUE,
108
      'form info' => array('finish text' => t('Preview')),
109
      'no update and save' => TRUE,
110
    ),
111
  ),
112

    
113
  'tab operation' => 'panels_panel_context_tab_operation',
114

    
115
  // Callback to render the data.
116
  'render' => 'panels_panel_context_render',
117
  // Callback to return addressable data.
118
  'addressable callback' => 'panels_panel_context_get_addressable',
119

    
120
  // Various callbacks for operations performed on the handler to ensure
121
  // related data is updated properly.
122
  'save' => 'panels_panel_context_save',
123
  'delete' => 'panels_panel_context_delete',
124
  'export' => 'panels_panel_context_export',
125
  'clone' => 'panels_panel_context_clone',
126

    
127
  'add features' => array(
128
    'criteria' => t('Selection rules'),
129
    'context' => t('Contexts'),
130
  ),
131
  // Where to go when finished.
132
  'add finish' => 'content',
133

    
134
  'required forms' => array(
135
    'choose' => t('Choose layout'),
136
    'settings' => t('Panel settings'),
137
    'content' => t('Panel content'),
138
  ),
139

    
140
  'edit forms' => array(
141
    'content' => t('Panel content'),
142
    'criteria' => t('Selection rules'),
143
    'settings' => t('General'),
144
    'context' => t('Contexts'),
145
    'layout' => t('Change layout'),
146
    'move' => '', // no title makes it a 'hidden' edit form.
147
  ),
148
  'forms' => array(
149
    'settings' => array(
150
      'form id' => 'panels_panel_context_edit_settings',
151
    ),
152
    'choose' => array(
153
      'form id' => 'panels_panel_context_edit_choose',
154
      'no back validate' => TRUE,
155
    ),
156
    'layout' => array(
157
      'no return' => TRUE,
158
      'form id' => 'panels_panel_context_edit_layout',
159
    ),
160
    'move' => array(
161
      'include' => array(
162
        drupal_get_path('module', 'panels') . '/includes/display-layout.inc',
163
      ),
164
      'form id' => 'panels_panel_context_edit_move',
165
      'submit' => 'panels_change_layout_submit',
166
    ),
167
    'content' => array(
168
      'include' => array(
169
        drupal_get_path('module', 'panels') . '/includes/display-edit.inc',
170
      ),
171
      'form id' => 'panels_panel_context_edit_content',
172
      'no blocks' => TRUE,
173
    ),
174
    'context' => array(
175
      'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
176
      'form id' => 'ctools_context_handler_edit_context',
177
    ),
178
    'criteria' => array(
179
      'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
180
      'form id' => 'ctools_context_handler_edit_criteria',
181
    ),
182
  ),
183
  'default conf' => array(
184
    'title' => t('Panel'),
185
    'no_blocks' => FALSE,
186
    'pipeline' => variable_get('panels_renderer_default', 'standard'),
187
    'body_classes_to_remove' => '',
188
    'body_classes_to_add' => '',
189
    'css_id' => '',
190
    'css' => '',
191
    'contexts' => array(),
192
    'relationships' => array(),
193
  ),
194
);
195

    
196
/**
197
 * Provide the operation trail for the 'Edit panel' link.
198
 *
199
 * When editing the panel, go directly to the content tab.
200
 */
201
function panels_panel_context_tab_operation($handler, $contexts, $args) {
202
  return array('handlers', $handler->name, 'content');
203
}
204

    
205
/**
206
 * Get the display for a task handler.
207
 *
208
 * There are three methods that the display can be found.
209
 * - In the database. $handler->conf['did'] will be set in this case,
210
 *   and $handler->conf['display'] won't be.
211
 * - In $handler->conf['display'], with $handler->conf['did'] empty. This
212
 *   will be true for a default/imported task handler as well as a handler
213
 *   that has just been created but has not yet been saved.
214
 * - in $handler->conf['display'] with $handler->conf['did' populated. This
215
 *   simply means that the display has been modified and is awaiting
216
 *   save. The modified one should always be used for editing purposes.
217
 * - If none of the above is true, then a new display needs to be created
218
 *   for the handler and pla.
219
 */
220
function &panels_panel_context_get_display(&$handler) {
221
  if (!isset($handler->conf['display'])) {
222
    if (isset($handler->conf['did'])) {
223
      $handler->conf['display'] = panels_load_display($handler->conf['did']);
224
    }
225

    
226
    // Check for again for a valid display. If no valid display could be loaded,
227
    // something is wrong and we'll create a new one.
228
    if (empty($handler->conf['display'])) {
229
      $handler->conf['display'] = panels_new_display();
230
    }
231
  }
232

    
233
  $display =& $handler->conf['display'];
234
  $display->storage_type = 'page_manager';
235
  $display->storage_id = !empty($handler->name) ? $handler->name : 'new';
236

    
237
  return $display;
238
}
239

    
240
/**
241
 * Build the cache key so that the editor and IPE can properly find
242
 * everything needed for this display.
243
 */
244
function panels_panel_context_cache_key($task_name, $handler_id, $args) {
245
  $arguments = array();
246
  foreach ($args as $arg) {
247
    // Sadly things like panels everywhere actually use non-string arguments
248
    // and they basically can't be represented here. Luckily, PE also does
249
    // not use a system where this matters, so replace its args with a 0
250
    // for a placeholder.
251
    if (is_string($arg)) {
252
      $arguments[] = $arg;
253
    }
254
    else {
255
      $arguments[] = '0';
256
    }
257
  }
258
  $cache_key = 'panel_context:' . $task_name . '::' . $handler_id . '::' . implode('\\', $arguments) . '::';
259
  return $cache_key;
260
}
261

    
262
/**
263
 * Check selection rules and, if passed, render the contexts.
264
 */
265
function panels_panel_context_render($handler, $base_contexts, $args, $test = TRUE) {
266
  // Go through arguments and see if they match.
267
  ctools_include('context');
268
  ctools_include('context-task-handler');
269
  ctools_include('plugins', 'panels');
270

    
271
  // Add my contexts.
272
  $contexts = ctools_context_handler_get_handler_contexts($base_contexts, $handler);
273

    
274
  // Test.
275
  if ($test && !ctools_context_handler_select($handler, $contexts)) {
276
    return;
277
  }
278

    
279
  if (isset($handler->handler)) {
280
    ctools_context_handler_pre_render($handler, $contexts, $args);
281
  }
282

    
283
  // Load the display.
284
  $display = panels_panel_context_get_display($handler);
285

    
286
  $display->context = $contexts;
287
  $display->args = $args;
288
  $page_css_id = ctools_context_keyword_substitute($handler->conf['css_id'], array(), $contexts);
289
  $display->css_id = check_plain($page_css_id);
290
  $task_name = page_manager_make_task_name($handler->task, $handler->subtask);
291

    
292
  $display->cache_key = panels_panel_context_cache_key($task_name, $handler->name, $args);
293

    
294
  // Check to see if there is any CSS.
295
  if (!empty($handler->conf['css'])) {
296
    ctools_include('css');
297
    $css_id = 'panel_context:' . $handler->name;
298
    $filename = ctools_css_retrieve($css_id);
299
    if (!$filename) {
300
      // Add keywords from context.
301
      $css = ctools_context_keyword_substitute($handler->conf['css'], array(), $contexts, array('css safe' => TRUE));
302
      $filename = ctools_css_store($css_id, $css);
303
    }
304
    drupal_add_css($filename);
305
  }
306

    
307
  // With an argument, this actually sets the display.
308
  panels_get_current_page_display($display);
309

    
310
  $renderer = panels_get_renderer($handler->conf['pipeline'], $display);
311
  // If the IPE is enabled, but the user does not have access to edit
312
  // load the standard renderer instead.
313
  $parents = class_parents($renderer);
314
  if (!empty($parents['panels_renderer_editor']) && !user_access('user page manager') && !user_access('use ipe with page manager')) {
315
    $renderer = panels_get_renderer_handler('standard', $display);
316
  }
317

    
318
  // Remove and add body element classes.
319
  $panel_body_css = &drupal_static('panel_body_css');
320

    
321
  if (isset($handler->conf['body_classes_to_remove'])) {
322
    $classes = ctools_context_keyword_substitute($handler->conf['body_classes_to_remove'], array(), $contexts, array('css safe' => TRUE));
323
    if (!isset($panel_body_css['body_classes_to_remove'])) {
324
      $panel_body_css['body_classes_to_remove'] = check_plain($classes);
325
    }
326
    else {
327
      $panel_body_css['body_classes_to_remove'] .= ' ' . check_plain($classes);
328
    }
329
  }
330
  if (isset($handler->conf['body_classes_to_add'])) {
331
    $classes = ctools_context_keyword_substitute($handler->conf['body_classes_to_add'], array(), $contexts, array('css safe' => TRUE));
332
    if (!isset($panel_body_css['body_classes_to_add'])) {
333
      $panel_body_css['body_classes_to_add'] = check_plain($classes);
334
    }
335
    else {
336
      $panel_body_css['body_classes_to_add'] .= ' ' . check_plain($classes);
337
    }
338
  }
339

    
340
  $info = array(
341
    'content' => panels_render_display($display, $renderer),
342
    'no_blocks' => !empty($handler->conf['no_blocks']),
343
  );
344

    
345
  $info['title'] = $display->get_title();
346

    
347
  return $info;
348
}
349

    
350
/**
351
 * Callback to allow the handler to react to being saved.
352
 *
353
 * When a handler with a display is saved, two things have to happen.
354
 * First, we have to save the display so that it becomes a real display,
355
 * not the fake one we started with. Second, we have to cache
356
 * any CSS that the display is using. This CSS can get re-cached
357
 * later if the file disappears, but it's imperative that we do it here
358
 * to make sure that old, dirty CSS cache gets removed.
359
 */
360
function panels_panel_context_save(&$handler, $update) {
361
  // Only save the display if we believe it has been modified.
362
  if (isset($handler->conf['display'])) {
363
    panels_save_display($handler->conf['display']);
364
    $handler->conf['did'] = $handler->conf['display']->did;
365
    unset($handler->conf['display']);
366
  }
367

    
368
  // Delete any previous CSS cache file.
369
  ctools_include('css');
370
  ctools_css_clear('panel_context:' . $handler->name);
371

    
372
  if (isset($handler->conf['temp_layout'])) {
373
    unset($handler->conf['temp_layout']);
374
  }
375
}
376

    
377
/**
378
 * Special handling for exporting a panel task handler.
379
 *
380
 * When a panel is exported, we need to export the display separately
381
 * rather than just letting its object be unpacked, which does not work
382
 * very well.
383
 */
384
function panels_panel_context_export(&$handler, $indent) {
385
  $display = panels_panel_context_get_display($handler);
386
  foreach (array('display', 'did', 'css_cache', 'temp_layout') as $item) {
387
    if (isset($handler->conf[$item])) {
388
      unset($handler->conf[$item]);
389
    }
390
  }
391

    
392
  $output = panels_export_display($display, $indent);
393
  $output .= $indent . '$handler->conf[\'display\'] = $display' . ";\n";
394
  return $output;
395
}
396

    
397
/**
398
 * When a handler is cloned, we have to clone the display.
399
 */
400
function panels_panel_context_clone(&$handler) {
401
  $old_display = panels_panel_context_get_display($handler);
402
  $code = panels_export_display($old_display);
403
  eval($code);
404
  foreach (array('display', 'did', 'css_cache', 'temp_layout') as $item) {
405
    if (isset($handler->conf[$item])) {
406
      unset($handler->conf[$item]);
407
    }
408
  }
409
  $display = (object) array(
410
    'did' => 'new',
411
    'uuid' => ctools_uuid_generate(),
412
  );
413
  $handler->conf['display'] = $display;
414
}
415

    
416
/**
417
 * Callback to delete the display when a handler is deleted.
418
 */
419
function panels_panel_context_delete(&$handler) {
420
  if (!empty($handler->conf['did'])) {
421
    panels_delete_display($handler->conf['did']);
422
  }
423
}
424

    
425
/**
426
 * Set up a title for the panel based upon the selection rules.
427
 */
428
function panels_panel_context_title($handler, $task, $subtask) {
429
  if (isset($handler->conf['title'])) {
430
    return check_plain($handler->conf['title']);
431
  }
432
  else {
433
    return t('Panel');
434
  }
435
}
436

    
437
/**
438
 * Provide a nice little summary of what's in a panel.
439
 *
440
 * The task handler manager provides a summary of a given handler in a
441
 * collapsible div. This callback provides that. For a Panel, we
442
 * provide a summary of the layout type and content on one side, and
443
 * a summary of the contexts in use on the other.
444
 */
445
function panels_panel_context_admin_summary($handler, $task, $subtask, $page, $show_title = TRUE) {
446
  $task_name = page_manager_make_task_name($task['name'], $subtask['name']);
447
  $output = '';
448

    
449
  $display = panels_panel_context_get_display($handler);
450

    
451
  ctools_include('plugins', 'panels');
452
  ctools_include('context');
453
  ctools_include('context-task-handler');
454

    
455
  // Get the operations.
456
  $operations = page_manager_get_operations($page);
457

    
458
  // Get operations for just this handler.
459
  $operations = $operations['handlers']['children'][$handler->name]['children']['actions']['children'];
460
  $args = array('handlers', $handler->name, 'actions');
461
  $rendered_operations = page_manager_render_operations($page, $operations, array(), array('class' => array('actions')), 'actions', $args);
462

    
463
  $layout = panels_get_layout($display->layout);
464

    
465
  $plugin = page_manager_get_task_handler($handler->handler);
466

    
467
  $object = ctools_context_handler_get_task_object($task, $subtask, $handler);
468
  $display->context = ctools_context_load_contexts($object, TRUE);
469

    
470
  $access = ctools_access_group_summary(!empty($handler->conf['access']) ? $handler->conf['access'] : array(), $display->context);
471
  if ($access) {
472
    $access = t('This panel will be selected if @conditions.', array('@conditions' => $access));
473
  }
474
  else {
475
    $access = t('This panel will always be selected.');
476
  }
477

    
478
  $rows = array();
479

    
480
  $type = $handler->type == t('Default') ? t('In code') : $handler->type;
481
  $rows[] = array(
482
    array('class' => t('page-summary-label'), 'data' => t('Storage')),
483
    array('class' => t('page-summary-data'), 'data' => $type),
484
    array('class' => t('page-summary-operation'), 'data' => ''),
485
  );
486

    
487
  if (!empty($handler->disabled)) {
488
    $link = l(t('Enable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'enable')));
489
    $text = t('Disabled');
490
  }
491
  else {
492
    $link = l(t('Disable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'disable')));
493
    $text = t('Enabled');
494
  }
495

    
496
  $rows[] = array(
497
    array('class' => t('page-summary-label'), 'data' => t('Status')),
498
    array('class' => t('page-summary-data'), 'data' => $text),
499
    array('class' => t('page-summary-operation'), 'data' => $link),
500
  );
501

    
502
  $link = l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'criteria')));
503
  $rows[] = array(
504
    array('class' => t('page-summary-label'), 'data' => t('Selection rule')),
505
    array('class' => t('page-summary-data'), 'data' => $access),
506
    array('class' => t('page-summary-operation'), 'data' => $link),
507
  );
508

    
509
  $link = l(t('Change layout'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'layout')));
510
  $link .= '<br />' . l(t('Edit content'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'content')));
511
  $link .= '<br />' . l(t('Preview'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'preview')));
512
  $rows[] = array(
513
    array('class' => t('page-summary-label'), 'data' => t('Layout')),
514
    array('class' => t('page-summary-data'), 'data' => check_plain($layout['title'])),
515
    array('class' => t('page-summary-operation'), 'data' => $link),
516
  );
517

    
518
  $content_link = ' [' . l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'content'))) . ']';
519
  $context_link = ' [' . l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'context'))) . ']';
520

    
521
  $info = theme('table', array('rows' => $rows, 'attributes' => array('class' => 'page-manager-handler-summary')));
522

    
523
  $title = $handler->conf['title'];
524
  if ($title != t('Panel')) {
525
    $title = t('Panel: @title', array('@title' => $title));
526
  }
527

    
528
  $output .= '<div class="clearfix">';
529
  if ($show_title) {
530
    $output .= '<div class="handler-title clearfix">';
531
    $output .= '<div class="actions handler-actions">' . $rendered_operations['actions'] . '</div>';
532
    $output .= '<span class="title-label">' . $title . '</span>';
533
  }
534

    
535
  $output .= '</div>';
536
  $output .= $info;
537
  $output .= '</div>';
538
  /*
539
  $output .= '<div class="right-container">';
540
  $output .= '<h3 class="context-title">' . t('Contexts') . $context_link . '</h3>';
541
  $output .= $contexts;
542
  $output .= '</div>';
543

    
544
  $output .= '<div class="left-container">';
545
  //  $output .= $icon;
546
  $output .= '<h3 class="handler-title">' . t('Content') . $content_link . '</h3>';
547
  $output .= $content;
548
  $output .= '</div>';
549
   */
550
  return $output;
551
}
552

    
553
// --------------------------------------------------------------------------
554
// Forms.
555
/**
556
 * General notes about forms: The handler is automatically cached by the form
557
 * wizard, so anything we store on $form_state['handler'] anywhere will get
558
 * saved and appear on the next form. The cache is a 'working' cache and
559
 * if the user hits cancel on any page of the multi-page wizard, all
560
 * changes since the last 'update/finish' click will be flushed away.
561
 *
562
 * Many of the Panels forms call through to the real Panels cousins. These
563
 * forms are smart enough to know that they're being wrapped in another
564
 * form and act appropriately. Some of them are so smart that we just let
565
 * their submit and validate handlers do the work rather than writing
566
 * additional ones here.
567
 */
568

    
569
/**
570
 * Choose a layout for this panel.
571
 *
572
 * This is only called during 'add', when we know that there isn't a
573
 * previous layout to choose from. a different, only slightly different
574
 * variant is called to change a pre-existing layout.
575
 */
576
function panels_panel_context_edit_choose($form, &$form_state) {
577
  ctools_include('common', 'panels');
578
  ctools_include('display-layout', 'panels');
579
  ctools_include('plugins', 'panels');
580

    
581
  // @todo -- figure out where/how to deal with this.
582
  $form_state['allowed_layouts'] = 'panels_page';
583

    
584
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
585

    
586
  // Tell the Panels form not to display buttons.
587
  $form_state['no buttons'] = TRUE;
588

    
589
  // Change the #id of the form so the CSS applies properly.
590
  $form['#id'] = 'panels-choose-layout';
591
  $form = panels_choose_layout($form, $form_state);
592

    
593
  return $form;
594
}
595

    
596
/**
597
 * Validate that a layout was chosen.
598
 */
599
function panels_panel_context_edit_choose_validate(&$form, &$form_state) {
600
  if (empty($form_state['values']['layout'])) {
601
    form_error($form['layout'], t('You must select a layout.'));
602
  }
603
}
604

    
605
/**
606
 * A layout has been selected, set it up.
607
 */
608
function panels_panel_context_edit_choose_submit(&$form, &$form_state) {
609
  $form_state['display']->layout = $form_state['values']['layout'];
610
  $form_state['handler']->conf['display'] = $form_state['display'];
611
  if (isset($form_state['page']->display_cache[$form_state['handler_id']])) {
612
    $form_state['page']->display_cache[$form_state['handler_id']]->display = $form_state['display'];
613
  }
614
}
615

    
616
/**
617
 * Change the layout for this panel.
618
 *
619
 * This form is only used if a layout already exists and the user wants
620
 * to change to a different one. The submit handler changes the next form
621
 * to the move content form, which is 'hidden' so it won't be accessed
622
 * directly.
623
 */
624
function panels_panel_context_edit_layout($form, &$form_state) {
625
  ctools_include('common', 'panels');
626
  ctools_include('display-layout', 'panels');
627
  ctools_include('plugins', 'panels');
628

    
629
  // @todo -- figure out where/how to deal with this.
630
  $form_state['allowed_layouts'] = 'panels_page';
631

    
632
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
633

    
634
  // Tell the Panels form not to display buttons.
635
  $form_state['no buttons'] = TRUE;
636

    
637
  // Change the #id of the form so the CSS applies properly.
638
  $form['#id'] = 'panels-choose-layout';
639
  $form = panels_choose_layout($form, $form_state);
640

    
641
  return $form;
642
}
643

    
644
/**
645
 * Validate that a layout was chosen.
646
 */
647
function panels_panel_context_edit_layout_validate(&$form, &$form_state) {
648
  $display = &panels_panel_context_get_display($form_state['handler']);
649

    
650
  if (empty($form_state['values']['layout'])) {
651
    form_error($form['layout'], t('You must select a layout.'));
652
  }
653
  if ($form_state['values']['layout'] == $display->layout) {
654
    form_error($form['layout'], t('You must select a different layout if you wish to change layouts.'));
655
  }
656
}
657

    
658
/**
659
 * A layout has been selected, set it up.
660
 */
661
function panels_panel_context_edit_layout_submit(&$form, &$form_state) {
662
  $display = &panels_panel_context_get_display($form_state['handler']);
663

    
664
  if ($form_state['values']['layout'] != $display->layout) {
665
    $form_state['handler']->conf['temp_layout'] = $form_state['values']['layout'];
666
  }
667
}
668

    
669
/**
670
 * When a layout is changed, the user is given the opportunity to move content.
671
 */
672
function panels_panel_context_edit_move($form, &$form_state) {
673
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
674
  $form_state['layout'] = $form_state['handler']->conf['temp_layout'];
675

    
676
  $form_state['cache_key'] = panels_panel_context_cache_key($form_state['task_name'], $form_state['handler_id'], array());
677

    
678
  ctools_include('common', 'panels');
679
  ctools_include('display-layout', 'panels');
680
  ctools_include('plugins', 'panels');
681

    
682
  // Tell the Panels form not to display buttons.
683
  $form_state['no buttons'] = TRUE;
684

    
685
  // Change the #id of the form so the CSS applies properly.
686
  $form = panels_change_layout($form, $form_state);
687

    
688
  // Change the 'back' button to just go directly to the previous form
689
  //  $task_id = $form_state['task']['name'];
690
  //  $handler_id = $form_state['handler']->handler;
691
  //  $name = $form_state['handler']->name;
692
  // This form is outside the normal wizard list, so we need to specify the
693
  // previous/next forms.
694
  $form['buttons']['previous']['#next'] = 'layout';
695
  $form['buttons']['next']['#next'] = 'content';
696

    
697
  $form_state['form_info']['return path'] = page_manager_edit_url($form_state['page']->task_name, array('handlers', $form_state['handler_id'], 'content'));
698
  return $form;
699
}
700

    
701
/**
702
 * Present the panels drag & drop editor to edit the display attached
703
 * to the task handler.
704
 */
705
function panels_panel_context_edit_content($form, &$form_state) {
706
  ctools_include('ajax');
707
  ctools_include('plugins', 'panels');
708
  ctools_include('common', 'panels');
709
  ctools_include('context');
710
  ctools_include('context-task-handler');
711

    
712
  $cache = panels_edit_cache_get(panels_panel_context_cache_key($form_state['task_name'], $form_state['handler_id'], array()));
713

    
714
  $form_state['renderer'] = panels_get_renderer_handler('editor', $cache->display);
715
  $form_state['renderer']->cache = &$cache;
716

    
717
  $form_state['display'] = &$cache->display;
718
  $form_state['content_types'] = $cache->content_types;
719
  // Tell the Panels form not to display buttons.
720
  $form_state['no buttons'] = TRUE;
721
  $form_state['display_title'] = !empty($cache->display_title);
722
  $form_state['no preview'] = TRUE;
723
  $form_state['page']->display_cache[$form_state['handler_id']] = $cache;
724

    
725
  $form = panels_edit_display_form($form, $form_state);
726

    
727
  if (!isset($form_state['type']) || $form_state['type'] != 'add' && !empty($form_state['handler_id']) && !empty($form['buttons'])) {
728
    $form['buttons']['preview'] = $form['buttons']['return'];
729
    $form['buttons']['preview']['#value'] = t('Update and preview');
730
  }
731
  return $form;
732
}
733

    
734
/**
735
 * Validate changes to the panel content form.
736
 */
737
function panels_panel_context_edit_content_validate(&$form, &$form_state) {
738
  panels_edit_display_form_validate($form, $form_state);
739
}
740

    
741
function panels_panel_context_edit_content_submit(&$form, &$form_state) {
742
  // Update the storage_id if this is a new variant before saving.
743
  if ($form_state['display']->storage_id == 'new') {
744
    $form_state['display']->storage_id = $form_state['handler_id'];
745
  }
746
  panels_edit_display_form_submit($form, $form_state);
747
  $handler = &$form_state['handler'];
748

    
749
  // Update the cached display:
750
  $display = $form_state['page']->display_cache[$form_state['handler_id']]->display;
751
  $handler->conf['display'] = $display;
752
  unset($form_state['page']->display_cache[$form_state['handler_id']]);
753

    
754
  if ($form_state['clicked_button']['#value'] == t('Update and preview')) {
755
    $form_state['new trail'] = array('handlers', $form_state['handler_id'], 'preview');
756
  }
757
}
758

    
759
/**
760
 * General settings for the panel.
761
 */
762
function panels_panel_context_edit_settings($form, &$form_state) {
763
  $conf = $form_state['handler']->conf;
764
  $form['conf']['title'] = array(
765
    '#type' => 'textfield',
766
    '#default_value' => $conf['title'],
767
    '#title' => t('Administrative title'),
768
    '#description' => t('Administrative title of this variant.'),
769
  );
770

    
771
  $form['conf']['no_blocks'] = array(
772
    '#type' => 'checkbox',
773
    '#default_value' => $conf['no_blocks'],
774
    '#title' => t('Disable Drupal blocks/regions'),
775
    '#description' => t('Check this to have the page disable all regions displayed in the theme. Note that some themes support this setting better than others. If in doubt, try with stock themes to see.'),
776
  );
777

    
778
  $form['conf']['body_classes_to_remove'] = array(
779
    '#type' => 'textfield',
780
    '#size' => 128,
781
    '#default_value' => empty($conf['body_classes_to_remove']) ? '' : $conf['body_classes_to_remove'],
782
    '#title' => t('Remove body CSS classes'),
783
    '#description' => t('The CSS classes to remove from the body element of this page. Separated by a space. For example: no-sidebars one-sidebar sidebar-first sidebar-second two-sidebars. Keywords from context are allowed.'),
784
  );
785

    
786
  $form['conf']['body_classes_to_add'] = array(
787
    '#type' => 'textfield',
788
    '#size' => 128,
789
    '#default_value' => empty($conf['body_classes_to_add']) ? '' : $conf['body_classes_to_add'],
790
    '#title' => t('Add body CSS classes'),
791
    '#description' => t('The CSS classes to add to the body element of this page. Separated by a space. For example: no-sidebars one-sidebar sidebar-first sidebar-second two-sidebars. Keywords from context are allowed.'),
792
  );
793

    
794
  ctools_include('plugins', 'panels');
795
  $pipelines = panels_get_renderer_pipelines();
796

    
797
  // Handle backward compatibility with the IPE checkbox.
798
  if (empty($conf['pipeline'])) {
799
    $conf['pipeline'] = !empty($conf['use_ipe']) ? 'ipe' : 'standard';
800
  }
801

    
802
  // If there are no pipelines, that probably means we're operating in
803
  // legacy mode.
804
  if (empty($pipelines)) {
805
    // We retain the original pipeline so we don't wreck things by installing
806
    // old modules.
807
    $form['conf']['pipeline'] = array(
808
      '#type' => 'value',
809
      '#value' => $conf['pipeline'],
810
    );
811
  }
812
  else {
813
    $options = array();
814
    foreach ($pipelines as $name => $pipeline) {
815
      $options[$name] = check_plain($pipeline->admin_title) . '<div class="description">' . check_plain($pipeline->admin_description) . '</div>';
816
    }
817

    
818
    $form['conf']['pipeline'] = array(
819
      '#type' => 'radios',
820
      '#options' => $options,
821
      '#title' => t('Renderer'),
822
      '#default_value' => $conf['pipeline'],
823
    );
824
  }
825

    
826
  $form['conf']['css_id'] = array(
827
    '#type' => 'textfield',
828
    '#size' => 35,
829
    '#default_value' => $conf['css_id'],
830
    '#title' => t('CSS ID'),
831
    '#description' => t('The CSS ID to apply to this page. Keywords from context are allowed.'),
832
  );
833

    
834
  $form['conf']['css'] = array(
835
    '#type' => 'textarea',
836
    '#title' => t('CSS code'),
837
    '#description' => t('Enter well-formed CSS code here; this code will be embedded into the page, and should only be used for minor adjustments; it is usually better to try to put CSS for the page into the theme if possible. This CSS will be filtered for safety so some CSS may not work. Keywords from context are allowed.'),
838
    '#default_value' => $conf['css'],
839
  );
840

    
841
  return $form;
842
}
843

    
844
/**
845
 * Submit handler for general settings form.
846
 */
847
function panels_panel_context_edit_settings_submit(&$form, &$form_state) {
848
  $form_state['handler']->conf['no_blocks'] = $form_state['values']['no_blocks'];
849
  $form_state['handler']->conf['body_classes_to_remove'] = $form_state['values']['body_classes_to_remove'];
850
  $form_state['handler']->conf['body_classes_to_add'] = $form_state['values']['body_classes_to_add'];
851
  $form_state['handler']->conf['pipeline'] = $form_state['values']['pipeline'];
852
  $form_state['handler']->conf['css_id'] = $form_state['values']['css_id'];
853
  $form_state['handler']->conf['css'] = $form_state['values']['css'];
854
  $form_state['handler']->conf['title'] = $form_state['values']['title'];
855

    
856
  // Unset the old checkbox so we don't store needless data.
857
  if (isset($form_state['handler']->conf['use_ipe'])) {
858
    unset($form_state['handler']->conf['use_ipe']);
859
  }
860
}
861

    
862
/**
863
 * Form to show a nice preview.
864
 */
865
function panels_panel_context_edit_preview($form, &$form_state) {
866
  ctools_include('context');
867
  ctools_include('context-task-handler');
868

    
869
  $contexts = ctools_context_handler_get_all_contexts($form_state['task'], $form_state['subtask'], $form_state['handler']);
870
  $form['preview'] = array();
871
  ctools_context_replace_form($form['preview'], $contexts);
872

    
873
  // Automatically preview if there are no argument placeholders.
874
  if (empty($form['preview'])) {
875
    $display = panels_panel_context_get_display($form_state['handler']);
876
    $display->context = $contexts;
877
    $display->skip_cache = TRUE;
878
    $output = panels_render_display($display);
879
    if (isset($form['buttons'])) {
880
      unset($form['buttons']);
881
    }
882
  }
883
  else {
884
    $form['preview']['#tree'] = TRUE;
885
    $form_state['contexts'] = $contexts;
886
  }
887

    
888
  if (!empty($output)) {
889
    $form['output'] = array(
890
      '#markup' => $output,
891
    );
892
  }
893

    
894
  $form_state['do not cache'] = TRUE;
895

    
896
  return $form;
897
}
898

    
899
/**
900
 * Display a preview upon submit if arguments were needed.
901
 */
902
function panels_panel_context_edit_preview_submit(&$form, &$form_state) {
903
  $display = panels_panel_context_get_display($form_state['handler']);
904
  $display->context = ctools_context_replace_placeholders($form_state['contexts'], $form_state['values']['preview']);
905

    
906
  $form_state['content'] = panels_render_display($display);
907
  $form_state['redirect'] = FALSE;
908
  $form_state['rerender'] = TRUE;
909
}
910

    
911
function panels_panel_context_get_addressable($task, $subtask_name, $handler, $address, $contexts, $arguments, $type) {
912
  // Load the display.
913
  $display = panels_panel_context_get_display($handler);
914

    
915
  $display->context = $contexts;
916
  $display->args = $arguments;
917
  $display->css_id = $handler->conf['css_id'];
918
  $display->cache_key = panels_panel_context_cache_key($task->name, $handler->name, $arguments);
919

    
920
  $renderer = panels_get_renderer($handler->conf['pipeline'], $display);
921
  $renderer->prepare();
922

    
923
  if ($address) {
924
    $pid = array_shift($address);
925
    if (!empty($renderer->prepared['panes'][$pid])) {
926
      if ($type == 'content') {
927
        return $renderer->render_pane($renderer->prepared['panes'][$pid]);
928
      }
929
      elseif ($type == 'pane') {
930
        return $renderer->prepared['panes'][$pid];
931
      }
932
    }
933
  }
934
  else {
935
    if ($type == 'content') {
936
      return $renderer->render();
937
    }
938
    elseif ($type == 'renderer') {
939
      return $renderer;
940
    }
941
  }
942
}