Issues (326)

src/Controller/PostingsController.php (8 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace App\Controller;
14
15
use Api\Controller\ApiAppController;
16
use App\Controller\Component\PostingComponent;
17
use App\Model\Entity\Entry;
18
use App\Model\Table\EntriesTable;
19
use Cake\Core\Configure;
20
use Cake\Http\Exception\BadRequestException;
21
use Cake\Http\Exception\NotFoundException;
22
use Saito\Exception\SaitoForbiddenException;
23
use Saito\Posting\PostingInterface;
24
25
/**
26
 * Endpoint for adding/POST and editing/PUT posting
27
 *
28
 * @property EntriesTable $Entries
29
 * @property PostingComponent $Posting
30
 */
31
class PostingsController extends ApiAppController
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    public function initialize()
37
    {
38
        parent::initialize();
39
        $this->loadModel('Entries');
40
        $this->loadComponent('Posting');
41
    }
42
43
    /**
44
     * Add a a new posting
45
     *
46
     * @return void
47
     */
48
    public function add(): void
49
    {
50
        $data = $this->getRequest()->getData();
51
        $allowedFields = ['category_id', 'edited', 'edited_by', 'pid', 'subject', 'text'];
52
        $data = array_intersect_key($data, array_fill_keys($allowedFields, 1));
0 ignored issues
show
It seems like $data can also be of type null; however, parameter $array1 of array_intersect_key() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

52
        $data = array_intersect_key(/** @scrutinizer ignore-type */ $data, array_fill_keys($allowedFields, 1));
Loading history...
53
54
        $data += [
55
            'name' => $this->CurrentUser->get('username'),
56
            'user_id' => $this->CurrentUser->getId(),
57
        ];
58
59
        /** @var Entry */
60
        $posting = $this->Posting->create($data, $this->CurrentUser);
61
62
        if (empty($posting)) {
63
            throw new BadRequestException();
64
        }
65
66
        $errors = $posting->getErrors();
67
68
        if (!count($errors)) {
69
            $this->set(compact('posting'));
70
71
            return;
72
        }
73
74
        $this->set(compact('errors'));
75
        $this->viewBuilder()->setTemplate('/Error/json/entityValidation');
76
    }
77
78
    /**
79
     * Edit an existing posting
80
     *
81
     * @param string $id Unused in favor of request-data.
82
     * @return void
83
     */
84
    public function edit(string $id): void
0 ignored issues
show
The parameter $id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

84
    public function edit(/** @scrutinizer ignore-unused */ string $id): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
85
    {
86
        $id = $this->getRequest()->getData('id', null);
87
88
        if (empty($id)) {
89
            throw new BadRequestException('No posting-id provided.');
90
        }
91
92
        $posting = $this->Entries->get($id);
0 ignored issues
show
$id of type array|string is incompatible with the type integer expected by parameter $primaryKey of App\Model\Table\EntriesTable::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

92
        $posting = $this->Entries->get(/** @scrutinizer ignore-type */ $id);
Loading history...
93
        if (!$posting) {
94
            throw new NotFoundException('Posting not found.');
95
        }
96
97
        $data = $this->getRequest()->getData();
98
        $allowedFields = ['category_id', 'edited', 'edited_by', 'subject', 'text'];
99
        $data = array_intersect_key($data, array_fill_keys($allowedFields, 1));
0 ignored issues
show
It seems like $data can also be of type null; however, parameter $array1 of array_intersect_key() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
        $data = array_intersect_key(/** @scrutinizer ignore-type */ $data, array_fill_keys($allowedFields, 1));
Loading history...
100
101
        $data += [
102
            'edited' => bDate(),
103
            'edited_by' => $this->CurrentUser->get('username'),
104
        ];
105
106
        $updatedPosting = $this->Posting->update($posting, $data, $this->CurrentUser);
0 ignored issues
show
It seems like $posting can also be of type array; however, parameter $entry of App\Controller\Component...tingComponent::update() does only seem to accept App\Model\Entity\Entry, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
        $updatedPosting = $this->Posting->update(/** @scrutinizer ignore-type */ $posting, $data, $this->CurrentUser);
Loading history...
107
108
        if (!$updatedPosting) {
0 ignored issues
show
$updatedPosting is of type App\Model\Entity\Entry, thus it always evaluated to true.
Loading history...
109
            throw new BadRequestException('Posting could not be saved.');
110
        }
111
112
        if (!$updatedPosting->hasErrors()) {
113
            $this->set('posting', $updatedPosting);
114
            $this->render('/Postings/json/add');
115
116
            return;
117
        }
118
119
        $errors = $updatedPosting->getErrors();
120
        $this->set(compact('errors'));
121
        $this->viewBuilder()->setTemplate('/Error/json/entityValidation');
122
    }
123
124
    /**
125
     * Serves meta information required to add or edit a posting
126
     *
127
     * @param string|null $id ID of the posting (send on edit)
128
     * @return void
129
     */
130
    public function meta(?string $id = null): void
131
    {
132
        $id = (int)$id;
133
        $isEdit = !empty($id);
134
        $pid = $this->getRequest()->getQuery('pid', null);
135
        $isAnswer = !empty($pid);
136
137
        if ($isAnswer) {
138
            /** @var PostingInterface */
139
            $parent = $this->Entries->get($pid)->toPosting()->withCurrentUser($this->CurrentUser);
0 ignored issues
show
The method toPosting() does not exist on Cake\Datasource\EntityInterface. It seems like you code against a sub-type of Cake\Datasource\EntityInterface such as App\Model\Entity\Entry. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

139
            $parent = $this->Entries->get($pid)->/** @scrutinizer ignore-call */ toPosting()->withCurrentUser($this->CurrentUser);
Loading history...
$pid of type array|string is incompatible with the type integer expected by parameter $primaryKey of App\Model\Table\EntriesTable::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

139
            $parent = $this->Entries->get(/** @scrutinizer ignore-type */ $pid)->toPosting()->withCurrentUser($this->CurrentUser);
Loading history...
140
141
            // Don't leak content of forbidden categories
142
            if ($parent->isAnsweringForbidden()) {
143
                throw new SaitoForbiddenException(
144
                    'Access to parent in PostingsController:meta() forbidden.',
145
                    ['CurrentUser' => $this->CurrentUser]
146
                );
147
            }
148
149
            $this->set('parent', $parent);
150
        }
151
152
        if ($isEdit) {
153
            /** @var PostingInterface */
154
            $posting = $this->Entries->get($id)->toPosting()->withCurrentUser($this->CurrentUser);
155
            if (!$posting->isEditingAllowed()) {
156
                throw new SaitoForbiddenException(
157
                    'Access to posting in PostingsController:meta() forbidden.',
158
                    ['CurrentUser' => $this->CurrentUser]
159
                );
160
            }
161
            $this->set('posting', $posting);
162
        } else {
163
            /// We currently don't save drafts for edits
164
            $where = ['user_id' => $this->CurrentUser->getId()];
165
            if (is_numeric($pid)) {
166
                $where['pid'] = $pid;
167
            }
168
            $draft = $this->Entries->Drafts->find()->where($where)->first();
169
170
            if ($draft) {
171
                $this->set('draft', $draft);
172
            }
173
        }
174
175
        $settings = Configure::read('Saito.Settings');
176
177
        $this->set(compact('isAnswer', 'isEdit', 'settings'));
178
179
        $action = $isAnswer ? 'answer' : 'thread';
180
        $categories = $this->CurrentUser->getCategories()->getAll($action, 'list');
181
        $this->set('categories', $categories);
182
    }
183
}
184