Captcha Provider/Consumer API 1.0

Using the following API, plugins can be created to provide captchas as a service and other plugins can consume those services to render and verify one or multiple captchas whenever human verification is needed.

Plugin Hooks

The first thing a captcha consumer needs to know is if all registered captchas have been solved. It can verify this by triggering the following hook, passing true in:

if (elgg_trigger_plugin_hook('captchas:all_solved', 'before', array(), true)) {
    // all are solved, can bypass verification

Captcha plugins should register for this event. Handlers receiving false should do nothing. If a handler receives true, it should check if its captcha has been solved and change it to false if not.

When a form is submitted, captchas need to be notified to check the POSTed values and, again, let us know if all captchas are solved:

if (elgg_trigger_plugin_hook('captchas:all_solved', 'after', array(), true)) {
    // all are solved, can bypass verification

Captcha services should register for this hook, handle the POSTed values, and store successes in $_SESSION.

After all captchas are verified, the consumer should let captchas know to unset any SESSION vars they have stored:

elgg_trigger_plugin_hook('captchas:reset', 'after');


Form authors should render the "input/captchas" view if it exists (first checking with elgg_view_exists), and pass in alternative content as the option "alternative". If all captchas have been solved, this content will be rendered.

Since the "input/captchas" view isn't in core, all captcha providers should include it, but it should output nothing. Instead, each provider will extend the view to display its captcha (if not already verified).

  • I'm unclear as to the purpose of the before and after hooks

  • Both hooks return whether all the captchas are solved.

    before => so the captcha consumer (Elgg core) can decide if a captcha needs to be shown.

    after => alerts the captcha provider to process form input.

    Probably better is to have an interface for the captcha provider and the provider registers it with Elgg.

    interface CaptchaProviderInterface with methods: isSolved(), handleRequest(Request $req), forget()

  • ah I see, the naming of the hooks confused me (before all_solved?).  I understood the after hook being the check - that's how the current captcha plugins work in the action hooks.  I wasn't following what the before hook was.  So the before hook is an extra chance to decide to render the captcha or not.