Issue #2569119 by pwolanin, marvin_B8, jhedstrom, csheltonlcm, alexpott, dawehner, Fabianx, catch: Use Crypt::hashBase64(), not hash('crc32b') or sha1 for placeholder tokens

8.3.x
Alex Pott 2016-12-15 10:20:19 +00:00
parent f403ccb9c5
commit 94f0aacff6
24 changed files with 108 additions and 65 deletions

View File

@ -1554,7 +1554,7 @@ services:
class: Drupal\Core\Extension\InfoParser class: Drupal\Core\Extension\InfoParser
twig: twig:
class: Drupal\Core\Template\TwigEnvironment class: Drupal\Core\Template\TwigEnvironment
arguments: ['@app.root', '@cache.default', '%twig_extension_hash%', '@twig.loader', '%twig.config%'] arguments: ['@app.root', '@cache.default', '%twig_extension_hash%', '@state', '@twig.loader', '%twig.config%']
tags: tags:
- { name: service_collector, tag: 'twig.extension', call: addExtension } - { name: service_collector, tag: 'twig.extension', call: addExtension }
twig.extension: twig.extension:

View File

@ -10,6 +10,7 @@ use Doctrine\Common\Annotations\SimpleAnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Reflection\StaticReflectionParser; use Doctrine\Common\Reflection\StaticReflectionParser;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait; use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
use Drupal\Component\Utility\Crypt;
/** /**
* Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces. * Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
@ -74,7 +75,7 @@ class AnnotatedClassDiscovery implements DiscoveryInterface {
$this->annotationNamespaces = $annotation_namespaces; $this->annotationNamespaces = $annotation_namespaces;
$file_cache_suffix = str_replace('\\', '_', $plugin_definition_annotation_name); $file_cache_suffix = str_replace('\\', '_', $plugin_definition_annotation_name);
$file_cache_suffix .= ':' . hash('crc32b', serialize($annotation_namespaces)); $file_cache_suffix .= ':' . Crypt::hashBase64(serialize($annotation_namespaces));
$this->fileCache = FileCacheFactory::get('annotation_discovery:' . $file_cache_suffix); $this->fileCache = FileCacheFactory::get('annotation_discovery:' . $file_cache_suffix);
} }

View File

@ -2,6 +2,7 @@
namespace Drupal\Component\DependencyInjection\Dumper; namespace Drupal\Component\DependencyInjection\Dumper;
use Drupal\Component\Utility\Crypt;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Parameter;
@ -373,7 +374,7 @@ class OptimizedPhpArrayDumper extends Dumper {
protected function getPrivateServiceCall($id, Definition $definition, $shared = FALSE) { protected function getPrivateServiceCall($id, Definition $definition, $shared = FALSE) {
$service_definition = $this->getServiceDefinition($definition); $service_definition = $this->getServiceDefinition($definition);
if (!$id) { if (!$id) {
$hash = hash('sha1', serialize($service_definition)); $hash = Crypt::hashBase64(serialize($service_definition));
$id = 'private__' . $hash; $id = 'private__' . $hash;
} }
return (object) array( return (object) array(

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\Access; namespace Drupal\Core\Access;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface; use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
@ -45,7 +46,7 @@ class RouteProcessorCsrf implements OutboundRouteProcessorInterface {
} }
else { else {
// Generate a placeholder and a render array to replace it. // Generate a placeholder and a render array to replace it.
$placeholder = hash('sha1', $path); $placeholder = Crypt::hashBase64($path);
$placeholder_render_array = [ $placeholder_render_array = [
'#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]], '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
]; ];

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\Config\Development; namespace Drupal\Core\Config\Development;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Config\ConfigCrudEvent; use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents; use Drupal\Core\Config\ConfigEvents;
@ -79,7 +80,7 @@ class ConfigSchemaChecker implements EventSubscriberInterface {
$name = $saved_config->getName(); $name = $saved_config->getName();
$data = $saved_config->get(); $data = $saved_config->get();
$checksum = hash('crc32b', serialize($data)); $checksum = Crypt::hashBase64(serialize($data));
if (!in_array($name, $this->exclude) && !isset($this->checked[$name . ':' . $checksum])) { if (!in_array($name, $this->exclude) && !isset($this->checked[$name . ':' . $checksum])) {
$this->checked[$name . ':' . $checksum] = TRUE; $this->checked[$name . ':' . $checksum] = TRUE;
$errors = $this->checkConfigSchema($this->typedManager, $name, $data); $errors = $this->checkConfigSchema($this->typedManager, $name, $data);

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\DependencyInjection\Compiler; namespace Drupal\Core\DependencyInjection\Compiler;
use Drupal\Component\Utility\Crypt;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -26,7 +27,7 @@ class TwigExtensionPass implements CompilerPassInterface {
$twig_extension_hash .= $class_name . filemtime($reflection->getFileName()); $twig_extension_hash .= $class_name . filemtime($reflection->getFileName());
} }
$container->setParameter('twig_extension_hash', hash('crc32b', $twig_extension_hash)); $container->setParameter('twig_extension_hash', Crypt::hashBase64($twig_extension_hash));
} }
} }

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\Entity; namespace Drupal\Core\Entity;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay;
@ -462,7 +463,7 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
// series of fields individually for cases such as views tables. // series of fields individually for cases such as views tables.
$entity_type_id = $entity->getEntityTypeId(); $entity_type_id = $entity->getEntityTypeId();
$bundle = $entity->bundle(); $bundle = $entity->bundle();
$key = $entity_type_id . ':' . $bundle . ':' . $field_name . ':' . hash('crc32b', serialize($display_options)); $key = $entity_type_id . ':' . $bundle . ':' . $field_name . ':' . Crypt::hashBase64(serialize($display_options));
if (!isset($this->singleFieldDisplays[$key])) { if (!isset($this->singleFieldDisplays[$key])) {
$this->singleFieldDisplays[$key] = EntityViewDisplay::create(array( $this->singleFieldDisplays[$key] = EntityViewDisplay::create(array(
'targetEntityType' => $entity_type_id, 'targetEntityType' => $entity_type_id,

View File

@ -683,8 +683,9 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
// will be replaced at the very last moment. This ensures forms with // will be replaced at the very last moment. This ensures forms with
// dynamically generated action URLs don't have poor cacheability. // dynamically generated action URLs don't have poor cacheability.
// Use the proper API to generate the placeholder, when we have one. See // Use the proper API to generate the placeholder, when we have one. See
// https://www.drupal.org/node/2562341. // https://www.drupal.org/node/2562341. The placholder uses a fixed string
$placeholder = 'form_action_' . hash('crc32b', __METHOD__); // that is Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
$placeholder = 'form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM';
$form['#attached']['placeholders'][$placeholder] = [ $form['#attached']['placeholders'][$placeholder] = [
'#lazy_builder' => ['form_builder:renderPlaceholderFormAction', []], '#lazy_builder' => ['form_builder:renderPlaceholderFormAction', []],
@ -744,7 +745,7 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
if ($user && $user->isAuthenticated()) { if ($user && $user->isAuthenticated()) {
// Generate a public token based on the form id. // Generate a public token based on the form id.
// Generates a placeholder based on the form ID. // Generates a placeholder based on the form ID.
$placeholder = 'form_token_placeholder_' . hash('crc32b', $form_id); $placeholder = 'form_token_placeholder_' . Crypt::hashBase64($form_id);
$form['#token'] = $placeholder; $form['#token'] = $placeholder;
$form['form_token'] = array( $form['form_token'] = array(

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\Render; namespace Drupal\Core\Render;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper; use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
@ -84,7 +85,7 @@ class PlaceholderGenerator implements PlaceholderGeneratorInterface {
// debugging. // debugging.
$callback = $placeholder_render_array['#lazy_builder'][0]; $callback = $placeholder_render_array['#lazy_builder'][0];
$arguments = UrlHelper::buildQuery($placeholder_render_array['#lazy_builder'][1]); $arguments = UrlHelper::buildQuery($placeholder_render_array['#lazy_builder'][1]);
$token = hash('crc32b', serialize($placeholder_render_array)); $token = Crypt::hashBase64(serialize($placeholder_render_array));
$placeholder_markup = '<drupal-render-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-render-placeholder>'; $placeholder_markup = '<drupal-render-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-render-placeholder>';
// Build the placeholder element to return. // Build the placeholder element to return.

View File

@ -4,6 +4,7 @@ namespace Drupal\Core\Template;
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Render\Markup; use Drupal\Core\Render\Markup;
use Drupal\Core\State\StateInterface;
/** /**
* A class that defines a Twig environment for Drupal. * A class that defines a Twig environment for Drupal.
@ -22,6 +23,8 @@ class TwigEnvironment extends \Twig_Environment {
*/ */
protected $templateClasses; protected $templateClasses;
protected $twigCachePrefix = '';
/** /**
* Constructs a TwigEnvironment object and stores cache and storage * Constructs a TwigEnvironment object and stores cache and storage
* internally. * internally.
@ -32,12 +35,14 @@ class TwigEnvironment extends \Twig_Environment {
* The cache bin. * The cache bin.
* @param string $twig_extension_hash * @param string $twig_extension_hash
* The Twig extension hash. * The Twig extension hash.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Twig_LoaderInterface $loader * @param \Twig_LoaderInterface $loader
* The Twig loader or loader chain. * The Twig loader or loader chain.
* @param array $options * @param array $options
* The options for the Twig environment. * The options for the Twig environment.
*/ */
public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, \Twig_LoaderInterface $loader = NULL, $options = array()) { public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, $options = array()) {
// Ensure that twig.engine is loaded, given that it is needed to render a // Ensure that twig.engine is loaded, given that it is needed to render a
// template because functions like TwigExtension::escapeFilter() are called. // template because functions like TwigExtension::escapeFilter() are called.
require_once $root . '/core/themes/engines/twig/twig.engine'; require_once $root . '/core/themes/engines/twig/twig.engine';
@ -58,13 +63,35 @@ class TwigEnvironment extends \Twig_Environment {
$this->addExtension($sandbox); $this->addExtension($sandbox);
if ($options['cache'] === TRUE) { if ($options['cache'] === TRUE) {
$options['cache'] = new TwigPhpStorageCache($cache, $twig_extension_hash); $current = $state->get('twig_extension_hash_prefix', ['twig_extension_hash' => '']);
if ($current['twig_extension_hash'] !== $twig_extension_hash || empty($current['twig_cache_prefix'])) {
$current = [
'twig_extension_hash' => $twig_extension_hash,
// Generate a new prefix which invalidates any existing cached files.
'twig_cache_prefix' => uniqid(),
];
$state->set('twig_extension_hash_prefix', $current);
}
$this->twigCachePrefix = $current['twig_cache_prefix'];
$options['cache'] = new TwigPhpStorageCache($cache, $this->twigCachePrefix);
} }
$this->loader = $loader; $this->loader = $loader;
parent::__construct($this->loader, $options); parent::__construct($this->loader, $options);
} }
/**
* Get the cache prefixed used by \Drupal\Core\Template\TwigPhpStorageCache
*
* @return string
* The file cache prefix, or empty string if the cache is disabled.
*/
public function getTwigCachePrefix() {
return $this->twigCachePrefix;
}
/** /**
* Gets the template class associated with the given string. * Gets the template class associated with the given string.
* *

View File

@ -43,12 +43,12 @@ class TwigPhpStorageCache implements \Twig_CacheInterface {
* *
* @param \Drupal\Core\Cache\CacheBackendInterface $cache * @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache bin. * The cache bin.
* @param string $twig_extension_hash * @param string $twig_cache_prefix
* The Twig extension hash. * A Twig cache file prefix that changes when Twig extensions change.
*/ */
public function __construct(CacheBackendInterface $cache, $twig_extension_hash) { public function __construct(CacheBackendInterface $cache, $twig_cache_prefix) {
$this->cache = $cache; $this->cache = $cache;
$this->templateCacheFilenamePrefix = $twig_extension_hash; $this->templateCacheFilenamePrefix = $twig_cache_prefix;
} }
/** /**

View File

@ -158,9 +158,9 @@ class TypedDataManager extends DefaultPluginManager implements TypedDataManagerI
// Root data type and settings. // Root data type and settings.
$parts[] = $root_definition->getDataType(); $parts[] = $root_definition->getDataType();
if ($settings = $root_definition->getSettings()) { if ($settings = $root_definition->getSettings()) {
// Hash the settings into a string. crc32 is the fastest way to hash // Include the settings serialized as JSON as part of the key. The JSON is
// something for non-cryptographic purposes. // a shorter string than the serialized form, so array access is faster.
$parts[] = hash('crc32b', serialize($settings)); $parts[] = json_encode($settings);
} }
// Property path for the requested data object. When creating a list item, // Property path for the requested data object. When creating a list item,
// use 0 in the key as all items look the same. // use 0 in the key as all items look the same.

View File

@ -2,6 +2,7 @@
namespace Drupal\big_pipe\Render\Placeholder; namespace Drupal\big_pipe\Render\Placeholder;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper; use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface; use Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface;
@ -260,7 +261,7 @@ class BigPipeStrategy implements PlaceholderStrategyInterface {
if (isset($placeholder_render_array['#lazy_builder'])) { if (isset($placeholder_render_array['#lazy_builder'])) {
$callback = $placeholder_render_array['#lazy_builder'][0]; $callback = $placeholder_render_array['#lazy_builder'][0];
$arguments = $placeholder_render_array['#lazy_builder'][1]; $arguments = $placeholder_render_array['#lazy_builder'][1];
$token = hash('crc32b', serialize($placeholder_render_array)); $token = Crypt::hashBase64(serialize($placeholder_render_array));
return UrlHelper::buildQuery(['callback' => $callback, 'args' => $arguments, 'token' => $token]); return UrlHelper::buildQuery(['callback' => $callback, 'args' => $arguments, 'token' => $token]);
} }
// When the placeholder's render array is not using a #lazy_builder, // When the placeholder's render array is not using a #lazy_builder,

View File

@ -51,7 +51,7 @@ class BigPipePlaceholderTestCases {
// 1. Real-world example of HTML placeholder. // 1. Real-world example of HTML placeholder.
$status_messages = new BigPipePlaceholderTestCase( $status_messages = new BigPipePlaceholderTestCase(
['#type' => 'status_messages'], ['#type' => 'status_messages'],
'<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="a8c34b5e"></drupal-render-placeholder>', '<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></drupal-render-placeholder>',
[ [
'#lazy_builder' => [ '#lazy_builder' => [
'Drupal\Core\Render\Element\StatusMessages::renderMessages', 'Drupal\Core\Render\Element\StatusMessages::renderMessages',
@ -59,29 +59,29 @@ class BigPipePlaceholderTestCases {
], ],
] ]
); );
$status_messages->bigPipePlaceholderId = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e'; $status_messages->bigPipePlaceholderId = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
$status_messages->bigPipePlaceholderRenderArray = [ $status_messages->bigPipePlaceholderRenderArray = [
'#markup' => '<div data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e"></div>', '#markup' => '<div data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></div>',
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
'#attached' => [ '#attached' => [
'library' => ['big_pipe/big_pipe'], 'library' => ['big_pipe/big_pipe'],
'drupalSettings' => [ 'drupalSettings' => [
'bigPipePlaceholderIds' => [ 'bigPipePlaceholderIds' => [
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=a8c34b5e' => TRUE, 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => TRUE,
], ],
], ],
'big_pipe_placeholders' => [ 'big_pipe_placeholders' => [
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e' => $status_messages->placeholderRenderArray, 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => $status_messages->placeholderRenderArray,
], ],
], ],
]; ];
$status_messages->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e"></div>'; $status_messages->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></div>';
$status_messages->bigPipeNoJsPlaceholderRenderArray = [ $status_messages->bigPipeNoJsPlaceholderRenderArray = [
'#markup' => '<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e"></div>', '#markup' => '<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></div>',
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
'#attached' => [ '#attached' => [
'big_pipe_nojs_placeholders' => [ 'big_pipe_nojs_placeholders' => [
'<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e"></div>' => $status_messages->placeholderRenderArray, '<div data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></div>' => $status_messages->placeholderRenderArray,
], ],
], ],
]; ];
@ -109,7 +109,7 @@ class BigPipePlaceholderTestCases {
[ [
'command' => 'insert', 'command' => 'insert',
'method' => 'replaceWith', 'method' => 'replaceWith',
'selector' => '[data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=a8c34b5e"]', 'selector' => '[data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"]',
'data' => "\n" . ' <div role="contentinfo" aria-label="Status message" class="messages messages--status">' . "\n" . ' <h2 class="visually-hidden">Status message</h2>' . "\n" . ' Hello from BigPipe!' . "\n" . ' </div>' . "\n ", 'data' => "\n" . ' <div role="contentinfo" aria-label="Status message" class="messages messages--status">' . "\n" . ' <h2 class="visually-hidden">Status message</h2>' . "\n" . ' Hello from BigPipe!' . "\n" . ' </div>' . "\n ",
'settings' => NULL, 'settings' => NULL,
], ],
@ -267,29 +267,29 @@ class BigPipePlaceholderTestCases {
'#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']], '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']],
'#create_placeholder' => TRUE, '#create_placeholder' => TRUE,
], ],
'<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::exception" arguments="0=llamas&amp;1=suck" token="68a75f1a"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::exception" arguments="0=llamas&amp;1=suck" token="uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></drupal-render-placeholder>',
[ [
'#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']], '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']],
] ]
); );
$exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=68a75f1a'; $exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU';
$exception->bigPipePlaceholderRenderArray = [ $exception->bigPipePlaceholderRenderArray = [
'#markup' => '<div data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=68a75f1a"></div>', '#markup' => '<div data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></div>',
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
'#attached' => [ '#attached' => [
'library' => ['big_pipe/big_pipe'], 'library' => ['big_pipe/big_pipe'],
'drupalSettings' => [ 'drupalSettings' => [
'bigPipePlaceholderIds' => [ 'bigPipePlaceholderIds' => [
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=68a75f1a' => TRUE, 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => TRUE,
], ],
], ],
'big_pipe_placeholders' => [ 'big_pipe_placeholders' => [
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=68a75f1a' => $exception->placeholderRenderArray, 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => $exception->placeholderRenderArray,
], ],
], ],
]; ];
$exception->embeddedAjaxResponseCommands = NULL; $exception->embeddedAjaxResponseCommands = NULL;
$exception->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=68a75f1a"></div>'; $exception->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&amp;args[0]=llamas&amp;args[1]=suck&amp;token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></div>';
$exception->bigPipeNoJsPlaceholderRenderArray = [ $exception->bigPipeNoJsPlaceholderRenderArray = [
'#markup' => $exception->bigPipeNoJsPlaceholder, '#markup' => $exception->bigPipeNoJsPlaceholder,
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
@ -307,29 +307,29 @@ class BigPipePlaceholderTestCases {
'#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []], '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []],
'#create_placeholder' => TRUE, '#create_placeholder' => TRUE,
], ],
'<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::responseException" arguments="" token="2a9bd022"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::responseException" arguments="" token="PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></drupal-render-placeholder>',
[ [
'#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []], '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []],
] ]
); );
$embedded_response_exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=2a9bd022'; $embedded_response_exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU';
$embedded_response_exception->bigPipePlaceholderRenderArray = [ $embedded_response_exception->bigPipePlaceholderRenderArray = [
'#markup' => '<div data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=2a9bd022"></div>', '#markup' => '<div data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></div>',
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
'#attached' => [ '#attached' => [
'library' => ['big_pipe/big_pipe'], 'library' => ['big_pipe/big_pipe'],
'drupalSettings' => [ 'drupalSettings' => [
'bigPipePlaceholderIds' => [ 'bigPipePlaceholderIds' => [
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=2a9bd022' => TRUE, 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU' => TRUE,
], ],
], ],
'big_pipe_placeholders' => [ 'big_pipe_placeholders' => [
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=2a9bd022' => $embedded_response_exception->placeholderRenderArray, 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU' => $embedded_response_exception->placeholderRenderArray,
], ],
], ],
]; ];
$embedded_response_exception->embeddedAjaxResponseCommands = NULL; $embedded_response_exception->embeddedAjaxResponseCommands = NULL;
$embedded_response_exception->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=2a9bd022"></div>'; $embedded_response_exception->bigPipeNoJsPlaceholder = '<div data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&amp;&amp;token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></div>';
$embedded_response_exception->bigPipeNoJsPlaceholderRenderArray = [ $embedded_response_exception->bigPipeNoJsPlaceholderRenderArray = [
'#markup' => $embedded_response_exception->bigPipeNoJsPlaceholder, '#markup' => $embedded_response_exception->bigPipeNoJsPlaceholder,
'#cache' => $cacheability_depends_on_session_and_nojs_cookie, '#cache' => $cacheability_depends_on_session_and_nojs_cookie,

View File

@ -289,7 +289,7 @@ class BigPipeTest extends WebTestBase {
// @see performMetaRefresh() // @see performMetaRefresh()
$this->drupalGet(Url::fromRoute('big_pipe_test_multi_occurrence')); $this->drupalGet(Url::fromRoute('big_pipe_test_multi_occurrence'));
$big_pipe_placeholder_id = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=a8c34b5e'; $big_pipe_placeholder_id = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
$expected_placeholder_replacement = '<script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="' . $big_pipe_placeholder_id . '">'; $expected_placeholder_replacement = '<script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="' . $big_pipe_placeholder_id . '">';
$this->assertRaw('The count is 1.'); $this->assertRaw('The count is 1.');
$this->assertNoRaw('The count is 2.'); $this->assertNoRaw('The count is 2.');

View File

@ -2,8 +2,10 @@
namespace Drupal\block\Tests; namespace Drupal\block\Tests;
use Drupal\Component\Utility\Crypt;
use Drupal\simpletest\WebTestBase; use Drupal\simpletest\WebTestBase;
/** /**
* Tests form in block caching. * Tests form in block caching.
* *
@ -64,7 +66,7 @@ class BlockFormInBlockTest extends WebTestBase {
public function testPlaceholders() { public function testPlaceholders() {
$this->drupalGet('test-multiple-forms'); $this->drupalGet('test-multiple-forms');
$placeholder = 'form_action_' . hash('crc32b', 'Drupal\Core\Form\FormBuilder::prepareForm'); $placeholder = 'form_action_' . Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
$this->assertText('Form action: ' . $placeholder, 'placeholder found.'); $this->assertText('Form action: ' . $placeholder, 'placeholder found.');
} }

View File

@ -2,6 +2,7 @@
namespace Drupal\filter; namespace Drupal\filter;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper; use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
@ -134,7 +135,7 @@ class FilterProcessResult extends BubbleableMetadata {
// Generate placeholder markup. // Generate placeholder markup.
// @see \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder() // @see \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder()
$arguments = UrlHelper::buildQuery($args); $arguments = UrlHelper::buildQuery($args);
$token = hash('crc32b', serialize([$callback, $args])); $token = Crypt::hashBase64(serialize([$callback, $args]));
$placeholder_markup = '<drupal-filter-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-filter-placeholder>'; $placeholder_markup = '<drupal-filter-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-filter-placeholder>';
// Add the placeholder attachment. // Add the placeholder attachment.

View File

@ -60,8 +60,8 @@ function system_post_update_add_region_to_entity_displays() {
/** /**
* Force Twig PHP file cache to be cleared. * Force caches using hashes to be cleared (Twig, render cache, etc.).
*/ */
function system_post_update_clear_twig_cache() { function system_post_update_hashes_clear_cache() {
// Empty post-update hook. // Empty post-update hook.
} }

