Projet

Général

Profil

Paste
Télécharger (136 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / panelizer / plugins / entity / PanelizerEntityDefault.class.php @ a2bb1a14

1 85ad3d82 Assos Assos
<?php
2
/**
3
 * @file
4
 * Base class for the Panelizer Entity plugin.
5
 */
6
7
/**
8
 * Interface to describe how PanelizerEntity plugin objects are implemented.
9
 */
10
interface PanelizerEntityInterface {
11
  /**
12
   * Initialize the plugin object.
13
   */
14
  public function init($plugin);
15
16
  // Public Drupal hooks
17
  public function hook_menu(&$items);
18
  public function hook_menu_alter(&$items);
19
  public function hook_form_alter(&$form, &$form_state, $form_id);
20
  public function hook_permission(&$items);
21
  public function hook_admin_paths(&$items);
22
  public function hook_views_data_alter(&$data);
23
24
  // Entity specific Drupal hooks
25
  public function hook_entity_load(&$entities);
26
  public function hook_entity_insert($entity);
27
  public function hook_entity_update($entity);
28
  public function hook_entity_delete($entity);
29
  public function hook_field_attach_delete_revision($entity);
30
31 e5e66f93 Assos Assos
  /**
32
   * Check if the necessary Page Manager display is enabled and the appropriate
33
   * variant has not been disabled.
34
   *
35
   * @return boolean
36
   *   Whether or not both the Page Manager display and the variant are enabled.
37
   */
38
  public function check_page_manager_status();
39
40 85ad3d82 Assos Assos
  /**
41
   * Add entity specific form to the Panelizer settings form.
42
   *
43
   * This is primarily to allow bundle selection per entity type.
44
   */
45
  public function settings_form(&$form, &$form_state);
46
47
  /**
48
   * Validate entity specific settings on the Panelizer settings form.
49
   */
50
  public function settings_form_validate(&$form, &$form_state);
51
52
  /**
53
   * Submit entity specific settings on the Panelizer settings form.
54
   */
55
  public function settings_form_submit(&$form, &$form_state);
56
57
  /**
58
   * Load the named default panel for the bundle.
59
   */
60
  public function get_default_panelizer_object($bundle, $name);
61
62
  /**
63
   * Determine if the current user has access to the $panelizer.
64
   */
65
  public function access_default_panelizer_object($panelizer);
66
67
  /**
68
   * Determine if a bundle is panelized
69
   */
70
  public function is_panelized($bundle);
71
72
  /**
73
   * Determine if a bundle has a defalt panel
74
   */
75
  public function has_default_panel($bundle);
76
77
  /**
78
   * Determine if a bundle is allowed choices.
79
   */
80
  public function has_panel_choice($bundle);
81
82 e5e66f93 Assos Assos
  /**
83
   * Determine the default name for the default object.
84
   */
85
  public function get_default_display_default_name($bundle, $view_mode = 'page_manager');
86
87
  /**
88
   * Determine the variable name used to identify the default display for the
89
   * given bundle/view mode combination.
90
   */
91
  public function get_default_display_variable_name($bundle, $view_mode = 'page_manager');
92
93
  /**
94
   * Determine the default display name for a given bundle & view mode
95
   * combination.
96
   */
97
  public function get_default_display_name($bundle, $view_mode = 'page_manager');
98
99
  /**
100
   * Determine whether a specific default display object exists.
101
   */
102
  public function default_display_exists($display_name);
103
104 85ad3d82 Assos Assos
  /**
105
   * Get a default display for a newly panelized entity.
106
   *
107
   * This is meant to give administrators a starting point when panelizing
108
   * new entities.
109
   */
110
  function get_default_display($bundle, $view_mode);
111
112 e5e66f93 Assos Assos
  /**
113
   * Identify the view modes that are available for use with this entity bundle.
114
   *
115
   * @param string $bundle
116
   *   The entity bundle to check. Defaults to '0', which will check for view
117
   *   modes that are available by default for all entities.
118
   *
119
   * @return array
120
   *   A list of view modes that are available to be panelized.
121
   */
122
  public function get_available_view_modes($bundle = 0);
123
124
  /**
125
   * Identify the view modes that are enabled for use with Panelizer.
126
   *
127
   * @param string $bundle
128
   *   The entity bundle to check.
129
   *
130
   * @return array
131
   *   A list of view modes that are panelized.
132
   */
133
  public function get_enabled_view_modes($bundle);
134
135 85ad3d82 Assos Assos
  /**
136
   * Get a panelizer object for the key.
137
   *
138
   * This must be implemented for each entity type, as the default object
139
   * implements a special case for handling panelizer defaults.
140
   */
141
   // @todo this seems to be unused now.
142
//  function get_panelizer_object($key);
143
144
  /**
145
   * Render a panelized entity.
146
   */
147
  function render_entity($entity, $view_mode, $langcode = NULL, $args = array(), $address = NULL);
148
149
  /**
150
   * Fetch an object array of CTools contexts from panelizer information.
151
   */
152
  public function get_contexts($panelizer, $entity = NULL);
153
154
  /**
155
   * Callback to get the base context for a panelized entity
156
   */
157
  public function get_base_contexts($entity = NULL);
158
159 e5e66f93 Assos Assos
  /**
160
   * Confirm the view mode to be used, check if a substitute is assigned,
161
   * failover to 'default'.
162
   *
163
   * @param string $view_mode
164
   *   The original view mode to be checked.
165
   * @param string $bundle
166
   *   The entity bundle being used.
167
   *
168
   * @return string
169
   *   The final view mode that will be used.
170
   */
171
  public function get_view_mode($view_mode, $bundle);
172
173
  /**
174
   * Obtain the machine name of the Page Manager task.
175
   *
176
   * @return string
177
   *   The machine name for the Page Manager task; returns FALSE if this
178
   *   entity does not support Page Manager.
179
   */
180
  public function get_page_manager_task_name();
181
182
  /**
183
   * Identifies a substitute view mode for a given bundle.
184
   *
185
   * @param string $view_mode
186
   *   The original view mode to be checked.
187
   * @param string $bundle
188
   *   The entity bundle being checked.
189
   *
190
   * @return string
191
   *   The view mode that will be used.
192
   */
193
  public function get_substitute($view_mode, $bundle);
194
195
  /**
196
   * Obtain the system path to an entity bundle's display settings page for a
197
   * specific view mode.
198
   *
199
   * @param string $bundle
200
   * @param string $view_mode
201
   *
202
   * @return string
203
   *   The system path of the display settings page for this bundle/view mode
204
   *   combination.
205
   */
206
  public function admin_bundle_display_path($bundle, $view_mode);
207
208 85ad3d82 Assos Assos
  /**
209
   * Determine if the current user has $op access on the $entity.
210
   */
211
  public function entity_access($op, $entity);
212
213
  /**
214
   * Implement the save function for the entity.
215
   */
216
  public function entity_save($entity);
217
218
  /**
219
   * Determine if an entity allows revisions and whether or not the current
220
   * user has access to control that.
221
   *
222
   * @param $entity
223
   *   The entity in question.
224
   * @return
225
   *   An array. The first parameter is a boolean as to whether or not the
226 e5e66f93 Assos Assos
   *   entity supports revisions, the second parameter is whether or not the
227
   *   user can control if a revision is created, the third states whether or
228
   *   not the revision is created by default.
229 85ad3d82 Assos Assos
   */
230
  public function entity_allows_revisions($entity);
231
232
  /**
233
   * Get the visible identifier of the identity.
234
   *
235
   * This is overridable because it can be a bit awkward using the
236
   * default label.
237
   *
238
   * @return
239
   *   A translated, safe string.
240
   */
241
  public function entity_identifier($entity);
242
243
  /**
244
   * Get the name of bundles on the entity.
245
   *
246
   * Entity API doesn't give us a way to determine this, so the class must
247
   * do this.
248
   *
249
   * @return
250
   *   A translated, safe string.
251
   */
252
  public function entity_bundle_label();
253
254
  /**
255
   * Fetch the entity out of a build for hook_entity_view.
256
   *
257
   * @param $build
258
   *   The render array that contains the entity.
259
   */
260
  public function get_entity_view_entity($build);
261 e5e66f93 Assos Assos
262
  /**
263
   * Identify whether page manager is enabled for this entity type.
264
   *
265
   * @return bool
266
   */
267
  public function is_page_manager_enabled();
268 85ad3d82 Assos Assos
}
269
270
/**
271
 * Base class for the Panelizer Entity plugin.
272
 */
273
abstract class PanelizerEntityDefault implements PanelizerEntityInterface {
274
  /**
275
   * Where in the entity admin UI we should add Panelizer tabs with bundles.
276
   */
277
  public $entity_admin_root = NULL;
278
279
  /**
280
   * True if the entity supports revisions.
281
   */
282
  public $supports_revisions = FALSE;
283
284
  /**
285
   * The base table in SQL the entity uses, for views support.
286
   */
287
  public $views_table = '';
288
289
  /**
290
   * The plugin metadata.
291
   */
292
  public $plugin = NULL;
293
294
  /**
295
   * The entity type the plugin is for. This is from the $plugin array.
296
   */
297
  public $entity_type = '';
298
299 e5e66f93 Assos Assos
  /**
300
   * Storage for the display defaults already loaded by the system. Used in
301
   * default_display_exists().
302
   */
303
  private $displays = array();
304
  private $displays_loaded = array();
305
306
  /**
307
   *
308
   */
309
  private $enabled_view_modes = array();
310
311 85ad3d82 Assos Assos
  /**
312
   * Initialize the plugin and store the plugin info.
313
   */
314
  function init($plugin) {
315
    $this->plugin = $plugin;
316
    $this->entity_type = $plugin['name'];
317
  }
318
319
  /**
320
   * Implements a delegated hook_permission.
321
   */
322
  public function hook_permission(&$items) {
323
    $entity_info = entity_get_info($this->entity_type);
324
    // Make a permission for each bundle we control.
325
    foreach ($this->plugin['bundles'] as $bundle => $settings) {
326
      // This is before the if because it shows up regardless of whether
327
      // or not a type is panelized.
328
      $items["administer panelizer $this->entity_type $bundle defaults"] = array(
329
        'title' => t('%entity_name %bundle_name: Administer Panelizer default panels, allowed content and settings.', array(
330
          '%entity_name' => $entity_info['label'],
331
          '%bundle_name' => $entity_info['bundles'][$bundle]['label'],
332
        )),
333
        'description' => t('Users with this permission can fully administer panelizer for this entity bundle.'),
334
      );
335
336
      if (empty($settings['status'])) {
337
        continue;
338
      }
339
340
      $items["administer panelizer $this->entity_type $bundle overview"] = array(
341
        'title' => t('%entity_name %bundle_name: Administer Panelizer overview', array(
342
          '%entity_name' => $entity_info['label'],
343
          '%bundle_name' => $entity_info['bundles'][$bundle]['label'],
344
        )),
345
        '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.'),
346
      );
347
      foreach (panelizer_operations() as $path => $operation) {
348
        $items["administer panelizer $this->entity_type $bundle $path"] = array(
349
          'title' => t('%entity_name %bundle_name: Administer Panelizer @operation', array(
350
            '%entity_name' => $entity_info['label'],
351
            '%bundle_name' => $entity_info['bundles'][$bundle]['label'],
352
            '@operation' => $operation['link title'],
353
          )),
354
        );
355
      }
356
357 e5e66f93 Assos Assos
      // Account for the choice permission when dealing with view modes.
358
      foreach ($settings['view modes'] as $view_mode => $view_mode_settings) {
359
        if (!empty($view_mode_settings['choice'])) {
360
          $items["administer panelizer $this->entity_type $bundle choice"] = array(
361
            'title' => t('%entity_name %bundle_name: Choose panels', array(
362
              '%entity_name' => $entity_info['label'],
363
              '%bundle_name' => $entity_info['bundles'][$bundle]['label'],
364
            )),
365
            'description' => t('Allows the user to choose which default display the entity uses.'),
366
          );
367
          // Break out of loop after finding one we just need to see if we should
368
          // enable the permission.
369
          break;
370
        }
371 85ad3d82 Assos Assos
      }
372
    }
373
  }
374
375
  /**
376
   * Implements a delegated hook_menu.
377
   */
378
  public function hook_menu(&$items) {
379
    if (!empty($this->plugin['entity path'])) {
380
      // Figure out where in the path the entity will be.
381
      $bits = explode('/', $this->plugin['entity path']);
382
      foreach ($bits as $count => $bit) {
383
        if (strpos($bit, '%') === 0) {
384
          $position = $count;
385
          break;
386
        }
387
      }
388
389
      if (!isset($position)) {
390
        return;
391
      }
392
393
      $total = count($bits);
394
395
      // Configure entity editing pages
396
      $base = array(
397
        'access callback' => 'panelizer_entity_plugin_callback_switcher',
398
        'access arguments' => array($this->entity_type, 'access', 'admin', $position, 'overview'),
399 e5e66f93 Assos Assos
        'page callback' => 'panelizer_entity_plugin_switcher_page',
400 85ad3d82 Assos Assos
        'type' => MENU_LOCAL_TASK,
401
      );
402
403
      $items[$this->plugin['entity path'] . '/panelizer'] = array(
404 e5e66f93 Assos Assos
        'title' => 'Customize display',
405 85ad3d82 Assos Assos
        // make sure this is accessible to panelize entities with no defaults.
406
        'page arguments' => array($this->entity_type, 'overview', $position),
407
        'weight' => 11,
408
        'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
409
      ) + $base;
410
411
      $items[$this->plugin['entity path'] . '/panelizer/overview'] = array(
412
        'title' => 'Overview',
413
        'page arguments' => array($this->entity_type, 'overview', $position),
414
        'type' => MENU_DEFAULT_LOCAL_TASK,
415 e5e66f93 Assos Assos
        'weight' => -10,
416 85ad3d82 Assos Assos
      ) + $base;
417
418 e5e66f93 Assos Assos
      if ($this->supports_revisions) {
419
        $rev_base = $base;
420
        $rev_base['load arguments'] = array($position + 2);
421
        $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer'] = array(
422
          'title' => 'Customize display',
423
          // Make sure this is accessible to panelize entities with no defaults.
424
          'page arguments' => array($this->entity_type, 'overview', $position),
425
          'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
426
          'type' => MENU_LOCAL_TASK,
427
          'weight' => 11,
428
        ) + $rev_base;
429
430
        // Integration with Workbench Moderation.
431
        if (module_exists('workbench_moderation') && $this->entity_type == 'node') {
432
          $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer']['type'] = MENU_CALLBACK;
433
        }
434
435
        $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/overview'] = array(
436
          'title' => 'Overview',
437
          'page arguments' => array($this->entity_type, 'overview', $position),
438
          'type' => MENU_DEFAULT_LOCAL_TASK,
439
          'weight' => -100,
440
        ) + $rev_base;
441
      }
442
443 85ad3d82 Assos Assos
      // Put in all of our view mode based paths.
444
      $weight = 0;
445
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
446
        $items[$this->plugin['entity path'] . "/panelizer/$view_mode"] = array(
447
          'title' => $view_mode_info['label'],
448
          'page arguments' => array($this->entity_type, 'settings', $position, $view_mode),
449
          'access arguments' => array($this->entity_type, 'access', 'admin', $position, 'settings', $view_mode),
450
          'weight' => $weight++,
451
        ) + $base;
452
453 e5e66f93 Assos Assos
        if ($this->supports_revisions) {
454
          $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode] = array(
455
            'title' => $view_mode_info['label'],
456
            'page arguments' => array($this->entity_type, 'content', $position, $view_mode),
457
            'access arguments' => array($this->entity_type, 'access', 'admin', $position, 'content', $view_mode),
458
            'weight' => $weight++,
459
          ) + $base;
460
        }
461
462 85ad3d82 Assos Assos
        foreach (panelizer_operations() as $path => $operation) {
463
          $items[$this->plugin['entity path'] . '/panelizer/' . $view_mode . '/' . $path] = array(
464
            'title' => $operation['menu title'],
465
            'page arguments' => array($this->entity_type, $path, $position, $view_mode),
466
            'access arguments' => array($this->entity_type, 'access', 'admin', $position, $path, $view_mode),
467
            'weight' => $weight++,
468
          ) + $base;
469
          if (isset($operation['file'])) {
470
            $items[$this->plugin['entity path'] . '/panelizer/' . $view_mode . '/' . $path]['file'] = $operation['file'];
471
          }
472
          if (isset($operation['file path'])) {
473
            $items[$this->plugin['entity path'] . '/panelizer/' . $view_mode . '/' . $path]['file path'] = $operation['file path'];
474
          }
475
        }
476 e5e66f93 Assos Assos
477 85ad3d82 Assos Assos
        // Add our special reset item:
478
        $items[$this->plugin['entity path'] . '/panelizer/' . $view_mode . '/reset'] = array(
479
          'title' => t('Reset to Defaults'),
480
          'page arguments' => array($this->entity_type, 'reset', $position, $view_mode),
481
          'type' => MENU_CALLBACK,
482
        ) + $base;
483 e5e66f93 Assos Assos
484
        if ($this->supports_revisions) {
485
          $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode . '/' . $path] = array(
486
            'title' => $operation['menu title'],
487
            'page arguments' => array($this->entity_type, $path, $position, $view_mode),
488
            'access arguments' => array($this->entity_type, 'access', 'admin', $position, $path, $view_mode),
489
            'weight' => $weight++,
490
          ) + $rev_base;
491
492
          if (isset($operation['file'])) {
493
            $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode . '/' . $path]['file'] = $operation['file'];
494
          }
495
          if (isset($operation['file path'])) {
496
            $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode . '/' . $path]['file path'] = $operation['file path'];
497
          }
498
        }
499
500
        // Make the 'content' URLs the local default tasks.
501
        $items[$this->plugin['entity path'] . '/panelizer/' . $view_mode . '/content']['type'] = MENU_DEFAULT_LOCAL_TASK;
502
        if ($this->supports_revisions && isset($items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode . '/content']['type'])) {
503
          $items[$this->plugin['entity path'] . '/revisions/%panelizer_node_revision/panelizer/' . $view_mode . '/content']['type'] = MENU_DEFAULT_LOCAL_TASK;
504
        }
505 85ad3d82 Assos Assos
      }
506
    }
507
508 e5e66f93 Assos Assos
    if (!empty($items)) {
509
      ksort($items);
510
    }
511
512 85ad3d82 Assos Assos
    // Also add administrative links to the bundle.
513
    if (!empty($this->entity_admin_root)) {
514
      $this->add_admin_links($this->entity_admin_root, $this->entity_admin_bundle, $items);
515
    }
516
  }
517
518
  /**
519
   * Helper function to add administrative menu items into an entity's already existing structure.
520
   *
521
   * While this very closely follows the administrative items placed into the
522
   * menu in admin.inc, it is a little bit different because of how bundles
523
   * are placed into the URL. So the code is close but not QUITE reusable
524
   * without going through some hoops.
525
   *
526
   * @param $root
527
   *   The root path. This will be something like 'admin/structure/types/manage/%'.
528
   *   Everything will be placed at $root/panelizer/*.
529
   * @param $bundle
530
   *   This is either the numeric position of the bundle or, for entity types
531
   *   that do not support bundles, a hard coded bundle string.
532
   * @param &$items
533
   *   The array of menu items this is being added to.
534
   */
