Projet

Général

Profil

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

root / drupal7 / sites / all / modules / panelizer / panelizer.module @ 651307cd

1 85ad3d82 Assos Assos
<?php
2
/**
3
 * @file
4 e5e66f93 Assos Assos
 * The Panelizer module attaches panels to entities, providing default panels
5
 * and allowing each panel to be configured independently by privileged users.
6 85ad3d82 Assos Assos
 */
7
8
define('PANELIZER_VERSION', '3.0');
9
10
// -----------------------------------------------------------------------
11
// Drupal core hooks
12
13 e5e66f93 Assos Assos
/**
14
 * Implements hook_help().
15
 */
16
function panelizer_help($path, $arg) {
17
  if ($path == 'admin/structure/panelizer') {
18
    return '<p>' . t('Other than "Full page override" or "Default" (when applicable), only view modes enabled through the Custom Display Settings section of the <em>Manage Display</em> settings for that entity or bundle will be available for use.') . '</p>';
19
  }
20
}
21
22
/**
23
 * Implements hook_hook_info().
24
 */
25
function panelizer_hook_info() {
26
  $hooks = array(
27
    'panelizer_defaults_override_alter',
28
    'panelizer_entity_plugin_process_alter',
29
    'panelizer_operations_alter',
30
  );
31
32
  return array_fill_keys($hooks, array('group' => 'panelizer'));
33
}
34
35 85ad3d82 Assos Assos
/**
36
 * Implements hook_permission().
37
 */
38
function panelizer_permission() {
39
  $items = array(
40
    'administer panelizer' => array(
41
      'title' => t('administer panelizer'),
42
      'description' => t('Fully administer panelizer and all panelizer settings.'),
43
    ),
44
  );
45
46
  // Delegate.
47
  foreach (panelizer_get_plugins_with_hook('permission') as $handler) {
48
    $handler->hook_permission($items);
49
  }
50
51
  return $items;
52
}
53
54 e5e66f93 Assos Assos
/**
55
 * Implements hook_og_permission().
56
 */
57
function panelizer_og_permission() {
58
  $items = array();
59
60
  // Delegate.
61
  foreach (panelizer_get_plugins_with_hook('permission') as $handler) {
62
    if ($handler->entity_type == 'node') {
63
      $handler->hook_permission($items);
64
    }
65
  }
66
67
  $final = array(
68
    'administer panelizer og_group defaults' => array(
69
      'title' => t('Group: Administer Panelizer default panels, allowed content and settings.'),
70
      'description' => t('Users with this permission can fully administer panelizer for this entity bundle.'),
71
    ),
72
    'administer panelizer og_group overview' => array(
73
      'title' => t('Group: Administer Panelizer overview.'),
74
      'description' => t('Allow access to the panelizer overview page for the entity type/bundle. Note: This permission will be required for panelizer tabs to appear on an entity.'),
75
    ),
76
  );
77
78
  foreach (panelizer_operations() as $path => $operation) {
79
    $final["administer panelizer og_group $path"] = array(
80
      'title' => t('Group: Administer Panelizer @operation', array(
81
        '@operation' => $operation['link title'],
82
      )),
83
    );
84
  }
85
86
  foreach ($items as $key => $item) {
87
    // Get node bundle.
88
    $words = explode(' ', $key);
89
    $bundle = $words[3];
90
    if (og_is_group_content_type('node', $bundle)) {
91
      $final[$key] = $item;
92
    }
93
  }
94
95
  return $final;
96
}
97
98 85ad3d82 Assos Assos
/**
99
 * Implements hook_theme().
100
 */
101
function panelizer_theme() {
102
  $items = array();
103
104
  $items['panelizer_settings_page_table'] = array(
105
    'render element' => 'element',
106
    'file' => 'includes/admin.inc',
107
  );
108
109
  $items['panelizer_view_mode'] = array(
110
    'render element' => 'element',
111
    'template' => 'panelizer-view-mode',
112
    'path' => drupal_get_path('module', 'panelizer') . '/templates',
113
  );
114
115
  // Delegate.
116
  foreach (panelizer_get_plugins_with_hook('theme') as $handler) {
117
    $handler->hook_theme($items);
118
  }
119
120
  return $items;
121
}
122
123
/**
124
 * Implements hook_menu().
125
 */
126
function panelizer_menu() {
127
  $items = array();
128
129 e5e66f93 Assos Assos
  // Delegate admin menu stuff to admin.inc.
130 85ad3d82 Assos Assos
  ctools_include('admin', 'panelizer');
131
  panelizer_admin_hook_menu($items);
132
133
  // Delegate.
134
  foreach (panelizer_get_plugins_with_hook('menu') as $handler) {
135
    $handler->hook_menu($items);
136
  }
137
138
  return $items;
139
}
140
141
/**
142
 * Implements hook_menu_alter().
143
 */
144
function panelizer_menu_alter(&$items) {
145
  // Delegate.
146
  foreach (panelizer_get_plugins_with_hook('menu_alter') as $handler) {
147
    $handler->hook_menu_alter($items);
148
  }
149
}
150
151
/**
152
 * Implements hook_admin_paths().
153
 */
154
function panelizer_admin_paths() {
155
  $items = array();
156
157
  // Delegate.
158
  foreach (panelizer_get_plugins_with_hook('admin_paths') as $handler) {
159
    $handler->hook_admin_paths($items);
160
  }
161
162
  return $items;
163
}
164
165 136a805a Assos Assos
/**
166
 * Implements hook_panels_ipe_access().
167
 */
168
function panelizer_panels_ipe_access($display) {
169
  // We only care about Panels displays from panelizer.
170
  if (isset($display->context['panelizer'])) {
171
    // The type array contains 3 elements, where the first is the full context
172
    // type (ie. 'entity:ENTITY_TYPE'), and the remaining two are the parts
173
    // seperated by ':', so 'entity' and the entity type name.
174
    $entity_type = $display->context['panelizer']->type[2];
175
    if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
176
      // Only allow access to use the IPE if the user has 'update' access to
177
      // the underlying entity.
178
      $entity = $display->context['panelizer']->data;
179
      return $handler->entity_access('update', $entity);
180
    }
181
  }
182
}
183
184 e5e66f93 Assos Assos
/**
185
 * Implements hook_form_FORM_ID_alter().
186
 *
187
 * Check whether a given view mode is panelized. Set an error message if there
188
 * are un-hidden fields because they won't be printed anyway.
189
 */
190
function panelizer_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
191
  if (!empty($form['#entity_type']) && !empty($form['#bundle']) && !empty($form['#view_mode'])) {
192
    module_load_install('panelizer');
193
    if (panelizer_view_mode_extra_field_displays($form['#entity_type'], $form['#bundle'], $form['#view_mode'])) {
194
      $message = t("This view mode is being controlled via Panelizer. For performance reasons, it is recommended to move all fields to 'hidden'. Fields not marked as hidden will be prepared for output but will not actually output, thus needlessly increasing render and page load time.");
195
      drupal_set_message($message, 'error', FALSE);
196
    }
197
  }
198
}
199
200 85ad3d82 Assos Assos
/**
201
 * Implements hook_form_alter().
202
 */
203
function panelizer_form_alter(&$form, &$form_state, $form_id) {
204
  // Delegate.
205
  foreach (panelizer_get_plugins_with_hook('form_alter') as $handler) {
206
    $handler->hook_form_alter($form, $form_state, $form_id);
207
208 e5e66f93 Assos Assos
    // Support default content and layout settings.
209
    foreach ($handler->plugin['bundles'] as $bundle_name => $bundle) {
210 85ad3d82 Assos Assos
      if ($form_id == 'panels_common_settings' && $form_state['build_info']['args'][0] == 'panelizer_' . $handler->entity_type . ':' . $bundle_name) {
211
212 e5e66f93 Assos Assos
        // Provide settings for the default content and layout options.
213 85ad3d82 Assos Assos
        $form['default_settings'] = array(
214
          '#type' => 'fieldset',
215
          '#title' => t('Default settings'),
216
          '#group' => 'additional_settings',
217
          '#weight' => -20,
218
        );
219
        $form['default_settings']['default_content_settings'] = array(
220
          '#title' => t('Use the same allowed content as standard Panels pages?'),
221
          '#type' => 'checkbox',
222
          '#default_value' => variable_get($form_state['build_info']['args'][0] . '_allowed_types_default', FALSE),
223
        );
224
        $form['default_settings']['default_layout_settings'] = array(
225
          '#title' => t('Use the same allowed  layouts as standard Panels pages?'),
226
          '#type' => 'checkbox',
227
          '#default_value' => variable_get($form_state['build_info']['args'][0] . '_allowed_layouts_default', FALSE),
228
        );
229
230
        // Disable the layout options when the default layout setting is enabled
231
        if (!empty($form['layout_selection']['layouts']) && variable_get($form_state['build_info']['args'][0] . '_allowed_layouts_default', FALSE)) {
232
          $form['layout_selection']['layouts']['#disabled'] = TRUE;
233
        }
234
235 e5e66f93 Assos Assos
        // Disable the content options when the default content setting is
236
        // enabled.
237 85ad3d82 Assos Assos
        if (variable_get($form_state['build_info']['args'][0] . '_allowed_types_default', FALSE)) {
238
          $content_types = ctools_content_get_all_types();
239
          $content_types['other'] = array('title' => t('Other'), 'weight' => 10);
240 e5e66f93 Assos Assos
          foreach ($content_types as $content_type => $content_type_value) {
241 85ad3d82 Assos Assos
            if (!empty($form['content_types'][$content_type]['options'])) {
242
              $form['content_types'][$content_type]['options']['#disabled'] = TRUE;
243
            }
244
          }
245
          $form['common']['panels_common_default']['#disabled'] = TRUE;
246
        }
247
248
        $form['#submit'][] = 'panelizer_panels_default_settings_submit';
249
      }
250
    }
251
  }
252
}
253
254
/**
255 e5e66f93 Assos Assos
 * Custom submission handler for setting default content and layout settings.
256 85ad3d82 Assos Assos
 */
257
function panelizer_panels_default_settings_submit($form, &$form_state) {
258
  variable_set($form_state['values']['module_name'] . '_allowed_types_default', $form_state['values']['default_content_settings']);
259
  variable_set($form_state['values']['module_name'] . '_allowed_layouts_default', $form_state['values']['default_layout_settings']);
260
}
261
262
/**
263 e5e66f93 Assos Assos
 * Implements hook_process_page().
264 85ad3d82 Assos Assos
 */
