Projet

Général

Profil

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

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

1
<?php
2

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

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

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

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

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

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

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

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

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

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

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

    
226
  if (isset($handler->conf['did'])) {
227
    $handler->conf['display'] = panels_load_display($handler->conf['did']);
228

    
229
    // Check for a valid display. If no valid display can be loaded, something
230
    // is wrong and we'll create a new one.
231
    if (!empty($handler->conf['display'])) {
232
      return $handler->conf['display'];
233
    }
234
  }
235

    
236
  $handler->conf['display'] = panels_new_display();
237

    
238
  return $handler->conf['display'];
239
}
240

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

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

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

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

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

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

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

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

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

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

    
311
  $renderer = panels_get_renderer($handler->conf['pipeline'], $display);
312
  // If the IPE is enabled, but the user does not have access to edit
313
  // load the standard renderer instead.
314

    
315
  $parents = class_parents($renderer);
316
  if (!empty($parents['panels_renderer_editor']) && !user_access('user page manager') && !user_access('use ipe with page manager')) {
317
    $renderer = panels_get_renderer_handler('standard', $display);
318
  }
319

    
320
  // Remove and add body element classes
321
  $panel_body_css = &drupal_static('panel_body_css');
322

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

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

    
347
  $info['title'] = $display->get_title();
348

    
349
  return $info;
350
}
351

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

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

    
374
  if (isset($page->conf['temp_layout'])) {
375
    unset($page->conf['temp_layout']);
376
  }
377
}
378

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

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

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

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

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

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

    
451
  $display = panels_panel_context_get_display($handler);
452

    
453
  ctools_include('plugins', 'panels');
454
  ctools_include('context');
455
  ctools_include('context-task-handler');
456

    
457
  // Get the operations
458
  $operations = page_manager_get_operations($page);
459

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

    
465
  $layout = panels_get_layout($display->layout);
466

    
467
  $plugin = page_manager_get_task_handler($handler->handler);
468

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

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

    
480
  $rows = array();
481

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

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

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

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

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

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

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

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

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

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

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

    
555
// --------------------------------------------------------------------------
556
// Forms
557

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

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

    
584
  // @todo -- figure out where/how to deal with this.
585
  $form_state['allowed_layouts'] = 'panels_page';
586

    
587
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
588

    
589
  // Grab the storage_type and storage_id and inject it into the display.
590
  if (empty($form_state['display']->storage_type)) {
591
    if (!isset($form_state[$form_state['task_id']]->storage_type)) {
592
      watchdog('panels', "Unable to find the storage type for specified storage. Read 'Upgrading task handlers' in CHANGELOG.txt", array(), WATCHDOG_ERROR);
593
      $form_state['display']->storage_type = 'unknown';
594
    }
595
    else {
596
      $form_state['display']->storage_type = $form_state[$form_state['task_id']]->storage_type;
597
    }
598
    // When adding variants, we don't know the handler id yet. In that case,
599
    // Mark it as new. We'll assign it later.
600
    $form_state['display']->storage_id = !empty($form_state['handler_id']) ? $form_state['handler_id'] : 'new';
601
  }
602
  // Tell the Panels form not to display buttons.
603
  $form_state['no buttons'] = TRUE;
604

    
605
  // Change the #id of the form so the CSS applies properly.
606
  $form['#id'] = 'panels-choose-layout';
607
  $form = panels_choose_layout($form, $form_state);
608

    
609
  return $form;
610
}
611

    
612
/**
613
 * Validate that a layout was chosen.
614
 */
615
function panels_panel_context_edit_choose_validate(&$form, &$form_state) {
616
  if (empty($form_state['values']['layout'])) {
617
    form_error($form['layout'], t('You must select a layout.'));
618
  }
619
}
620

    
621
/**
622
 * A layout has been selected, set it up.
623
 */
624
function panels_panel_context_edit_choose_submit(&$form, &$form_state) {
625
  $form_state['display']->layout = $form_state['values']['layout'];
626
  $form_state['handler']->conf['display'] = $form_state['display'];
627
  if (isset($form_state['page']->display_cache[$form_state['handler_id']])) {
628
    $form_state['page']->display_cache[$form_state['handler_id']]->display = $form_state['display'];
629
  }
630
}
631

    
632
/**
633
 * Change the layout for this panel.
634
 *
635
 * This form is only used if a layout already exists and the user wants
636
 * to change to a different one. The submit handler changes the next form
637
 * to the move content form, which is 'hidden' so it won't be accessed
638
 * directly.
639
 */
