From 834d205c0e0b2c04c8609d5aec3f6abd3065c04d Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 9 May 2024 11:31:23 +0100 Subject: [PATCH 1/6] ci: remove old artifacts --- .github/workflows/ci.yml | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a74e714..3b78953 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,18 +159,17 @@ jobs: path: src/ standard: phpcs.xml -# TODO: Figure this one out: -# remove_old_artifacts: -# runs-on: ubuntu-latest -# -# steps: -# - name: Remove old artifacts for prior workflow runs on this repository -# env: -# GH_TOKEN: ${{ github.token }} -# run: | -# gh api "/repos/${{ github.repository }}/actions/artifacts?name=build-artifact" | jq ".artifacts[] | select(.name | startswith(\"build-artifact\")) | .id" > artifact-id-list.txt -# while read id -# do -# echo -n "Deleting artifact ID $id ... " -# gh api --method DELETE /repos/${{ github.repository }}/actions/artifacts/$id && echo "Done" -# done artifact-id-list.txt + while read id + do + echo -n "Deleting artifact ID $id ... " + gh api --method DELETE /repos/${{ github.repository }}/actions/artifacts/$id && echo "Done" + done Date: Mon, 10 Feb 2025 14:35:53 +0000 Subject: [PATCH 2/6] ci: run all php versions --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b78953..dff0d36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,13 +7,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] steps: - uses: actions/checkout@v4 - name: Cache Composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/composer-cache key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} @@ -37,7 +37,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] outputs: coverage: ${{ steps.store-coverage.outputs.coverage_text }} @@ -52,7 +52,7 @@ jobs: run: tar -xvf /tmp/github-actions/build.tar ./ - name: PHP Unit tests - uses: php-actions/phpunit@v3 + uses: php-actions/phpunit@v4 env: XDEBUG_MODE: cover with: @@ -73,7 +73,7 @@ jobs: needs: [ phpunit ] strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] steps: - uses: actions/download-artifact@v4 @@ -94,7 +94,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] steps: - uses: actions/download-artifact@v4 @@ -117,7 +117,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] steps: - uses: actions/download-artifact@v4 @@ -141,7 +141,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2, 8.3 ] + php: [ 8.1, 8.2, 8.3, 8.4 ] steps: - uses: actions/download-artifact@v4 From 30749be7edb9a606d747d67ce6fc0c2f07fe5e97 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 13 Feb 2025 10:57:16 +0000 Subject: [PATCH 3/6] build: require phpgt/json for #302 --- composer.json | 5 +- composer.lock | 162 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 164 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 5787271..5bc499a 100644 --- a/composer.json +++ b/composer.json @@ -5,11 +5,12 @@ "require": { "php": ">=8.1", - "phpgt/http": "^v1.1" + "phpgt/http": "^1.1", + "phpgt/json": "^1.2" }, "require-dev": { - "phpstan/phpstan": "^v1.10", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^10.5", "phpmd/phpmd": "^2.13", "squizlabs/php_codesniffer": "^3.7" diff --git a/composer.lock b/composer.lock index 722997d..48ddd31 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,62 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e9140dfc9ce00af49122f4c3a0e637a8", + "content-hash": "74675ca63bc6a83c02404557686a1d27", "packages": [ + { + "name": "phpgt/dataobject", + "version": "v1.0.7", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/DataObject.git", + "reference": "3b05cc3b64a0f2b763c8e550bc6c03b71474cd1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/DataObject/zipball/3b05cc3b64a0f2b763c8e550bc6c03b71474cd1a", + "reference": "3b05cc3b64a0f2b763c8e550bc6c03b71474cd1a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=8.0", + "phpgt/typesafegetter": "^1.3" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\DataObject\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": " Structured, type-safe, immutable data transfer.", + "support": { + "issues": "https://github.com/PhpGt/DataObject/issues", + "source": "https://github.com/PhpGt/DataObject/tree/v1.0.7" + }, + "funding": [ + { + "url": "https://github.com/phpgt", + "type": "github" + } + ], + "time": "2023-07-13T09:45:07+00:00" + }, { "name": "phpgt/http", "version": "v1.1.9", @@ -55,6 +109,112 @@ ], "time": "2023-03-10T15:04:04+00:00" }, + { + "name": "phpgt/json", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/Json.git", + "reference": "8938b374d550bc6114bf1d4e5c1cbe3283868e58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/Json/zipball/8938b374d550bc6114bf1d4e5c1cbe3283868e58", + "reference": "8938b374d550bc6114bf1d4e5c1cbe3283868e58", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=8.1", + "phpgt/dataobject": "^1.0.7" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\Json\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": " Structured, type-safe, immutable JSON objects.", + "support": { + "issues": "https://github.com/PhpGt/Json/issues", + "source": "https://github.com/PhpGt/Json/tree/v1.2.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2023-07-13T13:20:08+00:00" + }, + { + "name": "phpgt/typesafegetter", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/TypeSafeGetter.git", + "reference": "f760c05a37b1cc188dcbf800c5fdfab8a926b4b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/TypeSafeGetter/zipball/f760c05a37b1cc188dcbf800c5fdfab8a926b4b0", + "reference": "f760c05a37b1cc188dcbf800c5fdfab8a926b4b0", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\TypeSafeGetter\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": "An interface for objects that expose type-safe getter methods.", + "support": { + "issues": "https://github.com/PhpGt/TypeSafeGetter/issues", + "source": "https://github.com/PhpGt/TypeSafeGetter/tree/v1.3.2" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2023-04-28T14:42:27+00:00" + }, { "name": "psr/http-message", "version": "1.1", From ad1c9fe253f05860827d2904993694745f729da4 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 13 Feb 2025 10:59:48 +0000 Subject: [PATCH 4/6] build: initial non-json test for #302 --- src/Input.php | 6 ++++++ test/phpunit/InputTest.php | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/src/Input.php b/src/Input.php index c88b461..568bc0a 100644 --- a/src/Input.php +++ b/src/Input.php @@ -3,6 +3,7 @@ use ArrayAccess; use Countable; +use Gt\Json\JsonObject; use Iterator; use Psr\Http\Message\StreamInterface; use Gt\Input\Trigger\Trigger; @@ -249,4 +250,9 @@ protected function newTrigger(string $functionName, string...$args):Trigger { $trigger = new Trigger($this); return $trigger->$functionName(...$args); } + + public function getBodyJson():?JsonObject { + return null; + } + } diff --git a/test/phpunit/InputTest.php b/test/phpunit/InputTest.php index c4cfc0e..f79293c 100644 --- a/test/phpunit/InputTest.php +++ b/test/phpunit/InputTest.php @@ -664,6 +664,14 @@ public function testGetMultipleFile():void { } } + public function testGetBodyJson_notJson():void { + $get = []; + $post = ["this" => "is not JSON!"]; + $sut = new Input($get, $post); + $json = $sut->getBodyJson(); + self::assertNull($json); + } + public static function dataRandomGetPost():array { $data = []; From cfbd28b3e1eaae5b260b1ebd1ed581da3b533011 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 13 Feb 2025 11:23:02 +0000 Subject: [PATCH 5/6] feature: getBodyJson --- src/Input.php | 20 ++++++++++++++------ test/phpunit/InputTest.php | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/Input.php b/src/Input.php index 568bc0a..0ecf3f6 100644 --- a/src/Input.php +++ b/src/Input.php @@ -3,7 +3,9 @@ use ArrayAccess; use Countable; +use Gt\Json\JsonDecodeException; use Gt\Json\JsonObject; +use Gt\Json\JsonObjectBuilder; use Iterator; use Psr\Http\Message\StreamInterface; use Gt\Input\Trigger\Trigger; @@ -46,7 +48,7 @@ public function __construct( array $get = [], array $post = [], array $files = [], - string $bodyPath = "php://input" + string $bodyPath = "php://input", ) { $this->bodyStream = new BodyStream($bodyPath); @@ -194,6 +196,17 @@ public function getAll(?string $method = null):InputData { } } + public function getBodyJson():?JsonObject { + $jsonBuilder = new JsonObjectBuilder(); + + try { + return $jsonBuilder->fromJsonString($this->bodyStream->getContents()); + } + catch(JsonDecodeException) { + return null; + } + } + /** * Return a "do" Trigger, matching when a request variable is present with the * provided $match value. @@ -250,9 +263,4 @@ protected function newTrigger(string $functionName, string...$args):Trigger { $trigger = new Trigger($this); return $trigger->$functionName(...$args); } - - public function getBodyJson():?JsonObject { - return null; - } - } diff --git a/test/phpunit/InputTest.php b/test/phpunit/InputTest.php index f79293c..e13048c 100644 --- a/test/phpunit/InputTest.php +++ b/test/phpunit/InputTest.php @@ -11,6 +11,9 @@ use Gt\Input\MissingInputParameterException; use Gt\Input\Test\Helper\Helper; use Gt\Input\Trigger\Trigger; +use Gt\Json\JsonObject; +use Gt\Json\JsonPrimitive\JsonArrayPrimitive; +use Gt\Json\JsonPrimitive\JsonStringPrimitive; use PHPUnit\Framework\TestCase; class InputTest extends TestCase { @@ -672,6 +675,41 @@ public function testGetBodyJson_notJson():void { self::assertNull($json); } + public function testGetBodyJson_string():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "\"Hello, PHP.Gt!\""); + $sut = new Input(bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonStringPrimitive::class, $json); + self::assertSame("Hello, PHP.Gt!", $json->getPrimitiveValue()); + } + + public function testGetBodyJson_arrayWithObject():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "[1, 2, 3, {\"name\": \"Cody\"}]"); + $sut = new Input(bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonArrayPrimitive::class, $json); + $array = $json->getPrimitiveValue(); + self::assertSame(1, $array[0]); + self::assertSame(2, $array[1]); + self::assertSame(3, $array[2]); + /** @var JsonObject $thirdArrayElement */ + $thirdArrayElement = $array[3]; + self::assertInstanceOf(JsonObject::class, $thirdArrayElement); + self::assertSame("Cody", $thirdArrayElement->getString("name")); + } + + public function testGetBodyJson_withQueryString():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "\"Hello, PHP.Gt!\""); + $sut = new Input(["id" => 123], bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonStringPrimitive::class, $json); + self::assertSame("Hello, PHP.Gt!", $json->getPrimitiveValue()); + self::assertSame(123, $sut->getInt("id")); + } + public static function dataRandomGetPost():array { $data = []; From 8c2919714499143be8167236ae9cf4ca3c2c029c Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 13 Feb 2025 11:29:35 +0000 Subject: [PATCH 6/6] tweak: suppress coupling between objects warning --- src/Input.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Input.php b/src/Input.php index 0ecf3f6..f6fe5c1 100644 --- a/src/Input.php +++ b/src/Input.php @@ -22,6 +22,7 @@ /** * @implements ArrayAccess * @implements Iterator + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Input implements ArrayAccess, Countable, Iterator { use InputValueGetter;