Menú del Comedor

No se ha indicado un aulario válido.

"basal", "label" => "Menú basal", "color" => "#0d6efd"], ["id" => "vegetariano", "label" => "Menú vegetariano", "color" => "#198754"], ["id" => "alergias", "label" => "Menú alergias", "color" => "#dc3545"], ]; $menuTypes = db_get_comedor_menu_types($centro_id, $source_aulario_id); if (!is_array($menuTypes) || count($menuTypes) === 0) { $menuTypes = $defaultMenuTypes; db_set_comedor_menu_types($centro_id, $source_aulario_id, $menuTypes); } $menuTypeIds = []; foreach ($menuTypes as $t) { if (!empty($t["id"])) { $menuTypeIds[] = $t["id"]; } } $dateParam = $_GET["date"] ?? date("Y-m-d"); $dateObj = DateTime::createFromFormat("Y-m-d", $dateParam) ?: new DateTime(); $date = $dateObj->format("Y-m-d"); $menuTypeId = $_GET["menu"] ?? ($menuTypeIds[0] ?? "basal"); if (!in_array($menuTypeId, $menuTypeIds, true)) { $menuTypeId = $menuTypeIds[0] ?? "basal"; } $ym = $dateObj->format("Y-m"); $day = $dateObj->format("d"); function blank_menu() { return [ "plates" => [ "primero" => ["name" => "", "pictogram" => ""], "segundo" => ["name" => "", "pictogram" => ""], "postre" => ["name" => "", "pictogram" => ""], ] ]; } $menuData = [ "date" => $date, "menus" => [] ]; $existing = db_get_comedor_entry($centro_id, $source_aulario_id, $ym, $day); if (is_array($existing) && !empty($existing)) { $menuData = array_merge($menuData, $existing); } if (!isset($menuData["menus"][$menuTypeId])) { $menuData["menus"][$menuTypeId] = blank_menu(); } $canEdit = in_array("sysadmin:access", $_SESSION["auth_data"]["permissions"] ?? []) && !$is_shared; $saveNotice = ""; $uploadErrors = []; function safe_filename($name) { // Normalize to base name to avoid directory traversal $name = basename($name); // Best-effort normalize encoding to avoid odd Unicode tricks if (function_exists('mb_convert_encoding')) { $name = mb_convert_encoding($name, 'UTF-8', 'UTF-8'); } // Replace disallowed characters with underscore $name = preg_replace("/[^a-zA-Z0-9._-]/", "_", $name); // Collapse multiple underscores introduced by replacement $name = preg_replace('/_+/', '_', $name); // Remove leading dots to avoid hidden/special files like ".htaccess" $name = ltrim($name, '.'); // Ensure there is at most one dot in the filename to prevent extension confusion if (substr_count($name, '.') > 1) { $parts = explode('.', $name); $ext = array_pop($parts); $base = implode('_', $parts); // Ensure extension is not empty if ($ext === '') { $name = $base === '' ? 'file' : $base; } else { $name = ($base === '' ? 'file' : $base) . '.' . $ext; } } // Trim stray dots/underscores from the start and end $name = trim($name, "._"); // Enforce a maximum length (common filesystem limit is 255 bytes) $maxLen = 255; if (strlen($name) > $maxLen) { $dotPos = strrpos($name, '.'); if ($dotPos !== false) { $ext = substr($name, $dotPos); $base = substr($name, 0, $dotPos); $baseMaxLen = $maxLen - strlen($ext); if ($baseMaxLen < 1) { // Fallback if extension is unusually long $name = substr($name, 0, $maxLen); } else { $name = substr($base, 0, $baseMaxLen) . $ext; } } else { $name = substr($name, 0, $maxLen); } } // Ensure we never return an empty or invalid filename if ($name === '' || $name === '.' || $name === '..') { $name = 'file'; } return $name; } function handle_image_upload($fieldName, $targetBaseName, $baseDir, &$uploadErrors) { if (!isset($_FILES[$fieldName]) || $_FILES[$fieldName]["error"] !== UPLOAD_ERR_OK) { return null; } $ext = strtolower(pathinfo($_FILES[$fieldName]["name"], PATHINFO_EXTENSION)); $allowed = ["jpg", "jpeg", "png", "webp", "gif"]; // Validate by extension first if (!in_array($ext, $allowed, true)) { $uploadErrors[] = "El archivo " . htmlspecialchars($_FILES[$fieldName]["name"]) . " no es una imagen válida."; return null; } // Also validate by MIME type / file contents to avoid spoofed extensions $tmpPath = $_FILES[$fieldName]["tmp_name"]; $mimeType = null; if (function_exists('finfo_open')) { $finfo = @finfo_open(FILEINFO_MIME_TYPE); if ($finfo !== false) { $mime = @finfo_file($finfo, $tmpPath); if ($mime !== false) { $mimeType = $mime; } @finfo_close($finfo); } } // Fallback: try exif_imagetype if available and finfo did not work if ($mimeType === null && function_exists('exif_imagetype')) { $type = @exif_imagetype($tmpPath); if ($type !== false) { switch ($type) { case IMAGETYPE_JPEG: $mimeType = 'image/jpeg'; break; case IMAGETYPE_PNG: $mimeType = 'image/png'; break; case IMAGETYPE_GIF: $mimeType = 'image/gif'; break; case IMAGETYPE_WEBP: $mimeType = 'image/webp'; break; } } } $allowedMime = [ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', ]; if ($mimeType === null || !in_array($mimeType, $allowedMime, true)) { $uploadErrors[] = "El archivo " . htmlspecialchars($_FILES[$fieldName]["name"]) . " no es una imagen válida."; return null; } if (!is_dir($baseDir)) { mkdir($baseDir, 0777, true); } $target = "$targetBaseName.$ext"; $targetPath = $baseDir . "/" . safe_filename($target); if (move_uploaded_file($_FILES[$fieldName]["tmp_name"], $targetPath)) { return basename($targetPath); } $uploadErrors[] = "No se pudo guardar " . htmlspecialchars($_FILES[$fieldName]["name"]) . "."; return null; } if ($_SERVER["REQUEST_METHOD"] === "POST" && $canEdit) { $action = $_POST["action"] ?? ""; if ($action === "add_type") { $newId = safe_id_segment(strtolower(trim($_POST["new_type_id"] ?? ""))); $newLabel = trim($_POST["new_type_label"] ?? ""); $newColor = trim($_POST["new_type_color"] ?? "#0d6efd"); if ($newId !== "" && $newLabel !== "") { $exists = false; foreach ($menuTypes as $t) { if (($t["id"] ?? "") === $newId) { $exists = true; break; } } if (!$exists) { $menuTypes[] = ["id" => $newId, "label" => $newLabel, "color" => $newColor]; db_set_comedor_menu_types($centro_id, $source_aulario_id, $menuTypes); header("Location: /entreaulas/comedor.php?aulario=" . urlencode($aulario_id) . "&date=" . urlencode($date) . "&menu=" . urlencode($newId)); exit; } } } if ($action === "delete_type") { $deleteId = safe_id_segment(trim($_POST["delete_type_id"] ?? "")); if ($deleteId !== "") { $newMenuTypes = array_values(array_filter($menuTypes, fn($t) => ($t["id"] ?? "") !== $deleteId)); if (count($newMenuTypes) !== count($menuTypes)) { $menuTypes = $newMenuTypes; db_set_comedor_menu_types($centro_id, $source_aulario_id, $menuTypes); $redirectMenuId = !empty($menuTypes) ? $menuTypes[0]["id"] : "basal"; header("Location: /entreaulas/comedor.php?aulario=" . urlencode($aulario_id) . "&date=" . urlencode($date) . "&menu=" . urlencode($redirectMenuId)); exit; } } } if ($action === "rename_type") { $renameId = safe_id_segment(trim($_POST["rename_type_id"] ?? "")); $newLabel = trim($_POST["rename_type_label"] ?? ""); $newColor = trim($_POST["rename_type_color"] ?? ""); if ($renameId !== "" && $newLabel !== "") { foreach ($menuTypes as &$t) { if (($t["id"] ?? "") === $renameId) { $t["label"] = $newLabel; if ($newColor !== "") { $t["color"] = $newColor; } break; } } unset($t); db_set_comedor_menu_types($centro_id, $source_aulario_id, $menuTypes); header("Location: /entreaulas/comedor.php?aulario=" . urlencode($aulario_id) . "&date=" . urlencode($date) . "&menu=" . urlencode($renameId)); exit; } } if ($action === "save") { $menuTypeId = safe_id_segment($_POST["menu_type"] ?? $menuTypeId); if (!isset($menuData["menus"][$menuTypeId])) { $menuData["menus"][$menuTypeId] = blank_menu(); } // Pictogram images still stored on filesystem in Comedor dir $baseDir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_id/Comedor/$ym/$day"; $plates = ["primero", "segundo", "postre"]; foreach ($plates as $plate) { $name = trim($_POST["name_" . $plate] ?? ""); $menuData["menus"][$menuTypeId]["plates"][$plate]["name"] = $name; $pictUpload = handle_image_upload("pictogram_file_" . $plate, $menuTypeId . "_" . $plate . "_pict", $baseDir, $uploadErrors); if ($pictUpload !== null) { $menuData["menus"][$menuTypeId]["plates"][$plate]["pictogram"] = $pictUpload; } } db_set_comedor_entry($centro_id, $source_aulario_id, $ym, $day, $menuData); $saveNotice = "Menú guardado correctamente."; } } $menuForType = $menuData["menus"][$menuTypeId] ?? blank_menu(); function image_src($value, $centro_id, $source_aulario_id, $date) { if (!$value) { return ""; } if (filter_var($value, FILTER_VALIDATE_URL)) { return $value; } return "/entreaulas/_filefetch.php?type=comedor_image¢ro=" . urlencode($centro_id) . "&aulario=" . urlencode($source_aulario_id) . "&date=" . urlencode($date) . "&file=" . urlencode($value); } $prevDate = (clone $dateObj)->modify("-1 day")->format("Y-m-d"); $nextDate = (clone $dateObj)->modify("+1 day")->format("Y-m-d"); $userAulas = $_SESSION["auth_data"]["entreaulas"]["aulas"] ?? []; $aulaOptions = []; foreach ($userAulas as $aulaId) { $aulaIdSafe = safe_id_segment($aulaId); if ($aulaIdSafe === "") { continue; } $aulaData = db_get_aulario($centro_id, $aulaIdSafe); $aulaOptions[] = [ "id" => $aulaIdSafe, "name" => $aulaData["name"] ?? $aulaIdSafe, ]; } require_once "_incl/pre-body.php"; ?>
ℹ️ Datos compartidos: Este aulario está mostrando los menús del aulario . Para editar, debes acceder al aulario origen o desactivar el acceso compartido en la configuración.
0): ?>
⟵ Día anterior Día siguiente ⟶

Tipos de menú

" class="btn btn-lg" style="background: ; color: white; border: 3px solid ;">
Editar menú
$plateLabel): $plate = $menuForType["plates"][$plateKey] ?? ["name" => "", "pictogram" => ""]; ?>

" placeholder="Ej. Lentejas">
Administrar tipos de menú

Añadir nuevo tipo de menú

Tipos de menú existentes

;">

ID:
Color: ; border-radius: 3px; vertical-align: middle;">
">
" style="display: none; margin-top: 15px; padding-top: 15px; border-top: 1px solid #ddd;">
">
" required>
">