commit ae540f0070a0155e91e85a06fd29e18eab5116ac Author: xjm Date: Tue Jan 20 20:24:56 2015 +0000 Move stuff to plugin base, and some refactoring. diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php index e09545f..dfe960e 100644 --- a/core/modules/views/src/Plugin/views/PluginBase.php +++ b/core/modules/views/src/Plugin/views/PluginBase.php @@ -319,13 +319,68 @@ public function globalTokenReplace($string = '', array $options = array()) { return \Drupal::token()->replace($string, array('view' => $this->view), $options); } + + /** + * Indicates whether the value has a potential Views argument token. + * + * @param string $value + * The string to check + * + * @return bool + * TRUE if the string has a potential Views argument token. + * + * @see \Drupal\views\Plugin\views\display\DisplayPluginBase::getArgumentTokens() + */ + public function hasArgumentToken($value) { + // If the string definitely does not contain a token, return FALSE + // immediately for performance. + if ((strpos($value, '!') === FALSE) && (strpos($value, '%') === FALSE)) { + return FALSE; + } + // Otherwise, scan for valid token patterns. + return preg_match('/[!%]\d+/', $value); + } + + /** + * Indicates whether the value has a potential Views row-level token. + * + * @param string $value + * The string to check + * + * @return bool + * TRUE if the string has a potential row token. + * + * @see \Drupal\views\Plugin\views\field\FieldPluginBase::getRenderTokens() + */ + public function hasRenderToken($value) { + // If the string definitely does not contain a token, return FALSE + // immediately for performance. + if (strpos($value, '{{') === FALSE) { + return FALSE; + } + // Otherwise, scan for valid token patterns. + // Match any non-empty string between {{ and }} except another {{. + return preg_match('/\{\{[^(\{\{)]+\}\}/', $value); + } + + /** + * Indicates whether the value has a potential Views token. + * + * @param string $value + * The string to check + * + * @return bool + * TRUE if the string has any token pattern. + */ + public function hasToken($value) { + return ($this->hasArgumentToken($value) || $this->hasRenderToken($value)); + } + /** - * Replaces Views' tokens in a given string. It is the responsibility of the - * calling function to ensure $text and $token replacements are sanitized. + * Replaces Views' tokens in a given string. * - * This used to be a simple strtr() scattered throughout the code. Some Views - * tokens, such as arguments (e.g.: %1 or !1), still use the old format so we - * handle those as well as the new Twig-based tokens (e.g.: {{ field_name }}) + * It is the responsibility of the calling function to ensure $text and + * $token replacements are sanitized. * * @param $text * String with possible tokens. @@ -333,6 +388,11 @@ public function globalTokenReplace($string = '', array $options = array()) { * Array of token => replacement_value items. * * @return String + * The text with the tokens replaced. + * + * @see \Drupal\views\Plugin\views\PluginBase::hasToken() + * @see \Drupal\views\Plugin\views\display\DisplayPluginBase::getArgumentTokens() + * @see \Drupal\views\Plugin\views\field\FieldPluginBase::getRenderTokens() */ protected function viewsTokenReplace($text, $tokens) { if (empty($tokens)) { @@ -344,8 +404,9 @@ protected function viewsTokenReplace($text, $tokens) { $twig_tokens = array(); $other_tokens = array(); foreach ($tokens as $token => $replacement) { - if (strpos($token, '{{') !== FALSE) { + if ($this->hasRenderToken($token)) { // Twig wants a token replacement array stripped of curly-brackets. + // @todo Do this with the regex instead. $token = trim(str_replace(array('{', '}'), '', $token)); $twig_tokens[$token] = $replacement; } diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 61c9e84..e0f33cb 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -1053,7 +1053,7 @@ public function optionLink($text, $section, $class = '', $title = '') { * This function is similar to views_handler_field::getRenderTokens() * but without fields tokens. */ - public function getArgumentsTokens() { + public function getArgumentTokens() { $tokens = array(); if (!empty($this->view->build_info['substitutions'])) { $tokens = $this->view->build_info['substitutions']; @@ -2131,7 +2131,7 @@ public function renderMoreLink() { $path = $this->getPath(); if ($this->getOption('link_display') == 'custom_url' && $override_path = $this->getOption('link_url')) { - $tokens = $this->getArgumentsTokens(); + $tokens = $this->getArgumentTokens(); $path = $this->viewsTokenReplace($override_path, $tokens); } diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index c68680e..520af7c 100644 --- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -331,7 +331,7 @@ public function elementClasses($row_index = NULL) { * {@inheritdoc} */ public function tokenizeValue($value, $row_index = NULL) { - if ($this->view->getStyle()->hasTwigToken($value) || $this->view->getStyle()->hasArgToken($value)) { + if ($this->view->getStyle()->hasRenderToken($value) || $this->view->getStyle()->hasArgumentToken($value)) { $fake_item = array( 'alter_text' => TRUE, 'text' => $value, @@ -1468,22 +1468,7 @@ protected function renderAsLink($alter, $text, $tokens) { * {@inheritdoc} */ public function getRenderTokens($item) { - $tokens = array(); - if (!empty($this->view->build_info['substitutions'])) { - $tokens = $this->view->build_info['substitutions']; - } - $count = 0; - foreach ($this->view->display_handler->getHandlers('argument') as $arg => $handler) { - $token = '%' . ++$count; - if (!isset($tokens[$token])) { - $tokens[$token] = ''; - } - - // Use strip tags as there should never be HTML in the path. - // However, we need to preserve special characters like " that - // were removed by String::checkPlain(). - $tokens['!' . $count] = isset($this->view->args[$count - 1]) ? strip_tags(String::decodeEntities($this->view->args[$count - 1])) : ''; - } + $tokens = $this->view->display_handler->getArgumentTokens(); // Get flattened set of tokens for any array depth in query parameters. $tokens += $this->getTokenValuesRecursive($this->view->getRequest()->query->all()); diff --git a/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/core/modules/views/src/Plugin/views/style/StylePluginBase.php index c125782..14389ad 100644 --- a/core/modules/views/src/Plugin/views/style/StylePluginBase.php +++ b/core/modules/views/src/Plugin/views/style/StylePluginBase.php @@ -214,7 +214,7 @@ public function getRowClass($row_index) { * Take a value and apply token replacement logic to it. */ public function tokenizeValue($value, $row_index) { - if ($this->hasArgToken($value) || $this->hasTwigToken($value)) { + if ($this->hasArgumentToken($value) || $this->hasRenderToken($value)) { // Row tokens might be empty, for example for node row style. $tokens = isset($this->rowTokens[$row_index]) ? $this->rowTokens[$row_index] : array(); if (!empty($this->view->build_info['substitutions'])) { @@ -225,59 +225,6 @@ public function tokenizeValue($value, $row_index) { } return $value; } - - /** - * Indicates whether the value has a potential Views argument token. - * - * @param string $value - * The string to check - * - * @return bool - * TRUE if the string has a potential Views argument token. - */ - public function hasArgToken($value) { - // If the string definitely does not contain a token, return FALSE - // immediately for performance. - if ((strpos($value, '!') === FALSE) && (strpos($value, '%') === FALSE)) { - return FALSE; - } - // Otherwise, scan for valid token patterns. - return preg_match('/[!%]\d+/', $value); - } - - /** - * Indicates whether the value has a potential Views row-level token. - * - * @param string $value - * The string to check - * - * @return bool - * TRUE if the string has a potential row token. - */ - public function hasTwigToken($value) { - // If the string definitely does not contain a token, return FALSE - // immediately for performance. - if (strpos($value, '{{') === FALSE) { - return FALSE; - } - // Otherwise, scan for valid token patterns. - // Match any non-empty string between {{ and }} except another {{. - return preg_match('/\{\{[^(\{\{)]+\}\}/', $value); - } - - /** - * Indicates whether the value has a potential Views token. - * - * @param string $value - * The string to check - * - * @return bool - * TRUE if the string has any token pattern. - */ - public function hasToken($value) { - return ($this->hasArgToken($value) || $this->hasTwigToken($value)); - } - /** * Should the output of the style plugin be rendered even if it's a empty view. */ diff --git a/core/modules/views/tests/src/Unit/Plugin/style/StylePluginBaseTest.php b/core/modules/views/tests/src/Unit/Plugin/style/StylePluginBaseTest.php deleted file mode 100644 index 445552c..0000000 --- a/core/modules/views/tests/src/Unit/Plugin/style/StylePluginBaseTest.php +++ /dev/null @@ -1,136 +0,0 @@ -stylePlugin = new TestStylePlugin(array(), 'default', array()); - } - - /** - * @covers ::hasArgToken - * @dataProvider providerHasArgToken - */ - public function testHasArgToken($value, $return) { - $this->assertEquals($this->stylePlugin->hasArgToken($value), $return); - } - - /** - * Data provider for testHasArgToken(). - * - * @return array - */ - public function providerHasArgToken() { - return array( - array('%', FALSE), - array('!', FALSE), - array('!', FALSE), - array('% 1', FALSE), - array('! 1', FALSE), - array('!1', TRUE), - array('%1', TRUE), - array(' !12345 ', TRUE), - array(' %54321 ', TRUE), - array('%elephant', FALSE), - array('!elephant', FALSE), - array('[old_token]', FALSE), - array('[other:token]', FALSE), - array('{{twig_token}}', FALSE), - ); - } - - /** - * @covers ::hasTwigToken - * @dataProvider providerHasTwigToken - */ - public function testHasTwigToken($value, $return) { - $this->assertEquals($this->stylePlugin->hasTwigToken($value), $return); - } - - /** - * Data provider for testHasTwigToken(). - * - * @return array - */ - public function providerHasTwigToken() { - return array( - array('%1', FALSE), - array('!1', FALSE), - array('{', FALSE), - array('{{', FALSE), - array('}', FALSE), - array('}}', FALSE), - array('{{}}', FALSE), - array('{{{{}}', FALSE), - array('{{ elephant }}', TRUE), - array(' {{elephant_twig_token_1}} ', TRUE), - ); - } - - /** - * @covers ::hasToken - * @dataProvider providerHasToken - */ - public function testHasToken($value, $return) { - $this->assertEquals($this->stylePlugin->hasToken($value), $return); - } - - /** - * Data provider for testHasToken(). - * - * @return array - * - * @see \Drupal\system\Tests\System\TokenScanTest - */ - public function providerHasToken() { - return array( - array('%', FALSE), - array('!', FALSE), - array('!', FALSE), - array('% 1', FALSE), - array('! 1', FALSE), - array('!1', TRUE), - array('%1', TRUE), - array(' !12345 ', TRUE), - array(' %54321 ', TRUE), - array('%elephant', FALSE), - array('!elephant', FALSE), - array('{', FALSE), - array('{{', FALSE), - array('}', FALSE), - array('}}', FALSE), - array('{{}}', FALSE), - array('{{{{}}', FALSE), - array('{{ elephant }}', TRUE), - array(' {{elephant_twig_token_1}} ', TRUE), - array('[old_token]', FALSE), - array('[other:token]', FALSE), - ); - } - -} - -class TestStylePlugin extends StylePluginBase {} diff --git a/core/modules/views/tests/src/Unit/PluginBaseTest.php b/core/modules/views/tests/src/Unit/PluginBaseTest.php index 9c180a6..240f36a 100644 --- a/core/modules/views/tests/src/Unit/PluginBaseTest.php +++ b/core/modules/views/tests/src/Unit/PluginBaseTest.php @@ -320,4 +320,103 @@ public function providerTestFilterByDefinedOptions() { return $data; } + /** + * @covers ::hasArgumentToken + * @dataProvider providerHasArgumentToken + */ + public function testHasArgumentToken($value, $return) { + $this->assertEquals($this->testHelperPlugin->hasArgumentToken($value), $return); + } + + /** + * Data provider for testHasArgumentToken(). + * + * @return array + */ + public function providerHasArgumentToken() { + return array( + array('%', FALSE), + array('!', FALSE), + array('!', FALSE), + array('% 1', FALSE), + array('! 1', FALSE), + array('!1', TRUE), + array('%1', TRUE), + array(' !12345 ', TRUE), + array(' %54321 ', TRUE), + array('%elephant', FALSE), + array('!elephant', FALSE), + array('[old_token]', FALSE), + array('[other:token]', FALSE), + array('{{render_token}}', FALSE), + ); + } + + /** + * @covers ::hasRenderToken + * @dataProvider providerHasRenderToken + */ + public function testHasRenderToken($value, $return) { + $this->assertEquals($this->testHelperPlugin->hasRenderToken($value), $return); + } + + /** + * Data provider for testHasRenderToken(). + * + * @return array + */ + public function providerHasRenderToken() { + return array( + array('%1', FALSE), + array('!1', FALSE), + array('{', FALSE), + array('{{', FALSE), + array('}', FALSE), + array('}}', FALSE), + array('{{}}', FALSE), + array('{{{{}}', FALSE), + array('{{ elephant }}', TRUE), + array(' {{elephant_render_token_1}} ', TRUE), + ); + } + + /** + * @covers ::hasToken + * @dataProvider providerHasToken + */ + public function testHasToken($value, $return) { + $this->assertEquals($this->testHelperPlugin->hasToken($value), $return); + } + + /** + * Data provider for testHasToken(). + * + * @return array + */ + public function providerHasToken() { + return array( + array('%', FALSE), + array('!', FALSE), + array('!', FALSE), + array('% 1', FALSE), + array('! 1', FALSE), + array('!1', TRUE), + array('%1', TRUE), + array(' !12345 ', TRUE), + array(' %54321 ', TRUE), + array('%elephant', FALSE), + array('!elephant', FALSE), + array('{', FALSE), + array('{{', FALSE), + array('}', FALSE), + array('}}', FALSE), + array('{{}}', FALSE), + array('{{{{}}', FALSE), + array('{{ elephant }}', TRUE), + array(' {{elephant_render_token_1}} ', TRUE), + array('[old_token]', FALSE), + array('[other:token]', FALSE), + ); + } + }