Bicycle/App/Repositories/CategoryRepository.php
2026-08-15 10:39:22 +03:00

118 lines
4.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* @package Bicycle
* @author Egor Isaev
* @description CategoryRepository.php
* @copyright (c) 11/08/2026
*/
namespace App\Repositories;
use System\Classes\Repository;
/**
* Репозиторий таблицы categories (статьи income/expense; группа — отдельная сущность,
* см. App\Repositories\CategoryGroupRepository, статья ссылается на неё через group_id).
*/
class CategoryRepository extends Repository
{
/**
* @param string|null $connection Имя подключения (Database::instance($connection)); null — по умолчанию
*/
public function __construct(?string $connection = null)
{
parent::__construct('categories', connection: $connection);
}
/**
* Активная (is_delete=0) статья с тем же названием у пользователя, в рамках type+group_id.
*
* @param int $user_id
* @param string $type income|expense
* @param int|null $group_id null — без группы
* @param string $title
* @param int|null $exclude_id Исключить этот id (правка своего же названия — не дубль)
* @return object|false
*/
public function findActiveDuplicate(int $user_id, string $type, ?int $group_id, string $title, ?int $exclude_id = null): mixed
{
return $this->findDuplicate($user_id, $type, $group_id, $title, false, $exclude_id);
}
/**
* Архивная (is_delete=1) статья с тем же названием у пользователя.
*
* @param int $user_id
* @param string $type income|expense
* @param int|null $group_id
* @param string $title
* @param int|null $exclude_id
* @return object|false
*/
public function findArchivedDuplicate(int $user_id, string $type, ?int $group_id, string $title, ?int $exclude_id = null): mixed
{
return $this->findDuplicate($user_id, $type, $group_id, $title, true, $exclude_id);
}
/**
* @param int $user_id
* @param string $type
* @param int|null $group_id
* @param string $title
* @param bool $is_delete
* @param int|null $exclude_id
* @return object|false
*/
protected function findDuplicate(int $user_id, string $type, ?int $group_id, string $title, bool $is_delete, ?int $exclude_id): mixed
{
$pdo = $this->pdo->pdo();
$where = "user_id = $user_id"
. ' AND type = ' . $pdo->quote($type)
. ' AND is_delete = ' . ($is_delete ? 1 : 0)
. ' AND title = ' . $pdo->quote($title)
. ' AND group_id ' . ($group_id === null ? 'IS NULL' : "= $group_id");
if ($exclude_id !== null) {
$where .= " AND id != $exclude_id";
}
return $this->getItemWhere($where);
}
/**
* Активные статьи пользователя, сгруппированные по group_id (0 — без группы, вместо null,
* чтобы использовать как ключ массива) — для рендера списка статей по группам.
*
* @param int $user_id
* @return array<int,object[]>
*/
public function getTree(int $user_id): array
{
$categories = $this->getList('*', ['user_id' => $user_id, 'is_delete' => 0], '`order`');
$tree = [];
foreach ($categories ?: [] as $category) {
$key = $category->group_id === null ? 0 : (int)$category->group_id;
$tree[$key][] = $category;
}
return $tree;
}
/**
* Отвязать все статьи пользователя от группы (group_id = NULL) — используется при архивации
* группы (App\Controller\CategoryGroupsController::deleteAction), не при её физическом
* удалении (то делает fk_categories_group ... ON DELETE SET NULL само).
*
* @param int $group_id
* @param int $user_id
* @return void
*/
public function clearGroup(int $group_id, int $user_id): void
{
$this->pdo->prepare("UPDATE $this->table SET group_id = NULL WHERE group_id = :group_id AND user_id = :user_id")
->execute(['group_id' => $group_id, 'user_id' => $user_id]);
}
}