Completed
Push — master ( 9dab44...8bd79e )
by Robbie
02:00
created

src/Forms/CommentForm.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SilverStripe\Comments\Forms;
4
5
use SilverStripe\Control\HTTPResponse;
6
use SilverStripe\Forms\CompositeField;
7
use SilverStripe\Forms\EmailField;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\Form;
10
use SilverStripe\Forms\FormAction;
11
use SilverStripe\Forms\HiddenField;
12
use SilverStripe\Forms\ReadonlyField;
13
use SilverStripe\Forms\RequiredFields;
14
use SilverStripe\Forms\TextareaField;
15
use SilverStripe\Forms\TextField;
16
use SilverStripe\Security\Member;
17
use SilverStripe\Control\Cookie;
18
use SilverStripe\Core\Convert;
19
use SilverStripe\Security\Security;
20
use SilverStripe\Comments\Model\Comment;
21
use SilverStripe\Control\Controller;
22
use SilverStripe\Comments\Controllers\CommentingController;
23
use SilverStripe\Core\Config\Config;
24
25
class CommentForm extends Form
26
{
27
    /**
28
     * @param string $name
29
     * @param CommentingController $controller
30
     */
31
    public function __construct($name, CommentingController $controller)
32
    {
33
        $usePreview = $controller->getOption('use_preview');
34
        $nameRequired = _t('CommentInterface.YOURNAME_MESSAGE_REQUIRED', 'Please enter your name');
35
        $emailRequired = _t('CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED', 'Please enter your email address');
36
        $emailInvalid = _t('CommentInterface.EMAILADDRESS_MESSAGE_EMAIL', 'Please enter a valid email address');
37
        $urlInvalid = _t('CommentInterface.COMMENT_MESSAGE_URL', 'Please enter a valid URL');
38
        $commentRequired = _t('CommentInterface.COMMENT_MESSAGE_REQUIRED', 'Please enter your comment');
39
40
        $fields = FieldList::create(
41
            $dataFields = CompositeField::create(
42
                // Name
43
                $a = TextField::create('Name', _t('CommentInterface.YOURNAME', 'Your name'))
44
                    ->setCustomValidationMessage($nameRequired)
45
                    ->setAttribute('data-msg-required', $nameRequired),
46
                // Email
47
                EmailField::create(
48
                    'Email',
49
                    _t('SilverStripe\\Comments\\Controllers\\CommentingController.EMAILADDRESS', 'Your email address (will not be published)')
50
                )
51
                    ->setCustomValidationMessage($emailRequired)
52
                    ->setAttribute('data-msg-required', $emailRequired)
53
                    ->setAttribute('data-msg-email', $emailInvalid)
54
                    ->setAttribute('data-rule-email', true),
55
                // Url
56
                TextField::create('URL', _t('SilverStripe\\Comments\\Controllers\\CommentingController.WEBSITEURL', 'Your website URL'))
57
                    ->setAttribute('data-msg-url', $urlInvalid)
58
                    ->setAttribute('data-rule-url', true),
59
                // Comment
60
                TextareaField::create('Comment', _t('SilverStripe\\Comments\\Controllers\\CommentingController.COMMENTS', 'Comments'))
61
                    ->setCustomValidationMessage($commentRequired)
62
                    ->setAttribute('data-msg-required', $commentRequired)
63
            ),
64
            HiddenField::create('ParentID'),
65
            HiddenField::create('ParentClassName'),
66
            HiddenField::create('ReturnURL'),
67
            HiddenField::create('ParentCommentID')
68
        );
69
70
        // Preview formatted comment. Makes most sense when shortcodes or
71
        // limited HTML is allowed. Populated by JS/Ajax.
72
        if ($usePreview) {
73
            $fields->insertAfter(
74
                ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview'))
75
                    ->setAttribute('style', 'display: none'), // enable through JS
76
                'Comment'
77
            );
78
        }
79
80
        $dataFields->addExtraClass('data-fields');
81
82
        // save actions
83
        $actions = FieldList::create(
84
            $postAction = new FormAction('doPostComment', _t('CommentInterface.POST', 'Post'))
85
        );
86
87
        if ($usePreview) {
88
            $actions->push(
89
                FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview'))
90
                    ->addExtraClass('action-minor')
91
                    ->setAttribute('style', 'display: none') // enable through JS
92
            );
93
        }
94
95
        $required = new RequiredFields(
96
            $controller->config()->required_fields
97
        );
98
99
        parent::__construct($controller, $name, $fields, $actions, $required);
100
101
102
        // if the record exists load the extra required data
103
        if ($record = $controller->getOwnerRecord()) {
104
            // Load member data
105
            $member = Member::currentUser();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
106
            if (($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) {
107
                $fields = $this->Fields();
108
109
                $fields->removeByName('Name');
110
                $fields->removeByName('Email');
111
                $fields->insertBefore(
112
                    new ReadonlyField(
113
                        'NameView',
114
                        _t('CommentInterface.YOURNAME', 'Your name'),
115
                        $member->getName()
116
                    ),
117
                    'URL'
118
                );
119
                $fields->push(new HiddenField('Name', '', $member->getName()));
120
                $fields->push(new HiddenField('Email', '', $member->Email));
121
            }
122
123
            // we do not want to read a new URL when the form has already been submitted
124
            // which in here, it hasn't been.
125
            $this->loadDataFrom(array(
126
                'ParentID'        => $record->ID,
127
                'ReturnURL'       => $controller->getRequest()->getURL(),
128
                'ParentClassName' => $controller->getParentClass()
129
            ));
130
        }
131
132
        // Set it so the user gets redirected back down to the form upon form fail
133
        $this->setRedirectToFormOnValidationError(true);
134
135
        // load any data from the cookies
136
        if ($data = Cookie::get('CommentsForm_UserData')) {
137
            $data = Convert::json2array($data);
138
139
            $this->loadDataFrom(array(
140
                'Name'  => isset($data['Name']) ? $data['Name'] : '',
141
                'URL'   => isset($data['URL']) ? $data['URL'] : '',
142
                'Email' => isset($data['Email']) ? $data['Email'] : ''
143
            ));
144
145
            // allow previous value to fill if comment not stored in cookie (i.e. validation error)
146
            $prevComment = Cookie::get('CommentsForm_Comment');
147
148
            if ($prevComment && $prevComment != '') {
149
                $this->loadDataFrom(array('Comment' => $prevComment));
150
            }
151
        }
152
    }
153
154
    /**
155
     * @param  array $data
156
     * @param  Form $form
157
     * @return HTTPResponse
158
     */
159
    public function doPreviewComment($data, $form)
160
    {
161
        $data['IsPreview'] = 1;
162
163
        return $this->doPostComment($data, $form);
164
    }
165
166
    /**
167
     * Process which creates a {@link Comment} once a user submits a comment from this form.
168
     *
169
     * @param  array $data
170
     * @param  Form $form
171
     * @return HTTPResponse
172
     */
173
    public function doPostComment($data, $form)
174
    {
175
        // Load class and parent from data
176
        if (isset($data['ParentClassName'])) {
177
            $this->controller->setParentClass($data['ParentClassName']);
178
        }
179
        if (isset($data['ParentID']) && ($class = $this->controller->getParentClass())) {
180
            $this->controller->setOwnerRecord($class::get()->byID($data['ParentID']));
181
        }
182
        if (!$this->controller->getOwnerRecord()) {
183
            return $this->getRequestHandler()->httpError(404);
184
        }
185
186
        // cache users data
187
        Cookie::set('CommentsForm_UserData', Convert::raw2json($data));
188
        Cookie::set('CommentsForm_Comment', $data['Comment']);
189
190
        // extend hook to allow extensions. Also see onAfterPostComment
191
        $this->controller->extend('onBeforePostComment', $form);
192
193
        // If commenting can only be done by logged in users, make sure the user is logged in
194
        if (!$this->controller->getOwnerRecord()->canPostComment()) {
195
            return Security::permissionFailure(
196
                $this->controller,
197
                _t(
198
                    'SilverStripe\\Comments\\Controllers\\CommentingController.PERMISSIONFAILURE',
199
                    "You're not able to post comments to this page. Please ensure you are logged in and have an "
200
                    . 'appropriate permission level.'
201
                )
202
            );
203
        }
204
205
        if ($member = Security::getCurrentUser()) {
206
            $form->Fields()->push(new HiddenField('AuthorID', 'Author ID', $member->ID));
207
        }
208
209
        // What kind of moderation is required?
210
        switch ($this->controller->getOwnerRecord()->ModerationRequired) {
211
            case 'Required':
212
                $requireModeration = true;
213
                break;
214
            case 'NonMembersOnly':
215
                $requireModeration = empty($member);
216
                break;
217
            case 'None':
218
            default:
219
                $requireModeration = false;
220
                break;
221
        }
222
223
        $comment = Comment::create();
224
        $form->saveInto($comment);
225
226
        $comment->ParentID = $data['ParentID'];
227
        $comment->ParentClass = $data['ParentClassName'];
228
229
        $comment->AllowHtml = $this->controller->getOption('html_allowed');
230
        $comment->Moderated = !$requireModeration;
231
232
        // Save into DB, or call pre-save hooks to give accurate preview
233
        $usePreview = $this->controller->getOption('use_preview');
234
        $isPreview = $usePreview && !empty($data['IsPreview']);
235
        if ($isPreview) {
236
            $comment->extend('onBeforeWrite');
237
        } else {
238
            $comment->write();
239
240
            // extend hook to allow extensions. Also see onBeforePostComment
241
            $this->controller->extend('onAfterPostComment', $comment);
242
        }
243
244
        // we want to show a notification if comments are moderated
245
        if ($requireModeration && !$comment->IsSpam) {
246
            $this->getRequest()->getSession()->set('CommentsModerated', 1);
247
        }
248
249
        // clear the users comment since it passed validation
250
        Cookie::set('CommentsForm_Comment', false);
251
252
        // Find parent link
253
        if (!empty($data['ReturnURL'])) {
254
            $url = $data['ReturnURL'];
255
        } elseif ($parent = $comment->Parent()) {
256
            $url = $parent->Link();
257
        } else {
258
            return $this->controller->redirectBack();
259
        }
260
261
        // Given a redirect page exists, attempt to link to the correct anchor
262
        if ($comment->IsSpam) {
263
            // Link to the form with the error message contained
264
            $hash = $form->FormName();
265
        } elseif (!$comment->Moderated) {
266
            // Display the "awaiting moderation" text
267
            $hash = 'moderated';
268
        } else {
269
            // Link to the moderated, non-spam comment
270
            $hash = $comment->Permalink();
271
        }
272
273
        return $this->controller->redirect(Controller::join_links($url, "#{$hash}"));
274
    }
275
}
276