From 702624b9592d9638bdc595201464bfc6dbeaba96 Mon Sep 17 00:00:00 2001
From: Tomas Votruba <tomas.vot@gmail.com>
Date: Thu, 8 Aug 2019 11:07:15 +0200
Subject: [PATCH] simplify ManualJsonStringToJsonEncodeArrayRector

---
 .../CodingStyle/src/Node/ConcatJoiner.php     |  2 +-
 ...anualJsonStringToJsonEncodeArrayRector.php | 61 +++++++++++--------
 .../Fixture/array_concat.php.inc              | 30 +++++++++
 ...lJsonStringToJsonEncodeArrayRectorTest.php |  1 +
 4 files changed, 69 insertions(+), 25 deletions(-)
 create mode 100644 packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/Fixture/array_concat.php.inc

diff --git a/packages/CodingStyle/src/Node/ConcatJoiner.php b/packages/CodingStyle/src/Node/ConcatJoiner.php
index 7ac9ab08788..1c4fe066cb7 100644
--- a/packages/CodingStyle/src/Node/ConcatJoiner.php
+++ b/packages/CodingStyle/src/Node/ConcatJoiner.php
@@ -44,7 +44,7 @@ final class ConcatJoiner
         } elseif ($expr instanceof Concat) {
             $this->joinToStringAndPlaceholderNodes($expr);
         } else {
-            $objectHash = spl_object_hash($expr);
+            $objectHash = '____' . spl_object_hash($expr) . '____';
             $this->placeholderNodes[$objectHash] = $expr;
 
             $this->content .= $objectHash;
diff --git a/packages/CodingStyle/src/Rector/String_/ManualJsonStringToJsonEncodeArrayRector.php b/packages/CodingStyle/src/Rector/String_/ManualJsonStringToJsonEncodeArrayRector.php
index 3eaff9a9985..874f52ed7fe 100644
--- a/packages/CodingStyle/src/Rector/String_/ManualJsonStringToJsonEncodeArrayRector.php
+++ b/packages/CodingStyle/src/Rector/String_/ManualJsonStringToJsonEncodeArrayRector.php
@@ -103,21 +103,13 @@ CODE_SAMPLE
             $concatExpressionJoinData = $this->collectContentAndPlaceholderNodesFromNextExpressions($node);
 
             $stringValue .= $concatExpressionJoinData->getString();
-            if (! $this->isJsonString($stringValue)) {
-                return null;
-            }
 
-            // remove nodes
-            $this->removeNodes($concatExpressionJoinData->getNodesToRemove());
-
-            $jsonArray = $this->createArrayNodeFromJsonString($stringValue);
-
-            $this->replaceNodeObjectHashPlaceholdersWithNodes(
-                $jsonArray,
-                $concatExpressionJoinData->getPlaceholdersToNodes()
+            return $this->removeNodesAndCreateJsonEncodeFromStringValue(
+                $concatExpressionJoinData->getNodesToRemove(),
+                $stringValue,
+                $concatExpressionJoinData->getPlaceholdersToNodes(),
+                $node
             );
-
-            return $this->createAndReturnJsonEncodeFromArray($node, $jsonArray);
         }
 
         if ($node->expr instanceof Concat) {
@@ -137,16 +129,12 @@ CODE_SAMPLE
             /** @var string $stringValue */
             $stringValue .= $concatExpressionJoinData->getString();
 
-            if (! $this->isJsonString($stringValue)) {
-                return null;
-            }
-
-            $jsonArray = $this->createArrayNodeFromJsonString($stringValue);
-            $this->replaceNodeObjectHashPlaceholdersWithNodes($jsonArray, $placeholderNodes);
-
-            $this->removeNodes($concatExpressionJoinData->getNodesToRemove());
-
-            return $this->createAndReturnJsonEncodeFromArray($node, $jsonArray);
+            return $this->removeNodesAndCreateJsonEncodeFromStringValue(
+                $concatExpressionJoinData->getNodesToRemove(),
+                $stringValue,
+                $placeholderNodes,
+                $node
+            );
         }
 
         return null;
@@ -290,7 +278,8 @@ CODE_SAMPLE
                     $concatExpressionJoinData->addPlaceholderToNode($placeholder, $expr);
                 }
             } elseif ($valueNode instanceof Expr) {
-                $objectHash = spl_object_hash($valueNode);
+                $objectHash = '____' . spl_object_hash($valueNode) . '____';
+
                 $concatExpressionJoinData->addString($objectHash);
                 $concatExpressionJoinData->addPlaceholderToNode($objectHash, $valueNode);
             }