640
function panels_panel_context_edit_layout($form, &$form_state) {
641
  ctools_include('common', 'panels');
642
  ctools_include('display-layout', 'panels');
643
  ctools_include('plugins', 'panels');
644

    
645
  // @todo -- figure out where/how to deal with this.
646
  $form_state['allowed_layouts'] = 'panels_page';
647

    
648
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
649

    
650
  // Tell the Panels form not to display buttons.
651
  $form_state['no buttons'] = TRUE;
652

    
653
  // Change the #id of the form so the CSS applies properly.
654
  $form['#id'] = 'panels-choose-layout';
655
  $form = panels_choose_layout($form, $form_state);
656

    
657
  return $form;
658
}
659

    
660
/**
661
 * Validate that a layout was chosen.
662
 */
663
function panels_panel_context_edit_layout_validate(&$form, &$form_state) {
664
  $display = &panels_panel_context_get_display($form_state['handler']);
665

    
666
  if (empty($form_state['values']['layout'])) {
667
    form_error($form['layout'], t('You must select a layout.'));
668
  }
669
  if ($form_state['values']['layout'] == $display->layout) {
670
    form_error($form['layout'], t('You must select a different layout if you wish to change layouts.'));
671
  }
672
}
673

    
674
/**
675
 * A layout has been selected, set it up.
676
 */
677
function panels_panel_context_edit_layout_submit(&$form, &$form_state) {
678
  $display = &panels_panel_context_get_display($form_state['handler']);
679

    
680
  if ($form_state['values']['layout'] != $display->layout) {
681
    $form_state['handler']->conf['temp_layout'] = $form_state['values']['layout'];
682
  }
683
}
684

    
685
/**
686
 * When a layout is changed, the user is given the opportunity to move content.
687
 */
688
function panels_panel_context_edit_move($form, &$form_state) {
689
  $form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
690
  $form_state['layout'] = $form_state['handler']->conf['temp_layout'];
691

    
692
  $form_state['cache_key'] = panels_panel_context_cache_key($form_state['task_name'], $form_state['handler_id'], array());
693

    
694
  ctools_include('common', 'panels');
695
  ctools_include('display-layout', 'panels');
696
  ctools_include('plugins', 'panels');
697

    
698
  // Tell the Panels form not to display buttons.
699
  $form_state['no buttons'] = TRUE;
700

    
701
  // Change the #id of the form so the CSS applies properly.
702
  $form = panels_change_layout($form, $form_state);
703

    
704
  // Change the 'back' button to just go directly to the previous form
705
//  $task_id = $form_state['task']['name'];
706
//  $handler_id = $form_state['handler']->handler;
707
//  $name = $form_state['handler']->name;
708

    
709
  // This form is outside the normal wizard list, so we need to specify the
710
  // previous/next forms.
711
  $form['buttons']['previous']['#next'] = 'layout';
712
  $form['buttons']['next']['#next'] = 'content';
713

    
714
  $form_state['form_info']['return path'] = page_manager_edit_url($form_state['page']->task_name, array('handlers', $form_state['handler_id'], 'content'));
715
  return $form;
716
}
717

    
718
/**
719
 * Present the panels drag & drop editor to edit the display attached
720
 * to the task handler.
721
 */
722
function panels_panel_context_edit_content($form, &$form_state) {
723
  ctools_include('ajax');
724
  ctools_include('plugins', 'panels');
725
  ctools_include('common', 'panels');
726
  ctools_include('context');
727
  ctools_include('context-task-handler');
728

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

    
731
  $form_state['renderer'] = panels_get_renderer_handler('editor', $cache->display);
732
  $form_state['renderer']->cache = &$cache;
733

    
734
  $form_state['display'] = &$cache->display;
735
  $form_state['content_types'] = $cache->content_types;
736
  // Tell the Panels form not to display buttons.
737
  $form_state['no buttons'] = TRUE;
738
  $form_state['display_title'] = !empty($cache->display_title);
739
  $form_state['no preview'] = TRUE;
740
  $form_state['page']->display_cache[$form_state['handler_id']] = $cache;
741

    
742
  $form = panels_edit_display_form($form, $form_state);
743

    
744
  if (!isset($form_state['type']) || $form_state['type'] != 'add' && !empty($form_state['handler_id']) && !empty($form['buttons'])) {
745
    $form['buttons']['preview'] = $form['buttons']['return'];
746
    $form['buttons']['preview']['#value'] = t('Update and preview');
747
  }
748
  return $form;
749
}
750

    
751
/**
752
 * Validate changes to the panel content form.
753
 */
