Update to Drupal 8.0.0-rc3. For more information, see https://www.drupal.org/node/2608078
This commit is contained in:
parent
6419a031d7
commit
4afb23bbd3
762 changed files with 20080 additions and 6368 deletions
|
@ -90,7 +90,7 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetGet().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet($name) {
|
||||
if (isset($this->storage[$name])) {
|
||||
|
@ -99,7 +99,7 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetSet().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($name, $value) {
|
||||
$this->storage[$name] = $this->createAttributeValue($name, $value);
|
||||
|
@ -151,14 +151,14 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetUnset().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset($name) {
|
||||
unset($this->storage[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetExists().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists($name) {
|
||||
return isset($this->storage[$name]);
|
||||
|
@ -324,7 +324,7 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements IteratorAggregate::getIterator().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new \ArrayIterator($this->storage);
|
||||
|
|
|
@ -38,14 +38,14 @@ class AttributeArray extends AttributeValueBase implements \ArrayAccess, \Iterat
|
|||
const RENDER_EMPTY_ATTRIBUTE = FALSE;
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetGet().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet($offset) {
|
||||
return $this->value[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetSet().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($offset, $value) {
|
||||
if (isset($offset)) {
|
||||
|
@ -57,14 +57,14 @@ class AttributeArray extends AttributeValueBase implements \ArrayAccess, \Iterat
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetUnset().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset($offset) {
|
||||
unset($this->value[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ArrayAccess::offsetExists().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists($offset) {
|
||||
return isset($this->value[$offset]);
|
||||
|
@ -80,7 +80,7 @@ class AttributeArray extends AttributeValueBase implements \ArrayAccess, \Iterat
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements IteratorAggregate::getIterator().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new \ArrayIterator($this->value);
|
||||
|
|
|
@ -32,7 +32,7 @@ use Drupal\Component\Utility\Html;
|
|||
class AttributeBoolean extends AttributeValueBase {
|
||||
|
||||
/**
|
||||
* Overrides AttributeValueBase::render().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render() {
|
||||
return $this->__toString();
|
||||
|
|
|
@ -38,6 +38,8 @@ class ThemeRegistryLoader extends \Twig_Loader_Filesystem {
|
|||
*
|
||||
* @param string $name
|
||||
* The name of the template to load.
|
||||
* @param bool $throw
|
||||
* Whether to throw an exception when an error occurs.
|
||||
*
|
||||
* @return string
|
||||
* The path to the template.
|
||||
|
@ -45,7 +47,7 @@ class ThemeRegistryLoader extends \Twig_Loader_Filesystem {
|
|||
* @throws \Twig_Error_Loader
|
||||
* Thrown if a template matching $name cannot be found.
|
||||
*/
|
||||
protected function findTemplate($name) {
|
||||
protected function findTemplate($name, $throw = TRUE) {
|
||||
// Allow for loading based on the Drupal theme registry.
|
||||
$hook = str_replace('.html.twig', '', strtr($name, '-', '_'));
|
||||
$theme_registry = $this->themeRegistry->getRuntime();
|
||||
|
@ -63,7 +65,9 @@ class ThemeRegistryLoader extends \Twig_Loader_Filesystem {
|
|||
}
|
||||
}
|
||||
|
||||
throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
|
||||
if ($throw) {
|
||||
throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,6 +58,10 @@ class TwigEnvironment extends \Twig_Environment {
|
|||
// Ensure autoescaping is always on.
|
||||
$options['autoescape'] = 'html';
|
||||
|
||||
$policy = new TwigSandboxPolicy();
|
||||
$sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
|
||||
$this->addExtension($sandbox);
|
||||
|
||||
if ($options['cache'] === TRUE) {
|
||||
$options['cache'] = new TwigPhpStorageCache($cache, $twig_extension_hash);
|
||||
}
|
||||
|
|
|
@ -534,7 +534,7 @@ class TwigExtension extends \Twig_Extension {
|
|||
*
|
||||
* @param \Twig_Environment $env
|
||||
* A Twig_Environment instance.
|
||||
* @param mixed[]|\Traversable $value
|
||||
* @param mixed[]|\Traversable|NULL $value
|
||||
* The pieces to join.
|
||||
* @param string $glue
|
||||
* The delimiter with which to join the string. Defaults to an empty string.
|
||||
|
@ -545,10 +545,14 @@ class TwigExtension extends \Twig_Extension {
|
|||
* The strings joined together.
|
||||
*/
|
||||
public function safeJoin(\Twig_Environment $env, $value, $glue = '') {
|
||||
if ($value instanceof \Traversable) {
|
||||
$value = iterator_to_array($value, false);
|
||||
}
|
||||
|
||||
return implode($glue, array_map(function($item) use ($env) {
|
||||
// If $item is not marked safe then it will be escaped.
|
||||
return $this->escapeFilter($env, $item, 'html', NULL, TRUE);
|
||||
}, $value));
|
||||
}, (array) $value));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class TwigNodeTrans extends \Twig_Node {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(\Twig_NodeInterface $body, \Twig_NodeInterface $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
|
||||
public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
|
||||
parent::__construct(array(
|
||||
'count' => $count,
|
||||
'body' => $body,
|
||||
|
@ -88,7 +88,7 @@ class TwigNodeTrans extends \Twig_Node {
|
|||
/**
|
||||
* Extracts the text and tokens for the "trans" tag.
|
||||
*
|
||||
* @param \Twig_NodeInterface $body
|
||||
* @param \Twig_Node $body
|
||||
* The node to compile.
|
||||
*
|
||||
* @return array
|
||||
|
@ -98,7 +98,7 @@ class TwigNodeTrans extends \Twig_Node {
|
|||
* - array $tokens
|
||||
* The extracted tokens as new \Twig_Node_Expression_Name instances.
|
||||
*/
|
||||
protected function compileString(\Twig_NodeInterface $body) {
|
||||
protected function compileString(\Twig_Node $body) {
|
||||
if ($body instanceof \Twig_Node_Expression_Name || $body instanceof \Twig_Node_Expression_Constant || $body instanceof \Twig_Node_Expression_TempName) {
|
||||
return array($body, array());
|
||||
}
|
||||
|
|
|
@ -16,19 +16,19 @@ namespace Drupal\Core\Template;
|
|||
*
|
||||
* @see twig_render
|
||||
*/
|
||||
class TwigNodeVisitor implements \Twig_NodeVisitorInterface {
|
||||
class TwigNodeVisitor extends \Twig_BaseNodeVisitor {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
|
||||
protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
|
||||
protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) {
|
||||
// We use this to inject a call to render_var -> TwigExtension->renderVar()
|
||||
// before anything is printed.
|
||||
if ($node instanceof \Twig_Node_Print) {
|
||||
|
|
104
core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
Normal file
104
core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Template\TwigSandboxPolicy.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Template;
|
||||
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
||||
/**
|
||||
* Default sandbox policy for Twig templates.
|
||||
*
|
||||
* Twig's sandbox extension is usually used to evaluate untrusted code by
|
||||
* limiting access to potentially unsafe properties or methods. Since we do not
|
||||
* use ViewModels when passing objects to Twig templates, we limit what those
|
||||
* objects can do by whitelisting certain classes, method names, and method
|
||||
* names with an allowed prefix. All object properties may be accessed.
|
||||
*/
|
||||
class TwigSandboxPolicy implements \Twig_Sandbox_SecurityPolicyInterface {
|
||||
|
||||
/**
|
||||
* An array of whitelisted methods in the form of methodName => TRUE.
|
||||
*/
|
||||
protected $whitelisted_methods = NULL;
|
||||
|
||||
/**
|
||||
* An array of whitelisted method prefixes -- any method starting with one of
|
||||
* these prefixes will be allowed.
|
||||
*/
|
||||
protected $whitelisted_prefixes = NULL;
|
||||
|
||||
/**
|
||||
* An array of class names for which any method calls are allowed.
|
||||
*/
|
||||
protected $whitelisted_classes = NULL;
|
||||
|
||||
/**
|
||||
* Constructs a new TwigSandboxPolicy object.
|
||||
*/
|
||||
public function __construct() {
|
||||
// Allow settings.php to override our default whitelisted classes, methods,
|
||||
// and prefixes.
|
||||
$whitelisted_classes = Settings::get('twig_sandbox_whitelisted_classes', [
|
||||
// Allow any operations on the Attribute object as it is intended to be
|
||||
// changed from a Twig template, for example calling addClass().
|
||||
'Drupal\Core\Template\Attribute',
|
||||
]);
|
||||
// Flip the arrays so we can check using isset().
|
||||
$this->whitelisted_classes = array_flip($whitelisted_classes);
|
||||
|
||||
$whitelisted_methods = Settings::get('twig_sandbox_whitelisted_methods', [
|
||||
// Only allow idempotent methods.
|
||||
'id',
|
||||
'label',
|
||||
'bundle',
|
||||
'get',
|
||||
'__toString',
|
||||
]);
|
||||
$this->whitelisted_methods = array_flip($whitelisted_methods);
|
||||
|
||||
$this->whitelisted_prefixes = Settings::get('twig_sandbox_whitelisted_prefixes', [
|
||||
'get',
|
||||
'has',
|
||||
'is',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkSecurity($tags, $filters, $functions) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkPropertyAllowed($obj, $property) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkMethodAllowed($obj, $method) {
|
||||
if (isset($this->whitelisted_classes[get_class($obj)])) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Return quickly for an exact match of the method name.
|
||||
if (isset($this->whitelisted_methods[$method])) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// If the method name starts with a whitelisted prefix, allow it.
|
||||
// Note: strpos() is between 3x and 7x faster than preg_match in this case.
|
||||
foreach ($this->whitelisted_prefixes as $prefix) {
|
||||
if (strpos($method, $prefix) === 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
|
||||
}
|
||||
|
||||
}
|
|
@ -82,14 +82,14 @@ class TwigTransTokenParser extends \Twig_TokenParser {
|
|||
/**
|
||||
* Ensure that any nodes that are parsed are only of allowed types.
|
||||
*
|
||||
* @param \Twig_NodeInterface $body
|
||||
* @param \Twig_Node $body
|
||||
* The expression to check.
|
||||
* @param integer $lineno
|
||||
* The source line.
|
||||
*
|
||||
* @throws \Twig_Error_Syntax
|
||||
*/
|
||||
protected function checkTransString(\Twig_NodeInterface $body, $lineno) {
|
||||
protected function checkTransString(\Twig_Node $body, $lineno) {
|
||||
foreach ($body as $node) {
|
||||
if (
|
||||
$node instanceof \Twig_Node_Text
|
||||
|
|
Reference in a new issue