From 56d7c489d18c1194b30216cef4b0b1821d59edcf Mon Sep 17 00:00:00 2001
From: Christopher Georg <christopher.georg@sr-travel.de>
Date: Tue, 14 Nov 2023 16:55:39 +0100
Subject: [PATCH] feat: drop support for PHP <= 7.3

---
 .github/workflows/continuous-integration.yml | 13 +--
 .github/workflows/lint.yml                   |  1 -
 CHANGELOG.md                                 |  4 +
 composer.json                                |  6 +-
 phpunit.xml.dist                             | 18 ++--
 tests/JsonParserTest.php                     | 97 +++++++-------------
 6 files changed, 47 insertions(+), 92 deletions(-)

diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 9e07b88..564d6ae 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -16,18 +16,11 @@ jobs:
     strategy:
       matrix:
         php-version:
-          - "5.3"
-          - "5.4"
-          - "5.5"
-          - "5.6"
-          - "7.0"
-          - "7.1"
-          - "7.2"
-          - "7.3"
           - "7.4"
           - "8.0"
-          # disabled for now as it leads to PHPUnit installing in a very old 4.3 version due to phpspec/prophecy not allowing 8.1
-          # - "8.1"
+          - "8.1"
+          - "8.2"
+          - "8.3"
 
     steps:
       - name: "Checkout"
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index cb07e31..d3480bc 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,7 +13,6 @@ jobs:
     strategy:
       matrix:
         php-version:
-          - "5.3"
           - "7.4"
 
     steps:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b141347..d44b371 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 You can find newer changelog entries in [GitHub releases](https://github.com/Seldaek/jsonlint/releases)
 
+### 1.11.0 (2023-11-xx)
+
+  * Drop Support for PHP <= 7.3 
+
 ### 1.10.0 (2023-05-11)
 
   * Added ALLOW_COMMENTS flag to parse while allowing (and ignoring) inline `//` and multiline `/* */` comments in the JSON document (#81)
diff --git a/composer.json b/composer.json
index d01217c..bfd785d 100644
--- a/composer.json
+++ b/composer.json
@@ -12,11 +12,11 @@
         }
     ],
     "require": {
-        "php": "^5.3 || ^7.0 || ^8.0"
+        "php": "^7.4 || ^8.0"
     },
     "require-dev": {
-        "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13",
-        "phpstan/phpstan": "^1.5"
+        "phpunit/phpunit": "^9.6 || ^10.4",
+        "phpstan/phpstan": "^1.10"
     },
     "autoload": {
         "psr-4": { "Seld\\JsonLint\\": "src/Seld/JsonLint/" }
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 5de888b..a233822 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,14 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<phpunit backupGlobals="false"
-         backupStaticAttributes="false"
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
          colors="true"
-         convertErrorsToExceptions="true"
-         convertNoticesToExceptions="true"
-         convertWarningsToExceptions="true"
-         processIsolation="false"
-         stopOnFailure="false"
-         syntaxCheck="false"
          bootstrap="tests/bootstrap.php"
 >
     <testsuites>
@@ -17,9 +11,9 @@
         </testsuite>
     </testsuites>
 
-    <filter>
-        <whitelist>
+    <coverage>
+        <include>
             <directory>./src/Seld/JsonLint/</directory>
-        </whitelist>
-    </filter>
+        </include>
+    </coverage>
 </phpunit>
diff --git a/tests/JsonParserTest.php b/tests/JsonParserTest.php
index 560e303..09ca848 100644
--- a/tests/JsonParserTest.php
+++ b/tests/JsonParserTest.php
@@ -19,7 +19,7 @@ class JsonParserTest extends TestCase
     /**
      * @var list<string>
      */
-    protected $json = array(
+    protected static array $json = [
         '42', '42.3', '0.3', '-42', '-42.3', '-0.3',
         '2e1', '2E1', '-2e1', '-2E1', '2E+2', '2E-2', '-2E+2', '-2E-2',
         'true', 'false', 'null', '""', '[]', '{}', '"string"',
@@ -42,23 +42,22 @@ class JsonParserTest extends TestCase
         '"Argument \u0022input\u0022 has an invalid value: ..."',
         '"👻"',
         '"\u1f47d"',
-    );
+    ];
 
     /**
      * @dataProvider provideValidStrings
-     * @param string $input
      */
-    public function testParsesValidStrings($input)
+    public function testParsesValidStrings(string $input)
     {
         $parser = new JsonParser();
         $this->assertEquals(json_decode($input), $parser->parse($input));
     }
 
-    public function provideValidStrings()
+    public static function provideValidStrings(): array
     {
-        $strings = array();
-        foreach ($this->json as $input) {
-            $strings[] = array($input);
+        $strings = [];
+        foreach (self::$json as $input) {
+            $strings[] = [$input];
         }
 
         return $strings;
@@ -73,7 +72,7 @@ public function testErrorOnTrailingComma()
 }');
             $this->fail('Invalid trailing comma should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('It appears you have an extra trailing comma', $e->getMessage());
+            $this->assertStringContainsString('It appears you have an extra trailing comma', $e->getMessage());
         }
     }
 
@@ -86,7 +85,7 @@ public function testErrorOnInvalidQuotes()
 }');
             $this->fail('Invalid quotes for string should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('Invalid string, it appears you used single quotes instead of double quotes', $e->getMessage());
+            $this->assertStringContainsString('Invalid string, it appears you used single quotes instead of double quotes', $e->getMessage());
         }
     }
 
