115 lines
4.0 KiB
PHP
115 lines
4.0 KiB
PHP
<?php
|
|
|
|
class Habit
|
|
{
|
|
public static function allForUser(int $userId, array $filters = []): array
|
|
{
|
|
$where = ['h.user_id = :user_id'];
|
|
$params = ['user_id' => $userId];
|
|
|
|
if (!empty($filters['category_id'])) {
|
|
$where[] = 'h.category_id = :category_id';
|
|
$params['category_id'] = (int) $filters['category_id'];
|
|
}
|
|
|
|
if (($filters['status'] ?? '') === 'done') {
|
|
$where[] = 'hl.id IS NOT NULL';
|
|
} elseif (($filters['status'] ?? '') === 'open') {
|
|
$where[] = 'hl.id IS NULL';
|
|
}
|
|
|
|
$sql = 'SELECT h.*, c.name AS category_name, c.color AS category_color,
|
|
CASE WHEN hl.id IS NULL THEN 0 ELSE 1 END AS done_today,
|
|
(SELECT COUNT(*)
|
|
FROM habit_logs hwl
|
|
WHERE hwl.habit_id = h.id
|
|
AND YEARWEEK(hwl.completed_on, 1) = YEARWEEK(CURRENT_DATE, 1)) AS completed_this_week
|
|
FROM habits h
|
|
LEFT JOIN categories c ON c.id = h.category_id
|
|
LEFT JOIN habit_logs hl
|
|
ON hl.habit_id = h.id
|
|
AND hl.completed_on = CURRENT_DATE
|
|
WHERE ' . implode(' AND ', $where) . '
|
|
ORDER BY h.created_at DESC';
|
|
|
|
$statement = Database::connection()->prepare($sql);
|
|
$statement->execute($params);
|
|
|
|
return $statement->fetchAll();
|
|
}
|
|
|
|
public static function findForUser(int $id, int $userId): ?array
|
|
{
|
|
$statement = Database::connection()->prepare(
|
|
'SELECT * FROM habits WHERE id = :id AND user_id = :user_id LIMIT 1'
|
|
);
|
|
$statement->execute(['id' => $id, 'user_id' => $userId]);
|
|
|
|
$habit = $statement->fetch();
|
|
return $habit ?: null;
|
|
}
|
|
|
|
public static function create(int $userId, array $data): bool
|
|
{
|
|
$sql = 'INSERT INTO habits (user_id, category_id, title, description, target_per_week)
|
|
VALUES (:user_id, :category_id, :title, :description, :target_per_week)';
|
|
|
|
return Database::connection()->prepare($sql)->execute([
|
|
'user_id' => $userId,
|
|
'category_id' => $data['category_id'] ?: null,
|
|
'title' => $data['title'],
|
|
'description' => $data['description'],
|
|
'target_per_week' => (int) $data['target_per_week'],
|
|
]);
|
|
}
|
|
|
|
public static function update(int $id, int $userId, array $data): bool
|
|
{
|
|
$sql = 'UPDATE habits
|
|
SET category_id = :category_id,
|
|
title = :title,
|
|
description = :description,
|
|
target_per_week = :target_per_week
|
|
WHERE id = :id AND user_id = :user_id';
|
|
|
|
return Database::connection()->prepare($sql)->execute([
|
|
'id' => $id,
|
|
'user_id' => $userId,
|
|
'category_id' => $data['category_id'] ?: null,
|
|
'title' => $data['title'],
|
|
'description' => $data['description'],
|
|
'target_per_week' => (int) $data['target_per_week'],
|
|
]);
|
|
}
|
|
|
|
public static function delete(int $id, int $userId): bool
|
|
{
|
|
$statement = Database::connection()->prepare('DELETE FROM habits WHERE id = :id AND user_id = :user_id');
|
|
|
|
return $statement->execute(['id' => $id, 'user_id' => $userId]);
|
|
}
|
|
|
|
public static function toggleToday(int $id, int $userId): bool
|
|
{
|
|
$habit = self::findForUser($id, $userId);
|
|
|
|
if (!$habit) {
|
|
return false;
|
|
}
|
|
|
|
$db = Database::connection();
|
|
$check = $db->prepare(
|
|
'SELECT id FROM habit_logs WHERE habit_id = :habit_id AND completed_on = CURRENT_DATE LIMIT 1'
|
|
);
|
|
$check->execute(['habit_id' => $id]);
|
|
$log = $check->fetch();
|
|
|
|
if ($log) {
|
|
return $db->prepare('DELETE FROM habit_logs WHERE id = :id')->execute(['id' => $log['id']]);
|
|
}
|
|
|
|
$insert = $db->prepare('INSERT INTO habit_logs (habit_id, completed_on) VALUES (:habit_id, CURRENT_DATE)');
|
|
return $insert->execute(['habit_id' => $id]);
|
|
}
|
|
}
|