db_name, [ 'id', 'id_order', 'name', 'id_ready', 'id_admin' ], [ 'ORDER' => ['id_order' => 'ASC'] ]); // Обрабатываем id_admin для каждого проекта return array_map(function($project) use ($current_user_id) { $admins = $project['id_admin'] ? json_decode($project['id_admin'], true) : []; if ($current_user_id && in_array((int)$current_user_id, $admins, true)) { $project['id_admin'] = true; } else { unset($project['id_admin']); } return $project; }, $projects); } // Получение одного проекта // $current_user_id — ID текущего пользователя для проверки админства public static function get($id, $current_user_id = null) { $project = Database::get('project', [ 'id', 'id_order', 'name', 'id_ready', 'id_admin' ], ['id' => $id]); if ($project) { $admins = $project['id_admin'] ? json_decode($project['id_admin'], true) : []; // Если передан user_id — проверяем админство if ($current_user_id && in_array((int)$current_user_id, $admins, true)) { $project['id_admin'] = true; } else { // Не админ — убираем поле unset($project['id_admin']); } } return $project; } // Получение id_ready (ID колонки "Готово") по ID проекта public static function getReadyColumnId($project_id) { $project = Database::get('project', ['id_ready'], ['id' => $project_id]); return $project ? (int)$project['id_ready'] : null; } // Получение колонок проекта public static function getColumns($project_id) { return Database::select('columns', [ 'id', 'name_columns', 'color', 'id_order' ], [ 'id_project' => $project_id, 'ORDER' => ['id_order' => 'ASC'] ]); } // Получение отделов проекта public static function getDepartments($project_id) { return Database::select('departments', [ 'id', 'name_departments', 'color' ], [ 'id_project' => $project_id ]); } // Получение всех данных проекта (проект + колонки + отделы + метки) public static function getProjectData($project_id) { // Получаем ID текущего пользователя для проверки админства $current_user_id = RestApi::getCurrentUserId(); $project = self::get($project_id, $current_user_id); if (!$project) { return null; } // Получаем метки (глобальные) $labels = Database::select('labels', [ 'id', 'name_labels', 'icon', 'color' ]); return [ 'project' => $project, 'columns' => self::getColumns($project_id), 'departments' => self::getDepartments($project_id), 'labels' => $labels ]; } // Проверка является ли пользователь админом проекта public static function isAdmin($project_id, $user_id): bool { $project = Database::get('project', ['id_admin'], ['id' => $project_id]); if (!$project || !$project['id_admin']) { return false; } $admins = json_decode($project['id_admin'], true) ?: []; return in_array((int)$user_id, $admins, true); } // ==================== CRUD ПРОЕКТОВ ==================== // Создание проекта с дефолтными колонками public static function create($name, $user_id) { // Получаем максимальный id_order $maxOrder = Database::max('project', 'id_order') ?? 0; // Создаём проект Database::insert('project', [ 'name' => $name, 'id_order' => $maxOrder + 1, 'id_admin' => json_encode([(int)$user_id]), 'id_member' => json_encode([]) ]); $projectId = Database::id(); if (!$projectId) { return ['success' => false, 'errors' => ['project' => 'Ошибка создания проекта']]; } // Создаём дефолтные колонки Database::insert('columns', [ 'name_columns' => 'К выполнению', 'color' => '#6366f1', 'id_project' => $projectId, 'id_order' => 1 ]); $firstColumnId = Database::id(); Database::insert('columns', [ 'name_columns' => 'Готово', 'color' => '#22c55e', 'id_project' => $projectId, 'id_order' => 2 ]); $readyColumnId = Database::id(); // Устанавливаем id_ready Database::update('project', ['id_ready' => $readyColumnId], ['id' => $projectId]); return [ 'success' => true, 'id' => $projectId, 'columns' => [ ['id' => $firstColumnId, 'name_columns' => 'К выполнению', 'color' => '#6366f1', 'id_order' => 1], ['id' => $readyColumnId, 'name_columns' => 'Готово', 'color' => '#22c55e', 'id_order' => 2] ], 'id_ready' => $readyColumnId ]; } // Обновление проекта public static function update($id, $name, $user_id) { // Проверяем права if (!self::isAdmin($id, $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на редактирование']]; } Database::update('project', ['name' => $name], ['id' => $id]); return ['success' => true]; } // Удаление проекта (каскадно: колонки, задачи, комментарии, файлы) public static function delete($id, $user_id) { // Проверяем права if (!self::isAdmin($id, $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на удаление']]; } // Получаем все задачи проекта $tasks = Database::select('cards_task', ['id'], ['id_project' => $id]); $taskIds = array_column($tasks, 'id'); if (!empty($taskIds)) { // Получаем все комментарии к задачам $comments = Database::select('comments', ['id'], ['id_task' => $taskIds]); // Удаляем файлы комментариев с диска foreach ($comments as $comment) { FileUpload::deleteFolder('comment', $comment['id']); } // Удаляем комментарии из БД Database::delete('comments', ['id_task' => $taskIds]); } // Удаляем файлы задач с диска foreach ($tasks as $task) { FileUpload::deleteFolder('task', $task['id']); } // Удаляем задачи из БД Database::delete('cards_task', ['id_project' => $id]); // Удаляем колонки Database::delete('columns', ['id_project' => $id]); // Удаляем отделы проекта Database::delete('departments', ['id_project' => $id]); // Удаляем проект Database::delete('project', ['id' => $id]); return ['success' => true]; } // Обновление порядка проектов public static function updateOrder($ids, $user_id) { foreach ($ids as $order => $id) { Database::update('project', ['id_order' => $order + 1], ['id' => $id]); } return ['success' => true]; } // ==================== CRUD КОЛОНОК ==================== // Добавление колонки public static function addColumn($project_id, $name, $color, $user_id) { // Проверяем права if (!self::isAdmin($project_id, $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на редактирование']]; } // Получаем максимальный id_order для проекта $maxOrder = Database::max('columns', 'id_order', ['id_project' => $project_id]) ?? 0; Database::insert('columns', [ 'name_columns' => $name, 'color' => $color ?: '#6366f1', 'id_project' => $project_id, 'id_order' => $maxOrder + 1 ]); $columnId = Database::id(); return [ 'success' => true, 'id' => $columnId, 'column' => [ 'id' => $columnId, 'name_columns' => $name, 'color' => $color ?: '#6366f1', 'id_order' => $maxOrder + 1 ] ]; } // Обновление колонки public static function updateColumn($id, $name, $color, $user_id) { // Получаем колонку для проверки проекта $column = Database::get('columns', ['id_project'], ['id' => $id]); if (!$column) { return ['success' => false, 'errors' => ['column' => 'Колонка не найдена']]; } // Проверяем права if (!self::isAdmin($column['id_project'], $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на редактирование']]; } $updateData = []; if ($name !== null) $updateData['name_columns'] = $name; if ($color !== null) $updateData['color'] = $color; if (!empty($updateData)) { Database::update('columns', $updateData, ['id' => $id]); } return ['success' => true]; } // Удаление колонки (возвращает количество задач для подтверждения) public static function getColumnTasksCount($column_id) { return Database::count('cards_task', ['column_id' => $column_id]); } // Удаление колонки с задачами public static function deleteColumn($id, $user_id) { // Получаем колонку для проверки проекта $column = Database::get('columns', ['id_project', 'id_order'], ['id' => $id]); if (!$column) { return ['success' => false, 'errors' => ['column' => 'Колонка не найдена']]; } // Проверяем права if (!self::isAdmin($column['id_project'], $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на удаление']]; } // Проверяем, не является ли это последней колонкой перед "Готово" // Минимум должно быть 3 колонки (2 обычные + готово), чтобы можно было удалить $columnsCount = Database::count('columns', ['id_project' => $column['id_project']]); if ($columnsCount <= 2) { return ['success' => false, 'errors' => ['column' => 'Нельзя удалить последнюю колонку перед финальной']]; } // Проверяем, не является ли это последней (финальной) колонкой $lastColumn = Database::get('columns', ['id'], [ 'id_project' => $column['id_project'], 'ORDER' => ['id_order' => 'DESC'], 'LIMIT' => 1 ]); if ($lastColumn && (int)$lastColumn['id'] === (int)$id) { return ['success' => false, 'errors' => ['column' => 'Нельзя удалить финальную колонку (последнюю)']]; } // Получаем задачи колонки $tasks = Database::select('cards_task', ['id'], ['column_id' => $id]); $taskIds = array_column($tasks, 'id'); // Удаляем комментарии к задачам if (!empty($taskIds)) { Database::delete('comments', ['id_task' => $taskIds]); } // Удаляем задачи Database::delete('cards_task', ['column_id' => $id]); // Удаляем колонку Database::delete('columns', ['id' => $id]); // Обновляем id_ready на новую последнюю колонку $newLastColumn = Database::get('columns', ['id'], [ 'id_project' => $column['id_project'], 'ORDER' => ['id_order' => 'DESC'], 'LIMIT' => 1 ]); if ($newLastColumn) { Database::update('project', ['id_ready' => $newLastColumn['id']], ['id' => $column['id_project']]); } return ['success' => true, 'deleted_tasks' => count($taskIds)]; } // Обновление порядка колонок public static function updateColumnsOrder($project_id, $ids, $user_id) { // Проверяем права if (!self::isAdmin($project_id, $user_id)) { return ['success' => false, 'errors' => ['access' => 'Нет прав на редактирование']]; } foreach ($ids as $order => $id) { Database::update('columns', ['id_order' => $order + 1], ['id' => $id, 'id_project' => $project_id]); } // Автоматически устанавливаем id_ready на последнюю колонку $lastColumnId = end($ids); if ($lastColumnId) { Database::update('project', ['id_ready' => $lastColumnId], ['id' => $project_id]); } return ['success' => true]; } // Установка финальной колонки (id_ready) - ЗАБЛОКИРОВАНО // Финальная колонка всегда последняя, изменение запрещено public static function setReadyColumn($project_id, $column_id, $user_id) { return ['success' => false, 'errors' => ['column' => 'Изменение финальной колонки запрещено. Финальная колонка всегда последняя.']]; } } ?>