1. Создание личных проектов 2. Управление командой 3. Приглашение участников 4. Уведомления и многое другое...
238 lines
8.9 KiB
PHP
238 lines
8.9 KiB
PHP
<?php
|
||
|
||
class ProjectInvite {
|
||
|
||
const STATUS_PENDING = 'pending';
|
||
const STATUS_ACCEPTED = 'accepted';
|
||
const STATUS_DECLINED = 'declined';
|
||
|
||
// ==================== СОЗДАНИЕ ПРИГЛАШЕНИЯ ====================
|
||
|
||
/**
|
||
* Создать приглашение в проект
|
||
*/
|
||
public static function create(int $project_id, int $to_user_id, int $from_user_id, bool $is_admin = false, ?array $permissions = null): array {
|
||
// Нельзя пригласить себя
|
||
if ($to_user_id === $from_user_id) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Нельзя пригласить себя в проект']];
|
||
}
|
||
|
||
// Проверяем, что пользователь существует
|
||
$user = Database::get('accounts', ['id'], ['id' => $to_user_id]);
|
||
if (!$user) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Пользователь не найден']];
|
||
}
|
||
|
||
// Проверяем, что пользователь ещё не участник проекта
|
||
if (ProjectAccess::isMember($project_id, $to_user_id)) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Пользователь уже участник проекта']];
|
||
}
|
||
|
||
// Проверяем, нет ли уже pending-приглашения
|
||
if (self::hasPending($project_id, $to_user_id)) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Пользователь уже приглашён, ожидается ответ']];
|
||
}
|
||
|
||
// Права по умолчанию
|
||
$perms = $permissions ?? ProjectAccess::DEFAULT_PERMISSIONS;
|
||
|
||
// Сохраняем is_admin в permissions для передачи при accept
|
||
$inviteData = [
|
||
'is_admin' => $is_admin,
|
||
'permissions' => $perms
|
||
];
|
||
|
||
Database::insert('project_invites', [
|
||
'id_project' => $project_id,
|
||
'id_from_user' => $from_user_id,
|
||
'id_to_user' => $to_user_id,
|
||
'status' => self::STATUS_PENDING,
|
||
'permissions' => json_encode($inviteData),
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
|
||
return ['success' => true, 'id' => Database::id()];
|
||
}
|
||
|
||
// ==================== ПРОВЕРКИ ====================
|
||
|
||
/**
|
||
* Есть ли pending-приглашение для пользователя в проект
|
||
*/
|
||
public static function hasPending(int $project_id, int $to_user_id): bool {
|
||
return Database::has('project_invites', [
|
||
'id_project' => $project_id,
|
||
'id_to_user' => $to_user_id,
|
||
'status' => self::STATUS_PENDING
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Получить количество pending-приглашений для пользователя
|
||
*/
|
||
public static function getPendingCount(int $user_id): int {
|
||
return Database::count('project_invites', [
|
||
'id_to_user' => $user_id,
|
||
'status' => self::STATUS_PENDING
|
||
]);
|
||
}
|
||
|
||
// ==================== ПОЛУЧЕНИЕ ПРИГЛАШЕНИЙ ====================
|
||
|
||
/**
|
||
* Получить все pending-приглашения для пользователя (входящие)
|
||
*/
|
||
public static function getMyPending(int $user_id): array {
|
||
$invites = Database::select('project_invites', [
|
||
'[>]project' => ['id_project' => 'id'],
|
||
'[>]accounts' => ['id_from_user' => 'id']
|
||
], [
|
||
'project_invites.id',
|
||
'project_invites.id_project',
|
||
'project_invites.created_at',
|
||
'project_invites.permissions',
|
||
'project.name(project_name)',
|
||
'accounts.name(from_user_name)',
|
||
'accounts.username(from_user_username)',
|
||
'accounts.avatar_url(from_user_avatar)'
|
||
], [
|
||
'project_invites.id_to_user' => $user_id,
|
||
'project_invites.status' => self::STATUS_PENDING,
|
||
'ORDER' => ['project_invites.created_at' => 'DESC']
|
||
]);
|
||
|
||
return array_map(function($invite) {
|
||
$permData = $invite['permissions'] ? json_decode($invite['permissions'], true) : [];
|
||
return [
|
||
'id' => (int)$invite['id'],
|
||
'project_id' => (int)$invite['id_project'],
|
||
'project_name' => $invite['project_name'],
|
||
'from_user' => [
|
||
'name' => $invite['from_user_name'],
|
||
'username' => $invite['from_user_username'],
|
||
'avatar_url' => $invite['from_user_avatar']
|
||
],
|
||
'is_admin' => $permData['is_admin'] ?? false,
|
||
'created_at' => $invite['created_at']
|
||
];
|
||
}, $invites);
|
||
}
|
||
|
||
/**
|
||
* Получить pending-приглашения для проекта (для админа)
|
||
*/
|
||
public static function getProjectPending(int $project_id): array {
|
||
$invites = Database::select('project_invites', [
|
||
'[>]accounts' => ['id_to_user' => 'id']
|
||
], [
|
||
'project_invites.id',
|
||
'project_invites.id_to_user',
|
||
'project_invites.created_at',
|
||
'project_invites.permissions',
|
||
'accounts.name',
|
||
'accounts.username',
|
||
'accounts.avatar_url'
|
||
], [
|
||
'project_invites.id_project' => $project_id,
|
||
'project_invites.status' => self::STATUS_PENDING,
|
||
'ORDER' => ['project_invites.created_at' => 'DESC']
|
||
]);
|
||
|
||
return array_map(function($invite) {
|
||
$permData = $invite['permissions'] ? json_decode($invite['permissions'], true) : [];
|
||
return [
|
||
'id' => (int)$invite['id'],
|
||
'id_user' => (int)$invite['id_to_user'],
|
||
'name' => $invite['name'],
|
||
'username' => $invite['username'],
|
||
'avatar_url' => $invite['avatar_url'],
|
||
'is_admin' => $permData['is_admin'] ?? false,
|
||
'created_at' => $invite['created_at'],
|
||
'status' => 'pending'
|
||
];
|
||
}, $invites);
|
||
}
|
||
|
||
// ==================== ОТВЕТ НА ПРИГЛАШЕНИЕ ====================
|
||
|
||
/**
|
||
* Принять приглашение
|
||
*/
|
||
public static function accept(int $invite_id, int $user_id): array {
|
||
$invite = Database::get('project_invites', '*', [
|
||
'id' => $invite_id,
|
||
'id_to_user' => $user_id,
|
||
'status' => self::STATUS_PENDING
|
||
]);
|
||
|
||
if (!$invite) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Приглашение не найдено или уже обработано']];
|
||
}
|
||
|
||
$project_id = (int)$invite['id_project'];
|
||
$permData = $invite['permissions'] ? json_decode($invite['permissions'], true) : [];
|
||
$is_admin = $permData['is_admin'] ?? false;
|
||
$permissions = $permData['permissions'] ?? ProjectAccess::DEFAULT_PERMISSIONS;
|
||
|
||
// Добавляем в project_members
|
||
Database::insert('project_members', [
|
||
'id_project' => $project_id,
|
||
'id_user' => $user_id,
|
||
'is_admin' => $is_admin ? 1 : 0,
|
||
'permissions' => json_encode($permissions),
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
|
||
// Обновляем статус приглашения
|
||
Database::update('project_invites', [
|
||
'status' => self::STATUS_ACCEPTED,
|
||
'responded_at' => date('Y-m-d H:i:s')
|
||
], ['id' => $invite_id]);
|
||
|
||
return ['success' => true, 'project_id' => $project_id];
|
||
}
|
||
|
||
/**
|
||
* Отклонить приглашение
|
||
*/
|
||
public static function decline(int $invite_id, int $user_id): array {
|
||
$invite = Database::get('project_invites', ['id'], [
|
||
'id' => $invite_id,
|
||
'id_to_user' => $user_id,
|
||
'status' => self::STATUS_PENDING
|
||
]);
|
||
|
||
if (!$invite) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Приглашение не найдено или уже обработано']];
|
||
}
|
||
|
||
Database::update('project_invites', [
|
||
'status' => self::STATUS_DECLINED,
|
||
'responded_at' => date('Y-m-d H:i:s')
|
||
], ['id' => $invite_id]);
|
||
|
||
return ['success' => true];
|
||
}
|
||
|
||
/**
|
||
* Отменить приглашение (для админа)
|
||
*/
|
||
public static function cancel(int $invite_id, int $project_id): array {
|
||
$invite = Database::get('project_invites', ['id'], [
|
||
'id' => $invite_id,
|
||
'id_project' => $project_id,
|
||
'status' => self::STATUS_PENDING
|
||
]);
|
||
|
||
if (!$invite) {
|
||
return ['success' => false, 'errors' => ['invite' => 'Приглашение не найдено']];
|
||
}
|
||
|
||
Database::delete('project_invites', ['id' => $invite_id]);
|
||
|
||
return ['success' => true];
|
||
}
|
||
}
|
||
|
||
?>
|