Update to Drupal 8.0.0-rc3. For more information, see https://www.drupal.org/node/2608078

This commit is contained in:
Pantheon Automation 2015-11-04 11:11:27 -08:00 committed by Greg Anderson
parent 6419a031d7
commit 4afb23bbd3
762 changed files with 20080 additions and 6368 deletions

View file

@ -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);

View file

@ -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);

View file

@ -32,7 +32,7 @@ use Drupal\Component\Utility\Html;
class AttributeBoolean extends AttributeValueBase {
/**
* Overrides AttributeValueBase::render().
* {@inheritdoc}
*/
public function render() {
return $this->__toString();

View file

@ -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));
}
}
}

View file

@ -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);
}

View file

@ -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));
}
}

View file

@ -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());
}

View file

@ -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) {

View 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)));
}
}

View file

@ -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