Skip to content

Commit

Permalink
Improved namespacing performance
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed Dec 28, 2023
1 parent 099e76a commit ed7939d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Improved the performance of input namespacing.
- `relatedToAssets`, `relatedToCategories`, `relatedToEntries`, `relatedToTags`, and `relatedToUsers` are now reserved user field handles. ([#14075](https://github.com/craftcms/cms/issues/14075))
- `craft\services\Security::$sensitiveKeywords` is no longer case-sensitive. ([#14064](https://github.com/craftcms/cms/discussions/14064))
- Fixed a bug where the `index-assets/cleanup` command accepted `--cache-remote-images`, `--create-missing-assets`, and `--delete-missing-assets` options, even though they didn’t do anything.
Expand Down
49 changes: 41 additions & 8 deletions src/helpers/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -852,16 +852,34 @@ private static function _escapeTextareas(string &$html): array
{
$markers = [];
$offset = 0;
$r = '';

while (preg_match('/<textarea\b[^>]*>/i', $html, $openMatch, PREG_OFFSET_CAPTURE, $offset)) {
$innerOffset = $openMatch[0][1] + strlen($openMatch[0][0]);
if (!preg_match('/<\/textarea>/', $html, $closeMatch, PREG_OFFSET_CAPTURE, $innerOffset)) {
while (($pos = stripos($html, '<textarea', $offset)) !== false) {
$gtPos = strpos($html, '>', $pos + 9);
if ($gtPos === false) {
break;
}
$marker = sprintf('{marker:%s}', StringHelper::randomString());
$markers[$marker] = substr($html, $innerOffset, $closeMatch[0][1] - $innerOffset);
$html = substr($html, 0, $innerOffset) . $marker . substr($html, $closeMatch[0][1]);
$offset = $innerOffset + strlen($marker) + strlen($closeMatch[0][0]);
$innerHtmlPos = $gtPos + 1;
$closePos = stripos($html, '</textarea>', $innerHtmlPos);
if ($closePos === false) {
break;
}
$outerPos = $closePos + 11;
$innerHtml = $closePos !== $innerHtmlPos ? substr($html, $innerHtmlPos, $closePos - $innerHtmlPos) : null;

if ($innerHtml !== null && str_contains($innerHtml, '<')) {
$marker = sprintf('{marker:%s}', mt_rand());
$r .= substr($html, $offset, $innerHtmlPos - $offset) . $marker . substr($html, $closePos, 11);
$markers[$marker] = $innerHtml;
} else {
$r .= substr($html, $offset, $outerPos - $offset);
}

$offset = $outerPos;
}

if ($offset !== 0) {
$html = $r . substr($html, $offset);
}

return $markers;
Expand All @@ -876,7 +894,22 @@ private static function _escapeTextareas(string &$html): array
*/
private static function _restoreTextareas(string $html, array $markers): string
{
return str_replace(array_keys($markers), array_values($markers), $html);
if (empty($markers)) {
return $html;
}

$r = '';
$offset = 0;

foreach ($markers as $marker => $textarea) {
$pos = strpos($html, $marker, $offset);
if ($pos !== false) {
$r .= substr($html, $offset, $pos - $offset) . $textarea;
$offset = $pos + strlen($marker);
}
}

return $r . substr($html, $offset);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/helpers/HtmlHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,8 @@ public function namespaceInputsDataProvider(): array
return [
['<input name="foo[bar]">', '<input name="bar">', 'foo'],
['<input name="foo[bar][baz]">', '<input name="bar[baz]">', 'foo'],
['<textarea name="foo[bar]"></textarea>', '<textarea name="bar"></textarea>', 'foo'],
['<textarea name="foo[bar]">blah</textarea>', '<textarea name="bar">blah</textarea>', 'foo'],
['<textarea name="foo[bar]"><input name="foo"></textarea>', '<textarea name="bar"><input name="foo"></textarea>', 'foo'],
['<input name="3[foo]">', '<input name="foo">', '3'],
];
Expand Down

0 comments on commit ed7939d

Please sign in to comment.