Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Customising the CMS

adding fields to the page comment form


Go to End
Reply

9 Posts   14976 Views

Avatar
Anatol

12 February 2010 at 2:42pm 126 Posts

Hi,

this question is related to [url=http://www.silverstripe.org/general-questions/show/266651]this post[/url].

What I want to do is to remove the URL field from the comment form and instead add an email field and a 'private message' checkbox field (to allow users to send a comment that is not visible on the public site but only to me when I'm logged in to the CMS).

I can create the form, no problem. To do so I added the following code to the end of /mysite/code/Page.php

class PageCommentPlus extends Extension {
   function extraStatics() {
      return array(
         'db' => array(
            'CommenterEmail' => 'Text',
            'Private' => 'Boolean'
         )
      );
   }
}

class PageCommentPlusInterface extends PageCommentInterface {
   
   // the following method is simply copied from /cms/code/sitefeatures/PageCommentInterface.php; added lines are in green, removed lines in red
   function PostCommentForm() {
      $fields = new FieldSet(
         new HiddenField("ParentID", "ParentID", $this->page->ID)
      );
      
      $member = Member::currentUser();
      
      if((self::$comments_require_login || self::$comments_require_permission) && $member && $member->FirstName) {
         // note this was a ReadonlyField - which displayed the name in a span as well as the hidden field but
         // it was not saving correctly. Have changed it to a hidden field. It passes the data correctly but I
         // believe the id of the form field is wrong.
         $fields->push(new ReadonlyField("NameView", _t('PageCommentInterface.YOURNAME', 'Your name'), $member->getName()));
         $fields->push(new HiddenField("Name", "", $member->getName()));
      } else {
         $fields->push(new TextField("Name", _t('PageCommentInterface.YOURNAME', 'Your name')));
      }
            
      // optional commenter URL
      //$fields->push(new TextField("CommenterURL", _t('PageCommentInterface.COMMENTERURL', "Your website URL")));
      $fields->push(new TextField("CommenterEmail", 'Your email address (will not be published)'));
      
      if(MathSpamProtection::isEnabled()){
         $fields->push(new TextField("Math", sprintf(_t('PageCommentInterface.SPAMQUESTION', "Spam protection question: %s"), MathSpamProtection::getMathQuestion())));
      }            
      
      $fields->push(new TextareaField("Comment", _t('PageCommentInterface.YOURCOMMENT', "Comments")));
      
      $fields->push(new CheckboxField("Private", 'Send this as a private message (your comment will not appear on this website).'));
      
      $form = new PageCommentInterface_Form($this, "PostCommentForm", $fields, new FieldSet(
         new FormAction("postcomment", _t('PageCommentInterface.POST', 'Post'))
      ));
      
      // Set it so the user gets redirected back down to the form upon form fail
      $form->setRedirectToFormOnValidationError(true);
      
      // Optional Spam Protection.
      if(class_exists('SpamProtectorManager')) {
         SpamProtectorManager::update_form($form, null, array('Name', 'CommenterURL', 'Comment'));
         self::set_use_ajax_commenting(false);
      }
      
      // Shall We use AJAX?
      if(self::$use_ajax_commenting) {
         Requirements::javascript(THIRDPARTY_DIR . '/behaviour.js');
         Requirements::javascript(THIRDPARTY_DIR . '/prototype.js');
         Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/effects.js');
         Requirements::javascript(CMS_DIR . '/javascript/PageCommentInterface.js');
      }
      
      // Load the data from Session
      $form->loadDataFrom(array(
         "Name" => Cookie::get("PageCommentInterface_Name"),
         "Comment" => Cookie::get("PageCommentInterface_Comment"),
         "CommenterURL" => Cookie::get("PageCommentInterface_CommenterURL")   
      ));
      
      return $form;
   }
}

The comment form now looks the way it should. When I run /dev/build/?flush=all no fields get added to the database. probably because I haven't added the extension in /mysite/_config.php . But when I add

Object::add_extension('PageComment','PageCommentPlus');
Object::add_extension('PageCommentInterface','PageCommentPlusInterface');

all I get is a PHP error

PHP Fatal Error: Object::add_extension() - Can't find extension class for PageCommentPlus in /path/to/sapphire/core/Object.php on line 404

I then tried to copy class PageCommentPlus extends Extension (see above) into the Object.php file that's mentioned in the error message but that doesn't work either, because then it says

PHP Fatal Error: Class 'Extension' not found in /path/to/sapphire/core/Object.php

I don't think that I'm too far from a solution. Any hints are much appreciated.

Cheers!
Anatol

Avatar
MarcusDalgren

12 February 2010 at 9:45pm Community Member, 288 Posts

You are indeed very close.

There's a tutorial on [url=http://www.ssbits.com/adding-fields-to-page-comments/]SSBits.com[/url] that covers this but I'll try to walk you through the last part here as well.

Your second Object::add_extension is probably what's causing you issues. Your new PageCommentInterface extends the original so it's not a decorator, it's a normal class that you can use normally. Also your PageCommentPlus can extend DataObjectDecorator instead of Extension since PageComment is a DataObject.

Also since all you're doing is adding/removing fields from the parent CommentInterface you don't have to duplicate all that code.
The parent returns a form object so you can grab that and extract the form fields from the form, modify them and then put them back in.

It would look something like this

class PageCommentPlusInterface extends PageCommentInterface {
...
function PostCommentForm() {
   $form = parent::PostCommentForm();
   $fields = $form->Fields();
   $fields->removeByName("CommenterURL");
   $fields->insertAfter(new TextField("CommenterEmail", 'Your email address (will not be published)'), 'Name');
   $fields->insertAfter(new CheckboxField("Private", 'Send this as a private message (your comment will not appear on this website).'), 'Comment');
   $form->setFields($fields);
   return $form;
}
...

All you should need in your _config.php is this

Object::add_extension('PageComment', 'PageCommentPlus');

I have also attached a rar archive with the relevant classes I made when doing this kind of modification so you can look in that code as well if you need to.

Hope this helps!

Avatar
Anatol

16 February 2010 at 3:10pm 126 Posts

Hi Smurkas,

thank you so much for the detailed reply. Highly appreciated. I didn't find the time yet to try this but will do so soon.

Thank you!
Anatol

Avatar
wmk

4 March 2010 at 4:36am Community Member, 45 Posts

Hi Smurkas,

thanks for your very cool solution. Works so far like a charm. Email is saved to db but isn't accessible from CommentAdmin.

How did you extend / decorate CommentAdmin ?

cheers,

wmk

Avatar
MarcusDalgren

4 March 2010 at 4:45am Community Member, 288 Posts

The short answer is that I didn't touch the admin part but there's a tutorial on SSBits that goes into this. You can read it [url=http://www.ssbits.com/adding-fields-to-page-comments/]here[/url]. I haven't tried that part of the tutorial but I think you can pretty much do the same thing with that part that I did with the PostCommentForm-function. That way you don't have to copy the original function.

If I have the time I'll look at it and post back here on what I find.

Avatar
IOTI

5 June 2010 at 2:46am Community Member, 189 Posts

I've been trying to use the code in this post to achieve these results, I have the new email field showing up in my DB but not in the actual form.

I created a class called PageCommentPlus.php

<?php

class PageCommentPlus extends Extension{
      
      public function extraStatics(){
      
         return array(
            'db' => array("CommenterEmail" => "Varchar")
         );
      }
}

?>

and I created PageCommentPlusInterface.php

<?php

class PageCommentPlusInterface extends PageCommentInterface{
      
      function PostCommentForm() {
         $form = parent::PostCommentForm();
         $fields = $form->Fields();
         $fields->insertAfter(
            new TextField("CommenterEmail", 'Email Address'), 'Name');
         $form->setFields($fields);
         return $form;
      }
}

?>

finally in my _config.php I added

Object::add_extension('PageComment', 'PageCommentPlus');

any ideas why it wouldn't show up in the comments form?

Avatar
MarcusDalgren

5 June 2010 at 4:41am Community Member, 288 Posts

I actually forgot the last part.

In your page class you have to override the ContentController method PageComments(). If you have a look at it you'll see that it's returning a PageCommentInterface and you of course want it to return your new class instead.

So in your Page_Controller you do

   function PageComments() {
      if($this->data() && $this->data()->ProvideComments) {
         return new PageCommentPlusInterface($this, 'PageComments', $this->data());
      } else {
         if(isset($_REQUEST['executeForm']) && $_REQUEST['executeForm'] == 'PageComments.PostCommentForm') {
            echo "Comments have been disabled for this page";
            die();
         }
      }
   }


And you should be getting your form with whatever extra fields you added to it.

Avatar
IOTI

5 June 2010 at 5:10am Community Member, 189 Posts

It works :D

Thank you so much.

Go to Top