@@ -99,7 +98,7 @@ public function testErrorOnUnescapedBackslash()
 }');
             $this->fail('Invalid unescaped string should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('Invalid string, it appears you have an unescaped backslash at: \z', $e->getMessage());
+            $this->assertStringContainsString('Invalid string, it appears you have an unescaped backslash at: \z', $e->getMessage());
         }
     }
 
@@ -148,7 +147,7 @@ public function testErrorOnUnterminatedString()
             $parser->parse('{"bar": "foo}');
             $this->fail('Invalid unterminated string should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('Invalid string, it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid', $e->getMessage());
+            $this->assertStringContainsString('Invalid string, it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid', $e->getMessage());
         }
     }
 
@@ -160,7 +159,7 @@ public function testErrorOnMultilineString()
 bar"}');
             $this->fail('Invalid multi-line string should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('Invalid string, it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid', $e->getMessage());
+            $this->assertStringContainsString('Invalid string, it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid', $e->getMessage());
         }
     }
 
@@ -173,14 +172,14 @@ public function testErrorAtBeginning()
 ');
             $this->fail('Empty string should be invalid');
         } catch (ParsingException $e) {
-            $this->assertContains("Parse error on line 1:\n\n^", $e->getMessage());
+            $this->assertStringContainsString("Parse error on line 1:\n\n^", $e->getMessage());
         }
     }
 
     public function testParsesMultiInARow()
     {
         $parser = new JsonParser();
-        foreach ($this->json as $input) {
+        foreach (self::$json as $input) {
             $this->assertEquals(json_decode($input), $parser->parse($input));
         }
     }
@@ -193,26 +192,9 @@ public function testDetectsKeyOverrides()
             $parser->parse('{"a":"b", "a":"c"}', JsonParser::DETECT_KEY_CONFLICTS);
             $this->fail('Duplicate keys should not be allowed');
         } catch (DuplicateKeyException $e) {
-            $this->assertContains('Duplicate key: a', $e->getMessage());
+            $this->assertStringContainsString('Duplicate key: a', $e->getMessage());
             $this->assertSame('a', $e->getKey());
-            $this->assertSame(array('line' => 1, 'key' => 'a'), $e->getDetails());
-        }
-    }
-
-    public function testDetectsKeyOverridesWithEmpty()
-    {
-        $parser = new JsonParser();
-
-        if (PHP_VERSION_ID >= 70100) {
-            $this->markTestSkipped('Only for PHP < 7.1');
-        }
-        try {
-            $parser->parse('{"":"b", "_empty_":"a"}', JsonParser::DETECT_KEY_CONFLICTS);
-            $this->fail('Duplicate keys should not be allowed');
-        } catch (DuplicateKeyException $e) {
-            $this->assertContains('Duplicate key: _empty_', $e->getMessage());
-            $this->assertSame('_empty_', $e->getKey());
-            $this->assertSame(array('line' => 1, 'key' => '_empty_'), $e->getDetails());
+            $this->assertSame(['line' => 1, 'key' => 'a'], $e->getDetails());
         }
     }
 