265 e5e66f93 Assos Assos
function panelizer_process_page(&$variables) {
266 85ad3d82 Assos Assos
  // Delegate.
267 e5e66f93 Assos Assos
  // Target the theme layer to ensure we can manipulate the overview table.
268 85ad3d82 Assos Assos
  foreach (panelizer_get_plugins_with_hook('page_alter') as $handler) {
269 e5e66f93 Assos Assos
    $handler->hook_page_alter($variables['page']);
270 85ad3d82 Assos Assos
  }
271
}
272
273
/**
274
 * Implements hook_entity_load().
275
 */
276
function panelizer_entity_load(&$entities, $entity_type) {
277
  // Delegate to the handler.
278
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
279
    $handler->hook_entity_load($entities);
280
  }
281
}
282
283
/**
284
 * Implements hook_entity_update().
285
 */
286
function panelizer_entity_update($entity, $entity_type) {
287
  // Delegate to the handler.
288
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
289
    $handler->hook_entity_update($entity);
290
  }
291
}
292
293
/**
294
 * Implements hook_entity_insert().
295
 */
296
function panelizer_entity_insert($entity, $entity_type) {
297
  // Delegate to the handler.
298
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
299
    $handler->hook_entity_insert($entity);
300
  }
301
}
302
303
/**
304
 * Implements hook_entity_delete().
305
 */
306
function panelizer_entity_delete($entity, $entity_type) {
307
  // Delegate to the handler.
308
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
309
    $handler->hook_entity_delete($entity);
310
  }
311
}
312
313
/**
314
 * Implements hook_field_attach_delete_revision().
315
 */
316
function panelizer_field_attach_delete_revision($entity_type, $entity) {
317
  // Delegate to the handler.
318
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
319
    $handler->hook_field_attach_delete_revision($entity);
320
  }
321
}
322
323
function panelizer_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
324
  // Delegate to the handler.
325
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
326
    $handler->hook_field_attach_form($entity, $form, $form_state, $langcode);
327
  }
328
}
329
330
function panelizer_field_attach_submit($entity_type, $entity, &$form, &$form_state) {
331
  // Delegate to the handler.
332
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
333
    $handler->hook_field_attach_submit($entity, $form, $form_state);
334
  }
335
}
336
337
/**
338
 * Implements hook_entity_view_alter().
339
 */
340
function panelizer_entity_view_alter(&$build, $entity_type) {
341
  static $recursion_prevention = array();
342
  // Prepare variables.
343
  $handler = panelizer_entity_plugin_get_handler($entity_type);
344
  if (!$handler) {
345
    return;
346
  }
347
348
  $entity = $handler->get_entity_view_entity($build);
349
350 e5e66f93 Assos Assos
  // Safety check in case the entity can't be loaded.
351 85ad3d82 Assos Assos
  if (!$entity) {
352
    return;
353
  }
354
355
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
356
357 e5e66f93 Assos Assos
  // If the requested view mode does not exist, check if a substitute is
358
  // assigned, otherwise rendering will fall back to 'default' and we should
359
  // check that one instead.
360
  $view_mode = $handler->get_view_mode($build['#view_mode'], $bundle);
361 85ad3d82 Assos Assos
362
  // Make sure the bundle + view mode is actually panelized!
363
  if (!$handler->is_panelized($bundle . '.' . $view_mode)) {
364
    return;
365
  }
366
367 e5e66f93 Assos Assos
  // Also verify that the configuration exists. This may happen if a display is
368
  // improperly configured.
369
  if (empty($entity->panelizer[$view_mode])) {
370
    return;
371
  }
372
373 85ad3d82 Assos Assos
  if (!empty($recursion_prevention[$entity_type][$entity_id][$view_mode])) {
374
    return;
375
  }
376
377
  $recursion_prevention[$entity_type][$entity_id][$view_mode] = TRUE;
378
379
  if ($info = $handler->render_entity($entity, $view_mode)) {
380
    // Change theming function and add the content on the $build array.
381
    $build['#theme'] = 'panelizer_view_mode';
382
    $build['#panelizer'] = $entity->panelizer[$view_mode];
383
    $build['#panelizer_content'] = $info;
384
    $build['#panelizer_handler'] = $handler;
385
    $build['#panelizer_entity'] = $entity;
386
    $build['#panelizer_bundle'] = $bundle;
387
    $build['#panelizer_entity_id'] = $entity_id;
388
  }
389
  $recursion_prevention[$entity_type][$entity_id][$view_mode] = FALSE;
390 e5e66f93 Assos Assos
}
391 85ad3d82 Assos Assos
392 e5e66f93 Assos Assos
/**
393
 * Implements hook_node_update_index().
394
 */
395
function panelizer_node_update_index($node) {
396
  // Populate search index for nodes managed via Panelizer if 'search_index'
397
  // view mode is configured to do so.
398
  if (
399
    ($handler = panelizer_entity_plugin_get_handler('node'))
400
    && ($view_mode = $handler->get_view_mode('search_index', $node->type))
401
    && $handler->is_panelized($node->type . '.' . $view_mode)
402
    && !empty($node->panelizer[$view_mode])
403
    && ($info = $handler->render_entity($node, $view_mode))
404
  ) {
405
    $build['#view_mode'] = $view_mode;
406
    $build['#theme'] = 'panelizer_view_mode';
407
    $build['#panelizer'] = $node->panelizer[$view_mode];
408
    $build['#panelizer_content'] = $info;
409
    $build['#panelizer_handler'] = $handler;
410
    $build['#panelizer_entity'] = $node;
411
    $build['#panelizer_bundle'] = $node->type;
412
    $build['#panelizer_entity_id'] = $node->nid;
413
    return drupal_render($build);
414
  }
415
}
416
417
/**
418
 * Implements hook_node_search_result().
419
 */
420
function panelizer_node_search_result($node) {
421
  // Populate search result highlighting input for nodes managed via Panelizer
422
  // if 'search_result' view mode is configured to do so.
423
  if (
424
    ($handler = panelizer_entity_plugin_get_handler('node'))
425
    && ($view_mode = $handler->get_view_mode('search_result', $node->type))
426
    && $handler->is_panelized($node->type . '.' . $view_mode)
427
    && !empty($node->panelizer[$view_mode])
428
    && ($info = $handler->render_entity($node, $view_mode))
429
  ) {
430
    $build['#view_mode'] = $view_mode;
431
    $build['#theme'] = 'panelizer_view_mode';
432
    $build['#panelizer'] = $node->panelizer[$view_mode];
433
    $build['#panelizer_content'] = $info;
434
    $build['#panelizer_handler'] = $handler;
435
    $build['#panelizer_entity'] = $node;
436
    $build['#panelizer_bundle'] = $node->type;
437
    $build['#panelizer_entity_id'] = $node->nid;
438
    $node->rendered .= drupal_render($build);
439
  }
440 85ad3d82 Assos Assos
}
441
442
// -----------------------------------------------------------------------
443
// Panels and CTools hooks
444
445
/**
446 e5e66f93 Assos Assos
 * Implements hook_ctools_plugin_type().
447 85ad3d82 Assos Assos
 */
448
function panelizer_ctools_plugin_type() {
449
  $items['entity'] = array(
450
    'cache' => FALSE,
451
    'process' => array(
452
      'function' => 'panelizer_entity_plugin_process',
453
    ),
454
    'classes' => array('handler'),
455
  );
456
457
  return $items;
458
}
459
460
/**
461 e5e66f93 Assos Assos
 * Implements hook_ctools_plugin_directory().
462 85ad3d82 Assos Assos
 */
463
function panelizer_ctools_plugin_directory($module, $plugin) {
464
  if (in_array($module, array('panelizer', 'ctools', 'page_manager'))) {
465
    return 'plugins/' . $plugin;
466
  }
467 136a805a Assos Assos
  if ($module == 'panels' && $plugin == 'panels_storage') {
468
    return 'plugins/' . $plugin;
469
  }
470 85ad3d82 Assos Assos
}
471
472
/**
473
 * Implements hook_ctools_plugin_api().
474
 */
475
function panelizer_ctools_plugin_api($module, $api) {
476
  if (($module == 'page_manager' && $api == 'pages_default') || $module == 'panelizer') {
477
    return array(
478
      'version' => 1,
479
      'path' => drupal_get_path('module', 'panelizer') . '/includes',
480
    );
481
  }
482
}
483
484
/**
485
 * Implements hook_features_api().
486
 */
487
function panelizer_features_api() {
488
  $api = array();
489
  if (function_exists('_ctools_features_get_info') && defined('FEATURES_ALTER_TYPE_NONE')) {
490
    $api['panelizer_defaults'] = _ctools_features_get_info('panelizer_defaults');
491
    // CTools calls our hook_panelizer_defaults_alter so prevent Features from
492
    // calling it too. FEATURES_ALTER_TYPE_INLINE means we are handling alter
493
    // hooks ourselves here.
494
    $api['panelizer_defaults']['alter_type'] = FEATURES_ALTER_TYPE_INLINE;
495
    // Provide a separate alter hook for features_override.
496
    $api['panelizer_defaults']['alter_hook'] = 'panelizer_defaults_override';
497
  }
498
499
  return $api;
500
}
501
502
/**
503
 * Implementation of hook_views_api().
504
 */
505
function panelizer_views_api() {
506
  return array(
507
    'api' => 2.0,
508
    'path' => drupal_get_path('module', 'panelizer') . '/plugins/views',
509
  );
510
}
511
512
/**
513
 * Implements hook_panelizer_defaults_alter().
514
 */
515
function panelizer_panelizer_defaults_alter(&$items) {
516
  // Delegate.
517
  foreach (panelizer_get_plugins_with_hook('panelizer_defaults') as $handler) {
518
    $handler->hook_panelizer_defaults($items);
519
  }
520
521 2545992a Assos Assos
  // If a default Panels display has no storage type, set it.
522
  foreach ($items as &$panelizer) {
523
    $display =& $panelizer->display;
524
    if (empty($display->storage_type)) {
525
      $display->storage_type = 'panelizer_default';
526
      $display->storage_id = $panelizer->name;
527
    }
528
  }
529
530 85ad3d82 Assos Assos
  // Allow features_overrides to alter the config.
531
  drupal_alter('panelizer_defaults_override', $items);
532
}
533
534
/**
535
 * Implements hook_default_page_manager_handlers().
536
 */
537
function panelizer_default_page_manager_handlers() {
538
  $items = array();
539
  // Delegate.
540
  foreach (panelizer_get_plugins_with_hook('default_page_manager_handlers') as $handler) {
541
    $handler->hook_default_page_manager_handlers($items);
542
  }
543
544
  return $items;
545
}
546
547
/**
548
 * Implement CTools access form caching callback: get.
549
 */
