Browse Source

Add new Strings::performWithEscapedBlocks methods

- Add new BBCode::performWithEscapedTags method
- Add tests
tags/2020.07
Hypolite Petovan 2 months ago
parent
commit
348b71d0b0
3 changed files with 92 additions and 0 deletions
  1. +18
    -0
      src/Content/Text/BBCode.php
  2. +48
    -0
      src/Util/Strings.php
  3. +26
    -0
      tests/src/Util/StringsTest.php

+ 18
- 0
src/Content/Text/BBCode.php View 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);
}
}

+ 48
- 0
src/Util/Strings.php View 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;
}
}

+ 26
- 0
tests/src/Util/StringsTest.php View 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);
}
}

Loading…
Cancel
Save