Issue #2571817 by Cottser, hussainweb: Remove race condition handling in TwigEnvironment::loadTemplate(), it's fixed upstream now

8.0.x
Alex Pott 2015-09-25 17:27:48 +02:00
parent bfcba53277
commit dc95ff1c81
15 changed files with 72 additions and 120 deletions

View File

@ -17,7 +17,7 @@
"symfony/validator": "2.7.*", "symfony/validator": "2.7.*",
"symfony/process": "2.7.*", "symfony/process": "2.7.*",
"symfony/yaml": "2.7.*", "symfony/yaml": "2.7.*",
"twig/twig": "~1.22", "twig/twig": "^1.22.2",
"doctrine/common": "2.5.*", "doctrine/common": "2.5.*",
"doctrine/annotations": "1.2.*", "doctrine/annotations": "1.2.*",
"guzzlehttp/guzzle": "~6.1", "guzzlehttp/guzzle": "~6.1",

15
core/composer.lock generated
View File

@ -4,8 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "e917b58b5b2a847270d4bd49b0bcb22e", "hash": "e6a3c80757f0e2a34ecc1cb9332cdab1",
"content-hash": "bbb9004b899df99873971591682b1e42",
"packages": [ "packages": [
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
@ -1779,16 +1778,16 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v1.22.1", "version": "v1.22.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "b7fc2469fa009897871fb95b68237286fc54a5ad" "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/b7fc2469fa009897871fb95b68237286fc54a5ad", "url": "https://api.github.com/repos/twigphp/Twig/zipball/79249fc8c9ff62e41e217e0c630e2e00bcadda6a",
"reference": "b7fc2469fa009897871fb95b68237286fc54a5ad", "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1836,7 +1835,7 @@
"keywords": [ "keywords": [
"templating" "templating"
], ],
"time": "2015-09-15 06:50:16" "time": "2015-09-22 13:59:32"
}, },
{ {
"name": "zendframework/zend-diactoros", "name": "zendframework/zend-diactoros",
@ -2169,7 +2168,7 @@
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/7e9a7319cc0e8cf9d4d4c9e06e2020d3a31bd792", "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/c8e254f127d6f2242b994afd4339fb62d471df3f",
"reference": "cc5ce119b5a8e06662f634b35967aff0b0c7dfdd", "reference": "cc5ce119b5a8e06662f634b35967aff0b0c7dfdd",
"shasum": "" "shasum": ""
}, },

View File

@ -67,56 +67,6 @@ class TwigEnvironment extends \Twig_Environment {
parent::__construct($this->loader, $options); parent::__construct($this->loader, $options);
} }
/**
* Implements Twig_Environment::loadTemplate().
*
* We need to overwrite this function to integrate with drupal_php_storage().
*
* This is a straight copy from loadTemplate() changed to use
* drupal_php_storage().
*
* @param string $name
* The template name or the string which should be rendered as template.
* @param int $index
* The index if it is an embedded template.
*
* @return \Twig_TemplateInterface
* A template instance representing the given template name.
*
* @throws \Twig_Error_Loader
* When the template cannot be found.
* @throws \Twig_Error_Syntax
* When an error occurred during compilation.
*/
public function loadTemplate($name, $index = NULL) {
$cls = $this->getTemplateClass($name, $index);
if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls];
}
if (!class_exists($cls, FALSE)) {
$key = $this->cache->generateKey($name, $cls);
if (!$this->cache->has($key) || ($this->isAutoReload() && !$this->isTemplateFresh($name, $this->cache->getTimestamp($key)))) {
$this->cache->write($key, $this->compileSource($this->getLoader()->getSource($name), $name));
}
$this->cache->load($key);
if (!class_exists($cls, FALSE)) {
$compiled_source = $this->compileSource($this->loader->getSource($name), $name);
eval('?' . '>' . $compiled_source);
}
}
if (!$this->runtimeInitialized) {
$this->initRuntime();
}
return $this->loadedTemplates[$cls] = new $cls($this);
}
/** /**
* Gets the template class associated with the given string. * Gets the template class associated with the given string.
* *

View File

@ -78,13 +78,6 @@ class TwigPhpStorageCache implements \Twig_CacheInterface {
return $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $hash; return $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $hash;
} }
/**
* {@inheritdoc}
*/
public function has($key) {
return $this->storage()->exists($key);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -592,7 +592,7 @@
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/7e9a7319cc0e8cf9d4d4c9e06e2020d3a31bd792", "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/c8e254f127d6f2242b994afd4339fb62d471df3f",
"reference": "cc5ce119b5a8e06662f634b35967aff0b0c7dfdd", "reference": "cc5ce119b5a8e06662f634b35967aff0b0c7dfdd",
"shasum": "" "shasum": ""
}, },
@ -3418,17 +3418,17 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v1.22.1", "version": "v1.22.2",
"version_normalized": "1.22.1.0", "version_normalized": "1.22.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "b7fc2469fa009897871fb95b68237286fc54a5ad" "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/b7fc2469fa009897871fb95b68237286fc54a5ad", "url": "https://api.github.com/repos/twigphp/Twig/zipball/79249fc8c9ff62e41e217e0c630e2e00bcadda6a",
"reference": "b7fc2469fa009897871fb95b68237286fc54a5ad", "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3438,7 +3438,7 @@
"symfony/debug": "~2.7", "symfony/debug": "~2.7",
"symfony/phpunit-bridge": "~2.7" "symfony/phpunit-bridge": "~2.7"
}, },
"time": "2015-09-15 06:50:16", "time": "2015-09-22 13:59:32",
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View File