550
function panelizer_ctools_access_get($argument) {
551
  list($entity_type, $bundle, $name) = explode(':', $argument);
552
  $handler = panelizer_entity_plugin_get_handler($entity_type);
553
  $panelizer = $handler->get_default_panelizer_object($bundle, $name);
554
555
  if (empty($panelizer)) {
556
    return;
557
  }
558
559
  if (!$handler->access_default_panelizer_object($panelizer)) {
560
    return;
561
  }
562
563 e5e66f93 Assos Assos
  // First, see if there's a cache.
564 85ad3d82 Assos Assos
  ctools_include('object-cache');
565
  $access = ctools_object_cache_get('panelizer_access', $argument);
566
  if (!$access) {
567
    $access = $panelizer->access;
568
  }
569
570
  $context = $handler->get_contexts($panelizer);
571
572
  return array($access, $context);
573
}
574
575
/**
576
 * Implement CTools access form caching callback: set.
577
 */
578
function panelizer_ctools_access_set($argument, $access) {
579
  list($entity_type, $bundle, $name) = explode(':', $argument);
580
  $handler = panelizer_entity_plugin_get_handler($entity_type);
581
  $panelizer = $handler->get_default_panelizer_object($bundle, $name);
582
583
  if (empty($panelizer)) {
584
    return;
585
  }
586
587
  if (!$handler->access_default_panelizer_object($panelizer)) {
588
    return;
589
  }
590
591
  ctools_include('object-cache');
592
  ctools_object_cache_set('panelizer_access', $argument, $access);
593
}
594
595
/**
596
 * Implement CTools access form caching callback: get.
597
 */
598
function panelizer_ctools_access_clear($argument) {
599
  list($entity_type, $bundle, $name) = explode(':', $argument);
600
  $handler = panelizer_entity_plugin_get_handler($entity_type);
601
  $panelizer = $handler->get_default_panelizer_object($bundle, $name);
602
603
  if (empty($panelizer)) {
604
    return;
605
  }
606
607
  if (!$handler->access_default_panelizer_object($panelizer)) {
608
    return;
609
  }
610
611
  ctools_include('object-cache');
612
  ctools_object_cache_clear('panelizer', $argument);
613
}
614
615
// -----------------------------------------------------------------------
616 e5e66f93 Assos Assos
// CTools entity plugin support code.
617 85ad3d82 Assos Assos
618
/**
619
 * CTools process callback for an entity plugin.
620
 *
621 e5e66f93 Assos Assos
 * This adds configuration data to the plugin so that we know what bundles it is
622
 * enabled for.
623 85ad3d82 Assos Assos
 */
624
function panelizer_entity_plugin_process(&$plugin, $info) {
625
  $entity_type = $plugin['name'];
626
  $entity_info = entity_get_info($entity_type);
627
  $plugin['bundles'] = array();
628
  if ($entity_info) {
629
    foreach ($entity_info['bundles'] as $bundle => $label) {
630
      if ($settings = variable_get('panelizer_defaults_' . $entity_type . '_' . $bundle, array())) {
631 e5e66f93 Assos Assos
        // Translate from settings that existed prior to view mode support.
632 85ad3d82 Assos Assos
        if (empty($settings['view modes'])) {
633
          $old_settings = $settings;
634
          $settings = array('view modes' => array());
635
          if (empty($plugin['uses page manager'])) {
636
            $settings['view modes']['default'] = $old_settings;
637
          }
638
          else {
639
            $settings['view modes']['page_manager'] = $old_settings;
640
          }
641
          $settings['status'] = $old_settings['status'];
642
        }
643
        $plugin['bundles'][$bundle] = $settings;
644
645
        // Build the custom settings of the view modes for this bundle.
646
        $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
647
        foreach ($entity_info['view modes'] as $view_mode_name => $view_mode_info) {
648
          $plugin['view mode status'][$bundle][$view_mode_name] = !empty($view_mode_settings[$view_mode_name]['custom_settings']);
649
        }
650
      }
651
    }
652
653
    // Add our fake view modes.
654
    $plugin['view modes'] = array(
655
      'page_manager' => array(
656
        'label' => t('Full page override'),
657
      ),
658
      'default' => array(
659
        'label' => t('Default'),
660
      ),
661
    );
662
663
    if (!empty($entity_info['view modes'])) {
664
      foreach ($entity_info['view modes'] as $view_mode => $view_mode_info) {
665
        $plugin['view modes'][$view_mode] = $view_mode_info;
666
      }
667
    }
668
669
    // It seems silly to unset this after but the logic is cleaner to read.
670
    if (empty($plugin['uses page manager'])) {
671
      unset($plugin['view modes']['page_manager']);
672
    }
673
  }
674
675
  drupal_alter('panelizer_entity_plugin_process', $plugin, $info);
676
}
677
678
/**
679
 * Fetch a single entity plugin.
680
 */
681
function panelizer_get_entity_plugin($entity_type) {
682
  ctools_include('plugins');
683
  return ctools_get_plugins('panelizer', 'entity', $entity_type);
684
}
685
686
/**
687
 * Fetch all entity plugin.
688
 */
689
function panelizer_get_entity_plugins() {
690
  ctools_include('plugins');
691
  return ctools_get_plugins('panelizer', 'entity');
692
}
693
694
/**
695
 * Get the class to handle custom code for a given entity type plugin.
696
 *
697 e5e66f93 Assos Assos
 * If a plugin does not define a class at all, then the default class.
698 85ad3d82 Assos Assos
 *
699
 * @return
700
 *   Either the instantiated handler or FALSE if one could not be had.
701
 */
702
function panelizer_entity_plugin_get_handler($plugin) {
703
  // The default plugin handler is abstract and cannot be loaded.
704
  if ($plugin == 'default') {
705
    return;
706
  }
707
708
  $cache = &drupal_static(__FUNCTION__, array());
709
710
  // If a string was passed, turn it into a plugin.
711
  if (is_string($plugin)) {
712
    $plugin = panelizer_get_entity_plugin($plugin);
713
    if (!$plugin) {
714
      return FALSE;
715
    }
716
  }
717
718
  // Get the class name from the 'handler' property if we have not already
719
  // cached a handler.
720
  if (empty($cache[$plugin['name']]) && ($class = ctools_plugin_get_class($plugin, 'handler'))) {
721
    // @todo is there a good reason to use ->init instead of __construct?
722
    $cache[$plugin['name']] = new $class();
723
    $cache[$plugin['name']]->init($plugin);
724
  }
725
  return !empty($cache[$plugin['name']]) ? $cache[$plugin['name']] : FALSE;
726
}
727
728
/**
729
 * Load handler to get a plugin as a menu callback.
730
 */
731
function panelizer_handler_load($entity_type) {
732
  return panelizer_entity_plugin_get_handler($entity_type);
733
}
734
735
/**
736
 * Fetch handler objects for all plugins that implement the named hook.
737
 *
738 e5e66f93 Assos Assos
 * These plugins must set $plugin['hooks'][$hook] = TRUE in order to be
739
 * instantiated.
740 85ad3d82 Assos Assos
 *
741
 * This is only called for system wide hooks such as hook_menu and
742
 * hook_menu_alter; entity specific hooks will always be called.
743
 */
744
function panelizer_get_plugins_with_hook($hook) {
745
  $objects = array();
746
  $plugins = panelizer_get_entity_plugins();
747
  foreach ($plugins as $entity_type => $plugin) {
748
    if (!empty($plugin['hooks'][$hook])) {
749
      if ($handler = panelizer_entity_plugin_get_handler($plugin)) {
750
        $objects[$entity_type] = $handler;
751
      }
752
    }
753
  }
754
755
  return $objects;
756
}
757
758
/**
759
 * Page callback for entity menu callbacks.
760
 *
761 e5e66f93 Assos Assos
 * This function is to be used as a menu callback for menu items that are to be
762
 * handled by a method on the handler object. It loads the object defined in the
763
 * plugin and hands it off to a method based upon the name of the operation in
764
 * use.
765 85ad3d82 Assos Assos
 *
766
 * For example, if the 'op' is 'revision' then the callback method will be
767 e5e66f93 Assos Assos
 * 'page_revisions', with all of the arguments *except* the $op and the plugin
768
 * name.
769 85ad3d82 Assos Assos
 */
770
function panelizer_entity_plugin_switcher_page($entity_type, $op) {
771
  $args = func_get_args();
772
773 e5e66f93 Assos Assos
  // Load the $plugin information.
774 85ad3d82 Assos Assos
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
775 e5e66f93 Assos Assos
    // Replace the first two arguments.
776
    $args[0] = !empty($_REQUEST['js']);
777 85ad3d82 Assos Assos
    $args[1] = $_POST;
778 e5e66f93 Assos Assos
    if (empty($args[3])) {
779
      $args[3] = 'page_manager';
780
    }
781 85ad3d82 Assos Assos
    $method = 'page_' . $op;
782
    if (method_exists($handler, $method)) {
783
      return call_user_func_array(array($handler, $method), $args);
784
    }
785 e5e66f93 Assos Assos
    // Check to see if this is an operation from panelizer_operations with a
786
    // callback instead.
787 85ad3d82 Assos Assos
    $operations = panelizer_operations();
788
    if (isset($operations[$op]) && isset($operations[$op]['entity callback']) && function_exists($operations[$op]['entity callback'])) {
789
      array_unshift($args, $handler);
790
      return call_user_func_array($operations[$op]['entity callback'], $args);
791
    }
792
  }
793
  else {
794
    return t('Configuration error. No handler found.');
795
  }
796
}
797
798
/**
799
 * Callback used for switching callbacks into the proper plugin.
800
 */
801
function panelizer_entity_plugin_callback_switcher($entity_type, $switcher_type, $op) {
802
  $args = func_get_args();
803
  if (count($args) < 3) {
804
    return FALSE;
805
  }
806
  $entity_type = array_shift($args);
807
  $switcher_type = array_shift($args);
808
  $op = array_shift($args);
809
810 e5e66f93 Assos Assos
  // Load the $plugin information.
811 85ad3d82 Assos Assos
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
812
    $method = $switcher_type . '_' . $op;
813
    if (method_exists($handler, $method)) {
814
      return call_user_func_array(array($handler, $method), $args);
815
    }
816
  }
817
  else {
818
    return FALSE;
819
  }
820
}
821
822
/**
823
 * Page callback to delegate to either the settings page or list page.
824
 */