535
  public function add_admin_links($root, $bundle, &$items) {
536
    // Node $root = 'admin/structure/types/manage/%
537
    // Taxonomy $root = 'admin/structure/taxonomy/%'
538
    // User $root = 'admin/config/people/accounts'
539
    $parts = explode('/', $root);
540
    $base_count = count($parts);
541
542
    // Configure settings pages.
543
    $settings_base = array(
544
      'access callback' => 'panelizer_is_panelized',
545
      'access arguments' => array($this->entity_type, $bundle),
546
      'file' => 'includes/admin.inc',
547
    );
548
549
    // This is the base tab that will be added. The weight is set
550
    // to try and make sure it stays to the right of manage fields
551
    // and manage display.
552
    $items[$root . '/panelizer'] = array(
553
      'title' => 'Panelizer',
554
      'page callback' => 'panelizer_allowed_content_page',
555
      'page arguments' => array($this->entity_type, $bundle),
556
      'type' => MENU_LOCAL_TASK,
557
      'weight' => 5,
558
    ) + $settings_base;
559
560
    $items[$root . '/panelizer/allowed'] = array(
561
      'title' => 'Allowed content',
562
      'page callback' => 'panelizer_allowed_content_page',
563
      'page arguments' => array($this->entity_type, $bundle),
564
      'type' => MENU_DEFAULT_LOCAL_TASK,
565
      'weight' => -10,
566
    ) + $settings_base;
567
568
    $weight = 1;
569
    foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
570
      $tabs_base = array(
571
        'access callback' => 'panelizer_has_no_choice_callback',
572
        'access arguments' => array($this->entity_type, $bundle, $view_mode),
573
        'page arguments' => array($this->entity_type, $bundle, 'default', $view_mode),
574
        'type' => MENU_LOCAL_TASK,
575
        'file' => 'includes/admin.inc',
576
        'weight' => $weight++,
577
      );
578
579
      $items[$root . '/panelizer/' . $view_mode] = array(
580
        'access callback' => 'panelizer_is_panelized',
581
        'title' => $view_mode_info['label'],
582
        'page callback' => 'panelizer_default_list_or_settings_page',
583
      ) + $tabs_base;
584
585
      $index = 0;
586
      foreach (panelizer_operations() as $path => $operation) {
587
        $items[$root . '/panelizer/' . $view_mode . '/' . $path] = array(
588
          'title' => $operation['menu title'],
589
          'page callback' => $operation['admin callback'],
590
          // Use the index to keep them in the proper order.
591
          'weight' => $index - 4,
592
          'type' => ($index === 0) ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
593
        ) + $tabs_base;
594
        if (isset($operation['file'])) {
595
          $items[$root . '/panelizer/' . $view_mode . '/' . $path]['file'] = $operation['file'];
596
        }
597
        if (isset($operation['file path'])) {
598
          $items[$root . '/panelizer/' . $view_mode . '/' . $path]['file path'] = $operation['file path'];
599
        }
600
        $index++;
601
      }
602
603
      $subtabs_base = array(
604
        'access callback' => 'panelizer_administer_panelizer_default',
605
        'access arguments' => array($this->entity_type, $bundle, $base_count + 2, $base_count + 1),
606
        'page arguments' => array($this->entity_type, $bundle, $base_count + 2, $base_count + 1),
607
        'type' => MENU_LOCAL_TASK,
608
        'file' => 'includes/admin.inc',
609
      );
610
611
      $items[$root . '/panelizer/' . $view_mode . '/%'] = array(
612
        'title' => 'Settings',
613
        'page callback' => 'panelizer_default_settings_page',
614
        'title callback' => 'panelizer_default_name_title_callback',
615
        'type' => MENU_CALLBACK,
616
      ) + $subtabs_base;
617
618
      $index = 0;
619
      foreach (panelizer_operations() as $path => $operation) {
620
        $items[$root . '/panelizer/' . $view_mode . '/%/' . $path] = array(
621
          'title' => $operation['menu title'],
622
          'page callback' => $operation['admin callback'],
623
          // Use the index to keep them in the proper order.
624
          'weight' => $index - 4,
625
        ) + $subtabs_base;
626
        if (isset($operation['file'])) {
627
          $items[$root . '/panelizer/' . $view_mode . '/%/' . $path]['file'] = $operation['file'];
628
        }
629
        if (isset($operation['file path'])) {
630
          $items[$root . '/panelizer/' . $view_mode . '/%/' . $path]['file path'] = $operation['file path'];
631
        }
632
        $index++;
633
      }
634
635
      // This special tab isn't a normal operation because appears only
636
      // in the admin menu.
637
      $items[$root . '/panelizer/' . $view_mode . '/%/access'] = array(
638
        'title' => 'Access',
639
        'page callback' => 'panelizer_default_access_page',
640
        'weight' => -2,
641
      ) + $subtabs_base;
642
643
      // Also make clones of all the export UI menu items. Again there is some
644
      // duplicated code here because of subtle differences.
645 e5e66f93 Assos Assos
      // Load the $plugin information.
646
      ctools_include('export-ui');
647 85ad3d82 Assos Assos
      $plugin = ctools_get_export_ui('panelizer_defaults');
648
649
      $ui_items = $plugin['menu']['items'];
650
651
      // Change the item to a tab.
652
      $ui_items['list']['type'] = MENU_LOCAL_TASK;
653
      $ui_items['list']['weight'] = -6;
654
      $ui_items['list']['title'] = 'List';
655
656 e5e66f93 Assos Assos
      // Menu local actions are weird.
657
      if (isset($ui_items['add']['path'])) {
658
        $ui_items['add']['path'] = 'list/add';
659
      }
660
      if (isset($ui_items['import']['path'])) {
661
        $ui_items['import']['path'] = 'list/import';
662
      }
663 85ad3d82 Assos Assos
664 e5e66f93 Assos Assos
      // Edit is being handled elsewhere.
665 85ad3d82 Assos Assos
      unset($ui_items['edit callback']);
666
      unset($ui_items['access']);
667
      unset($ui_items['list callback']);
668
      foreach (panelizer_operations() as $path => $operation) {
669
        $location = isset($operation['ui path']) ? $operation['ui path'] : $path;
670
        if (isset($ui_items[$location])) {
671
          unset($ui_items[$location]);
672
        }
673
      }
674
675 e5e66f93 Assos Assos
      // Change the callbacks for everything.
676 85ad3d82 Assos Assos
      foreach ($ui_items as $key => $item) {
677
        // originally admin/config/content/panelizer/%panelizer_handler
678
        $ui_items[$key]['access callback'] = 'panelizer_has_choice_callback_view_mode';
679
        $ui_items[$key]['access arguments'] = array($this->entity_type, $bundle, $view_mode);
680
        $ui_items[$key]['page callback'] = 'panelizer_default_list_or_settings_page';
681
        $ui_items[$key]['page arguments'][0] = $view_mode;
682
        array_unshift($ui_items[$key]['page arguments'], '');
683
        array_unshift($ui_items[$key]['page arguments'], $bundle);
684
        array_unshift($ui_items[$key]['page arguments'], $this->entity_type);
685
        $ui_items[$key]['path'] = str_replace('list/', '', $ui_items[$key]['path']);
686 e5e66f93 Assos Assos
687
        // Some of the page arguments attempt to pass the eight argument (item
688
        // #7, starting at 0) to the callback in order to work on the display
689
        // object. However, for some entities this will end up being the $op
690
        // instead of the object name, e.g. 'clone' instead of
691
        // 'taxonomy_term:tags:default'.
692
        if (!empty($ui_items[$key]['page arguments'][5]) && is_numeric($bundle)) {
693
          $ui_items[$key]['page arguments'][5] = $bundle + 3;
694
        }
695 85ad3d82 Assos Assos
      }
696
697
      foreach ($ui_items as $item) {
698
        // Add menu item defaults.
699
        $item += array(
700
          'file' => 'export-ui.inc',
701
          'file path' => drupal_get_path('module', 'ctools') . '/includes',
702
        );
703
704
        $path = !empty($item['path']) ? $root . '/panelizer/' . $view_mode . '/' . $item['path'] : $root . '/panelizer/' . $view_mode;
705
        unset($item['path']);
706
        $items[$path] = $item;
707
      }
708
    }
709
  }
710
711 e5e66f93 Assos Assos
  /**
712
   * Identify the view modes that are available for use with this entity bundle.
713
   *
714
   * @param string $bundle
715
   *   The entity bundle to identify. Defaults to '0', a placeholder for all
716
   *   bundles on this entity.
717
   *
718
   * @return array
719
   *   A list of view modes that are available to be panelized.
720
   */
721
  public function get_available_view_modes($bundle = 0) {
722
    if (!isset($this->enabled_view_modes[$bundle])) {
723
      $view_modes = array();
724
      $entity_info = entity_get_info($this->entity_type);
725
      $bundle_info = array();
726
      $view_mode_settings = array();
727
      if (!empty($bundle)) {
728
        $view_mode_settings = field_view_mode_settings($this->entity_type, $bundle);
729
730
        if (isset($entity_info['bundles'][$bundle])) {
731
          $bundle_info = $entity_info['bundles'][$bundle];
732
        }
733
      }
734
735
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
736
        // Automatically allow view modes that are part of Panels.
737
        if (isset($entity_info['view modes'][$view_mode])) {
738
          // Skip this view mode if it isn't enabled for this bundle.
739
          if (!empty($bundle)) {
740
            if (empty($view_mode_settings[$view_mode]['custom_settings'])) {
741
              continue;
742
            }
743
          }
744
          // When configuring a new bundle for an entity, the view modes that are by
745
          // default set to now have custom settings will be hidden, to avoid
746
          // confusion.
747
          else {
748
            if (isset($entity_info['view modes'][$view_mode]['custom settings']) && empty($entity_info['view modes'][$view_mode]['custom settings'])) {
749
              continue;
750
            }
751
          }
752
        }
753
        $this->enabled_view_modes[$bundle][$view_mode] = $view_mode_info['label'];
754
      }
755
    }
756
757
    return $this->enabled_view_modes[$bundle];
758
  }
759
760
  /**
761
   * Identify the view modes that are enabled for use with Panelizer.
762
   *
763
   * @param string $bundle
764
   *   The entity bundle to identify. Defaults to '0', a placeholder for all
765
   *   bundles on this entity.
766
   *
767
   * @return array
768
   *   A list of view modes that are panelized.
769
   */
770
  public function get_enabled_view_modes($bundle) {
771
    $enabled = array();
772
    $available = $this->get_available_view_modes($bundle);
773
  }
774
775
  /**
776
   * Identify the view mode that will actually be used for a specific request.
777
   *
778
   * @param string $view_mode
779
   *   The original view mode to be checked.
780
   * @param string $bundle
781
   *   The entity bundle being used.
782
   *
783
   * @return string
784
   *   The final view mode that will be used.
785
   */
786
  public function get_view_mode($view_mode, $bundle) {
787
    $settings = !empty($this->plugin['bundles'][$bundle]) ? $this->plugin['bundles'][$bundle] : array('status' => FALSE, 'choice' => FALSE);
788
789
    // Test to see if this view mode is actually panelizable at all.
790
    if (!isset($this->plugin['view modes'][$view_mode]) || (empty($this->plugin['view modes'][$view_mode]['custom settings']) && empty($this->plugin['view mode status'][$bundle][$view_mode]))) {
791
      $view_mode = 'default';
792
    }
793
794
    // See if a substitute should be used.
795
    $substitute = $this->get_substitute($view_mode, $bundle);
796
    if (!empty($substitute)) {
797
      $view_mode = $substitute;
798
    }
799
800
    return $view_mode;
801
  }
802
803
  /**
804
   * Obtain the machine name of the Page Manager task.
805
   *
806
   * @return string
807
   *   The machine name for the Page Manager task; returns FALSE if this
808
   *   entity does not support Page Manager.
809
   */
810
  public function get_page_manager_task_name() {
811
    if (empty($this->plugin['uses page manager'])) {
812
      return FALSE;
813
    }
814
    else {
815
      return $this->entity_type . '_view';
816
    }
817
  }
818
819
  /**
820
   * Identifies a substitute view mode for a given bundle.
821
   *
822
   * @param string $view_mode
823
   *   The original view mode to be checked.
824
   * @param string $bundle
825
   *   The entity bundle being checked.
826
   *
827
   * @return string
828
   *   The view mode that will be used.
829
   */
830
  public function get_substitute($view_mode, $bundle) {
831
    $substitute = '';
832
833
    // See if a substitute should be used.
834
    $settings = !empty($this->plugin['bundles'][$bundle]) ? $this->plugin['bundles'][$bundle] : array('status' => FALSE, 'choice' => FALSE);
835
    if (!empty($settings['view modes'][$view_mode]['substitute'])) {
836
      $substitute = $settings['view modes'][$view_mode]['substitute'];
837
    }
838
839
    return $substitute;
840
  }
841
842
  /**
843
   * Obtain the system path to an entity bundle's display settings page for a
844
   * specific view mode.
845
   *
846
   * @param string $bundle
847
   * @param string $view_mode
848
   *
849
   * @return string
850
   *   The system path of the display settings page for this bundle/view mode
851
   *   combination.
852
   */
853
  public function admin_bundle_display_path($bundle, $view_mode) {
854
    $path = $this->entity_admin_root;
855
856
    $pos = strpos($path, '%');
857
    if ($pos !== FALSE) {
858
      $path = substr($path, 0, $pos) . $bundle;
859
    }
860
861
    $path .= '/display';
862
    if ($view_mode != 'default') {
863
      $path .= '/' . $view_mode;
864
    }
865
866
    return $path;
867
  }
868
869
  /**
870
   * Check if the necessary Page Manager display is enabled and the appropriate
871
   * variant has not been disabled.
872
   *
873
   * @return boolean
874
   *   Whether or not both the Page Manager display and the variant are enabled.
875
   */
876
  public function check_page_manager_status() {
877
    $pm_links = array(
878
      '!pm' => l('Page Manager', 'admin/structure/pages'),
879
      '!panels' => l('Panels', 'admin/structure/panels'),
880
      '!task_name' => $this->get_page_manager_task_name(),
881
      '!entity_type' => $this->entity_type,
882
    );
883
884
    // The display in Page Manager must be enabled.
885
    if ($this->is_page_manager_enabled()) {
886
      drupal_set_message(t('Note: "!task_name" display must be enabled in !pm in order for the !entity_type full page display ("Full page override") to work correctly.', $pm_links), 'warning', FALSE);
887
      return FALSE;
888
    }
889
    // The Panelizer variant must also be enabled.
890
    else {
891
      $task = page_manager_get_task($pm_links['!task_name']);
892
      $handler = page_manager_load_task_handler($task, '', 'term_view_panelizer');
893
      if (!empty($handler->disabled)) {
894
        drupal_set_message(t('The "Panelizer" variant on the "!task_name" display is currently not enabled in !pm. This must be enabled for Panelizer to be able to display !entity_types using the "Full page override" view mode.', $pm_links), 'warning', FALSE);
895
        return FALSE;
896
      }
897
    }
898
899
    return TRUE;
900
  }
901
902 85ad3d82 Assos Assos
  /**
903
   * Add the panelizer settings form to a single entity bundle config form.
904
   *
905
   * @param &$form
906
   *   The form array.
907
   * @param &$form_state
908
   *   The form state array.
909
   * @param $bundle
910
   *   The machine name of the bundle this form is for.
911
   * @param $type_location
912
   *   The location in the form state values that the bundle name will be;
913
   *   this is used so that if a machine name of a bundle is changed, Panelizer
914
   *   can update as much as possible.
915
   */
