View file app/Controllers/VoteController.php

File size: 8.03Kb
<?php

namespace App\Controllers;

use App\Classes\Validator;
use App\Models\Polling;
use App\Models\Vote;
use App\Models\VoteAnswer;
use Illuminate\Http\Request;

class VoteController extends BaseController
{
    /**
     * Главная страница
     *
     * @return string
     */
    public function index(): string
    {
        $total = Vote::query()->where('closed', 0)->count();
        $page = paginate(setting('allvotes'), $total);

        $votes = Vote::query()
            ->where('closed', 0)
            ->orderBy('created_at', 'desc')
            ->offset($page->offset)
            ->limit($page->limit)
            ->with('topic')
            ->get();

        return view('votes/index', compact('votes', 'page'));
    }

    /**
     * Просмотр голосования
     *
     * @param int       $id
     * @param Request   $request
     * @param Validator $validator
     * @return string
     */
    public function view(int $id, Request $request, Validator $validator): string
    {
        $show = $request->input('show');

        /** @var Vote $vote */
        $vote = Vote::query()->find($id);

        if (! $vote) {
            abort(404, 'Данного голосования не существует!');
        }

        if ($vote->closed) {
            abort('default', 'Данный опрос закрыт для голосования!');
        }

        $vote->answers = VoteAnswer::query()
            ->where('vote_id', $vote->id)
            ->orderBy('id')
            ->get();

        if ($vote->answers->isEmpty()) {
            abort('default', 'Для данного голосования не созданы варианты ответов');
        }

        $vote->poll = $vote->pollings()
            ->where('user_id', getUser('id'))
            ->first();

        if ($request->isMethod('post')) {
            $token = check($request->input('token'));
            $poll  = int($request->input('poll'));

            $validator->equal($token, $_SESSION['token'], 'Неверный идентификатор сессии, повторите действие!')
                ->empty($vote->poll, 'Вы уже проголосовали в этом опросе!')
                ->notEmpty($poll, 'Вы не выбрали вариант ответа!');

            $answer = VoteAnswer::query()->where('id', $poll)->where('vote_id', $vote->id)->first();

            if ($poll) {
                $validator->notEmpty($answer, 'Ответ для данного голосования не найден!');
            }

            if ($validator->isValid()) {
                $vote->increment('count');
                $answer->increment('result');

                Polling::query()->create([
                    'relate_type' => Vote::class,
                    'relate_id'   => $vote->id,
                    'user_id'     => getUser('id'),
                    'vote'        => '+',
                    'created_at'  => SITETIME,
                ]);

                setFlash('success', 'Ваш голос успешно принят!');
                redirect('/votes/'.$vote->id);
            } else {
                setInput($request->all());
                setFlash('danger', $validator->getErrors());
            }
        }

        $voted = array_pluck($vote->answers, 'result', 'answer');
        $max   = max($voted);

        arsort($voted);

        $info['voted'] = $voted;
        $info['sum']   = $vote->count > 0 ? $vote->count : 1;
        $info['max']   = $max > 0 ? $max : 1;

        return view('votes/view', compact('vote', 'show', 'info'));
    }

    /**
     * Проголосовавшие
     *
     * @param int $id
     * @return string
     */
    public function voters(int $id): string
    {
        /** @var Vote $vote */
        $vote = Vote::query()->find($id);

        if (! $vote) {
            abort(404, 'Данного голосования не существует!');
        }

        $voters = Polling::query()
            ->where('relate_type', Vote::class)
            ->where('relate_id', $vote->id)
            ->limit(50)
            ->with('user')
            ->get();

        return view('votes/voters', compact('vote', 'voters'));
    }

    /**
     * История голосований
     *
     * @return string
     */
    public function history(): string
    {
        $total = Vote::query()->where('closed', 1)->count();
        $page = paginate(setting('allvotes'), $total);

        $votes = Vote::query()
            ->where('closed', 1)
            ->orderBy('created_at', 'desc')
            ->offset($page->offset)
            ->limit($page->limit)
            ->with('topic')
            ->get();

        return view('votes/history', compact('votes', 'page'));
    }

    /**
     * Результаты истории голосований
     *
     * @param int $id
     * @return string
     */
    public function viewHistory(int $id): string
    {
        /** @var Vote $vote */
        $vote = Vote::query()->find($id);

        if (! $vote) {
            abort(404, 'Данного голосования не существует!');
        }

        if (! $vote->closed) {
            abort('default', 'Данный опрос еще не в архиве!');
        }

        $vote->answers = VoteAnswer::query()
            ->where('vote_id', $vote->id)
            ->orderBy('id')
            ->get();

        if ($vote->answers->isEmpty()) {
            abort('default', 'Для данного голосования не созданы варианты ответов');
        }

        $voted = array_pluck($vote->answers, 'result', 'answer');
        $max   = max($voted);

        arsort($voted);

        $info['voted'] = $voted;
        $info['sum']   = $vote->count > 0 ? $vote->count : 1;
        $info['max']   = $max > 0 ? $max : 1;

        return view('votes/view_history', compact('vote', 'info'));
    }

    /**
     * Создание голосования
     *
     * @param Request   $request
     * @param Validator $validator
     * @return string
     */
    public function create(Request $request, Validator $validator): string
    {
        if ($request->isMethod('post')) {

            $token    = check($request->input('token'));
            $question = check($request->input('question'));
            $answers  = check($request->input('answer'));

            $validator->equal($token, $_SESSION['token'], 'Неверный идентификатор сессии, повторите действие!')
                ->length($question, 5, 100, ['question' => 'Слишком длинный или короткий текст вопроса!']);

            $answers = array_unique(array_diff($answers, ['']));

            foreach ($answers as $answer) {
                if (utfStrlen($answer) > 50) {
                    $validator->addError(['answer' => 'Длина вариантов ответа не должна быть более 50 символов!']);
                    break;
                }
            }

            $validator->between(\count($answers), 2, 10, ['answer' => 'Недостаточное количество вариантов ответов!']);

            if ($validator->isValid()) {

                /** @var Vote $vote */
                $vote = Vote::query()->create([
                    'title'      => $question,
                    'created_at' => SITETIME,
                ]);

                $prepareAnswers = [];
                foreach ($answers as $answer) {
                    $prepareAnswers[] = [
                        'vote_id' => $vote->id,
                        'answer'  => $answer
                    ];
                }

                VoteAnswer::query()->insert($prepareAnswers);

                setFlash('success', 'Голосование успешно создано!');
                redirect('/votes/' . $vote->id);
            } else {
                setInput($request->all());
                setFlash('danger', $validator->getErrors());
            }
        }

        return view('votes/create');
    }
}