Browse Source

Make `\Cake\Utility\Text` accept `\Transliterator` objects.

ndm2 7 years ago
parent
commit
b29fd68a0e
2 changed files with 228 additions and 32 deletions
  1. 80 14
      src/Utility/Text.php
  2. 148 18
      tests/TestCase/Utility/TextTest.php

+ 80 - 14
src/Utility/Text.php

@@ -25,9 +25,18 @@ class Text
     /**
      * Default transliterator id string.
      *
-     * @param string $_defaultTransliteratorId Transliterator identifier string.
+     * @deprecated 3.7.0 Use $_defaultTransliterator instead.
+     * @var string $_defaultTransliteratorId Transliterator identifier string.
      */
-    protected static $_defaultTransliteratorId = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
+    protected static $_defaultTransliteratorId;
+
+    /**
+     * Default transliterator.
+     *
+     * @var \Transliterator|string Either a Transliterator instance, or a
+     *   transliterator identifier string.
+     */
+    protected static $_defaultTransliterator = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
 
     /**
      * Default html tags who must not be count for truncate text.
@@ -1054,38 +1063,86 @@ class Text
     /**
      * Get default transliterator identifier string.
      *
+     * @deprecated 3.7.0 Use getTransliterator() instead.
      * @return string Transliterator identifier.
      */
     public static function getTransliteratorId()
     {
-        return static::$_defaultTransliteratorId;
+        deprecationWarning(
+            'Text::getTransliteratorId() is deprecated. ' .
+            'Use Text::getTransliterator() instead.'
+        );
+
+        return static::getTransliterator();
     }
 
     /**
      * Set default transliterator identifier string.
      *
+     * @deprecated 3.7.0 Use setTransliterator() instead.
      * @param string $transliteratorId Transliterator identifier.
      * @return void
      */
     public static function setTransliteratorId($transliteratorId)
     {
-        static::$_defaultTransliteratorId = $transliteratorId;
+        deprecationWarning(
+            'Text::setTransliteratorId() is deprecated. ' .
+            'Use Text::setTransliterator() instead.'
+        );
+
+        static::setTransliterator($transliteratorId);
+    }
+
+    /**
+     * Get the default transliterator.
+     *
+     * @return \Transliterator|string Either a Transliterator instance, or a
+     *   transliterator identifier string.
+     * @since 3.7.0
+     */
+    public static function getTransliterator()
+    {
+        return static::$_defaultTransliterator;
+    }
+
+    /**
+     * Set default transliterator identifier string.
+     *
+     * @param \Transliterator|string $transliterator Either a Transliterator
+     *   instance, or a transliterator identifier string.
+     * @return void
+     * @since 3.7.0
+     */
+    public static function setTransliterator($transliterator)
+    {
+        static::$_defaultTransliterator = $transliterator;
     }
 
     /**
      * Transliterate string.
      *
      * @param string $string String to transliterate.
-     * @param string|null $transliteratorId Transliterator identifier. If null
-     *   Text::$_defaultTransliteratorId will be used.
+     * @param \Transliterator|string|null $transliterator Either a Transliterator
+     *   instance, or a transliterator identifier string. If `null`
+     *   `Text::$_defaultTransliterator` will be used.
      * @return string
      * @see https://secure.php.net/manual/en/transliterator.transliterate.php
      */
-    public static function transliterate($string, $transliteratorId = null)
+    public static function transliterate($string, $transliterator = null)
     {
-        $transliteratorId = $transliteratorId ?: static::$_defaultTransliteratorId;
+        if (!$transliterator) {
+            if (static::$_defaultTransliteratorId !== null) {
+                deprecationWarning(
+                    '`Text::$_defaultTransliteratorId` is deprecated. ' .
+                    'Use `Text::$_defaultTransliterator` instead.'
+                );
+                $transliterator = static::$_defaultTransliteratorId;
+            } else {
+                $transliterator = static::$_defaultTransliterator;
+            }
+        }
 
-        return transliterator_transliterate($transliteratorId, $string);
+        return transliterator_transliterate($transliterator, $string);
     }
 
     /**
@@ -1095,9 +1152,11 @@ class Text
      * ### Options:
      *
      * - `replacement`: Replacement string. Default '-'.
-     * - `transliteratorId`: A valid tranliterator id string.
-     *   If default `null` Text::$_defaultTransliteratorId to be used.
+     * - `transliterator`: A Transliterator instance, or a transliterator id string.
+     *   If `null` (default) `Text::$_defaultTransliterator` will be used.
      *   If `false` no transliteration will be done, only non words will be removed.
+     * - `transliteratorId`: Deprecated as of 3.7.0, use the `transliterator` option
+     *   instead.
      * - `preserve`: Specific non-word character to preserve. Default `null`.
      *   For e.g. this option can be set to '.' to generate clean file names.
      *
@@ -1113,12 +1172,19 @@ class Text
         }
         $options += [
             'replacement' => '-',
-            'transliteratorId' => null,
+            'transliterator' => null,
             'preserve' => null
         ];
 
-        if ($options['transliteratorId'] !== false) {
-            $string = static::transliterate($string, $options['transliteratorId']);
+        if (array_key_exists('transliteratorId', $options)) {
+            deprecationWarning(
+                'The `transliteratorId` option is deprecated. ' .
+                'Use `transliterator` instead.'
+            );
+            $options['transliterator'] = $options['transliteratorId'];
+        }
+        if ($options['transliterator'] !== false) {
+            $string = static::transliterate($string, $options['transliterator']);
         }
 
         $regex = '^\s\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}';

+ 148 - 18
tests/TestCase/Utility/TextTest.php

@@ -18,6 +18,14 @@ use Cake\TestSuite\TestCase;
 use Cake\Utility\Text;
 
 /**
+ * Helper class that assists with testing overloading of a deprecated property.
+ */
+class TextOverloadDeprecatedTransliteratorIdProperty extends Text
+{
+    protected static $_defaultTransliteratorId = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
+}
+
+/**
  * TextTest class
  */
 class TextTest extends TestCase
