218 lines
7.0 KiB
PHP
218 lines
7.0 KiB
PHP
<?php
|
|
/**
|
|
* Admin Controller for AddLivePhoto Module
|
|
*/
|
|
|
|
class AdminAddLivePhotoController extends ModuleAdminController
|
|
{
|
|
public function __construct()
|
|
{
|
|
$this->bootstrap = true;
|
|
$this->display = 'view'; // Force custom view
|
|
parent::__construct();
|
|
}
|
|
|
|
public function initContent()
|
|
{
|
|
// Не викликаємо parent::initContent(), бо нам не потрібен стандартний список
|
|
// Але нам потрібен header і footer адмінки
|
|
$this->context->smarty->assign([
|
|
'content' => $this->renderView(), // Це вставить наш tpl
|
|
]);
|
|
|
|
// Викликаємо батьківський метод для відображення структури адмінки
|
|
parent::initContent();
|
|
}
|
|
|
|
public function renderView()
|
|
{
|
|
$ajax_url = $this->context->link->getAdminLink(
|
|
'AdminAddLivePhoto',
|
|
true,
|
|
[],
|
|
['ajax' => 1]
|
|
);
|
|
|
|
$this->context->smarty->assign([
|
|
'ajax_url' => $ajax_url,
|
|
'module_dir' => _MODULE_DIR_ . $this->module->name . '/',
|
|
]);
|
|
|
|
return $this->context->smarty->fetch($this->module->getLocalPath() . 'views/templates/admin/uploader.tpl');
|
|
}
|
|
|
|
public function ajaxProcess()
|
|
{
|
|
$action = Tools::getValue('action');
|
|
|
|
try {
|
|
switch ($action) {
|
|
case 'searchProduct':
|
|
$this->processSearchProduct();
|
|
break;
|
|
case 'uploadImage':
|
|
$this->processUploadImage();
|
|
break;
|
|
case 'deleteImage':
|
|
$this->processDeleteFreshImage();
|
|
break;
|
|
default:
|
|
throw new Exception('Unknown action');
|
|
}
|
|
} catch (Exception $e) {
|
|
$this->jsonResponse(['success' => false, 'message' => $e->getMessage()]);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
protected function processSearchProduct()
|
|
{
|
|
$identifier = trim(Tools::getValue('identifier'));
|
|
if (empty($identifier)) {
|
|
throw new Exception($this->trans('Please enter a barcode or ID.', [], 'Modules.Addlivephoto.Admin'));
|
|
}
|
|
|
|
$id_product = 0;
|
|
// 1. Спробуємо знайти по EAN13
|
|
$sql = 'SELECT id_product FROM `' . _DB_PREFIX_ . 'product` WHERE ean13 = "'.pSQL($identifier).'"';
|
|
$id_by_ean = Db::getInstance()->getValue($sql);
|
|
|
|
if ($id_by_ean) {
|
|
$id_product = (int)$id_by_ean;
|
|
} elseif (is_numeric($identifier)) {
|
|
// 2. Якщо це число, пробуємо як ID
|
|
$id_product = (int)$identifier;
|
|
}
|
|
|
|
$product = new Product($id_product, false, $this->context->language->id);
|
|
|
|
if (!Validate::isLoadedObject($product)) {
|
|
throw new Exception($this->trans('Product not found.', [], 'Modules.Addlivephoto.Admin'));
|
|
}
|
|
|
|
// Отримуємо існуючі фото
|
|
$existing_photos = $this->getLivePhotos($product->id);
|
|
|
|
$this->jsonResponse([
|
|
'success' => true,
|
|
'data' => [
|
|
'id_product' => $product->id,
|
|
'name' => $product->name,
|
|
'reference' => $product->reference,
|
|
'ean13' => $product->ean13,
|
|
'existing_photos' => $existing_photos
|
|
]
|
|
]);
|
|
}
|
|
|
|
protected function processUploadImage()
|
|
{
|
|
$id_product = (int)Tools::getValue('id_product');
|
|
$rawImage = Tools::getValue('imageData'); // base64 string
|
|
$imageType = Tools::getValue('image_type'); // expiry або packaging
|
|
|
|
if (!$id_product || !$rawImage) {
|
|
throw new Exception('Missing ID or Image Data');
|
|
}
|
|
|
|
if (!in_array($imageType, ['expiry', 'packaging'])) {
|
|
$imageType = 'expiry'; // Fallback
|
|
}
|
|
|
|
// Clean Base64
|
|
if (preg_match('/^data:image\/(\w+);base64,/', $rawImage, $type)) {
|
|
$rawImage = substr($rawImage, strpos($rawImage, ',') + 1);
|
|
$type = strtolower($type[1]); // jpg, png, webp
|
|
|
|
if (!in_array($type, ['jpg', 'jpeg', 'png', 'webp'])) {
|
|
throw new Exception('Invalid image type');
|
|
}
|
|
|
|
$rawImage = base64_decode($rawImage);
|
|
if ($rawImage === false) {
|
|
throw new Exception('Base64 decode failed');
|
|
}
|
|
} else {
|
|
throw new Exception('Did not match data URI with image data');
|
|
}
|
|
|
|
// Generate Filename
|
|
$filename = uniqid() . '.webp'; // Save as WebP usually
|
|
$path = $this->module->getProductImageServerPath($id_product);
|
|
|
|
if (!$path) {
|
|
throw new Exception('Could not create directory');
|
|
}
|
|
|
|
// Save File
|
|
if (!file_put_contents($path . $filename, $rawImage)) {
|
|
throw new Exception('Failed to write file to disk');
|
|
}
|
|
|
|
// Save to DB
|
|
$res = Db::getInstance()->insert('add_live_photo', [
|
|
'id_product' => $id_product,
|
|
'image_name' => pSQL($filename),
|
|
'image_type' => pSQL($imageType),
|
|
'date_add' => date('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
if (!$res) {
|
|
@unlink($path . $filename); // Cleanup
|
|
throw new Exception('Database insert error');
|
|
}
|
|
|
|
$photoUrl = $this->module->getProductImageUri($id_product, $filename);
|
|
|
|
$this->jsonResponse([
|
|
'success' => true,
|
|
'message' => 'Saved successfully!',
|
|
'photo' => [
|
|
'name' => $filename,
|
|
'url' => $photoUrl,
|
|
'type' => $imageType
|
|
]
|
|
]);
|
|
}
|
|
|
|
protected function processDeleteFreshImage()
|
|
{
|
|
$id_product = (int)Tools::getValue('id_product');
|
|
$image_name = Tools::getValue('image_name');
|
|
|
|
if ($this->module->deleteProductImage($id_product, $image_name)) {
|
|
$this->jsonResponse(['success' => true, 'message' => 'Deleted']);
|
|
} else {
|
|
throw new Exception('Delete failed');
|
|
}
|
|
}
|
|
|
|
private function getLivePhotos($id_product)
|
|
{
|
|
$sql = new DbQuery();
|
|
$sql->select('*');
|
|
$sql->from('add_live_photo');
|
|
$sql->where('id_product = ' . (int)$id_product);
|
|
$sql->orderBy('date_add DESC');
|
|
|
|
$res = Db::getInstance()->executeS($sql);
|
|
$photos = [];
|
|
if ($res) {
|
|
foreach($res as $row) {
|
|
$photos[] = [
|
|
'name' => $row['image_name'],
|
|
'type' => isset($row['image_type']) ? $row['image_type'] : 'expiry',
|
|
'url' => $this->module->getProductImageUri($id_product, $row['image_name'])
|
|
];
|
|
}
|
|
}
|
|
return $photos;
|
|
}
|
|
|
|
private function jsonResponse($data)
|
|
{
|
|
header('Content-Type: application/json');
|
|
echo json_encode($data);
|
|
exit;
|
|
}
|
|
} |