Skip to content
Snippets Groups Projects
Unverified Commit 96ef832f authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2941208 by AdamPS, dpi, sja112, aleevas, andypost, anmolgoyal74,...

Issue #2941208 by AdamPS, dpi, sja112, aleevas, andypost, anmolgoyal74, Spokje, jofitz, Rinku Jacob 13, jonathanshaw, plach, larowlan, alexpott, catch, lauriii: Title formatting broken due to flawed EntityViewController->buildTitle
parent d0342520
No related branches found
No related tags found
38 merge requests!7471uncessary 5 files are moved from media-library folder to misc folder,!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!3630Issue #2815301 by Chi, DanielVeza, kostyashupenko, smustgrave: Allow to create...,!3291Issue #3336463: Rewrite rules for gzipped CSS and JavaScript aggregates never match,!3143Issue #3313342: [PHP 8.1] Deprecated function: strpos(): Passing null to parameter #1 LayoutBuilderUiCacheContext.php on line 28,!3102Issue #3164428 by DonAtt, longwave, sahil.goyal, Anchal_gupta, alexpott: Use...,!2853#3274419 Makes BaseFieldOverride inherit the internal property from the base field.,!2719Issue #3110137: Remove Classy from core.,!2437Issue #3238257 by hooroomoo, Wim Leers: Fragment link pointing to <textarea>...,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2074Issue #2707689: NodeForm::actions() checks for delete access on new entities,!2062Issue #3246454: Add weekly granularity to views date sort,!1974Issue #3036862 demonstration,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1254Issue #3238915: Refactor (if feasible) uses of the jQuery ready function to use VanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!957Added throwing of InvalidPluginDefinitionException from getDefinition().,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!873Issue #2875228: Site install not using batch API service,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!712Issue #2909128: Autocomplete intermittent on Chrome Android,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -55,6 +55,19 @@ public static function create(ContainerInterface $container) {
/**
* Pre-render callback to build the page title.
*
* There are two possibilities, depending on the value of the additional
* entity type property 'enable_page_title_template'.
* - FALSE (default): use the output of the related field formatter if it
* exists. This approach only works correctly for the node entity type and
* with the 'string' formatter. In other cases it likely produces illegal
* markup and possibly incorrect display. This option has been retained for
* backward-compatibility to support sites that expect attributes set on
* the field to propagate to the page title.
* - TRUE: use the output from the entity_page_title template. This approach
* works correctly in all cases, without relying on a particular field
* formatter or special templates and is the preferred option for the
* future.
*
* @param array $page
* A page render array.
*
......@@ -64,12 +77,31 @@ public static function create(ContainerInterface $container) {
public function buildTitle(array $page) {
$entity_type = $page['#entity_type'];
$entity = $page['#' . $entity_type];
// If the entity's label is rendered using a field formatter, set the
// rendered title field formatter as the page title instead of the default
// plain text title. This allows attributes set on the field to propagate
// correctly (e.g. in-place editing).
// If the entity has a label field, build the page title based on it.
if ($entity instanceof FieldableEntityInterface) {
$label_field = $entity->getEntityType()->getKey('label');
$template_enabled = $entity->getEntityType()->get('enable_page_title_template');
if ($label_field && $template_enabled) {
// Set page title to the output from the entity_page_title template.
$page_title = [
'#theme' => 'entity_page_title',
'#title' => $entity->label(),
'#entity' => $entity,
'#view_mode' => $page['#view_mode'],
];
$page['#title'] = $this->renderer->render($page_title);
// Prevent output of the label field in the main content.
$page[$label_field]['#access'] = FALSE;
return $page;
}
// Set page title to the rendered title field formatter instead of
// the default plain text title.
//
// @todo https://www.drupal.org/project/drupal/issues/3015623
// Eventually delete this code and always use the first approach.
if (isset($page[$label_field])) {
// Allow templates and theme functions to generate different markup
// for the page title, which must be inline markup as it will be placed
......
......@@ -25,4 +25,5 @@ function node_display_configurable_test_entity_base_field_info_alter(&$base_fiel
function node_display_configurable_test_entity_type_build(array &$entity_types) {
// Allow skipping of extra preprocessing for configurable display.
$entity_types['node']->set('enable_base_field_custom_preprocess_skipping', TRUE);
$entity_types['node']->set('enable_page_title_template', TRUE);
}
......@@ -69,7 +69,7 @@ public function testDisplayConfigurable(string $theme, string $metadata_region,
// Check the node with Drupal default non-configurable display.
$this->drupalGet($node->toUrl());
$this->assertNodeHtml($node, $user, TRUE, $metadata_region, $field_classes);
$this->assertNodeHtml($node, $user, TRUE, $metadata_region, $field_classes, $field_classes);
// Enable module to make base fields' displays configurable.
\Drupal::service('module_installer')->install(['node_display_configurable_test']);
......@@ -82,12 +82,13 @@ public function testDisplayConfigurable(string $theme, string $metadata_region,
'label' => 'above',
'settings' => ['link' => FALSE],
])
->removeComponent('title')
->save();
// Recheck the node with configurable display.
$this->drupalGet($node->toUrl());
$this->assertNodeHtml($node, $user, FALSE, $metadata_region, $field_classes);
$this->assertNodeHtml($node, $user, FALSE, $metadata_region, $field_classes, FALSE);
$assert->elementExists('css', 'div[rel="schema:author"]');
......@@ -113,15 +114,17 @@ public function testDisplayConfigurable(string $theme, string $metadata_region,
* @param string $metadata_region
* The region of the node html content where meta data is expected.
* @param bool $field_classes
* If TRUE, check for field--name-XXX classes.
* If TRUE, check for field--name-XXX classes on created/uid fields.
* @param bool $title_classes
* If TRUE, check for field--name-XXX classes on title field.
*
* @internal
*/
protected function assertNodeHtml(NodeInterface $node, UserInterface $user, bool $is_inline, string $metadata_region, bool $field_classes): void {
protected function assertNodeHtml(NodeInterface $node, UserInterface $user, bool $is_inline, string $metadata_region, bool $field_classes, bool $title_classes): void {
$assert = $this->assertSession();
$html_element = $is_inline ? 'span' : 'div';
$title_selector = 'h1 span' . ($field_classes ? '.field--name-title' : '');
$title_selector = 'h1 span' . ($title_classes ? '.field--name-title' : '');
$assert->elementTextContains('css', $title_selector, $node->getTitle());
// With field classes, the selector can be very specific.
......
......@@ -128,6 +128,23 @@ function quickedit_preprocess_page_title(&$variables) {
}
}
/**
* Implements hook_preprocess_entity_page_title().
*/
function quickedit_preprocess_entity_page_title(&$variables) {
$variables['#cache']['contexts'][] = 'user.permissions';
$entity = $variables['entity'];
if (!\Drupal::currentUser()->hasPermission('access in-place editing')) {
return;
}
if (($entity instanceof RevisionableInterface) && !$entity->isLatestRevision()) {
return;
}
$label_field = $entity->getEntityType()->getKey('label');
$variables['attributes']['data-quickedit-field-id'] = $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $label_field . '/' . $entity->language()->getId() . '/' . $variables['view_mode'];
}
/**
* Implements hook_preprocess_HOOK() for field templates.
*/
......
......@@ -253,6 +253,14 @@ function system_theme() {
'file' => 'system.theme.inc',
'variables' => ['error_message' => []],
],
'entity_page_title' => [
'variables' => [
'attributes' => [],
'title' => NULL,
'entity' => NULL,
'view_mode' => NULL,
],
],
]);
}
......
{#
/**
* @file
* Default theme implementation for entity page title.
*
* This output from this template is nested within the page-title template as
* the title variable. This allows a further refinement of the page title
* specific to an entity.
*
* This template is only used if the additional entity type property
* 'enable_page_title_template' is set to TRUE.
*
* Available variables:
* - attributes: HTML attributes for the containing span element.
* - title: Entity label.
* - entity: Entity having a label field.
* - view_mode: View mode; for example, "teaser" or "full".
*
* @see \Drupal\Core\Entity\Controller\EntityViewController::buildTitle()
*
* @ingroup themeable
*/
#}
<span{{ attributes }}>
{{ title }}
</span>
{#
/**
* @file
* Theme override for entity page title.
*
* This output from this template is nested within the page-title template as
* the title variable. This allows a further refinement of the page title
* specific to an entity.
*
* This template is only used if the additional entity type property
* 'enable_page_title_template' is set to TRUE.
*
* Available variables:
* - attributes: HTML attributes for the containing span element.
* - title: Entity label.
* - entity: Entity having a label field.
* - view_mode: View mode; for example, "teaser" or "full".
*/
#}
<span{{ attributes }}>
{{ title }}
</span>
{#
/**
* @file
* Theme override for entity page title.
*
* This output from this template is nested within the page-title template as
* the title variable. This allows a further refinement of the page title
* specific to an entity.
*
* This template is only used if the additional entity type property
* 'enable_page_title_template' is set to TRUE.
*
* Available variables:
* - attributes: HTML attributes for the containing span element.
* - title: Entity label.
* - entity: Entity having a label field.
* - view_mode: View mode; for example, "teaser" or "full".
*/
#}
<span{{ attributes }}>
{{ title }}
</span>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment