Hi all,
Recently I did say that I’d look at how Captcha could be added into UserComments. Well, I sat down over a coffee today and decided to draw up a tutorial on how to do this - mainly because there are various versions of UserComments available and so hopefully this tutorial will help you modify whichever version you’re currently using.
First things first, I have attached a copy of the basic UserComments snippet with my modifications, and all my changes are commented with
//-- CAPTCHA and
//-- END CAPTCHA.
Either if you’re using my attached version or modifying your own versions, just add &useCaptcha=`1` to your snippet call to enable Captcha.
So, here’s what to do ...
Step 1: Adding the snippet parameter and the HTML output for the Captcha image
The following code, which is added immediately after the snippet comments (for ease of access) sets a snippet parameter that can be used to toggle the Captcha image on and off. Secondly, a variable is created to hold the HTML output for the Captcha image and necessary form field:
//set snippet parameter
$useCaptcha = (isset ($useCaptcha)) ? true : false;
//set 'captcha' placeholder
$phCaptcha = 'Form Code:<br /><input type="text" name="formcode" class="inputBox" style="width:150px" size="20">
<a href="[+action+]"><img align="top" src="manager/includes/veriword.php?rand=' . rand() . '" width="148" height="60" alt="If you have trouble reading the code, click on the code itself to generate a new random code." style="border: 1px solid #003399"></a>';
//replace the 'action' placeholder with the page url
$phCaptcha = str_replace("[+action+]", $modx->makeUrl($modx->getDocumentIdentifier('id'), '', ''), $phCaptcha);
(Some of the code was taken directly from the WebLogin snippet in case anybody recognises it

Style as you wish)
Step 2: Preventing the comment from being submitted if the Captcha code is incorrect
To prevent the posting of comments if the Captcha code is incorrect, it is necessary to wrap a quick check around the existing code that detects if the comments form has been submitted and that the Captcha code is correctly entered:
if ((!$useCaptcha || isset ($_POST['formcode']) && isset ($_SESSION['veriword']) && $_SESSION['veriword'] == $_POST['formcode'])) {
// get postback status
$isPostBack = isset ($_POST['UserCommentForm' . $tagid]) ? true : false;
} else {
$isPostBack = false;
}
Step 3: Modifying the form template
Here, I have modified the default template in the snippet but the same process applies to any custom templates you may be using. The modification adds in placeholders where the form values can be inserted back into the template should the Captcha code not validate and the page has to be reloaded.
$formTpl = '
<form method="post" action="[~[*id*]~]">
<input name="[+tagname+]" type="hidden" value="on" />
Subject:<br /><input name="subject" type="text" size="40" value="[+subject+]" /><br />
Comment:<br /><textarea name="comment" cols="50" rows="8">[+comment+]</textarea><br />
[+captcha+]
<input name="send" type="submit" value="Submit" />
</form>
';
Notice the addition of the [+subject+] and [+comment+] compared to the standard default template. The placeholders you add should correspond to the names you have used for your form fields (including any additional fields you have added) Also, notice the addition of the [+captcha+] tag that will render the captcha image and form field.
Step 4: Substituting the Captcha HTML and any form values into the form template
To complete the process, the only remaining step is to substitute all the values into the form template. The following code does just that:
if ($useCaptcha == true)
$formTpl = str_replace("[+captcha+]", $phCaptcha, $formTpl);
if (!$isPostBack) {
foreach ($_POST as $n => $v) {
$formTpl = str_replace("[+$n+]", $v, $formTpl);
}
}
The MODx document parser will remove any empty placeholder tags that haven’t been replaced by this code when the page is rendered.
And that’s it, you now have a Captcha-enabled UserComments snippet. Well, I hope that helps everybody out anyway. Comments welcome,
Garry