From ef3ad7a4b9f5b0918d82bbb565896be6206e02e4 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 15:56:34 +0300 Subject: [PATCH 01/11] Refactoring. Code duplication. Removed 7.4+ expression. --- ContactsEncoder.php | 94 +++++++++++---------------------------------- 1 file changed, 23 insertions(+), 71 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 1f6c6fa..c39c0e7 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -300,83 +300,35 @@ public function modifyContent($content, $skip_exclusions = false) */ public function modifyGlobalEmails($content) { - $replacing_result = ''; - - if ( version_compare(phpversion(), '7.4.0', '>=') ) { - $replacing_result = preg_replace_callback($this->global_email_pattern, function ($matches) use ($content) { - if ( isset($matches[3][0], $matches[0][0]) && in_array(strtolower($matches[3][0]), ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp']) ) { - return $matches[0][0]; - } - - //chek if email is placed in excluded attributes and return unchanged if so - if ( isset($matches[0][0]) && $this->helper->hasAttributeExclusions($matches[0][0], $this->temp_content) ) { - return $matches[0][0]; - } - - // skip encoding if the content in script tag - if ( isset($matches[0][0]) && $this->helper->isInsideScriptTag($matches[0][0], $content) ) { - return $matches[0][0]; - } - - // skip encoding inside select option values/text — breaks form submission - if ( isset($matches[0][0]) && $this->helper->isInsideOptionTag($matches[0][0], $content) ) { - return $matches[0][0]; - } - - if ( isset($matches[0][0]) && $this->helper->isMailto($matches[0][0]) ) { - return $this->encodeMailtoLinkV2($matches[0], $content); - } - - if ( - isset($matches[0]) && - is_array($matches[0]) && - $this->helper->isMailtoAdditionalCopy($matches[0], $content) - ) { - return ''; - } - - if ( - isset($matches[0], $matches[0][0]) && - is_array($matches[0]) && - $this->helper->isEmailInLink($matches[0], $content) - ) { - return $matches[0][0]; - } - - if ( isset($matches[0][0]) ) { - return $this->encodePlainEmail($matches[0][0]); - } - - return ''; - }, $content, -1, $count, PREG_OFFSET_CAPTURE); - } + $replacing_result = preg_replace_callback($this->global_email_pattern, function ($matches) { + if ( isset($matches[3]) && in_array(strtolower($matches[3]), ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp']) && isset($matches[0]) ) { + return $matches[0]; + } - if ( version_compare(phpversion(), '7.4.0', '<') ) { - $replacing_result = preg_replace_callback($this->global_email_pattern, function ($matches) { - if ( isset($matches[3]) && in_array(strtolower($matches[3]), ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp']) && isset($matches[0]) ) { - return $matches[0]; - } + //chek if email is placed in excluded attributes and return unchanged if so + if ( isset($matches[0]) && $this->helper->hasAttributeExclusions($matches[0], $this->temp_content) ) { + return $matches[0]; + } - //chek if email is placed in excluded attributes and return unchanged if so - if ( isset($matches[0]) && $this->helper->hasAttributeExclusions($matches[0], $this->temp_content) ) { - return $matches[0]; - } + // skip encoding if the content in script tag + if ( isset($matches[0]) && $this->helper->isInsideScriptTag($matches[0], $this->temp_content) ) { + return $matches[0]; + } - if ( isset($matches[0]) && $this->helper->isInsideOptionTag($matches[0], $this->temp_content) ) { - return $matches[0]; - } + if ( isset($matches[0]) && $this->helper->isInsideOptionTag($matches[0], $this->temp_content) ) { + return $matches[0]; + } - if ( isset($matches[0]) && $this->helper->isMailto($matches[0]) ) { - return $this->encodeMailtoLink($matches[0]); - } + if ( isset($matches[0]) && $this->helper->isMailto($matches[0]) ) { + return $this->encodeMailtoLink($matches[0]); + } - if ( isset($matches[0]) ) { - return $this->encodePlainEmail($matches[0]); - } + if ( isset($matches[0]) ) { + return $this->encodePlainEmail($matches[0]); + } - return ''; - }, $content); - } + return ''; + }, $content); // modify content to turn back aria-label $replacing_result = $this->handleAriaLabelContent($replacing_result, true); From 519e0ac40c1090bc83d61aed4fd3718560409f5b Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:03:26 +0300 Subject: [PATCH 02/11] Refactoring. Code duplication. Unpresented checks added to `modifyGlobalEmails`. --- ContactsEncoder.php | 6 ++++++ Helper/ContactsEncoderHelper.php | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index c39c0e7..4b6aa8b 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -319,6 +319,12 @@ public function modifyGlobalEmails($content) return $matches[0]; } + if ( + isset($matches[0]) && $this->helper->isEmailInLink($matches[0], $this->temp_content) + ) { + return $matches[0]; + } + if ( isset($matches[0]) && $this->helper->isMailto($matches[0]) ) { return $this->encodeMailtoLink($matches[0]); } diff --git a/Helper/ContactsEncoderHelper.php b/Helper/ContactsEncoderHelper.php index 228488f..452e035 100644 --- a/Helper/ContactsEncoderHelper.php +++ b/Helper/ContactsEncoderHelper.php @@ -75,15 +75,17 @@ public function isMailtoAdditionalCopy($match, $content) /** * Checking if email in link * - * @param array $matches + * @param string $email * @param string $content * * @return bool */ - public function isEmailInLink($matches, $content) + public function isEmailInLink($email, $content) { - $email = isset($matches[0]) && is_string($matches[0]) ? $matches[0] : null; - $position = isset($matches[1]) ? (int)$matches[1] : null; + $position = strpos($content, $email); + if ($position === false) { + return false; + } if (null === $position || null === $email) { return false; From a0bd933e1ac647b6ec70979fd67f3edce2e267fe Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:06:08 +0300 Subject: [PATCH 03/11] Refactoring. Code duplication. Unpresented encoding added to `modifyGlobalEmails`. --- ContactsEncoder.php | 6 ++++++ Helper/ContactsEncoderHelper.php | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 4b6aa8b..86adc05 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -325,6 +325,12 @@ public function modifyGlobalEmails($content) return $matches[0]; } + if ( + isset($matches[0]) && $this->helper->isMailtoAdditionalCopy($matches[0], $this->temp_content) + ) { + return ''; + } + if ( isset($matches[0]) && $this->helper->isMailto($matches[0]) ) { return $this->encodeMailtoLink($matches[0]); } diff --git a/Helper/ContactsEncoderHelper.php b/Helper/ContactsEncoderHelper.php index 452e035..0cdb654 100644 --- a/Helper/ContactsEncoderHelper.php +++ b/Helper/ContactsEncoderHelper.php @@ -46,16 +46,16 @@ public function isTelTag($string) /** * Checking if the string contains mailto: link * - * @param array $match + * @param string $email * @param string $content * * @return bool */ - public function isMailtoAdditionalCopy($match, $content) + public function isMailtoAdditionalCopy($email, $content) { - $position = isset($match[1]) ? (int)$match[1] : null; + $position = strpos($content, $email); - if (null === $position) { + if ($position === false) { return false; } From 0256d3ac6ecec6f3c4dc721a18358679d4cb177e Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:11:54 +0300 Subject: [PATCH 04/11] Refactoring. Code duplication. Removed 7.4+ expression for `modifyGlobalPhoneNumbers`. --- ContactsEncoder.php | 92 ++++++++++----------------------------------- 1 file changed, 20 insertions(+), 72 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 86adc05..a905eb8 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -359,89 +359,37 @@ public function modifyGlobalEmails($content) public function modifyGlobalPhoneNumbers($content) { $phones_pattern = $this->global_phones_pattern; - $replacing_result = ''; - - if ( version_compare(phpversion(), '7.4.0', '>=') ) { - $replacing_result = preg_replace_callback( - $phones_pattern, - function ($matches) use ($content) { - if ( isset($matches[0]) ) { - $first_group = $matches[0]; - } else { - return ''; - } - - if ( isset($first_group[0]) ) { - $second_group = $first_group[0]; - } else { - return ''; + $replacing_result = preg_replace_callback( + $phones_pattern, + function ($matches) { + if ( isset($matches[0]) ) { + if ( $this->helper->isTelTag($matches[0]) ) { + return $this->encodeTelLink($matches[0]); } - if (is_array($first_group) && $this->helper->isTelTag($second_group) ) { - return $this->encodeTelLinkV2($first_group, $content); - } - //symbols clearance - $item_length = strlen(str_replace([' ', '(', ')', '-', '+', '.'], '', $second_group)); - //check length + $item_length = strlen(str_replace([' ', '(', ')', '-', '+', '.'], '', $matches[0])); if ( $item_length > 12 || $item_length < 8 ) { - return $second_group; - } - //check attribute exclusions - if ( $this->helper->hasAttributeExclusions($second_group, $this->temp_content) ) { - return $second_group; + return $matches[0]; } - //check if in script - if ( $this->helper->isInsideScriptTag($second_group, $content) ) { - return $second_group; + + if ( $this->helper->hasAttributeExclusions($matches[0][0], $this->temp_content) ) { + return $matches[0]; } - //do encode + } + + if ( isset($matches[0]) ) { return $this->encodeAny( - $second_group, + $matches[0], $this->global_obfuscation_mode, $this->global_replacing_text, true ); - }, - $content, - -1, - $count, - PREG_OFFSET_CAPTURE - ); - } - - if ( version_compare(phpversion(), '7.4.0', '<') ) { - $replacing_result = preg_replace_callback( - $phones_pattern, - function ($matches) { - if ( isset($matches[0]) ) { - if ( $this->helper->isTelTag($matches[0]) ) { - return $this->encodeTelLink($matches[0]); - } - - $item_length = strlen(str_replace([' ', '(', ')', '-', '+', '.'], '', $matches[0])); - if ( $item_length > 12 || $item_length < 8 ) { - return $matches[0]; - } - - if ( $this->helper->hasAttributeExclusions($matches[0][0], $this->temp_content) ) { - return $matches[0]; - } - } - - if ( isset($matches[0]) ) { - return $this->encodeAny( - $matches[0], - $this->global_obfuscation_mode, - $this->global_replacing_text, - true - ); - } + } - return ''; - }, - $content - ); - } + return ''; + }, + $content + ); // modify content to turn back aria-label $replacing_result = $this->handleAriaLabelContent($replacing_result, true); From eab016dd7cd53367eae095f6daf8bc598769cde5 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:14:35 +0300 Subject: [PATCH 05/11] Refactoring. Code duplication. Unpresented checks added to `modifyGlobalPhoneNumbers`. --- ContactsEncoder.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index a905eb8..562facb 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -367,17 +367,24 @@ function ($matches) { return $this->encodeTelLink($matches[0]); } + // symbols clearance $item_length = strlen(str_replace([' ', '(', ')', '-', '+', '.'], '', $matches[0])); + + // check length if ( $item_length > 12 || $item_length < 8 ) { return $matches[0]; } + // check attribute exclusions if ( $this->helper->hasAttributeExclusions($matches[0][0], $this->temp_content) ) { return $matches[0]; } - } - if ( isset($matches[0]) ) { + // check if in script + if ( $this->helper->isInsideScriptTag($matches[0][0], $this->temp_content) ) { + return $matches[0]; + } + return $this->encodeAny( $matches[0], $this->global_obfuscation_mode, From 673bdb157faa8b3e3df72003c2171676fbb1ce65 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:15:53 +0300 Subject: [PATCH 06/11] Refactoring. Code duplication. Unnecessary method `encodeMailtoLinkV2` removed. --- ContactsEncoder.php | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 562facb..1f5697a 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -494,39 +494,6 @@ private function encodeMailtoLink($mailto_link_str) return 'mailto:' . $text . '" data-original-string="' . $encoded . '" title="' . htmlspecialchars($this->getTooltip(), ENT_QUOTES, 'UTF-8'); } - /** - * Method to process mailto: links. Use this only for PHP 7.4+ - * - * @param $match array - * @param $content string - * - * @return string - */ - private function encodeMailtoLinkV2($match, $content) - { - $position = $match[1]; - $q_position = $position + strcspn($content, '\'"', $position); - $mailto_link_str = substr($content, $position, $q_position - $position); - // Get inner tag text and place it in $matches[1] - preg_match($this->global_mailto_pattern, $mailto_link_str, $matches); - if ( isset($matches[1]) ) { - $mailto_inner_text = preg_replace_callback($this->plain_email_pattern_without_capturing, function ($matches) { - if ( isset($matches[0]) ) { - return $this->getObfuscatedEmailString($matches[0]); - } - - return ''; - }, $matches[1]); - } - - $mailto_link_str = str_replace('mailto:', '', $mailto_link_str); - $encoded = $this->encoder->encodeString($mailto_link_str); - - $text = isset($mailto_inner_text) ? $mailto_inner_text : $mailto_link_str; - - return 'mailto:' . $text . '" data-original-string="' . $encoded . '" title="' . htmlspecialchars($this->getTooltip(), ENT_QUOTES, 'UTF-8'); - } - /** * Method to process tel: links. For PHP < 7.4 * From 312001600a112c795d953cef1d5de943f8f3bd7c Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:16:18 +0300 Subject: [PATCH 07/11] Refactoring. Code duplication. Unnecessary method `encodeTelLinkV2` removed. --- ContactsEncoder.php | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 1f5697a..544f715 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -521,42 +521,6 @@ private function encodeTelLink($tel_link_str) return 'tel:' . $text . '" data-original-string="' . $encoded . '" title="' . htmlspecialchars($this->getTooltip(), ENT_QUOTES, 'UTF-8'); } - /** - * Method to process tel: links. Use this only for PHP 7.4+ - * - * @param array $match - * @param string $content - * - * @return string - */ - private function encodeTelLinkV2($match, $content) - { - $position = !empty($match[1]) ? (int)$match[1] : null; - if (null === $position) { - return $content; - } - $q_position = $position + strcspn($content, '\'"', $position); - $tel_link_string = substr($content, $position, $q_position - $position); - // Get inner tag text and place it in $matches[1] - preg_match($this->global_tel_pattern, $tel_link_string, $matches); - if ( isset($matches[1]) ) { - $tel_inner_text = preg_replace_callback('/' . self::PHONE_NUMBER . '/', function ($matches) { - if ( isset($matches[0]) ) { - $obfuscator = new Obfuscator(); - return $obfuscator->processPhone($matches[0]); - } - return ''; - }, $matches[1]); - } - - $tel_link_string = str_replace('tel:', '', $tel_link_string); - $encoded = $this->encoder->encodeString($tel_link_string); - - $text = isset($tel_inner_text) ? $tel_inner_text : $tel_link_string; - - return 'tel:' . $text . '" data-original-string="' . $encoded . '" title="' . htmlspecialchars($this->getTooltip(), ENT_QUOTES, 'UTF-8'); - } - /** * @param string $email_str * From 0d972ff63ab160364ecc65a0e70826c3061f9fe3 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 14 Aug 2026 16:21:11 +0300 Subject: [PATCH 08/11] Refactoring. Code duplication. Unnecessary property `plain_email_pattern_without_capturing` removed. --- ContactsEncoder.php | 7 ------- tests/ContactsEncoder/TestContactsEncoderPatterns.php | 8 -------- 2 files changed, 15 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 544f715..a8f3964 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -82,12 +82,6 @@ class ContactsEncoder */ protected $plain_email_pattern; - /** - * @var string example: '/\b[_A-Za-z0-9-\.]+@[_A-Za-z0-9-\.]+\.[A-Za-z]{2,}/' - * @ToDo Is this regular expression needed? A little different against `$plain_email_pattern`. - */ - protected $plain_email_pattern_without_capturing; - /** * @var string example: '/tel:(\+\d{8,12})/' * @ToDo Is this regexp is actual and right? @@ -223,7 +217,6 @@ private function prepareRegularExpressions() $this->global_phones_pattern = '/' . implode('|', self::PHONE_NUMBERS_PATTERNS) . '/'; $this->global_mailto_pattern = '/mailto\:(' . self::EMAIL_PATTERN . ')/'; $this->plain_email_pattern = '/(\b' . self::EMAIL_PATTERN . '\b)/'; - $this->plain_email_pattern_without_capturing = '/\b' . self::EMAIL_PATTERN . '/'; $this->global_tel_pattern = '/tel:(' . self::PHONE_NUMBER . ')/'; } diff --git a/tests/ContactsEncoder/TestContactsEncoderPatterns.php b/tests/ContactsEncoder/TestContactsEncoderPatterns.php index ddbad2a..3f784c3 100644 --- a/tests/ContactsEncoder/TestContactsEncoderPatterns.php +++ b/tests/ContactsEncoder/TestContactsEncoderPatterns.php @@ -86,14 +86,6 @@ public function testPlainEmailPatternProperty() $this->assertEquals($expected, $pattern); } - public function testPlainEmailPatternWithoutCapturingProperty() - { - $encoder = $this->createConcreteContactsEncoder($this->getTestParams()); - $pattern = $encoder->getProperty('plain_email_pattern_without_capturing'); - $expected = '/\b[_A-Za-z0-9-\.]+@[_A-Za-z0-9-\.]+\.[A-Za-z]{2,}\b/'; - $this->assertEquals($expected, $pattern); - } - public function testGlobalTelPatternProperty() { $encoder = $this->createConcreteContactsEncoder($this->getTestParams()); From 16f6eb701e667eba73ba1e95244372f4983fb81a Mon Sep 17 00:00:00 2001 From: Glomberg Date: Mon, 17 Aug 2026 11:45:22 +0300 Subject: [PATCH 09/11] Refactoring. Code duplication. Unnecessary method `isEmailInLink` removed. --- ContactsEncoder.php | 6 ------ Helper/ContactsEncoderHelper.php | 28 ---------------------------- 2 files changed, 34 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index a8f3964..5d0a48d 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -312,12 +312,6 @@ public function modifyGlobalEmails($content) return $matches[0]; } - if ( - isset($matches[0]) && $this->helper->isEmailInLink($matches[0], $this->temp_content) - ) { - return $matches[0]; - } - if ( isset($matches[0]) && $this->helper->isMailtoAdditionalCopy($matches[0], $this->temp_content) ) { diff --git a/Helper/ContactsEncoderHelper.php b/Helper/ContactsEncoderHelper.php index 0cdb654..93dcb68 100644 --- a/Helper/ContactsEncoderHelper.php +++ b/Helper/ContactsEncoderHelper.php @@ -72,34 +72,6 @@ public function isMailtoAdditionalCopy($email, $content) return false; } - /** - * Checking if email in link - * - * @param string $email - * @param string $content - * - * @return bool - */ - public function isEmailInLink($email, $content) - { - $position = strpos($content, $email); - if ($position === false) { - return false; - } - - if (null === $position || null === $email) { - return false; - } - - $href_position = strrpos(substr($content, 0, $position), 'href='); - - if ( $href_position !== false && $href_position + 6 == $position ) { - return true; - } - - return strpos($email, 'mailto:') !== false; - } - /** * Check if the given email is inside an option element text (not attributes). * From f7f86212b68f1721d85350c458d1219358d0ea08 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Mon, 17 Aug 2026 11:49:25 +0300 Subject: [PATCH 10/11] Refactoring. Code. Method `modifyGlobalPhoneNumbers` logic fixed. --- ContactsEncoder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index 5d0a48d..ee28dc5 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -363,12 +363,12 @@ function ($matches) { } // check attribute exclusions - if ( $this->helper->hasAttributeExclusions($matches[0][0], $this->temp_content) ) { + if ( $this->helper->hasAttributeExclusions($matches[0], $this->temp_content) ) { return $matches[0]; } // check if in script - if ( $this->helper->isInsideScriptTag($matches[0][0], $this->temp_content) ) { + if ( $this->helper->isInsideScriptTag($matches[0], $this->temp_content) ) { return $matches[0]; } From 415fe948321e0c737890ea2dfa3152494aa4b192 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Mon, 17 Aug 2026 11:50:41 +0300 Subject: [PATCH 11/11] Refactoring. Code. DocBlocks fixed. --- ContactsEncoder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ContactsEncoder.php b/ContactsEncoder.php index ee28dc5..8b91e9d 100644 --- a/ContactsEncoder.php +++ b/ContactsEncoder.php @@ -456,7 +456,7 @@ protected function encodeAny($string, $mode = Params::OBFUSCATION_MODE_BLUR, $re } /** - * Method to process mailto: links. For PHP < 7.4 + * Method to process mailto: links. * * @param string $mailto_link_str * @@ -482,7 +482,7 @@ private function encodeMailtoLink($mailto_link_str) } /** - * Method to process tel: links. For PHP < 7.4 + * Method to process tel: links. * * @param string $tel_link_str *