754
function panels_panel_context_edit_content_validate(&$form, &$form_state) {
755
  panels_edit_display_form_validate($form, $form_state);
756
}
757

    
758
function panels_panel_context_edit_content_submit(&$form, &$form_state) {
759
  // Update the storage_id if this is a new variant before saving.
760
  if ($form_state['display']->storage_id == 'new') {
761
    $form_state['display']->storage_id = $form_state['handler_id'];
762
  }
763
  panels_edit_display_form_submit($form, $form_state);
764
  $handler = &$form_state['handler'];
765

    
766
  // update the cached display:
767
  $display = $form_state['page']->display_cache[$form_state['handler_id']]->display;
768
  $handler->conf['display'] = $display;
769
  unset($form_state['page']->display_cache[$form_state['handler_id']]);
770

    
771
  if ($form_state['clicked_button']['#value'] == t('Update and preview')) {
772
    $form_state['new trail'] = array('handlers', $form_state['handler_id'], 'preview');
773
  }
774
}
775

    
776
/**
777
 * General settings for the panel
778
 */
779
function panels_panel_context_edit_settings($form, &$form_state) {
780
  $conf = $form_state['handler']->conf;
781
  $form['conf']['title'] = array(
782
    '#type' => 'textfield',
783
    '#default_value' => $conf['title'],
784
    '#title' => t('Administrative title'),
785
    '#description' => t('Administrative title of this variant.'),
786
  );
787

    
788
  $form['conf']['no_blocks'] = array(
789
    '#type' => 'checkbox',
790
    '#default_value' => $conf['no_blocks'],
791
    '#title' => t('Disable Drupal blocks/regions'),
792
    '#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.'),
793
  );
794

    
795
  $form['conf']['body_classes_to_remove'] = array(
796
    '#type' => 'textfield',
797
    '#size' => 128,
798
    '#default_value' => empty($conf['body_classes_to_remove']) ? '' : $conf['body_classes_to_remove'],
799
    '#title' => t('Remove body CSS classes'),
800
    '#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.'),
801
  );
802

    
803
  $form['conf']['body_classes_to_add'] = array(
804
    '#type' => 'textfield',
805
    '#size' => 128,
806
    '#default_value' => empty($conf['body_classes_to_add']) ? '' : $conf['body_classes_to_add'],
807
    '#title' => t('Add body CSS classes'),
808
    '#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.'),
809
  );
810

    
811
  ctools_include('plugins', 'panels');
812
  $pipelines = panels_get_renderer_pipelines();
813

    
814
  // Handle backward compatibility with the IPE checkbox.
815
  if (empty($conf['pipeline'])) {
816
    $conf['pipeline'] = !empty($conf['use_ipe']) ? 'ipe' : 'standard';
817
  }
818

    
819
  // If there are no pipelines, that probably means we're operating in
820
  // legacy mode.
821
  if (empty($pipelines)) {
822
    // We retain the original pipeline so we don't wreck things by installing
823
    // old modules.
824
    $form['conf']['pipeline'] = array(
825
      '#type' => 'value',
826
      '#value' => $conf['pipeline'],
827
    );
828
  }
829
  else {
830
    $options = array();
831
    foreach ($pipelines as $name => $pipeline) {
832
      $options[$name] = check_plain($pipeline->admin_title) . '<div class="description">' . check_plain($pipeline->admin_description) . '</div>';
833
    }
834

    
835
    $form['conf']['pipeline'] = array(
836
      '#type' => 'radios',
837
      '#options' => $options,
838
      '#title' => t('Renderer'),
839
      '#default_value' => $conf['pipeline'],
840
    );
841
  }
842

    
843
  $form['conf']['css_id'] = array(
844
    '#type' => 'textfield',
845
    '#size' => 35,
846
    '#default_value' => $conf['css_id'],
847
    '#title' => t('CSS ID'),
848
    '#description' => t('The CSS ID to apply to this page. Keywords from context are allowed.'),
849
  );
