Completed
Branch #338-Save_posting_before_movin... (60770e)
by Schlaefer
02:30
created

PostingBehavior::validatorSetup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
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\Model\Behavior;
14
15
use App\Lib\Model\Table\FieldFilter;
16
use App\Model\Entity\Entry;
17
use App\Model\Table\EntriesTable;
18
use Cake\ORM\Behavior;
19
use Saito\Posting\Basic\BasicPostingInterface;
20
use Saito\Posting\Posting;
21
use Saito\User\CurrentUser\CurrentUserInterface;
22
23
class PostingBehavior extends Behavior
24
{
25
    /** @var CurrentUserInterface */
26
    private $CurrentUser;
27
28
    /** @var FieldFilter */
29
    private $fieldFilter;
30
31
    /**
32
     * {@inheritDoc}
33
     */
34
    public function initialize(array $config)
35
    {
36
        $this->fieldFilter = (new fieldfilter())
37
            ->setConfig('create', ['category_id', 'pid', 'subject', 'text'])
38
            ->setConfig('update', ['category_id', 'subject', 'text']);
39
    }
40
41
    /**
42
     * Creates a new posting from user
43
     *
44
     * @param array $data raw posting data
45
     * @param CurrentUserInterface $CurrentUser the current user
46
     * @return Entry|null on success, null otherwise
47
     */
48
    public function createPosting(array $data, CurrentUserInterface $CurrentUser): ?Entry
49
    {
50
        $data = $this->fieldFilter->filterFields($data, 'create');
51
52
        if (!empty($data['pid'])) {
53
            /// new posting is answer to existing posting
54
            $parent = $this->getTable()->get($data['pid']);
55
56
            if (empty($parent)) {
57
                throw new \InvalidArgumentException(
58
                    'Parent posting for creating a new answer not found.',
59
                    1564756571
60
                );
61
            }
62
63
            $data = $this->prepareChildPosting($parent, $data);
64
        } else {
65
            /// if no pid is provided the new posting is root-posting
66
            $data['pid'] = 0;
67
        }
68
69
        /// set user who created the posting
70
        $data['user_id'] = $CurrentUser->getId();
71
        $data['name'] = $CurrentUser->get('username');
72
73
        $this->validatorSetup($CurrentUser);
74
75
        /** @var EntriesTable */
76
        $table = $this->getTable();
77
78
        return $table->createEntry($data);
79
    }
80
81
    /**
82
     * Updates an existing posting
83
     *
84
     * @param Entry $posting the posting to update
85
     * @param array $data data the posting should be updated with
86
     * @param CurrentUserInterface $CurrentUser the current-user
87
     * @return Entry the posting which was asked to update
88
     */
89
    public function updatePosting(Entry $posting, array $data, CurrentUserInterface $CurrentUser): Entry
90
    {
91
        $data = $this->fieldFilter->filterFields($data, 'update');
92
        $isRoot = $posting->isRoot();
93
        $parent = $this->getTable()->get($posting->get('pid'));
94
95
        if (!$isRoot) {
96
            $data = $this->prepareChildPosting($parent, $data);
97
        }
98
99
        $data['edited_by'] = $CurrentUser->get('username');
100
101
        /// must be set for validation
102
        $data['time'] = $posting->get('time');
103
        $data['user_id'] = $posting->get('user_id');
104
        $data['locked'] = $posting->get('locked');
105
106
        $this->validatorSetup($CurrentUser);
107
        $this->getTable()->getValidator()->add(
108
            'edited_by',
109
            'isEditingAllowed',
110
            ['rule' => [$this, 'validateEditingAllowed']]
111
        );
112
113
        /** @var EntriesTable */
114
        $table = $this->getTable();
115
116
        return $table->updateEntry($posting, $data);
117
    }
118
119
    /**
120
     * Populates data of an answer derived from parent the parent-posting
121
     *
122
     * @param BasicPostingInterface $parent parent data
123
     * @param array $data current posting data
124
     * @return array populated $data
125
     */
126
    public function prepareChildPosting(BasicPostingInterface $parent, array $data): array
127
    {
128
        if (empty($data['subject'])) {
129
            /// if new subject is empty use the parent's subject
130
            $data['subject'] = $parent->get('subject');
131
        }
132
133
        $data['tid'] = $parent->get('tid');
134
        $data['category_id'] = $parent->get('category_id');
135
136
        return $data;
137
    }
138
139
    /**
140
     * Sets-up validator for the table
141
     *
142
     * @param CurrentUserInterface $CurrentUser current user
143
     * @return void
144
     */
145
    private function validatorSetup(CurrentUserInterface $CurrentUser): void
146
    {
147
        $this->CurrentUser = $CurrentUser;
148
149
        $this->getTable()->getValidator()->add(
150
            'category_id',
151
            'isAllowed',
152
            ['rule' => [$this, 'validateCategoryIsAllowed']]
153
        );
154
    }
155
156
    /**
157
     * check that entries are only in existing and allowed categories
158
     *
159
     * @param mixed $categoryId value
160
     * @param array $context context
161
     * @return bool
162
     */
163
    public function validateCategoryIsAllowed($categoryId, $context): bool
164
    {
165
        $isRoot = $context['data']['pid'] == 0;
166
        $action = $isRoot ? 'thread' : 'answer';
167
168
        // @td better return !$posting->isAnsweringForbidden();
169
        return $this->CurrentUser->getCategories()->permission($action, $categoryId);
170
    }
171
172
    /**
173
     * check editing allowed
174
     *
175
     * @param mixed $check value
176
     * @param array $context context
177
     * @return bool
178
     */
179
    public function validateEditingAllowed($check, $context): bool
180
    {
181
        $posting = new Posting($this->CurrentUser, $context['data']);
182
183
        return $posting->isEditingAllowed();
184
    }
185
}
186