Call captcha plugin programatically in custom component

For Joomla! 4.x Coding related discussions, you could also use: http://groups.google.com/group/joomla-dev-general

Moderators: ooffick, General Support Moderators

Forum rules
Forum Rules
Absolute Beginner's Guide to Joomla! <-- please read before posting, this means YOU.
Forum Post Assistant - If you are serious about wanting help, you will use this tool to help you post.
Windows Defender SmartScreen Issues <-- please read this if using Windows 10.
Post Reply
Dekari
Joomla! Apprentice
Joomla! Apprentice
Posts: 15
Joined: Fri Feb 01, 2013 9:50 am

Call captcha plugin programatically in custom component

Post by Dekari » Mon Jul 17, 2023 5:27 pm

Hello all, until Joomla 3 I was able to call re-captcha plugin with following code:

Code: Select all

                    J
JPluginHelper::importPlugin('captcha');
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('onInit');
Anyone can help me understand what's the equivalent for joomla 4?

naaz simra
Joomla! Apprentice
Joomla! Apprentice
Posts: 7
Joined: Fri Nov 23, 2018 6:17 am

Re: Call captcha plugin programatically in custom component

Post by naaz simra » Mon Jul 17, 2023 11:43 pm

In Joomla 4, the way to trigger plugin events has changed. Instead of using the JDispatcher class, you can now use the new EventDispatcher class.
Try this.

Code: Select all

use Joomla\CMS\Plugin\EventDispatcher;

$dispatcher = EventDispatcher::getInstance();
$dispatcher->trigger('onInit', ['captcha']);
I hope it help you.

SharkyKZ
Joomla! Hero
Joomla! Hero
Posts: 2941
Joined: Fri Jul 05, 2013 10:35 am
Location: Parts Unknown

Re: Call captcha plugin programatically in custom component

Post by SharkyKZ » Tue Jul 18, 2023 5:25 am

Don't use event dispatcher. That's wrong even in J3. Use Joomla\CMS\Captcha\Captcha class.

Code: Select all

use Joomla\CMS\Captcha\Captcha;

$captcha = Captcha::getInstance($type);

// To display captcha.
$captcha->display($name, $id);

// To validate answer.
$captcha->checkAnswer($answer);

Abatap
Joomla! Apprentice
Joomla! Apprentice
Posts: 12
Joined: Thu Aug 31, 2017 1:49 pm

Re: Call captcha plugin programatically in custom component

Post by Abatap » Tue Feb 13, 2024 7:04 am

SharkyKZ wrote:
Tue Jul 18, 2023 5:25 am
Don't use event dispatcher. That's wrong even in J3. Use Joomla\CMS\Captcha\Captcha class.

Code: Select all

use Joomla\CMS\Captcha\Captcha;

$captcha = Captcha::getInstance($type);

// To display captcha.
$captcha->display($name, $id);

// To validate answer.
$captcha->checkAnswer($answer);
Hello. I have recently tried to refactor some of my old Joomla! 3-era captcha code to the new ways of J! 4 and 5. Since the stock Joomla! reCAPTCHA plugins have all been deprecated in J!5, I've decided to switch to what appears to be your Google reCAPTCHA v3 plugin from here: https://github.com/SharkyKZ/joomla-recaptcha-v3-plugin

The problem is that I'm completely lost when it comes to retrieving the answer code as hinted by your sample code from above.

Here is my view code for displaying captcha in form:

Code: Select all

use Joomla\CMS\Captcha\Captcha;
use Joomla\CMS\Factory;

$joomlaApplication = Factory::getApplication();

if (Factory::getUser()->guest && (Factory::getConfig()->get('captcha') === 'recaptcha_v3')) {
    $joomlaCaptcha = Captcha::getInstance('recaptcha_v3');

    try {
        echo $joomlaCaptcha->display('custom-form-captcha', 'custom-form-captcha-123');
    } catch (Exception $joomlaCaptchaException) {
        // In case the captcha initialization process fails
        $joomlaApplication->enqueueMessage(
            $joomlaCaptchaException->getMessage(),
            $joomlaApplication::MSG_ERROR,
        );
    }
}
And here is my controller code:

Code: Select all

use Joomla\CMS\Captcha\Captcha;
use Joomla\CMS\Factory;

$joomlaApplication = Factory::getApplication();