825
function panelizer_default_list_or_settings_page($handler, $bundle, $name, $view_mode, $operation = 'list', $item = NULL) {
826
  if (is_string($handler)) {
827
    $handler = panelizer_entity_plugin_get_handler($handler);
828
  }
829
830
  // We need a version of $bundle with $view_mode but we need to retain one
831
  // without it so we can pass straight $bundle to the settings page.
832
  $test_bundle = $bundle;
833
  if ($view_mode) {
834
    $test_bundle .= '.' . $view_mode;
835
  }
836
837
  if ($handler->has_panel_choice($test_bundle)) {
838 e5e66f93 Assos Assos
    // Call through to the UI switcher for the list.
839 85ad3d82 Assos Assos
    ctools_include('export-ui');
840
    return panelizer_export_ui_switcher_page($handler, $test_bundle, 'panelizer_defaults', $operation, $item);
841
  }
842
  else {
843
    return panelizer_default_settings_page($handler, $bundle, $name, $view_mode);
844
  }
845
}
846
847
/**
848 e5e66f93 Assos Assos
 * Specialized version of ctools_export_ui_switcher_page().
849 85ad3d82 Assos Assos
 *
850 e5e66f93 Assos Assos
 * This one is designed to set our entity handler and bundle on the object so we
851
 * can refer to it later without having to override all of the entry points.
852 85ad3d82 Assos Assos
 */
853
function panelizer_export_ui_switcher_page($entity_handler, $bundle, $plugin_name, $op) {
854
  $args = func_get_args();
855
856
  // Remove the handler and the bundle.
857
  array_shift($args);
858
  array_shift($args);
859
  $js = !empty($_REQUEST['js']);
860
861
  // Break our bundle up as necessary.
862
  if (strpos($bundle, '.') !== FALSE) {
863
    list($bundle, $view_mode) = explode('.', $bundle);
864
  }
865
  else {
866
    $view_mode = 'page_manager';
867
  }
868
869 e5e66f93 Assos Assos
  // Load the $plugin information.
870
  ctools_include('export-ui');
871 85ad3d82 Assos Assos
  $plugin = ctools_get_export_ui($plugin_name);
872
  $handler = ctools_export_ui_get_handler($plugin);
873
874
  if ($handler) {
875
    if (is_string($entity_handler)) {
876
      $entity_handler = panelizer_entity_plugin_get_handler($entity_handler);
877
    }
878
879
    $handler->entity_handler = $entity_handler;
880
    $handler->entity_bundle = $bundle;
881
    $handler->entity_view_mode = $view_mode;
882
883 e5e66f93 Assos Assos
    if (empty($entity_handler->entity_admin_root) || substr($_GET['q'], 30) == 'admin/structure/panelizer') {
884
      $handler->plugin['menu']['menu prefix'] = 'admin/structure/panelizer' . $entity_handler->entity_type;
885 85ad3d82 Assos Assos
      $handler->plugin['menu']['menu item'] = $bundle;
886
    }
887
    else {
888
      $base_path = $entity_handler->entity_admin_root . '/panelizer/' . $view_mode;
889
      if (is_numeric($entity_handler->entity_admin_bundle)) {
890
        $bits = explode('/', $base_path);
891
        $bits[$entity_handler->entity_admin_bundle] = $bundle;
892
        $base_path = implode('/', $bits);
893
      }
894
      $handler->plugin['menu']['menu prefix'] = dirname($base_path);
895
      $handler->plugin['menu']['menu item'] = basename($base_path);
896
      foreach ($handler->plugin['menu']['items'] as $key => &$item) {
897
        $item['path'] = str_replace('list/', '', $item['path']);
898
      }
899
    }
900
901
    $path = $handler->plugin['menu']['menu prefix'] . '/' . $handler->plugin['menu']['menu item'];
902
903
    foreach ($handler->plugin['redirect'] as $key => $old_path) {
904
      if ($key == 'add') {
905 e5e66f93 Assos Assos
        $handler->plugin['redirect'][$key] = $path . '/%ctools_export_ui/settings';
906 85ad3d82 Assos Assos
      }
907
      else {
908 e5e66f93 Assos Assos
        $handler->plugin['redirect'][$key] = $path;
909 85ad3d82 Assos Assos
      }
910
    }
911
912
    $method = $op . '_page';
913
    if (method_exists($handler, $method)) {
914 e5e66f93 Assos Assos
      // Replace the first two arguments.
915 85ad3d82 Assos Assos
      $args[0] = $js;
916
      $args[1] = $_POST;
917
      return call_user_func_array(array($handler, $method), $args);
918
    }
919
  }
920
  else {
921
    return t('Configuration error. No handler found.');
922
  }
923
}
924
925
// ---------------------------------------------------------------------------
926
// Menu callbacks
927
928
/**
929
 * Title callback to properly set the tile when editing panelizer defaults.
930
 */
931
function panelizer_default_title_callback($handler, $bundle) {
932
  if (is_string($handler)) {
933
    $handler = panelizer_entity_plugin_get_handler($handler);
934
  }
935
936
  if (!$handler) {
937
    return '';
938
  }
939
940
  $entity_info = entity_get_info($handler->entity_type);
941
942
  $title = $entity_info['label'];
943
944
  if (strpos($bundle, '.') === FALSE) {
945
    $bundle = $bundle;
946
    $view_mode = '';
947
  }
948
  else {
949
    list($bundle, $view_mode) = explode('.', $bundle);
950
  }
951
952
  $title .= ' | ' . $handler->get_bundle_title($bundle);
953
954
  if ($view_mode && !empty($handler->plugin['view modes'][$view_mode]['label'])) {
955
    $title .= ' | ' . $handler->plugin['view modes'][$view_mode]['label'];
956
  }
957
958
  return $title;
959
}
960
961
/**
962
 * Menu callback to determine if a type has a choice of defaults.
963
 *
964
 * We use this to make sure the right tabs appear.
965
 */
966
function panelizer_has_choice_callback($handler, $bundle, $name = NULL) {
967
  if (is_string($handler)) {
968
    $handler = panelizer_entity_plugin_get_handler($handler);
969
  }
970
971 e5e66f93 Assos Assos
  if (empty($handler)) {
972 85ad3d82 Assos Assos
    return FALSE;
973
  }
974
975
  if (!panelizer_administer_entity_bundle($handler, $bundle)) {
976
    return FALSE;
977
  }
978
979 e5e66f93 Assos Assos
  // Check to see if $name is valid.
980
  if (!empty($name) && !$handler->get_default_panelizer_object($bundle, $name)) {
981 85ad3d82 Assos Assos
    return FALSE;
982
  }
983
984
  return $handler->has_panel_choice($bundle);
985
}
986
987
/**
988 e5e66f93 Assos Assos
 * Menu callback to determine if a type+view_mode has a choice of defaults.
989 85ad3d82 Assos Assos
 */
990
function panelizer_has_choice_callback_view_mode($handler, $bundle, $view_mode) {
991
  return panelizer_has_choice_callback($handler, $bundle . '.' . $view_mode);
992
}
993
994
/**
995
 * Menu callback to determine if a type has a choice of defaults.
996
 *
997 e5e66f93 Assos Assos
 * Use to make sure the right tabs appear.
998 85ad3d82 Assos Assos
 */
999
function panelizer_has_no_choice_callback($handler, $bundle, $view_mode = NULL) {
1000
  if (is_string($handler)) {
1001
    $handler = panelizer_entity_plugin_get_handler($handler);
1002
  }
1003
1004 e5e66f93 Assos Assos
  if (empty($handler)) {
1005 85ad3d82 Assos Assos
    return FALSE;
1006
  }
1007
1008 e5e66f93 Assos Assos
  if (!empty($view_mode)) {
1009 85ad3d82 Assos Assos
    $bundle .= '.' . $view_mode;
1010
  }
1011
1012
  if (!panelizer_administer_entity_bundle($handler, $bundle)) {
1013
    return FALSE;
1014
  }
1015
1016 e5e66f93 Assos Assos
  return !$handler->has_panel_choice($bundle);
1017 85ad3d82 Assos Assos
}
1018
1019
/**
1020
 * Menu callback to determine if a type has a choice of defaults.
1021
 *
1022 e5e66f93 Assos Assos
 * Used to make sure the right tabs appear.
1023 85ad3d82 Assos Assos
 */
1024
function panelizer_is_panelized($handler, $bundle, $view_mode = NULL) {
1025
  if (is_string($handler)) {
1026
    $handler = panelizer_entity_plugin_get_handler($handler);
1027
  }
1028
1029
  if (!$handler) {
1030
    return FALSE;
1031
  }
1032
1033
  if ($view_mode) {
1034
    $bundle .= '.' . $view_mode;
1035
  }
1036
1037
  if (!panelizer_administer_entity_bundle($handler, $bundle)) {
1038
    return FALSE;
1039
  }
1040
1041
  return $handler->is_panelized($bundle);
1042
}
1043
1044
/**
1045
 * Access callback to see if a user can administer a particular bundle.
1046
 */
1047
function panelizer_administer_entity_bundle($handler, $bundle) {
1048
  if (is_string($handler)) {
1049
    $handler = panelizer_entity_plugin_get_handler($handler);
1050
  }
1051
1052 e5e66f93 Assos Assos
  // Adjust for the presence of a view mode.
1053 85ad3d82 Assos Assos
  if (strpos($bundle, '.') !== FALSE) {
1054
    list($bundle, $view_mode) = explode('.', $bundle);
1055
  }
1056
1057
  return user_access('administer panelizer') || user_access("administer panelizer $handler->entity_type $bundle defaults");
1058
}
1059
1060
/**
1061 e5e66f93 Assos Assos
 * Access callback to see if a user can administer a particular default.
1062 85ad3d82 Assos Assos
 */
1063
function panelizer_administer_panelizer_default($handler, $bundle, $name, $view_mode = NULL) {
1064
  if (is_string($handler)) {
1065
    $handler = panelizer_entity_plugin_get_handler($handler);
1066
  }
1067
1068
  if ($view_mode) {
1069
    $bundle .= '.' . $view_mode;
1070
  }
1071
1072
  $panelizer = $handler->get_default_panelizer_object($bundle, $name);
1073
  if (!$panelizer) {
1074
    return FALSE;
1075
  }
1076
1077
  return $handler->access_default_panelizer_object($panelizer);
1078
}
1079
1080
/**
1081
 * Menu load callback to scrub a node bundle from the URL safe equivalent.
1082
 */
1083
function panelizer_node_type_load($name) {
1084
  if ($type = node_type_get_type(strtr($name, array('-' => '_')))) {
1085
    return $type->type;
1086
  }
1087
}
1088
1089
// ---------------------------------------------------------------------------
1090 e5e66f93 Assos Assos
// export.inc callbacks to handle proper in/out of our defaults.
1091 85ad3d82 Assos Assos
1092
/**
1093
 * export.inc callback to properly save a panelizer default.
1094
 */