View File

@ -14,9 +14,9 @@ class RenderPlaceholderMessageTestController implements ContainerAwareInterface
*/ */
public function messagesPlaceholderFirst() { public function messagesPlaceholderFirst() {
return $this->build([ return $this->build([
'<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="a8c34b5e"></drupal-render-placeholder>', '<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="0546ada3"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="JBp04zOwNhYqMBgRkyBnPdma8m4l2elDnXMJ9tEsP6k"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="83d2df0d"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="JnoubSJT1l92Dm4fJw4EPsSzRsmE88H6Q1zu9-OzDh4"></drupal-render-placeholder>',
]); ]);
} }
@ -25,9 +25,9 @@ class RenderPlaceholderMessageTestController implements ContainerAwareInterface
*/ */
public function messagesPlaceholderMiddle() { public function messagesPlaceholderMiddle() {
return $this->build([ return $this->build([
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="0546ada3"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="JBp04zOwNhYqMBgRkyBnPdma8m4l2elDnXMJ9tEsP6k"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="a8c34b5e"></drupal-render-placeholder>', '<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="83d2df0d"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="JnoubSJT1l92Dm4fJw4EPsSzRsmE88H6Q1zu9-OzDh4"></drupal-render-placeholder>',
]); ]);
} }
@ -36,9 +36,9 @@ class RenderPlaceholderMessageTestController implements ContainerAwareInterface
*/ */
public function messagesPlaceholderLast() { public function messagesPlaceholderLast() {
return $this->build([ return $this->build([
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="0546ada3"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P1" token="JBp04zOwNhYqMBgRkyBnPdma8m4l2elDnXMJ9tEsP6k"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="83d2df0d"></drupal-render-placeholder>', '<drupal-render-placeholder callback="\Drupal\render_placeholder_message_test\RenderPlaceholderMessageTestController::setAndLogMessage" arguments="0=P2" token="JnoubSJT1l92Dm4fJw4EPsSzRsmE88H6Q1zu9-OzDh4"></drupal-render-placeholder>',
'<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="a8c34b5e"></drupal-render-placeholder>', '<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></drupal-render-placeholder>',
]); ]);
} }