916
  public function add_bundle_setting_form(&$form, &$form_state, $bundle, $type_location) {
917 e5e66f93 Assos Assos
    $settings = !empty($this->plugin['bundles'][$bundle]) ? $this->plugin['bundles'][$bundle] : array('status' => FALSE, 'choice' => FALSE);
918
    $entity_info = entity_get_info($this->entity_type);
919
    $perms_url = url('admin/people/permissions');
920
    $manage_display = t('Manage Display');
921
    $bundle_info = array();
922
    if (isset($entity_info['bundles'][$bundle])) {
923
      $bundle_info = $entity_info['bundles'][$bundle];
924
      if (!empty($bundle_info['admin']['real path'])) {
925
        $manage_display = l($manage_display, $bundle_info['admin']['real path'] . '/display');
926
      }
927
    }
928
    $view_mode_settings = array();
929
    if (!empty($bundle)) {
930
      $view_mode_settings = field_view_mode_settings($this->entity_type, $bundle);
931
    }
932 85ad3d82 Assos Assos
933
    $form['panelizer'] = array(
934
      '#type' => 'fieldset',
935
      '#title' => t('Panelizer'),
936
      '#collapsible' => TRUE,
937
      '#collapsed' => FALSE,
938
      '#group' => 'additional_settings',
939
      '#attributes' => array(
940 e5e66f93 Assos Assos
        'class' => array('panelizer-entity-bundle'),
941 85ad3d82 Assos Assos
      ),
942
      '#bundle' => $bundle,
943
      '#location' => $type_location,
944
      '#tree' => TRUE,
945
      '#access' => panelizer_administer_entity_bundle($this, $bundle),
946 e5e66f93 Assos Assos
      '#attached' => array(
947
        'js' => array(ctools_attach_js('panelizer-entity-bundle', 'panelizer')),
948
      ),
949 85ad3d82 Assos Assos
    );
950
951 e5e66f93 Assos Assos
    // The master checkbox.
952 85ad3d82 Assos Assos
    $form['panelizer']['status'] = array(
953
      '#title' => t('Panelize'),
954
      '#type' => 'checkbox',
955
      '#default_value' => !empty($settings['status']),
956
      '#id' => 'panelizer-status',
957 e5e66f93 Assos Assos
      '#description' => t('Allow content of this type to have its display controlled by Panelizer. Once enabled, each individual view mode will have further options and will add <a href="!perm_url">several new permissions</a>.', array('!perm_url' => $perms_url)) . '<br />'
958
        . t('Other than "Full page override" and "Default", only view modes enabled through the Custom Display Settings section of the !manage_display tab will be available for use.', array('!manage_display' => $manage_display)) . '<br />'
959
        . t('Once enabled, a new tab named "Customize display" will show on pages for this content.'),
960 85ad3d82 Assos Assos
    );
961
962 e5e66f93 Assos Assos
    // Help, I need somebody.
963
    $form['panelizer']['help'] = array(
964
      '#title' => t('Optional help message to show above the display selector, if applicable'),
965
      '#type' => 'textarea',
966
      '#rows' => 3,
967
      '#default_value' => !empty($settings['help']) ? $settings['help'] : '',
968
      '#id' => 'panelizer-help',
969
      '#description' => t('Only used if one or more of the view modes has a display that allows multiple values and the "Customize display" tab is to be shown on the entity edit form. Allows HTML.'),
970
      '#states' => array(
971
        'visible' => array(
972
          '#panelizer-status' => array('checked' => TRUE),
973
        ),
974
      ),
975
    );
976
977
    $view_modes = $this->get_available_view_modes($bundle);
978
    foreach ($view_modes as $view_mode => $view_mode_label) {
979
      $view_mode_info = $this->plugin['view modes'][$view_mode];
980
981 85ad3d82 Assos Assos
      $form['panelizer']['view modes'][$view_mode] = array(
982
        '#type' => 'item',
983 e5e66f93 Assos Assos
        // '#title' => '<hr />' . $view_mode_info['label'],
984 85ad3d82 Assos Assos
        '#states' => array(
985
          'visible' => array(
986
            '#panelizer-status' => array('checked' => TRUE),
987
          ),
988
        ),
989
      );
990
991 e5e66f93 Assos Assos
      // Show the optional view mode description.
992
      $pm_links = array(
993
        '!pm' => l('Page Manager', 'admin/structure/pages'),
994
        '!panels' => l('Panels', 'admin/structure/panels'),
995
        '!entity_type' => $this->entity_type,
996
        '!task_name' => $this->get_page_manager_task_name(),
997
      );
998
999
      $description = '';
1000
      if ($view_mode == 'default') {
1001
        $description = t('If a requested view mode for an entity was not enabled in the !manage_display tab page, this view mode will be used as a failover. For example, if "Teaser" was being used but it was not enabled.', array('!manage_display' => $manage_display));
1002
      }
1003
      elseif ($view_mode == 'page_manager') {
1004
        $description = t("A custom view mode only used when !pm/!panels is used to control this entity's full page display, i.e. the '!task_name' display is enabled. Unlike the \"!full\" view mode, this one allows customization of the page title.",
1005
          $pm_links + array(
1006
            '!full' => !empty($entity_info['view modes']['full']['label']) ? $entity_info['view modes']['full']['label'] : 'Full',
1007
          ));
1008
      }
1009
      elseif ($view_mode == 'full') {
1010
        $description = t('Used when viewing !entity_type entities on their standalone page, does not allow customization of the page title.', array('!entity_type' => $this->entity_type));
1011
      }
1012
      elseif ($view_mode == 'teaser') {
1013
        $description = t('Used in content lists by default, e.g. on the default homepage and on taxonomy term pages.');
1014
      }
1015
      elseif ($view_mode == 'rss') {
1016
        $description = t('Used by the default RSS content lists.');
1017
      }
1018 85ad3d82 Assos Assos
      $form['panelizer']['view modes'][$view_mode]['status'] = array(
1019 e5e66f93 Assos Assos
        '#title' => $view_mode_info['label'],
1020 85ad3d82 Assos Assos
        '#type' => 'checkbox',
1021
        '#default_value' => !empty($settings['view modes'][$view_mode]['status']),
1022
        '#id' => 'panelizer-' . $view_mode . '-status',
1023 e5e66f93 Assos Assos
        '#prefix' => '<hr />',
1024
        '#description' => $description,
1025
        '#attributes' => array(
1026
          'title' => $view_mode_info['label'],
1027
        ),
1028
        '#states' => array(
1029
          'visible' => array(
1030
            '#panelizer-status' => array('checked' => TRUE),
1031
          ),
1032
        ),
1033
      );
1034
      if ($view_mode == 'page_manager') {
1035
        if (!$this->is_page_manager_enabled()) {
1036
          $form['panelizer']['view modes'][$view_mode]['status']['#title'] .= ' (<em>'
1037
            . t('!pm is enabled correctly', $pm_links)
1038
            . '</em>)';
1039
        }
1040
        else {
1041
          $form['panelizer']['view modes'][$view_mode]['status']['#title'] .= ' (<em>'
1042
            . t('"!task_name" must be enabled in !pm', $pm_links)
1043
            . '</em>)';
1044
          // Only display this message if the form has not been submitted, the
1045
          // bundle has been panelized and the view mode is panelized.
1046
          if (empty($form_state['input']) && !empty($settings['status']) && !empty($settings['view modes'][$view_mode]['status'])) {
1047
            drupal_set_message(t('Note: "!task_name" display must be enabled in !pm in order for the !entity_type full page display ("Full page override") to work correctly.', $pm_links), 'warning', FALSE);
1048
          }
1049
        }
1050
      }
1051
1052
      $options = array('' => t('- Ignore this option -')) + $view_modes;
1053
      unset($options[$view_mode]);
1054
      $form['panelizer']['view modes'][$view_mode]['substitute'] = array(
1055
        '#title' => t('Substitute a different view mode in place of this one'),
1056
        '#description' => t("Allows this view mode to be enabled but for the actual display to be handled by another view mode. This can save on configuration effort should multiple view modes need to look the same."),
1057
        '#type' => 'select',
1058
        '#options' => $options,
1059
        '#default_value' => $this->get_substitute($view_mode, $bundle),
1060
        '#id' => 'panelizer-' . $view_mode . '-substitute',
1061 85ad3d82 Assos Assos
        '#states' => array(
1062
          'visible' => array(
1063
            '#panelizer-status' => array('checked' => TRUE),
1064 e5e66f93 Assos Assos
            '#panelizer-' . $view_mode . '-status' => array('checked' => TRUE),
1065 85ad3d82 Assos Assos
          ),
1066
        ),
1067
      );
1068 e5e66f93 Assos Assos
1069 85ad3d82 Assos Assos
      $form['panelizer']['view modes'][$view_mode]['default'] = array(
1070 e5e66f93 Assos Assos
        '#title' => t('Provide an initial display named "Default"'),
1071 85ad3d82 Assos Assos
        '#type' => 'checkbox',
1072 e5e66f93 Assos Assos
        '#default_value' => !empty($settings['view modes'][$view_mode]['status']) && !empty($settings['view modes'][$view_mode]['default']),
1073
        '#id' => 'panelizer-' . $view_mode . '-initial',
1074 85ad3d82 Assos Assos
        '#states' => array(
1075
          'visible' => array(
1076
            '#panelizer-status' => array('checked' => TRUE),
1077
            '#panelizer-' . $view_mode . '-status' => array('checked' => TRUE),
1078 e5e66f93 Assos Assos
            '#panelizer-' . $view_mode . '-substitute' => array('value' => ''),
1079 85ad3d82 Assos Assos
          ),
1080
        ),
1081
      );
1082
1083 e5e66f93 Assos Assos
      // Obtain a list of all available panels for this view mode / bundle.
1084
      $panelizers = $this->get_default_panelizer_objects($bundle . '.' . $view_mode);
1085
      $options = array();
1086
      if (!empty($panelizers)) {
1087
        foreach ($panelizers as $name => $panelizer) {
1088
          // Don't show disabled displays.
1089
          if (empty($panelizer->disabled)) {
1090
            $options[$name] = $panelizer->title;
1091
          }
1092
        }
1093
      }
1094
      if (!empty($options)) {
1095
        ksort($options);
1096
      }
1097
1098
      // The default display to be used if nothing found.
1099
      $default_name = implode(':', array($this->entity_type, $bundle, 'default'));
1100
      $variable_name = 'panelizer_' . $this->entity_type . ':' . $bundle . ':' . $view_mode . '_selection';
1101
      if ($view_mode != 'page_manager') {
1102
        $default_name .= ':' . $view_mode;
1103
      }
1104
      // If this has not been set previously, use the 'default' as the default
1105
      // selection.
1106
      $default_value = variable_get($variable_name, FALSE);
1107
      if (empty($default_value)) {
1108
        $default_value = $default_name;
1109
      }
1110
      // Indicate which item is actually the default.
1111
      if (count($options) > 1 && isset($options[$default_value])) {
1112
        $options[$default_value] .= ' (' . t('default') . ')';
1113
      }
1114
1115
      if (!empty($bundle_info) && count($options) > 0) {
1116
        $form['panelizer']['view modes'][$view_mode]['selection'] = array(
1117
          '#title' => t('Default panel'),
1118
          '#type' => 'select',
1119
          '#options' => $options,
1120
          '#default_value' => $default_value,
1121
          '#id' => 'panelizer-' . $view_mode . '-default',
1122
          '#states' => array(
1123
            'visible' => array(
1124
              '#panelizer-status' => array('checked' => TRUE),
1125
              '#panelizer-' . $view_mode . '-status' => array('checked' => TRUE),
1126
              '#panelizer-' . $view_mode . '-substitute' => array('value' => ''),
1127
            ),
1128
          ),
1129
          '#required' => count($options),
1130
          '#disabled' => count($options) == 0,
1131
          '#description' => t('The default display to be used for new %bundle records. If "Allow panel choice" is not enabled, the item selected will be used for any new %bundle record. All existing %bundle records will have to be manually updated to the new selection.', array('%bundle' => $bundle)),
1132
        );
1133
1134
        $form['panelizer']['view modes'][$view_mode]['default revert'] = array(
1135
          '#type' => 'checkbox',
1136
          '#title' => t('Update existing entities to use this display'),
1137
          '#states' => array(
1138
            'visible' => array(
1139
              '#panelizer-status' => array('checked' => TRUE),
1140
              '#panelizer-' . $view_mode . '-status' => array('checked' => TRUE),
1141
              '#panelizer-' . $view_mode . '-substitute' => array('value' => ''),
1142
            ),
1143
          ),
1144
          '#description' => t('Will update all %bundle records to use the newly selected display, unless they have been customized. Note: only takes effect when the display is changed, and will not work if the default was not assigned previously.', array('%bundle' => $bundle)),
1145
          '#field_prefix' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
1146
        );
1147
      }
1148
1149
      // Control whether the default can be selected.
1150 85ad3d82 Assos Assos
      $form['panelizer']['view modes'][$view_mode]['choice'] = array(
1151 e5e66f93 Assos Assos
        '#title' => t('Allow per-record display choice'),
1152 85ad3d82 Assos Assos
        '#type' => 'checkbox',
1153 e5e66f93 Assos Assos
        '#default_value' => !empty($settings['view modes'][$view_mode]['status']) && !empty($settings['view modes'][$view_mode]['choice']),
1154
        '#id' => 'panelizer-' . $view_mode . '-choice',
1155 85ad3d82 Assos Assos
        '#states' => array(
1156
          'visible' => array(
1157
            '#panelizer-status' => array('checked' => TRUE),
1158
            '#panelizer-' . $view_mode . '-status' => array('checked' => TRUE),
1159 e5e66f93 Assos Assos
            '#panelizer-' . $view_mode . '-substitute' => array('value' => ''),
1160 85ad3d82 Assos Assos
          ),
1161
        ),
1162 e5e66f93 Assos Assos
        '#description' => t("Allows multiple displays to be created for this view mode. Once created, a selector will be provided on the %bundle record's edit form allowing the display of this view mode to be chosen. Additionally, any customizations made will be based upon the selected display. Note: the selector will not be shown if there is only one display, instead the default will be automatically selected.", array('%bundle' => $bundle)),
1163 85ad3d82 Assos Assos
      );
1164 e5e66f93 Assos Assos
      if (!empty($bundle)) {
1165
        $form['panelizer']['view modes'][$view_mode]['choice']['#description'] .= '<br />'
1166
          . t('This option adds a <a href="!perm_url">new permission</a>: !perm',
1167
            array(
1168
              '!perm_url' => $perms_url,
1169
              '!perm' => t('%entity_name %bundle_name: Choose panels',
1170
                array(
1171
                  '%entity_name' => $entity_info['label'],
1172
                  '%bundle_name' => $entity_info['bundles'][$bundle]['label'],
1173
                )
1174
              ),
1175
            )
1176
          );
1177
      }
1178 85ad3d82 Assos Assos
    }
1179
1180
    array_unshift($form['#submit'], 'panelizer_entity_default_bundle_form_submit');
1181
1182
    $form_state['panelizer_entity_handler'] = $this;
1183
  }
1184
1185
  /**
1186
   * Submit callback for the bundle edit form.
1187
   */
1188
  public function add_bundle_setting_form_submit($form, &$form_state, $bundle, $type_location) {
1189
    // Some types do not support changing bundles, so we don't check if it's
1190
    // not possible to change.
1191
    if ($type_location) {
1192
      $new_bundle = drupal_array_get_nested_value($form_state['values'], $type_location);
1193
    }
1194
    else {
1195
      $new_bundle = $bundle;
1196
    }
1197
1198 e5e66f93 Assos Assos
    // Check to see if the bundle has changed. If so, we need to move stuff
1199
    // around.
1200 85ad3d82 Assos Assos
    if ($bundle && $new_bundle != $bundle) {
1201
      // Remove old settings.
1202
      variable_del('panelizer_defaults_' . $this->entity_type . '_' . $bundle);
1203
      $allowed_layouts = variable_get('panelizer_' . $this->entity_type . ':' . $bundle . '_allowed_layouts', NULL);
1204
      if ($allowed_layouts) {
1205
        variable_del('panelizer_' . $this->entity_type . ':' . $bundle . '_allowed_layouts');
1206
        variable_set('panelizer_' . $this->entity_type . ':' . $new_bundle . '_allowed_layouts', $allowed_layouts);
1207
      }
1208
      $default = variable_get('panelizer_' . $this->entity_type . ':' . $bundle . '_default', NULL);
1209
      if ($default) {
1210
        variable_del('panelizer_' . $this->entity_type . ':' . $bundle . '_default');
1211
        variable_set('panelizer_' . $this->entity_type . ':' . $new_bundle . '_default', $default);
1212
      }
1213
1214
      // Load up all panelizer defaults for the old bundle and resave them
1215
      // for the new bundle.
1216
      $panelizer_defaults = $this->get_default_panelizer_objects($bundle);
1217 e5e66f93 Assos Assos
      if (!empty($panelizer_defaults)) {
1218
        foreach ($panelizer_defaults as $panelizer) {
1219
          list($entity_type, $old_bundle, $name) = explode(':', $panelizer->name);
1220
          $panelizer->name = implode(':', array($entity_type, $new_bundle, $name));
1221
          if ($panelizer->view_mode != 'page_manager') {
1222
            $panelizer->name .= ':' . $panelizer->view_mode;
1223
          }
1224
1225
          // The default display selection.
1226
          $old_variable_name = 'panelizer_' . $this->entity_type . ':' . $bundle . ':' . $panelizer->view_mode . '_selection';
1227
          $new_variable_name = 'panelizer_' . $this->entity_type . ':' . $new_bundle . ':' . $panelizer->view_mode . '_selection';
1228
          $default_layout = variable_get($old_variable_name, NULL);
1229
          if (!is_null($default_layout)) {
1230
            variable_set($new_variable_name, $default_layout);
1231
            variable_del($old_variable_name);
1232
          }
1233
1234
          $panelizer->panelizer_key = $new_bundle;
1235
          // If there's a pnid this should change the name and retain the pnid.
1236
          // If there is no pnid this will create a new one in the database
1237
          // because exported panelizer defaults attached to a bundle will have
1238
          // to be moved to the database in order to follow along and then be
1239
          // re-exported.
1240
          // @todo Should we warn the user about this?
1241
          ctools_export_crud_save('panelizer_defaults', $panelizer);
1242 85ad3d82 Assos Assos
        }
1243 e5e66f93 Assos Assos
      }
1244
    }
1245 85ad3d82 Assos Assos
1246 e5e66f93 Assos Assos
    // Fix the configuration.
1247
    // If the main configuration is disabled then everything gets disabled.
1248
    if (empty($form_state['values']['panelizer']['status'])) {
1249
      $form_state['values']['panelizer']['view modes'] = array();
1250
    }
1251
    elseif (!empty($form_state['values']['panelizer']['view modes'])) {
1252
      // Make sure each setting is disabled if the view mode is disabled.
1253
      foreach ($form_state['values']['panelizer']['view modes'] as $view_mode => &$config) {
1254
        if (empty($config['status'])) {
1255
          foreach ($config as $key => $val) {
1256
            $config[$key] = 0;
1257
          }
1258
        }
1259
      }
1260
    }
1261
1262
    // Save the default display for this bundle to a variable so that it may be
1263
    // controlled separately.
1264
    foreach ($this->get_default_panelizer_objects($new_bundle) as $panelizer) {
1265
      if (isset($form_state['values']['panelizer']['view modes'][$panelizer->view_mode]['selection'])) {
1266
        $variable_name = 'panelizer_' . $this->entity_type . ':' . $new_bundle . ':' . $panelizer->view_mode . '_selection';
1267
        $old_value = variable_get($variable_name, NULL);
1268
        $new_value = $form_state['values']['panelizer']['view modes'][$panelizer->view_mode]['selection'];
1269
1270
        // Save the variable.
1271
        variable_set($variable_name, $new_value);
1272
1273
        // Cleanup.
1274
1275
        // Additional cleanup if the default display was changed.
1276
        if (!is_null($old_value) && $old_value != $new_value) {
1277
          // The user specifically requested that existing entities are to be
1278
          // updated to the new display.
1279
          if (!empty($form_state['values']['panelizer']['view modes'][$panelizer->view_mode]['default revert'])) {
1280
            $updated_count = db_update('panelizer_entity')
1281
              ->fields(array('name' => $new_value))
1282
              ->condition('name', $old_value)
1283
              ->execute();
1284
            drupal_set_message(t('@count @entity records were updated to the new Panelizer display for the @mode view mode.', array('@count' => $updated_count, '@entity' => $this->entity_type, '@mode' => $panelizer->view_mode)));
1285
1286
            // If EntityCache is enabled, clear all records of this type. This
1287
            // is a little heavy-handed, but I don't believe there's an easy way
1288
            // to clear only entities of certain types without querying for them
1289
            // first, which could trigger an execution timeout.
1290
            if (module_exists('entitycache')) {
1291
              cache_clear_all('*', 'cache_entity_' . $this->entity_type, TRUE);
1292
            }
1293
          }
1294
        }
1295
      }
1296
    }
1297
1298
    // Remove some settings that shouldn't be saved with the others.
1299
    if (!empty($form_state['values']['panelizer']['view modes'])) {
1300
      foreach ($form_state['values']['panelizer']['view modes'] as $view_mode => $settings) {
1301
        unset($form_state['values']['panelizer']['view modes'][$view_mode]['selection']);
1302
        unset($form_state['values']['panelizer']['view modes'][$view_mode]['default revert']);
1303 85ad3d82 Assos Assos
      }
1304
    }
1305
1306
    variable_set('panelizer_defaults_' . $this->entity_type . '_' . $new_bundle, $form_state['values']['panelizer']);
1307
1308 e5e66f93 Assos Assos
    // Verify the necessary Page Manager prerequisites are ready.
1309
    if (!empty($form_state['values']['panelizer']['status'])
1310
      && !empty($form_state['values']['panelizer']['view modes']['page_manager']['status'])
1311
      && $this->is_page_manager_enabled()) {
1312
      $this->check_page_manager_status();
1313
    }
1314
1315 85ad3d82 Assos Assos
    // Unset this so that the type save forms don't try to save it to variables.
1316
    unset($form_state['values']['panelizer']);
1317
  }
1318
1319
  /**
1320
   * Implements a delegated hook_menu.
1321
   */
1322
  public function hook_admin_paths(&$items) {
1323
    if (!empty($this->plugin['entity path'])) {
1324
      $bits = explode('/', $this->plugin['entity path']);
1325
      foreach ($bits as $count => $bit) {
1326
        if (strpos($bit, '%') === 0) {
1327
          $bits[$count] = '*';
1328
        }
1329
      }
1330
1331
      $path = implode('/', $bits);
1332
      $items[$path . '/panelizer*'] = TRUE;
1333
    }
1334
  }
1335
1336
  public function hook_menu_alter(&$items) {
1337
1338
  }
1339
1340
  public function hook_form_alter(&$form, &$form_state, $form_id) {
1341
1342
  }
1343
1344 e5e66f93 Assos Assos
  public function get_default_display_default_name($bundle, $view_mode = 'page_manager') {
1345
    $default_name = implode(':', array($this->entity_type, $bundle, 'default'));
1346
1347
    if ($view_mode != 'page_manager') {
1348
      $default_name .= ':' . $view_mode;
1349
    }
1350
1351
    return $default_name;
1352
  }
1353
1354
  public function get_default_display_name($bundle, $view_mode = 'page_manager') {
1355
    $variable_name = $this->get_default_display_variable_name($bundle, $view_mode);
1356
    // If this has not been set previously, use the 'default' as the default
1357
    // selection.
1358
    $default_value = variable_get($variable_name, FALSE);
1359
1360
    if (empty($default_value)) {
1361
      $default_value = $this->get_default_display_default_name($bundle, $view_mode);
1362
    }
1363
1364
    return $default_value;
1365
  }
1366
1367
  public function default_display_exists($display_name) {
1368
    // If the display name is empty then the display doesn't exist.
1369
    if (empty($display_name)) {
1370
      return FALSE;
1371
    }
1372
1373
    $parts = explode(':', $display_name);
1374
    // If the display name doesn't contain the entity_type, the bundle and the
1375
    // display machine name, then it's an invalid name.
1376
    if (count($parts) <= 2) {
1377
      return FALSE;
1378
    }
1379
1380
    // The entity bundle is the second part of the $display_name string.
1381
    $bundle = $parts[1];
1382
1383
    // If no check was performed already to see if displays exist for this
1384
    // bundle, try loading them.
1385
    if (empty($this->displays_loaded[$bundle])) {
1386
      $this->displays_loaded[$bundle] = TRUE;
1387
      $displays = $this->get_default_panelizer_objects($bundle);
1388
      $this->displays = array_merge($this->displays, $displays);
1389
    }
1390
1391
    return isset($this->displays[$display_name]);
1392
  }
1393
1394
  public function get_default_display_variable_name($bundle, $view_mode = 'page_manager') {
1395
    return 'panelizer_' . $this->entity_type . ':' . $bundle . ':' . $view_mode . '_selection';
1396
  }
1397
1398 85ad3d82 Assos Assos
  // Entity specific Drupal hooks
