+ $page['content']['system_main']['#attributes']['data-edit-is-contextual-region-for-entity'] = '';
+ }
+
// Abuse the 'page_top' region for attaching our libraries.
$page['page_top']['#attached']['library'][] = array('edit', 'edit');
@@ -362,7 +376,10 @@ function edit_preprocess_field(&$variables) {
// mode).
// @see field_view_field()
// @see https://drupal.org/node/2120335
- if ($element['#view_mode'] === '_custom_display') {
+ // However, we do support Panelizer, and Panelizer always uses a custom view
+ // mode when rendering field panes, in all of its own "view modes".
+ // @see includes/panelizer.inc
+ if ($element['#view_mode'] === '_custom_display' && !isset($element['#object']->panelizer)) {
return;
}
@@ -407,6 +424,12 @@ function edit_preprocess_field(&$variables) {
}
}
+ // Panelizer support; see explanation at the top of this function.
+ // @see includes/panelizer.inc
+ if ($element['#view_mode'] === '_custom_display' && isset($element['#object']->panelizer)) {
+ $view_mode = _panelizer_generate_edit_viewmode($element['#object']);
+ }
+
// Provide metadata through data- attributes.
$variables['attributes_array']['data-edit-field-id'] = "$entity_type/$id/$field_name/$language/$view_mode";
}
diff --git a/includes/panelizer.inc b/includes/panelizer.inc
new file mode 100644
index 0000000..1a560b0
--- /dev/null
+++ b/includes/panelizer.inc
@@ -0,0 +1,169 @@
+type[1] === 'entity') {
+ $entity_id = $context['args'][0];
+ $entity_type = $page_context->type[2];
+ $prefix = '
';
+ $suffix = '
';
+ $info['content'] = $prefix . $info['content'] . $suffix;
+
+ // Detect when an entity is being rendered by page_manager, and then set
+ // a global (GASP!) variable. This is necessary, because page manager
+ // has an incorrectly applied "contextual-links-region" class: it's set
+ // on the wrong element (by ctools_context_handler_render_handler(),
+ // hence breaking Edit module's JS in the process. The worst part: it is
+ // *impossible* to override it in a sane way.
+ // As always, there is a work-around in Drupal, but it's not pretty:
+ // detect here whether an entity is being rendered by page manager, set
+ // a global variable, and then let edit_page_build() perform string
+ // manipulation on the final $page renderable array.
+ global $edit_workaround_for_fundamentally_broken_page_manager;
+ $edit_workaround_for_fundamentally_broken_page_manager = TRUE;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Implements hook_preprocess_panelizer_view_mode().
+ *
+ * Sets data-edit-entity-id attribute in case of a panelized, non-full-page
+ * entity view.
+ *
+ * @see edit_ctools_render_alter()
+ * @see edit_preprocess_node()
+ */
+function edit_preprocess_panelizer_view_mode(&$variables) {
+ $entity_type = $variables['element']['#entity_type'];
+ $entity = $variables['element']['#' . $entity_type];
+ $entity_id = entity_id($entity_type, $entity);
+
+ // Set data-edit-entity-id attribute.
+ $variables['attributes_array']['data-edit-entity-id'] = $entity_type . '/' . $entity_id;
+
+ // If the entity has a title, set data-edit-field-id attribute.
+ if (!empty($entity->title)) {
+ $language = !empty($entity->language) ? $entity->language : LANGUAGE_NONE;
+ $view_mode = _panelizer_generate_edit_viewmode($entity);
+ $variables['title_attributes_array']['data-edit-field-id'] = "$entity_type/$entity_id/title/$language/$view_mode";
+ }
+}
+
+/**
+ * Helper function to transform the "panelizer view mode" into an "Edit view
+ * mode ID", to make Edit use Panelizer's render pipeline to re-render fields
+ * after they've been edited.
+ *
+ * @see panelizer_edit_render_field()
+ */
+function _panelizer_generate_edit_viewmode($entity) {
+ // Ensure Panelizer view mode property exists.
+ if (!isset($entity->panelizer_view_mode)) {
+ return;
+ }
+
+ // @see includes/panelizer.inc/panelizer_panelizer_pre_render_alter()
+ $key = $entity->panelizer_view_mode;
+ $panelizer_entity = $entity->panelizer[$key];
+ return implode('-', array('panelizer', $panelizer_entity->view_mode));
+}
+
+/**
+ * Implements hook_edit_render_field().
+ *
+ * @see _panelizer_generate_edit_viewmode()
+ */
+function panelizer_edit_render_field($entity_type, $entity, $field_name, $view_mode_id, $langcode) {
+ ctools_include('plugins', 'panels');
+ ctools_include('content', 'ctools');
+
+ list($module, $panelizer_view_mode) = explode('-', $view_mode_id);
+
+ // Now render the given field (which resides in the given pane ID) through
+ // Panels' render pipeline.
+ $args = array(entity_id($entity_type, $entity));
+ // @see panelizer_panelizer_task_render()
+ $entity_handler = panelizer_entity_plugin_get_handler($entity_type);
+ // @see PanelizerEntityDefault.class.php::render_entity().
+ $panelizer = $entity->panelizer[$panelizer_view_mode];
+
+ // Special case: the title.
+ // Note: it is technically impossible to determine what should be rendered
+ // exactly, because it is determined by a subset of a template. Hence we do a
+ // best-effort approximation.
+ // @see panelizer-view-mode.tpl.php
+ if ($field_name === 'title') {
+ $entity_id = entity_id($entity_type, $entity);
+ // @see PanelizerEntityDefault::preprocess_panelizer_view_mode()
+ $title_element = 'h2';
+ if (!empty($panelizer->title_element)) {
+ $title_element = $panelizer->title_element;
+ }
+ $entity_url = NULL;
+ if (!empty($panelizer->link_to_entity)) {
+ $bits = explode('/', $entity_handler->plugin['entity path']);
+ foreach ($bits as $count => $bit) {
+ if (strpos($bit, '%') === 0) {
+ $bits[$count] = $entity_id;
+ }
+ }
+ $entity_url = url(implode('/', $bits));
+ }
+ // Immediately return the rendered title pseudo-field.
+ $edit_id = "$entity_type/$entity_id/title/$langcode/$view_mode_id";
+ $prefix = '<' . $title_element . ' data-edit-field-id="' . $edit_id .'">';
+ $suffix . '' . $title_element . '>';
+ if (isset($entity_url)) {
+ $markup = $prefix . '
' . $entity->title . '' . $suffix;
+ }
+ else {
+ $markup = $prefix . $entity->title . $suffix;
+ }
+ return array('#markup' => $markup);
+ }
+
+ // @see PanelizerEntityDefault.class.php::render_entity().
+ $display = $panelizer->display;
+ $display->context = $entity_handler->get_contexts($panelizer, $entity);
+ $display->args = $args;
+ $display->css_id = $panelizer->css_id;
+ $renderer = panels_get_renderer_handler($panelizer->pipeline, $display);
+ // Find the ID of the pane where the given field resides; it's impossible to
+ // know which pane ID the field is being rendered in when the
+ // data-edit-field-id attribute gets set in edit_preprocess_field(), so sadly
+ // we have to resort to this work-around. This *will* break down if the same
+ // field is rendered multiple times.
+ $pane_id = NULL;
+ foreach ($display->content as $id => $pane) {
+ if ($pane->type === 'entity_field' && $pane->subtype === $entity_type . ':'. $field_name) {
+ $pane_id = $id;
+ break;
+ }
+ }
+ // @see panels_renderer_standard::render_panes()
+ $pane = $display->content[$pane_id];
+ // @see panels_renderer_standard::render_pane()
+ module_invoke_all('panels_pane_prerender', $pane);
+ $pane_content = $renderer->render_pane_content($pane);
+
+ // Finally, return the renderable array containing the field.
+ return $pane_content->content;
+}