if (Factory::getUser()->guest && (Factory::getConfig()->get('captcha') === 'recaptcha_v3')) {
    $joomlaCaptcha = Captcha::getInstance('recaptcha_v3');
    $joomlaCaptchaResult = false;
    
    try {
        $joomlaCaptchaResult = $joomlaCaptcha->checkAnswer(
            $joomlaApplication->input->post->get(
                'custom-form-captcha',
                'missing-input-response', // Default reCAPTCHA error code
		'string',
            ),
        );
    } catch (Exception $joomlaCaptchaException) {
        // Display any captcha issues to the user
        $joomlaApplication->enqueueMessage(
            $joomlaCaptchaException->getMessage(),
            $joomlaApplication::MSG_WARNING,
        );
    }
    
    if ($joomlaCaptchaResult === false) {
        // cancel form submission...
    }
}
Captcha appears to initialize just fine and all relevant hidden inputs are present in the form but the $_POST['custom-form-captcha'] key's value is always empty, so refactoring the controller code like this:

Code: Select all

$joomlaCaptcha->checkAnswer($_POST['custom-form-captcha']);
or like this

Code: Select all

$joomlaCaptcha->checkAnswer('custom-form-captcha');
or even like this

Code: Select all

$joomlaCaptcha->checkAnswer(''); // This is supposed to activate a fallback to the older 'g-recaptcha-response' input that reCAPTCHA v3 still supports
yields no difference whatsoever.

In all cases the plugin responds with an exception passing a language constant of PLG_CAPTCHA_RECAPTCHA_V3_ERROR_EMPTY_RESPONSE which is supposed to indicate an empty response value.

P.S. Your plugin works as intended in all other XML-based forms (Joomla!'s user password recovery form, Contact forms, etc.), so it is certainly not a plugin configuration issue.
Last edited by Abatap on Tue Feb 13, 2024 8:54 am, edited 1 time in total.

SharkyKZ
Joomla! Hero
Joomla! Hero
Posts: 2941
Joined: Fri Jul 05, 2013 10:35 am
Location: Parts Unknown

Re: Call captcha plugin programatically in custom component

Post by SharkyKZ » Tue Feb 13, 2024 8:00 am

I just tried your code and it worked. Your initial controller code is correct, you need to read the answer from input. If it's empty, check if media/plg_captcha_recaptcha_v3/js/main.js script is loaded and check for JS errors in browser. I do find it strange that you're getting untranslated language constant. Plugin's language file is loaded right before constant is used so you should definitely see a translated string.

Unrelated to your issue, but you should explicitly check that checkAnswer() returns true. In case of failure it may throw an exception but it may also return false.

Abatap
Joomla! Apprentice
Joomla! Apprentice
Posts: 12
Joined: Thu Aug 31, 2017 1:49 pm

Re: Call captcha plugin programatically in custom component

Post by Abatap » Tue Feb 13, 2024 9:00 am

Oh, nevermind about the language constant. Of course, the plugin correctly returns the corresponding language string instead of the constant identifier itself. It was just me presenting it in a form of an underlying constant for a simple direct reference to a code point the said constant is used at.

I have investigated the plugin's JS file you were referring to and while it appears to be included correctly at all times, the contents of it gave me a clue about one possible issue I'll have to turn my attention to: There is a custom event listener that cancels out the click event of the form's submit button just to do some additional form data validation and pre-processing and then it submits the button's form itself via something like a document.forms["my-cool-form"].submit(); call. I guess that's the key to why no hidden captcha field output by your plugin gets populated with Google's response values.

And thank you about that tip on the proper use of checkAnswer() method return value. I've updated my sample code from the post above accordingly.

neo314
Joomla! Apprentice
Joomla! Apprentice
Posts: 36
Joined: Sat Mar 13, 2010 4:22 am

Re: Call captcha plugin programatically in custom component

Post by neo314 » Sat Mar 23, 2024 10:16 am

I just asked this question anew in the J5 coding forum, but it seems this may be the thread to ask the question.

I seem to have the plugin working in basically the same way described here but using invisible reCaptcha, but when the reCaptcha challenge does appear, if one clicks off of the challenge form and on the overlay, the challenge disappears. The challenge does not reappear. The form submits and fails validation server-side.

Any fix for this problem?


Post Reply

Return to “Joomla! 4.x Coding”