1399
  public function hook_entity_load(&$entities) {
1400
    ctools_include('export');
1401
    $ids = array();
1402
    $vids = array();
1403
    $bundles = array();
1404
1405
    foreach ($entities as $entity) {
1406
      // Don't bother if somehow we've already loaded and are asked to
1407
      // load again.
1408
      if (!empty($entity->panelizer)) {
1409
        continue;
1410
      }
1411
1412
      list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1413
      if ($this->is_panelized($bundle)) {
1414
        $ids[] = $entity_id;
1415
        if ($this->supports_revisions) {
1416
          $vids[] = $revision_id;
1417
        }
1418
        $bundles[$entity_id] = $bundle;
1419
      }
1420
    }
1421
1422 e5e66f93 Assos Assos
    if (empty($ids)) {
1423 85ad3d82 Assos Assos
      return;
1424
    }
1425
1426
    // Load all the panelizers associated with the list of entities.
1427
    if ($this->supports_revisions) {
1428 e5e66f93 Assos Assos
      $result = db_query("SELECT * FROM {panelizer_entity} WHERE entity_type = :entity_type AND revision_id IN (:vids)", array(':entity_type' => $this->entity_type, ':vids' => $vids));
1429 85ad3d82 Assos Assos
    }
1430
    else {
1431 e5e66f93 Assos Assos
      $result = db_query("SELECT * FROM {panelizer_entity} WHERE entity_type = :entity_type AND entity_id IN (:ids)", array(':entity_type' => $this->entity_type, ':ids' => $ids));
1432 85ad3d82 Assos Assos
    }
1433
1434
    $panelizers = array();
1435
    while ($panelizer = $result->fetchObject()) {
1436
      $panelizers[$panelizer->entity_id][$panelizer->view_mode] = $panelizer;
1437
    }
1438
1439
    $defaults = array();
1440
    $dids = array();
1441 e5e66f93 Assos Assos
1442 85ad3d82 Assos Assos
    // Go through our entity list and generate a list of defaults and displays
1443
    foreach ($entities as $entity_id => $entity) {
1444
      // Don't bother if somehow we've already loaded and are asked to
1445
      // load again.
1446
      if (!empty($entity->panelizer)) {
1447
        continue;
1448
      }
1449
1450
      // Skip not panelized bundles.
1451
      if (empty($bundles[$entity_id])) {
1452
        continue;
1453
      }
1454
1455
      // Check for each view mode.
1456
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
1457 e5e66f93 Assos Assos
        // Skip disabled view modes.
1458
        $check_needed = array_key_exists($view_mode, $this->plugin['bundles'][$bundles[$entity_id]]['view modes']);
1459
        $view_mode_disabled = empty($this->plugin['bundles'][$bundles[$entity_id]]['view modes'][$view_mode]['status']);
1460
        if ($check_needed === FALSE || $view_mode_disabled) {
1461
          continue;
1462 85ad3d82 Assos Assos
        }
1463
1464 e5e66f93 Assos Assos
        // Load the default display for this entity bundle / view_mode.
1465
        $name = $this->get_default_display_name($bundles[$entity_id], $view_mode);
1466
1467 85ad3d82 Assos Assos
        // If no panelizer was loaded for the view mode, queue up defaults.
1468
        if (empty($panelizers[$entity_id][$view_mode]) && $this->has_default_panel($bundles[$entity_id] . '.' . $view_mode)) {
1469
          $defaults[$name] = $name;
1470
        }
1471
        // Otherwise unpack the loaded panelizer.
1472
        else if (!empty($panelizers[$entity_id][$view_mode])) {
1473
          $entity->panelizer[$view_mode] = ctools_export_unpack_object('panelizer_entity', $panelizers[$entity_id][$view_mode]);
1474
          // If somehow we have no name AND no did, fill in the default.
1475
          // This can happen if use of defaults has switched around maybe?
1476 e5e66f93 Assos Assos
          if (empty($entity->panelizer[$view_mode]->did) && empty($entity->panelizer[$view_mode]->name)) {
1477 85ad3d82 Assos Assos
            if ($this->has_default_panel($bundles[$entity_id] . '.' . $view_mode)) {
1478
              $entity->panelizer[$view_mode]->name = $name;
1479
            }
1480
            else {
1481
              // With no default, did or name, this doesn't actually exist.
1482
              unset($entity->panelizer[$view_mode]);
1483
              list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1484
1485
              db_delete('panelizer_entity')
1486
                ->condition('entity_type', $this->entity_type)
1487
                ->condition('entity_id', $entity_id)
1488
                ->condition('revision_id', $revision_id)
1489
                ->condition('view_mode', $view_mode)
1490
                ->execute();
1491
              continue;
1492
            }
1493
          }
1494
1495
          // Panelizers that do not have dids are just a selection of defaults
1496
          // that has never actually been modified.
1497
          if (empty($entity->panelizer[$view_mode]->did) && !empty($entity->panelizer[$view_mode]->name)) {
1498
            $defaults[$entity->panelizer[$view_mode]->name] = $entity->panelizer[$view_mode]->name;
1499
          }
1500
          else {
1501
            $dids[$entity->panelizer[$view_mode]->did] = $entity->panelizer[$view_mode]->did;
1502
          }
1503
        }
1504
      }
1505
    }
1506
1507
    // Load any defaults we collected.
1508 e5e66f93 Assos Assos
    if (!empty($defaults)) {
1509 85ad3d82 Assos Assos
      $panelizer_defaults = $this->load_default_panelizer_objects($defaults);
1510
    }
1511
1512
    // if any panelizers were loaded, get their attached displays.
1513 e5e66f93 Assos Assos
    if (!empty($dids)) {
1514 85ad3d82 Assos Assos
      $displays = panels_load_displays($dids);
1515
    }
1516
1517
    // Now, go back through our entities and assign dids and defaults
1518
    // accordingly.
1519
    foreach ($entities as $entity_id => $entity) {
1520
      // Skip not panelized bundles.
1521
      if (empty($bundles[$entity_id])) {
1522
        continue;
1523
      }
1524 e5e66f93 Assos Assos
1525
      // Reload these.
1526
      list(, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1527
1528 85ad3d82 Assos Assos
      // Check for each view mode.
1529
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
1530
        if (empty($entity->panelizer[$view_mode])) {
1531 e5e66f93 Assos Assos
          // Load the configured default display.
1532
          $default_value = $this->get_default_display_name($bundle, $view_mode);
1533 85ad3d82 Assos Assos
1534 e5e66f93 Assos Assos
          if (!empty($panelizer_defaults[$default_value])) {
1535
            $entity->panelizer[$view_mode] = clone $panelizer_defaults[$default_value];
1536
            // Make sure this entity can't write to the default display.
1537 85ad3d82 Assos Assos
            $entity->panelizer[$view_mode]->did = NULL;
1538 e5e66f93 Assos Assos
            $entity->panelizer[$view_mode]->entity_id = 0;
1539
            $entity->panelizer[$view_mode]->revision_id = 0;
1540 85ad3d82 Assos Assos
          }
1541
        }
1542 e5e66f93 Assos Assos
        elseif (empty($entity->panelizer[$view_mode]->display) || empty($entity->panelizer[$view_mode]->did)) {
1543 85ad3d82 Assos Assos
          if (!empty($entity->panelizer[$view_mode]->did)) {
1544
            if (empty($displays[$entity->panelizer[$view_mode]->did])) {
1545
              // Somehow the display for this entity has gotten lost?
1546
              $entity->panelizer[$view_mode]->did = NULL;
1547
              $entity->panelizer[$view_mode]->display = $this->get_default_display($bundles[$entity_id], $view_mode);
1548
            }
1549
            else {
1550
              $entity->panelizer[$view_mode]->display = $displays[$entity->panelizer[$view_mode]->did];
1551
            }
1552
          }
1553
          else {
1554
            if (!empty($panelizer_defaults[$entity->panelizer[$view_mode]->name])) {
1555 e5e66f93 Assos Assos
              // Reload the settings from the default configuration.
1556
              $entity->panelizer[$view_mode] = clone $panelizer_defaults[$entity->panelizer[$view_mode]->name];
1557
              $entity->panelizer[$view_mode]->did = NULL;
1558
              $entity->panelizer[$view_mode]->entity_id = $entity_id;
1559
              $entity->panelizer[$view_mode]->revision_id = $revision_id;
1560 85ad3d82 Assos Assos
            }
1561
          }
1562
        }
1563
      }
1564
    }
1565
  }
1566
1567
  public function hook_entity_insert($entity) {
1568
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1569
    if (!$this->is_panelized($bundle)) {
1570
      return;
1571
    }
1572
1573 e5e66f93 Assos Assos
    // Check to see if this entity is a translation of another entity.
1574
    // If so, use the source entity's panelizer information to clone it.
1575
    if (isset($entity->translation_source) && isset($entity->translation_source->panelizer)) {
1576
      $entity->panelizer = $entity->translation_source->panelizer;
1577
    }
1578
1579 85ad3d82 Assos Assos
    // If there's no panelizer information on the entity then there is nothing to do.
1580
    if (empty($entity->panelizer)) {
1581
      return;
1582
    }
1583
1584
    // Allow exports or older data to be deployed successfully.
1585
    if (is_object($entity->panelizer)) {
1586
      $entity->panelizer = array('page_manager' => $entity->panelizer);
1587
    }
1588
1589
    foreach ($entity->panelizer as $view_mode => $panelizer) {
1590 e5e66f93 Assos Assos
      // Don't write out empty records.
1591
      if (empty($panelizer)) {
1592
        continue;
1593
      }
1594
1595 85ad3d82 Assos Assos
      // Just a safety check to make sure we can't have a missing view mode.
1596
      if (empty($view_mode)) {
1597
        $view_mode = 'page_manager';
1598
      }
1599
1600 e5e66f93 Assos Assos
      // In certain circumstances $panelizer will be the default's name rather
1601
      // than a full object.
1602
      if (!is_object($panelizer) && is_array($panelizer) && !empty($panelizer['name'])) {
1603
        $panelizer = $this->get_default_panelizer_object($bundle . '.' . $view_mode, $panelizer['name']);
1604
        $panelizer->did = NULL;
1605
1606
        // Ensure original values are maintained.
1607
        $panelizer->entity_id = $entity_id;
1608
        $panelizer->revision_id = $revision_id;
1609
      }
1610
1611
      // If this is a default display, skip saving it.
1612
      $default_display = $this->get_default_display_default_name($bundle, $view_mode);
1613
      if (!empty($panelizer->name) && $panelizer->name == $default_display) {
1614
        continue;
1615
      }
1616
1617 85ad3d82 Assos Assos
      // On entity insert, we only write the display if it is not a default.
1618
      // That probably means it came from an export or deploy or something
1619
      // along those lines.
1620
      if (empty($panelizer->name) && !empty($panelizer->display)) {
1621
        // Ensure we don't accidentally overwrite existing display
1622
        // data or anything silly like that.
1623
        $panelizer = $this->clone_panelizer($panelizer, $entity);
1624 136a805a Assos Assos
        // Ensure that Panels storage is set correctly.
1625
        $panelizer->display->storage_type = 'panelizer_entity';
1626
        $panelizer->display->storage_id = implode(':', array($this->entity_type, $entity_id, $view_mode));
1627 85ad3d82 Assos Assos
        // First write the display
1628
        panels_save_display($panelizer->display);
1629
1630
        // Make sure we have the new did.
1631
        $panelizer->did = $panelizer->display->did;
1632
      }
1633 e5e66f93 Assos Assos
1634
      // To prevent overwriting a cloned entity's $panelizer object, clone it.
1635 85ad3d82 Assos Assos
      else {
1636 e5e66f93 Assos Assos
        // Store $panelizer->name as  it is removed by clone_panelizer().
1637
        $stored_name = $panelizer->name;
1638 85ad3d82 Assos Assos
1639 e5e66f93 Assos Assos
        // Clone the $panelizer object.
1640
        $panelizer = $this->clone_panelizer($panelizer, $entity);
1641 85ad3d82 Assos Assos
1642 e5e66f93 Assos Assos
        // Restore the original $panelizer->name.
1643
        $panelizer->name = $stored_name;
1644 85ad3d82 Assos Assos
      }
1645 e5e66f93 Assos Assos
1646
      // Make sure there is a view mode.
1647
      if (empty($panelizer->view_mode)) {
1648
        $panelizer->view_mode = $view_mode;
1649
      }
1650
1651
      // And write the new record.
1652
      drupal_write_record('panelizer_entity', $panelizer);
1653 85ad3d82 Assos Assos
    }
1654
  }
1655
1656
  public function hook_entity_update($entity) {
1657
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1658
    if (!$this->is_panelized($bundle)) {
1659
      return;
1660
    }
1661
1662 e5e66f93 Assos Assos
    // If there's no panelizer information on the entity then there is nothing
1663
    // to do.
1664 85ad3d82 Assos Assos
    if (empty($entity->panelizer)) {
1665
      return;
1666
    }
1667
1668
    // Allow exports or older data to be deployed successfully.
1669
    if (is_object($entity->panelizer)) {
1670
      $entity->panelizer = array('page_manager' => $entity->panelizer);
1671
    }
1672
1673 e5e66f93 Assos Assos
    // When updating many/most objects, make sure the previous revision's
1674
    // configuration is loaded too, as they won't be automatically loaded.
1675
    // @todo There may be another way of handling this.
1676
    if (isset($entity->original, $entity->original->panelizer)) {
1677
      foreach ($entity->original->panelizer as $view_mode => $panelizer) {
1678
        if (!isset($entity->panelizer[$view_mode])) {
1679
          $entity->panelizer[$view_mode] = clone $panelizer;
1680
        }
1681
      }
1682
    }
1683
1684
    // Update each panelizer configuration.
1685 85ad3d82 Assos Assos
    foreach ($entity->panelizer as $view_mode => $panelizer) {
1686 e5e66f93 Assos Assos
      // Don't write out empty records.
1687
      if (empty($panelizer)) {
1688
        continue;
1689
      }
1690
1691
      // In some cases $panelizer is array, convert it to an object.
1692
      if (is_array($panelizer)) {
1693
        $panelizer = (object) $panelizer;
1694
      }
1695
1696 85ad3d82 Assos Assos
      // Just a safety check to make sure we can't have a missing view mode.
1697
      if (empty($view_mode)) {
1698
        $view_mode = 'page_manager';
1699
      }
1700
1701 e5e66f93 Assos Assos
      // In certain circumstances $panelizer will be the default's name rather
1702
      // than a full object.
1703
      if (!is_object($panelizer) && is_array($panelizer) && !empty($panelizer['name'])) {
1704
        $panelizer = $this->get_default_panelizer_object($bundle . '.' . $view_mode, $panelizer['name']);
1705
        $panelizer->did = NULL;
1706
1707
        // Ensure original values are maintained.
1708
        $panelizer->entity_id = $entity_id;
1709
        $panelizer->revision_id = $revision_id;
1710
      }
1711
1712
      // If this is a default display, and a change wasn't made, skip saving it.
1713
      $default_display = $this->get_default_display_default_name($bundle, $view_mode);
1714
      if (empty($panelizer->display_is_modified)
1715
          && !empty($panelizer->name) && $panelizer->name == $default_display) {
1716
        // Delete the existing record for this revision/entity if one existed
1717
        // before and a new revision was not being saved.
1718
        if (empty($entity->revision)) {
1719
          // Only delete the display for this specific revision.
1720
          $this->delete_entity_panelizer($entity, $view_mode, TRUE);
1721
        }
1722
        continue;
1723
      }
1724
1725
      // Determine whether an existing Panelizer record needs to be updated or
1726
      // a new one created.
1727
      $update = array();
1728
1729
      // This entity supports revisions.
1730 85ad3d82 Assos Assos
      if ($this->supports_revisions) {
1731 e5e66f93 Assos Assos
        // If no revision value is assigned, indicating that no record was
1732
        // previously saved for this entity/view_mode combination, or a new
1733
        // revision is being created, create a new {panelizer_entity} record.
1734 85ad3d82 Assos Assos
        if (empty($panelizer->revision_id) || $panelizer->revision_id != $revision_id) {
1735
          $panelizer->revision_id = $revision_id;
1736 e5e66f93 Assos Assos
          // If this has a custom display, flag the system that the display
1737
          // needs to be saved as a new record.
1738
          if (!empty($panelizer->did)) {
1739
            $panelizer->display_is_modified = TRUE;
1740
          }
1741 85ad3d82 Assos Assos
        }
1742 e5e66f93 Assos Assos
        // This entity is being updated.
1743 85ad3d82 Assos Assos
        else {
1744 e5e66f93 Assos Assos
          $update = array('entity_type', 'entity_id', 'revision_id', 'view_mode');
1745 85ad3d82 Assos Assos
        }
1746
      }
1747 e5e66f93 Assos Assos
      // This entity does not support revisions.
1748 85ad3d82 Assos Assos
      else {
1749 e5e66f93 Assos Assos
        // There is no entity_id set yet, the record was never saved before.
1750 85ad3d82 Assos Assos
        if (empty($panelizer->entity_id)) {
1751 e5e66f93 Assos Assos
          // Nothing to do.
1752 85ad3d82 Assos Assos
        }
1753 e5e66f93 Assos Assos
        // This record is being updated.
1754 85ad3d82 Assos Assos
        else {
1755
          $update = array('entity_type', 'entity_id', 'view_mode');
1756
        }
1757
      }
1758
1759
      // The editor will set this flag if the display is modified. This lets
1760
      // us know if we need to clone a new display or not.
1761
      // NOTE: This means that when exporting or deploying, we need to be sure
1762
      // to set the display_is_modified flag to ensure this gets written.
1763
      if (!empty($panelizer->display_is_modified)) {
1764 e5e66f93 Assos Assos
        // Check if this display is shared and avoid changing other revisions
1765
        // displays.
1766
        $has_shared_display_args = array(
1767
          ':entity_type' => $this->entity_type,
1768
          ':entity_id' => $entity_id,
1769
          ':revision_id' => $revision_id,
1770
          ':did' => $panelizer->did,
1771
        );
1772
        $has_shared_display = db_query('SELECT COUNT(did) FROM {panelizer_entity} WHERE entity_type = :entity_type AND entity_id = :entity_id AND revision_id <> :revision_id AND did = :did', $has_shared_display_args)->fetchField();
1773
1774
        // If this is a new entry or the entry is using a display from a
1775
        // default, or revision is enabled and this is a shared display, clone
1776
        // the display.
1777
        if (!$update || empty($panelizer->did) || !empty($has_shared_display)) {
1778 85ad3d82 Assos Assos
          $entity->panelizer[$view_mode] = $panelizer = $this->clone_panelizer($panelizer, $entity);
1779
1780
          // Update the cache key since we are adding a new display
1781 e5e66f93 Assos Assos
          $panelizer->display->cache_key = implode(':', array_filter(array('panelizer', $panelizer->entity_type, $panelizer->entity_id, $view_mode, $revision_id)));
1782 85ad3d82 Assos Assos
        }
1783
1784 136a805a Assos Assos
        // Ensure that Panels storage is set correctly.
1785
        $panelizer->display->storage_type = 'panelizer_entity';
1786
        $panelizer->display->storage_id = implode(':', array($this->entity_type, $entity_id, $view_mode));
1787
1788 e5e66f93 Assos Assos
        // First write the display.
1789 85ad3d82 Assos Assos
        panels_save_display($panelizer->display);
1790
1791
        // Make sure we have the did.
1792
        $panelizer->did = $panelizer->display->did;
1793
1794
        // Ensure that we always write this as NULL when we have our own panel:
1795
        $panelizer->name = NULL;
1796
      }
1797
      else {
1798
        $panelizer->entity_type = $this->entity_type;
1799
        $panelizer->entity_id = $entity_id;
1800
        // The (int) ensures that entities that do not support revisions work
1801
        // since the revision_id cannot be NULL.
1802
        $panelizer->revision_id = (int) $revision_id;
1803
1804 e5e66f93 Assos Assos
        // Make sure we keep the same did as the original if the layout wasn't
1805
        // changed.
1806
        if (empty($panelizer->name) && empty($panelizer->did) && !empty($entity->original->panelizer[$view_mode]->did)) {
1807
          $panelizer->did = $entity->original->panelizer[$view_mode]->did;
1808
          $update = array('entity_type', 'entity_id', 'revision_id', 'view_mode');
1809 85ad3d82 Assos Assos
        }
1810 e5e66f93 Assos Assos
      }
1811
1812
      // Make sure there is a view mode.
1813
      if (empty($panelizer->view_mode)) {
1814
        $panelizer->view_mode = $view_mode;
1815
      }
1816
1817
      // Make sure there is a 'did' value. This can happen when the value is
1818
      // passed via inline_entity_form.
1819
      if (!isset($panelizer->did)) {
1820
        $panelizer->did = 0;
1821
      }
1822
1823
      // Save the record.
1824
      drupal_write_record('panelizer_entity', $panelizer, $update);
1825 85ad3d82 Assos Assos
1826 e5e66f93 Assos Assos
      // If there was a CSS value saved before, update the exported file. This
1827
      // is done after the entity is updated to ensure that the next page load
1828
      // gets the new file.
1829
      ctools_include('css');
1830
      $cache_key = implode(':', array_filter(array('panelizer', $this->entity_type, $entity_id, $view_mode, $revision_id)));
1831
      $filename = ctools_css_retrieve($cache_key);
1832
      if ($filename) {
1833
        ctools_css_clear($cache_key);
1834
      }
1835
      if (!empty($panelizer->css)) {
1836
        ctools_css_store($cache_key, $panelizer->css);
1837 85ad3d82 Assos Assos
      }
1838
    }
1839
  }
