]> git.mxchange.org Git - friendica.git/commitdiff
Add new Strings::substringReplace method
authorHypolite Petovan <hypolite@mrpetovan.com>
Mon, 30 Mar 2020 05:57:10 +0000 (01:57 -0400)
committerHypolite Petovan <hypolite@mrpetovan.com>
Mon, 30 Mar 2020 14:49:53 +0000 (10:49 -0400)
- Add tests for the method

src/Util/Strings.php
tests/src/Util/StringsTest.php

index c520b54b9ba508f1aaaa42331585c6d92ee5dc25..3dd91193d2cc98501f0717f13f31307e527c53e9 100644 (file)
@@ -420,4 +420,42 @@ class Strings
 
                return $pathItem;
        }
+
+       /**
+        * Multi-byte safe implementation of substr_replace where $start and $length are character offset and count rather
+        * than byte offset and counts.
+        *
+        * Depends on mbstring, use default encoding.
+        *
+        * @param string   $string
+        * @param string   $replacement
+        * @param int      $start
+        * @param int|null $length
+        * @return string
+        * @see substr_replace()
+        */
+       public static function substringReplace(string $string, string $replacement, int $start, int $length = null)
+       {
+               $string_length = mb_strlen($string);
+
+               $length = $length ?? $string_length;
+
+               if ($start < 0) {
+                       $start = max(0, $string_length + $start);
+               } else if ($start > $string_length) {
+                       $start = $string_length;
+               }
+
+               if ($length < 0) {
+                       $length = max(0, $string_length - $start + $length);
+               } else if ($length > $string_length) {
+                       $length = $string_length;
+               }
+
+               if (($start + $length) > $string_length) {
+                       $length = $string_length - $start;
+               }
+
+               return mb_substr($string, 0, $start) . $replacement . mb_substr($string, $start + $length, $string_length - $start - $length);
+       }
 }
index 86280cc5f126a974ef30a4be3b0a4f4656583ee6..66fb2f0f53466d3be9595e56356c4704687ad550 100644 (file)
@@ -134,4 +134,64 @@ class StringsTest extends TestCase
        {
                $this->assertEquals($valid, Strings::isHex($input));
        }
+
+       /**
+        * Tests that Strings::substringReplace behaves the same as substr_replace with ASCII strings in all the possible
+        * numerical parameter configurations (positive, negative, zero, out of bounds either side, null)
+        */
+       public function testSubstringReplaceASCII()
+       {
+               for ($start = -10; $start <= 10; $start += 5) {
+                       $this->assertEquals(
+                               substr_replace('string', 'replacement', $start),
+                               Strings::substringReplace('string', 'replacement', $start)
+                       );
+
+                       for ($length = -10; $length <= 10; $length += 5) {
+                               $this->assertEquals(
+                                       substr_replace('string', 'replacement', $start, $length),
+                                       Strings::substringReplace('string', 'replacement', $start, $length)
+                               );
+                       }
+               }
+       }
+
+
+       public function dataSubstringReplaceMultiByte()
+       {
+               return [
+                       'issue-8470' => [
+                               'expected' => 'Je n’y pense que maintenant (pask ma sonnette ne fonctionne pas) : mettre un gentil mot avec mes coordonnées sur ma porte est le moyen le plus simple de rester en contact si besoin avec mon voisinage direct ! [url=https://www.instagram.com/p/B-UdH2loee1/?igshid=x4aglyju9kva]instagram.com/p/B-UdH2loee1/…[/url] [rest of the post]',
+                               'string' => 'Je n’y pense que maintenant (pask ma sonnette ne fonctionne pas) : mettre un gentil mot avec mes coordonnées sur ma porte est le moyen le plus simple de rester en contact si besoin avec mon voisinage direct ! https://t.co/YoBWTHsAAk [rest of the post]',
+                               'replacement' => '[url=https://www.instagram.com/p/B-UdH2loee1/?igshid=x4aglyju9kva]instagram.com/p/B-UdH2loee1/…[/url]',
+                               'start' => 209,
+                               'length' => 23,
+                       ],
+               ];
+       }
+
+       /**
+        * Tests cases where Strings::substringReplace is needed over substr_replace with multi-byte strings and character
+        * offsets
+        *
+        * @param string   $expected
+        * @param string   $string
+        * @param string   $replacement
+        * @param int      $start
+        * @param int|null $length
+        *
+        * @dataProvider dataSubstringReplaceMultiByte
+        */
+       public function testSubstringReplaceMultiByte(string $expected, string $string, string $replacement, int $start, int $length = null)
+       {
+               $this->assertEquals(
+                       $expected,
+                       Strings::substringReplace(
+                               $string,
+                               $replacement,
+                               $start,
+                               $length
+                       )
+               );
+       }
 }