diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php
index 9225712..08faaf7 100644
--- a/core/lib/Drupal/Core/Template/TwigEnvironment.php
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -58,6 +58,10 @@ public function __construct($root, \Twig_LoaderInterface $loader = NULL, $option
// Ensure autoescaping is always on.
$options['autoescape'] = TRUE;
+ $policy = new TwigSandboxPolicy();
+ $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
+ $this->addExtension($sandbox);
+
$this->loader = $loader;
parent::__construct($this->loader, $options);
}
diff --git a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
new file mode 100644
index 0000000..3ca65f2
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
@@ -0,0 +1,59 @@
+
-
{{ title_prefix }}
{% if not page %}
diff --git a/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
new file mode 100644
index 0000000..46ed159
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
@@ -0,0 +1,89 @@
+addExtension($sandbox);
+
+ $entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+
+ $caught = FALSE;
+ try {
+ $twig->render('{{ entity.delete }}', ['entity' => $entity]);
+ } catch (\Twig_Sandbox_SecurityError $e) {
+ $caught = TRUE;
+ }
+ $this->assertTrue($caught, '\Twig_sandbox_security exception was thrown when entity was tried to be removed.');
+
+ $caught = FALSE;
+ try {
+ $twig->render('{{ entity.save }}', ['entity' => $entity]);
+ } catch (\Twig_Sandbox_SecurityError $e) {
+ $caught = TRUE;
+ }
+ $this->assertTrue($caught, '\Twig_sandbox_security exception was thrown when entity was tried to be saved.');
+
+ $caught = FALSE;
+ try {
+ $twig->render('{{ entity.create }}', ['entity' => $entity]);
+ } catch (\Twig_Sandbox_SecurityError $e) {
+ $caught = TRUE;
+ }
+ $this->assertTrue($caught, '\Twig_sandbox_security exception was thrown when new entity was tried to be created.');
+ }
+
+ public function testEntitySafeMethods() {
+ $loader = new \Twig_Loader_String();
+ $twig = new \Twig_Environment($loader);
+ $policy = new TwigSandboxPolicy();
+ $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
+ $twig->addExtension($sandbox);
+
+ $entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+ $entity->expects($this->atLeastOnce())
+ ->method('hasLinkTemplate')
+ ->with('test')
+ ->willReturn(TRUE);
+ $result = $twig->render('{{ entity.hasLinkTemplate("test") }}', ['entity' => $entity]);
+ $this->assertTrue((bool)$result, 'Sandbox policy allows has* functions to be called.');
+
+ $entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+ $entity->expects($this->atLeastOnce())
+ ->method('isNew')
+ ->willReturn(TRUE);
+ $result = $twig->render('{{ entity.isNew }}', ['entity' => $entity]);
+ $this->assertTrue((bool)$result, 'Sandbox policy allows is* functions to be called.');
+
+ $entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+ $entity->expects($this->atLeastOnce())
+ ->method('getEntityType')
+ ->willReturn('test');
+ $result = $twig->render('{{ entity.getEntityType }}', ['entity' => $entity]);
+ $this->assertEquals($result, 'test', 'Sandbox policy allows get* functions to be called.');
+ }
+
+}
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index 25144bf..1d1afd3 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -4,12 +4,10 @@
* Bartik's theme implementation to display a node.
*
* Available variables:
- * - node: Full node entity.
- * - id: The node ID.
- * - bundle: The type of the node, for example, "page" or "article".
- * - authorid: The user ID of the node author.
- * - createdtime: Time the node was published formatted in Unix timestamp.
- * - changedtime: Time the node was changed formatted in Unix timestamp.
+ * - node: The node entity with limited access to object properties and methods.
+ Only "getter" methods (method names starting with "get", "has", or "is")
+ and a few common attributes such as "id" and "label" are available. Calling
+ other methods (such as node.delete) will result in an exception.
* - label: The title of the node.
* - content: All node items. Use {{ content }} to print them all,
* or print a subset such as {{ content.field_example }}. Use
@@ -64,7 +62,7 @@
{%
set classes = [
'node',
- 'node--type-' ~ node.bundle|clean_class,
+ 'node--type-' ~ node.getType()|clean_class,
node.isPromoted() ? 'node--promoted',
node.isSticky() ? 'node--sticky',
not node.isPublished() ? 'node--unpublished',
diff --git a/core/themes/classy/templates/content/node.html.twig b/core/themes/classy/templates/content/node.html.twig
index 5d746a6..cbc1899 100644
--- a/core/themes/classy/templates/content/node.html.twig
+++ b/core/themes/classy/templates/content/node.html.twig
@@ -4,12 +4,10 @@
* Theme override to display a node.
*
* Available variables:
- * - node: Full node entity.
- * - id: The node ID.
- * - bundle: The type of the node, for example, "page" or "article".
- * - authorid: The user ID of the node author.
- * - createdtime: Time the node was published formatted in Unix timestamp.
- * - changedtime: Time the node was changed formatted in Unix timestamp.
+ * - node: The node entity with limited access to object properties and methods.
+ Only "getter" methods (method names starting with "get", "has", or "is")
+ and a few common attributes such as "id" and "label" are available. Calling
+ other methods (such as node.delete) will result in an exception.
* - label: The title of the node.
* - content: All node items. Use {{ content }} to print them all,
* or print a subset such as {{ content.field_example }}. Use
@@ -68,7 +66,7 @@
{%
set classes = [
'node',
- 'node--type-' ~ node.bundle|clean_class,
+ 'node--type-' ~ node.getType()|clean_class,
node.isPromoted() ? 'node--promoted',
node.isSticky() ? 'node--sticky',
not node.isPublished() ? 'node--unpublished',
diff --git a/core/themes/classy/templates/content/taxonomy-term.html.twig b/core/themes/classy/templates/content/taxonomy-term.html.twig
index 7e0446e..4284950 100644
--- a/core/themes/classy/templates/content/taxonomy-term.html.twig
+++ b/core/themes/classy/templates/content/taxonomy-term.html.twig
@@ -26,7 +26,7 @@
{%
set classes = [
'taxonomy-term',
- 'vocabulary-' ~ term.bundle|clean_class,
+ 'vocabulary-' ~ term.getType()|clean_class,
]
%}