@@ -221,28 +203,11 @@ public function testDuplicateKeys()
         $parser = new JsonParser();
 
         $result = $parser->parse('{"a":"b", "a":"c", "a":"d"}', JsonParser::ALLOW_DUPLICATE_KEYS);
-        $this->assertThat($result,
-            $this->logicalAnd(
-                $this->objectHasAttribute('a'),
-                $this->objectHasAttribute('a.1'),
-                $this->objectHasAttribute('a.2')
-            )
-        );
-    }
 
-    public function testDuplicateKeysWithEmpty()
-    {
-        $parser = new JsonParser();
-
-        if (PHP_VERSION_ID >= 70100) {
-            $this->markTestSkipped('Only for PHP < 7.1');
-        }
-        $result = $parser->parse('{"":"a", "_empty_":"b"}', JsonParser::ALLOW_DUPLICATE_KEYS);
-        $this->assertThat($result,
-            $this->logicalAnd(
-                $this->objectHasAttribute('_empty_'),
-                $this->objectHasAttribute('_empty_.1')
-            )
+        $this->assertTrue(
+            property_exists($result, 'a') &&
+            property_exists($result, 'a.1') &&
+            property_exists($result, 'a.2')
         );
     }
 
@@ -262,7 +227,7 @@ public function testFileWithBOM()
             $parser->parse((string) file_get_contents(dirname(__FILE__) .'/bom.json'));
             $this->fail('BOM should be detected');
         } catch (ParsingException $e) {
-            $this->assertContains('BOM detected', $e->getMessage());
+            $this->assertStringContainsString('BOM detected', $e->getMessage());
         }
     }
 
@@ -281,7 +246,7 @@ public function testParseNoneTerminatingString()
         try {
             $this->assertEquals('', $parser->parse('{"'));
         } catch (ParsingException $e) {
-            $this->assertContains('Invalid string, it appears you forgot to terminate a string', $e->getMessage());
+            $this->assertStringContainsString('Invalid string, it appears you forgot to terminate a string', $e->getMessage());
         }
     }
 
@@ -299,25 +264,25 @@ public function testParsesJsonStringWithComments($withComment, $valid)
         $this->assertEquals(json_decode($valid), $parser->parse($withComment, JsonParser::ALLOW_COMMENTS));
     }
 
-    public function provideStringsWithComments()
+    public static function provideStringsWithComments(): array
     {
-        $json = array(
+        $json = [
             '["a", "sdfsd"]//test' => '["a", "sdfsd"]',
             '[/*"a",*/ "sdfsd"]//' => '["sdfsd"]',
             '["a", "sdf//sd"]/**/' => '["a", "sdf//sd"]',
             '/**/{/*"":*/"g":"foo"}' => '{"g":"foo"}',
             '{"a":"b"}//, "b":"c"}' => '{"a":"b"}',
-        );
+        ];
 
-        $strings = array();
+        $strings = [];
         foreach ($json as $withComment => $valid) {
-            $strings[] = array($withComment, $valid);
+            $strings[] = [$withComment, $valid];
         }
 
-        $strings[] = array(
-            file_get_contents(dirname(__FILE__) .'/with-comments.json'),
-            file_get_contents(dirname(__FILE__) .'/without-comments.json')
-        );
+        $strings[] = [
+            file_get_contents(__DIR__ .'/with-comments.json'),
+            file_get_contents(__DIR__ .'/without-comments.json')
+        ];
 
         return $strings;
     }