big_pipe.module

Same filename and directory in other branches
  1. 9 core/modules/big_pipe/big_pipe.module
  2. 8.9.x core/modules/big_pipe/big_pipe.module
  3. 10 core/modules/big_pipe/big_pipe.module

Adds BigPipe no-JS detection.

File

core/modules/big_pipe/big_pipe.module

View source
<?php


/**
 * @file
 * Adds BigPipe no-JS detection.
 */
use Drupal\big_pipe\Render\Placeholder\BigPipeStrategy;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;

/**
 * Implements hook_help().
 */
function big_pipe_help($route_name, RouteMatchInterface $route_match) {
    switch ($route_name) {
        case 'help.page.big_pipe':
            $output = '<h2>' . t('About') . '</h2>';
            $output .= '<p>' . t('The BigPipe module sends pages with dynamic content in a way that allows browsers to show them much faster. For more information, see the <a href=":big_pipe-documentation">online documentation for the BigPipe module</a>.', [
                ':big_pipe-documentation' => 'https://www.drupal.org/documentation/modules/big_pipe',
            ]) . '</p>';
            $output .= '<h2>' . t('Uses') . '</h2>';
            $output .= '<dl>';
            $output .= '<dt>' . t('Speeding up your site') . '</dt>';
            $output .= '<dd>' . t('The module requires no configuration. Every part of the page contains metadata that allows BigPipe to figure this out on its own.') . '</dd>';
            $output .= '</dl>';
            return $output;
    }
}

/**
 * Implements hook_page_attachments().
 *
 * @see \Drupal\big_pipe\Controller\BigPipeController::setNoJsCookie()
 */
function big_pipe_page_attachments(array &$page) {
    // Routes that don't use BigPipe also don't need no-JS detection.
    if (\Drupal::routeMatch()->getRouteObject()
        ->getOption('_no_big_pipe')) {
        return;
    }
    $request = \Drupal::request();
    // BigPipe is only used when there is an actual session, so only add the no-JS
    // detection when there actually is a session.
    // @see \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy.
    $session_exists = \Drupal::service('session_configuration')->hasSession($request);
    $page['#cache']['contexts'][] = 'session.exists';
    // Only do the no-JS detection while we don't know if there's no JS support:
    // avoid endless redirect loops.
    $has_big_pipe_nojs_cookie = $request->cookies
        ->has(BigPipeStrategy::NOJS_COOKIE);
    $page['#cache']['contexts'][] = 'cookies:' . BigPipeStrategy::NOJS_COOKIE;
    if ($session_exists) {
        if (!$has_big_pipe_nojs_cookie) {
            // Let server set the BigPipe no-JS cookie.
            $page['#attached']['html_head'][] = [
                [
                    // Redirect through a 'Refresh' meta tag if JavaScript is disabled.
'#tag' => 'meta',
                    '#noscript' => TRUE,
                    '#attributes' => [
                        'http-equiv' => 'Refresh',
                        'content' => '0; URL=' . Url::fromRoute('big_pipe.nojs', [], [
                            'query' => \Drupal::service('redirect.destination')->getAsArray(),
                        ])
                            ->toString(),
                    ],
                ],
                'big_pipe_detect_nojs',
            ];
        }
        else {
            // Let client delete the BigPipe no-JS cookie.
            $page['#attached']['html_head'][] = [
                [
                    '#tag' => 'script',
                    '#value' => 'document.cookie = "' . BigPipeStrategy::NOJS_COOKIE . '=1; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"',
                ],
                'big_pipe_detect_js',
            ];
        }
    }
}

/**
 * Implements hook_theme().
 */
function big_pipe_theme() {
    return [
        'big_pipe_interface_preview' => [
            'variables' => [
                'callback' => NULL,
                'arguments' => NULL,
                'preview' => NULL,
            ],
        ],
    ];
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function big_pipe_theme_suggestions_big_pipe_interface_preview(array $variables) {
    $common_callbacks_simplified_suggestions = [
        'Drupal_block_BlockViewBuilder__lazyBuilder' => 'block',
    ];
    $suggestions = [];
    $suggestion = 'big_pipe_interface_preview';
    if ($variables['callback']) {
        $callback = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['callback']);
        if (is_array($callback)) {
            $callback = implode('__', $callback);
        }
        // Use simplified template suggestion, if any.
        // For example, this simplifies
        // big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--<BLOCK ID>.html.twig
        // to
        // big-pipe-interface-preview--block--<BLOCK ID>.html.twig
        if (isset($common_callbacks_simplified_suggestions[$callback])) {
            $callback = $common_callbacks_simplified_suggestions[$callback];
        }
        $suggestions[] = $suggestion .= '__' . $callback;
        if (is_array($variables['arguments'])) {
            $arguments = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['arguments']);
            foreach ($arguments as $argument) {
                if (empty($argument)) {
                    continue;
                }
                $suggestions[] = $suggestion . '__' . $argument;
            }
        }
    }
    return $suggestions;
}

Functions

Title Deprecated Summary
big_pipe_help Implements hook_help().
big_pipe_page_attachments Implements hook_page_attachments().
big_pipe_theme Implements hook_theme().
big_pipe_theme_suggestions_big_pipe_interface_preview Implements hook_theme_suggestions_HOOK().

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.