MODx Revo FormIt + no captcha reCAPTCHA

Hallo, die Welt. Так уж сложилось, что это будет первая информативная страница на данном ресурсе, и речь в ней пойдёт об использовании нового reCAPTCHA API в системе управления контентом MODx.
Йа не робот!
С недавних пор Google ввел в строй новую версию reCAPTCHA, благодаря которой в большинстве случаев пользователю не потребуется вводить нечитаемые слова для подтверждения своего биологического происхождения: достаточно лишь клацнуть мышкой на кнопку. К сожалению, на данныый момент компонент MODx для обработки форм — FormIt — ещё не умеет работать с reCAPTCHA2, что, впрочем, не мешает с помощью небольшого напильника научить его работать…

FormIt предоставляет свойства preHooks и hooks для выполнения скриптов (сниппетов) при отображении формы и после прохождения валидации введённых пользователем данных соответствием, чем и можно воспользоваться.

Итак, прежде всего, необходимо создать сниппет reCAPTCHA2_prehook, который выполнит инициализацию и отображение капчи. Необходимые ключи берутся из системных переменных — точно таких же, что использовались во встроенном в FormIt recaptcha. Сами ключи, кстати, работают с обоими версиями капчи, то есть пересоздавать их не нужно.

<?php
$recaptcha_public_key = $hook->formit->modx->getOption('formit.recaptcha_public_key');

if (empty($recaptcha_public_key)) return false;

$html = <<<EOF
    <div class="g-recaptcha" data-sitekey="$recaptcha_public_key"></div>
EOF;
$hook->modx->regClientStartupScript('//www.google.com/recaptcha/api.js?hl=ru');
$hook->modx->setPlaceholder('formit.recaptcha_html', $html);

return true;

Далее — сниппет reCAPTCHA2, отвечающий за обработку капчи:

<?php
$recaptcha_private_key = $hook->formit->modx->getOption('formit.recaptcha_private_key');
if (empty($recaptcha_private_key)) {
    return false; 
}

if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response'])){
    
    // workaround for recaptcha
    $remoteip = $_SERVER['REMOTE_ADDR'];
    if ($remoteip == '127.0.0.1') { // in some cases recaptcha doesn't work with 127.0.0.1, when domain name != localhost
        $remoteip = file_get_contents('http://phihag.de/ip/');
    }
    
    $requestParams = array(
        'secret' => $recaptcha_private_key,
        'response' => $_POST['g-recaptcha-response'],
        'remoteip' => $remoteip,
    );
    
    $googleResponce = file_get_contents(
        'https://www.google.com/recaptcha/api/siteverify', 
        false, 
        stream_context_create(array(
            'http' => array(
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                'method'  => 'POST',
                'content' => http_build_query($requestParams),
            )
        ))
    );
    

    if (!$googleResponce) {
        return false;
    }
    
    $res = json_decode($googleResponce, true);
    if($res && isset($res['success']) && $res['success'] == true){
        return true;    
    }
}

$hook->addError('recaptcha', 'Докажите, что Вы не робот.');
return false;

И, наконец, пример использования этих сниппетов вместе с FormIt:

[[!FormIt?
   &hooks=`spam,reCAPTCHA2,...` 
   &preHooks=`reCAPTCHA2_prehook`
.....

Как видно, миграция на новую версию reCAPTCHA происходит бесшовно и с минимальными изменениями в самих документах.

p.s.
Обращаю внимание на то, что регистр символов в названии сниппетов имеет значение. Изначально я назвал сниппет recaptcha2 и потом долго пытался понять, почему вместо новой капчи отображается старая — пока не посмотрел в код FormIt. А там всё просто и тупо:
public function hasHook($hook) { return strpos($this->config[‘hooks’],$hook) !== false; }
т.е. на recaptcha2 всегда отзывался встроенный recaptcha из-за strpos…