Completed
Push — master ( fd5325...d7e193 )
by Schlaefer
05:54 queued 03:00
created

PostingsController::meta()   B

Complexity

Conditions 8
Paths 23

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 23
nop 1
dl 0
loc 51
rs 7.8246
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Model\Entity\Entry;
17
use App\Model\Table\EntriesTable;
18
use Cake\Core\Configure;
19
use Cake\Http\Exception\BadRequestException;
20
use Cake\Http\Exception\NotFoundException;
21
use Saito\Exception\SaitoForbiddenException;
22
use Saito\Posting\PostingInterface;
23
24
/**
25
 * Endpoint for adding/POST and editing/PUT posting
26
 *
27
 * @property EntriesTable $Entries
28
 */
29
class PostingsController extends ApiAppController
30
{
31
    /**
32
     * {@inheritDoc}
33
     */
34
    public function initialize()
35
    {
36
        parent::initialize();
37
        $this->loadModel('Entries');
38
    }
39
40
    /**
41
     * Add a a new posting
42
     *
43
     * @return void
44
     */
45
    public function add(): void
46
    {
47
        $data = $this->request->getData();
48
49
        /** @var Entry */
50
        $posting = $this->Entries->createPosting($data, $this->CurrentUser);
0 ignored issues
show
Bug introduced by
It seems like $data defined by $this->request->getData() on line 47 can also be of type null or string; however, App\Model\Table\EntriesTable::createPosting() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
51
52
        if (empty($posting)) {
53
            throw new BadRequestException();
54
        }
55
56
        $errors = $posting->getErrors();
57
58
        if (!count($errors)) {
59
            $this->set(compact('posting'));
60
61
            return;
62
        }
63
64
        $this->set(compact('errors'));
65
        $this->viewBuilder()->setTemplate('/Error/json/entityValidation');
66
    }
67
68
    /**
69
     * Edit an existing posting
70
     *
71
     * @param string $id Unused in favor of request-data.
72
     * @return void
73
     */
74
    public function edit(string $id): void
75
    {
76
        $data = $this->request->getData();
77
78
        if (empty($data['id'])) {
79
            throw new BadRequestException('No posting-id provided.');
80
        }
81
82
        $id = $data['id'];
83
        $posting = $this->Entries->get($id, ['return' => 'Entity']);
84
        if (!$posting) {
85
            throw new NotFoundException('Posting not found.');
86
        }
87
88
        $updatedPosting = $this->Entries->updatePosting($posting, $data, $this->CurrentUser);
0 ignored issues
show
Bug introduced by
It seems like $data defined by $this->request->getData() on line 76 can also be of type string; however, App\Model\Table\EntriesTable::updatePosting() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
89
90
        if (!$updatedPosting) {
91
            throw new BadRequestException('Posting could not be saved.');
92
        }
93
94
        if (!$updatedPosting->hasErrors()) {
95
            $this->set('posting', $updatedPosting);
96
            $this->render('/Postings/json/add');
97
98
            return;
99
        }
100
101
        $errors = $updatedPosting->getErrors();
102
        $this->set(compact('errors'));
103
        $this->viewBuilder()->setTemplate('/Error/json/entityValidation');
104
    }
105
106
    /**
107
     * Serves meta information required to add or edit a posting
108
     *
109
     * @param string|null $id ID of the posting (send on edit)
110
     * @return void
111
     */
112
    public function meta(?string $id = null): void
113
    {
114
        $id = (int)$id;
115
        $isEdit = !empty($id);
116
        $pid = $this->getRequest()->getQuery('pid', null);
117
        $isAnswer = !empty($pid);
118
119
        if ($isAnswer) {
120
            /** @var PostingInterface */
121
            $parent = $this->Entries->get($pid);
0 ignored issues
show
Documentation introduced by
$pid is of type string|array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
122
123
            // Don't leak content of forbidden categories
124
            if ($parent->isAnsweringForbidden()) {
125
                throw new SaitoForbiddenException(
126
                    'Access to parent in PostingsController:meta() forbidden.',
127
                    ['CurrentUser' => $this->CurrentUser]
128
                );
129
            }
130
131
            $this->set('parent', $parent);
132
        }
133
134
        if ($isEdit) {
135
            /** @var PostingInterface */
136
            $posting = $this->Entries->get($id);
137
            if (!$posting->isEditingAllowed()) {
138
                throw new SaitoForbiddenException(
139
                    'Access to posting in PostingsController:meta() forbidden.',
140
                    ['CurrentUser' => $this->CurrentUser]
141
                );
142
            }
143
            $this->set('posting', $posting);
144
        } else {
145
            /// We currently don't save drafts for edits
146
            $where = ['user_id' => $this->CurrentUser->getId()];
147
            ($pid) ? $where['pid'] = $pid : $where[] = 'pid IS NULL';
148
            $draft = $this->Entries->Drafts->find()->where($where)->first();
149
150
            if ($draft) {
151
                $this->set('draft', $draft);
152
            }
153
        }
154
155
        $settings = Configure::read('Saito.Settings');
156
157
        $this->set(compact('isAnswer', 'isEdit', 'settings'));
158
159
        $action = $isAnswer ? 'answer' : 'thread';
160
        $categories = $this->CurrentUser->getCategories()->getAll($action, 'list');
161
        $this->set('categories', $categories);
162
    }
163
}
164