<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Models\Comment;
use App\Models\Poll;
use App\Models\Story;
use App\Services\Session;
use App\Services\Validator;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* RatingController
*/
class RatingController extends Controller
{
public function __construct(
protected Session $session,
protected Validator $validator,
) {}
/**
* Change rating
*
* @param int $id
* @param Request $request
* @param Response $response
*
* @return Response
*/
public function change(int $id, Request $request, Response $response): Response
{
$input = (array) $request->getParsedBody();
$modelName = $this->getModelByType($input['type']);
if (! $modelName) {
return $this->json($response, [
'success' => false,
'message' => 'Неверный тип записи!',
]);
}
$model = $modelName::query()->find($id);
if (! $model) {
return $this->json($response, [
'success' => false,
'message' => 'Запись не найдена!',
]);
}
$this->validator
->required(['csrf', 'vote'])
->same('csrf', $this->session->get('csrf'), 'Неверный идентификатор сессии, повторите действие!')
->in('vote', ['+', '-'])
->custom($model->user_id !== getUser('id'), 'Нельзя изменять рейтинг своей записи!');
if ($this->validator->isValid($input)) {
$poll = Poll::query()
->where('entity_id', $id)
->where('entity_name', $input['type'])
->where('user_id', getUser('id'))
->first();
$cancel = false;
if ($poll) {
if ($poll->vote === $input['vote']) {
return $this->json($response, [
'success' => false,
]);
}
$poll->delete();
$cancel = true;
} else {
Poll::query()->create([
'user_id' => getUser('id'),
'entity_id' => $id,
'entity_name' => $input['type'],
'vote' => $input['vote'],
'created_at' => time(),
]);
}
if ($input['vote'] === '+') {
$rating = $model->rating + 1;
} else {
$rating = $model->rating - 1;
}
$model->rating = $rating;
$model->save();
return $this->json($response, [
'success' => true,
'cancel' => $cancel,
'rating' => $model->getRating(),
]);
}
return $this->json($response, [
'success' => false,
'message' => current($this->validator->getErrors()),
]);
}
/**
* Get map types
*
* @return string[]
*/
private function getMapTypes(): array
{
return [
'story' => Story::class,
'comment' => Comment::class,
];
}
/**
* Get model by type
*
* @param string $type
*
* @return string|null
*/
private function getModelByType(string $type): ?string
{
return $this->getMapTypes()[$type] ?? null;
}
}