Version: current

      1 <?php
      2 /**
      3  * Represents an interface for viewing and adding page comments
      4  * Create one, passing the page discussed to the constructor.  It can then be
      5  * inserted into a template.
      6  * @package cms
      7  * @subpackage comments
      8  */
      9 class PageCommentInterface extends RequestHandler {
     10     static $url_handlers = array(
     11         '$Item!' => '$Item',
     12     );
     13     static $allowed_actions = array(
     14         'PostCommentForm',
     15     );
     16
     17     protected $controller, $methodName, $page;
     18
     19     /**
     20      * If this is true, you must be logged in to post a comment
     21      * (and therefore, you don't need to specify a 'Your name' field unless
     22      * your name is blank)
     23      *
     24      * @var bool
     25      */
     26     static $comments_require_login = false;
     27
     28     /**
     29      * If this is a valid permission code, you must be logged in
     30      * and have the appropriate permission code on your account before you can
     31      * post a comment.
     32      *
     33      * @var string
     34      */
     35     static $comments_require_permission = "";
     36
     37     /**
     38      * If this is true it will include the javascript for AJAX
     39      * commenting. If it is set to false then it will not load
     40      * the files required and it will fall back
     41      *
     42      * @var bool
     43      */
     44     static $use_ajax_commenting = true;
     45
     46     /**
     47      * If this is true then we should show the existing comments on
     48      * the page even when we have disabled the comment form.
     49      *
     50      * If this is false the form + existing comments will be hidden
     51      *
     52      * @var bool
     53      * @since 2.4 - Always show them by default
     54      */
     55     static $show_comments_when_disabled = true;
     56
     57     /**
     58      * Define how you want to order page comments by. By default order by newest
     59      * to oldest.
     60      *
     61      * @var String - used as $orderby in DB query
     62      * @since 2.4
     63      */
     64     static $order_comments_by = "\"Created\" DESC";
     65
     66     /**
     67      * Required fields for Comment Form
     68      *
     69      * by menedem
     70      */
     71     static $required_fields = array();
     72
     73     /**
     74      * Create a new page comment interface
     75      * @param controller The controller that the interface is used on
     76      * @param methodName The method to return this PageCommentInterface object
     77      * @param page The page that we're commenting on
     78      */
     79     function __construct($controller, $methodName, $page) {
     80         $this->controller = $controller;
     81         $this->methodName = $methodName;
     82         $this->page = $page;
     83         parent::__construct();
     84     }
     85
     86     function Link() {
     87         return Controller::join_links($this->controller->Link(), $this->methodName);
     88     }
     89
     90     /**
     91      * See {@link PageCommentInterface::$comments_require_login}
     92      *
     93      * @param boolean state The new state of this static field
     94      */
     95     static function set_comments_require_login($state) {
     96         self::$comments_require_login = (boolean) $state;
     97     }
     98
     99     /**
    100      * See {@link PageCommentInterface::$comments_require_permission}
    101      *
    102      * @param string permission The permission to check against.
    103      */
    104     static function set_comments_require_permission($permission) {
    105         self::$comments_require_permission = $permission;
    106     }
    107
    108     /**
    109      * See {@link PageCommentInterface::$show_comments_when_disabled}
    110      *
    111      * @param bool - show / hide the existing comments when disabled
    112      */
    113     static function set_show_comments_when_disabled($state) {
    114         self::$show_comments_when_disabled = $state;
    115     }
    116
    117     /**
    118      * See {@link PageCommentInterface::$order_comments_by}
    119      *
    120      * @param String
    121      */
    122     static function set_order_comments_by($order) {
    123         self::$order_comments_by = $order;
    124     }
    125
    126     /**
    127      * See {@link PageCommentInterface::$use_ajax_commenting}
    128      *
    129      * @param bool
    130      */
    131     static function set_use_ajax_commenting($state) {
    132         self::$use_ajax_commenting = $state;
    133     }
    134
    135     function forTemplate() {
    136         return $this->renderWith('PageCommentInterface');
    137     }
    138
    139     /**
    140      * @return boolean true if the currently logged in user can post a comment,
    141      * false if they can't. Users can post comments by default, enforce
    142      * security by using
    143      * @link PageCommentInterface::set_comments_require_login() and
    144      * @link {PageCommentInterface::set_comments_require_permission()}.
    145      */
    146     static function CanPostComment() {
    147         $member = Member::currentUser();
    148         if(self::$comments_require_permission && $member && Permission::check(self::$comments_require_permission)) {
    149             return true; // Comments require a certain permission, and the user has the correct permission
    150         } elseif(self::$comments_require_login && $member && !self::$comments_require_permission) {
    151             return true; // Comments only require that a member is logged in
    152         } elseif(!self::$comments_require_permission && !self::$comments_require_login) {
    153             return true; // Comments don't require anything - anyone can add a comment
    154         }
    155
    156         return false;
    157     }
    158
    159     /**
    160      * if this page comment form requires users to have a
    161      * valid permission code in order to post (used to customize the error
    162      * message).
    163      *
    164      * @return bool
    165      */
    166     function PostingRequiresPermission() {
    167         return self::$comments_require_permission;
    168     }
    169
    170     function Page() {
    171         return $this->page;
    172     }
    173
    174     function PostCommentForm() {
    175         if(!$this->page->ProvideComments || !$this->page->allowComments()){
    176             return false;
    177         }
    178         $fields = new FieldSet(
    179             new HiddenField("ParentID", "ParentID", $this->page->ID)
    180         );
    181
    182         $member = Member::currentUser();
    183
    184         if((self::$comments_require_login || self::$comments_require_permission) && $member && $member->FirstName) {
    185             // note this was a ReadonlyField - which displayed the name in a span as well as the hidden field but
    186             // it was not saving correctly. Have changed it to a hidden field. It passes the data correctly but I
    187             // believe the id of the form field is wrong.
    188             $fields->push(new ReadonlyField("NameView", _t('PageCommentInterface.YOURNAME', 'Your name'), $member->getName()));
    189             $fields->push(new HiddenField("Name", "", $member->getName()));
    190         } else {
    191             $fields->push(new TextField("Name", _t('PageCommentInterface.YOURNAME', 'Your name')));
    192         }
    193
    194         // optional commenter URL
    195         $fields->push(new TextField("CommenterURL", _t('PageCommentInterface.COMMENTERURL', "Your website URL")));
    196
    197         if(MathSpamProtection::isEnabled()){
    198             $fields->push(new TextField("Math", sprintf(_t('PageCommentInterface.SPAMQUESTION', "Spam protection question: %s"), MathSpamProtection::getMathQuestion())));
    199         }
    200
    201         $fields->push(new TextareaField("Comment", _t('PageCommentInterface.YOURCOMMENT', "Comments")));
    202
    203         $required_fields = self::$required_fields;
    204         $siteConfig = SiteConfig::current_site_config();
    205         if ($siteConfig->hasMethod('SiteAgreementField') && ($rulesField = $siteConfig->SiteAgreementField())) {
    206             $fields->push($rulesField);
    207             $required_fields[] = $rulesField->Name();
    208         }
    209         $validator = new RequiredFields($required_fields);
    210
    211         $form = new PageCommentInterface_Form($this, "PostCommentForm", $fields, new FieldSet(
    212             new FormAction("postcomment", _t('PageCommentInterface.POST', 'Post'))
    213         ), $validator);
    214
    215         // Set it so the user gets redirected back down to the form upon form fail
    216         $form->setRedirectToFormOnValidationError(true);
    217
    218         // Optional Spam Protection.
    219         if(class_exists('SpamProtectorManager')) {
    220             SpamProtectorManager::update_form($form, null, array('Name' => 'author_name', 'CommenterURL' => 'author_url', 'Comment' => 'post_body'),_t('PageCommentInterface.Captcha','SpamProtection'));
    221             self::set_use_ajax_commenting(false);
    222         }
    223
    224         // Shall We use AJAX?
    225         if(self::$use_ajax_commenting) {
    226             Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/behaviour/behaviour.js');
    227             Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/prototype/prototype.js');
    228             Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/effects.js');
    229             Requirements::javascript(CMS_DIR . '/javascript/PageCommentInterface.js');
    230         }
    231
    232         $this->extend('updatePageCommentForm', $form);
    233         // Load the data from Session
    234         $form->loadDataFrom(array(
    235             "Name" => Cookie::get("PageCommentInterface_Name"),
    236             "Comment" => Cookie::get("PageCommentInterface_Comment"),
    237             "CommenterURL" => Cookie::get("PageCommentInterface_CommenterURL")
    238         ));
    239
    240         return $form;
    241     }
    242
    243     function Comments() {
    244         // Comment limits
    245         $limit = array();
    246         $limit['start'] = isset($_GET['commentStart']) ? (int)$_GET['commentStart'] : 0;
    247         $limit['limit'] = PageComment::$comments_per_page;
    248
    249         $spamfilter = isset($_GET['showspam']) ? '' : "AND \"IsSpam\" = 0";
    250         $unmoderatedfilter = Permission::check('ADMIN') ? '' : "AND \"NeedsModeration\" = 0";
    251         $order = self::$order_comments_by;
    252         $comments =  DataObject::get("PageComment", "\"ParentID\" = '" . Convert::raw2sql($this->page->ID) . "' $spamfilter $unmoderatedfilter", $order, "", $limit);
    253
    254         if(is_null($comments)) {
    255             return;
    256         }
    257
    258         // This allows us to use the normal 'start' GET variables as well (In the weird circumstance where you have paginated comments AND something else paginated)
    259         $comments->setPaginationGetVar('commentStart');
    260
    261         return $comments;
    262     }
    263
    264     function CommentRssLink() {
    265         return Director::absoluteBaseURL() . "PageComment/rss?pageid=" . $this->page->ID;
    266     }
    267
    268     /**
    269      * A link to PageComment_Controller.deleteallcomments() which deletes all
    270      * comments on a page referenced by the url param pageid
    271      */
    272     function DeleteAllLink() {
    273         if(Permission::check('CMS_ACCESS_CMSMain')) {
    274             return Director::absoluteBaseURL() . "PageComment/deleteallcomments?pageid=" . $this->page->ID;
    275         }
    276     }
    277
    278 }
    279
    280 /**
    281  * @package cms
    282  * @subpackage comments
    283  */
    284 class PageCommentInterface_Form extends Form {
    285     function postcomment($data) {
    286         // Spam filtering
    287         Cookie::set("PageCommentInterface_Name", $data['Name']);
    288         Cookie::set("PageCommentInterface_CommenterURL", $data['CommenterURL']);
    289         Cookie::set("PageCommentInterface_Comment", $data['Comment']);
    290
    291         if(SSAkismet::isEnabled()) {
    292             try {
    293                 $akismet = new SSAkismet();
    294
    295                 $akismet->setCommentAuthor($data['Name']);
    296                 $akismet->setCommentContent($data['Comment']);
    297
    298                 if($akismet->isCommentSpam()) {
    299                     if(SSAkismet::getSaveSpam()) {
    300                         $comment = SS_Object::create('PageComment');
    301                         $this->saveInto($comment);
    302                         $comment->setField("IsSpam", true);
    303                         $comment->write();
    304                     }
    305                     echo "<b>"._t('PageCommentInterface_Form.SPAMDETECTED', 'Spam detected!!') . "</b><br /><br />";
    306                     printf("If you believe this was in error, please email %s.", preg_replace("!@!", " _(at)_", Email::getAdminEmail()));
    307                     echo "<br /><br />"._t('PageCommentInterface_Form.MSGYOUPOSTED', 'The message you posted was:'). "<br /><br />";
    308                     echo $data['Comment'];
    309
    310                     return;
    311                 }
    312             } catch (Exception $e) {
    313                 // Akismet didn't work, continue without spam check
    314             }
    315         }
    316
    317         //check if spam question was right.
    318         if(MathSpamProtection::isEnabled()){
    319             if(!MathSpamProtection::correctAnswer($data['Math'])){
    320                 if(!Director::is_ajax()) {
    321                     Director::redirectBack();
    322                 }
    323                 return "spamprotectionfailed"; //used by javascript for checking if the spam question was wrong
    324             }
    325         }
    326
    327         // If commenting can only be done by logged in users, make sure the user is logged in
    328         $member = Member::currentUser();
    329         if(PageCommentInterface::CanPostComment() && $member) {
    330             $this->Fields()->push(new HiddenField("AuthorID", "Author ID", $member->ID));
    331         } elseif(!PageCommentInterface::CanPostComment()) {
    332             echo "You're not able to post comments to this page. Please ensure you are logged in and have an appropriate permission level.";
    333             return;
    334         }
    335
    336         $comment = SS_Object::create('PageComment');
    337         $this->saveInto($comment);
    338
    339         // Store the Session ID if needed for Spamprotection
    340         if($session = Session::get('mollom_user_session_id')) {
    341             $comment->SessionID = $session;
    342             Session::clear('mollom_user_session_id');
    343         }
    344         $comment->IsSpam = false;
    345         $comment->NeedsModeration = PageComment::moderationEnabled();
    346         $comment->write();
    347
    348         $this->extend('OnAfterPost', $comment, $data);
    349         Cookie::set("PageCommentInterface_Comment", '');
    350
    351         $moderationMsg = _t('PageCommentInterface_Form.AWAITINGMODERATION', "Your comment has been submitted and is now awaiting moderation.");
    352
    353         if(Director::is_ajax()) {
    354             if($comment->NeedsModeration){
    355                 echo $moderationMsg;
    356             } else{
    357                 echo $comment->renderWith('PageCommentInterface_singlecomment');
    358             }
    359         } else {
    360             if($comment->NeedsModeration){
    361                 $this->sessionMessage($moderationMsg, 'good');
    362             }
    363             // since it is not ajax redirect user down to their comment since it has been posted
    364             // get the pages url off the comments parent ID.
    365             if($comment->ParentID) {
    366                 $page = DataObject::get_by_id("Page", $comment->ParentID);
    367                 if($page) {
    368                     // Redirect to the actual post on the page.
    369                     return Director::redirect($page->Link() . '#PageComment_' . $comment->ID);
    370                 }
    371             }
    372
    373             return Director::redirectBack(); // worst case, just go back to the page
    374         }
    375     }
    376 }
    377
    378 /**
    379  * @package cms
    380  * @subpackage comments
    381  */
    382 class PageCommentInterface_Controller extends ContentController {
    383     function __construct() {
    384         parent::__construct(null);
    385     }
    386
    387     function newspamquestion() {
    388         if(Director::is_ajax()) {
    389             echo Convert::raw2xml(sprintf(_t('PageCommentInterface_Controller.SPAMQUESTION', "Spam protection question: %s"),MathSpamProtection::getMathQuestion()));
    390         }
    391     }
    392 }
    393
    394 ?>
    395

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -