refactor: use Symfony Foundation to handle HTTP requests and responses

This commit is contained in:
2025-12-05 15:28:16 +03:00
parent 95dd545dc5
commit 4e416ead49
36 changed files with 128 additions and 227 deletions

View File

@@ -3,7 +3,7 @@
namespace Bastion\Handlers;
use App\Services\SettingsService;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -3,7 +3,7 @@
namespace Bastion\Handlers;
use App\Services\SettingsService;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -4,7 +4,7 @@ namespace Bastion\Handlers;
use JsonException;
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -3,7 +3,7 @@
namespace Bastion\Handlers;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
class LogsHandler
{

View File

@@ -8,7 +8,7 @@ use App\Exceptions\TelegramCustomerNotFoundException;
use App\Exceptions\TelegramCustomerWriteNotAllowedException;
use App\Models\TelegramCustomer;
use GuzzleHttp\Exception\GuzzleException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Telegram\TelegramService;
use Psr\Log\LoggerInterface;

View File

@@ -8,7 +8,7 @@ use Bastion\Services\SettingsService;
use Exception;
use Openguru\OpenCartFramework\Cache\CacheInterface;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -2,7 +2,7 @@
namespace Bastion\Handlers;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
use Openguru\OpenCartFramework\QueryBuilder\RawExpression;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Bastion\Handlers;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\RawExpression;

View File

@@ -7,7 +7,7 @@ use Exception;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\GuzzleException;
use Openguru\OpenCartFramework\Cache\CacheInterface;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\Support\Arr;

View File

@@ -31,7 +31,8 @@
"psr/log": "^1.1",
"symfony/cache": "^5.4",
"vlucas/phpdotenv": "^5.6",
"ramsey/uuid": "^4.2"
"ramsey/uuid": "^4.2",
"symfony/http-foundation": "^5.4"
},
"require-dev": {
"doctrine/sql-formatter": "^1.3",

View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "049ebb1f7c985aa2bbbe3578c203fb37",
"content-hash": "73829e240f399344756292ca05f62e89",
"packages": [
{
"name": "brick/math",
@@ -1979,6 +1979,86 @@
],
"time": "2024-09-25T14:11:13+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v5.4.50",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "1a0706e8b8041046052ea2695eb8aeee04f97609"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/1a0706e8b8041046052ea2695eb8aeee04f97609",
"reference": "1a0706e8b8041046052ea2695eb8aeee04f97609",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-mbstring": "~1.1",
"symfony/polyfill-php80": "^1.16"
},
"require-dev": {
"predis/predis": "^1.0|^2.0",
"symfony/cache": "^4.4|^5.0|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
"symfony/mime": "^4.4|^5.0|^6.0",
"symfony/rate-limiter": "^5.2|^6.0"
},
"suggest": {
"symfony/mime": "To use the file extension guesser"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.4.50"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-11-03T12:58:48+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.33.0",

View File

@@ -2,13 +2,11 @@
namespace Openguru\OpenCartFramework;
use Carbon\Carbon;
use Closure;
use Dotenv\Dotenv;
use InvalidArgumentException;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Container\Container;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\MaintenanceTasks\MaintenanceTasksService;
use Openguru\OpenCartFramework\MaintenanceTasks\MaintenanceTasksServiceProvider;
@@ -17,6 +15,7 @@ use Openguru\OpenCartFramework\Router\Router;
use Openguru\OpenCartFramework\Support\ExecutionTimeProfiler;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
class Application extends Container implements LoggerAwareInterface
{
@@ -83,7 +82,7 @@ class Application extends Container implements LoggerAwareInterface
return $this;
}
public function handleRequest(Request $request): JsonResponse
public function handleRequest(Request $request): Response
{
$this->bind(Request::class, function () use ($request) {
return $request;
@@ -118,6 +117,7 @@ class Application extends Container implements LoggerAwareInterface
public function bootAndHandleRequest(): void
{
$this->boot();
$request = Request::createFromGlobals();
$response = $this->handleRequest($request);
$response->send();

View File

@@ -4,7 +4,7 @@ namespace Openguru\OpenCartFramework\Container;
use Openguru\OpenCartFramework\Events\EventDispatcher;
use Openguru\OpenCartFramework\Exceptions\ContainerDependencyResolutionException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Support\Arr;
use Phar;
use Psr\Container\ContainerInterface;

View File

@@ -2,7 +2,7 @@
namespace Openguru\OpenCartFramework\Contracts;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Throwable;
interface ExceptionHandlerInterface

View File

@@ -7,7 +7,7 @@ use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
use Openguru\OpenCartFramework\Exceptions\ActionNotFoundException;
use Openguru\OpenCartFramework\Exceptions\InvalidApiTokenException;
use Openguru\OpenCartFramework\Exceptions\NonLoggableExceptionInterface;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Response;
use Psr\Log\LoggerInterface;
use Throwable;

View File

@@ -1,52 +0,0 @@
<?php
namespace Openguru\OpenCartFramework\Http;
class JsonResponse extends Response
{
private array $data;
private int $code;
public function __construct(array $data, int $code = self::HTTP_OK)
{
$this->data = $data;
$this->code = $code;
}
public function getData(): array
{
return $this->data;
}
public function getCode(): int
{
return $this->code;
}
public function send(): void
{
$this->sendHeaders();
$this->sendContent();
}
private function sendContent(): void
{
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
echo json_encode($this->getData(), JSON_THROW_ON_ERROR);
}
private function sendHeaders(): void
{
http_response_code($this->getCode());
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Credentials: true');
header('X-TELECART-VERSION: ' . module_version());
}
}

View File

@@ -4,49 +4,10 @@ namespace Openguru\OpenCartFramework\Http;
use Openguru\OpenCartFramework\Support\Arr;
use Openguru\OpenCartFramework\Support\Utils;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
final class Request
final class Request extends SymfonyRequest
{
private $query;
private $request;
private $cookies;
private $files;
private $server;
private $content;
private array $headers = [];
public function __construct(
array $query,
array $request,
array $cookies,
array $files,
array $server,
array $headers = [],
string $content = null
) {
$this->query = $query;
$this->request = $request;
$this->cookies = $cookies;
$this->files = $files;
$this->server = $server;
$this->headers = $headers;
$this->content = $content;
}
public static function createFromGlobals(): Request
{
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, getallheaders());
}
public function getContent(): string
{
if ($this->content === null || $this->content === '') {
$this->content = (string)file_get_contents('php://input');
}
return $this->content;
}
public function json(string $key = null, $default = null)
{
$content = $this->getContent();
@@ -66,11 +27,7 @@ final class Request
public function get(string $key = null, $default = null)
{
if ($key === null) {
return $this->query;
}
return $this->query[$key] ?? $default;
return $this->query->get($key, $default);
}
public function getClientIp(): ?string
@@ -83,37 +40,9 @@ final class Request
return $_SERVER['HTTP_USER_AGENT'] ?? null;
}
public function header(string $name): ?string
public function header(string $key, ?string $default = null): ?string
{
$headers = [];
foreach ($this->headers as $key => $value) {
$headers[mb_strtolower($key)] = trim($value);
}
return $headers[mb_strtolower($name)] ?? null;
}
/**
* @param array|string $key
* @return bool
*/
public function has($key): bool
{
if (is_array($key)) {
foreach ($key as $k) {
if ($this->has($k)) {
return true;
}
}
return false;
}
if (array_key_exists($key, $this->query)) {
return true;
}
return $this->json($key) !== null;
return $this->headers->get($key, $default);
}
public function getApiKey(): ?string

View File

@@ -3,7 +3,7 @@
namespace App\Exceptions;
use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\Telegram\Exceptions\TelegramInvalidSignatureException;
use Psr\Log\LoggerInterface;

View File

@@ -3,7 +3,7 @@
namespace App\Handlers;
use App\Services\BlocksService;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
class BlocksHandler

View File

@@ -4,7 +4,7 @@ namespace App\Handlers;
use App\Services\CartService;
use Cart\Cart;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
class CartHandler

View File

@@ -6,7 +6,7 @@ namespace App\Handlers;
use App\Services\SettingsService;
use App\Support\Utils;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -5,7 +5,7 @@ namespace App\Handlers;
use Carbon\Carbon;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Exceptions\InvalidApiTokenException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\RawExpression;

View File

@@ -4,7 +4,7 @@ namespace App\Handlers;
use App\Filters\ProductCategory;
use App\Filters\ProductPrice;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
class FiltersHandler
{

View File

@@ -4,7 +4,7 @@ namespace App\Handlers;
use JsonException;
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\QueryBuilder\Builder;

View File

@@ -2,7 +2,7 @@
namespace App\Handlers;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Response;
class HealthCheckHandler

View File

@@ -4,7 +4,7 @@ namespace App\Handlers;
use App\Exceptions\OrderValidationFailedException;
use App\Services\OrderCreateService;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;

View File

@@ -4,7 +4,7 @@ namespace App\Handlers;
use App\Models\TelegramCustomer;
use Carbon\Carbon;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\Support\Arr;

View File

@@ -8,7 +8,7 @@ use App\Services\ProductsService;
use App\Services\SettingsService;
use Exception;
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Psr\Log\LoggerInterface;

View File

@@ -5,7 +5,7 @@ namespace App\Handlers;
use App\Services\SettingsService;
use Exception;
use GuzzleHttp\Exception\ClientException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\Router\Router;

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace App\Handlers;
use App\Services\TelegramCustomerService;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\Support\Arr;

View File

@@ -6,7 +6,7 @@ use GuzzleHttp\Exception\GuzzleException;
use Mockery\Exception;
use Openguru\OpenCartFramework\Cache\CacheInterface;
use Openguru\OpenCartFramework\Container\Container;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Psr\Log\LoggerInterface;
use Openguru\OpenCartFramework\Support\Arr;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Handlers;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\TeleCartPulse\PulseIngestException;

View File

@@ -2,7 +2,7 @@
namespace Tests\Helpers\ExampleClasses;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use stdClass;
class TestClassWithMethod

View File

@@ -4,7 +4,7 @@ namespace Tests\Unit\Framework;
use Openguru\OpenCartFramework\Container\Container;
use Openguru\OpenCartFramework\Exceptions\ContainerDependencyResolutionException;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use stdClass;
use Tests\Helpers\ExampleClasses\TestClassWithMethod;
use Tests\TestCase;

View File

@@ -2,8 +2,9 @@
namespace Tests\Unit\Framework;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
class JsonResponseTest extends TestCase
{
@@ -13,8 +14,8 @@ class JsonResponseTest extends TestCase
$code = 201;
$response = new JsonResponse($data, $code);
$this->assertEquals($data, $response->getData());
$this->assertEquals($code, $response->getCode());
$this->assertEquals('{"key":"value"}', $response->getContent());
$this->assertEquals($code, $response->getStatusCode());
}
public function testDefaultCodeIs200(): void
@@ -22,7 +23,7 @@ class JsonResponseTest extends TestCase
$data = ['key' => 'value'];
$response = new JsonResponse($data);
$this->assertEquals(JsonResponse::HTTP_OK, $response->getCode());
$this->assertEquals(SymfonyResponse::HTTP_OK, $response->getStatusCode());
}
public function testGetDataReturnsCorrectData(): void
@@ -30,28 +31,21 @@ class JsonResponseTest extends TestCase
$data = ['message' => 'success', 'items' => [1, 2, 3]];
$response = new JsonResponse($data);
$this->assertEquals($data, $response->getData());
$this->assertEquals('{"message":"success","items":[1,2,3]}', $response->getContent());
}
public function testGetCodeReturnsCorrectCode(): void
{
$response = new JsonResponse([], 404);
$this->assertEquals(404, $response->getCode());
}
public function testResponseInheritsFromResponse(): void
{
$response = new JsonResponse([]);
$this->assertInstanceOf(\Openguru\OpenCartFramework\Http\Response::class, $response);
$this->assertEquals(404, $response->getStatusCode());
}
public function testCanUseHttpConstants(): void
{
$response = new JsonResponse([], JsonResponse::HTTP_CREATED);
$this->assertEquals(201, $response->getCode());
$this->assertEquals(201, $response->getStatusCode());
}
}

View File

@@ -7,56 +7,5 @@ use PHPUnit\Framework\TestCase;
class RequestTest extends TestCase
{
public function testHasQueryParam(): void
{
$request = new Request(
['foo' => 'bar'],
[],
[],
[],
[]
);
$this->assertTrue($request->has('foo'));
$this->assertFalse($request->has('xyz'));
}
public function testHasJsonParam(): void
{
$request = new Request(
[],
[],
[],
[],
[],
[],
'{"foo":"bar"}'
);
$this->assertTrue($request->has('foo'));
}
public function testHasAtLeastOne(): void
{
$request = new Request(
['foo' => 'bar'],
[],
[],
[],
[],
[],
'{"xyz":"bar"}'
);
$this->assertTrue($request->has([
'foo',
'xyz',
'some_other'
]));
$this->assertFalse($request->has([
'abc',
'some_other'
]));
}
}