Completed
Pull Request — master (#203)
by
unknown
40:36
created

ForumThread::canCreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace SilverStripe\Forum\Models;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Forum\Pages\Forum;
7
use SilverStripe\ORM\FieldType\DBBoolean;
8
use SilverStripe\ORM\FieldType\DBInt;
9
use SilverStripe\ORM\FieldType\DBText;
10
use SilverStripe\ORM\FieldType\DBVarchar;
11
use SilverStripe\ORM\HasManyList;
12
use SilverStripe\Security\Member;
13
use SilverStripe\ORM\DataObject;
14
use SilverStripe\Control\Session;
15
use SilverStripe\Core\Convert;
16
use SilverStripe\ORM\DB;
17
use SilverStripe\ORM\FieldType\DBField;
18
use SilverStripe\Core\Config\Config;
19
use SilverStripe\Control\Email\Email;
20
use SilverStripe\Control\Director;
21
22
/**
23
 * A representation of a forum thread. A forum thread is 1 topic on the forum
24
 * which has multiple posts underneath it.
25
 *
26
 * @package forum
27
 * @property DBVarchar Title
28
 * @property DBInt     NumViews
29
 * @property DBBoolean IsSticky
30
 * @property DBBoolean IsReadOnly
31
 * @property DBBoolean IsGlobalSticky
32
 * @method Forum Forum
33
 * @method HasManyList Posts
34
 */
35
class ForumThread extends DataObject
36
{
37
    /** @var array */
38
    private static $db = array(
39
        "Title"          => "Varchar(255)",
40
        "NumViews"       => "Int",
41
        "IsSticky"       => "Boolean",
42
        "IsReadOnly"     => "Boolean",
43
        "IsGlobalSticky" => "Boolean"
44
    );
45
46
    /** @var array */
47
    private static $has_one = array(
48
        'Forum' => 'Forum'
49
    );
50
51
    /** @var array */
52
    private static $has_many = array(
53
        'Posts' => 'Post'
54
    );
55
56
    /** @var array */
57
    private static $defaults = array(
58
        'NumViews'       => 0,
59
        'IsSticky'       => false,
60
        'IsReadOnly'     => false,
61
        'IsGlobalSticky' => false
62
    );
63
64
    /** @var array */
65
    private static $indexes = array(
66
        'IsSticky'       => true,
67
        'IsGlobalSticky' => true
68
    );
69
70
    /**
71
     * @var null|boolean Per-request cache, whether we should display signatures on a post.
72
     */
73
    private static $cacheDisplaySignatures = null;
74
75
    /**
76
     * Check if the user can create new threads and add responses
77
     *
78
     * @param null|Member $member
79
     *
80
     * @return bool
81
     */
82
    public function canPost($member = null)
83
    {
84
        if (!$member) {
85
            $member = Member::currentUser();
86
        }
87
88
        return ($this->Forum()->canPost($member) && !$this->IsReadOnly);
89
    }
90
91
    /**
92
     * Check if user can moderate this thread
93
     *
94
     * @param null|Member $member
95
     *
96
     * @return bool
97
     */
98
    public function canModerate($member = null)
99
    {
100
        if (!$member) {
101
            $member = Member::currentUser();
102
        }
103
104
        return $this->Forum()->canModerate($member);
105
    }
106
107
    /**
108
     * Check if user can view the thread
109
     *
110
     * @param null|Member $member
111
     *
112
     * @return bool
113
     */
114
    public function canView($member = null)
115
    {
116
        if (!$member) {
117
            $member = Member::currentUser();
118
        }
119
120
        return $this->Forum()->canView($member);
121
    }
122
123
    /**
124
     * Hook up into moderation.
125
     *
126
     * @param null|Member $member
127
     *
128
     * @return bool
129
     */
130
    public function canEdit($member = null)
131
    {
132
        if (!$member) {
133
            $member = Member::currentUser();
134
        }
135
136
        return $this->canModerate($member);
137
    }
138
139
    /**
140
     * Hook up into moderation - users cannot delete their own posts/threads because
141
     * we will loose history this way.
142
     *
143
     * @param null|Member $member
144
     *
145
     * @return bool
146
     */
147
    public function canDelete($member = null)
148
    {
149
        if (!$member) {
150
            $member = Member::currentUser();
151
        }
152
153
        return $this->canModerate($member);
154
    }
155
156
    /**
157
     * Hook up into canPost check
158
     *
159
     * @param null|Member $member
160
     *
161
     * @return bool
162
     */
163
    public function canCreate($member = null)
164
    {
165
        if (!$member) {
166
            $member = Member::currentUser();
167
        }
168
169
        return $this->canPost($member);
170
    }
171
172
    /**
173
     * Are Forum Signatures on Member profiles allowed.
174
     * This only needs to be checked once, so we cache the initial value once per-request.
175
     *
176
     * @return bool
177
     */
178
    public function getDisplaySignatures()
179
    {
180
        if (isset(self::$cacheDisplaySignatures) && self::$cacheDisplaySignatures !== null) {
181
            return self::$cacheDisplaySignatures;
182
        }
183
184
        $result                       = $this->Forum()->Parent()->DisplaySignatures;
185
        self::$cacheDisplaySignatures = $result;
186
187
        return $result;
188
    }
189
190
    /**
191
     * Get the latest post from this thread. Nicer way then using an control
192
     * from the template
193
     *
194
     * @return Post
195
     */
196
    public function getLatestPost()
197
    {
198
        return Post::get()->filter(['ThreadID' => $this->ID])
199
            ->sort('ID DESC')
200
            ->first();
201
    }
202
203
    /**
204
     * Return the first post from the thread. Useful to working out the original author
205
     *
206
     * @return Post
207
     */
208
    public function getFirstPost()
209
    {
210
        return Post::get()->filter(['ThreadID' => $this->ID])
211
            ->sort('ID ASC')
212
            ->first();
213
    }
214
215
    /**
216
     * Return the number of posts in this thread. We could use count on
217
     * the dataobject set but that is slower and causes a performance overhead
218
     *
219
     * @todo SS4 compat
220
     * @return int
221
     */
222 View Code Duplication
    public function getNumPosts()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
    {
224
        $sqlQuery = new SQLQuery();
225
        $sqlQuery->setFrom('"Post"');
226
        $sqlQuery->setSelect('COUNT("Post"."ID")');
227
        $sqlQuery->addInnerJoin('SilverStripe\\Security\\Member', '"Post"."AuthorID" = "Member"."ID"');
228
        $sqlQuery->addWhere('"Member"."ForumStatus" = \'Normal\'');
229
        $sqlQuery->addWhere('"ThreadID" = ' . $this->ID);
230
231
        return $sqlQuery->execute()->value();
232
    }
233
234
    /**
235
     * Check if they have visited this thread before. If they haven't increment
236
     * the NumViews value by 1 and set visited to true.
237
     *
238
     * @return void
239
     */
240
    public function incNumViews()
241
    {
242
        if (Session::get('ForumViewed-' . $this->ID)) {
243
            return;
244
        }
245
246
        Session::set('ForumViewed-' . $this->ID, 'true');
247
248
        $this->NumViews++;
249
        $this->write();
250
    }
251
252
    /**
253
     * Link to this forum thread
254
     *
255
     * @param string $action
256
     * @param bool   $showID
257
     *
258
     * @return String
259
     */
260
    public function Link($action = "show", $showID = true)
261
    {
262
        /** @var Forum $forum */
263
        $forum = Forum::get()->byID($this->ForumID);
264
        if (!$forum) {
265
            user_error("Bad ForumID '$this->ForumID'", E_USER_WARNING);
266
        }
267
268
        $baseLink = $forum->Link();
269
270
        return ($action) ? Controller::join_links($baseLink, $action, ($showID) ? $this->ID : null) : $baseLink;
271
    }
272
273
    /**
274
     * Check to see if the user has subscribed to this thread
275
     *
276
     * @return bool
277
     */
278
    public function getHasSubscribed()
279
    {
280
        $member = Member::currentUser();
281
282
        return ($member) ? ForumThreadSubscription::alreadySubscribed($this->ID, $member->ID) : false;
283
    }
284
285
    /**
286
     * Before deleting the thread remove all the posts
287
     *
288
     * @return void
289
     */
290
    public function onBeforeDelete()
291
    {
292
        parent::onBeforeDelete();
293
294
        if ($posts = $this->Posts()) {
295
            foreach ($posts as $post) {
296
                // attachment deletion is handled by the {@link Post::onBeforeDelete}
297
                $post->delete();
298
            }
299
        }
300
    }
301
302
    /**
303
     * Ensure the correct ForumID is applied to the record
304
     * 
305
     * @return void
306
     */
307
    public function onAfterWrite()
308
    {
309
        if ($this->isChanged('ForumID', 2)) {
310
            $posts = $this->Posts();
311
            if ($posts && $posts->count()) {
312
                foreach ($posts as $post) {
313
                    $post->ForumID = $this->ForumID;
314
                    $post->write();
315
                }
316
            }
317
        }
318
        parent::onAfterWrite();
319
    }
320
321
    /**
322
     * @return DBText
323
     */
324
    public function getEscapedTitle()
325
    {
326
        return DBField::create_field('Text', $this->dbObject('Title')->XML());
327
    }
328
}