View File

@ -83,11 +83,11 @@ class TwigEnvironmentTest extends KernelTestBase {
$this->assertEqual($renderer->renderRoot($element_copy), $expected); $this->assertEqual($renderer->renderRoot($element_copy), $expected);
$name = '{# inline_template_start #}' . $element['test']['#template']; $name = '{# inline_template_start #}' . $element['test']['#template'];
$hash = $this->container->getParameter('twig_extension_hash'); $prefix = $environment->getTwigCachePrefix();
$cache = $environment->getCache(); $cache = $environment->getCache();
$class = $environment->getTemplateClass($name); $class = $environment->getTemplateClass($name);
$expected = $hash . '_inline-template' . '_' . hash('sha256', $class); $expected = $prefix . '_inline-template' . '_' . hash('sha256', $class);
$this->assertEqual($expected, $cache->generateKey($name, $class)); $this->assertEqual($expected, $cache->generateKey($name, $class));
} }

View File

@ -7,6 +7,7 @@
namespace Drupal\Tests\Component\DependencyInjection; namespace Drupal\Tests\Component\DependencyInjection;
use Drupal\Component\Utility\Crypt;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Prophecy\Argument; use Prophecy\Argument;
@ -1000,7 +1001,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase {
*/ */
protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) {
if (!$id) { if (!$id) {
$hash = sha1(serialize($service_definition)); $hash = Crypt::hashBase64(serialize($service_definition));
$id = 'private__' . $hash; $id = 'private__' . $hash;
} }
return (object) array( return (object) array(

View File

@ -7,6 +7,7 @@
namespace Drupal\Tests\Component\DependencyInjection\Dumper { namespace Drupal\Tests\Component\DependencyInjection\Dumper {
use Drupal\Component\Utility\Crypt;
use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Parameter;
@ -625,7 +626,7 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
*/ */
protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) {
if (!$id) { if (!$id) {
$hash = sha1(serialize($service_definition)); $hash = Crypt::hashBase64(serialize($service_definition));
$id = 'private__' . $hash; $id = 'private__' . $hash;
} }
return (object) array( return (object) array(

View File

@ -2,6 +2,7 @@
namespace Drupal\Tests\Core\Access; namespace Drupal\Tests\Core\Access;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
use Drupal\Core\Access\RouteProcessorCsrf; use Drupal\Core\Access\RouteProcessorCsrf;
@ -68,7 +69,7 @@ class RouteProcessorCsrfTest extends UnitTestCase {
// Bubbleable metadata of routes with a _csrf_token route requirement is a // Bubbleable metadata of routes with a _csrf_token route requirement is a
// placeholder. // placeholder.
$path = 'test-path'; $path = 'test-path';
$placeholder = hash('sha1', $path); $placeholder = Crypt::hashBase64($path);
$placeholder_render_array = [ $placeholder_render_array = [
'#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]], '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
]; ];
@ -88,7 +89,7 @@ class RouteProcessorCsrfTest extends UnitTestCase {
// Bubbleable metadata of routes with a _csrf_token route requirement is a // Bubbleable metadata of routes with a _csrf_token route requirement is a
// placeholder. // placeholder.
$path = 'test-path/100'; $path = 'test-path/100';
$placeholder = hash('sha1', $path); $placeholder = Crypt::hashBase64($path);
$placeholder_render_array = [ $placeholder_render_array = [
'#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]], '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
]; ];
@ -107,7 +108,7 @@ class RouteProcessorCsrfTest extends UnitTestCase {
// Bubbleable metadata of routes with a _csrf_token route requirement is a // Bubbleable metadata of routes with a _csrf_token route requirement is a
// placeholder. // placeholder.
$path = '100/test-path/test'; $path = '100/test-path/test';
$placeholder = hash('sha1', $path); $placeholder = Crypt::hashBase64($path);
$placeholder_render_array = [ $placeholder_render_array = [
'#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]], '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
]; ];

View File

@ -7,6 +7,7 @@
namespace Drupal\Tests\Core\Render; namespace Drupal\Tests\Core\Render;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\Render\Markup; use Drupal\Core\Render\Markup;
@ -71,7 +72,7 @@ class RendererPlaceholdersTest extends RendererTestBase {
if (is_array($cache_keys)) { if (is_array($cache_keys)) {
$token_render_array['#cache']['keys'] = $cache_keys; $token_render_array['#cache']['keys'] = $cache_keys;
} }
$token = hash('crc32b', serialize($token_render_array)); $token = Crypt::hashBase64(serialize($token_render_array));
// \Drupal\Core\Render\Markup::create() is necessary as the render // \Drupal\Core\Render\Markup::create() is necessary as the render
// system would mangle this markup. As this is exactly what happens at // system would mangle this markup. As this is exactly what happens at
// runtime this is a valid use-case. // runtime this is a valid use-case.
@ -618,7 +619,7 @@ class RendererPlaceholdersTest extends RendererTestBase {
$this->setUpRequest('GET'); $this->setUpRequest('GET');
$token = hash('crc32b', serialize($expected_placeholder_render_array)); $token = Crypt::hashBase64(serialize($expected_placeholder_render_array));
$placeholder_callback = $expected_placeholder_render_array['#lazy_builder'][0]; $placeholder_callback = $expected_placeholder_render_array['#lazy_builder'][0];
$expected_placeholder_markup = '<drupal-render-placeholder callback="' . $placeholder_callback . '" arguments="0=' . $args[0] . '" token="' . $token . '"></drupal-render-placeholder>'; $expected_placeholder_markup = '<drupal-render-placeholder callback="' . $placeholder_callback . '" arguments="0=' . $args[0] . '" token="' . $token . '"></drupal-render-placeholder>';
$this->assertSame($expected_placeholder_markup, Html::normalize($expected_placeholder_markup), 'Placeholder unaltered by Html::normalize() which is used by FilterHtmlCorrector.'); $this->assertSame($expected_placeholder_markup, Html::normalize($expected_placeholder_markup), 'Placeholder unaltered by Html::normalize() which is used by FilterHtmlCorrector.');