diff options
author | Nathaniel Catchpole | 2014-04-21 12:53:23 (GMT) |
---|---|---|
committer | Nathaniel Catchpole | 2014-04-21 12:53:23 (GMT) |
commit | 1d8a302aad133d30b3d45313c631e0ca738ca94f (patch) | |
tree | 6b1c34dfd803ed4c86f998e1b7910109490d5c00 | |
parent | 5cc27d94cc9d96847d8d5484ae2063c1ed982920 (diff) |
Issue #1211864 by Xano, Taz, Dave Reid: Add caching to \Drupal\Core\Utility\Token::getInfo().
-rw-r--r-- | core/core.services.yml | 2 | ||||
-rw-r--r-- | core/lib/Drupal/Core/Utility/Token.php | 52 | ||||
-rw-r--r-- | core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php | 118 |
3 files changed, 166 insertions, 6 deletions
diff --git a/core/core.services.yml b/core/core.services.yml index 3f7c394..c3bb8d2 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -652,7 +652,7 @@ services: arguments: ['@module_handler'] token: class: Drupal\Core\Utility\Token - arguments: ['@module_handler'] + arguments: ['@module_handler', '@cache.discovery', '@language_manager'] batch.storage: class: Drupal\Core\Batch\BatchStorage arguments: ['@database'] diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php index 27a4519..4a1238e 100644 --- a/core/lib/Drupal/Core/Utility/Token.php +++ b/core/lib/Drupal/Core/Utility/Token.php @@ -7,7 +7,10 @@ namespace Drupal\Core\Utility; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Language\Language; +use Drupal\Core\Language\LanguageManagerInterface; /** * Drupal placeholder/token replacement system. @@ -55,9 +58,28 @@ use Drupal\Core\Extension\ModuleHandlerInterface; class Token { /** + * The tag to cache token info with. + */ + const TOKEN_INFO_CACHE_TAG = 'token_info'; + + /** + * The token cache. + * + * @var \Drupal\Core\Cache\CacheBackendInterface + */ + protected $cache; + + /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + + /** * Token definitions. * - * @var array|null + * @var array[]|null * An array of token definitions, or NULL when the definitions are not set. * * @see self::setInfo() @@ -74,11 +96,18 @@ class Token { protected $moduleHandler; /** - * Constructor. + * Constructs a new class instance. * * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache + * The token cache. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(ModuleHandlerInterface $module_handler) { + public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager) { + $this->cache = $cache; + $this->languageManager = $language_manager; $this->moduleHandler = $module_handler; } @@ -282,8 +311,18 @@ class Token { */ public function getInfo() { if (is_null($this->tokenInfo)) { - $this->tokenInfo = $this->moduleHandler->invokeAll('token_info'); - $this->moduleHandler->alter('token_info', $this->tokenInfo); + $cache_id = 'token_info:' . $this->languageManager->getCurrentLanguage(Language::TYPE_CONTENT)->id; + $cache = $this->cache->get($cache_id); + if ($cache) { + $this->tokenInfo = $cache->data; + } + else { + $this->tokenInfo = $this->moduleHandler->invokeAll('token_info'); + $this->moduleHandler->alter('token_info', $this->tokenInfo); + $this->cache->set($cache_id, $this->tokenInfo, CacheBackendInterface::CACHE_PERMANENT, array( + static::TOKEN_INFO_CACHE_TAG => TRUE, + )); + } } return $this->tokenInfo; @@ -307,5 +346,8 @@ class Token { */ public function resetInfo() { $this->tokenInfo = NULL; + $this->cache->deleteTags(array( + static::TOKEN_INFO_CACHE_TAG => TRUE, + )); } } diff --git a/core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php b/core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php new file mode 100644 index 0000000..f2d0a2d --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php @@ -0,0 +1,118 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Utility\TokenUnitTest. + */ + +namespace Drupal\Tests\Core\Utility; + +use Drupal\Core\Language\Language; +use Drupal\Core\Utility\Token; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\Tests\Core\Utility\Token + */ +class TokenUnitTest extends UnitTestCase { + + /** + * The cache used for testing. + * + * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cache; + + /** + * The language manager used for testing. + * + * @var \Drupal\Core\Language\LanguageManager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $languageManager; + + /** + * The module handler service used for testing. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleHandler; + + /** + * The token service under test. + * + * @var \Drupal\Core\Utility\Token|\PHPUnit_Framework_MockObject_MockObject + */ + protected $token; + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'description' => '', + 'name' => '\Drupal\Tests\Core\Utility\Token unit test', + 'group' => 'System', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + $this->cache = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface'); + + $this->languageManager = $this->getMockBuilder('\Drupal\Core\Language\LanguageManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'); + + $this->token = new Token($this->moduleHandler, $this->cache, $this->languageManager); + } + + /** + * @covers getInfo + */ + public function testGetInfo() { + $token_info = array( + 'types' => array( + 'foo' => array( + 'name' => $this->randomName(), + ), + ), + ); + + $language = $this->getMock('\Drupal\Core\Language\Language'); + $language->id = $this->randomName(); + + $this->languageManager->expects($this->once()) + ->method('getCurrentLanguage') + ->with(Language::TYPE_CONTENT) + ->will($this->returnValue($language)); + + // The persistent cache must only be hit once, after which the info is + // cached statically. + $this->cache->expects($this->once()) + ->method('get'); + $this->cache->expects($this->once()) + ->method('set') + ->with('token_info:' . $language->id, $token_info); + + $this->moduleHandler->expects($this->once()) + ->method('invokeAll') + ->with('token_info') + ->will($this->returnValue($token_info)); + $this->moduleHandler->expects($this->once()) + ->method('alter') + ->with('token_info', $token_info); + + // Get the information for the first time. The cache should be checked, the + // hooks invoked, and the info should be set to the cache should. + $this->token->getInfo(); + // Get the information for the second time. The data must be returned from + // the static cache, so the persistent cache must not be accessed and the + // hooks must not be invoked. + $this->token->getInfo(); + } + +} |