Passed
Push — develop ( bca4b6...66c5e1 )
by Schlaefer
03:54
created

PostingComponent::update()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 4
nop 3
dl 0
loc 15
rs 10
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\Component;
14
15
use App\Model\Entity\Entry;
16
use App\Model\Table\EntriesTable;
17
use Cake\Controller\Component;
18
use Cake\Http\Exception\ForbiddenException;
19
use Cake\ORM\TableRegistry;
20
use Saito\Posting\Basic\BasicPostingInterface;
21
use Saito\Posting\Posting;
22
use Saito\User\CurrentUser\CurrentUserInterface;
23
24
class PostingComponent extends Component
25
{
26
27
    /**
28
     * Creates a new posting from user
29
     *
30
     * @param array $data raw posting data
31
     * @param CurrentUserInterface $CurrentUser the current user
32
     * @return Entry|null on success, null otherwise
33
     */
34
    public function create(array $data, CurrentUserInterface $CurrentUser): ?Entry
35
    {
36
        if (!empty($data['pid'])) {
37
            /// new posting is answer to existing posting
38
            $parent = $this->getTable()->get($data['pid']);
39
40
            if (empty($parent)) {
41
                throw new \InvalidArgumentException(
42
                    'Parent posting for creating a new answer not found.',
43
                    1564756571
44
                );
45
            }
46
47
            $data = $this->prepareChildPosting($parent, $data);
0 ignored issues
show
Bug introduced by
$parent of type Cake\Datasource\EntityInterface|array is incompatible with the type Saito\Posting\Basic\BasicPostingInterface expected by parameter $parent of App\Controller\Component...::prepareChildPosting(). ( Ignorable by Annotation )

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

47
            $data = $this->prepareChildPosting(/** @scrutinizer ignore-type */ $parent, $data);
Loading history...
48
        } else {
49
            /// if no pid is provided the new posting is root-posting
50
            $data['pid'] = 0;
51
            // We can't wait for entity-validation cause we check the category
52
            // in permissions.
53
            if (!isset($data['category_id'])) {
54
                throw new \InvalidArgumentException(
55
                    'No category for new posting provided.',
56
                    1573123345
57
                );
58
            }
59
        }
60
61
        $posting = new Posting($data + ['id' => 0]);
62
        $action = $posting->isRoot() ? 'thread' : 'answer';
63
        // @td better return !$posting->isAnsweringForbidden();
64
        $allowed = $CurrentUser->getCategories()->permission($action, $posting->get('category_id'));
65
        if ($allowed !== true) {
66
            throw new ForbiddenException('Creating new posting not allowed.');
67
        }
68
69
        return $this->getTable()->createEntry($data);
70
    }
71
72
    /**
73
     * Updates an existing posting
74
     *
75
     * @param Entry $entry the posting to update
76
     * @param array $data data the posting should be updated with
77
     * @param CurrentUserInterface $CurrentUser the current-user
78
     * @return Entry|null the posting which was asked to update
79
     */
80
    public function update(Entry $entry, array $data, CurrentUserInterface $CurrentUser): ?Entry
81
    {
82
        $isRoot = $entry->isRoot();
83
84
        if (!$isRoot) {
85
            $parent = $this->getTable()->get($entry->get('pid'));
86
            $data = $this->prepareChildPosting($parent, $data);
0 ignored issues
show
Bug introduced by
$parent of type Cake\Datasource\EntityInterface|array|false is incompatible with the type Saito\Posting\Basic\BasicPostingInterface expected by parameter $parent of App\Controller\Component...::prepareChildPosting(). ( Ignorable by Annotation )

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

86
            $data = $this->prepareChildPosting(/** @scrutinizer ignore-type */ $parent, $data);
Loading history...
87
        }
88
89
        $allowed = $entry->toPosting()->withCurrentUser($CurrentUser)->isEditingAllowed();
90
        if ($allowed !== true) {
91
            throw new ForbiddenException('Updating posting not allowed.');
92
        }
93
94
        return $this->getTable()->updateEntry($entry, $data);
95
    }
96
97
    /**
98
     * Populates data of an child derived from its parent-posting
99
     *
100
     * @param BasicPostingInterface $parent parent data
101
     * @param array $data current posting data
102
     * @return array populated $data
103
     */
104
    public function prepareChildPosting(BasicPostingInterface $parent, array $data): array
105
    {
106
        if (empty($data['subject'])) {
107
            // if new subject is empty use the parent's subject
108
            $data['subject'] = $parent->get('subject');
109
        }
110
111
        $data['category_id'] = $data['category_id'] ?? $parent->get('category_id');
112
        $data['tid'] = $parent->get('tid');
113
114
        return $data;
115
    }
116
117
    /**
118
     * Get Entries table
119
     *
120
     * @return EntriesTable
121
     */
122
    protected function getTable(): EntriesTable
123
    {
124
        /** @var EntriesTable */
125
        $table = TableRegistry::getTableLocator()->get('Entries');
126
127
        return $table;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $table returns the type Cake\ORM\Table which includes types incompatible with the type-hinted return App\Model\Table\EntriesTable.
Loading history...
128
    }
129
}
130