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", diff --git a/src/Input.php b/src/Input.php index c88b461..f6fe5c1 100644 --- a/src/Input.php +++ b/src/Input.php @@ -3,6 +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; @@ -19,6 +22,7 @@ /** * @implements ArrayAccess * @implements Iterator + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Input implements ArrayAccess, Countable, Iterator { use InputValueGetter; @@ -45,7 +49,7 @@ public function __construct( array $get = [], array $post = [], array $files = [], - string $bodyPath = "php://input" + string $bodyPath = "php://input", ) { $this->bodyStream = new BodyStream($bodyPath); @@ -193,6 +197,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. diff --git a/test/phpunit/InputTest.php b/test/phpunit/InputTest.php index c4cfc0e..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 { @@ -664,6 +667,49 @@ 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 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 = [];