@ -1,3 +1,7 @@
* 1.22.2 (2015-09-22)
* fixed a race condition in template loading
* 1.22.1 (2015-09-15) * 1.22.1 (2015-09-15)
* fixed regression in template_from_string * fixed regression in template_from_string

View File

@ -15,7 +15,7 @@
#ifndef PHP_TWIG_H #ifndef PHP_TWIG_H
#define PHP_TWIG_H #define PHP_TWIG_H
#define PHP_TWIG_VERSION "1.22.1" #define PHP_TWIG_VERSION "1.22.2"
#include "php.h" #include "php.h"

View File

@ -19,7 +19,7 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
const FORCE_BYTECODE_INVALIDATION = 1; const FORCE_BYTECODE_INVALIDATION = 1;
private $directory; private $directory;
private $invalidateBytecode; private $options;
/** /**
* @param $directory string The root cache directory * @param $directory string The root cache directory
@ -41,20 +41,12 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
return $this->directory.'/'.$hash[0].'/'.$hash[1].'/'.$hash.'.php'; return $this->directory.'/'.$hash[0].'/'.$hash[1].'/'.$hash.'.php';
} }
/**
* {@inheritdoc}
*/
public function has($key)
{
return is_file($key);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function load($key) public function load($key)
{ {
require_once $key; @include_once $key;
} }
/** /**
@ -64,11 +56,8 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
{ {
$dir = dirname($key); $dir = dirname($key);
if (!is_dir($dir)) { if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true)) { if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
clearstatcache(false, $dir); throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
if (!is_dir($dir)) {
throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
}
} }
} elseif (!is_writable($dir)) { } elseif (!is_writable($dir)) {
throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
@ -98,6 +87,6 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
*/ */
public function getTimestamp($key) public function getTimestamp($key)
{ {
return filemtime($key); return (int) @filemtime($key);
} }
} }

View File

@ -24,20 +24,11 @@ class Twig_Cache_Null implements Twig_CacheInterface
return ''; return '';
} }
/**
* {@inheritdoc}
*/
public function has($key)
{
return false;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function write($key, $content) public function write($key, $content)
{ {
eval('?>'.$content);
} }
/** /**
@ -52,7 +43,6 @@ class Twig_Cache_Null implements Twig_CacheInterface
*/ */
public function getTimestamp($key) public function getTimestamp($key)
{ {
// never called as has() always returns false
return 0; return 0;
} }
} }

View File