1840
1841
  public function hook_entity_delete($entity) {
1842
    $this->delete_entity_panelizer($entity);
1843
  }
1844
1845
  public function hook_field_attach_delete_revision($entity) {
1846
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1847
1848
    // Locate and delete all displays associated with the entity.
1849 e5e66f93 Assos Assos
    $revisions = db_query("SELECT revision_id, did FROM {panelizer_entity} WHERE entity_type = :type AND entity_id = :id", array(':type' => (string) $this->entity_type, ':id' => $entity_id))->fetchAllAssoc('revision_id');
1850 85ad3d82 Assos Assos
1851
    // It is possible to have the same did on multiple revisions, if none of
1852
    // those revisions modified the display. Be careful NOT to delete a display
1853
    // that might be in use by another revision.
1854
    $seen = array();
1855
    foreach ($revisions as $info) {
1856
      if ($info->revision_id != $revision_id) {
1857
        $seen[$info->did] = TRUE;
1858
      }
1859
    }
1860
1861
    if (!empty($revisions[$revision_id]->did) && empty($seen[$revisions[$revision_id]->did])) {
1862
      panels_delete_display($revisions[$revision_id]->did);
1863
    }
1864
1865
    db_delete('panelizer_entity')
1866
      ->condition('entity_type', $this->entity_type)
1867
      ->condition('entity_id', $entity_id)
1868
      ->condition('revision_id', $revision_id)
1869
      ->execute();
1870
  }
1871
1872
  public function hook_field_attach_form($entity, &$form, &$form_state, $langcode) {
1873
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1874
1875
    // We'll store the form array here so that we can tell at the end if we
1876
    // have any and need to add our fieldset.
1877
    $widgets = array();
1878 e5e66f93 Assos Assos
    // Need to track the number of actual visible widgets because
1879
    // element_get_visible_children doesn't handle nested fields.
1880
    $visible_widgets = 0;
1881 85ad3d82 Assos Assos
1882
    foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
1883
      $view_bundle = $bundle . '.' . $view_mode;
1884
1885 e5e66f93 Assos Assos
      $panelizers = $this->get_default_panelizer_objects($view_bundle);
1886
1887
      // Ignore view modes that don't have a choice, have no displays defined,
1888
      // or already have their own custom display set up.
1889
      if (!$this->has_panel_choice($view_bundle) || empty($panelizers) || !empty($entity->panelizer[$view_mode]->did)) {
1890 85ad3d82 Assos Assos
        continue;
1891
      }
1892
1893
      $options = array();
1894
      foreach ($panelizers as $name => $panelizer) {
1895
        if (empty($panelizer->disabled)) {
1896
          $options[$name] = $panelizer->title ? $panelizer->title : t('Default');
1897
        }
1898
      }
1899
1900 e5e66f93 Assos Assos
      // Load the configured default display.
1901
      $default_value = $this->get_default_display_name($bundle, $view_mode);
1902
1903
      // The selected value.
1904
      $selected = $default_value;
1905 85ad3d82 Assos Assos
      if (!empty($entity->panelizer[$view_mode]->name)) {
1906 e5e66f93 Assos Assos
        $selected = $entity->panelizer[$view_mode]->name;
1907 85ad3d82 Assos Assos
      }
1908 e5e66f93 Assos Assos
1909
      // Only display the selector if options were available.
1910
      if (!empty($options)) {
1911
        // Indicate which item is the default.
1912
        if (isset($options[$default_value])) {
1913
          $options[$default_value] .= ' (' . t("default for '@bundle'", array('@bundle' => $bundle)) . ')';
1914
        }
1915
1916
        // If only one option is available, don't show the selector.
1917
        if (count($options) === 1) {
1918
          $widgets[$view_mode]['name'] = array(
1919
            '#title' => $view_mode_info['label'],
1920
            '#type' => 'value',
1921
            '#value' => $selected,
1922
            // Put these here because submit does not get a real entity with the
1923
            // actual *(&)ing panelizer.
1924
            '#revision_id' => isset($entity->panelizer[$view_mode]->revision_id) ? $entity->panelizer[$view_mode]->revision_id : NULL,
1925
            '#entity_id' => isset($entity->panelizer[$view_mode]->entity_id) ? $entity->panelizer[$view_mode]->entity_id : NULL,
1926
          );
1927 85ad3d82 Assos Assos
        }
1928
        else {
1929 e5e66f93 Assos Assos
          $widgets[$view_mode]['name'] = array(
1930
            '#title' => $view_mode_info['label'],
1931
            '#type' => 'select',
1932
            '#options' => $options,
1933
            '#default_value' => $selected,
1934
            '#required' => TRUE,
1935
            // Put these here because submit does not get a real entity with the
1936
            // actual *(&)ing panelizer.
1937
            '#revision_id' => isset($entity->panelizer[$view_mode]->revision_id) ? $entity->panelizer[$view_mode]->revision_id : NULL,
1938
            '#entity_id' => isset($entity->panelizer[$view_mode]->entity_id) ? $entity->panelizer[$view_mode]->entity_id : NULL,
1939
          );
1940
          $visible_widgets++;
1941 85ad3d82 Assos Assos
        }
1942
      }
1943
    }
1944
1945 e5e66f93 Assos Assos
    // Only display this if the entity has visible options available.
1946
    if (!empty($widgets)) {
1947 85ad3d82 Assos Assos
      $form_state['panelizer has choice'] = TRUE;
1948
      $form['panelizer'] = array(
1949
        '#type' => 'fieldset',
1950
        '#access' => $this->panelizer_access('choice', $entity, $view_mode),
1951 e5e66f93 Assos Assos
        '#title' => t('Customize display'),
1952 85ad3d82 Assos Assos
        '#collapsible' => TRUE,
1953
        '#collapsed' => TRUE,
1954
        '#group' => 'additional_settings',
1955
        '#attributes' => array(
1956
          'class' => array('panelizer-entity-options'),
1957
        ),
1958
        '#attached' => array(
1959
          'js' => array(ctools_attach_js('panelizer-vertical-tabs', 'panelizer')),
1960
        ),
1961
        '#weight' => -10,
1962
        '#tree' => TRUE,
1963
      ) + $widgets;
1964 e5e66f93 Assos Assos
1965
      // Optional fieldset description.
1966
      if (!empty($this->plugin['bundles'][$bundle]['help'])) {
1967
        $form['panelizer']['#description'] = $this->plugin['bundles'][$bundle]['help'];
1968
      }
1969
1970
      // If there are no visible widgets, don't display the fieldset.
1971
      if ($visible_widgets == 0) {
1972
        $form['panelizer']['#access'] = FALSE;
1973
      }
1974 85ad3d82 Assos Assos
    }
1975
  }
1976
1977
  public function hook_field_attach_submit($entity, &$form, &$form_state) {
1978
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
1979
    if (!empty($form_state['panelizer has choice'])) {
1980
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
1981
        if (isset($form_state['values']['panelizer'][$view_mode]['name'])) {
1982
          $entity->panelizer[$view_mode] = $this->get_default_panelizer_object($bundle . '.' . $view_mode, $form_state['values']['panelizer'][$view_mode]['name']);
1983 e5e66f93 Assos Assos
          if (!empty($entity->panelizer[$view_mode])) {
1984
            $entity->panelizer[$view_mode]->did = NULL;
1985 85ad3d82 Assos Assos
1986 e5e66f93 Assos Assos
            // Ensure original values are maintained, if they exist.
1987
            if (isset($form['panelizer'][$view_mode]['name'])) {
1988
              $entity->panelizer[$view_mode]->entity_id = $form['panelizer'][$view_mode]['name']['#entity_id'];
1989
              $entity->panelizer[$view_mode]->revision_id = $form['panelizer'][$view_mode]['name']['#revision_id'];
1990
            }
1991
          }
1992 85ad3d82 Assos Assos
        }
1993
      }
1994
    }
1995
  }
1996
1997
  /**
1998
   * Determine if the entity allows revisions.
1999
   *
2000
   * @param $entity
2001
   *   The entity to test.
2002
   *
2003
   * @return array
2004 e5e66f93 Assos Assos
   *   An array. The first parameter is a boolean as to whether or not the
2005
   *   entity supports revisions, the second parameter is whether or not the
2006
   *   user can control if a revision is created, the third states whether or
2007
   *   not the revision is created by default.
2008 85ad3d82 Assos Assos
   */
2009
  public function entity_allows_revisions($entity) {
2010 e5e66f93 Assos Assos
    return array(
2011
      // Whether or not the entity supports revisions.
2012
      FALSE,
2013
2014
      // Whether or not the user can control if a revision is created.
2015
      FALSE,
2016
2017
      // Whether or not the revision is created by default.
2018
      FALSE,
2019
    );
2020 85ad3d82 Assos Assos
  }
2021
2022
  /**
2023
   * Create a new, scrubbed version of a panelizer object.
2024
   */
2025
  public function clone_panelizer($panelizer, $entity) {
2026
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2027
    $panelizer_clone = clone $panelizer;
2028
2029
    // In order to ensure we don't actually use and modify the default display,
2030
    // we export and re-import it.
2031
    $code = panels_export_display($panelizer->display);
2032
    ob_start();
2033
    eval($code);
2034
    ob_end_clean();
2035
2036
    $panelizer_clone->display = $display;
2037
    $panelizer_clone->did = NULL;
2038
    $panelizer_clone->name = NULL;
2039
    $panelizer_clone->entity_type = $this->entity_type;
2040
    $panelizer_clone->entity_id = $entity_id;
2041
    // The (int) ensures that entities that do not support revisions work
2042
    // since the revision_id cannot be NULL.
2043
    $panelizer_clone->revision_id = (int) $revision_id;
2044
2045
    return $panelizer_clone;
2046
  }
2047
2048
  function access_admin($entity, $op = NULL, $view_mode = NULL) {
2049
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2050
    if ($view_mode) {
2051
      $bundle .= '.' . $view_mode;
2052
    }
2053
    else {
2054
      $view_mode = 'page_manager';
2055
    }
2056
2057
    if (!$this->is_panelized($bundle)) {
2058
      return FALSE;
2059
    }
2060
2061
    return $this->panelizer_access($op, $entity, $view_mode) && $this->entity_access('update', $entity);
2062
  }
2063
2064
  /**
2065
   * Determine if the user has access to the panelizer operation for this type.
2066
   */
2067
  function panelizer_access($op, $bundle, $view_mode) {
2068 e5e66f93 Assos Assos
    $og_access = FALSE;
2069 85ad3d82 Assos Assos
    if (is_object($bundle)) {
2070
      $entity = $bundle;
2071
      list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2072
2073 e5e66f93 Assos Assos
      // Additional support for Organic Groups.
2074
      // @todo move to og_panelizer_access();
2075
      if (module_exists('og')) {
2076
        if (og_is_group($this->entity_type, $entity)) {
2077
          $og_access = og_user_access($this->entity_type, $entity_id, "administer panelizer og_group $op");
2078
        }
2079
        else {
2080
          $og_groups = og_get_entity_groups($this->entity_type, $entity);
2081
          foreach ($og_groups as $og_group_type => $og_gids) {
2082
            foreach ($og_gids as $og_gid) {
2083
              if (og_user_access($og_group_type, $og_gid, "administer panelizer $this->entity_type $bundle $op")) {
2084
                $og_access = TRUE;
2085
              }
2086
            }
2087
          }
2088
        }
2089
      }
2090
2091 85ad3d82 Assos Assos
      // If there is an $op, this must actually be panelized in order to pass.
2092 e5e66f93 Assos Assos
      // If there is no $op, then the settings page can provide us a "panelize
2093
      // it!" page even if there is no display.
2094 85ad3d82 Assos Assos
      if ($op && $op != 'overview' && $op != 'settings' && $op != 'choice' && empty($entity->panelizer[$view_mode])) {
2095
        return FALSE;
2096
      }
2097
    }
2098
2099 e5e66f93 Assos Assos
    // Invoke hook_panelizer_access().
2100
    $panelizer_access = module_invoke_all('panelizer_access', $op, $this->entity_type, $bundle, $view_mode);
2101
    array_unshift($panelizer_access, user_access('administer panelizer'), user_access("administer panelizer {$this->entity_type} {$bundle} {$op}"));
2102
    $panelizer_access[] = $og_access;
2103
2104
    // Trigger hook_panelizer_access_alter().
2105
    // We can't pass this many parameters to drupal_alter, so stuff them into
2106
    // an array.
2107
    $options = array(
2108
      'op' => $op,
2109
      'entity_type' => $this->entity_type,
2110
      'bundle' => $bundle,
2111
      'view_mode' => $view_mode
2112
    );
2113
    drupal_alter('panelizer_access', $panelizer_access, $options);
2114
2115
    foreach ($panelizer_access as $access) {
2116
      if ($access) {
2117
        return $access;
2118
      }
2119
    }
2120
    return FALSE;
2121 85ad3d82 Assos Assos
  }
2122
2123 e5e66f93 Assos Assos
2124 85ad3d82 Assos Assos
  /**
2125
   * Switched page callback to give the overview page
2126
   */
2127
  function page_overview($js, $input, $entity) {
2128
    $header = array(
2129
      t('View mode'),
2130
      t('Status'),
2131
      t('Operations'),
2132
    );
2133
2134
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2135
2136
    $rows = array();
2137
2138
    $base_url = $this->entity_base_url($entity);
2139
2140
    foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
2141
      if (!$this->is_panelized($bundle . '.' . $view_mode)) {
2142
        continue;
2143
      }
2144
2145
      $row = array();
2146
      $row[] = $view_mode_info['label'];
2147
      $panelized = TRUE;
2148
2149
      if (!empty($entity->panelizer[$view_mode]->name)) {
2150
        ctools_include('export');
2151
        $panelizer = ctools_export_crud_load('panelizer_defaults', $entity->panelizer[$view_mode]->name);
2152
        $status = !empty($panelizer->title) ? check_plain($panelizer->title) : t('Default');
2153
      }
2154
      else if (!empty($entity->panelizer[$view_mode]->did)) {
2155
        $status = t('Custom');
2156
      }
2157
      else {
2158
        $status = t('Not panelized');
2159
        $panelized = FALSE;
2160
      }
2161
      $row[] = $status;
2162
2163
      if ($panelized) {
2164
        $links_array = array();
2165
        foreach (panelizer_operations() as $path => $operation) {
2166
          if ($this->panelizer_access($path, $entity, $view_mode)) {
2167
            $links_array[$path] = array(
2168
              'title' => $operation['link title'],
2169
              'href' => $base_url . '/' . $view_mode . '/' . $path,
2170
            );
2171
          }
2172
        }
2173
        if ($status == t('Custom')) {
2174
          $links_array['reset'] = array(
2175
            'title' => t('reset'),
2176
            'href' => $base_url . '/' . $view_mode . '/reset',
2177
          );
2178
        }
2179
      }
2180
      else {
2181
        $links_array = array(
2182
          'panelize' => array(
2183
            'title' => t('panelize'),
2184
            'href' => $base_url . '/' . $view_mode,
2185
          ),
2186
        );
2187
      }
2188
2189
      // Allow applications to add additional panelizer tabs.
2190 e5e66f93 Assos Assos
      $context = array(
2191
        'entity' => $entity,
2192
        'view_mode' => $view_mode,
2193
        'status' => $status,
2194
        'panelized' => $panelized,
2195
      );
2196
      drupal_alter('panelizer_overview_links', $links_array, $this->entity_type, $context);
2197 85ad3d82 Assos Assos
2198
      $links = theme('links', array(
2199
        'links' => $links_array,
2200
        'attributes' => array('class' => array('links', 'inline')),
2201
      ));
2202
2203
      $row[] = $links;
2204
      $rows[] = $row;
2205
    }
2206
2207 e5e66f93 Assos Assos
    return array(
2208
      '#theme' => 'table',
2209
      '#header' => $header,
2210
      '#rows' => $rows,
2211
      '#prefix' => '<p>'
2212
        . t('Changes made here will override the default (Panelizer) displays and will only affect this @entity.', array('@entity' => $this->entity_type))
2213
        . "</p>\n",
2214
    );
2215 85ad3d82 Assos Assos
  }
2216
2217
  /**
2218
   * Provides the base panelizer URL for an entity.
2219
   */
2220
  function entity_base_url($entity, $view_mode = NULL) {
2221
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2222
2223 e5e66f93 Assos Assos
    $path_elements[] = $entity_id;
2224
2225
    $path = $this->plugin['entity path'];
2226
    if ($this->supports_revisions) {
2227
      $current_entities = entity_load($this->entity_type, array($entity_id));
2228
      $current_entity = array_pop($current_entities);
2229
      if ($revision_id !== $current_entity->vid) {
2230
        $path_elements[] = $revision_id;
2231
        $path .= '/revisions/%';
2232
      }
2233
    }
2234
2235
    $bits = explode('/', $path);
2236 85ad3d82 Assos Assos
    foreach ($bits as $count => $bit) {
2237
      if (strpos($bit, '%') === 0) {
2238 e5e66f93 Assos Assos
        $bits[$count] = array_shift($path_elements);
2239 85ad3d82 Assos Assos
      }
2240
    }
2241
2242
    $bits[] = 'panelizer';
2243
    if ($view_mode) {
2244
      $bits[] = $view_mode;
2245
    }
2246
    $base_url = implode('/', $bits);
2247
2248
    return $base_url;
2249
  }
2250
2251
  /**
2252
   * Provides a wrapper for the panelizer page output.
2253
   *
2254
   * Drupal only supports 2 levels of tabs, but we need a 3rd
2255
   * level. We will fake it.
2256
   */
2257
  function wrap_entity_panelizer_pages($entity, $view_mode, $output) {
2258
    $base_url = $this->entity_base_url($entity, $view_mode);
2259
    return $this->make_fake_tabs($base_url, $entity, $view_mode, $output);
2260
  }
2261
2262
  /**
2263
   * Provides a wrapper for the panelizer page output.
2264
   *
2265
   * Drupal only supports 2 levels of tabs, but we need a 3rd
2266
   * level. We will fake it.
2267
   */
2268
  function wrap_default_panelizer_pages($bundle, $output) {
2269
    list($bundle, $view_mode) = explode('.', $bundle);
2270
    $base_url = $this->entity_admin_root . '/panelizer/' . $view_mode;
2271
    // We have to sub in the bundle if this is set.
2272
    if (is_numeric($this->entity_admin_bundle)) {
2273
      $bits = explode('/', $base_url);
2274
      $bits[$this->entity_admin_bundle] = $bundle;
2275
      $base_url = implode('/', $bits);
2276
    }
2277
2278
    return $this->make_fake_tabs($base_url, $bundle, $view_mode, $output);
2279
  }
