Geizkragen/productAdder.php

406 lines
16 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// product_add.php
require_once __DIR__ . '/lib/bootstrap.php';
/* =======================
0) Zugriffskontrolle nur ADMIN
======================= */
if (empty($_SESSION['user_id']) || empty($_SESSION['user_roles']) || !in_array('ADMIN', $_SESSION['user_roles'], true)) {
http_response_code(403);
include 'header.php';
echo '<main class="auth"><section class="auth__grid"><div class="auth__card">';
echo '<h2 class="auth__title">Zugriff verweigert</h2>';
echo '<p>Du hast keine Berechtigung, Produkte hinzuzufügen.</p>';
echo '</div></section></main>';
include 'footer.php';
exit;
}
/* =======================
1) Kategorie aus GET
======================= */
$categoryID = 0;
if (isset($_GET['categoryID']) && ctype_digit($_GET['categoryID'])) {
$categoryID = (int)$_GET['categoryID'];
} elseif (isset($_POST['categoryID']) && ctype_digit($_POST['categoryID'])) {
$categoryID = (int)$_POST['categoryID'];
}
/* =======================
2) DB-Verbindung
======================= */
$conn = new mysqli("localhost", "FSST", "L9wUNZZ9Qkbt", "FSST", 3306);
if ($conn->connect_error) {
die("Datenbankfehler");
}
/* =======================
3) Kategorien laden
======================= */
$categories = [];
$result = $conn->query("
SELECT categoryID, name
FROM categories
ORDER BY name
");
while ($row = $result->fetch_assoc()) {
$categories[] = $row;
}
/* =======================
3b) Marken laden
======================= */
$brands = [];
$result = $conn->query("
SELECT brandID, name
FROM brands
ORDER BY name
");
while ($row = $result->fetch_assoc()) {
$brands[] = $row;
}
/* =======================
4) Attribute zur Kategorie
======================= */
$attributes = [];
if ($categoryID > 0) {
$stmt = $conn->prepare("
SELECT a.attributeID, a.name, a.unit, a.dataType
FROM categoryAttributes ca
JOIN attributes a ON a.attributeID = ca.attributeID
WHERE ca.categoryID = ?
ORDER BY a.name
");
$stmt->bind_param("i", $categoryID);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$attributes[] = $row;
}
}
/* =======================
5) Produkt speichern
======================= */
$saveError = null;
$debugMode = isset($_GET['debug']) && $_GET['debug'] === '1';
$debugDetails = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['saveProduct'])) {
$model = trim($_POST['model']);
$description = $_POST['description'] ?? null;
$categoryID = (int)$_POST['categoryID'];
$brandID = (int)($_POST['brandID'] ?? 0);
$imageUrl = trim((string)($_POST['imageUrl'] ?? ''));
$imageFile = (isset($_FILES['productImage']) && is_array($_FILES['productImage'])) ? $_FILES['productImage'] : null;
$hasUpload = $imageFile && isset($imageFile['error']) && (int)$imageFile['error'] !== UPLOAD_ERR_NO_FILE;
$uploadMime = null;
if ($debugMode) {
$debugDetails['post_categoryID'] = $_POST['categoryID'] ?? null;
$debugDetails['post_brandID'] = $_POST['brandID'] ?? null;
$debugDetails['post_model'] = $model;
$debugDetails['file_present'] = $imageFile !== null ? 'yes' : 'no';
$debugDetails['file_error'] = $imageFile['error'] ?? null;
$debugDetails['file_name'] = $imageFile['name'] ?? null;
$debugDetails['file_size'] = $imageFile['size'] ?? null;
$debugDetails['file_tmp'] = isset($imageFile['tmp_name']) ? (string)$imageFile['tmp_name'] : null;
$debugDetails['upload_max_filesize'] = ini_get('upload_max_filesize');
$debugDetails['post_max_size'] = ini_get('post_max_size');
}
if ($categoryID <= 0) {
$saveError = 'Bitte eine Kategorie auswählen.';
} elseif ($brandID <= 0) {
$saveError = 'Bitte eine Marke auswählen.';
} elseif ($model === '') {
$saveError = 'Bitte ein Modell angeben.';
} elseif ($imageUrl !== '' && !filter_var($imageUrl, FILTER_VALIDATE_URL)) {
$saveError = 'Bitte eine gueltige Bild-URL eingeben.';
} elseif ($hasUpload) {
$fileError = (int)$imageFile['error'];
if ($fileError !== UPLOAD_ERR_OK) {
$saveError = 'Bild-Upload fehlgeschlagen (Code ' . $fileError . ').';
} else {
$tmp = isset($imageFile['tmp_name']) ? (string)$imageFile['tmp_name'] : '';
if ($tmp === '' || !is_uploaded_file($tmp)) {
$saveError = 'Upload-Datei ungueltig.';
} else {
$allowedMimeToExt = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
];
$mime = null;
$imageInfo = @getimagesize($tmp);
$imageType = (is_array($imageInfo) && isset($imageInfo[2])) ? (int)$imageInfo[2] : null;
if ($imageType === IMAGETYPE_PNG) {
$mime = 'image/png';
} elseif ($imageType === IMAGETYPE_JPEG) {
$mime = 'image/jpeg';
}
if (!$mime) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($tmp);
}
$fileExt = strtolower(pathinfo((string)($imageFile['name'] ?? ''), PATHINFO_EXTENSION));
if ($debugMode) {
$debugDetails['getimagesize_mime'] = $imageInfo['mime'] ?? null;
$debugDetails['getimagesize_type'] = $imageType;
$debugDetails['finfo_mime'] = $mime;
$debugDetails['file_ext'] = $fileExt;
}
if (!$mime || !isset($allowedMimeToExt[$mime])) {
if (in_array($fileExt, ['jpg', 'jpeg', 'png'], true)) {
$uploadMime = ($fileExt === 'png') ? 'image/png' : 'image/jpeg';
} else {
$saveError = 'Nur JPG oder PNG sind erlaubt. Erkannter Typ: ' . ($mime ?: 'unbekannt');
}
} else {
$uploadMime = $mime;
}
}
}
}
if ($saveError === null) {
// --- Produkt anlegen ---
$stmt = $conn->prepare("
INSERT INTO products (categoryID, brandID, model, description)
VALUES (?, ?, ?, ?)
");
if (!$stmt) {
$saveError = 'Datenbankfehler beim Anlegen des Produkts.';
} else {
$stmt->bind_param("iiss", $categoryID, $brandID, $model, $description);
$ok = $stmt->execute();
if (!$ok) {
error_log('Product insert failed: ' . $stmt->error);
$saveError = 'Produkt konnte nicht gespeichert werden (DB-Fehler).';
if ($debugMode) {
$debugDetails['db_error'] = $stmt->error;
}
} else {
$productID = $stmt->insert_id;
$publicImagePath = null;
if ($hasUpload) {
$relativeTargetDir = 'assets/images/products';
$dirTargetDir = rtrim(__DIR__, "\\/") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relativeTargetDir);
$documentRoot = isset($_SERVER['DOCUMENT_ROOT']) ? (string)$_SERVER['DOCUMENT_ROOT'] : '';
$docRootTrim = rtrim($documentRoot, "\\/");
$docTargetDir = ($docRootTrim !== '')
? $docRootTrim . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relativeTargetDir)
: '';
$targetDir = $dirTargetDir;
if ($docTargetDir !== '' && !is_dir($dirTargetDir) && is_dir($docTargetDir)) {
$targetDir = $docTargetDir;
}
if (!is_dir($targetDir) && !@mkdir($targetDir, 0755, true)) {
$saveError = 'Zielordner fuer Upload nicht verfuegbar.';
} elseif (!is_writable($targetDir)) {
$saveError = 'Zielordner ist nicht beschreibbar.';
} else {
$tmp = (string)$imageFile['tmp_name'];
$mime = $uploadMime;
if (!$mime) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($tmp);
}
$filename = $productID . '.png';
$targetPath = rtrim($targetDir, "\\/") . DIRECTORY_SEPARATOR . $filename;
$savedOk = false;
if ($mime === 'image/png') {
$savedOk = move_uploaded_file($tmp, $targetPath);
} elseif ($mime === 'image/jpeg') {
$sourceImage = @imagecreatefromjpeg($tmp);
if ($sourceImage !== false) {
$savedOk = imagepng($sourceImage, $targetPath);
imagedestroy($sourceImage);
}
}
if ($savedOk) {
$publicImagePath = $relativeTargetDir . '/' . $filename;
} else {
$saveError = 'Bild konnte nicht gespeichert werden.';
}
}
} elseif ($imageUrl !== '') {
$publicImagePath = $imageUrl;
}
if ($saveError === null && $publicImagePath !== null) {
$stmtImg = $conn->prepare("UPDATE products SET imagePath = ? WHERE productID = ?");
if ($stmtImg) {
$stmtImg->bind_param("si", $publicImagePath, $productID);
$stmtImg->execute();
}
}
// --- Attribute speichern ---
if (!empty($_POST['attributes'])) {
$stmtAttr = $conn->prepare("
INSERT INTO productAttributes
(productID, attributeID, valueString, valueNumber, valueBool)
VALUES (?, ?, ?, ?, ?)
");
foreach ($_POST['attributes'] as $attributeID => $value) {
if ($value === '' || $value === null) {
continue;
}
$valueString = null;
$valueNumber = null;
$valueBool = null;
if (is_numeric($value)) {
$valueNumber = $value;
} elseif ($value === '0' || $value === '1') {
$valueBool = (int)$value;
} else {
$valueString = trim($value);
}
$stmtAttr->bind_param(
"iisdi",
$productID,
$attributeID,
$valueString,
$valueNumber,
$valueBool
);
$stmtAttr->execute();
}
}
if ($saveError === null) {
header("Location: productAdder.php?categoryID=" . $categoryID);
exit;
}
}
}
}
}
include 'header.php';
?>
<main class="auth">
<section class="auth__grid">
<!-- Kategorie waehlen -->
<div class="auth__card">
<header class="auth__header">
<h2 class="auth__title">Kategorie wählen</h2>
</header>
<form method="get" class="auth__form">
<div class="auth__select__wrap">
<label class="auth__select__label" for="categoryID">Kategorie</label>
<select id="categoryID" name="categoryID" class="auth__select" onchange="this.form.submit()" required>
<option value="">Kategorie wählen</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['categoryID'] ?>"
<?= $cat['categoryID'] === $categoryID ? 'selected' : '' ?>>
<?= htmlspecialchars($cat['name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
</form>
</div>
<!-- Produkt anlegen -->
<?php if ($categoryID > 0): ?>
<div class="auth__card">
<header class="auth__header">
<h2 class="auth__title">Produkt hinzufügen</h2>
</header>
<form method="post" class="auth__form" enctype="multipart/form-data">
<input type="hidden" name="categoryID" value="<?= $categoryID ?>">
<?php if ($saveError): ?>
<p class="auth__error"><?= htmlspecialchars($saveError) ?></p>
<?php endif; ?>
<?php if ($debugMode && !empty($debugDetails)): ?>
<pre class="auth__error"><?= htmlspecialchars(print_r($debugDetails, true)) ?></pre>
<?php endif; ?>
<label for="brandID">Marke</label>
<select id="brandID" name="brandID" class="auth__select" required>
<option value="">Marke wählen</option>
<?php foreach ($brands as $brand): ?>
<option value="<?= $brand['brandID'] ?>">
<?= htmlspecialchars($brand['name']) ?>
</option>
<?php endforeach; ?>
</select>
<label for="model">Modell</label>
<input id="model" type="text" name="model" class="auth__input" required>
<label for="description">Beschreibung</label>
<textarea id="description" name="description" class="auth__input"></textarea>
<label for="productImage">Produktbild hochladen (PNG oder JPG)</label>
<div class="auth__field">
<input id="productImage" type="file" name="productImage" accept="image/*">
<p class="auth__tip">Erlaubt: JPG/PNG. max. 20MB.</p>
</div>
<label for="imageUrl">oder Bild-URL</label>
<input id="imageUrl" type="url" name="imageUrl" class="auth__input" placeholder="https://...">
<h3 class="auth__title">Attribute</h3>
<?php foreach ($attributes as $attr): ?>
<label>
<?= htmlspecialchars($attr['name']) ?>
<?php if ($attr['unit']): ?>
(<?= htmlspecialchars($attr['unit']) ?>)
<?php endif; ?>
</label>
<input
type="<?= $attr['dataType'] === 'number' ? 'number' : 'text' ?>"
name="attributes[<?= $attr['attributeID'] ?>]"
class="auth__input"
>
<?php endforeach; ?>
<div class="auth__actions">
<button type="submit" name="saveProduct" class="auth__submit">
Produkt speichern
</button>
</div>
</form>
</div>
<?php endif; ?>
</section>
</main>
<?php
$conn->close();
include 'footer.php';
?>