Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
52 / 52
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
QuestionsController
100.00% covered (success)
100.00%
52 / 52
100.00% covered (success)
100.00%
6 / 6
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 delete
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 edit
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 save
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
3
 showEdit
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Controllers\Admin;
6
7use Carbon\Carbon;
8use Engelsystem\Controllers\BaseController;
9use Engelsystem\Controllers\HasUserNotifications;
10use Engelsystem\Helpers\Authenticator;
11use Engelsystem\Http\Redirector;
12use Engelsystem\Http\Request;
13use Engelsystem\Http\Response;
14use Engelsystem\Models\Question;
15use Psr\Log\LoggerInterface;
16
17class QuestionsController extends BaseController
18{
19    use HasUserNotifications;
20
21    /** @var array<string> */
22    protected array $permissions = [
23        'question.add',
24        'question.edit',
25    ];
26
27    public function __construct(
28        protected Authenticator $auth,
29        protected LoggerInterface $log,
30        protected Question $question,
31        protected Redirector $redirect,
32        protected Response $response
33    ) {
34    }
35
36    public function index(): Response
37    {
38        $questions = $this->question
39            ->orderBy('answered_at')
40            ->orderByDesc('created_at')
41            ->get()
42            ->load(['user.state', 'answerer.state']);
43
44        return $this->response->withView(
45            'pages/questions/index.twig',
46            ['questions' => $questions, 'is_admin' => true]
47        );
48    }
49
50    public function delete(Request $request): Response
51    {
52        $data = $this->validate($request, [
53            'id'     => 'required|int',
54            'delete' => 'checked',
55        ]);
56
57        $question = $this->question->findOrFail($data['id']);
58        $question->delete();
59
60        $this->log->info('Deleted question {question}', ['question' => $question->text]);
61        $this->addNotification('question.delete.success');
62
63        return $this->redirect->to('/admin/questions');
64    }
65
66    public function edit(Request $request): Response
67    {
68        $questionId = (int) $request->getAttribute('question_id');
69
70        $questions = $this->question->find($questionId);
71
72        return $this->showEdit($questions);
73    }
74
75    public function save(Request $request): Response
76    {
77        $questionId = (int) $request->getAttribute('question_id');
78
79        /** @var Question $question */
80        $question = $this->question->findOrNew($questionId);
81
82        $data = $this->validate($request, [
83            'text'    => 'required',
84            'answer'  => 'required',
85            'delete'  => 'optional|checked',
86            'preview' => 'optional|checked',
87        ]);
88
89        if (!is_null($data['delete'])) {
90            $question->delete();
91
92            $this->log->info('Deleted question "{question}"', ['question' => $question->text]);
93
94            $this->addNotification('question.delete.success');
95
96            return $this->redirect->to('/admin/questions');
97        }
98
99        $question->text = $data['text'];
100        $question->answer = $data['answer'];
101        $question->answered_at = Carbon::now();
102        $question->answerer()->associate($this->auth->user());
103
104        if (!is_null($data['preview'])) {
105            return $this->showEdit($question);
106        }
107
108        $question->save();
109
110        $this->log->info(
111            'Updated questions "{text}": {answer}',
112            ['text' => $question->text, 'answer' => $question->answer]
113        );
114
115        $this->addNotification('question.edit.success');
116
117        return $this->redirect->to('/admin/questions');
118    }
119
120    protected function showEdit(?Question $question): Response
121    {
122        return $this->response->withView(
123            'pages/questions/edit.twig',
124            ['question' => $question, 'is_admin' => true]
125        );
126    }
127}