@@ -1685,16 +1693,44 @@ HTML;
      *
      * @return void
      */
-    public function testGetSetTransliteratorId()
+    public function testDeprecatedGetSetTransliteratorId()
     {
-        $defaultTransliteratorId = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
-        $this->assertEquals($defaultTransliteratorId, Text::getTransliteratorId());
+        $this->deprecated(function () {
+            $defaultTransliteratorId = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
+            $this->assertEquals($defaultTransliteratorId, Text::getTransliteratorId());
 
-        $expected = 'Latin-ASCII; [\u0080-\u7fff] remove';
-        Text::setTransliteratorId($expected);
-        $this->assertEquals($expected, Text::getTransliteratorId());
+            $expected = 'Latin-ASCII; [\u0080-\u7fff] remove';
+            Text::setTransliteratorId($expected);
+            $this->assertEquals($expected, Text::getTransliteratorId());
 
-        Text::setTransliteratorId($defaultTransliteratorId);
+            Text::setTransliteratorId($defaultTransliteratorId);
+        });
+    }
+
+    /**
+     * Test getting/setting default transliterator.
+     *
+     * @return void
+     */
+    public function testGetSetTransliterator()
+    {
+        $defaultTransliterator = 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove';
+        $this->assertEquals($defaultTransliterator, Text::getTransliterator());
+
+        $expected = 'Latin-ASCII; [\u0080-\u7fff] remove';
+        Text::setTransliterator($expected);
+        $this->assertEquals($expected, Text::getTransliterator());
+
+        $transliterator = \Transliterator::createFromRules('
+            $nonletter = [:^Letter:];
+            $nonletter → \'*\';
+            ::Latin-ASCII;
+        ');
+        $this->assertInstanceOf(\Transliterator::class, $transliterator);
+        Text::setTransliterator($transliterator);
+        $this->assertSame($transliterator, Text::getTransliterator());
+
+        Text::setTransliterator($defaultTransliterator);
     }
 
     /**
@@ -1748,17 +1784,35 @@ HTML;
      * testTransliterate method
      *
      * @param string $string String
-     * @param string $transliteratorId Transliterator Id
-     * @param String $expected Exepected string
+     * @param \Transliterator|string|null $transliterator Transliterator
+     * @param String $expected Expected string
      * @return void
      * @dataProvider transliterateInputProvider
      */
-    public function testTransliterate($string, $transliteratorId, $expected)
+    public function testTransliterate($string, $transliterator, $expected)
     {
-        $result = Text::transliterate($string, $transliteratorId);
+        $result = Text::transliterate($string, $transliterator);
         $this->assertEquals($expected, $result);
     }
 
+    /**
+     * testTransliterateOverloadDeprecatedTransliteratorIdProperty method
+     *
+     * Tests that extending classes that overload the deprecated `$_defaultTransliteratorId`
+     * property still work as expected, and trigger a deprecation notice.
+     *
+     * @return void
+     */
+    public function testTransliterateOverloadDeprecatedTransliteratorIdProperty()
+    {
+        $this->deprecated(function () {
+            $this->assertEquals(
+                'ringo',
+                TextOverloadDeprecatedTransliteratorIdProperty::transliterate('りんご')
+            );
+        });
+    }
+
     public function slugInputProvider()
     {
         return [
@@ -1779,12 +1833,29 @@ HTML;
                 'A-ae-Ubermensch-pa-hoyeste-niva-I-a-lublu-PHP-est-fi'
             ],
             [
-                'A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. fi ¦', ['transliteratorId' => 'Latin-ASCII'],
+                'A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. fi ¦', ['transliterator' => 'Latin-ASCII'],
                 'A-ae-Ubermensch-pa-hoyeste-niva-И-я-люблю-PHP-есть-fi'
             ],
             [
-                'Äpfel Über Öl grün ärgert groß öko', [],
-                'Apfel-Uber-Ol-grun-argert-gross-oko'
+                'Äpfel Über Öl grün ärgert groß öko',
+                [
+                    'transliterator' => \Transliterator::createFromRules('
+                        $AE = [Ä {A \u0308}];
+                        $OE = [Ö {O \u0308}];
+                        $UE = [Ü {U \u0308}];
+                        [ä {a \u0308}] → ae;
+                        [ö {o \u0308}] → oe;
+                        [ü {u \u0308}] → ue;
+                        {$AE} [:Lowercase:] → Ae;
+                        {$OE} [:Lowercase:] → Oe;
+                        {$UE} [:Lowercase:] → Ue;
+                        $AE → AE;
+                        $OE → OE;
+                        $UE → UE;
+                        ::Latin-ASCII;
+                    '),
+                ],
+                'Aepfel-Ueber-Oel-gruen-aergert-gross-oeko'
             ],
             [
                 'The truth - and- more- news', [],
@@ -1811,15 +1882,15 @@ HTML;
                 'this-melts-your-face1-2-3'
             ],
             [
-                'controller/action/りんご/1', ['transliteratorId' => false],
+                'controller/action/りんご/1', ['transliterator' => false],
                 'controller-action-りんご-1'
             ],
             [
-                'の話が出たので大丈夫かなあと', ['transliteratorId' => false],
+                'の話が出たので大丈夫かなあと', ['transliterator' => false],
                 'の話が出たので大丈夫かなあと'
             ],
             [
-                'posts/view/한국어/page:1/sort:asc', ['transliteratorId' => false],
+                'posts/view/한국어/page:1/sort:asc', ['transliterator' => false],
                 'posts-view-한국어-page-1-sort-asc'
             ],
             [
@@ -1850,7 +1921,7 @@ HTML;
      *
      * @param string $string String
      * @param array $options Options
-     * @param String $expected Exepected string
+     * @param String $expected Expected string
      * @return void
      * @dataProvider slugInputProvider
      */
@@ -1860,6 +1931,65 @@ HTML;
         $this->assertEquals($expected, $result);
     }
 
+    public function slugDeprecatedTransliteratorIdOptionInputProvider()
+    {
+        return [
+            [
+                'A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. fi ¦',
+                ['transliteratorId' => 'Latin-ASCII'],
+                'A-ae-Ubermensch-pa-hoyeste-niva-И-я-люблю-PHP-есть-fi'
+            ],
+            [
+                'Äpfel Über Öl grün ärgert groß öko',
+                [
+                    'transliterator' => \Transliterator::createFromRules('
+                        $AE = [Ä {A \u0308}];
+                        $OE = [Ö {O \u0308}];
+                        $UE = [Ü {U \u0308}];
+                        [ä {a \u0308}] → ae;
+                        [ö {o \u0308}] → oe;
+                        [ü {u \u0308}] → ue;
+                        {$AE} [:Lowercase:] → Ae;
+                        {$OE} [:Lowercase:] → Oe;
+                        {$UE} [:Lowercase:] → Ue;
+                        $AE → AE;
+                        $OE → OE;
+                        $UE → UE;
+                        ::Latin-ASCII;
+                    '),
+                ],
+                'Aepfel-Ueber-Oel-gruen-aergert-gross-oeko'
+            ],
+            [
+                'controller/action/りんご/1',
+                ['transliteratorId' => false],
+                'controller-action-りんご-1'
+            ],
+            [
+                'cl#ean(me',
+                ['transliteratorId' => null],
+                'cl-ean-me'
+            ]
+        ];
+    }
+
+    /**
+     * testSlugDeprecatedTransliteratorIdOption method
+     *
+     * @param string $string String
+     * @param array $options Options
+     * @param String $expected Expected string
+     * @return void
+     * @dataProvider slugDeprecatedTransliteratorIdOptionInputProvider
+     */
+    public function testSlugDeprecatedTransliteratorIdOption($string, $options, $expected)
+    {
+        $this->deprecated(function () use ($string, $options, $expected) {
+            $result = Text::slug($string, $options);
+            $this->assertEquals($expected, $result);
+        });
+    }
+
     /**
      * Text truncateByWidth method
      *