Commit 72b0180f authored by catch's avatar catch
Browse files

Issue #2454649 by Aki Tendo, dawehner: Cache Optimization and hardening --...

Issue #2454649 by Aki Tendo, dawehner: Cache Optimization and hardening -- [PP-1] Use assert() instead of exceptions in Cache::merge(Tags|Contexts)
parent 8d196a79
......@@ -166,7 +166,7 @@ protected function prepareItem($cache, $allow_invalid) {
* {@inheritdoc}
*/
public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
Cache::validateTags($tags);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache tags must be strings.');
$tags = array_unique($tags);
$cache = new \stdClass();
$cache->cid = $cid;
......
......@@ -34,7 +34,7 @@ class Cache {
*/
public static function mergeContexts(array $a = [], array $b = []) {
$cache_contexts = array_unique(array_merge($a, $b));
\Drupal::service('cache_contexts_manager')->validateTokens($cache_contexts);
assert('\Drupal::service(\'cache_contexts_manager\')->assertValidTokens($cache_contexts)');
sort($cache_contexts);
return $cache_contexts;
}
......@@ -59,8 +59,9 @@ public static function mergeContexts(array $a = [], array $b = []) {
* The merged array of cache tags.
*/
public static function mergeTags(array $a = [], array $b = []) {
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($a) && \Drupal\Component\Assertion\Inspector::assertAllStrings($b)', 'Cache tags must be valid strings');
$cache_tags = array_unique(array_merge($a, $b));
static::validateTags($cache_tags);
sort($cache_tags);
return $cache_tags;
}
......@@ -99,6 +100,9 @@ public static function mergeMaxAges($a = Cache::PERMANENT, $b = Cache::PERMANENT
* @param string[] $tags
* An array of cache tags.
*
* @deprecated
* Use assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)');
*
* @throws \LogicException
*/
public static function validateTags(array $tags) {
......
......@@ -115,7 +115,7 @@ abstract class CacheCollector implements CacheCollectorInterface, DestructableIn
* (optional) The tags to specify for the cache item.
*/
public function __construct($cid, CacheBackendInterface $cache, LockBackendInterface $lock, array $tags = array()) {
Cache::validateTags($tags);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache tags must be strings.');
$this->cid = $cid;
$this->cache = $cache;
$this->tags = $tags;
......
......@@ -27,8 +27,7 @@ class CacheTagsInvalidator implements CacheTagsInvalidatorInterface {
* {@inheritdoc}
*/
public function invalidateTags(array $tags) {
// Validate the tags.
Cache::validateTags($tags);
assert('Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache tags must be strings.');
// Notify all added cache tags invalidators.
foreach ($this->invalidators as $invalidator) {
......
......@@ -103,11 +103,9 @@ public function getLabels($include_calculated_cache_contexts = FALSE) {
* The ContextCacheKeys object containing the converted cache keys and
* cacheability metadata.
*
* @throws \LogicException
* Thrown if any of the context tokens or parameters are not valid.
*/
public function convertTokensToKeys(array $context_tokens) {
$this->validateTokens($context_tokens);
assert('$this->assertValidTokens($context_tokens)');
$cacheable_metadata = new CacheableMetadata();
$optimized_tokens = $this->optimizeTokens($context_tokens);
// Iterate over cache contexts that have been optimized away and get their
......@@ -299,4 +297,33 @@ public function validateTokens(array $context_tokens = []) {
}
}
/**
* Asserts the context tokens are valid
*
* Similar to ::validateTokens, this method returns boolean TRUE when the
* context tokens are valid, and FALSE when they are not instead of returning
* NULL when they are valid and throwing a \LogicException when they are not.
* This function should be used with the assert() statement.
*
* @param mixed $context_tokens
* Variable to be examined - should be array of context_tokens.
*
* @return bool
* TRUE if context_tokens is an array of valid tokens.
*/
public function assertValidTokens($context_tokens) {
if (!is_array($context_tokens)) {
return FALSE;
}
try {
$this->validateTokens($context_tokens);
}
catch (\LogicException $e) {
return FALSE;
}
return TRUE;
}
}
......@@ -199,7 +199,7 @@ protected function doSetMultiple(array $items) {
'tags' => array(),
);
Cache::validateTags($item['tags']);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($item[\'tags\'])', 'Cache Tags must be strings.');
$item['tags'] = array_unique($item['tags']);
// Sort the cache tags so that they are stored consistently in the DB.
sort($item['tags']);
......
......@@ -107,7 +107,7 @@ protected function prepareItem($cache, $allow_invalid) {
* Implements Drupal\Core\Cache\CacheBackendInterface::set().
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
Cache::validateTags($tags);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache Tags must be strings.');
$tags = array_unique($tags);
// Sort the cache tags so that they are stored consistently in the database.
sort($tags);
......
......@@ -148,7 +148,7 @@ protected function prepareItem($cache, $allow_invalid) {
* {@inheritdoc}
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
Cache::validateTags($tags);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache Tags must be strings.');
$item = (object) array(
'cid' => $cid,
'data' => $data,
......
......@@ -154,7 +154,7 @@ public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInte
* definitions should be cleared along with other, related cache entries.
*/
public function setCacheBackend(CacheBackendInterface $cache_backend, $cache_key, array $cache_tags = array()) {
Cache::validateTags($cache_tags);
assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($cache_tags)', 'Cache Tags must be strings.');
$this->cacheBackend = $cache_backend;
$this->cacheKey = $cache_key;
$this->cacheTags = $cache_tags;
......
......@@ -57,9 +57,8 @@ public function setUpDisplayVariant($configuration = array(), $definition = arra
->getMock();
$container->set('cache_contexts_manager', $cache_context_manager);
$cache_context_manager->expects($this->any())
->method('validateTokens')
->with([])
->willReturn([]);
->method('assertValidTokens')
->willReturn(TRUE);
\Drupal::setContainer($container);
$this->blockRepository = $this->getMock('Drupal\block\BlockRepositoryInterface');
......
......@@ -40,6 +40,7 @@ protected function setUp() {
$this->cacheContextsManager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$this->cacheContextsManager->method('assertValidTokens')->willReturn(TRUE);
$container = new ContainerBuilder();
$container->set('cache_contexts_manager', $this->cacheContextsManager);
......
......@@ -27,8 +27,7 @@ public function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->expects($this->any())
->method('validate_tokens');
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
......@@ -28,8 +28,7 @@ public function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->expects($this->any())
->method('validate_tokens');
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
......@@ -27,8 +27,7 @@ public function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->expects($this->any())
->method('validate_tokens');
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
......@@ -60,6 +60,7 @@ protected function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new ContainerBuilder();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
......@@ -34,7 +34,9 @@ class EditEntityFieldAccessCheckTest extends UnitTestCase {
protected function setUp() {
$this->editAccessCheck = new EditEntityFieldAccessCheck();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
$cache_contexts_manager->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
......@@ -969,6 +969,10 @@ public function run(array $methods = array()) {
$this->httpAuthCredentials = $username . ':' . $password;
}
// Force assertion failures to be thrown as AssertionError for PHP 5 & 7
// compatibility.
\Drupal\Component\Assertion\Handle::register();
set_error_handler(array($this, 'errorHandler'));
// Iterate through all the methods in this class, unless a specific list of
// methods to run was passed.
......
......@@ -218,13 +218,13 @@ public function testSetGet() {
$this->assertEqual('value', $backend->get('TEST8')->data);
$this->assertFalse($backend->get('test8'));
// Calling ::set() with invalid cache tags.
// Calling ::set() with invalid cache tags. This should fail an assertion.
try {
$backend->set('exception_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
$this->fail('::set() was called with invalid cache tags, no exception was thrown.');
$backend->set('assertion_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
$this->fail('::set() was called with invalid cache tags, runtime assertion did not fail.');
}
catch (\LogicException $e) {
$this->pass('::set() was called with invalid cache tags, an exception was thrown.');
catch (\AssertionError $e) {
$this->pass('::set() was called with invalid cache tags, runtime assertion failed.');
}
}
......@@ -412,7 +412,8 @@ public function testSetMultiple() {
$this->assertEqual($cached['cid_5']->data, $items['cid_5']['data'], 'New cache item set correctly.');
// Calling ::setMultiple() with invalid cache tags.
// Calling ::setMultiple() with invalid cache tags. This should fail an
// assertion.
try {
$items = [
'exception_test_1' => array('data' => 1, 'tags' => []),
......@@ -420,10 +421,10 @@ public function testSetMultiple() {
'exception_test_3' => array('data' => 3, 'tags' => ['node' => [3, 5, 7]]),
];
$backend->setMultiple($items);
$this->fail('::setMultiple() was called with invalid cache tags, no exception was thrown.');
$this->fail('::setMultiple() was called with invalid cache tags, runtime assertion did not fail.');
}
catch (\LogicException $e) {
$this->pass('::setMultiple() was called with invalid cache tags, an exception was thrown.');
catch (\AssertionError $e) {
$this->pass('::setMultiple() was called with invalid cache tags, runtime assertion failed.');
}
}
......
......@@ -124,6 +124,7 @@ protected function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$cache_contexts_manager->expects($this->any())
->method('validate_tokens');
$container = new Container();
......
......@@ -47,6 +47,7 @@ protected function setUp() {
$cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
$container = new ContainerBuilder();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment