Spam is a big problem on the web. If you leave your contact form unsecured on your website it won't be long before you have many, many spam responses. Fortunately, Concrete CMS contains several systems to combat this plague. All user-facing forms, including those used by the Form block, the Survey block, and the registration system route their input through our Anti-Spam layer. Additionally, Captcha is an option on all these forms.
Enabling Anti-Spam and Captcha
Want more information on how to enable this functionality on your site? Check out the Captcha and Spam Control sections of the Editors Documentation.
Adding Captcha Support To Your Forms
To add a captcha to your own own custom form, just add this code to the bottom of the view layer:
<form method="post" action="<?=$view->action('submit_form')?>">
<?php
$captcha = Core::make('captcha');
?>
<div class="form-group">
<label class="control-label"><?=$captcha->label()?></label>
<div><?php $captcha->display(); ?></div>
<div><?php $captcha->showInput(); ?></div>
</div>
</form>
That will display the output of the selected Captcha library.
Next, you'll need to check the Captcha when your form is submitted.
public function submit_form()
{
$captcha = \Core::make("captcha");
if ($captcha->check()) {
// Proceed with submission
} else {
// Show the captcha error to the end user...
}
}
That's it! Your form is now protected by a captcha.
Adding Anti-Spam Support to Your Forms
It's similarly simple to add anti-spam support to your forms. Let's say the form above has the following input fields it's tracking:
- first_name
- last_name
- feedback
We want to check these fields for spam. We'll take the method above and add the following code:
$antispam = \Core::make('helper/validation/antispam');
$message = "First Name: {$this->request->request->get('first_name')}\n";
$message .= "Last Name: {$this->request->request->get('last_name')}\n";
$message .= "Feedback: {$this->request->request->get('feedback')}\n";
$u = new \User();
$additionalArgs = array('user' => $u);
if (!$antispam->check($message, 'feedback_form', $additionalArgs)) {
return false;
}
This is pretty self-explanatory: first, we load up the anti-spam service. Next, we craft a single string that contains all the elements we want to check for spam. Then we retrieve the current user's User object, and pass it in as an additional argument. Finally, we run the check()
method on our anti-spam library. If it returns false, that means the message is thought to be spam, and we return silently.
Building Your Own Captcha Service
The Anti-Spam and Captcha services are meant to be extendable; by default, Concrete doesn't come with any Anti-Spam services installed, and only the fairly basic SecurImage Captcha as the default Captcha library. It is easy to write your own Captcha and Anti-Spam libraries as part of a Package.
First, install your Captcha
In your package's install()
method, you'll want to install your Captcha library. Let's say you've written a package named "Awesome Captcha" with the package handle "awesome_captcha" and you want to actually name the Captcha object itself "Awesome Captcha"
public function install()
{
$pkg = parent::install();
\Concrete\Core\Captcha\Library::add('awesome_captcha', t('Awesome Captcha'), $pkg);
}
That's it! Concrete now believes there to be a valid Captcha library with the handle "awesome_captcha".
Next, a Captcha Class
Now, you'll need to create a capcha class within your package. If you add this to your package controller:
$pkgAutoloaderMapCoreExtensions = true;
your file will be found here:
packages/awesome_captcha/src/Concrete/Captcha/AwesomeCaptchaController.php
and its namespace will be
namespace Concrete\Package\AwesomeCaptcha\Captcha;
If you don't add $pkgAutoloaderMapCoreExtensions = true
to your class, the file will be found here:
packages/awesome_captcha/src/Captcha/AwesomeCaptchaController.php
and its namespace will be
namespace Concrete\Package\AwesomeCaptcha\Src\Captcha;
Once you've added your class in the right spot, you'll need to implement the required methods:
showInput()
- shows an input on the page for this Captcha librarydisplay()
- Displays the graphical portion of the Captchalabel()
- Displays the label for the formcheck()
- Runs server-side to validate the submitted Captcha
Optional: Custom Options Form
Does your Captcha have custom options? For example, to use Google's ReCaptcha captcha service, you'll need to provide an API key. Fortunately the Concrete Captcha system makes it easy to ask for custom options in the Dashboard, and save them against the captcha library.
First, simply create a form at packages/awesome_captcha/elements/system/captcha/awesome_captcha/form.php. This is simple HTML/PHP form, containing form fields for whatever custom elements you need to track against your captcha.
Then, simply define a saveOptions($data)
method in your controller above, which is responsible for saving the data submitted in the form. Typically, we would use the Configuration system to store this data.
Example
A great, full-featured example of a working Captcha in a package is the ExchangeCore ReCaptcha Add-On
Building Your Own Anti-Spam Provider
First, install your Provider
In your package's install()
method, you'll want to install your Anti-Spam library. Let's say you've written a package for the Wordpress "Akismet" Anti-Spam service with the package handle "akismet" and you want to actually name the Captcha object itself "Akismet"
public function install()
{
$pkg = parent::install();
\Concrete\Core\Antispam\Library::add('akismet', t('Akismet'), $pkg);
}
That's it!
Next, an Anti-Spam Class
Now, much like the Captcha class, you'll need to create an Anti-Spam class within your package. If you add this to your package controller:
$pkgAutoloaderMapCoreExtensions = true;
your file will be found here:
packages/akismet/src/Concrete/Antispam/AkismetController.php
and its namespace will be
namespace Concrete\Package\Akismet\Captcha;
If you don't add $pkgAutoloaderMapCoreExtensions = true
to your class, the file will be found here:
packages/awesome_captcha/src/Antispam/AkismetController.php
and its namespace will be
namespace Concrete\Package\AwesomeCaptcha\Src\Antispam;
Once you've added your class in the right spot, you'll need to implement the required methods:
check($data)
- Checks the submitted data for spam. Returns true if the data is free of spam.report($data)
- Reports spam to the Spam service
Optional: Custom Options Form
Does your Captcha have custom options? For example, to use Google's ReCaptcha captcha service, you'll need to provide an API key. Fortunately the Concrete Captcha system makes it easy to ask for custom options in the Dashboard, and save them against the captcha library.
First, simply create a form at packages/akismet/elements/system/antispam/akismet/form.php. This is simple HTML/PHP form, containing form fields for whatever custom elements you need to track against your captcha.
Then, simply define a saveOptions($data)
method in your controller above, which is responsible for saving the data submitted in the form. Typically, we would use the Configuration system to store this data.