Add view classes for articles, banners, languages, menu, newsletter, containers, shop categories, clients, payment methods, products, and search
- Created `Articles` class for rendering article views including full articles, miniature lists, and news sections. - Added `Banners` class for handling banner displays. - Introduced `Languages` class for rendering language options. - Implemented `Menu` class for rendering page and menu structures. - Developed `Newsletter` class for newsletter rendering. - Created `Scontainers` class for rendering specific containers. - Added `ShopCategory` class for managing shop category views and pagination. - Implemented `ShopClient` class for client-related views including address management and login forms. - Created `ShopPaymentMethod` class for displaying payment methods in the basket. - Added `ShopProduct` class for generating product URLs. - Introduced `ShopSearch` class for rendering a simple search form. - Added `.htaccess` file in the plugins directory to enhance security by restricting access to sensitive files and directories.
This commit is contained in:
148
autoload/api/ApiRouter.php
Normal file
148
autoload/api/ApiRouter.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
namespace api;
|
||||
|
||||
use Domain\Settings\SettingsRepository;
|
||||
|
||||
class ApiRouter
|
||||
{
|
||||
private $db;
|
||||
private $settingsRepo;
|
||||
|
||||
public function __construct($db, SettingsRepository $settingsRepo)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
if (!headers_sent()) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$this->authenticate()) {
|
||||
self::sendError('UNAUTHORIZED', 'Invalid or missing API key', 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$endpoint = trim((string)($_GET['endpoint'] ?? ''));
|
||||
$action = trim((string)($_GET['action'] ?? ''));
|
||||
|
||||
if ($endpoint === '' || $action === '') {
|
||||
self::sendError('BAD_REQUEST', 'Missing endpoint or action parameter', 400);
|
||||
return;
|
||||
}
|
||||
|
||||
$controller = $this->resolveController($endpoint);
|
||||
if ($controller === null) {
|
||||
self::sendError('NOT_FOUND', 'Unknown endpoint: ' . $endpoint, 404);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!method_exists($controller, $action)) {
|
||||
self::sendError('NOT_FOUND', 'Unknown action: ' . $action, 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$controller->$action();
|
||||
} catch (\Exception $e) {
|
||||
self::sendError('INTERNAL_ERROR', 'Internal server error', 500);
|
||||
}
|
||||
}
|
||||
|
||||
private function authenticate(): bool
|
||||
{
|
||||
$headerKey = isset($_SERVER['HTTP_X_API_KEY']) ? $_SERVER['HTTP_X_API_KEY'] : '';
|
||||
if ($headerKey === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$storedKey = $this->settingsRepo->getSingleValue('api_key');
|
||||
if ($storedKey === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return hash_equals($storedKey, $headerKey);
|
||||
}
|
||||
|
||||
private function resolveController(string $endpoint)
|
||||
{
|
||||
$factories = $this->getControllerFactories();
|
||||
|
||||
if (!isset($factories[$endpoint])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $factories[$endpoint]();
|
||||
}
|
||||
|
||||
private function getControllerFactories(): array
|
||||
{
|
||||
$db = $this->db;
|
||||
|
||||
return [
|
||||
'orders' => function () use ($db) {
|
||||
$orderRepo = new \Domain\Order\OrderRepository($db);
|
||||
$settingsRepo = new \Domain\Settings\SettingsRepository($db);
|
||||
$productRepo = new \Domain\Product\ProductRepository($db);
|
||||
$transportRepo = new \Domain\Transport\TransportRepository($db);
|
||||
$service = new \Domain\Order\OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo);
|
||||
return new Controllers\OrdersApiController($service, $orderRepo);
|
||||
},
|
||||
'products' => function () use ($db) {
|
||||
$productRepo = new \Domain\Product\ProductRepository($db);
|
||||
return new Controllers\ProductsApiController($productRepo);
|
||||
},
|
||||
'dictionaries' => function () use ($db) {
|
||||
$statusRepo = new \Domain\ShopStatus\ShopStatusRepository($db);
|
||||
$transportRepo = new \Domain\Transport\TransportRepository($db);
|
||||
$paymentRepo = new \Domain\PaymentMethod\PaymentMethodRepository($db);
|
||||
return new Controllers\DictionariesApiController($statusRepo, $transportRepo, $paymentRepo);
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Static response helpers
|
||||
// =========================================================================
|
||||
|
||||
public static function sendSuccess($data): void
|
||||
{
|
||||
http_response_code(200);
|
||||
echo json_encode(['status' => 'ok', 'data' => $data], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
public static function sendError(string $code, string $message, int $httpCode = 400): void
|
||||
{
|
||||
http_response_code($httpCode);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
public static function getJsonBody(): ?array
|
||||
{
|
||||
$raw = file_get_contents('php://input');
|
||||
if ($raw === '' || $raw === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
return is_array($data) ? $data : null;
|
||||
}
|
||||
|
||||
public static function requireMethod(string $method): bool
|
||||
{
|
||||
$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET';
|
||||
if ($requestMethod !== strtoupper($method)) {
|
||||
self::sendError('METHOD_NOT_ALLOWED', 'Method ' . $requestMethod . ' not allowed, expected ' . strtoupper($method), 405);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user