|
@@ -12,11 +12,66 @@ $pageTitle = 'Produkte verwalten';
|
|
|
$message = '';
|
|
$message = '';
|
|
|
$messageType = '';
|
|
$messageType = '';
|
|
|
|
|
|
|
|
|
|
+function handleImageUpload($fileInputName = 'image_file') {
|
|
|
|
|
+ if (!isset($_FILES[$fileInputName]) || $_FILES[$fileInputName]['error'] === UPLOAD_ERR_NO_FILE) {
|
|
|
|
|
+ return ['success' => true, 'filename' => null];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $file = $_FILES[$fileInputName];
|
|
|
|
|
+ if ($file['error'] !== UPLOAD_ERR_OK) {
|
|
|
|
|
+ return ['success' => false, 'message' => 'Upload fehlgeschlagen. Bitte erneut versuchen.'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $allowedExtensions = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
|
|
|
|
|
+ $originalName = basename($file['name']);
|
|
|
|
|
+ $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
|
|
|
|
|
+ if (!in_array($extension, $allowedExtensions, true)) {
|
|
|
|
|
+ return ['success' => false, 'message' => 'Ungültiger Dateityp. Erlaubt: JPG, PNG, WEBP, GIF.'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $finfo = new finfo(FILEINFO_MIME_TYPE);
|
|
|
|
|
+ $mimeType = $finfo->file($file['tmp_name']);
|
|
|
|
|
+ $allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
|
|
|
|
+ if (!in_array($mimeType, $allowedMimes, true)) {
|
|
|
|
|
+ return ['success' => false, 'message' => 'Die hochgeladene Datei ist kein gültiges Bild.'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $imagesDir = __DIR__ . '/../assets/images';
|
|
|
|
|
+ if (!is_dir($imagesDir)) {
|
|
|
|
|
+ mkdir($imagesDir, 0755, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $safeBaseName = preg_replace('/[^a-zA-Z0-9_-]/', '-', pathinfo($originalName, PATHINFO_FILENAME));
|
|
|
|
|
+ $safeBaseName = trim($safeBaseName, '-');
|
|
|
|
|
+ if ($safeBaseName === '') {
|
|
|
|
|
+ $safeBaseName = 'bild';
|
|
|
|
|
+ }
|
|
|
|
|
+ $targetFilename = $safeBaseName . '.' . $extension;
|
|
|
|
|
+ $targetPath = $imagesDir . '/' . $targetFilename;
|
|
|
|
|
+ $counter = 1;
|
|
|
|
|
+ while (file_exists($targetPath)) {
|
|
|
|
|
+ $targetFilename = $safeBaseName . '-' . $counter . '.' . $extension;
|
|
|
|
|
+ $targetPath = $imagesDir . '/' . $targetFilename;
|
|
|
|
|
+ $counter++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
|
|
|
|
|
+ return ['success' => false, 'message' => 'Bild konnte nicht gespeichert werden.'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return ['success' => true, 'filename' => $targetFilename];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Handle product operations
|
|
// Handle product operations
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
$products = getProducts();
|
|
$products = getProducts();
|
|
|
|
|
|
|
|
if (isset($_POST['add_product'])) {
|
|
if (isset($_POST['add_product'])) {
|
|
|
|
|
+ $uploadResult = handleImageUpload();
|
|
|
|
|
+ if (!$uploadResult['success']) {
|
|
|
|
|
+ $message = $uploadResult['message'];
|
|
|
|
|
+ $messageType = 'error';
|
|
|
|
|
+ } else {
|
|
|
// Generate new ID
|
|
// Generate new ID
|
|
|
$newId = 1;
|
|
$newId = 1;
|
|
|
if (!empty($products)) {
|
|
if (!empty($products)) {
|
|
@@ -30,7 +85,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
'description' => sanitize($_POST['description']),
|
|
'description' => sanitize($_POST['description']),
|
|
|
'price' => (float)$_POST['price'],
|
|
'price' => (float)$_POST['price'],
|
|
|
'category' => sanitize($_POST['category']),
|
|
'category' => sanitize($_POST['category']),
|
|
|
- 'image' => sanitize($_POST['image'])
|
|
|
|
|
|
|
+ 'image' => $uploadResult['filename'] !== null ? $uploadResult['filename'] : sanitize($_POST['image'])
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
// Handle stock - per size for apparel, general for merch
|
|
// Handle stock - per size for apparel, general for merch
|
|
@@ -53,9 +108,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
saveProducts($products);
|
|
saveProducts($products);
|
|
|
$message = 'Produkt erfolgreich hinzugefügt.';
|
|
$message = 'Produkt erfolgreich hinzugefügt.';
|
|
|
$messageType = 'success';
|
|
$messageType = 'success';
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isset($_POST['update_product'])) {
|
|
if (isset($_POST['update_product'])) {
|
|
|
|
|
+ $uploadResult = handleImageUpload();
|
|
|
|
|
+ if (!$uploadResult['success']) {
|
|
|
|
|
+ $message = $uploadResult['message'];
|
|
|
|
|
+ $messageType = 'error';
|
|
|
|
|
+ } else {
|
|
|
$productId = (int)$_POST['product_id'];
|
|
$productId = (int)$_POST['product_id'];
|
|
|
foreach ($products as &$product) {
|
|
foreach ($products as &$product) {
|
|
|
if ($product['id'] == $productId) {
|
|
if ($product['id'] == $productId) {
|
|
@@ -63,7 +124,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
$product['description'] = sanitize($_POST['description']);
|
|
$product['description'] = sanitize($_POST['description']);
|
|
|
$product['price'] = (float)$_POST['price'];
|
|
$product['price'] = (float)$_POST['price'];
|
|
|
$product['category'] = sanitize($_POST['category']);
|
|
$product['category'] = sanitize($_POST['category']);
|
|
|
- $product['image'] = sanitize($_POST['image']);
|
|
|
|
|
|
|
+ $product['image'] = $uploadResult['filename'] !== null ? $uploadResult['filename'] : sanitize($_POST['image']);
|
|
|
|
|
|
|
|
// Update stock - per size for apparel, general for merch
|
|
// Update stock - per size for apparel, general for merch
|
|
|
if ($product['category'] === 'apparel') {
|
|
if ($product['category'] === 'apparel') {
|
|
@@ -97,6 +158,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
saveProducts($products);
|
|
saveProducts($products);
|
|
|
$message = 'Produkt erfolgreich aktualisiert.';
|
|
$message = 'Produkt erfolgreich aktualisiert.';
|
|
|
$messageType = 'success';
|
|
$messageType = 'success';
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isset($_POST['delete_product'])) {
|
|
if (isset($_POST['delete_product'])) {
|
|
@@ -138,7 +200,7 @@ include __DIR__ . '/../includes/header.php';
|
|
|
<?php if ($editingProduct): ?>
|
|
<?php if ($editingProduct): ?>
|
|
|
<div class="panel" style="padding: 2rem;">
|
|
<div class="panel" style="padding: 2rem;">
|
|
|
<h3>Produkt bearbeiten</h3>
|
|
<h3>Produkt bearbeiten</h3>
|
|
|
- <form method="POST">
|
|
|
|
|
|
|
+ <form method="POST" enctype="multipart/form-data">
|
|
|
<input type="hidden" name="product_id" value="<?php echo $editingProduct['id']; ?>">
|
|
<input type="hidden" name="product_id" value="<?php echo $editingProduct['id']; ?>">
|
|
|
<div class="form-group">
|
|
<div class="form-group">
|
|
|
<label for="name">Name *</label>
|
|
<label for="name">Name *</label>
|
|
@@ -185,6 +247,11 @@ include __DIR__ . '/../includes/header.php';
|
|
|
<label for="image">Bilddateiname (z.B. tshirt.jpg)</label>
|
|
<label for="image">Bilddateiname (z.B. tshirt.jpg)</label>
|
|
|
<input type="text" id="image" name="image" value="<?php echo htmlspecialchars($editingProduct['image']); ?>">
|
|
<input type="text" id="image" name="image" value="<?php echo htmlspecialchars($editingProduct['image']); ?>">
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="image_file">Oder neues Bild hochladen</label>
|
|
|
|
|
+ <input type="file" id="image_file" name="image_file" accept=".jpg,.jpeg,.png,.webp,.gif,image/*">
|
|
|
|
|
+ <small>Upload nach <code>assets/images</code>; ersetzt den Dateinamen oben automatisch.</small>
|
|
|
|
|
+ </div>
|
|
|
<script>
|
|
<script>
|
|
|
function toggleStockFields() {
|
|
function toggleStockFields() {
|
|
|
const category = document.getElementById('category').value;
|
|
const category = document.getElementById('category').value;
|
|
@@ -227,7 +294,7 @@ include __DIR__ . '/../includes/header.php';
|
|
|
<?php else: ?>
|
|
<?php else: ?>
|
|
|
<div class="panel" style="padding: 2rem;">
|
|
<div class="panel" style="padding: 2rem;">
|
|
|
<h3>Neues Produkt hinzufügen</h3>
|
|
<h3>Neues Produkt hinzufügen</h3>
|
|
|
- <form method="POST">
|
|
|
|
|
|
|
+ <form method="POST" enctype="multipart/form-data">
|
|
|
<div class="form-group">
|
|
<div class="form-group">
|
|
|
<label for="name">Name *</label>
|
|
<label for="name">Name *</label>
|
|
|
<input type="text" id="name" name="name" required>
|
|
<input type="text" id="name" name="name" required>
|
|
@@ -260,6 +327,11 @@ include __DIR__ . '/../includes/header.php';
|
|
|
<label for="image">Bilddateiname (z.B. tshirt.jpg)</label>
|
|
<label for="image">Bilddateiname (z.B. tshirt.jpg)</label>
|
|
|
<input type="text" id="image" name="image">
|
|
<input type="text" id="image" name="image">
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="image_file">Oder Bild hochladen</label>
|
|
|
|
|
+ <input type="file" id="image_file" name="image_file" accept=".jpg,.jpeg,.png,.webp,.gif,image/*">
|
|
|
|
|
+ <small>Upload nach <code>assets/images</code>; Dateiname wird automatisch übernommen.</small>
|
|
|
|
|
+ </div>
|
|
|
<script>
|
|
<script>
|
|
|
function toggleStockFields() {
|
|
function toggleStockFields() {
|
|
|
const category = document.getElementById('category').value;
|
|
const category = document.getElementById('category').value;
|