Strimoid/Strimoid

View on GitHub
app/Http/Controllers/PollController.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Strimoid\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Strimoid\Models\Content;

class PollController extends BaseController
{
    public function __construct(private readonly \Illuminate\Auth\AuthManager $authManager, private readonly \Illuminate\Routing\Redirector $redirector, private readonly \Illuminate\Validation\Factory $validationFactory)
    {
    }
    public function addVote(Request $request, Content $content)
    {
        $poll = $content->poll;

        // No double voting, sorry
        $hasVoted = in_array($this->authManager->id(), array_column($poll['votes'], 'user_id'));

        if ($hasVoted) {
            return $this->redirector->route('content_comments', $content->getKey())
                ->with('danger_msg', 'Oddałeś już głos w tej ankiecie.');
        }

        // Check if poll isn't closed already
        if (isset($poll['ends_at']) && Carbon::now()->gte($poll['ends_at'])) {
            return $this->redirector->route('content_comments', $content->getKey())
                ->with('danger_msg', 'Ankieta została już zakończona.');
        }

        // Create validation rules for all questions
        $rules = [];

        foreach ($poll['questions'] as $questionId => $question) {
            $rules[$questionId] = ['array', 'min:' . $question['min_selections'], 'max:' . $question['max_selections']];

            if ($question['min_selections']) {
                $rules[$questionId][] = 'required';
            }
        }

        // Now validate replies
        $validator = $this->validationFactory->make($request->all(), $rules, [
            'required' => 'Odpowiedź na to pytanie jest wymagana',
            'min' => 'Zaznaczyłeś zbyt małą liczbę odpowiedzi',
            'max' => 'Zaznaczyłeś zbyt dużą liczbę odpowiedzi',
        ]);

        if ($validator->fails()) {
            return $this->redirector->route('content_comments', $content->getKey())
                ->withInput()
                ->withErrors($validator);
        }

        // And add vote object to poll
        $replies = [];

        foreach ($poll['questions'] as $questionId => $question) {
            $optionIds = (array) $request->get($questionId);

            foreach ($optionIds as $optionId) {
                if (!in_array($optionId, array_column($question['options'], '_id'))) {
                    return $this->redirector->route('content_comments', $content->getKey())
                        ->withInput()
                        ->with('danger_msg', 'Wygląda na to, że jedna z odpowiedzi została usunięta. Spróbuj jeszcze raz.');
                }
            }

            $replies[$questionId] = $optionIds;
        }

        foreach ($replies as $questionId => $optionIds) {
            if (!$optionIds) {
                continue;
            }

            foreach ($optionIds as $optionId) {
                Content::where('_id', $content->getKey())
                    ->where('poll.questions.' . $questionId . '.options', 'elemmatch', ['_id' => $optionId])
                    ->increment('poll.questions.' . $questionId . '.options.$.votes', 1);
            }
        }

        $vote = ['created_at' => Carbon::now(), 'user_id' => $this->authManager->id(), 'replies' => $replies];

        $content->push('poll.votes', $vote);

        return $this->redirector->route('content_comments', $content->getKey())
            ->with('success_msg', 'Twój głos został dodany.');
    }
}