Unverified Commit b73b9291 authored by Alex Pott's avatar Alex Pott
Browse files

feat: #3339905 Add page_top and page_bottom to #attached to get rid of NodeThemeHooks::pageTop()

By: longwave
By: catch
By: acbramley
By: smustgrave
By: alexpott
(cherry picked from commit 07f90f1f3d757b67a81281f0f7b070608190a526)
parent 06cdb3bb
Loading
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -9667,18 +9667,6 @@
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php',
];
$ignoreErrors[] = [
	'message' => '#^Variable \\$page_bottom in empty\\(\\) always exists and is always falsy\\.$#',
	'identifier' => 'empty.variable',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php',
];
$ignoreErrors[] = [
	'message' => '#^Variable \\$page_top in empty\\(\\) always exists and is always falsy\\.$#',
	'identifier' => 'empty.variable',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\Render\\\\MetadataBubblingUrlGenerator\\:\\:bubble\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
 *   response attachment
 * - library: (optional) Asset libraries.
 * - placeholders: (optional) Any placeholders.
 * - page_top: (optional) Inject content into the top of the page.
 * - page_bottom: (optional) Inject content into the bottom of the page.
 *
 * @todo If in Drupal 9, we remove attachments other than assets (libraries +
 *   drupalSettings), then we can look into unifying this with
+2 −0
Original line number Diff line number Diff line
@@ -111,6 +111,8 @@ public function processAttachments(AttachmentsInterface $response) {
        'html_response_attachment_placeholders',
        'placeholders',
        'drupalSettings',
        'page_top',
        'page_bottom',
      ]
    );
    if (!empty($unsupported_types)) {
+6 −4
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
    // The special page regions will appear directly in html.html.twig, not in
    // page.html.twig, hence add them here, just before rendering
    // html.html.twig.
    $this->buildPageTopAndBottom($html);
    $this->buildPageTopAndBottom($html, $main_content['#attached']['page_top'] ?? [], $main_content['#attached']['page_bottom'] ?? []);

    // Render, but don't replace placeholders yet, because that happens later in
    // the render pipeline. To not replace placeholders yet, we use
@@ -337,6 +337,10 @@ function (callable $hook, string $module) use (&$attachments) {
   *   A #type 'html' render array, for which the page top and bottom hooks will
   *   be invoked, and to which the 'page_top' and 'page_bottom' children (also
   *   render arrays) will be added (if non-empty).
   * @param array $page_top
   *   (optional) The render array representing the initial page top content.
   * @param array $page_bottom
   *   (optional) The render array representing the initial page bottom content.
   *
   * @throws \LogicException
   *
@@ -346,10 +350,8 @@ function (callable $hook, string $module) use (&$attachments) {
   * @see hook_page_bottom()
   * @see html.html.twig
   */
  public function buildPageTopAndBottom(array &$html) {
  public function buildPageTopAndBottom(array &$html, array $page_top = [], array $page_bottom = []) {
    // Modules can add render arrays to the top and bottom of the page.
    $page_top = [];
    $page_bottom = [];
    $this->moduleHandler->invokeAllWith(
      'page_top',
      function (callable $hook, string $module) use (&$page_top) {
+25 −19
Original line number Diff line number Diff line
@@ -6,7 +6,9 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\node\Form\NodePreviewForm;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
@@ -15,25 +17,19 @@
class NodePreviewController extends EntityViewController {

  /**
   * The entity repository service.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   * Creates a NodePreviewController object.
   */
  protected $entityRepository;

  /**
   * Creates a NodeViewController object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer service.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer, EntityRepositoryInterface $entity_repository) {
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    RendererInterface $renderer,
    protected readonly EntityRepositoryInterface $entityRepository,
    protected ?FormBuilderInterface $formBuilder = NULL,
  ) {
    parent::__construct($entity_type_manager, $renderer);
    $this->entityRepository = $entity_repository;
    if ($this->formBuilder === NULL) {
      @trigger_error('Calling ' . __CLASS__ . ' constructor without the $formBuilder argument is deprecated in drupal:11.4.0 and it will be required in drupal:12.0.0. See https://www.drupal.org/project/drupal/issues/3339905', E_USER_DEPRECATED);
      $this->formBuilder = \Drupal::service('form_builder');
    }
  }

  /**
@@ -43,7 +39,8 @@ public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('renderer'),
      $container->get('entity.repository')
      $container->get('entity.repository'),
      $container->get('form_builder'),
    );
  }

@@ -55,7 +52,16 @@ public function view(EntityInterface $node_preview, $view_mode_id = 'full', $lan
    $build = parent::view($node_preview, $view_mode_id);

    $build['#attached']['library'][] = 'node/drupal.node.preview';

    $build['#attached']['page_top']['node_preview'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => [
          'node-preview-container',
          'container-inline',
        ],
      ],
      'view_mode' => $this->formBuilder->getForm(NodePreviewForm::class, $node_preview),
    ];
    // Don't render cache previews.
    unset($build['#cache']);

Loading