1095
function panelizer_export_save_callback(&$object) {
1096
  if (!empty($object->display)) {
1097 136a805a Assos Assos
    $object->display->storage_id = $object->name;
1098 e5e66f93 Assos Assos
    // First write the display.
1099 85ad3d82 Assos Assos
    panels_save_display($object->display);
1100
1101
    // Make sure we have the did.
1102
    $object->did = $object->display->did;
1103
  }
1104
1105
  // Then write the default
1106
  if ($object->export_type & EXPORT_IN_DATABASE) {
1107
    // Existing record.
1108
    $update = array('pnid');
1109
  }
1110
  else {
1111
    // New record.
1112
    $update = array();
1113
    $object->export_type = EXPORT_IN_DATABASE;
1114
  }
1115
1116 e5e66f93 Assos Assos
  // Reset the entity's cache. If the EntityCache module is enabled, this also
1117
  // resets its permanent cache.
1118
  list($entity_type, ) = explode(':', $object->name);
1119
  entity_get_controller($entity_type)->resetCache();
1120
1121 85ad3d82 Assos Assos
  return drupal_write_record('panelizer_defaults', $object, $update);
1122
}
1123
1124
/**
1125
 * export.inc callback to properly export a panelizer default.
1126
 */
1127
function panelizer_export_export_callback($object, $indent) {
1128
  $object->did = NULL;
1129
  $output = ctools_export_object('panelizer_defaults', $object, $indent);
1130
  $output .= panels_export_display($object->display, $indent);
1131
  $output .= $indent . '$panelizer->display = $display;' . "\n";
1132
1133
  return $output;
1134
}
1135
1136
/**
1137
 * export.inc callback to properly delete a panelizer default.
1138
 */
1139
function panelizer_export_delete_callback($object) {
1140
  if (!empty($object->did)) {
1141
    panels_delete_display($object->did);
1142
  }
1143
1144 e5e66f93 Assos Assos
  // Allow modules to react on a default Panelizer object before deletion.
1145
  // Triggers hook_panelizer_delete_default().
1146
  module_invoke_all('panelizer_delete_default', $object);
1147
1148 85ad3d82 Assos Assos
  db_delete('panelizer_defaults')
1149
    ->condition('name', $object->name)
1150
    ->execute();
1151
}
1152
1153
/**
1154
 * export.inc callback to delete sub records for an object.
1155
 */
1156
function panelizer_export_delete_callback_subrecords($objects) {
1157
  $dids = array();
1158
  foreach ($objects as $panelizer) {
1159
    if (!empty($panelizer->did)) {
1160
      $dids[$panelizer->did] = $panelizer->did;
1161
    }
1162
  }
1163
1164
  if ($dids) {
1165
    $displays = panels_load_displays($dids);
1166
    foreach ($objects as $panelizer) {
1167
      if (!empty($panelizer->did) && !empty($displays[$panelizer->did])) {
1168
        $panelizer->display = $displays[$panelizer->did];
1169
      }
1170
    }
1171
  }
1172
}
1173
1174
// ---------------------------------------------------------------------------
1175
// Context cache callbacks -- this really needs a less lame system someday.
1176
1177
/**
1178
 * Fetch the panelizer object from the object cache.
1179
 *
1180 e5e66f93 Assos Assos
 * CTools clumsy context editing system requires caching. This lets us do it
1181
 * reasonably.
1182 85ad3d82 Assos Assos
 *
1183
 * @param $entity_type
1184
 *   Can be something like 'node' or 'user' or 'default'.
1185
 * @param $key
1186
 *   Depends on the $entity_type. Can be a nid, a uid or a default key.
1187
 */
1188
function panelizer_context_cache_get($entity_type, $key) {
1189
  ctools_include('object-cache');
1190
  $cache = ctools_object_cache_get('panelizer_context_cache', $entity_type . ':' . $key);
1191
  if (!empty($cache)) {
1192
    $cache->cached = TRUE;
1193
    return $cache;
1194
  }
1195
1196
  if ($entity_type == 'default') {
1197
    list($entity_type, $bundle, $name) = @explode(':', $key, 3);
1198
    $get_default = TRUE;
1199
  }
1200
1201
  if ($handler = panelizer_entity_plugin_get_handler($entity_type)) {
1202
    if (!empty($get_default)) {
1203
      $panelizer = $handler->get_default_panelizer_object($bundle, $name);
1204
      $panelizer->base_contexts = $handler->get_base_contexts();
1205
      return $panelizer;
1206
    }
1207
    else {
1208
      list($entity_id, $view_mode) = explode('.', $key);
1209
      $entities = entity_load($entity_type, array($entity_id));
1210
      if (!empty($entities[$entity_id]) && !empty($entities[$entity_id]->panelizer[$view_mode])) {
1211
        $panelizer = $entities[$entity_id]->panelizer[$view_mode];
1212
        $panelizer->base_contexts = $handler->get_base_contexts($entities[$entity_id]);
1213
        return $panelizer;
1214
      }
1215
    }
1216
  }
1217
}
1218
1219
/**
1220
 * Store the panelizer object in the object cache.
1221
 *
1222 e5e66f93 Assos Assos
 * CTools clumsy context editing system requires caching. This lets us do it
1223
 * reasonably.
1224 85ad3d82 Assos Assos
 *
1225
 * @param $entity_type
1226
 *   Can be something like 'node' or 'user' or 'default'.
1227
 * @param $key
1228
 *   Either the node type or the nid.
1229
 * @param $object
1230
 *   The cached object.
1231
 */
1232
function panelizer_context_cache_set($entity_type, $key, $object) {
1233
  ctools_include('object-cache');
1234
  ctools_object_cache_set('panelizer_context_cache', $entity_type . ':' . $key, $object);
1235
}
1236
1237
/**
1238
 * Clear the panelizer object in the object cache.
1239
 *
1240 e5e66f93 Assos Assos
 * CTools clumsy context editing system requires caching. This lets us do it
1241
 * reasonably.
1242 85ad3d82 Assos Assos
 *
1243
 * @param $entity_type
1244
 *   Can be something like 'node' or 'user' or 'default'.
1245
 * @param $key
1246
 *   Either the node type or the nid.
1247
 */
1248
function panelizer_context_cache_clear($entity_type, $key) {
1249
  ctools_include('object-cache');
1250
  ctools_object_cache_clear('panelizer_context_cache', $entity_type . ':' . $key);
1251
}
1252
1253
// --------------------------------------------------------------------------
1254
// Panels edit cache contexts.
1255
1256
/**
1257 e5e66f93 Assos Assos
 * Implements hook_panels_cache_get().
1258
 *
1259
 * Get display edit cache for a display being edited.
1260 85ad3d82 Assos Assos
 *
1261 e5e66f93 Assos Assos
 * The key is the second half of the key in this form: panelizer:TYPE:KEY
1262 85ad3d82 Assos Assos
 */
1263
function panelizer_panels_cache_get($argument) {
1264
  ctools_include('object-cache');
1265
  list($entity_type, $key) = explode(':', $argument, 2);
1266
  $cache = ctools_object_cache_get('panelizer_display_cache', $entity_type . ':' . $key);
1267
1268
  // Keep $type because $entity_type can be 'default' which is not actually an
1269
  // entity type in that case.
1270
  $type = $entity_type;
1271
  if ($entity_type == 'default') {
1272
    list($entity_type, $bundle, $name) = @explode(':', $key, 3);
1273
    $get_default = TRUE;
1274
  }
1275
1276
  $handler = panelizer_entity_plugin_get_handler($entity_type);
1277
  if (!$handler) {
1278
    return;
1279
  }
1280
1281 e5e66f93 Assos Assos
  // Extract the entity ID and view mode.
1282
  list($entity_id, $view_mode) = explode(':', $key, 2);
1283
  // If this entity supports revisions, and a custom revision is being
1284
  // displayed, it's possible for the key to also include the revision ID.
1285
  if ($handler->supports_revisions && strpos($view_mode, ':') !== FALSE) {
1286
    list($entity_id, $view_mode, $vid) = explode(':', $key);
1287
  }
1288
1289 85ad3d82 Assos Assos
  // If it's already cached, we still need to restore our contexts.
1290
  if (!empty($cache)) {
1291
    $cache->cached = TRUE;
1292
    if (!empty($get_default)) {
1293
      $panelizer = $handler->get_default_panelizer_object($bundle, $name);
1294
      $cache->display->context = $handler->get_contexts($panelizer);
1295 136a805a Assos Assos
1296
      // Set the storage_type and storage_id if either is empty.
1297
      if (empty($cache->display->storage_type)) {
1298
        $cache->display->storage_type = 'panelizer_default';
1299
      }
1300
      if (empty($cache->display->storage_id)) {
1301
        $cache->display->storage_id = $panelizer->name;
1302
      }
1303 85ad3d82 Assos Assos
    }
1304
    else {
1305 e5e66f93 Assos Assos
      $conditions = (isset($vid) ? array('vid' => $vid) : array());
1306
      $entities = entity_load($entity_type, array($entity_id), $conditions);
1307 85ad3d82 Assos Assos
      if (!empty($entities[$entity_id]) && !empty($entities[$entity_id]->panelizer[$view_mode])) {
1308
        $panelizer = $entities[$entity_id]->panelizer[$view_mode];
1309
        $cache->display->context = $handler->get_contexts($panelizer, $entities[$entity_id]);
1310
      }
1311
    }
1312
1313
    return $cache;
1314
  }
1315
1316
  $cache = new stdClass();
1317
1318
  // If it wasn't cached, create a new cache.
1319
  if (!empty($get_default)) {
1320
    $panelizer = $handler->get_default_panelizer_object($bundle, $name);
1321
    $cache->display = $panelizer->display;
1322
    $cache->display->context = $handler->get_contexts($panelizer);
1323 136a805a Assos Assos
    
1324
    // Set the storage_type and storage_id if either is empty.
1325
     if (empty($cache->display->storage_type)) {
1326
       $cache->display->storage_type = 'panelizer_default';
1327
     }
1328
     if (empty($cache->display->storage_id)) {
1329
       $cache->display->storage_id = $panelizer->name;
1330
     }
1331 85ad3d82 Assos Assos
  }
1332
  else {
1333 e5e66f93 Assos Assos
    $conditions = (isset($vid) ? array('vid' => $vid) : array());
1334
    $entities = entity_load($entity_type, array($entity_id), $conditions);
1335 85ad3d82 Assos Assos
    if (empty($entities[$entity_id]) || empty($entities[$entity_id]->panelizer[$view_mode])) {
1336
      return $cache;
1337
    }
1338
1339
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entities[$entity_id]);
1340
    $panelizer = $entities[$entity_id]->panelizer[$view_mode];
1341
    $cache->display = $panelizer->display;
1342
    $cache->display->context = $handler->get_contexts($panelizer, $entities[$entity_id]);
1343
  }
1344
1345
  ctools_include('common', 'panels');
1346
  ctools_include('plugins', 'panels');
1347
1348 e5e66f93 Assos Assos
  $cache_keys = array(
1349
    'panelizer',
1350
    $type,
1351
    $key,
1352
  );
1353
  if (isset($vid) && is_numeric($vid) && substr($key, strlen($vid) * -1) != $vid) {
1354
    $cache_keys[] = $vid;
1355
  }
1356
  $cache->display->cache_key = implode(':', $cache_keys);
1357
1358
  // Set the allowed content types.
1359 85ad3d82 Assos Assos
  if (variable_get('panelizer_' . $type . ':' . $bundle . '_allowed_types_default', FALSE)) {
1360
    $cache->content_types = panels_common_get_allowed_types('panels_page', $cache->display->context);
1361
  }
1362
  else {
1363
    $cache->content_types = panels_common_get_allowed_types('panelizer_' . $type . ':' . $bundle, $cache->display->context);
1364
  }
1365
1366 e5e66f93 Assos Assos
  // Set the allowed layout options.
1367
  $cache->display->allowed_layouts = panels_common_get_allowed_layouts(panelizer_get_allowed_layouts_option($type, $bundle));
1368 85ad3d82 Assos Assos
1369
  return $cache;
1370
}
1371
1372
/**
1373 e5e66f93 Assos Assos
 * Implements hook_panels_cache_set().
1374
 *
1375 85ad3d82 Assos Assos
 * Store a display edit in progress in the page cache.
1376
 */
1377
function panelizer_panels_cache_set($argument, $cache) {
1378
  ctools_include('object-cache');
1379 e5e66f93 Assos Assos
  ctools_object_cache_set('panelizer_display_cache', $argument, $cache);
1380 85ad3d82 Assos Assos
}
1381
1382
/**
1383 e5e66f93 Assos Assos
 * Implements hook_panels_cache_clear().
1384
 *
1385 85ad3d82 Assos Assos
 * Save all changes made to a display using the Page Manager page cache.
1386
 */
1387
function panelizer_panels_cache_clear($argument, $cache) {
1388
  ctools_include('object-cache');
1389 e5e66f93 Assos Assos
  ctools_object_cache_clear('panelizer_display_cache', $argument);
1390 85ad3d82 Assos Assos
}
1391
1392
/**
1393 e5e66f93 Assos Assos
 * Implements hook_panels_cache_save().
1394
 *
1395 85ad3d82 Assos Assos
 * Save all changes made to a display using the Page Manager page cache.
1396
 */
1397
function panelizer_panels_cache_save($argument, $cache) {
1398
  // If this is set, they clicked a button that saves a different panelizer
1399
  // than was being edited, such as saving to default rather than customizing
1400
  // an entity.
1401
  $original = $argument;
1402
  if (isset($cache->display->swap_cache_key)) {
1403
    $argument = $cache->display->swap_cache_key;
1404
  }
1405
1406
  list($entity_type, $key) = explode(':', $argument, 2);
1407
  $type = $entity_type;
1408
  if ($entity_type == 'default') {
1409
    list($entity_type, $bundle, $name) = @explode(':', $key, 3);
1410
    $get_default = TRUE;
1411
  }
1412
1413
  $handler = panelizer_entity_plugin_get_handler($entity_type);
1414
  if (!$handler) {
1415
    return;
1416
  }
1417
1418
  if (!empty($get_default)) {
1419
    $panelizer = $handler->get_default_panelizer_object($bundle, $name);
1420
    $panelizer->display = $cache->display;
1421
    ctools_include('export');
1422
    ctools_export_crud_save('panelizer_defaults', $panelizer);
1423
  }
1424
  else {
1425
    list($entity_id, $view_mode) = explode(':', $key);
1426 e5e66f93 Assos Assos
    $conditions = (isset($vid) ? array('vid' => $vid) : array());
1427
    $entities = entity_load($entity_type, array($entity_id), $conditions);
1428 85ad3d82 Assos Assos
    if ($entities[$entity_id] && $entities[$entity_id]->panelizer[$view_mode]) {
1429
      $entities[$entity_id]->panelizer[$view_mode]->display = $cache->display;
1430
      $entities[$entity_id]->panelizer[$view_mode]->display_is_modified = TRUE;
1431
      $handler->entity_save($entities[$entity_id]);
1432 e5e66f93 Assos Assos
      // The display may have been cloned in the save process, so need to be
1433
      // sure to put the old display back, and its contexts.
1434 85ad3d82 Assos Assos
      $cache->display = $entities[$entity_id]->panelizer[$view_mode]->display;
1435
      $cache->display->context = $handler->get_contexts($entities[$entity_id]->panelizer[$view_mode], $entities[$entity_id]);
1436
    }
1437
  }
1438
  panelizer_panels_cache_clear($original, $cache);
1439
}
1440
1441
// ---------------------------------------------------------------------------
1442
// Contrib module hooks to provide needed functionality.
1443
1444
/**
1445
 * Implements hook_export_node_alter().
1446
 *
1447
 * Integrate with export.module for saving panel_nodes into code.
1448
 */
1449
function panelizer_export_node_alter(&$node, $original_node, $method) {
1450
  // @todo
1451
}
1452
1453
/**
1454
 * Implements hook_panelizer_defaults_alter().
1455
 *
1456
 * Remove the panels node because there is no point to panelizing it.
1457
 */
1458
function panelizer_panelizer_default_types_alter(&$bundles, $entity_type) {
1459
  switch ($entity_type) {
1460
    case 'node':
1461
      // Disallow the panel node type, since it's already a panel.
1462
      if (module_exists('panels_node') && !empty($bundles['panel'])) {
1463
        unset($bundles['panel']);
1464
      }
1465
      break;
1466
  }
1467
}
1468
1469
/**
1470 e5e66f93 Assos Assos
 * Implements hook_features_pipe_panelizer_defaults_alter().
1471 85ad3d82 Assos Assos
 */
1472 e5e66f93 Assos Assos
function panelizer_features_pipe_panelizer_defaults_alter(&$more, $data, $export) {
1473
  foreach ($data as $machine_name) {
1474
    list ($entity_type, $bundle) = explode(':', $machine_name);
1475 85ad3d82 Assos Assos
1476 e5e66f93 Assos Assos
    $variables = array(
1477
      'panelizer_defaults_' . $entity_type . '_' . $bundle,
1478
      'panelizer_' . $entity_type . ':' . $bundle . '_allowed_layouts',
1479
      'panelizer_' . $entity_type . ':' . $bundle . '_allowed_layouts_default',
1480
      'panelizer_' . $entity_type . ':' . $bundle . '_allowed_types',
1481
      'panelizer_' . $entity_type . ':' . $bundle . '_allowed_types_default',
1482
      'panelizer_' . $entity_type . ':' . $bundle . '_default',
1483
    );
1484 85ad3d82 Assos Assos
1485 e5e66f93 Assos Assos
    // Add default display variables for each view mode.
1486
    $entity_info = entity_get_info($entity_type);
1487
    $default_base = 'panelizer_' . $entity_type . ':' . $bundle . ':';
1488
    foreach ($entity_info['view modes'] as $view_mode => $view_info) {
1489
      $variables[] = $default_base . $view_mode . '_selection';
1490
    }
1491
    $variables[] = $default_base . 'page_manager' . '_selection';
1492
    $variables[] = $default_base . 'default' . '_selection';
1493 85ad3d82 Assos Assos
1494 e5e66f93 Assos Assos
    foreach ($variables as $variable) {
1495
      $more['variable'][$variable] = $variable;
1496 85ad3d82 Assos Assos
    }
1497
  }
1498
1499 e5e66f93 Assos Assos
  return $more;
1500
}
1501
1502
/**
1503
 * Implements hook_search_api_alter_callback_info().
1504
 */
1505
function panelizer_search_api_alter_callback_info() {
1506
  $info = array();
1507
  $info['panelizer'] = array(
1508
    'name' => t('Panelizer'),
1509
    'description' => t('Add the content from the Panelizer "Full page override" to the search index.'),
1510
    'class' => 'PanelizerSearchApiAlterCallback',
1511
  );
1512
  return $info;
1513 85ad3d82 Assos Assos
}
1514
1515
// -----------------------------------------------------------------------
1516
// Theme functions where necessary.
1517
1518
/**
1519
 * Panelizer view mode theme function.
1520
 */
1521
function template_preprocess_panelizer_view_mode(&$vars) {
1522
  $element = $vars['element'];
1523
  $entity = $element['#panelizer_entity'];
1524
  $panelizer = $element['#panelizer'];
1525
  $handler = $element['#panelizer_handler'];
1526
  $info = $element['#panelizer_content'];
1527
1528
  $handler->preprocess_panelizer_view_mode($vars, $entity, $element, $panelizer, $info);
1529
}
1530
1531
// -----------------------------------------------------------------------
1532
// Drupal actions integration for VBO.
1533
1534
/**
1535
 * Implements hook_action_info().
1536
 */
1537
function panelizer_action_info() {
1538
  return array(
1539
    'panelizer_set_status_action' => array(
1540
      'type' => 'entity',
1541
      'label' => t('Set panelizer status'),
1542
      'vbo_configurable' => TRUE,
1543
      'configurable' => FALSE,
1544
      'behavior' => array('changes_property'),
1545
      'configurable' => TRUE,
1546
    )
1547
  );
1548
}
1549
1550
/**
1551
 * Executes the panelizer_set_status action.
1552
 */
1553
function panelizer_set_status_action($entity, $context) {
1554
  $view_mode = 'page_manager';
1555
  if (isset($context['view_mode'])) {
1556
    $view_mode = $context['view_mode'];
1557
  }
1558
1559
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($context['entity_type'], $entity);
1560
  if (isset($context['panelizer_default'])) {
1561
    $entity->panelizer[$view_mode] = $context['panelizer_default'];
1562
    $entity->panelizer[$view_mode]->did = NULL;
1563
1564 e5e66f93 Assos Assos
    // Ensure original values are maintained.
1565 85ad3d82 Assos Assos
    $entity->panelizer[$view_mode]->entity_id = $entity_id;
1566
    $entity->panelizer[$view_mode]->revision_id = $revision_id;
1567
  }
1568
  else {
1569
    $entity->panelizer[$view_mode]->name = NULL;
1570
    $entity->panelizer[$view_mode]->did = NULL;
1571
  }
1572
}
1573
1574
/**
1575
 * Provides the panelizer_set_status_action form.
1576
 */