@ -30,15 +30,6 @@ interface Twig_CacheInterface
*/ */
public function generateKey($name, $className); public function generateKey($name, $className);
/**
* Checks if the cache key exists.
*
* @param string $key The cache key
*
* @return bool true if the cache key exists, false otherwise
*/
public function has($key);
/** /**
* Writes the compiled template to cache. * Writes the compiled template to cache.
* *

View File

@ -16,7 +16,7 @@
*/ */
class Twig_Environment class Twig_Environment
{ {
const VERSION = '1.22.1'; const VERSION = '1.22.2';
protected $charset; protected $charset;
protected $loader; protected $loader;
@ -375,15 +375,20 @@ class Twig_Environment
$key = $this->cache->generateKey($name, $cls); $key = $this->cache->generateKey($name, $cls);
} }
if (!$this->cache->has($key) || ($this->isAutoReload() && !$this->isTemplateFresh($name, $this->cache->getTimestamp($key)))) { if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
if ($this->bcWriteCacheFile) { $this->cache->load($key);
$this->writeCacheFile($key, $this->compileSource($this->getLoader()->getSource($name), $name));
} else {
$this->cache->write($key, $this->compileSource($this->getLoader()->getSource($name), $name));
}
} }
$this->cache->load($key); if (!class_exists($cls, false)) {
$content = $this->compileSource($this->getLoader()->getSource($name), $name);
if ($this->bcWriteCacheFile) {
$this->writeCacheFile($key, $content);
} else {
$this->cache->write($key, $content);
}
eval('?>'.$content);
}
} }
if (!$this->runtimeInitialized) { if (!$this->runtimeInitialized) {

View File

@ -885,6 +885,9 @@ function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = n
// The '_default' filter is used internally to avoid using the ternary operator // The '_default' filter is used internally to avoid using the ternary operator
// which costs a lot for big contexts (before PHP 5.4). So, on average, // which costs a lot for big contexts (before PHP 5.4). So, on average,
// a function call is cheaper. // a function call is cheaper.
/**
* @internal
*/
function _twig_default_filter($value, $default = '') function _twig_default_filter($value, $default = '')
{ {
if (twig_test_empty($value)) { if (twig_test_empty($value)) {
@ -982,7 +985,9 @@ function twig_sort_filter($array)
return $array; return $array;
} }
/* used internally */ /**
* @internal
*/
function twig_in_filter($value, $compare) function twig_in_filter($value, $compare)
{ {
if (is_array($compare)) { if (is_array($compare)) {
@ -1150,7 +1155,9 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
} }
} }
/* used internally */ /**
* @internal
*/
function twig_escape_filter_is_safe(Twig_Node $filterArgs) function twig_escape_filter_is_safe(Twig_Node $filterArgs)
{ {
foreach ($filterArgs as $arg) { foreach ($filterArgs as $arg) {
@ -1396,7 +1403,9 @@ else {
} }
} }
/* used internally */ /**
* @internal
*/
function twig_ensure_traversable($seq) function twig_ensure_traversable($seq)
{ {
if ($seq instanceof Traversable || is_array($seq)) { if ($seq instanceof Traversable || is_array($seq)) {

View File

@ -15,6 +15,8 @@
* This class is used by Twig_Environment as a staging area and must not be used directly. * This class is used by Twig_Environment as a staging area and must not be used directly.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/ */
class Twig_Extension_Staging extends Twig_Extension class Twig_Extension_Staging extends Twig_Extension
{ {

View File

@ -23,6 +23,8 @@
* *
* @deprecated since 1.18.1 (to be removed in 2.0) * @deprecated since 1.18.1 (to be removed in 2.0)
* *
* @internal
*
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface

View File

@ -61,6 +61,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param array $context * @param array $context
* *
* @return Twig_TemplateInterface|false The parent template or false if there is no parent * @return Twig_TemplateInterface|false The parent template or false if there is no parent
*
* @internal
*/ */
public function getParent(array $context) public function getParent(array $context)
{ {
@ -111,6 +113,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param string $name The block name to display from the parent * @param string $name The block name to display from the parent
* @param array $context The context * @param array $context The context
* @param array $blocks The current set of blocks * @param array $blocks The current set of blocks
*
* @internal
*/ */
public function displayParentBlock($name, array $context, array $blocks = array()) public function displayParentBlock($name, array $context, array $blocks = array())
{ {
@ -135,6 +139,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param array $context The context * @param array $context The context
* @param array $blocks The current set of blocks * @param array $blocks The current set of blocks
* @param bool $useBlocks Whether to use the current set of blocks * @param bool $useBlocks Whether to use the current set of blocks
*
* @internal
*/ */
public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true) public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
{ {
@ -191,6 +197,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param array $blocks The current set of blocks * @param array $blocks The current set of blocks
* *
* @return string The rendered block * @return string The rendered block
*
* @internal
*/ */
public function renderParentBlock($name, array $context, array $blocks = array()) public function renderParentBlock($name, array $context, array $blocks = array())
{ {
@ -212,6 +220,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param bool $useBlocks Whether to use the current set of blocks * @param bool $useBlocks Whether to use the current set of blocks
* *
* @return string The rendered block * @return string The rendered block
*
* @internal
*/ */
public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true) public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
{ {
@ -237,6 +247,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @param string $name The block name * @param string $name The block name
* *
* @return bool true if the block exists, false otherwise * @return bool true if the block exists, false otherwise
*
* @internal
*/ */
public function hasBlock($name) public function hasBlock($name)
{ {
@ -252,6 +264,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @return array An array of block names * @return array An array of block names
* *
* @see hasBlock * @see hasBlock
*
* @internal
*/ */
public function getBlockNames() public function getBlockNames()
{ {
@ -298,6 +312,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @return array An array of blocks * @return array An array of blocks
* *
* @see hasBlock * @see hasBlock
*
* @internal
*/ */
public function getBlocks() public function getBlocks()
{ {
@ -407,6 +423,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
* @return mixed The content of the context variable * @return mixed The content of the context variable
* *
* @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
*
* @internal
*/ */
final protected function getContext($context, $item, $ignoreStrictCheck = false) final protected function getContext($context, $item, $ignoreStrictCheck = false)
{ {