@@ -345,4 +334,28 @@ CODE_SAMPLE
 
         return $placeholderNodes[$node->value] ?? null;
     }
+
+    /**
+     * @param Node[] $nodesToRemove
+     * @param Expr[] $placeholderNodes
+     */
+    private function removeNodesAndCreateJsonEncodeFromStringValue(
+        array $nodesToRemove,
+        string $stringValue,
+        array $placeholderNodes,
+        Assign $assign
+    ): ?Assign {
+        // quote object hashes if needed - https://regex101.com/r/85PZHm/1
+        $stringValue = Strings::replace($stringValue, '#(?<start>[^\"])(?<hash>____\w+____)#', '$1"$2"');
+        if (! $this->isJsonString($stringValue)) {
+            return null;
+        }
+
+        $this->removeNodes($nodesToRemove);
+
+        $jsonArray = $this->createArrayNodeFromJsonString($stringValue);
+        $this->replaceNodeObjectHashPlaceholdersWithNodes($jsonArray, $placeholderNodes);
+
+        return $this->createAndReturnJsonEncodeFromArray($assign, $jsonArray);
+    }
 }
diff --git a/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/Fixture/array_concat.php.inc b/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/Fixture/array_concat.php.inc
new file mode 100644
index 00000000000..e45cf55d731
--- /dev/null
+++ b/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/Fixture/array_concat.php.inc
@@ -0,0 +1,30 @@
+<?php
+
+namespace Rector\CodingStyle\Tests\Rector\String_\ManualJsonStringToJsonEncodeArrayRector\Fixture;
+
+final class ArrayConcat
+{
+    public function run()
+    {
+        $json = '{"due_date_days":14,"billing_address":' . '{"name":"A","address":"B","city":"C",';
+        $json .= '"zip":"180 00"},"administrators":' . 5;
+        $json .= ',"settings":['. 3 .','. 4 .']}';
+    }
+}
+
+?>
+-----
+<?php
+
+namespace Rector\CodingStyle\Tests\Rector\String_\ManualJsonStringToJsonEncodeArrayRector\Fixture;
+
+final class ArrayConcat
+{
+    public function run()
+    {
+        $jsonData = ['due_date_days' => 14, 'billing_address' => ['name' => 'A', 'address' => 'B', 'city' => 'C', 'zip' => '180 00'], 'administrators' => 5, 'settings' => [3, 4]];
+        $json = \Nette\Utils\Json::encode($jsonData);
+    }
+}
+
+?>
diff --git a/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/ManualJsonStringToJsonEncodeArrayRectorTest.php b/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/ManualJsonStringToJsonEncodeArrayRectorTest.php
index 8fd22be576a..c961d329c74 100644
--- a/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/ManualJsonStringToJsonEncodeArrayRectorTest.php
+++ b/packages/CodingStyle/tests/Rector/String_/ManualJsonStringToJsonEncodeArrayRector/ManualJsonStringToJsonEncodeArrayRectorTest.php
@@ -17,6 +17,7 @@ final class ManualJsonStringToJsonEncodeArrayRectorTest extends AbstractRectorTe
             __DIR__ . '/Fixture/assign_with_concat.php.inc',
             __DIR__ . '/Fixture/with_implode.php.inc',
             __DIR__ . '/Fixture/without_assign.php.inc',
+            __DIR__ . '/Fixture/array_concat.php.inc',
         ]);
     }