- 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.
252 lines
8.0 KiB
PHP
252 lines
8.0 KiB
PHP
<?php
|
|
namespace api\Controllers;
|
|
|
|
use api\ApiRouter;
|
|
use Domain\Product\ProductRepository;
|
|
|
|
class ProductsApiController
|
|
{
|
|
private $productRepo;
|
|
|
|
public function __construct(ProductRepository $productRepo)
|
|
{
|
|
$this->productRepo = $productRepo;
|
|
}
|
|
|
|
public function list(): void
|
|
{
|
|
if (!ApiRouter::requireMethod('GET')) {
|
|
return;
|
|
}
|
|
|
|
$filters = [
|
|
'search' => isset($_GET['search']) ? $_GET['search'] : '',
|
|
'status' => isset($_GET['status']) ? $_GET['status'] : '',
|
|
'promoted' => isset($_GET['promoted']) ? $_GET['promoted'] : '',
|
|
];
|
|
|
|
$sort = isset($_GET['sort']) ? $_GET['sort'] : 'id';
|
|
$sortDir = isset($_GET['sort_dir']) ? $_GET['sort_dir'] : 'DESC';
|
|
$page = max(1, (int)(isset($_GET['page']) ? $_GET['page'] : 1));
|
|
$perPage = max(1, min(100, (int)(isset($_GET['per_page']) ? $_GET['per_page'] : 50)));
|
|
|
|
$result = $this->productRepo->listForApi($filters, $sort, $sortDir, $page, $perPage);
|
|
|
|
ApiRouter::sendSuccess($result);
|
|
}
|
|
|
|
public function get(): void
|
|
{
|
|
if (!ApiRouter::requireMethod('GET')) {
|
|
return;
|
|
}
|
|
|
|
$id = (int)(isset($_GET['id']) ? $_GET['id'] : 0);
|
|
if ($id <= 0) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing or invalid id parameter', 400);
|
|
return;
|
|
}
|
|
|
|
$product = $this->productRepo->findForApi($id);
|
|
if ($product === null) {
|
|
ApiRouter::sendError('NOT_FOUND', 'Product not found', 404);
|
|
return;
|
|
}
|
|
|
|
ApiRouter::sendSuccess($product);
|
|
}
|
|
|
|
public function create(): void
|
|
{
|
|
if (!ApiRouter::requireMethod('POST')) {
|
|
return;
|
|
}
|
|
|
|
$body = ApiRouter::getJsonBody();
|
|
if ($body === null) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing or invalid JSON body', 400);
|
|
return;
|
|
}
|
|
|
|
if (empty($body['languages']) || !is_array($body['languages'])) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing languages (at least one language with name is required)', 400);
|
|
return;
|
|
}
|
|
|
|
$hasName = false;
|
|
foreach ($body['languages'] as $lang) {
|
|
if (is_array($lang) && !empty($lang['name'])) {
|
|
$hasName = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$hasName) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'At least one language must have a name', 400);
|
|
return;
|
|
}
|
|
|
|
if (!isset($body['price_brutto'])) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing price_brutto', 400);
|
|
return;
|
|
}
|
|
|
|
$formData = $this->mapApiToFormData($body);
|
|
|
|
$productId = $this->productRepo->saveProduct($formData);
|
|
if ($productId === null) {
|
|
ApiRouter::sendError('INTERNAL_ERROR', 'Failed to create product', 500);
|
|
return;
|
|
}
|
|
|
|
http_response_code(201);
|
|
echo json_encode([
|
|
'status' => 'ok',
|
|
'data' => ['id' => $productId],
|
|
], JSON_UNESCAPED_UNICODE);
|
|
}
|
|
|
|
public function update(): void
|
|
{
|
|
if (!ApiRouter::requireMethod('PUT')) {
|
|
return;
|
|
}
|
|
|
|
$id = (int)(isset($_GET['id']) ? $_GET['id'] : 0);
|
|
if ($id <= 0) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing or invalid id parameter', 400);
|
|
return;
|
|
}
|
|
|
|
$existing = $this->productRepo->find($id);
|
|
if ($existing === null) {
|
|
ApiRouter::sendError('NOT_FOUND', 'Product not found', 404);
|
|
return;
|
|
}
|
|
|
|
$body = ApiRouter::getJsonBody();
|
|
if ($body === null) {
|
|
ApiRouter::sendError('BAD_REQUEST', 'Missing or invalid JSON body', 400);
|
|
return;
|
|
}
|
|
|
|
$formData = $this->mapApiToFormData($body, $existing);
|
|
$formData['id'] = $id;
|
|
|
|
$this->productRepo->saveProduct($formData);
|
|
|
|
$updated = $this->productRepo->findForApi($id);
|
|
|
|
ApiRouter::sendSuccess($updated);
|
|
}
|
|
|
|
/**
|
|
* Mapuje dane z JSON API na format oczekiwany przez saveProduct().
|
|
*
|
|
* @param array $body Dane z JSON body
|
|
* @param array|null $existing Istniejące dane produktu (partial update)
|
|
* @return array Dane w formacie formularza
|
|
*/
|
|
private function mapApiToFormData(array $body, ?array $existing = null): array
|
|
{
|
|
$d = [];
|
|
|
|
// Status/promoted — saveProduct expects 'on' for checkboxes
|
|
if (isset($body['status'])) {
|
|
$d['status'] = $body['status'] ? 'on' : '';
|
|
} elseif ($existing !== null) {
|
|
$d['status'] = !empty($existing['status']) ? 'on' : '';
|
|
}
|
|
|
|
if (isset($body['promoted'])) {
|
|
$d['promoted'] = $body['promoted'] ? 'on' : '';
|
|
} elseif ($existing !== null) {
|
|
$d['promoted'] = !empty($existing['promoted']) ? 'on' : '';
|
|
}
|
|
|
|
if (isset($body['stock_0_buy'])) {
|
|
$d['stock_0_buy'] = $body['stock_0_buy'] ? 'on' : '';
|
|
} elseif ($existing !== null) {
|
|
$d['stock_0_buy'] = !empty($existing['stock_0_buy']) ? 'on' : '';
|
|
}
|
|
|
|
// Numeric fields — direct mapping
|
|
$numericFields = [
|
|
'price_brutto', 'price_netto', 'price_brutto_promo', 'price_netto_promo',
|
|
'vat', 'quantity', 'weight',
|
|
];
|
|
foreach ($numericFields as $field) {
|
|
if (isset($body[$field])) {
|
|
$d[$field] = $body[$field];
|
|
} elseif ($existing !== null && isset($existing[$field])) {
|
|
$d[$field] = $existing[$field];
|
|
}
|
|
}
|
|
|
|
// String fields — direct mapping
|
|
$stringFields = [
|
|
'sku', 'ean', 'custom_label_0', 'custom_label_1', 'custom_label_2',
|
|
'custom_label_3', 'custom_label_4', 'wp',
|
|
];
|
|
foreach ($stringFields as $field) {
|
|
if (isset($body[$field])) {
|
|
$d[$field] = $body[$field];
|
|
} elseif ($existing !== null && isset($existing[$field])) {
|
|
$d[$field] = $existing[$field];
|
|
}
|
|
}
|
|
|
|
// Foreign keys
|
|
if (isset($body['set_id'])) {
|
|
$d['set'] = $body['set_id'];
|
|
} elseif ($existing !== null && isset($existing['set_id'])) {
|
|
$d['set'] = $existing['set_id'];
|
|
}
|
|
|
|
if (isset($body['producer_id'])) {
|
|
$d['producer_id'] = $body['producer_id'];
|
|
} elseif ($existing !== null && isset($existing['producer_id'])) {
|
|
$d['producer_id'] = $existing['producer_id'];
|
|
}
|
|
|
|
if (isset($body['product_unit_id'])) {
|
|
$d['product_unit'] = $body['product_unit_id'];
|
|
} elseif ($existing !== null && isset($existing['product_unit_id'])) {
|
|
$d['product_unit'] = $existing['product_unit_id'];
|
|
}
|
|
|
|
// Languages: body.languages.pl.name → d['name']['pl']
|
|
if (isset($body['languages']) && is_array($body['languages'])) {
|
|
$langFields = [
|
|
'name', 'short_description', 'description', 'meta_description',
|
|
'meta_keywords', 'meta_title', 'seo_link', 'copy_from',
|
|
'warehouse_message_zero', 'warehouse_message_nonzero',
|
|
'tab_name_1', 'tab_description_1', 'tab_name_2', 'tab_description_2',
|
|
'canonical', 'security_information',
|
|
];
|
|
|
|
foreach ($body['languages'] as $langId => $langData) {
|
|
if (!is_array($langData)) {
|
|
continue;
|
|
}
|
|
foreach ($langFields as $field) {
|
|
if (isset($langData[$field])) {
|
|
$d[$field][$langId] = $langData[$field];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Categories
|
|
if (isset($body['categories']) && is_array($body['categories'])) {
|
|
$d['categories'] = $body['categories'];
|
|
}
|
|
|
|
// Related products
|
|
if (isset($body['products_related']) && is_array($body['products_related'])) {
|
|
$d['products_related'] = $body['products_related'];
|
|
}
|
|
|
|
return $d;
|
|
}
|
|
}
|