Browse Source

minor: Add `Util::naturalLanguageJoin()` (#7022)

John Paul E. Balandan, CPA 1 year ago
parent
commit
5d795a0e90
2 changed files with 112 additions and 4 deletions
  1. 20 4
      src/Utils.php
  2. 92 0
      tests/UtilsTest.php

+ 20 - 4
src/Utils.php

@@ -122,20 +122,24 @@ final class Utils
     }
 
     /**
-     * Join names in natural language wrapped in backticks, e.g. `a`, `b` and `c`.
+     * Join names in natural language using specified wrapper (double quote by default).
      *
      * @param string[] $names
      *
      * @throws \InvalidArgumentException
      */
-    public static function naturalLanguageJoinWithBackticks(array $names): string
+    public static function naturalLanguageJoin(array $names, string $wrapper = '"'): string
     {
         if (0 === \count($names)) {
             throw new \InvalidArgumentException('Array of names cannot be empty.');
         }
 
-        $names = array_map(static function (string $name): string {
-            return sprintf('`%s`', $name);
+        if (\strlen($wrapper) > 1) {
+            throw new \InvalidArgumentException('Wrapper should be a single-char string or empty.');
+        }
+
+        $names = array_map(static function (string $name) use ($wrapper): string {
+            return sprintf('%2$s%1$s%2$s', $name, $wrapper);
         }, $names);
 
         $last = array_pop($names);
@@ -147,6 +151,18 @@ final class Utils
         return $last;
     }
 
+    /**
+     * Join names in natural language wrapped in backticks, e.g. `a`, `b` and `c`.
+     *
+     * @param string[] $names
+     *
+     * @throws \InvalidArgumentException
+     */
+    public static function naturalLanguageJoinWithBackticks(array $names): string
+    {
+        return self::naturalLanguageJoin($names, '`');
+    }
+
     public static function triggerDeprecation(\Exception $futureException): void
     {
         if (getenv('PHP_CS_FIXER_FUTURE_MODE')) {

+ 92 - 0
tests/UtilsTest.php

@@ -216,6 +216,98 @@ final class UtilsTest extends TestCase
         );
     }
 
+    public function testNaturalLanguageJoinThrowsInvalidArgumentExceptionForEmptyArray(): void
+    {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Array of names cannot be empty.');
+
+        Utils::naturalLanguageJoin([]);
+    }
+
+    public function testNaturalLanguageJoinThrowsInvalidArgumentExceptionForMoreThanOneCharWrapper(): void
+    {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Wrapper should be a single-char string or empty.');
+
+        Utils::naturalLanguageJoin(['a', 'b'], 'foo');
+    }
+
+    /**
+     * @dataProvider provideNaturalLanguageJoinCases
+     *
+     * @param list<string> $names
+     */
+    public function testNaturalLanguageJoin(string $joined, array $names, string $wrapper = '"'): void
+    {
+        self::assertSame($joined, Utils::naturalLanguageJoin($names, $wrapper));
+    }
+
+    /**
+     * @return iterable<array<null|array<string>|string>>
+     */
+    public static function provideNaturalLanguageJoinCases(): iterable
+    {
+        yield from [
+            [
+                '"a"',
+                ['a'],
+            ],
+            [
+                '"a" and "b"',
+                ['a', 'b'],
+            ],
+            [
+                '"a", "b" and "c"',
+                ['a', 'b', 'c'],
+            ],
+            [
+                '\'a\'',
+                ['a'],
+                '\'',
+            ],
+            [
+                '\'a\' and \'b\'',
+                ['a', 'b'],
+                '\'',
+            ],
+            [
+                '\'a\', \'b\' and \'c\'',
+                ['a', 'b', 'c'],
+                '\'',
+            ],
+            [
+                '?a?',
+                ['a'],
+                '?',
+            ],
+            [
+                '?a? and ?b?',
+                ['a', 'b'],
+                '?',
+            ],
+            [
+                '?a?, ?b? and ?c?',
+                ['a', 'b', 'c'],
+                '?',
+            ],
+            [
+                'a',
+                ['a'],
+                '',
+            ],
+            [
+                'a and b',
+                ['a', 'b'],
+                '',
+            ],
+            [
+                'a, b and c',
+                ['a', 'b', 'c'],
+                '',
+            ],
+        ];
+    }
+
     public function testNaturalLanguageJoinWithBackticksThrowsInvalidArgumentExceptionForEmptyArray(): void
     {
         $this->expectException(\InvalidArgumentException::class);