Skip to content

Hooks & Events

Fabian Wennink edited this page Oct 31, 2023 · 3 revisions

Hooks

Hooks are events that will be executed at different stages in the server-side code. These hooks allow you to, as the name suggests, hook into different stages and alter their outcome or perform actions based on them. All hooks must be defined in their own classes, which must implement the required interfaces. The path to these classes must be configured in the config file.

init hook

This hook is called when a challenge is requested, and can play an important role in determining whether to serve a challenge to the visitor or complete the captcha process immediately.

To create a custom class for this hook, it must implement the \IconCaptcha\Challenge\Hooks\InitHookInterface interface. This interface ensures that your class contains the required method to handle this specific hook. Below is an example of how you can implement the hook in a custom class.

use IconCaptcha\Challenge\Hooks\InitHookInterface;
use IconCaptcha\Session\SessionInterface;

class CustomInitHook implements InitHookInterface
{
    public function shouldImmediatelyComplete(array $request, SessionInterface $session, array $options): bool
    {
        // Your logic to determine whether to autocomplete the captcha or not.
        // For example, you can check the visitor's IP to decide whether to autocomplete the captcha.

        // Return TRUE to autocomplete, FALSE to serve a challenge.
        return true;
    }
}

To configure the 'init' hook, you need to specify it in the hook section of the configuration file, as follows:

'init' => \Path\To\Your\CustomInitHook::class,

generation hook

This hook is called after a challenge image has been generated and allows you to make additional modifications to the generated image. This can include applying filters, adding random noise, or implementing other custom alterations to increase the challenge's difficulty.

To create a custom class for the 'generation' hook, it must implement the \IconCaptcha\Challenge\Hooks\GenerationHookInterface interface. This interface ensures that your class contains the required method to handle this specific hook. Below is an example of how you can implement the hook in a custom class.

use IconCaptcha\Challenge\Hooks\GenerationHookInterface;
use IconCaptcha\Session\SessionInterface;

class CustomGenerationHook implements GenerationHookInterface
{
    public function generate(array $request, SessionInterface $session, array $options, $image)
    {
        // Your custom image manipulation logic goes here.
        // For example, you can apply filters or add noise to the generated image.

        $modifiedImage = $this->applyCustomModifications($image);

        return $modifiedImage;
    }

    private function applyCustomModifications($image)
    {
        // Your custom image manipulation logic goes here.

        // Return the modified image.
        return $image;
    }
}

To configure the 'generation' hook, you need to specify it in the hook section of the configuration file, as follows:

'generation' => \Path\To\Your\CustomGenerationHook::class,

selection hook

The 'selection' hook is allows you to perform actions based on a visitor's interaction with the captcha. This hook contains two functions: one for handling correct selections and another for incorrect selections. You can use these functions to perform specific actions when a visitor either correctly selects the icon (resulting in a successful completion of the captcha) or makes an incorrect selection.

To create a custom class for the 'selection' hook, you must implement the \IconCaptcha\Challenge\Hooks\SelectionHookInterface interface. This interface includes two functions as described above. Each function allows you to define custom logic for handling the respective actions.

use IconCaptcha\Challenge\Hooks\SelectionHookInterface;
use IconCaptcha\Session\SessionInterface;

class CustomSelectionHook implements SelectionHookInterface
{
    public function correct(array $request, SessionInterface $session, array $options): void
    {
        // Your custom logic for correct selections goes here.
    }

    public function incorrect(array $request, SessionInterface $session, array $options): void
    {
        // Your custom logic for incorrect selections goes here.
    }
}

To configure the 'selection' hook, you need to specify it in the hook section of the configuration file, as follows:

'selection' => \Path\To\Your\CustomSelectionHook::class,

Events

Events will be activated at different moments in the client-side code. You can use your own custom script to connect with these events and run your own code when needed. It's important to remember not to solely depend on these events because they can be manually triggered by potential attackers. Always make sure to perform server-side validation for security.

Event Description
init This event fires when the widget has been fully built, and the image details have been successfully requested from the server.
selected This event fires when the user selects an icon, regardless of whether the selected icon is correct or not.
refreshed This event fires when the user selects an incorrect icon, and the widget completes the process of refreshing its challenge.
timeout This event fires when the user makes too many incorrect selections, and the widget enters a timeout mode for a specific period.
invalidated This event fires when the widget invalidates itself after a defined period of user inactivity.
reset This event fires when a widget is manually reset using the reset function.
success This event fires when the user selects the correct icon.
error This event fires when the user selects an incorrect icon.

Listen for events

To catch these events, you can bind listeners to the initialized widget instance. If you want to listen to these events no matter which widget is causing them, you can opt for IconCaptcha.bind(...) instead. The widget identifier of the captcha which triggered the event can be accessed via e.detail.captchaId.

document.addEventListener('DOMContentLoaded', function () {
   
    // Example of widget specific event listeners.
    IconCaptcha.init('.iconcaptcha-widget', {
        ...
    })
    .bind('init', function(e) {
        console.log(e.detail.captchaId);
    }).bind('selected', function(e) {
        //
    }).bind('refreshed', function(e) {
        //
    }).bind('invalidated', function(e) {
        //
    }).bind('reset', function(e) {
        //
    }).bind('success', function(e) {
        //
    }).bind('error', function(e) {
        //
    });

    // Example of global event listeners.
    IconCaptcha.bind('init', function(e) {
        console.log(e.detail.captchaId);
    }).bind('selected', function(e) {
        //
    })
});