currentUser(); $group_repo = new CategoryGroupRepository(); $validation = $this->buildValidation($request->post()); if (!$validation->check()) { return $this->json(['success' => false, 'errors' => $validation->errors()], 422); } $type = $request->post('type'); $title = $request->post('title'); if ($group_repo->findActiveDuplicate($user->id, $type, $title)) { return $this->json(['success' => false, 'errors' => ['title' => 'Такая группа уже есть']], 422); } $archived_duplicate = $group_repo->findArchivedDuplicate($user->id, $type, $title); if ($archived_duplicate) { return $this->json([ 'success' => false, 'archived' => ['id' => $archived_duplicate->id, 'title' => $archived_duplicate->title], ], 422); } $group_repo->create([ 'user_id' => $user->id, 'title' => $title, 'type' => $type, 'is_delete' => false, 'order' => 0, ]); return $this->json(['success' => true]); } /** * @return string JSON * @throws HTTPException|MyException */ public function editAction(): string { $request = Request::$current; $user = $this->currentUser(); $group_repo = new CategoryGroupRepository(); $group = $this->ownGroup($group_repo, $user, (int)$request->param(0)); $validation = $this->buildValidation($request->post()); if (!$validation->check()) { return $this->json(['success' => false, 'errors' => $validation->errors()], 422); } $type = $request->post('type'); $title = $request->post('title'); if ($group_repo->findActiveDuplicate($user->id, $type, $title, (int)$group->id)) { return $this->json(['success' => false, 'errors' => ['title' => 'Такая группа уже есть']], 422); } $archived_duplicate = $group_repo->findArchivedDuplicate($user->id, $type, $title, (int)$group->id); if ($archived_duplicate) { return $this->json([ 'success' => false, 'archived' => ['id' => $archived_duplicate->id, 'title' => $archived_duplicate->title], ], 422); } $group_repo->update(['id' => $group->id, 'title' => $title, 'type' => $type]); return $this->json(['success' => true]); } /** * Архивация группы. Статьи внутри — не архивируются автоматически, а просто становятся без * группы (group_id = NULL): архивация группы не должна "тихо" утаскивать за собой все статьи — * это уже было бы массовым удалением без явного подтверждения. ON DELETE SET NULL в схеме * сработал бы так же, но только при физическом удалении группы, а тут — архивация (is_delete), * поэтому group_id у статей чистим явно сами. * * @return string JSON * @throws HTTPException|MyException */ public function deleteAction(): string { $request = Request::$current; $user = $this->currentUser(); $group_repo = new CategoryGroupRepository(); $group = $this->ownGroup($group_repo, $user, (int)$request->param(0)); $group_repo->update(['id' => $group->id, 'is_delete' => true]); (new CategoryRepository())->clearGroup((int)$group->id, (int)$user->id); return $this->json(['success' => true]); } /** * Возврат группы из архива. * * @return string JSON * @throws HTTPException|MyException */ public function restoreAction(): string { $request = Request::$current; $user = $this->currentUser(); $group_repo = new CategoryGroupRepository(); $group = $this->ownGroup($group_repo, $user, (int)$request->param(0)); $group_repo->update(['id' => $group->id, 'is_delete' => false]); return $this->json(['success' => true]); } /** * @param array $data * @return Validation */ protected function buildValidation(array $data): Validation { return Validation::factory($data) ->label('title', 'Название') ->label('type', 'Тип') ->rule('title', 'required') ->rule('title', 'max_length', [128]) ->rule('type', 'required') ->rule('type', 'in', [['income', 'expense']]); } /** * @return object * @throws HTTPException|MyException */ protected function currentUser(): object { $auth_user = Auth::instance()->getUser(); $user = (new UserRepository())->getByLogin($auth_user['login']); if (!$user) { throw HTTPException::factory(404); } return $user; } /** * @param CategoryGroupRepository $group_repo * @param object $user * @param int $id * @return object * @throws HTTPException|MyException */ protected function ownGroup(CategoryGroupRepository $group_repo, object $user, int $id): object { $group = $group_repo->get($id); if (!$group || (int)$group->user_id !== (int)$user->id) { throw HTTPException::factory(404); } return $group; } }