2280
2281
  /**
2282
   * Create some fake tabs that are attached to a page output.
2283
   */
2284
  function make_fake_tabs($base_url, $bundle, $view_mode, $output) {
2285 e5e66f93 Assos Assos
    // Integration with Workbench Moderation: these local tabs will be
2286
    // automatically added via the menu system.
2287
    if (module_exists('workbench_moderation') && isset($bundle->workbench_moderation) && $bundle->workbench_moderation['my_revision']->vid == $bundle->workbench_moderation['current']->vid) {
2288
      return $output;
2289
    }
2290
2291 85ad3d82 Assos Assos
    $links_array = array();
2292
    foreach (panelizer_operations() as $path => $operation) {
2293
      if ($this->panelizer_access($path, $bundle, $view_mode)) {
2294
        $links_array[$path] = array(
2295
          'title' => t($operation['menu title']),
2296
          'href' => $base_url . '/' . $path,
2297
        );
2298
      }
2299
    }
2300
2301
    // Allow applications to add additional panelizer tabs.
2302
    drupal_alter('panelizer_tab_links', $links_array, $this->entity_type, $bundle, $view_mode);
2303
2304
    // Only render if > 1 link, just like core.
2305
    if (count($links_array) <= 1) {
2306
      return $output;
2307
    }
2308
2309
    // These fake tabs are pretty despicable, but they'll do.
2310 e5e66f93 Assos Assos
    $links = '<div class="clearfix">' . theme('links', array(
2311 85ad3d82 Assos Assos
      'links' => $links_array,
2312
      'attributes' => array('class' => array('tabs', 'secondary')),
2313
    )) . '</div>';
2314
2315
    if (is_array($output)) {
2316
      // Use array addition because forms will already be sorted so
2317
      // #weight may not be effective.
2318
      $output = array(
2319
        'panelizer_links' => array(
2320
          '#markup' => $links,
2321
          '#weight' => -10000,
2322
        ),
2323
      ) + $output;
2324
    }
2325
    else {
2326
      $output = $links . $output;
2327
    }
2328
2329
    return $output;
2330
  }
2331
2332
  /**
2333
   * Switched page callback to give the settings form.
2334
   */
2335
  function page_reset($js, $input, $entity, $view_mode) {
2336
    $panelizer = $entity->panelizer[$view_mode];
2337
2338
    $form_state = array(
2339
      'entity' => $entity,
2340 e5e66f93 Assos Assos
      'revision info' => $this->entity_allows_revisions($entity),
2341 85ad3d82 Assos Assos
      'panelizer' => $panelizer,
2342
      'view_mode' => $view_mode,
2343
      'no_redirect' => TRUE,
2344
    );
2345
2346
    ctools_include('common', 'panelizer');
2347
    $output = drupal_build_form('panelizer_reset_entity_form', $form_state);
2348 e5e66f93 Assos Assos
2349 85ad3d82 Assos Assos
    if (!empty($form_state['executed'])) {
2350 e5e66f93 Assos Assos
      $this->reset_entity_panelizer($entity, $view_mode);
2351
      drupal_set_message(t('Panelizer display information has been reset.'));
2352 85ad3d82 Assos Assos
      drupal_goto(dirname(dirname($_GET['q'])));
2353
    }
2354
2355
    return $output;
2356
  }
2357
2358
  /**
2359
   * Switched page callback to give the settings form.
2360
   */
2361
  function page_settings($js, $input, $entity, $view_mode) {
2362
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2363
2364
    if (empty($entity->panelizer[$view_mode])) {
2365
      // If this entity is not yet panelized, and there is no default panel
2366
      // to do configuration, give them the option of panelizing it.
2367
      if ($this->has_default_panel($bundle . '.' . $view_mode)) {
2368
        return MENU_NOT_FOUND;
2369
      }
2370
2371
      // Set the form to the Panelize It! form.
2372
      $form_id = 'panelizer_panelize_entity_form';
2373
2374
      // Fetch a special default panelizer that is only accessible with the
2375
      // default_anyway flag.
2376
      $panelizer = $this->get_internal_default_panelizer($bundle, $view_mode);
2377
      $panelizer->name = NULL;
2378
    }
2379
    else {
2380
      $form_id = 'panelizer_settings_form';
2381
      $panelizer = $entity->panelizer[$view_mode];
2382
    }
2383
2384
    $form_state = array(
2385
      'entity' => $entity,
2386
      'revision info' => $this->entity_allows_revisions($entity),
2387
      'panelizer' => $panelizer,
2388
      'view_mode' => $view_mode,
2389
      'no_redirect' => TRUE,
2390
    );
2391
2392
    ctools_include('common', 'panelizer');
2393
    $output = drupal_build_form($form_id, $form_state);
2394
    if (!empty($form_state['executed'])) {
2395
      $entity->panelizer[$view_mode] = $form_state['panelizer'];
2396 e5e66f93 Assos Assos
2397
      // Make sure that entity_save knows that the panelizer settings are
2398
      // modified and must be made local to the entity.
2399 85ad3d82 Assos Assos
      if (empty($panelizer->did) || !empty($panelizer->name)) {
2400
        $panelizer->display_is_modified = TRUE;
2401
      }
2402 e5e66f93 Assos Assos
2403
      // Update the entity.
2404 85ad3d82 Assos Assos
      $this->entity_save($entity);
2405
2406 e5e66f93 Assos Assos
      drupal_set_message(t('The settings have been updated.'));
2407
2408
      // Redirect.
2409 85ad3d82 Assos Assos
      drupal_goto($_GET['q']);
2410
    }
2411
2412
    return $this->wrap_entity_panelizer_pages($entity, $view_mode, $output);
2413
  }
2414
2415
  function page_context($js, $input, $entity, $view_mode) {
2416
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2417
2418
    $cache_key = $entity_id . '.' . $view_mode;
2419
    $panelizer = panelizer_context_cache_get($this->entity_type, $cache_key);
2420
2421
    if (empty($panelizer)) {
2422
      return MENU_NOT_FOUND;
2423
    }
2424
2425
    $form_state = array(
2426
      'entity' => $entity,
2427
      'revision info' => $this->entity_allows_revisions($entity),
2428 e5e66f93 Assos Assos
      'panelizer' => &$panelizer,
2429 85ad3d82 Assos Assos
      'panelizer type' => $this->entity_type,
2430
      'cache key' => $cache_key,
2431
      'no_redirect' => TRUE,
2432
    );
2433
2434
    ctools_include('common', 'panelizer');
2435
    $output = drupal_build_form('panelizer_default_context_form', $form_state);
2436
    if (!empty($form_state['executed'])) {
2437
      if (!empty($form_state['clicked_button']['#write'])) {
2438
        $entity->panelizer[$view_mode] = $form_state['panelizer'];
2439 e5e66f93 Assos Assos
2440
        // Make sure that entity_save knows that the panelizer settings are
2441
        // modified and must be made local to the entity.
2442
        if (empty($panelizer->did) || !empty($panelizer->name)) {
2443
          $panelizer->display_is_modified = TRUE;
2444
        }
2445
2446
        // Update the entity.
2447 85ad3d82 Assos Assos
        $this->entity_save($entity);
2448 e5e66f93 Assos Assos
2449
        drupal_set_message(t('The settings have been updated.'));
2450 85ad3d82 Assos Assos
      }
2451
      else {
2452
        drupal_set_message(t('Changes have been discarded.'));
2453
      }
2454
2455 e5e66f93 Assos Assos
      // Clear the context cache.
2456 85ad3d82 Assos Assos
      panelizer_context_cache_clear($this->entity_type, $cache_key);
2457 e5e66f93 Assos Assos
2458
      // Redirect.
2459 85ad3d82 Assos Assos
      drupal_goto($_GET['q']);
2460
    }
2461
2462
    return $this->wrap_entity_panelizer_pages($entity, $view_mode, $output);
2463
  }
2464
2465
  function page_layout($js, $input, $entity, $view_mode, $step = NULL, $layout = NULL) {
2466
    $panelizer = $entity->panelizer[$view_mode];
2467
    if (empty($panelizer)) {
2468
      return MENU_NOT_FOUND;
2469
    }
2470
2471
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2472
2473
    $display = $panelizer->display;
2474
    $display->context = $this->get_contexts($panelizer, $entity);
2475
2476
    $path = $this->entity_base_url($entity, $view_mode);
2477
2478
    $form_state = array(
2479
      'entity' => $entity,
2480
      'revision info' => $this->entity_allows_revisions($entity),
2481
      'display' => $display,
2482
      'wizard path' => $path . '/layout/%step',
2483 e5e66f93 Assos Assos
      'allowed_layouts' => panelizer_get_allowed_layouts_option($this->entity_type, $bundle),
2484 85ad3d82 Assos Assos
    );
2485
2486
    ctools_include('common', 'panelizer');
2487
    $output = panelizer_change_layout_wizard($form_state, $step, $layout);
2488
    if (!empty($form_state['complete'])) {
2489
      $entity->panelizer[$view_mode]->display = $form_state['display'];
2490
      $entity->panelizer[$view_mode]->display_is_modified = TRUE;
2491
      $this->entity_save($entity);
2492
      drupal_set_message(t('The layout has been changed.'));
2493
      drupal_goto($path . '/content');
2494
    }
2495
2496
    return $this->wrap_entity_panelizer_pages($entity, $view_mode, $output);
2497
  }
2498
2499
  function page_content($js, $input, $entity, $view_mode) {
2500
    $panelizer = $entity->panelizer[$view_mode];
2501
    if (empty($panelizer)) {
2502
      return MENU_NOT_FOUND;
2503
    }
2504
2505
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2506
2507
    $form_state = array(
2508
      'entity' => $entity,
2509
      'revision info' => $this->entity_allows_revisions($entity),
2510 e5e66f93 Assos Assos
      'display cache' => panels_edit_cache_get(implode(':', array_filter(array('panelizer', $this->entity_type, $entity_id, $view_mode, $revision_id)))),
2511 85ad3d82 Assos Assos
      'no_redirect' => TRUE,
2512
    );
2513
2514
    ctools_include('common', 'panelizer');
2515
    $output = drupal_build_form('panelizer_edit_content_form', $form_state);
2516
    if (!empty($form_state['executed'])) {
2517
      if (!empty($form_state['clicked_button']['#save-display'])) {
2518
        drupal_set_message(t('The settings have been updated.'));
2519
        $entity->panelizer[$view_mode]->display = $form_state['display'];
2520
        $entity->panelizer[$view_mode]->display_is_modified = TRUE;
2521
        $this->entity_save($entity);
2522
      }
2523
      else {
2524
        drupal_set_message(t('Changes have been discarded.'));
2525
      }
2526
2527
      panels_edit_cache_clear($form_state['display cache']);
2528
      drupal_goto($_GET['q']);
2529
    }
2530
2531
    $output = $this->wrap_entity_panelizer_pages($entity, $view_mode, $output);
2532
2533
    ctools_set_no_blocks(FALSE);
2534
    drupal_set_page_content($output);
2535
    $page = element_info('page');
2536
    return $page;
2537
  }
2538
2539
  /**
2540
   * Delete panelizers associated with the entity.
2541
   *
2542
   * @param object $entity
2543
   *   The entity.
2544 e5e66f93 Assos Assos
   * @param string $view_mode
2545 85ad3d82 Assos Assos
   *   The view mode to delete. If not specified, all view modes will be
2546
   *   deleted.
2547 e5e66f93 Assos Assos
   * @param bool $one_revision
2548
   *   Whether to delete all revisions for this entity, or a specific one.
2549 85ad3d82 Assos Assos
   */
2550 e5e66f93 Assos Assos
  function delete_entity_panelizer($entity, $view_mode = NULL, $one_revision = FALSE) {
2551 85ad3d82 Assos Assos
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2552
2553 e5e66f93 Assos Assos
    // Locate any displays associated with the entity.
2554
    $query = db_select('panelizer_entity', 'pe')
2555
      ->fields('pe', array('did'))
2556
      ->condition('entity_type', $this->entity_type)
2557
      ->condition('entity_id', $entity_id);
2558
    if (!empty($view_mode)) {
2559
      $query->condition('view_mode', $view_mode);
2560 85ad3d82 Assos Assos
    }
2561 e5e66f93 Assos Assos
    if (!empty($revision_id) && !empty($one_revision)) {
2562
      $query->condition('revision_id', $revision_id);
2563 85ad3d82 Assos Assos
    }
2564 e5e66f93 Assos Assos
    $dids = $query->execute()
2565
      ->fetchCol();
2566 85ad3d82 Assos Assos
2567 e5e66f93 Assos Assos
    // Delete the Panels displays.
2568
    foreach (array_unique(array_filter($dids)) as $did) {
2569 85ad3d82 Assos Assos
      panels_delete_display($did);
2570
    }
2571
2572 e5e66f93 Assos Assos
    // Delete the {panelizer_entity} records.
2573 85ad3d82 Assos Assos
    $delete = db_delete('panelizer_entity')
2574
      ->condition('entity_type', $this->entity_type)
2575
      ->condition('entity_id', $entity_id);
2576 e5e66f93 Assos Assos
    if (!empty($view_mode)) {
2577 85ad3d82 Assos Assos
      $delete->condition('view_mode', $view_mode);
2578
    }
2579 e5e66f93 Assos Assos
    if (!empty($revision_id) && !empty($one_revision)) {
2580
      $delete->condition('revision_id', $revision_id);
2581
    }
2582 85ad3d82 Assos Assos
    $delete->execute();
2583 e5e66f93 Assos Assos
2584
    // Reset the entity's cache. If the EntityCache module is enabled, this also
2585
    // resets its permanent cache.
2586
    entity_get_controller($this->entity_type)->resetCache(array($entity_id));
2587
  }
2588
2589
  /**
2590
   * Reset displays so that the defaults can be used instead.
2591
   *
2592
   * @param object $entity
2593
   *   The entity.
2594
   * @param $view_mode
2595
   *   The view mode to delete. If not specified, all view modes will be
2596
   *   deleted.
2597
   */
2598
  function reset_entity_panelizer($entity, $view_mode = NULL) {
2599
    // Only proceed if the view mode was customized for this entity.
2600
    if (empty($entity->panelizer[$view_mode])) {
2601
      drupal_set_message(t('Unable to reset this view mode'));
2602
    }
2603
    else {
2604
      // Build a list of displays to delete.
2605
      $dids = array();
2606
2607
      // Identify this entity's bundle.
2608
      list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
2609
2610
      // Add the custom display to the list of displays to delete.
2611
      if (!empty($entity->panelizer[$view_mode]->did)) {
2612
        $dids[] = $entity->panelizer[$view_mode]->did;
2613
      }
2614
2615
      // Update the {panelizer_entity} record.
2616
      $entity->panelizer[$view_mode]->did = NULL;
2617
      $entity->panelizer[$view_mode]->name = NULL;
2618
2619
      // Update the entity.
2620
      $this->entity_save($entity);
2621
2622
      // If a new revision was not created, delete any unused displays.
2623
      if (empty($entity->revision)) {
2624
        // Work out which view modes to use.
2625
        if (!empty($view_mode)) {
2626
          $view_modes = array($view_mode);
2627
        }
2628
        else {
2629
          $entity_info = entity_get_info($this->entity_type);
2630
          $view_modes = array_keys($entity_info['view modes']);
2631
        }
2632
2633
        // Locate all displays associated with the entity.
2634
        $new_dids = db_select('panelizer_entity', 'p')
2635
          ->fields('p', array('did'))
2636
          ->condition('entity_type', $this->entity_type)
2637
          ->condition('revision_id', $revision_id)
2638
          ->condition('view_mode', $view_modes, 'IN')
2639
          ->condition('did', '0', '>')
2640
          ->execute()
2641
          ->fetchCol();
2642
        if (!empty($new_dids)) {
2643
          $dids = array_merge($dids, $new_dids);
2644
        }
2645
2646
        // Delete the display records if they are not still in use.
2647
        foreach (array_unique($dids) as $did) {
2648
          panels_delete_display($did);
2649
        }
2650
2651
        // Delete the {panelizer_entity} records.
2652
        db_delete('panelizer_entity')
2653
          ->condition('entity_type', $this->entity_type)
2654
          ->condition('revision_id', $revision_id)
2655
          ->condition('view_mode', $view_modes, 'IN')
2656
          ->condition('did', $dids, 'IN')
2657
          ->execute();
2658
2659
        // Reset the entity's cache. If the EntityCache module is enabled, this
2660
        // also resets its permanent cache.
2661
        entity_get_controller($this->entity_type)->resetCache(array($entity_id));
2662
      }
2663
    }
2664 85ad3d82 Assos Assos
  }
2665
2666
  /**
2667
   * Determine if a bundle is panelized.
2668
   */
2669
  public function is_panelized($bundle) {
2670
    if (strpos($bundle, '.') === FALSE) {
2671 e5e66f93 Assos Assos
      $has_bundle = !empty($this->plugin['bundles'][$bundle]);
2672
      $bundle_enabled = !empty($this->plugin['bundles'][$bundle]['status']);
2673
      return $has_bundle && $bundle_enabled;
2674 85ad3d82 Assos Assos
    }
2675
    else {
2676
      list($bundle, $view_mode) = explode('.', $bundle);
2677 e5e66f93 Assos Assos
      $has_bundle = !empty($this->plugin['bundles'][$bundle]);
2678
      $bundle_enabled = !empty($this->plugin['bundles'][$bundle]['status']);
2679
      $view_mode_enabled = !empty($this->plugin['bundles'][$bundle]['view modes'][$view_mode]['status']);
2680
      return $has_bundle && $bundle_enabled && $view_mode_enabled;
2681 85ad3d82 Assos Assos
    }
2682
  }
2683
2684
  /**
2685 e5e66f93 Assos Assos
   * Determine if a bundle has a default display.
2686 85ad3d82 Assos Assos
   *
2687
   * @param $bundle
2688
   *   A $bundle.$view_mode combo string. If no view mode is specified
2689
   *   then the 'page_manager' view mode will be assumed.
2690
   */
2691
  public function has_default_panel($bundle) {
2692
    if (strpos($bundle, '.') === FALSE) {
2693
      $bundle .= '.page_manager';
2694
    }
2695
    list($bundle, $view_mode) = explode('.', $bundle);
2696
2697 e5e66f93 Assos Assos
    // Is this display panelized?
2698
    $is_panelized = $this->is_panelized($bundle);
2699
2700
    // Load the default setting name.
2701
    $default = $this->get_default_display_name($bundle, $view_mode);
2702
2703
    // Verify the display exists.
2704
    $display_exists = $this->default_display_exists($default);
2705
2706
    return $is_panelized && !empty($default) && $display_exists;
2707 85ad3d82 Assos Assos
  }
2708
2709
  /**
2710
   * Determine if a bundle is allowed choices.
2711
   */
2712
  public function has_panel_choice($bundle) {
2713
    if (strpos($bundle, '.') === FALSE) {
2714
      $bundle .= '.page_manager';
2715
    }
2716 e5e66f93 Assos Assos
    list($bundle, $view_mode) = explode('.', $bundle);
2717 85ad3d82 Assos Assos
2718
    return $this->is_panelized($bundle) && !empty($this->plugin['bundles'][$bundle]['view modes'][$view_mode]['choice']);
2719
  }
2720
2721
  /**
2722
   * Get the default panels, keyed by names.
2723
   */
2724
  public function load_default_panelizer_objects($names) {
2725
    ctools_include('export');
2726
    $panelizers = ctools_export_load_object('panelizer_defaults', 'names', $names);
2727
    return $panelizers;
2728
  }
2729
2730
  /**
2731
   * Get the default panelizers for the given bundle.
2732
   */
