]> git.mxchange.org Git - friendica.git/commitdiff
Add new Strings::performWithEscapedBlocks methods
authorHypolite Petovan <hypolite@mrpetovan.com>
Thu, 4 Jun 2020 23:25:48 +0000 (19:25 -0400)
committerHypolite Petovan <hypolite@mrpetovan.com>
Mon, 8 Jun 2020 22:40:20 +0000 (18:40 -0400)
- Add new BBCode::performWithEscapedTags method
- Add tests

src/Content/Text/BBCode.php
src/Util/Strings.php
tests/src/Util/StringsTest.php

index 50536dc1a5af3778e0e92ff928f4406b1bccf569..0c718757b7a67660f07709b87ddae6ce1830d03e 100644 (file)
@@ -2163,4 +2163,22 @@ class BBCode
 
                return $ret;
        }
+
+       /**
+        * Perform a custom function on a text after having escaped blocks enclosed in the provided tag list.
+        *
+        * @param string   $text
+        * @param array    $tagList A list of tag names, e.g ['noparse', 'nobb', 'pre']
+        * @param callable $callback
+        * @return string
+        * @throws Exception
+        *@see Strings::performWithEscapedBlocks
+        *
+        */
+       public static function performWithEscapedTags(string $text, array $tagList, callable $callback)
+       {
+               $tagList = array_map('preg_quote', $tagList);
+
+               return Strings::performWithEscapedBlocks($text, '#\[(?:' . implode('|', $tagList) . ').*?\[/(?:' . implode('|', $tagList) . ')]#ism', $callback);
+       }
 }
index 04d676ef57364ac87ad5c37cb3aff83a53afd672..35e7ebe1510c732ccd793e2837297acdbbf666b0 100644 (file)
@@ -472,4 +472,52 @@ class Strings
 
                return mb_substr($string, 0, $start) . $replacement . mb_substr($string, $start + $length, $string_length - $start - $length);
        }
+
+       /**
+        * Perform a custom function on a text after having escaped blocks matched by the provided regular expressions.
+        * Only full matches are used, capturing group are ignored.
+        *
+        * To change the provided text, the callback function needs to return it and this function will return the modified
+        * version as well after having restored the escaped blocks.
+        *
+        * @param string   $text
+        * @param string   $regex
+        * @param callable $callback
+        * @return string
+        * @throws \Exception
+        */
+       public static function performWithEscapedBlocks(string $text, string $regex, callable $callback)
+       {
+               // Enables nested use
+               $executionId = random_int(PHP_INT_MAX / 10, PHP_INT_MAX);
+
+               $blocks = [];
+
+               $text = preg_replace_callback($regex,
+                       function ($matches) use ($executionId, &$blocks) {
+                               $return = '«block-' . $executionId . '-' . count($blocks) . '»';
+
+                               $blocks[] = $matches[0];
+
+                               return $return;
+                       },
+                       $text
+               );
+
+               $text = $callback($text) ?? '';
+
+               // Restore code blocks
+               $text = preg_replace_callback('/«block-' . $executionId . '-([0-9]+)»/iU',
+                       function ($matches) use ($blocks) {
+                               $return = $matches[0];
+                               if (isset($blocks[intval($matches[1])])) {
+                                       $return = $blocks[$matches[1]];
+                               }
+                               return $return;
+                       },
+                       $text
+               );
+
+               return $text;
+       }
 }
index 66fb2f0f53466d3be9595e56356c4704687ad550..611d72fe7cd8b10d864f78142688f97f47a19775 100644 (file)
@@ -194,4 +194,30 @@ class StringsTest extends TestCase
                        )
                );
        }
+
+       public function testPerformWithEscapedBlocks()
+       {
+               $originalText = '[noparse][/noparse][nobb]nobb[/nobb][noparse]noparse[/noparse]';
+
+               $text = Strings::performWithEscapedBlocks($originalText, '#[(?:noparse|nobb)].*?\[/(?:noparse|nobb)]#is', function ($text) {
+                       return $text;
+               });
+
+               $this->assertEquals($originalText, $text);
+       }
+
+       public function testPerformWithEscapedBlocksNested()
+       {
+               $originalText = '[noparse][/noparse][nobb]nobb[/nobb][noparse]noparse[/noparse]';
+
+               $text = Strings::performWithEscapedBlocks($originalText, '#[nobb].*?\[/nobb]#is', function ($text) {
+                       $text = Strings::performWithEscapedBlocks($text, '#[noparse].*?\[/noparse]#is', function ($text) {
+                               return $text;
+                       });
+
+                       return $text;
+               });
+
+               $this->assertEquals($originalText, $text);
+       }
 }