1577
function panelizer_set_status_action_form($context, &$form_state) {
1578
  $form = array();
1579
  $entity_info = entity_get_info($context['entity_type']);
1580
  $entities = entity_load($context['entity_type'], $form_state['selection']);
1581
  $bundles = array();
1582
1583
  $handler = panelizer_entity_plugin_get_handler($context['entity_type']);
1584
  // Collect our list of bundles.
1585
  foreach ($entities as $entity) {
1586
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($context['entity_type'], $entity);
1587
    $bundles[$bundle] = $bundle;
1588
  }
1589
1590
  $conditions = array(
1591
    'panelizer_type' => $context['entity_type'],
1592
    'panelizer_key' => $bundles,
1593
  );
1594
1595
  ctools_include('export');
1596
  $defaults = ctools_export_load_object('panelizer_defaults', 'conditions', $conditions);
1597
1598
  foreach ($defaults as $name => $default) {
1599
    if (empty($default->title)) {
1600
      $default->title = t('Default');
1601
    }
1602
    $options[$default->view_mode][$name] = t('@bundle: @title', array('@bundle' => $entity_info['bundles'][$default->panelizer_key]['label'], '@title' => $default->title));
1603
  }
1604
1605
  $view_modes = array();
1606
  foreach ($handler->plugin['view modes'] as $view_mode => $view_mode_info) {
1607
    $view_modes[$view_mode] = $view_mode_info['label'];
1608
  }
1609
1610
  $form['panelizer']['#tree'] = TRUE;
1611
1612
  foreach ($view_modes as $view_mode => $label) {
1613
    if (empty($options[$view_mode])) {
1614
      unset($view_modes[$view_mode]);
1615
      continue;
1616
    }
1617
1618
    natcasesort($options[$view_mode]);
1619
    $panelizers = array(
1620
      'not' => t('Not panelized'),
1621
    ) + $options[$view_mode];
1622
1623
    $form['panelizer'][$view_mode] = array(
1624
      '#type' => 'select',
1625
      '#title' => t('Panelizer status'),
1626
      '#options' => $panelizers,
1627
      '#states' => array(
1628
        'visible' => array(
1629
          '#panelizer-view-mode' => array('value' => $view_mode),
1630
        ),
1631
      ),
1632
    );
1633
  }
1634
1635
  $form['view_mode'] = array(
1636
    '#type' => 'select',
1637
    '#title' => t('View mode'),
1638
    '#options' => $view_modes,
1639
    '#id' => 'panelizer-view-mode',
1640
    '#weight' => -10,
1641
  );
1642
1643
  $form['#panelizer_defaults'] = $defaults;
1644
  return $form;
1645
}
1646
1647 e5e66f93 Assos Assos
/**
1648
 * FormAPI submission callback.
1649
 */
1650 85ad3d82 Assos Assos
function panelizer_set_status_action_submit($form, $form_state) {
1651
  $view_mode = $form_state['values']['view_mode'];
1652
  $panelizer = $form_state['values']['panelizer'][$view_mode];
1653
1654
  $retval = array(
1655
    'panelizer' => $panelizer,
1656
    'view_mode' => $view_mode,
1657
  );
1658
1659
  if ($form_state['values']['panelizer'] != 'not') {
1660
    $retval['panelizer_default'] = $form['#panelizer_defaults'][$panelizer];
1661
  }
1662
1663
  return $retval;
1664
}
1665
1666
// --------------------------------------------------------------------------
1667
// Miscellaneous helper functions
1668
1669
/**
1670
 * Return list of operations.
1671
 *
1672
 * @see hook_panelizer_operations_alter().
1673
 */
1674
function panelizer_operations() {
1675
  $operations = array(
1676
    'settings' => array(
1677
      'menu title' => 'Settings',
1678
      'link title' => t('settings'),
1679
      'admin callback' => 'panelizer_default_settings_page',
1680
      // ctools export ui thinks this is 'edit'.
1681
      'ui path' => 'edit',
1682
    ),
1683
    'context' => array(
1684
      'menu title' => 'Context',
1685
      'link title' => t('context'),
1686
      'admin callback' => 'panelizer_default_context_page',
1687
    ),
1688
    'layout' => array(
1689
      'menu title' => 'Layout',
1690
      'link title' => t('layout'),
1691
      'admin callback' => 'panelizer_default_layout_page',
1692
    ),
1693
    'content' => array(
1694
      'menu title' => 'Content',
1695
      'link title' => t('content'),
1696
      'admin callback' => 'panelizer_default_content_page',
1697
    ),
1698
  );
1699
1700
  drupal_alter('panelizer_operations', $operations);
1701
1702
  return $operations;
1703
}
1704
1705
/**
1706 e5e66f93 Assos Assos
 * Gets the current layout options approach for an entity bundle.
1707
 *
1708
 * @param string $type
1709
 *   The entity type.
1710
 * @param string $bundle
1711
 *   The entity bundle.
1712
 *
1713
 * @return string
1714
 *   The name of the layout approach to check (default or per bundle).
1715
 */
1716
function panelizer_get_allowed_layouts_option($type, $bundle) {
1717
  if (variable_get('panelizer_' . $type . ':' . $bundle . '_allowed_layouts_default', FALSE)) {
1718
    return 'panels_page';
1719
  }
1720
  else {
1721
    return 'panelizer_' . $type . ':' . $bundle;
1722
  }
1723
}
1724
1725
/**
1726
 * Implements hook_form_FORM_ID_alter() for panels_ipe_edit_control_form().
1727 85ad3d82 Assos Assos
 *
1728
 * Alter the IPE save control form to handle extra Panelizer functionality.
1729
 */
1730
function panelizer_form_panels_ipe_edit_control_form_alter(&$form, &$form_state) {
1731
  if (empty($form_state['renderer'])) {
1732
    return;
1733
  }
1734
1735
  $renderer = $form_state['renderer'];
1736
1737
  $cache_key = $renderer->display->cache_key;
1738 e5e66f93 Assos Assos
  $parts = explode(':', $cache_key, 3);
1739
  if ($parts[0] != 'panelizer') {
1740 85ad3d82 Assos Assos
    return;
1741
  }
1742
1743 e5e66f93 Assos Assos
  list($module, $type, $key) = $parts;
1744
1745 85ad3d82 Assos Assos
  if ($type == 'default') {
1746
    return;
1747
  }
1748
1749 e5e66f93 Assos Assos
  // Load the $plugin information.
1750 85ad3d82 Assos Assos
  $handler = panelizer_entity_plugin_get_handler($type);
1751
  if (!$handler) {
1752
    return;
1753
  }
1754
1755
  // Get the entity that's being edited.
1756
  list($entity_id, $view_mode) = explode(':', $key);
1757
  $entities = entity_load($handler->entity_type, array($entity_id));
1758
  if (empty($entities[$entity_id])) {
1759
    return;
1760
  }
1761
1762
  $entity = $entities[$entity_id];
1763
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($handler->entity_type, $entity);
1764
  $entity_info = entity_get_info($handler->entity_type);
1765
1766
  if (empty($entity->panelizer[$view_mode])) {
1767
    return;
1768
  }
1769
1770
  $panelizer = $entities[$entity_id]->panelizer[$view_mode];
1771
1772 e5e66f93 Assos Assos
  module_load_include('inc', 'panelizer', 'includes/common');
1773
  $revision_info = $handler->entity_allows_revisions($entity);
1774
1775
  // Set panelizer info regardless of revision or panelizer layout default
1776
  // status.
1777
  $form_state['panelizer entity'] = $entity;
1778
  $form_state['panelizer bundle'] = $bundle;
1779
  $form_state['panelizer handler'] = $handler;
1780
  $form_state['panelizer view_mode'] = $view_mode;
1781
1782
  // If this entity has revisions enabled we can assume that they have
1783
  // permissions to add revisions via IPE.
1784
  if (!empty($revision_info)) {
1785
    $form_state['entity'] = $entity;
1786
    $form_state['revision info'] = $revision_info;
1787
    panelizer_add_revision_info_form($form, $form_state);
1788
    // Tweak the log message field to make it fit better.
1789
    if (isset($form['revision_information']['log'])) {
1790
      $form['revision_information']['log']['#type'] = 'textfield';
1791
      $form['revision_information']['log']['#description'] = '';
1792
    }
1793
  }
1794
1795 85ad3d82 Assos Assos
  // If the entity already has customized panelizer data, add the revert button.
1796
  if (!empty($panelizer->did)) {
1797
    if ($handler->has_default_panel($bundle . '.' . $view_mode)) {
1798 e5e66f93 Assos Assos
      $uri = entity_uri($handler->entity_type, $entity);
1799
      $url = $uri['path'];
1800
      // Support for Workbench Moderation to redirect to the newest revision for
1801
      // this node.
1802
      if ($handler->entity_type == 'node' && module_exists('workbench_moderation')) {
1803
        $url = 'node/' . $entity->nid . '/current-revision';
1804
      }
1805
      $redirect_url = url($uri['path'] . '/panelizer/' . $view_mode . '/reset', array('query' => array('destination' => $url)));
1806
      drupal_add_js(array('panelizer' => array('revert_default_url' => $redirect_url)), 'setting');
1807
1808 85ad3d82 Assos Assos
      $form['buttons']['revert_default'] = array(
1809
        '#type' => 'submit',
1810
        '#value' => t('Revert to @bundle_name default', array('@bundle_name' => $entity_info['bundles'][$bundle]['label'])),
1811
        '#submit' => array('panels_ipe_revert_to_default'),
1812
        '#attributes' => array('class' => array('panels-ipe-cancel')),
1813
        '#id' => 'panelizer-ipe-revert',
1814 e5e66f93 Assos Assos
        '#access' => $handler->panelizer_access('defaults', $entity, $panelizer->view_mode),
1815 85ad3d82 Assos Assos
      );
1816
    }
1817
    return;
1818
  }
1819
1820
  // Change the default button to say "Save as custom".
1821
  $form['buttons']['submit']['#value'] = t('Save as custom');
1822
1823 e5e66f93 Assos Assos
  // Calculate the proper name to add to the cache key, which has some data
1824
  // stripped off of the true name.
1825
  $name = 'default';
1826
  if (!empty($panelizer->name)) {
1827 85ad3d82 Assos Assos
    $pieces = explode(':', $panelizer->name);
1828 e5e66f93 Assos Assos
    if (isset($pieces[2])) {
1829
      $name = $pieces[2];
1830
    }
1831 85ad3d82 Assos Assos
  }
1832
1833 e5e66f93 Assos Assos
  // Add another button to save as the default instead.
1834 85ad3d82 Assos Assos
  $form['buttons']['save_default'] = array(
1835
    '#type' => 'submit',
1836
    '#value' => t('Save as @bundle_name default', array('@bundle_name' => $entity_info['bundles'][$bundle]['label'])),
1837
    '#submit' => array('panels_ipe_change_to_default', 'panels_edit_display_form_submit'),
1838
    '#save-display' => TRUE,
1839
    '#weight' => -1,
1840 e5e66f93 Assos Assos
    // Precalculate the cache key so we don't have to unwind a bunch of stuff in
1841
    // the submit handler.
1842 85ad3d82 Assos Assos
    '#cache_key' => 'default:' . $handler->entity_type . ':' . $bundle . '.' . $panelizer->view_mode . ':' . $name,
1843
    '#attributes' => array('class' => array('panels-ipe-save')),
1844
    '#id' => 'panelizer-save-default',
1845 e5e66f93 Assos Assos
    '#access' => $handler->panelizer_access('defaults', $entity, $panelizer->view_mode),
1846 85ad3d82 Assos Assos
  );
1847
}
1848
1849
/**
1850 e5e66f93 Assos Assos
 * Implements hook_form_FORM_ID_alter() for panels_change_layout().
1851
 *
1852
 * Alter the change layout form to support saving as default.
1853
 */