2733
  public function get_default_panelizer_objects($bundle) {
2734
    if (strpos($bundle, '.') !== FALSE) {
2735
      list($bundle, $view_mode) = explode('.', $bundle);
2736
    }
2737
    $conditions = array(
2738
      'panelizer_type' => $this->entity_type,
2739
      'panelizer_key' => $bundle,
2740
    );
2741
2742 e5e66f93 Assos Assos
    // If the entity bundle is not panelized, nothing to do here.
2743
    if (!$this->is_panelized($bundle)) {
2744
      return array();
2745
    }
2746
2747 85ad3d82 Assos Assos
    if (!empty($view_mode)) {
2748 e5e66f93 Assos Assos
      // If this view mode is not panelized, nothing to do here.
2749
      if (!$this->is_panelized($bundle . '.' . $view_mode)) {
2750
        return array();
2751
      }
2752
2753 85ad3d82 Assos Assos
      $conditions['view_mode'] = $view_mode;
2754
    }
2755
2756
    ctools_include('export');
2757
    return ctools_export_load_object('panelizer_defaults', 'conditions', $conditions);
2758
  }
2759
2760
  /**
2761
   * Determine if the current user has access to the $panelizer.
2762
   */
2763
  public function access_default_panelizer_object($panelizer) {
2764
    // Automatically true for this, regardless of anything else.
2765
    if (user_access('administer panelizer')) {
2766
      return TRUE;
2767
    }
2768
2769
    ctools_include('context');
2770
    return user_access("administer panelizer $this->entity_type $panelizer->panelizer_key defaults") && ctools_access($panelizer->access, $this->get_contexts($panelizer));
2771
  }
2772
2773
  /**
2774
   * Implements a delegated hook_panelizer_defaults().
2775
   *
2776
   * This makes sure that all panelized entities configured to have a
2777
   * default actually have one.
2778
   */
2779
  public function hook_panelizer_defaults(&$panelizers) {
2780
    // For features integration, if they have modified a default and put
2781
    // it into the database, we do not want to show one as a default.
2782
    // Otherwise, features can't latch onto it.
2783
    $default_names = &drupal_static('panelizer_defaults_in_database', NULL);
2784
    if (!isset($default_names)) {
2785
      $default_names = drupal_map_assoc(db_query("SELECT name FROM {panelizer_defaults} WHERE name LIKE '%:default&'")->fetchCol());
2786
    }
2787
2788
    $entity_info = entity_get_info($this->entity_type);
2789
2790
    foreach ($this->plugin['bundles'] as $bundle => $info) {
2791
      // Don't bother if there are no
2792
      if (empty($info['status'])) {
2793
        continue;
2794
      }
2795
2796
      foreach ($this->plugin['view modes'] as $view_mode => $view_mode_info) {
2797
        if (!empty($info['view modes'][$view_mode]['status']) && !empty($info['view modes'][$view_mode]['default'])) {
2798
          $panelizer = $this->get_internal_default_panelizer($bundle, $view_mode);
2799
          if (empty($default_names[$panelizer->name]) && !isset($panelizers[$panelizer->name])) {
2800
            $panelizers[$panelizer->name] = $panelizer;
2801
          }
2802
        }
2803
      }
2804
    }
2805
  }
2806
2807
  /**
2808
   * An internal representation of a panelizer object, used to seed when
2809
   * we have none and want something to get started.
2810
   */
2811
  public function get_internal_default_panelizer($bundle, $view_mode) {
2812
    ctools_include('export');
2813
    $load_name = implode(':', array($this->entity_type, $bundle, 'default'));
2814
    $panelizer = ctools_export_crud_new('panelizer_defaults');
2815
    $panelizer->name = $load_name;
2816
    // Attach the view mode to the name, which is specially generated
2817
    // to ignore the specialty "page_manager" view mode.
2818
    if ($view_mode != 'page_manager') {
2819
      $panelizer->name .= ':' . $view_mode;
2820
    }
2821
2822
    $panelizer->panelizer_type = $this->entity_type;
2823
    $panelizer->panelizer_key = $bundle;
2824
    $panelizer->view_mode = $view_mode;
2825
    $panelizer->display = $this->get_default_display($bundle, $view_mode);
2826
    $panelizer->api_version = 1;
2827
    $panelizer->title = t('Default');
2828
2829
    return $panelizer;
2830
  }
2831
2832
  /**
2833 e5e66f93 Assos Assos
   * Load the named default display for the bundle.
2834 85ad3d82 Assos Assos
   */
2835
  public function get_default_panelizer_object($bundle, $name) {
2836
    if (strpos($bundle, '.') !== FALSE) {
2837
      list($bundle, $view_mode) = explode('.', $bundle);
2838
    }
2839
    else {
2840
      $view_mode = 'page_manager';
2841
    }
2842
2843
    // If the name is not in the format of entitytype:bundle:name which is
2844
    // the machine name used, split that out automatically.
2845
    if (strpos($name, ':') === FALSE) {
2846 e5e66f93 Assos Assos
      $name = implode(':', array($this->entity_type, $bundle, 'default'));
2847 85ad3d82 Assos Assos
      // This is the default view mode and older defaults won't have this,
2848
      // so we don't enforce it.
2849
      if ($view_mode != 'page_manager') {
2850
        $name .= ':' . $view_mode;
2851
      }
2852
    }
2853
2854
    ctools_include('export');
2855 e5e66f93 Assos Assos
    $panelizer = ctools_export_load_object('panelizer_defaults', 'names', array($name));
2856
    return reset($panelizer);
2857 85ad3d82 Assos Assos
  }
2858
2859
  /**
2860
   * Provide a default display for newly panelized entities.
2861
   *
2862
   * This should be implemented by the entity plugin.
2863
   */
