Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defining PHP 8.1 as base version #79

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
"prefer-stable": true,
"license": "MIT",
"require": {
"byjg/webrequest": "4.9.*",
"php": ">=7.4",
"byjg/webrequest": "dev-5.0.0rc",
byjg marked this conversation as resolved.
Show resolved Hide resolved
"php": ">=8.1",

Choose a reason for hiding this comment

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

This constraint also allows version 8.4, but this version of PHP is not covered by the GitHub workflow.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I am going to upgrade the project https://github.com/byjg/docker-php to support PHP 8.4 since alpine:edge has the 8.4 beta already :)

Choose a reason for hiding this comment

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

The problem is different: this packages can be installed with version 8.4 of PHP but it is not tested with that version. This can therefore lead to problems on the user side, as PHP does not follow semantic versioning.
This would help:

"php": "~8.1.0 || ~8.2.0 || ~8.3.0",

https://getcomposer.org/doc/articles/versions.md

Copy link
Owner Author

Choose a reason for hiding this comment

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

Gotcha. I'll add this.

"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "5.7.*|7.4.*|^9.5",
"byjg/restserver": "4.9.*"
"phpunit/phpunit": "^9.6",
"byjg/restserver": "^5.0"
},
"autoload": {
"psr-4": {
Expand Down
94 changes: 50 additions & 44 deletions src/AbstractRequester.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
namespace ByJG\ApiTools;

use ByJG\ApiTools\Base\Schema;
use ByJG\ApiTools\Exception\DefinitionNotFoundException;
use ByJG\ApiTools\Exception\GenericSwaggerException;
use ByJG\ApiTools\Exception\HttpMethodNotFoundException;
use ByJG\ApiTools\Exception\InvalidDefinitionException;
use ByJG\ApiTools\Exception\InvalidRequestException;
use ByJG\ApiTools\Exception\NotMatchedException;
use ByJG\ApiTools\Exception\PathNotFoundException;
use ByJG\ApiTools\Exception\RequiredArgumentNotFound;
use ByJG\ApiTools\Exception\StatusCodeNotMatchedException;
use ByJG\Util\Psr7\MessageException;
use ByJG\Util\Exception\MessageException;
use ByJG\Util\Exception\RequestException;
use ByJG\Util\Psr7\Request;
use ByJG\Util\Psr7\Response;
use ByJG\Util\Uri;
use ByJG\Util\Psr7\MemoryStream;
use Psr\Http\Message\RequestInterface;
Expand All @@ -27,22 +33,23 @@
abstract class AbstractRequester
{
/**
* @var Schema
* @var Schema|null
*/
protected $schema = null;
protected ?Schema $schema = null;

protected $statusExpected = 200;
protected $assertHeader = [];
protected $assertBody = [];
protected int $statusExpected = 200;
protected array $assertHeader = [];
protected array $assertBody = [];

/**
* @var RequestInterface
*/
protected $psr7Request;
protected RequestInterface $psr7Request;

/**
* AbstractRequester constructor.
* @throws MessageException
* @throws RequestException
*/
public function __construct()
{
Expand All @@ -58,13 +65,13 @@ public function __construct()
* @param RequestInterface $request
* @return ResponseInterface
*/
abstract protected function handleRequest(RequestInterface $request);
abstract protected function handleRequest(RequestInterface $request): ResponseInterface;

/**
* @param Schema $schema
* @return $this
*/
public function withSchema($schema)
public function withSchema(Schema $schema): self
{
$this->schema = $schema;

Expand All @@ -74,17 +81,16 @@ public function withSchema($schema)
/**
* @return bool
*/
public function hasSchema()
public function hasSchema(): bool
{
return !empty($this->schema);
}

/**
* @param string $method
* @return $this
* @throws MessageException
*/
public function withMethod($method)
public function withMethod(string $method): self
{
$this->psr7Request = $this->psr7Request->withMethod($method);

Expand All @@ -95,7 +101,7 @@ public function withMethod($method)
* @param string $path
* @return $this
*/
public function withPath($path)
public function withPath(string $path): self
{
$uri = $this->psr7Request->getUri()->withPath($path);
$this->psr7Request = $this->psr7Request->withUri($uri);
Expand All @@ -104,10 +110,10 @@ public function withPath($path)
}

/**
* @param array $requestHeader
* @param string|array $requestHeader
* @return $this
*/
public function withRequestHeader($requestHeader)
public function withRequestHeader(string|array $requestHeader): self
{
foreach ((array)$requestHeader as $name => $value) {
$this->psr7Request = $this->psr7Request->withHeader($name, $value);
Expand All @@ -117,10 +123,10 @@ public function withRequestHeader($requestHeader)
}

/**
* @param array $query
* @param array|null $query
* @return $this
*/
public function withQuery($query = null)
public function withQuery(array $query = null): self
{
$uri = $this->psr7Request->getUri();

Expand All @@ -143,58 +149,58 @@ public function withQuery($query = null)
* @param mixed $requestBody
* @return $this
*/
public function withRequestBody($requestBody)
public function withRequestBody(array|string $requestBody): self
{
$contentType = $this->psr7Request->getHeaderLine("Content-Type");
if (is_array($requestBody) && (empty($contentType) || strpos($contentType, "application/json") !== false)) {
if (is_array($requestBody) && (empty($contentType) || str_contains($contentType, "application/json"))) {
$requestBody = json_encode($requestBody);
}
$this->psr7Request = $this->psr7Request->withBody(new MemoryStream($requestBody));

return $this;
}

public function withPsr7Request(RequestInterface $requestInterface)
public function withPsr7Request(RequestInterface $requestInterface): self
{
$this->psr7Request = $requestInterface->withHeader("Accept", "application/json");

return $this;
}

public function assertResponseCode($code)
public function assertResponseCode(int $code): self
{
$this->statusExpected = $code;

return $this;
}

public function assertHeaderContains($header, $contains)
public function assertHeaderContains(string $header, string $contains): self
{
$this->assertHeader[$header] = $contains;

return $this;
}

public function assertBodyContains($contains)
public function assertBodyContains(string $contains): self
{
$this->assertBody[] = $contains;

return $this;
}

/**
* @return Response|ResponseInterface
* @throws Exception\DefinitionNotFoundException
* @throws Exception\GenericSwaggerException
* @throws Exception\HttpMethodNotFoundException
* @throws Exception\InvalidDefinitionException
* @throws Exception\PathNotFoundException
* @return ResponseInterface
* @throws DefinitionNotFoundException
* @throws GenericSwaggerException
* @throws HttpMethodNotFoundException
* @throws InvalidDefinitionException
* @throws InvalidRequestException
* @throws NotMatchedException
* @throws PathNotFoundException
* @throws RequiredArgumentNotFound
* @throws StatusCodeNotMatchedException
* @throws MessageException
* @throws InvalidRequestException
*/
public function send()
public function send(): ResponseInterface
{
// Process URI based on the OpenAPI schema
$uriSchema = new Uri($this->schema->getServerUrl());
Expand Down Expand Up @@ -225,12 +231,12 @@ public function send()
$requestBody = $requestBody->getContents();

$contentType = $this->psr7Request->getHeaderLine("content-type");
if (empty($contentType) || strpos($contentType, "application/json") !== false) {
if (empty($contentType) || str_contains($contentType, "application/json")) {
$requestBody = json_decode($requestBody, true);
} elseif (strpos($contentType, "multipart/") !== false) {
} elseif (str_contains($contentType, "multipart/")) {
$requestBody = $this->parseMultiPartForm($contentType, $requestBody);
} else {
throw new InvalidRequestException("Cannot handle Content Type '{$contentType}'");
throw new InvalidRequestException("Cannot handle Content Type '$contentType'");
}
}

Expand All @@ -248,7 +254,7 @@ public function send()
// Assert results
if ($this->statusExpected != $statusReturned) {
throw new StatusCodeNotMatchedException(
"Status code not matched: Expected {$this->statusExpected}, got {$statusReturned}",
"Status code not matched: Expected $this->statusExpected, got $statusReturned",
$responseBody
);
}
Expand All @@ -261,7 +267,7 @@ public function send()
$bodyResponseDef->match($responseBody);

foreach ($this->assertHeader as $key => $value) {
if (!isset($responseHeader[$key]) || strpos($responseHeader[$key][0], $value) === false) {
if (!isset($responseHeader[$key]) || !str_contains($responseHeader[$key][0], $value)) {
throw new NotMatchedException(
"Does not exists header '$key' with value '$value'",
$responseHeader
Expand All @@ -271,20 +277,20 @@ public function send()

if (!empty($responseBodyStr)) {
foreach ($this->assertBody as $item) {
if (strpos($responseBodyStr, $item) === false) {
throw new NotMatchedException("Body does not contain '{$item}'");
if (!str_contains($responseBodyStr, $item)) {
throw new NotMatchedException("Body does not contain '$item'");
}
}
}

return $response;
}

protected function parseMultiPartForm($contentType, $body)
protected function parseMultiPartForm(?string $contentType, string $body): array|null
{
$matchRequest = [];

if (empty($contentType) || strpos($contentType, "multipart/") === false) {
if (empty($contentType) || !str_contains($contentType, "multipart/")) {
return null;
}

Expand All @@ -298,11 +304,11 @@ protected function parseMultiPartForm($contentType, $body)
array_pop($blocks);

// loop data blocks
foreach ($blocks as $id => $block) {
foreach ($blocks as $block) {
if (empty($block))
continue;

if (strpos($block, 'application/octet-stream') !== false) {
if (str_contains($block, 'application/octet-stream')) {
preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches);
} else {
preg_match('/\bname=\"([^\"]*)\"\s*;.*?[\n|\r]+([^\n\r].*)?[\r|\n]$/s', $block, $matches);
Expand Down
17 changes: 9 additions & 8 deletions src/ApiRequester.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace ByJG\ApiTools;

use ByJG\Util\CurlException;
use ByJG\Util\Exception\MessageException;
use ByJG\Util\Exception\NetworkException;
use ByJG\Util\Exception\RequestException;
use ByJG\Util\HttpClient;
use ByJG\Util\Psr7\MessageException;
use ByJG\Util\Psr7\Response;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

Expand All @@ -15,10 +15,11 @@
class ApiRequester extends AbstractRequester
{
/** @var HttpClient */
private $httpClient;
private HttpClient $httpClient;

/**
* ApiRequester constructor.
* @throws RequestException
* @throws MessageException
*/
public function __construct()
Expand All @@ -31,11 +32,11 @@ public function __construct()

/**
* @param RequestInterface $request
* @return Response|ResponseInterface
* @throws CurlException
* @throws MessageException
* @return ResponseInterface
* @throws NetworkException
* @throws RequestException
*/
protected function handleRequest(RequestInterface $request)
protected function handleRequest(RequestInterface $request): ResponseInterface
{
$request = $request->withHeader("User-Agent", "ByJG Swagger Test");
return $this->httpClient->sendRequest($request);
Expand Down
Loading
Loading