[FEATURE] Integrate string replacement to stdWrap
authorOliver Hader <oliver@typo3.org>
Fri, 29 Jul 2011 09:47:45 +0000 (11:47 +0200)
committerJigal van Hemert <jigal@xs4all.nl>
Sun, 31 Jul 2011 17:34:41 +0000 (19:34 +0200)
Allow to search/replace strings, optionally with preg-regex.

Change-Id: I05a067e06cf6d6d664a178c6cf91e17178d691a8
Resolves: #19347
Reviewed-on: http://review.typo3.org/3855
Reviewed-by: Jo Hasenau
Tested-by: Jo Hasenau
Reviewed-by: Jigal van Hemert
Tested-by: Jigal van Hemert
tests/typo3/sysext/cms/tslib/class.tslib_contentTest.php
typo3/sysext/cms/tslib/class.tslib_content.php

index c9d6fd0..17e9ca0 100644 (file)
@@ -852,5 +852,54 @@ class tslib_contentTest extends tx_phpunit_testcase {
                $result = $this->cObj->numberFormat($float, $formatConf);
                $this->assertEquals($expected, $result);
        }
+
+       /**
+        * Data provider for the replacement test
+        *
+        * @return array multi-dimensional array with the second level like this:
+        *               0 => the input text
+        *               1 => the conf array for the replacement stdWrap function
+        *               2 => the expected result
+        *
+        * @see replacement
+        */
+       public function replacementDataProvider() {
+               $data = array(
+                       'multiple replacements, including regex' => array(
+                               'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
+                               array('replacement.' =>
+                                       array(
+                                               '120.' => array(
+                                                       'search' => 'in da hood',
+                                                       'replace' => 'around the block',
+                                               ),
+                                               '20.' => array(
+                                                       'search' => '_',
+                                                       'replace.' => array('char' => '32'),
+                                               ),
+                                               '130.' => array(
+                                                       'search' => '#a (Cat|Dog|Tiger)#i',
+                                                       'replace' => 'an animal',
+                                                       'useRegExp' => '1',
+                                               ),
+                                       ),
+                               ),
+                               'There is an animal, an animal and an animal around the block! Yeah!'
+                       ),
+               );
+               return $data;
+       }
+
+       /**
+        * Check if stdWrap.replacement and all of its properties work properly
+        *
+        * @dataProvider replacementDataProvider
+        *
+        * @test
+        */
+       public function replacement($input, $conf, $expected) {
+               $result = $this->cObj->stdWrap_replacement($input, $conf);
+               $this->assertEquals($expected, $result);
+       }
 }
 ?>
\ No newline at end of file
index b9dc14f..e094d30 100644 (file)
@@ -113,6 +113,7 @@ class tslib_cObj {
                'HTMLparser' => 'boolean',
                'HTMLparser.' => 'array',
                'split.' => 'array',
+               'replacement.' => 'array',
                'prioriCalc' => 'boolean',
                'prioriCalc.' => 'array',
                'char' => 'integer',
@@ -2277,6 +2278,19 @@ class tslib_cObj {
        }
 
        /**
+        * replacement
+        * Will execute replacements on the content (optionally with preg-regex)
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for replacement.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_replacement($content = '', $conf = array()) {
+               $content = $this->replacement($content, $conf['replacement.']);
+               return $content;
+       }
+
+       /**
         * prioriCalc
         * Will use the content as a mathematical term and calculate the result
         * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result
@@ -4150,6 +4164,72 @@ class tslib_cObj {
        }
 
        /**
+        * Processes ordered replacements on content data.
+        *
+        * @param string $content The content to be processed
+        * @param array $configuration The TypoScript configuration for stdWrap.replacement
+        * @return string The processed content data
+        */
+       protected function replacement($content, array $configuration) {
+                       // Sorts actions in configuration by numeric index
+               ksort($configuration, SORT_NUMERIC);
+
+               foreach ($configuration as $index => $action) {
+                               // Checks whether we have an valid action and a numeric key ending with a dot ("10.")
+                       if (is_array($action)
+                               && substr($index, -1) === '.'
+                               && t3lib_utility_Math::canBeInterpretedAsInteger(substr($index, 0, -1))) {
+                               $content = $this->replacementSingle($content, $action);
+                       }
+               }
+
+               return $content;
+       }
+
+       /**
+        * Processes a single search/replace on content data.
+        *
+        * @param       string          $content: The content to be processed
+        * @param       array           $configuration: The TypoScript of the search/replace action to be processed
+        * @return      string          The processed content data
+        */
+       protected function replacementSingle($content, array $configuration) {
+               if ((isset($configuration['search']) || isset($configuration['search.']))
+                       && (isset($configuration['replace']) || isset($configuration['replace.']))) {
+
+                               // Gets the strings
+                       $search = isset($configuration['search.'])
+                               ? $this->stdWrap($configuration['search'], $configuration['search.']) : $configuration['search'];
+                       $replace = isset($configuration['replace.'])
+                               ? $this->stdWrap($configuration['replace'], $configuration['replace.']) : $configuration['replace'];
+
+                               // Determines whether regular expression shall be used:
+                       if (isset($configuration['useRegExp']) || $configuration['useRegExp.']) {
+                               $useRegularExpression = isset($configuration['useRegExp.'])
+                                       ? $this->stdWrap($configuration['useRegExp'], $configuration['useRegExp.']) : $configuration['useRegExp'];
+                       }
+
+                               // Performs a replacement by preg_replace()
+                       if (isset($useRegularExpression)) {
+                                       // Get separator-character which precedes the string and separates search-string from the modifiers
+                               $separator = $search[0];
+                               $startModifiers = strrpos($search, $separator);
+                               if (($separator !== FALSE) && ($startModifiers > 0)) {
+                                       $modifiers = substr($search, $startModifiers + 1);
+                                               // remove "e" (eval-modifier), which would otherwise allow to run arbitrary PHP-code
+                                       $modifiers = str_replace('e', '', $modifiers);
+                                       $search = substr($search, 0, $startModifiers + 1) . $modifiers;
+                               }
+                               $content = preg_replace($search, $replace, $content);
+                       } else {
+                               $content = str_replace($search, $replace, $content);
+                       }
+               }
+
+               return $content;
+       }
+
+       /**
         * Implements the "round" property of stdWrap
         * This is a Wrapper function for PHP's rounding functions (round,ceil,floor), defaults to round()
         *