/
Francuz
/
DailyPort
Обзор
Документация
Войти
/
Francuz
/
DailyPort
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/Project.php
176 строк
7 KB
Francuz
feat: количество участников проекта
16 июн 2026, 03:00
16 июн 2026, 03:00
e7edb94
Код
Авторство
О чём код?
<?php /** * Класс Project — модель проекта. * * Проект — контейнер для строк, статусов и задач. * Каждый проект имеет: * - owner_id — главный админ (создатель) * - участников (project_members) * - строки (task_rows с project_id) * * Иерархия: Проект → Строки → Статусы → Задачи */ class Project { private Database $db; public function __construct(Database $db) { $this->db = $db; } /** Получить проекты, доступные пользователю (создатель или участник) */ public function getByUser(int $userId): array { $userId = $this->db->escape((string)$userId); $result = $this->db->query(" SELECT p.* FROM projects p LEFT JOIN project_members pm ON pm.project_id = p.id WHERE p.is_active = 1 AND (p.owner_id = $userId OR pm.user_id = $userId) GROUP BY p.id ORDER BY p.name ASC "); return $result->fetch_all(MYSQLI_ASSOC); } /** Получить все активные проекты */ public function all(): array { $result = $this->db->query("SELECT * FROM projects WHERE is_active = 1 ORDER BY name ASC"); return $result->fetch_all(MYSQLI_ASSOC); } /** Найти по ID */ public function find(int $id): ?array { $id = $this->db->escape((string)$id); $result = $this->db->query("SELECT * FROM projects WHERE id = $id"); return $result->fetch_assoc() ?: null; } /** Создать проект (создатель автоматически становится участником) */ public function create(string $name, int $ownerId, ?string $description = null): int { $name = $this->db->escape($name); $ownerId = $this->db->escape((string)$ownerId); $desc = $description !== null ? "'" . $this->db->escape($description) . "'" : 'NULL'; $this->db->query("INSERT INTO projects (name, owner_id, description) VALUES ('$name', $ownerId, $desc)"); $id = (int)$this->db->query("SELECT LAST_INSERT_ID() AS id")->fetch_assoc()['id']; // Создатель автоматически становится участником с ролью owner $this->addMember($id, $ownerId, 'owner'); return $id; } /** Обновить проект */ public function update(int $id, array $data): bool { $id = $this->db->escape((string)$id); $sets = []; if (array_key_exists('name', $data)) { $sets[] = "name = '" . $this->db->escape($data['name']) . "'"; } if (array_key_exists('description', $data)) { $val = $data['description']; $sets[] = $val === null ? "description = NULL" : "description = '" . $this->db->escape($val) . "'"; } if (array_key_exists('icon', $data)) { $val = $data['icon']; $sets[] = $val === null || $val === '' ? "icon = NULL" : "icon = '" . $this->db->escape($val) . "'"; } if (empty($sets)) return false; $this->db->query("UPDATE projects SET " . implode(', ', $sets) . " WHERE id = $id"); return true; } /** Удалить проект (мягкое удаление — в архив) */ public function delete(int $id): bool { $id = $this->db->escape((string)$id); $this->db->query("UPDATE projects SET is_active = 0 WHERE id = $id"); return true; } /** Восстановить проект из архива */ public function restore(int $id): bool { $id = $this->db->escape((string)$id); $this->db->query("UPDATE projects SET is_active = 1 WHERE id = $id"); return true; } /** Получить архивные проекты */ public function archived(): array { $result = $this->db->query("SELECT * FROM projects WHERE is_active = 0 ORDER BY name ASC"); return $result->fetch_all(MYSQLI_ASSOC); } // === Участники === /** Участники проекта */ public function getMembers(int $projectId): array { $projectId = $this->db->escape((string)$projectId); $result = $this->db->query(" SELECT pm.*, u.name, u.email, u.photo FROM project_members pm JOIN users u ON u.id = pm.user_id WHERE pm.project_id = $projectId ORDER BY pm.role DESC, u.name ASC "); return $result->fetch_all(MYSQLI_ASSOC); } /** Добавить участника */ public function addMember(int $projectId, int $userId, string $role = 'member'): int { $projectId = $this->db->escape((string)$projectId); $userId = $this->db->escape((string)$userId); $role = $this->db->escape($role); $this->db->query("INSERT IGNORE INTO project_members (project_id, user_id, role) VALUES ($projectId, $userId, '$role')"); return (int)$this->db->query("SELECT LAST_INSERT_ID() AS id")->fetch_assoc()['id']; } /** Удалить участника */ public function removeMember(int $projectId, int $userId): bool { $projectId = $this->db->escape((string)$projectId); $userId = $this->db->escape((string)$userId); $this->db->query("DELETE FROM project_members WHERE project_id = $projectId AND user_id = $userId"); return true; } /** Проверить, является ли пользователь участником */ public function isMember(int $projectId, int $userId): bool { $projectId = $this->db->escape((string)$projectId); $userId = $this->db->escape((string)$userId); $result = $this->db->query("SELECT COUNT(*) AS cnt FROM project_members WHERE project_id = $projectId AND user_id = $userId"); return (int)$result->fetch_assoc()['cnt'] > 0; } /** Проверить, является ли пользователь владельцем */ public function isOwner(int $projectId, int $userId): bool { $projectId = $this->db->escape((string)$projectId); $userId = $this->db->escape((string)$userId); $result = $this->db->query("SELECT COUNT(*) AS cnt FROM projects WHERE id = $projectId AND owner_id = $userId"); return (int)$result->fetch_assoc()['cnt'] > 0; } /** Количество участников проекта */ public function countMembers(int $projectId): int { $projectId = $this->db->escape((string)$projectId); $result = $this->db->query("SELECT COUNT(*) AS cnt FROM project_members WHERE project_id = $projectId"); return (int)$result->fetch_assoc()['cnt']; } }