Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class PostgresArrayToPHPArrayTransformerTest extends TestCase
#[Test]
public function can_transform_to_php_value(array $phpValue, string $postgresValue): void
{
self::assertEquals($phpValue, PostgresArrayToPHPArrayTransformer::transformPostgresArrayToPHPArray($postgresValue));
self::assertEquals($phpValue, PostgresArrayToPHPArrayTransformer::transformPostgresArrayToPHPArray($postgresValue), 'V3 values not equal');
self::assertEquals($phpValue, $this->transformPostgresTextArrayToPHPArray($postgresValue), 'V2 values not equal');
}

/**
Expand Down Expand Up @@ -142,9 +143,13 @@ public static function provideValidTransformations(): array
'phpValue' => ['', ''],
'postgresValue' => '{"",""}',
],
'github #351 regression: string with special characters and backslash' => [
'phpValue' => ["!@#\\$%^&*()_+=-}{[]|\":;'\\?><,./"],
'postgresValue' => '{"!@#\$%^&*()_+=-}{[]|\":;\'\?><,./"}',
'github #351 regression #1: string with special characters and backslash' => [
'phpValue' => ['⥀!@#$%^&*()_+=-}{[]|":;\'\?><,./'],
'postgresValue' => '{"⥀!@#$%^&*()_+=-}{[]|\":;\'\\?><,./"}',
],
'github #351 regression #2: string with special characters, backslash and additional element' => [
'phpValue' => ['⥀!@#$%^&*()_+=-}{[]|":;\'\?><,./', 'text'],
'postgresValue' => '{"⥀!@#$%^&*()_+=-}{[]|\":;\'\\?><,./",text}',
],
'backslash before backslash' => [
'phpValue' => ['a\b'],
Expand Down Expand Up @@ -254,4 +259,45 @@ public static function provideInvalidPostgresArrays(): array
],
];
}

// function from v2.10.3
private static function transformPostgresTextArrayToPHPArray(string $postgresArray): array
{
$transform = static function (string $textArrayToTransform): array {
$indicatesMultipleDimensions = \mb_strpos($textArrayToTransform, '},{') !== false
|| \mb_strpos($textArrayToTransform, '{{') === 0;
if ($indicatesMultipleDimensions) {
throw new \InvalidArgumentException('Only single-dimensioned arrays are supported');
}

$phpArray = \str_getcsv(\trim($textArrayToTransform, '{}'), escape: '\\');
foreach ($phpArray as $i => $text) {
if ($text === null) {
unset($phpArray[$i]);

break;
}

$isInteger = \is_numeric($text) && ''.(int) $text === $text;
if ($isInteger) {
$phpArray[$i] = (int) $text;

continue;
}

$isFloat = \is_numeric($text) && ''.(float) $text === $text;
if ($isFloat) {
$phpArray[$i] = (float) $text;

continue;
}

$phpArray[$i] = \stripslashes(\str_replace('\"', '"', $text));
}

return $phpArray;
};

return $transform($postgresArray);
}
Comment on lines +263 to +302
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical issues in the legacy transformation method implementation.

The legacy method has several problems that will cause test failures and incorrect behavior:

  1. Logic error with null handling: The break statement on line 278 will terminate processing after the first element if any element is null, leaving subsequent elements unprocessed.

  2. Inconsistent exception type: Uses \InvalidArgumentException instead of InvalidArrayFormatException used elsewhere in the codebase.

  3. Missing type conversions: Doesn't handle boolean values (true, false, t, f) or null string conversion (NULL, null) like the V3 transformer does.

  4. Unnecessary complexity: The closure wrapper adds no value and makes the code harder to read.

Apply this diff to fix the critical issues:

-    // function from v2.10.3
-    private static function transformPostgresTextArrayToPHPArray(string $postgresArray): array
-    {
-        $transform = static function (string $textArrayToTransform): array {
-            $indicatesMultipleDimensions = \mb_strpos($textArrayToTransform, '},{') !== false
-                || \mb_strpos($textArrayToTransform, '{{') === 0;
-            if ($indicatesMultipleDimensions) {
-                throw new \InvalidArgumentException('Only single-dimensioned arrays are supported');
-            }
-
-            $phpArray = \str_getcsv(\trim($textArrayToTransform, '{}'), escape: '\\');
-            foreach ($phpArray as $i => $text) {
-                if ($text === null) {
-                    unset($phpArray[$i]);
-
-                    break;
-                }
-
-                $isInteger = \is_numeric($text) && ''.(int) $text === $text;
-                if ($isInteger) {
-                    $phpArray[$i] = (int) $text;
-
-                    continue;
-                }
-
-                $isFloat = \is_numeric($text) && ''.(float) $text === $text;
-                if ($isFloat) {
-                    $phpArray[$i] = (float) $text;
-
-                    continue;
-                }
-
-                $phpArray[$i] = \stripslashes(\str_replace('\"', '"', $text));
-            }
-
-            return $phpArray;
-        };
-
-        return $transform($postgresArray);
-    }
+    // function from v2.10.3
+    private static function transformPostgresTextArrayToPHPArray(string $postgresArray): array
+    {
+        $indicatesMultipleDimensions = \mb_strpos($postgresArray, '},{') !== false
+            || \mb_strpos($postgresArray, '{{') === 0;
+        if ($indicatesMultipleDimensions) {
+            throw new InvalidArrayFormatException('Only single-dimensioned arrays are supported');
+        }
+
+        $phpArray = \str_getcsv(\trim($postgresArray, '{}'), escape: '\\');
+        foreach ($phpArray as $i => $text) {
+            // Handle null values
+            if (\in_array(\strtolower($text), ['null', ''], true)) {
+                $phpArray[$i] = null;
+                continue;
+            }
+
+            // Handle boolean values
+            if (\in_array(\strtolower($text), ['true', 't'], true)) {
+                $phpArray[$i] = true;
+                continue;
+            }
+            if (\in_array(\strtolower($text), ['false', 'f'], true)) {
+                $phpArray[$i] = false;
+                continue;
+            }
+
+            $isInteger = \is_numeric($text) && ''.(int) $text === $text;
+            if ($isInteger) {
+                $phpArray[$i] = (int) $text;
+                continue;
+            }
+
+            $isFloat = \is_numeric($text) && ''.(float) $text === $text;
+            if ($isFloat) {
+                $phpArray[$i] = (float) $text;
+                continue;
+            }
+
+            $phpArray[$i] = \stripslashes(\str_replace('\"', '"', $text));
+        }
+
+        return $phpArray;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// function from v2.10.3
private static function transformPostgresTextArrayToPHPArray(string $postgresArray): array
{
$transform = static function (string $textArrayToTransform): array {
$indicatesMultipleDimensions = \mb_strpos($textArrayToTransform, '},{') !== false
|| \mb_strpos($textArrayToTransform, '{{') === 0;
if ($indicatesMultipleDimensions) {
throw new \InvalidArgumentException('Only single-dimensioned arrays are supported');
}
$phpArray = \str_getcsv(\trim($textArrayToTransform, '{}'), escape: '\\');
foreach ($phpArray as $i => $text) {
if ($text === null) {
unset($phpArray[$i]);
break;
}
$isInteger = \is_numeric($text) && ''.(int) $text === $text;
if ($isInteger) {
$phpArray[$i] = (int) $text;
continue;
}
$isFloat = \is_numeric($text) && ''.(float) $text === $text;
if ($isFloat) {
$phpArray[$i] = (float) $text;
continue;
}
$phpArray[$i] = \stripslashes(\str_replace('\"', '"', $text));
}
return $phpArray;
};
return $transform($postgresArray);
}
// function from v2.10.3
private static function transformPostgresTextArrayToPHPArray(string $postgresArray): array
{
$indicatesMultipleDimensions = \mb_strpos($postgresArray, '},{') !== false
|| \mb_strpos($postgresArray, '{{') === 0;
if ($indicatesMultipleDimensions) {
throw new InvalidArrayFormatException('Only single-dimensioned arrays are supported');
}
$phpArray = \str_getcsv(\trim($postgresArray, '{}'), escape: '\\');
foreach ($phpArray as $i => $text) {
// Handle null values
if (\in_array(\strtolower($text), ['null', ''], true)) {
$phpArray[$i] = null;
continue;
}
// Handle boolean values
if (\in_array(\strtolower($text), ['true', 't'], true)) {
$phpArray[$i] = true;
continue;
}
if (\in_array(\strtolower($text), ['false', 'f'], true)) {
$phpArray[$i] = false;
continue;
}
$isInteger = \is_numeric($text) && ''.(int) $text === $text;
if ($isInteger) {
$phpArray[$i] = (int) $text;
continue;
}
$isFloat = \is_numeric($text) && ''.(float) $text === $text;
if ($isFloat) {
$phpArray[$i] = (float) $text;
continue;
}
$phpArray[$i] = \stripslashes(\str_replace('\"', '"', $text));
}
return $phpArray;
}
🤖 Prompt for AI Agents
In tests/Unit/MartinGeorgiev/Utils/PostgresArrayToPHPArrayTransformerTest.php
between lines 263 and 302, fix the legacy transformPostgresTextArrayToPHPArray
method by removing the break statement that prematurely stops processing on null
elements, replace the \InvalidArgumentException with InvalidArrayFormatException
for consistency, add handling to convert boolean string values ('true', 'false',
't', 'f') and null strings ('NULL', 'null') to their proper PHP types, and
eliminate the unnecessary closure wrapper to simplify the code structure.

}