850

    
851
  $form['conf']['css'] = array(
852
    '#type' => 'textarea',
853
    '#title' => t('CSS code'),
854
    '#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.'),
855
    '#default_value' => $conf['css'],
856
  );
857

    
858
  return $form;
859
}
860

    
861
/**
862
 * Submit handler for general settings form.
863
 */
864
function panels_panel_context_edit_settings_submit(&$form, &$form_state) {
865
  $form_state['handler']->conf['no_blocks'] = $form_state['values']['no_blocks'];
866
  $form_state['handler']->conf['body_classes_to_remove'] = $form_state['values']['body_classes_to_remove'];
867
  $form_state['handler']->conf['body_classes_to_add'] = $form_state['values']['body_classes_to_add'];
868
  $form_state['handler']->conf['pipeline'] = $form_state['values']['pipeline'];
869
  $form_state['handler']->conf['css_id'] = $form_state['values']['css_id'];
870
  $form_state['handler']->conf['css'] = $form_state['values']['css'];
871
  $form_state['handler']->conf['title'] = $form_state['values']['title'];
872

    
873
  // Unset the old checkbox so we don't store needless data.
874
  if (isset($form_state['handler']->conf['use_ipe'])) {
875
    unset($form_state['handler']->conf['use_ipe']);
876
  }
877
}
878

    
879
/**
880
 * Form to show a nice preview.
881
 */
882
function panels_panel_context_edit_preview($form, &$form_state) {
883
  ctools_include('context');
884
  ctools_include('context-task-handler');
885

    
886
  $contexts = ctools_context_handler_get_all_contexts($form_state['task'], $form_state['subtask'], $form_state['handler']);
887
  $form['preview'] = array();
888
  ctools_context_replace_form($form['preview'], $contexts);
889

    
890
  // automatically preview if there are no argument placeholders.
891
  if (empty($form['preview'])) {
892
    $display = panels_panel_context_get_display($form_state['handler']);
893
    $display->context = $contexts;
894
    $display->skip_cache = TRUE;
895
    $output = panels_render_display($display);
896
    if (isset($form['buttons'])) {
897
      unset($form['buttons']);
898
    }
899
  }
900
  else {
901
    $form['preview']['#tree'] = TRUE;
902
    $form_state['contexts'] = $contexts;
903
  }
904

    
905
  if (!empty($output)) {
906
    $form['output'] = array(
907
      '#markup' => $output,
908
    );
909
  }
910

    
911
  $form_state['do not cache'] = TRUE;
912

    
913
  return $form;
914
}
915

    
916
/**
917
 * Display a preview upon submit if arguments were needed.
918
 */
919
function panels_panel_context_edit_preview_submit(&$form, &$form_state) {
920
  $display = panels_panel_context_get_display($form_state['handler']);
921
  $display->context = ctools_context_replace_placeholders($form_state['contexts'], $form_state['values']['preview']);
922

    
923
  $form_state['content'] = panels_render_display($display);
924
  $form_state['redirect'] = FALSE;
925
  $form_state['rerender'] = TRUE;
926
}
927

    
928
function panels_panel_context_get_addressable($task, $subtask_name, $handler, $address, $contexts, $arguments, $type) {
929
  // Load the display
930
  $display = panels_panel_context_get_display($handler);
931

    
932
  $display->context = $contexts;
933
  $display->args = $arguments;
934
  $display->css_id = $handler->conf['css_id'];
935
  $display->cache_key = panels_panel_context_cache_key($task->name, $handler->name, $arguments);
936

    
937
  $renderer = panels_get_renderer($handler->conf['pipeline'], $display);
938
  $renderer->prepare();
939

    
940
  if ($address) {
941
    $pid = array_shift($address);
942
    if (!empty($renderer->prepared['panes'][$pid])) {
943
      if ($type == 'content') {
944
        return $renderer->render_pane($renderer->prepared['panes'][$pid]);
945
      }
946
      elseif ($type == 'pane') {
947
        return $renderer->prepared['panes'][$pid];
948
      }
949
    }
950
  }
951
  else {
952
    if ($type == 'content') {
953
      return $renderer->render();
954
    }
955
    elseif ($type == 'renderer') {
956
      return $renderer;
957
    }
958
  }
959
}