1854
function panelizer_form_panels_change_layout_alter(&$form, &$form_state) {
1855
  // Only alter on initial form build.
1856
  if (empty($form_state['executed'])) {
1857
    if (isset($form_state['back'])) {
1858
      // Do nothing when moving backwards.
1859
      return;
1860
    }
1861
1862
    // Extract the display from the form state.
1863
    $display = $form_state['display'];
1864
1865
    $cache_key = $display->cache_key;
1866
    $parts = explode(':', $cache_key, 3);
1867
    if ($parts[0] != 'panelizer') {
1868
      return;
1869
    }
1870
1871
    list($module, $type, $key) = $parts;
1872
1873
    // If the display is not owned by Panelizer, or is default handler, exit.
1874
    if ($module != 'panelizer' || $type == 'default') {
1875
      return;
1876
    }
1877
1878
    // Load the $plugin information.
1879
    $handler = panelizer_entity_plugin_get_handler($type);
1880
    if (!$handler) {
1881
      return;
1882
    }
1883
1884
    // Get the entity that's being edited through Panelizer context.
1885
    $entity = $display->context['panelizer']->data;
1886
1887
    // Check if the view mode is configured.
1888
    list($entity_id, $view_mode) = explode(':', $key);
1889
    if (empty($entity->panelizer[$view_mode])) {
1890
      return;
1891
    }
1892
1893
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($handler->entity_type, $entity);
1894
    $entity_info = entity_get_info($handler->entity_type);
1895
1896
    $panelizer = $entity->panelizer[$view_mode];
1897
1898
    // Calculate the proper name to add to the cache key, which has some data
1899
    // stripped off of the true name.
1900
    $name = 'default';
1901
    if (!empty($panelizer->name)) {
1902
      $pieces = explode(':', $panelizer->name);
1903
      if (isset($pieces[2])) {
1904
        $name = $pieces[2];
1905
      }
1906
    }
1907
1908
    // Change the default button to say "Save as custom".
1909
    $form['submit']['#value'] = t('Save as custom');
1910
1911
    // Add another button to save as the default instead.
1912
    $form['save_default'] = array(
1913
      '#type' => 'submit',
1914
      '#value' => t('Save as @bundle_name default', array('@bundle_name' => $entity_info['bundles'][$bundle]['label'])),
1915
      '#submit' => array('panels_ipe_change_to_default', 'panels_change_layout_submit'),
1916
      '#save-display' => TRUE,
1917
      '#cache_key' => 'default:' . $handler->entity_type . ':' . $bundle . '.' . $panelizer->view_mode . ':' . $name,
1918
      '#access' => $handler->panelizer_access('defaults', $entity, $panelizer->view_mode),
1919
    );
1920
  }
1921
}
1922
1923
/**
1924
 * Implement template_preprocess_panels_ipe_toolbar().
1925
 */
1926
function panelizer_preprocess_panels_ipe_toolbar(&$variables) {
1927
  // Some custom CSS to improve the UX.
1928
  // $variables['#attached'] = array(
1929
  //   'css' => array(
1930
  //     drupal_get_path('module', 'panelizer') . '/css/panelizer.ipe.css',
1931
  //   ),
1932
  // );
1933
  // dpm($variables);
1934
}
1935
1936
/**
1937
 * Implements hook_panels_ipe_ajax_save_commands_alter().
1938
 *
1939
 * If Workbench Moderation is enabled, and this is for the form submission on a
1940
 * Panelized node, redirect to the latest revision upon save.
1941
 */
1942
function panelizer_panels_ipe_ajax_save_commands_alter(&$ipe, $form_state) {
1943
  // This requires Workbench Moderation.
1944
  if (module_exists('workbench_moderation')) {
1945
    // The form was actually saved.
1946
    if (!empty($form_state['submitted']) && !empty($ipe->meta_location)) {
1947
      // This is for a revisions-enabled Panelizer entity.
1948
      if (!empty($form_state['use revisions'])) {
1949
        $entity = $form_state['entity'];
1950
        $ipe->commands[0] = ctools_ajax_command_redirect('node/' . $entity->nid . '/current-revision');
1951
      }
1952
    }
1953
  }
1954
}
1955
1956
/**
1957
 * Submit handler to save the panelizer default instead of customizing the
1958
 * entity.
1959 85ad3d82 Assos Assos
 */
1960
function panels_ipe_change_to_default($form, &$form_state) {
1961
  // Change the cache key so that it saves to the default instead of the
1962
  // entity. This works because we're actually editing the original display
1963
  // anyway, and everything else keys off the cache key.
1964
  $form_state['display']->swap_cache_key = $form_state['triggering_element']['#cache_key'];
1965
}
1966
1967
/**
1968
 * Submit handler to revert to the default panelizer.
1969
 */
1970
function panels_ipe_revert_to_default($form, &$form_state) {
1971
  // Reduce code complexity due to indirection.
1972
  $handler = $form_state['panelizer handler'];
1973
  $entity = $form_state['panelizer entity'];
1974
  $bundle = $form_state['panelizer bundle'];
1975
  $view_mode = $form_state['panelizer view_mode'];
1976
  $renderer = $form_state['renderer'];
1977
1978
  $handler->delete_entity_panelizer($entity, $view_mode);
1979
1980
  $name = implode(':', array($handler->entity_type, $bundle, 'default'));
1981
  if ($view_mode != 'page_manager') {
1982
    $name .= ':' . $view_mode;
1983
  }
1984
  $cache_key = $form_state['display']->cache_key;
1985
1986
  // Now load the original default display and force a rerender.
1987
  $panelizer = $handler->get_default_panelizer_object($bundle . '.' . $view_mode, $name);
1988
1989
  $renderer->display = $display = $panelizer->display;
1990
  $display->cache_key = $cache_key;
1991
1992
  $display->context = $handler->get_contexts($panelizer, $entity);
1993
1994
  $renderer->commands[] = ajax_command_replace("#panels-ipe-display-{$renderer->clean_key}", panels_render_display($display, $renderer));
1995
}
1996 e5e66f93 Assos Assos
1997
/**
1998
 * Implements hook_panelizer_pre_render_alter().
1999
 *
2000
 * Panelizer fails to communicate to the theme layer what view mode an entity's
2001
 * fields are being rendered in, so we unfortunately have to do that ourselves.
2002
 */
2003
function panelizer_panelizer_pre_render_alter(&$panelizer, &$display, &$entity) {
2004
  foreach ($entity->panelizer as $view_mode => $reference_panelizer) {
2005
    if ($reference_panelizer === $panelizer) {
2006
      $entity->panelizer_view_mode = $view_mode;
2007
      break;
2008
    }
2009
  }
2010
}
2011
2012
/**
2013
 * Implements hook_workbench_moderation_node_history_view_alter().
2014
 *
2015
 * This is a little kludgy as the data in the row is stored as final HTML for
2016
 * display.
2017
 */
2018
function panelizer_workbench_moderation_node_history_view_alter(&$rows) {
2019
  // Load the node.
2020
  $node = node_load(arg(1));
2021
2022
  // Verify the user has access to the Panelizer configuration.
2023
  if (panelizer_is_panelized('node', $node->type)) {
2024
    // Loop over each table row.
2025
    foreach ($rows as $key => &$row) {
2026
      // Published.
2027
      $path = 'node/' . $node->nid . '/panelizer';
2028
2029
      // Not published.
2030
      if (!in_array('published-revision', $row['class'])) {
2031
        $path = 'node/' . $node->nid . '/revisions/' . $row['data']['vid'] . '/panelizer';
2032
      }
2033
2034
      // Add a link to the Panelizer page.
2035
      $row['data']['revision'] .= ' | ' . l('Customize display', $path);
2036
    }
2037
  }
2038
}
2039
2040
/**
2041
 * Menu callback load method to either return the requested revision ID or FALSE
2042
 * to prevent the tab from being processed.
2043
 *
2044
 * @param string $vid
2045
 *   An entity's revision ID.
2046
 *
2047
 * @return mixed
2048
 *   Either the revision_id or FALSE if the revision was empty.
2049
 */
2050
function panelizer_node_revision_load($revision_id = NULL) {
2051
  if (!empty($revision_id)) {
2052
    return $revision_id;
2053
  }
2054
  return FALSE;
2055
}
2056
2057
/**
2058
 * Implements hook_clone_node_alter().
2059
 *
2060
 * Custom integration for Node Clone to handle objects that might be embedded in
2061
 * a custom Panelizer display. Currently supports Fieldable Panels Panes.
2062
 */
2063
function panelizer_clone_node_alter(&$node, $context) {
2064
  if (!empty($node->panelizer)) {
2065
    foreach ($node->panelizer as $view_mode => &$panelizer) {
2066
      // Only deal with custom displays, ignore default displays which would
2067
      // be selected in $panelizer->name.
2068
      if (!empty($panelizer->did) && !empty($panelizer->display)) {
2069
        // Loop over each pane.
2070
        foreach ($panelizer->display->content as &$pane) {
2071
          // Clone each FPP and then assign the new fpid.
2072
          if ($pane->type == 'fieldable_panels_pane') {
2073
            list($subtype, $fpid) = explode(':', $pane->subtype);
2074
            if ($subtype == 'fpid') {
2075
              // Clone the FPP object.
2076
              $fpp = fieldable_panels_panes_load($fpid);
2077
2078
              // Clean the some basic settings.
2079
              $fpp->fpid = NULL;
2080
              $fpp->created = NULL;
2081
              $fpp->timestamp = NULL;
2082
2083
              // Save the cloned FPP.
2084
              $newfpp = fieldable_panels_panes_save($fpp);
2085
2086
              // Update the FPP reference.
2087
              $pane->subtype = 'fpid:' . $newfpp->fpid;
2088
            }
2089
          }
2090
        }
2091
      }
2092
    }
2093
  }
2094
}