2864
  function get_default_display($bundle, $view_mode) {
2865
    // This is a straight up empty display.
2866
    $display = panels_new_display();
2867
    $display->layout = 'flexible';
2868
2869
    $panes = array();
2870
    foreach (field_info_instances($this->entity_type, $bundle) as $field_name => $instance) {
2871
      $view_mode_settings = field_view_mode_settings($this->entity_type, $bundle);
2872
      $actual_mode = (!empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default');
2873
      $field_display = $instance['display'][$actual_mode];
2874
2875
      $pane = panels_new_pane('entity_field', $this->entity_type . ':' . $field_name, TRUE);
2876
      $pane->configuration['formatter'] = $field_display['type'];
2877
      $pane->configuration['formatter_settings'] = $field_display['settings'];
2878
      $pane->configuration['label'] = $field_display['label'];
2879
      $pane->configuration['context'] = 'panelizer';
2880
      $panes[] = array(
2881
        '#pane' => $pane,
2882
        '#weight' => $field_display['weight'],
2883
      );
2884
    }
2885
2886
    // Use our #weights to sort these so they appear in whatever order the
2887
    // normal field configuration put them in.
2888
    uasort($panes, 'element_sort');
2889
    foreach ($panes as $pane) {
2890
      $display->add_pane($pane['#pane'], 'center');
2891
    }
2892
2893
    return $display;
2894
  }
2895
2896
  /**
2897
   * Get a panelizer object for the key.
2898
   *
2899
   * This must be implemented for each entity type.
2900
   */
2901
//  function get_panelizer_object($entity_id) {
2902
//  }
2903
2904
  /**
2905
   * Add entity specific form to the Panelizer settings form.
2906
   *
2907
   * This is primarily to allow bundle selection per entity type.
2908
   */
2909
  public function settings_form(&$form, &$form_state) {
2910
    // Add entity settings
2911
    // @todo change theme function name
2912
    $form['entities'][$this->entity_type] = array(
2913
      '#theme' => 'panelizer_settings_page_table',
2914
      '#header' => array(
2915 e5e66f93 Assos Assos
        array('data' => $this->entity_bundle_label(), 'style' => 'white-space:nowrap;'),
2916 85ad3d82 Assos Assos
        t('Panelize'),
2917 e5e66f93 Assos Assos
        t('Substitute view mode'),
2918
        t('Provide initial display'),
2919 85ad3d82 Assos Assos
        t('Allow panel choice'),
2920 e5e66f93 Assos Assos
        t('Default panel'),
2921
        t('Update existing entities to use this display'),
2922
        array('data' => t('Operations'), 'style' => 'white-space:nowrap;'),
2923
      ),
2924
      '#columns' => array(
2925
        'title',
2926
        'status',
2927
        'substitute',
2928
        'default',
2929
        'choice',
2930
        'selection',
2931
        'default revert',
2932
        'links',
2933 85ad3d82 Assos Assos
      ),
2934
    );
2935
2936
    $entity_info = entity_get_info($this->entity_type);
2937
    $bundles = $entity_info['bundles'];
2938
2939
    drupal_alter('panelizer_default_types', $bundles, $this->entity_type);
2940
2941
    foreach ($bundles as $bundle => $bundle_info) {
2942 e5e66f93 Assos Assos
      $view_mode_settings = array();
2943
      if (!empty($bundle)) {
2944
        $view_mode_settings = field_view_mode_settings($this->entity_type, $bundle);
2945
      }
2946
      $base_url = 'admin/structure/panelizer/' . $this->entity_type . '/' . $bundle;
2947 85ad3d82 Assos Assos
      $bundle_id = str_replace(array('][', '_', ' '), '-', '#edit-entities-' . $this->entity_type . '-' . $bundle . '-0');
2948
2949
      // Add the widgets that apply only to the bundle.
2950
      $form['entities'][$this->entity_type][$bundle][0]['title'] = array(
2951
        '#markup' => '<strong>' . $bundle_info['label'] . '</strong>',
2952
      );
2953
2954
      $form['entities'][$this->entity_type][$bundle][0]['status'] = array(
2955
        '#type' => 'checkbox',
2956 e5e66f93 Assos Assos
        '#title' => t('Panelize: @label', array('@label' => $bundle_info['label'])),
2957
        '#title_display' => 'invisible',
2958 85ad3d82 Assos Assos
        '#default_value' => !empty($this->plugin['bundles'][$bundle]['status']),
2959
      );
2960 e5e66f93 Assos Assos
      $form['entities'][$this->entity_type][$bundle][0]['help'] = array(
2961
        '#type' => 'hidden',
2962
        '#default_value' => !empty($this->plugin['bundles'][$bundle]['help']) ? $this->plugin['bundles'][$bundle]['help'] : '',
2963
      );
2964 85ad3d82 Assos Assos
2965
      // Set proper allowed content link for entire bundle based on status
2966
      if (!empty($this->plugin['bundles'][$bundle]['status'])) {
2967 e5e66f93 Assos Assos
        $links_array = array();
2968
        if (!empty($bundle_info['admin']['real path'])) {
2969
          $links_array['displays'] = array(
2970
            'title' => t('manage display'),
2971
            'href' => $bundle_info['admin']['real path'] . '/display',
2972
          );
2973
        }
2974
        $links_array['settings'] = array(
2975
          'title' => t('allowed content'),
2976
          'href' => $base_url . '/allowed',
2977 85ad3d82 Assos Assos
        );
2978
        $links = theme('links', array(
2979
          'links' => $links_array,
2980
          'attributes' => array('class' => array('links', 'inline')),
2981
        ));
2982
      }
2983
      else {
2984
        $links = t('Save to access allowed content');
2985
      }
2986
2987
      $form['entities'][$this->entity_type][$bundle][0]['links']['basic'] = array(
2988
        '#type' => 'item',
2989
        '#title' => $links,
2990
        '#states' => array(
2991 e5e66f93 Assos Assos
          'show' => array(
2992 85ad3d82 Assos Assos
            $bundle_id . '-status' => array('checked' => TRUE),
2993
          ),
2994
        ),
2995
      );
2996
2997 e5e66f93 Assos Assos
      $view_modes = $this->get_available_view_modes($bundle);
2998
      foreach ($view_modes as $view_mode => $view_mode_label) {
2999
        $view_mode_info = $this->plugin['view modes'][$view_mode];
3000 85ad3d82 Assos Assos
3001
        $base_id = str_replace(array('][', '_', ' '), '-', '#edit-entities-' . $this->entity_type . '-' . $bundle . '-' . $view_mode);
3002 e5e66f93 Assos Assos
        $base_url = 'admin/structure/panelizer/' . $this->entity_type . '/' . $bundle . '.' . $view_mode;
3003 85ad3d82 Assos Assos
3004
        if (!empty($this->plugin['bundles'][$bundle]['view modes'][$view_mode]) && is_array($this->plugin['bundles'][$bundle]['view modes'][$view_mode])) {
3005
          $settings = $this->plugin['bundles'][$bundle]['view modes'][$view_mode];
3006
        }
3007
        else {
3008
          $settings = array(
3009
            'status' => FALSE,
3010
            'default' => FALSE,
3011
            'choice' => FALSE
3012
          );
3013
        }
3014
3015
        if (empty($view_mode_info['panelizer special'])) {
3016
          $form['entities'][$this->entity_type][$bundle][$view_mode]['title'] = array(
3017 e5e66f93 Assos Assos
            '#markup' => '&nbsp;&nbsp;&nbsp;&nbsp;' . $view_mode_label,
3018 85ad3d82 Assos Assos
          );
3019
        }
3020
        else {
3021
          $form['entities'][$this->entity_type][$bundle][$view_mode]['title'] = array(
3022
            '#markup' => '<strong>' . $bundle_info['label'] . '</strong>',
3023
          );
3024
        }
3025
3026
        $form['entities'][$this->entity_type][$bundle][$view_mode]['status'] = array(
3027
          '#type' => 'checkbox',
3028
          '#default_value' => !empty($settings['status']),
3029 e5e66f93 Assos Assos
          '#title' => t(
3030
            'Panelize: @label, @bundle',
3031
            array(
3032
              '@label' => $bundle_info['label'],
3033
              '@bundle' => $view_mode_label
3034
            )
3035
          ),
3036
          '#title_display' => 'invisible',
3037 85ad3d82 Assos Assos
          '#states' => array(
3038 e5e66f93 Assos Assos
            'show' => array(
3039 85ad3d82 Assos Assos
              $bundle_id . '-status' => array('checked' => TRUE),
3040
            ),
3041
          ),
3042
        );
3043
3044 e5e66f93 Assos Assos
        $options = array('' => t('- Ignore this option -')) + $view_modes;
3045
        unset($options[$view_mode]);
3046
        $form['entities'][$this->entity_type][$bundle][$view_mode]['substitute'] = array(
3047
          '#type' => 'select',
3048
          '#options' => $options,
3049
          '#default_value' => $this->get_substitute($view_mode, $bundle),
3050
          '#title' => t(
3051
            'Substitute view mode: @label, @bundle',
3052
            array(
3053
              '@label' => $bundle_info['label'],
3054
              '@bundle' => $view_mode_label
3055
            )
3056
          ),
3057
          '#title_display' => 'invisible',
3058
          '#states' => array(
3059
            'show' => array(
3060
              $bundle_id . '-status' => array('checked' => TRUE),
3061
              $base_id . '-status' => array('checked' => TRUE),
3062
            ),
3063
          ),
3064
        );
3065
3066 85ad3d82 Assos Assos
        $form['entities'][$this->entity_type][$bundle][$view_mode]['default'] = array(
3067
          '#type' => 'checkbox',
3068
          '#default_value' => !empty($settings['default']),
3069 e5e66f93 Assos Assos
          '#title' => t(
3070
            'Provide initial display: @label, @bundle',
3071
            array(
3072
              '@label' => $bundle_info['label'],
3073
              '@bundle' => $view_mode_label
3074
            )
3075
          ),
3076
          '#title_display' => 'invisible',
3077 85ad3d82 Assos Assos
          '#states' => array(
3078 e5e66f93 Assos Assos
            'show' => array(
3079 85ad3d82 Assos Assos
              $bundle_id . '-status' => array('checked' => TRUE),
3080
              $base_id . '-status' => array('checked' => TRUE),
3081 e5e66f93 Assos Assos
              $base_id . '-substitute' => array('value' => ''),
3082 85ad3d82 Assos Assos
            ),
3083
          ),
3084
        );
3085
3086
        $form['entities'][$this->entity_type][$bundle][$view_mode]['choice'] = array(
3087
          '#type' => 'checkbox',
3088
          '#default_value' => !empty($settings['choice']),
3089 e5e66f93 Assos Assos
          '#title' => t(
3090
            'Allow panel choice: @label, @bundle',
3091
            array(
3092
              '@label' => $bundle_info['label'],
3093
              '@bundle' => $view_mode_label
3094
            )
3095
          ),
3096
          '#title_display' => 'invisible',
3097 85ad3d82 Assos Assos
          '#states' => array(
3098 e5e66f93 Assos Assos
            'show' => array(
3099
              $bundle_id . '-status' => array('checked' => TRUE),
3100
              $base_id . '-status' => array('checked' => TRUE),
3101
              $base_id . '-substitute' => array('value' => ''),
3102
            ),
3103
          ),
3104
        );
3105
3106
        // Obtain a list of all available panels for this view mode / bundle.
3107
        $panelizers = $this->get_default_panelizer_objects($bundle . '.' . $view_mode);
3108
        $options = array();
3109
        if (!empty($panelizers)) {
3110
          foreach ($panelizers as $name => $panelizer) {
3111
            // Don't show disabled displays.
3112
            if (empty($panelizer->disabled)) {
3113
              $options[$name] = $panelizer->title;
3114
            }
3115
          }
3116
        }
3117
        if (!empty($options)) {
3118
          ksort($options);
3119
        }
3120
3121
        // The default display to be used if nothing found.
3122
        $default_name = implode(':', array($this->entity_type, $bundle, 'default'));
3123
        $variable_name = 'panelizer_' . $this->entity_type . ':' . $bundle . ':' . $view_mode . '_selection';
3124
        if ($view_mode != 'page_manager') {
3125
          $default_name .= ':' . $view_mode;
3126
        }
3127
        // If this has not been set previously, use the 'default' as the default
3128
        // selection.
3129
        $default_value = variable_get($variable_name, FALSE);
3130
        if (empty($default_value)) {
3131
          $default_value = $default_name;
3132
        }
3133
3134
        // First time this is displayed there won't be any defaults assigned, so
3135
        // show a placeholder indicating the page needs to be saved before they
3136
        // will show.
3137
        if (count($options) == 0) {
3138
          if ($default_value == $default_name) {
3139
            $options = array('' => t('Save to access selector'));
3140
          }
3141
          else {
3142
            $options = array('' => t('No displays created yet'));
3143
          }
3144
        }
3145
        // Indicate which item is actually the default.
3146
        if (count($options) > 1 && isset($options[$default_value])) {
3147
          $options[$default_value] .= ' (' . t('default') . ')';
3148
        }
3149
        $form['entities'][$this->entity_type][$bundle][$view_mode]['selection'] = array(
3150
          '#type' => 'select',
3151
          '#options' => $options,
3152
          '#default_value' => $default_value,
3153
          '#title' => t(
3154
            'Default panel: @label, @bundle',
3155
            array(
3156
              '@label' => $bundle_info['label'],
3157
              '@bundle' => $view_mode_label
3158
            )
3159
          ),
3160
          '#title_display' => 'invisible',
3161
          '#states' => array(
3162
            'show' => array(
3163
              $bundle_id . '-status' => array('checked' => TRUE),
3164
              $base_id . '-status' => array('checked' => TRUE),
3165
              $base_id . '-substitute' => array('value' => ''),
3166
            ),
3167
          ),
3168
          '#disabled' => count($options) == 1,
3169
        );
3170
        $form['entities'][$this->entity_type][$bundle][$view_mode]['default revert'] = array(
3171
          '#type' => 'checkbox',
3172
          '#default_value' => FALSE,
3173
          '#title' => t(
3174
            'Update existing entities to use this display: @label, @bundle',
3175
            array(
3176
              '@label' => $bundle_info['label'],
3177
              '@bundle' => $view_mode_label
3178
            )
3179
          ),
3180
          '#title_display' => 'invisible',
3181
          '#states' => array(
3182
            'show' => array(
3183 85ad3d82 Assos Assos
              $bundle_id . '-status' => array('checked' => TRUE),
3184
              $base_id . '-status' => array('checked' => TRUE),
3185 e5e66f93 Assos Assos
              $base_id . '-substitute' => array('value' => ''),
3186 85ad3d82 Assos Assos
            ),
3187
          ),
3188 e5e66f93 Assos Assos
          '#disabled' => count($options) == 1,
3189 85ad3d82 Assos Assos
        );
3190
3191
        $form['entities'][$this->entity_type][$bundle][$view_mode]['links'] = array(
3192
          '#prefix' => '<div class="container-inline">',
3193
          '#suffix' => '</div>',
3194
        );
3195
3196 e5e66f93 Assos Assos
        // Panelize is enabled and a default display will be provided.
3197 85ad3d82 Assos Assos
        if (!empty($settings['status']) && !empty($settings['default']) && empty($settings['choice'])) {
3198
          $links_array = array();
3199
          foreach (panelizer_operations() as $path => $operation) {
3200
            $links_array[$path] = array(
3201
              'title' => $operation['link title'],
3202
              'href' => $base_url . '/' . $path,
3203
            );
3204
          }
3205
3206
          $links = theme('links', array(
3207
            'links' => $links_array,
3208
            'attributes' => array('class' => array('links', 'inline')),
3209
          ));
3210
        }
3211
        else {
3212
          $links = t('Save to access default panel');
3213
        }
3214
3215
        $form['entities'][$this->entity_type][$bundle][$view_mode]['links']['default'] = array(
3216
          '#type' => 'item',
3217
          '#title' => $links,
3218
          '#states' => array(
3219 e5e66f93 Assos Assos
            'show' => array(
3220 85ad3d82 Assos Assos
              $bundle_id . '-status' => array('checked' => TRUE),
3221
              $base_id . '-status' => array('checked' => TRUE),
3222
              $base_id . '-default' => array('checked' => TRUE),
3223
              $base_id . '-choice' => array('checked' => FALSE),
3224 e5e66f93 Assos Assos
              $base_id . '-substitute' => array('value' => ''),
3225 85ad3d82 Assos Assos
            ),
3226
          ),
3227
        );
3228
3229
        if (!empty($settings['status']) && !empty($settings['choice'])) {
3230
          $links_array = array(
3231
            'list' => array(
3232
              'title' => t('list'),
3233
              'href' => $base_url . '/list',
3234
            ),
3235
          );
3236
3237
          $links = theme('links', array(
3238
            'links' => $links_array,
3239
            'attributes' => array('class' => array('links', 'inline')),
3240
          ));
3241
        }
3242
        else {
3243 e5e66f93 Assos Assos
          $links = t('Save to access display list');
3244 85ad3d82 Assos Assos
        }
3245
3246
        $form['entities'][$this->entity_type][$bundle][$view_mode]['links']['default2'] = array(
3247
          '#type' => 'item',
3248
          '#title' => $links,
3249
          '#states' => array(
3250 e5e66f93 Assos Assos
            'show' => array(
3251 85ad3d82 Assos Assos
              $bundle_id . '-status' => array('checked' => TRUE),
3252
              $base_id . '-status' => array('checked' => TRUE),
3253
              $base_id . '-choice' => array('checked' => TRUE),
3254 e5e66f93 Assos Assos
              $base_id . '-substitute' => array('value' => ''),
3255 85ad3d82 Assos Assos
            ),
3256
          ),
3257
        );
3258 e5e66f93 Assos Assos
3259
        // Additional messages if this display is enabled.
3260
        if (empty($form_state['input']) && $view_mode == 'page_manager' && !empty($settings['status'])) {
3261
          $this->check_page_manager_status();
3262
        }
3263 85ad3d82 Assos Assos
      }
3264
    }
3265 e5e66f93 Assos Assos
    $form['#attached'] = array(
3266
      'js' => array(ctools_attach_js('states-show')),
3267
    );
3268 85ad3d82 Assos Assos
  }
3269
3270
  /**
3271
   * Validate entity specific settings on the Panelizer settings form.
3272
   */
3273
  public function settings_form_validate(&$form, &$form_state) {
3274
3275
  }
3276
3277
  /**
3278
   * Submit entity specific settings on the Panelizer settings form.
3279
   */
3280
  public function settings_form_submit(&$form, &$form_state) {
3281
    if (empty($form_state['values']['entities'][$this->entity_type])) {
3282
      return;
3283
    }
3284
3285
    foreach ($form_state['values']['entities'][$this->entity_type] as $bundle => $values) {
3286
      // Rewrite our settings because they're not quite in the right format in
3287
      // the form.
3288 e5e66f93 Assos Assos
      $settings = array(
3289
        'status' => $values[0]['status'],
3290
        'view modes' => array(),
3291
      );
3292
      if (!empty($values[0]['status'])) {
3293 2545992a Assos Assos
        // This field is optional so should not always be applied.
3294
        if (isset($values[0]['help']) && !empty($values[0]['help'])) {
3295
          $settings['help'] = $values[0]['help'];
3296
        }
3297 e5e66f93 Assos Assos
3298
        foreach ($values as $view_mode => $config) {
3299
          if (!empty($view_mode) && !empty($config)) {
3300
            // Fix the configuration.
3301 2545992a Assos Assos
            // Make sure each setting is disabled if the view mode is disabled.
3302 e5e66f93 Assos Assos
            if (empty($config['status'])) {
3303
              foreach ($config as $key => $val) {
3304
                $config[$key] = 0;
3305
              }
3306
            }
3307
3308
            // Save the default display for this bundle to a variable so that it
3309
            // may be controlled separately.
3310
            if (!empty($config['selection'])) {
3311
              $variable_name = 'panelizer_' . $this->entity_type . ':' . $bundle . ':' . $view_mode . '_selection';
3312
              $old_value = variable_get($variable_name, NULL);
3313
              $new_value = $config['selection'];
3314
              variable_set($variable_name, $config['selection']);
3315
3316
              // Cleanup.
3317
3318
              // Additional cleanup if the default display was changed.
3319
              if (!is_null($old_value) && $old_value != $new_value) {
3320
                // The user specifically requested that existing entities are
3321
                // to be updated to the new display.
3322
                if (!empty($config['default revert'])) {
3323
                  $updated_count = db_update('panelizer_entity')
3324
                    ->fields(array('name' => $new_value))
3325
                    ->condition('name', $old_value)
3326
                    ->execute();
3327
                  drupal_set_message(t('@count @entity records were updated to the new Panelizer display for the @mode view mode.', array('@count' => $updated_count, '@entity' => $this->entity_type, '@mode' => $view_mode)));
3328
3329
                  // If EntityCache is enabled, clear all records of this type.
3330
                  // This is a little heavy-handed, but I don't believe there's
3331
                  // an easy way to clear only entities of certain types
3332
                  // without querying for them first, which could trigger an
3333
                  // execution timeout.
3334
                  if (module_exists('entitycache')) {
3335
                    cache_clear_all('*', 'cache_entity_' . $this->entity_type, TRUE);
3336
                  }
3337
                }
3338
              }
3339
            }
3340
3341
            // Don't save some settings with the rest of the settings bundle.
3342
            unset($config['selection']);
3343
            unset($config['default revert']);
3344
3345
            $settings['view modes'][$view_mode] = $config;
3346
          }
3347 85ad3d82 Assos Assos
        }
3348
      }
3349
      variable_set('panelizer_defaults_' . $this->entity_type . '_' . $bundle, $settings);
3350
    }
3351
3352
    // @todo if we enable caching of the plugins, which we should, this
3353
    // needs to clear that cache so they get reloaded.
3354
  }
3355
3356
  /**
3357
   * Render the panels display for a given panelizer entity.
3358
   *
3359
   * @param stdClass $entity
3360
   *   A fully-loaded entity object controlled by panelizer.
3361
   * @param array $args
3362
   *   Optional array of arguments to pass to the panels display.
3363
   * @param string $address
3364
   *   An optional address to send to the renderer to use for addressable
3365
   *   content.
3366 e5e66f93 Assos Assos
   * @param array $extra_contexts
3367
   *   An optional array of extra context objects that will be added to the
3368
   *   display.
3369 85ad3d82 Assos Assos
   *
3370
   * @return array
3371
   *   If the entity isn't panelized, this returns NULL. Otherwise, it returns an
3372
   *   associative array as meant for use with CTools with the following keys:
3373
   *   - 'content': String containing the rendered panels display output.
3374
   *   - 'no_blocks': Boolean defining if the panels display wants to hide core
3375
   *      blocks or not when being rendered.
3376
   */
3377 e5e66f93 Assos Assos
  function render_entity($entity, $view_mode, $langcode = NULL, $args = array(), $address = NULL, $extra_contexts = array()) {
3378
    list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
3379
3380
    // Optionally substitute the view mode with another one.
3381
    $substitute = $this->get_substitute($view_mode, $bundle);
3382
    if (!empty($substitute)) {
3383
      $view_mode = $substitute;
3384
    }
3385
3386
    // Nothing configured for this view mode.
3387 85ad3d82 Assos Assos
    if (empty($entity->panelizer[$view_mode]) || empty($entity->panelizer[$view_mode]->display)) {
3388
      return FALSE;
3389
    }
3390
3391
    $panelizer = $entity->panelizer[$view_mode];
3392
    $display = $panelizer->display;
3393
3394 e5e66f93 Assos Assos
    $display->context = $this->get_contexts($panelizer, $entity) + $extra_contexts;
3395 85ad3d82 Assos Assos
    $display->args = $args;
3396
    $display->css_id = $panelizer->css_id;
3397
3398
    // This means the IPE will use our cache which means it will get appropriate
3399
    // allowed content should it be selected.
3400 e5e66f93 Assos Assos
    $display->cache_key = implode(':', array_filter(array('panelizer', $this->entity_type, $entity_id, $view_mode, $revision_id)));
3401 85ad3d82 Assos Assos
3402
    // Check to see if there is any CSS.
3403
    if (!empty($panelizer->css)) {
3404
      ctools_include('css');
3405
      $filename = ctools_css_retrieve($display->cache_key);
3406
      if (!$filename) {
3407
        $filename = ctools_css_store($display->cache_key, $panelizer->css);
3408
      }
3409
      drupal_add_css($filename, array('group' => CSS_THEME));
3410
    }
3411
3412
    if ($view_mode == 'page_manager') {
3413
      // We think this is handled as a page, so set the current page display.
3414
      panels_get_current_page_display($display);
3415
    }
3416
3417 e5e66f93 Assos Assos
    // Allow applications to alter the panelizer and the display before
3418
    // rendering them.
3419 85ad3d82 Assos Assos
    drupal_alter('panelizer_pre_render', $panelizer, $display, $entity);
3420
3421
    ctools_include('plugins', 'panels');
3422
    $renderer = panels_get_renderer($panelizer->pipeline, $display);
3423
3424
    // If the IPE is enabled, but the user does not have access to edit
3425
    // the entity, load the standard renderer instead.
3426
3427 e5e66f93 Assos Assos
    // Use class_parents so we don't try to autoload the class we are testing.
3428 85ad3d82 Assos Assos
    $parents = class_parents($renderer);
3429 e5e66f93 Assos Assos
    if (!empty($parents['panels_renderer_editor']) && (!$this->panelizer_access('content', $entity, $view_mode) && !$this->entity_access('update', $entity))) {
3430 85ad3d82 Assos Assos
      $renderer = panels_get_renderer_handler('standard', $display);
3431
    }
3432
3433
    $renderer->address = $address;
3434
3435
    $info = array(
3436 e5e66f93 Assos Assos
      'title' => $panelizer->display->get_title(),
3437 85ad3d82 Assos Assos
      'content' => panels_render_display($display, $renderer),
3438
      'no_blocks' => !empty($panelizer->no_blocks),
3439
    );
3440
3441
    $info['classes_array'] = array();
3442
3443
    if (!empty($panelizer->css_class)) {
3444
      foreach (explode(' ', $panelizer->css_class) as $class) {
3445
        $class = ctools_context_keyword_substitute($class, array(), $display->context);
3446
        if ($class) {
3447 e5e66f93 Assos Assos
          $info['classes_array'][] = drupal_html_class($class);
3448 85ad3d82 Assos Assos
        }
3449
      }
3450
    }
3451
3452
    if (!empty($parents['panels_renderer_editor'])) {
3453 e5e66f93 Assos Assos
      $path = drupal_get_path('module', 'panelizer');
3454 85ad3d82 Assos Assos
      ctools_add_js('panelizer-ipe', 'panelizer');
3455 e5e66f93 Assos Assos
      drupal_add_js($path . "/js/panelizer-ipe.js", array('group' => JS_LIBRARY));
3456
      drupal_add_css($path . "/css/panelizer-ipe.css");
3457 85ad3d82 Assos Assos
    }
3458
3459
    return $info;
3460
  }
3461
3462
  /**
3463
   * Fetch an object array of CTools contexts from panelizer information.
3464
   */
3465
  public function get_contexts($panelizer, $entity = NULL) {
3466
    ctools_include('context');
3467
    if (empty($panelizer->base_contexts)) {
3468
      $panelizer->base_contexts = $this->get_base_contexts($entity);
3469
    }
3470
3471
    $contexts = ctools_context_load_contexts($panelizer);
3472
    return $contexts;
3473
  }
3474
3475
  /**
3476
   * Callback to get the base context for a panelized entity
3477
   */
3478
  public function get_base_contexts($entity = NULL) {
3479
    ctools_include('context');
3480
    if ($entity) {
3481
      $context = ctools_context_create('entity:' . $this->entity_type, $entity);
3482
    }
3483
    else {
3484
      $context = ctools_context_create_empty('entity:' . $this->entity_type);
3485
      // The placeholder is needed to create the form used for the live
3486
      // preview.
3487
      $context->placeholder = array(
3488
        'type' => 'context',
3489
        'conf' => array(
3490
          'name' => $this->entity_type,
3491
          'identifier' => $this->entity_identifier($entity),
3492
          'keyword' => $this->entity_type,
3493
          'context_settings' => array(),
3494
        ),
3495
      );
3496
    }
3497
3498
    $context->identifier = $this->entity_identifier($entity);
3499
    $context->keyword = $this->entity_type;
3500
    return array('panelizer' => $context);
3501
  }
3502
3503
  /**
3504
   * Get the visible identifier if the identity.
3505
   *
3506
   * This is overridable because it can be a bit awkward using the
3507
   * default label.
3508
   */
3509
  public function entity_identifier($entity) {
3510
    $entity_info = entity_get_info($this->entity_type);
3511
    return t('This @entity', array('@entity' => $entity_info['label']));
3512
  }
3513
3514
  // Admin screens use a title callback for admin pages. This is used
3515
  // to fill in that title.
3516
  public function get_bundle_title($bundle) {
3517
    $entity_info = entity_get_info($this->entity_type);
3518
3519
    return isset($entity_info['bundles'][$bundle]['label']) ? $entity_info['bundles'][$bundle]['label'] : '';
3520
  }
3521
3522
  /**
3523
   * Get the name of bundles on the entity.
3524
   *
3525
   * Entity API doesn't give us a way to determine this, so the class must
3526
   * do this.
3527
   *
3528
   * @return
3529
   *   A translated, safe string.
3530
   */
3531
  public function entity_bundle_label() {
3532
    $entity_info = entity_get_info($this->entity_type);
3533
    return t('@entity bundle', array('@entity' => $entity_info['label']));
3534
  }
3535
3536
  /**
3537
   * Fetch the entity out of a build for hook_entity_view.
3538
   *
3539
   * @param $build
3540
   *   The render array that contains the entity.
3541
   */
3542
  public function get_entity_view_entity($build) {
3543
    $element = '#' . $this->entity_type;
3544
    if (isset($build[$element])) {
3545
      return $build[$element];
3546
    }
3547
    else if (isset($build['#entity'])) {
3548
      return $build['#entity'];
3549
    }
3550
  }
3551
3552
  /**
3553
   * Implement views support for panelizer entity types.
3554
   */
3555
  public function hook_views_data_alter(&$items) {
3556
    $entity_info = entity_get_info($this->entity_type);
3557
    if (!empty($entity_info['base table'])) {
3558
      $table = $entity_info['base table'];
3559
      $items[$table]['panelizer_link'] = array(
3560
        'field' => array(
3561
          'title' => t('Panelizer link'),
3562
          'help' => t('Provide a link to panelizer-related operations on the content.'),
3563
          'handler' => 'panelizer_handler_field_link',
3564
          'entity_type' => $this->entity_type,
3565
        ),
3566
      );
3567
      $items[$table]['panelizer_status'] = array(
3568
        'field' => array(
3569
          'title' => t('Panelizer status'),
3570
          'help' => t('Display whether an entity is panelized and which panelizer option it is using.'),
3571
          'handler' => 'panelizer_handler_panelizer_status',
3572
          'entity_type' => $this->entity_type,
3573
        ),
3574
      );
3575
3576
      // Join on revision id if possible or entity id if not.
3577
      if (!empty($entity_info['entity keys']['revision'])) {
3578
        $id_field = $entity_info['entity keys']['revision'];
3579
        $field = 'revision_id';
3580
      }
3581
      else {
3582
        $id_field = $entity_info['entity keys']['id'];
3583
        $field = 'entity_id';
3584
      }
3585
3586
      $items['panelizer_entity_' . $table]['table']['join'] = array(
3587
        $table => array(
3588
          'handler' => 'views_join',
3589
          'table' => 'panelizer_entity',
3590
          'left_table' => $table,
3591
          'left_field' => $id_field,
3592
          'field' => $field,
3593
          'extra' => array(array(
3594
            'field' => 'entity_type',
3595
            'value' => $this->entity_type,
3596
            'operator' => '=',
3597
          )),
3598
        ),
3599
      );
3600
3601
      $items['panelizer_entity_' . $table]['table']['group'] = $items[$table]['table']['group'];
3602
3603
      $items['panelizer_entity_' . $table]['name'] = array(
3604
        'filter' => array(
3605
          'title' => t('Panelizer status'),
3606
          'help' => t('Filter based upon panelizer status.'),
3607
          'handler' => 'panelizer_handler_filter_panelizer_status',
3608
          'entity_type' => $this->entity_type,
3609
        ),
3610
      );
3611
    }
3612
  }
3613
3614
  /**
3615
   * Preprocess the entity view mode template.
3616
   */
3617
  public function preprocess_panelizer_view_mode(&$vars, $entity, $element, $panelizer, $info) {
3618
    $vars['classes_array'][] = drupal_html_class($this->entity_type);
3619
    $vars['classes_array'][] = drupal_html_class($this->entity_type . '-' . $element['#view_mode']);
3620
    $vars['classes_array'][] = drupal_html_class($this->entity_type . '-' . $element['#panelizer_bundle']);
3621
    $vars['classes_array'][] = drupal_html_class($this->entity_type . '-' . $element['#panelizer_entity_id']);
3622
    if (!empty($entity->preview)) {
3623
      $vars['classes_array'][] = drupal_html_class($this->entity_type . '-preview');
3624
    }
3625
3626
    if (!empty($panelizer->title_element)) {
3627
      $vars['title_element'] = $panelizer->title_element;
3628
    }
3629
    else {
3630
      $vars['title_element'] = 'h2';
3631
    }
3632
3633
    $vars['content'] = $info['content'];
3634
    if (!empty($info['title'])) {
3635
      $vars['title'] = $info['title'];
3636
    }
3637
3638
    if (!empty($info['classes_array'])) {
3639
      $vars['classes_array'] = array_merge($vars['classes_array'], $info['classes_array']);
3640
    }
3641
3642
    if (!empty($panelizer->link_to_entity)) {
3643
      list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity);
3644
3645
      $bits = explode('/', $this->plugin['entity path']);
3646
      foreach ($bits as $count => $bit) {
3647
        if (strpos($bit, '%') === 0) {
3648
          $bits[$count] = $entity_id;
3649
        }
3650
      }
3651
      $vars['entity_url'] = url(implode('/', $bits));
3652
    }
3653
  }
3654 e5e66f93 Assos Assos
3655
  /**
3656
   * Identify whether page manager is enabled for this entity type.
3657
   */
3658
  public function is_page_manager_enabled() {
3659
    return variable_get('page_manager_' . $this->entity_type . '_view_disabled', TRUE);
3660
  }
3661 85ad3d82 Assos Assos
}
3662
3663
function panelizer_entity_default_bundle_form_submit($form, &$form_state) {
3664
  $bundle = $form['panelizer']['#bundle'];
3665
  $type_location = $form['panelizer']['#location'];
3666
  $form_state['panelizer_entity_handler']->add_bundle_setting_form_submit($form, $form_state, $bundle, $type_location);
3667
}