Proyectos

No se ha indicado un aulario válido.

($a["created_at"] ?? 0); }); return $projects; } /** * Get linked projects from other aularios based on aulario configuration * * @param array $aulario The aulario configuration containing linked_projects array * @param string $centro_id The centro ID for constructing file paths * @return array Array of project data arrays with is_linked and source_aulario fields added */ function get_linked_projects($aulario, $centro_id) { $linked = []; $linked_projects = $aulario["linked_projects"] ?? []; foreach ($linked_projects as $link) { $source_aulario = $link["source_aulario"] ?? ""; $project_id = $link["project_id"] ?? ""; if (empty($source_aulario) || empty($project_id)) { continue; } $source_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario/Proyectos"; $project_file = "$source_dir/$project_id.json"; if (file_exists($project_file)) { $project = json_decode(file_get_contents($project_file), true); if ($project && ($project["parent_id"] ?? null) === null) { // Mark as linked and add source info $project["is_linked"] = true; $project["source_aulario"] = $source_aulario; $linked[] = $project; } } } return $linked; } // Handle actions $message = ""; $error = ""; if ($_SERVER["REQUEST_METHOD"] === "POST") { $action = $_POST["action"] ?? ""; if ($action === "create_project") { $name = trim($_POST["name"] ?? ""); $description = trim($_POST["description"] ?? ""); $parent_id = trim($_POST["parent_id"] ?? ""); if ($name !== "") { // Determine level based on parent $level = 1; if ($parent_id !== "") { $parent = load_project($proyectos_dir, $parent_id); if ($parent) { $level = ($parent["level"] ?? 1) + 1; // Enforce max 3 levels if ($level > 3) { $error = "No se pueden crear más de 3 niveles de sub-proyectos."; } } else { $error = "Proyecto padre no encontrado."; } } if (empty($error)) { $project_id = generate_id($name); $project_data = [ "id" => $project_id, "name" => $name, "description" => $description, "created_at" => time(), "updated_at" => time(), "items" => [], "subprojects" => [], "parent_id" => $parent_id !== "" ? $parent_id : null, "level" => $level ]; save_project($proyectos_dir, $project_id, $project_data); // Create project directory $project_dir = "$proyectos_dir/$project_id"; if (!is_dir($project_dir)) { mkdir($project_dir, 0755, true); } // Update parent's subprojects list if ($parent_id !== "") { $parent = load_project($proyectos_dir, $parent_id); if ($parent) { if (!isset($parent["subprojects"])) { $parent["subprojects"] = []; } $parent["subprojects"][] = $project_id; $parent["updated_at"] = time(); save_project($proyectos_dir, $parent_id, $parent); } } header("Location: /entreaulas/proyectos.php?aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id)); exit; } } else { $error = "El nombre del proyecto es obligatorio."; } } if ($action === "delete_project") { $project_id = $_POST["project_id"] ?? ""; if ($project_id !== "") { $project_file = "$proyectos_dir/$project_id.json"; if (file_exists($project_file)) { // Load project to get parent_id $project = load_project($proyectos_dir, $project_id); // Remove from parent's subprojects list if ($project && !empty($project["parent_id"])) { $parent = load_project($proyectos_dir, $project["parent_id"]); if ($parent && isset($parent["subprojects"])) { $parent["subprojects"] = array_values(array_filter($parent["subprojects"], function($id) use ($project_id) { return $id !== $project_id; })); $parent["updated_at"] = time(); save_project($proyectos_dir, $project["parent_id"], $parent); } } unlink($project_file); // Also delete project directory $project_dir = "$proyectos_dir/$project_id"; if (is_dir($project_dir)) { // Delete all files in directory $files = glob("$project_dir/*"); foreach ($files as $file) { if (is_file($file)) { unlink($file); } } rmdir($project_dir); } $message = "Proyecto eliminado correctamente."; } } } if ($action === "add_item") { $project_id = $_POST["project_id"] ?? ""; $item_type = $_POST["item_type"] ?? "link"; $item_name = trim($_POST["item_name"] ?? ""); $item_url = trim($_POST["item_url"] ?? ""); $source_aulario_param = $_POST["source_aulario"] ?? ""; // Determine which directory to use and permission level $working_dir = $proyectos_dir; $needs_approval = false; $source_aulario_id_for_save = ""; if (!empty($source_aulario_param)) { // Validate the link $linked_projects = $aulario["linked_projects"] ?? []; foreach ($linked_projects as $link) { if (($link["source_aulario"] ?? "") === $source_aulario_param && ($link["project_id"] ?? "") === $project_id) { $permission = $link["permission"] ?? "read_only"; if ($permission === "full_edit") { $working_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_param/Proyectos"; } elseif ($permission === "request_edit") { // Changes need approval - save as pending $needs_approval = true; $source_aulario_id_for_save = $source_aulario_param; } break; } } } if ($project_id !== "" && $item_name !== "") { if ($needs_approval) { // Create pending change request $pending_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_id_for_save/Proyectos/$project_id/pending_changes"; if (!is_dir($pending_dir)) { mkdir($pending_dir, 0755, true); } $change_id = uniqid("change_"); $change_data = [ "id" => $change_id, "type" => "add_item", "requested_by_aulario" => $aulario_id, "requested_at" => time(), "status" => "pending", "item_type" => $item_type, "item_name" => $item_name, "item_url" => $item_url ]; // Handle file upload for pending changes if ($item_type === "file" && isset($_FILES["item_file"]) && $_FILES["item_file"]["error"] === UPLOAD_ERR_OK) { $ext = strtolower(pathinfo($_FILES["item_file"]["name"], PATHINFO_EXTENSION)); $allowed_extensions = ["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "jpg", "jpeg", "png", "gif", "webp", "txt", "zip", "mp4", "mp3"]; if (in_array($ext, $allowed_extensions, true)) { $safe_name = safe_filename($_FILES["item_file"]["name"]); $temp_file_path = "$pending_dir/{$change_id}_$safe_name"; if (move_uploaded_file($_FILES["item_file"]["tmp_name"], $temp_file_path)) { $change_data["pending_filename"] = basename($temp_file_path); $change_data["original_filename"] = $_FILES["item_file"]["name"]; } } } $change_file = "$pending_dir/$change_id.json"; file_put_contents($change_file, json_encode($change_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); $message = "Solicitud de cambio enviada. El aulario origen debe aprobarla."; $redirect_params = "aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id); if (!empty($source_aulario_param)) { $redirect_params .= "&source=" . urlencode($source_aulario_param); } // Don't exit yet, let the view render with the message } else { // Direct edit (full_edit permission or local project) $project = load_project($working_dir, $project_id); if ($project) { $item_id = generate_id($item_name); $item = [ "id" => $item_id, "name" => $item_name, "type" => $item_type, "created_at" => time() ]; $can_add_item = true; if ($item_type === "link" && $item_url !== "") { $item["url"] = $item_url; } elseif ($item_type === "file" && isset($_FILES["item_file"]) && $_FILES["item_file"]["error"] === UPLOAD_ERR_OK) { // Handle file upload with validation $project_dir = "$working_dir/$project_id"; if (!is_dir($project_dir)) { mkdir($project_dir, 0755, true); } // Validate file size (max 500MB as configured in PHP) $max_size = 500 * 1024 * 1024; // 500MB if ($_FILES["item_file"]["size"] > $max_size) { $error = "El archivo es demasiado grande. Tamaño máximo: 500MB."; $can_add_item = false; } // Validate file type if ($can_add_item) { $original_name = $_FILES["item_file"]["name"]; $ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION)); $allowed_extensions = ["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "jpg", "jpeg", "png", "gif", "webp", "txt", "zip", "mp4", "mp3"]; if (!in_array($ext, $allowed_extensions, true)) { $error = "Tipo de archivo no permitido. Extensiones permitidas: " . implode(", ", $allowed_extensions); $can_add_item = false; } } if ($can_add_item) { $safe_name = safe_filename($original_name); $target_path = "$project_dir/$safe_name"; // Make filename unique if exists $counter = 1; $basename = pathinfo($safe_name, PATHINFO_FILENAME); while (file_exists($target_path)) { $safe_name = safe_filename($basename . "_" . $counter . "." . $ext); $target_path = "$project_dir/$safe_name"; $counter++; } if (move_uploaded_file($_FILES["item_file"]["tmp_name"], $target_path)) { $item["filename"] = $safe_name; $item["original_name"] = $original_name; } else { $error = "No se pudo subir el archivo."; $can_add_item = false; } } } if ($can_add_item) { if (!isset($project["items"])) { $project["items"] = []; } $project["items"][] = $item; $project["updated_at"] = time(); save_project($working_dir, $project_id, $project); $redirect_params = "aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id); if (!empty($source_aulario_param)) { $redirect_params .= "&source=" . urlencode($source_aulario_param); } header("Location: /entreaulas/proyectos.php?" . $redirect_params); exit; } } } } } if ($action === "approve_change" || $action === "reject_change") { $change_id = $_POST["change_id"] ?? ""; $project_id = $_POST["project_id"] ?? ""; if (!empty($change_id) && !empty($project_id)) { $pending_dir = "$proyectos_dir/$project_id/pending_changes"; $change_file = "$pending_dir/$change_id.json"; if (file_exists($change_file)) { $change_data = json_decode(file_get_contents($change_file), true); if ($action === "approve_change") { // Apply the change $project = load_project($proyectos_dir, $project_id); if ($project) { $item_id = generate_id($change_data["item_name"]); $item = [ "id" => $item_id, "name" => $change_data["item_name"], "type" => $change_data["item_type"], "created_at" => time() ]; if ($change_data["item_type"] === "link") { $item["url"] = $change_data["item_url"]; } elseif ($change_data["item_type"] === "file" && !empty($change_data["pending_filename"])) { // Move file from pending to project directory $pending_file = "$pending_dir/" . $change_data["pending_filename"]; $project_dir = "$proyectos_dir/$project_id"; $target_file = "$project_dir/" . $change_data["pending_filename"]; if (file_exists($pending_file)) { if (!is_dir($project_dir)) { mkdir($project_dir, 0755, true); } rename($pending_file, $target_file); $item["filename"] = $change_data["pending_filename"]; $item["original_name"] = $change_data["original_filename"] ?? $change_data["pending_filename"]; } } if (!isset($project["items"])) { $project["items"] = []; } $project["items"][] = $item; $project["updated_at"] = time(); save_project($proyectos_dir, $project_id, $project); $message = "Cambio aprobado y aplicado."; } } else { // Reject - just delete pending file if exists if (!empty($change_data["pending_filename"])) { $pending_file = "$pending_dir/" . $change_data["pending_filename"]; if (file_exists($pending_file)) { unlink($pending_file); } } $message = "Cambio rechazado."; } // Delete the change request file unlink($change_file); } } } if ($action === "delete_item") { $project_id = $_POST["project_id"] ?? ""; $item_id = $_POST["item_id"] ?? ""; $source_aulario_param = $_POST["source_aulario"] ?? ""; // Determine which directory to use based on whether this is a linked project $working_dir = $proyectos_dir; if (!empty($source_aulario_param)) { // Validate the link $linked_projects = $aulario["linked_projects"] ?? []; foreach ($linked_projects as $link) { if (($link["source_aulario"] ?? "") === $source_aulario_param && ($link["project_id"] ?? "") === $project_id && (($link["permission"] ?? "read_only") === "full_edit" || ($link["permission"] ?? "read_only") === "request_edit")) { $working_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_param/Proyectos"; break; } } } if ($project_id !== "" && $item_id !== "") { $project = load_project($working_dir, $project_id); if ($project && isset($project["items"])) { $new_items = []; foreach ($project["items"] as $item) { if ($item["id"] !== $item_id) { $new_items[] = $item; } else { // Delete file if it's a file type if ($item["type"] === "file" && isset($item["filename"])) { $file_path = "$working_dir/$project_id/" . $item["filename"]; if (file_exists($file_path)) { unlink($file_path); } } } } $project["items"] = $new_items; $project["updated_at"] = time(); save_project($working_dir, $project_id, $project); $redirect_params = "aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id); if (!empty($source_aulario_param)) { $redirect_params .= "&source=" . urlencode($source_aulario_param); } header("Location: /entreaulas/proyectos.php?" . $redirect_params); exit; } } } } require_once "_incl/pre-body.php"; // Determine current view $current_project = $_GET["project"] ?? null; $view = $current_project ? "project" : "list"; ?>

Proyectos

Gestiona proyectos con enlaces y archivos para tu aulario.

($a["created_at"] ?? 0); }); if (count($projects) > 0): ?>
Compartido

elementos · sub-proyectos

No hay proyectos creados aún. ¡Crea tu primer proyecto!

Error

Proyecto no encontrado.

Volver a Proyectos
✏️ Proyecto compartido con permisos de edición: Este es un proyecto compartido desde otro aulario. Puedes ver y editar su contenido. Los cambios se guardarán directamente en el aulario origen. ✏️ Proyecto compartido con permisos de solicitud: Este es un proyecto compartido desde otro aulario. Puedes ver y proponer cambios. Los cambios requerirán aprobación del aulario origen antes de aplicarse. ℹ️ Proyecto compartido (solo lectura): Este es un proyecto compartido desde otro aulario. Solo puedes ver su contenido, pero no editarlo.

Nivel Compartido

" class="btn btn-secondary"> ← Volver al Proyecto Padre ← Volver a Proyectos
0): ?>

Sub-Proyectos

Nivel

elementos · sub-proyectos

0): ?>

Archivos y Enlaces

0): ?>

Este proyecto aún no tiene elementos. ¡Añade tu primer enlace o archivo!

0): ?>

⏳ Cambios Pendientes de Aprobación ()

Los siguientes cambios fueron solicitados por otros aularios y requieren tu aprobación:

Pendiente

Tipo:
Solicitado por:
Fecha:

">
">