214 lines
6.1 KiB
PHP
214 lines
6.1 KiB
PHP
<?php
|
|
/**
|
|
* @package ogre-captcha
|
|
* @author cleverogre
|
|
* @copyright 2026 CleverOgre
|
|
* @license GLP-3.0-or-later
|
|
* @version 1.2.0
|
|
* @since 1.0.0
|
|
*/
|
|
|
|
namespace Ogre\Captcha;
|
|
|
|
use Ogre\Captcha as Plugin;
|
|
use Ogre\Captcha\Settings;
|
|
use WP_HTML_Tag_Processor;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
final class Widget {
|
|
|
|
private const HANDLE = 'cap';
|
|
private const FLOATING_HANDLE = 'cap-floating';
|
|
private const DYNAMIC_FLOATING_HANDLE = 'cap-floating-dynamic';
|
|
private const TOKEN_NAME = 'cap-token';
|
|
|
|
private static function get_script_url():string {
|
|
if (!Settings::is_connected()) return '';
|
|
return Settings::get_instance_url('assets/widget.js');
|
|
}
|
|
|
|
private static function get_floating_script_url():string {
|
|
if (!Settings::is_connected()) return '';
|
|
return Settings::get_instance_url('assets/floating.js');
|
|
}
|
|
|
|
public static function enqueue_assets(bool $floating = false):void {
|
|
if (!Settings::is_connected()) return;
|
|
|
|
if (!wp_script_is(self::HANDLE)) {
|
|
wp_enqueue_script(
|
|
self::HANDLE,
|
|
self::get_script_url(),
|
|
args: [
|
|
'in_footer' => true
|
|
]
|
|
);
|
|
}
|
|
|
|
if ($floating && !wp_script_is(self::FLOATING_HANDLE)) {
|
|
wp_enqueue_script(
|
|
self::FLOATING_HANDLE,
|
|
self::get_floating_script_url(),
|
|
[
|
|
self::HANDLE
|
|
],
|
|
args: [
|
|
'in_footer' => true
|
|
]
|
|
);
|
|
}
|
|
|
|
if (!wp_style_is(self::HANDLE)) {
|
|
wp_enqueue_style(
|
|
self::HANDLE,
|
|
Plugin::get_url('assets/widget.css')
|
|
);
|
|
}
|
|
}
|
|
|
|
public static function render(array $args = []):void {
|
|
if (!Settings::is_connected()) return;
|
|
|
|
$args = wp_parse_args(
|
|
$args,
|
|
[
|
|
'id' => 'cap',
|
|
'floating' => Settings::is_widget_floating(),
|
|
]
|
|
);
|
|
|
|
self::enqueue_assets(!!$args['floating']);
|
|
printf(
|
|
'<cap-widget id="%s" required data-cap-api-endpoint="%s"></cap-widget>',
|
|
esc_attr(!empty($args['id']) ? strval($args['id']) : 'cap'),
|
|
esc_url(Settings::get_instance_url(Settings::get_site_key() . '/'))
|
|
);
|
|
}
|
|
|
|
public static function get_button_floating_attributes(array $args = []):array {
|
|
$args = wp_parse_args(
|
|
$args,
|
|
[
|
|
'id' => 'cap',
|
|
'position' => 'bottom',
|
|
'offset' => null,
|
|
]
|
|
);
|
|
|
|
$attributes = [
|
|
'data-cap-floating' => "#{$args['id']}",
|
|
'data-cap-floating-position' => $args['position'],
|
|
];
|
|
|
|
if (!is_null($args['offset'])) {
|
|
$attributes['data-cap-floating-offset'] = $args['offset'];
|
|
}
|
|
|
|
return $attributes;
|
|
}
|
|
|
|
private static function parse_button_floating_args(array $args):array {
|
|
return wp_parse_args(
|
|
$args,
|
|
[
|
|
'id' => 'cap',
|
|
'position' => 'bottom',
|
|
'offset' => null,
|
|
'tag_name' => null,
|
|
'class_name' => null,
|
|
'type_name' => 'submit',
|
|
]
|
|
);
|
|
}
|
|
|
|
private static function get_button_floating_selector(array $args):string {
|
|
$selector = '';
|
|
|
|
if (!is_null($args['tag_name']) && !empty($args['tag_name'])) {
|
|
$selector = $args['tag_name'];
|
|
} else {
|
|
$selector = ':where(input, button)';
|
|
}
|
|
|
|
if (!is_null($args['class_name']) && !empty($args['class_name'])) {
|
|
$selector = sprintf(
|
|
'.',
|
|
sanitize_html_class($args['class_name'])
|
|
);
|
|
}
|
|
|
|
if (!is_null($args['type_name']) && !empty($args['type_name'])) {
|
|
$selector .= sprintf(
|
|
'[type="%s"]',
|
|
esc_attr($args['type_name'])
|
|
);
|
|
}
|
|
|
|
return $selector;
|
|
}
|
|
|
|
public static function set_button_floating(string $html, array $args = []):string {
|
|
if (empty($html)) return $html;
|
|
|
|
$args = self::parse_button_floating_args($args);
|
|
$attributes = self::get_button_floating_attributes($args);
|
|
|
|
$queries = ['input', 'button'];
|
|
if (!is_null($args['tag_name']) || !is_null($args['class_name'])) {
|
|
$queries = [[
|
|
'tag_name' => $args['tag_name'],
|
|
'class_name' => $args['class_name'],
|
|
]];
|
|
}
|
|
|
|
$tags = new WP_HTML_Tag_Processor($html);
|
|
$tags->next_tag();
|
|
$tags->set_bookmark('top');
|
|
foreach ($queries as $query) {
|
|
$tags->seek('top');
|
|
$found = false;
|
|
while ($tags->next_tag($query)) {
|
|
if (!is_null($args['type_name']) && !empty($args['type_name']) && $tags->get_attribute('type') !== $args['type_name']) continue;
|
|
$found = true;
|
|
foreach ($attributes as $name => $value) {
|
|
$tags->set_attribute($name, $value);
|
|
}
|
|
}
|
|
if ($found) break;
|
|
}
|
|
return $tags->get_updated_html();
|
|
}
|
|
|
|
public static function add_dynamic_floating_attributes(array $args = []):void {
|
|
if (wp_script_is(self::DYNAMIC_FLOATING_HANDLE)) return;
|
|
|
|
$args = self::parse_button_floating_args($args);
|
|
|
|
wp_enqueue_script(
|
|
self::DYNAMIC_FLOATING_HANDLE,
|
|
Plugin::get_url('assets/floating.js'),
|
|
[
|
|
self::FLOATING_HANDLE
|
|
],
|
|
args: [
|
|
'in_footer' => true
|
|
]
|
|
);
|
|
|
|
wp_localize_script(
|
|
self::DYNAMIC_FLOATING_HANDLE,
|
|
'CAP_FLOATING_DYNAMIC',
|
|
[
|
|
'selector' => self::get_button_floating_selector($args),
|
|
'attributes' => self::get_button_floating_attributes($args),
|
|
]
|
|
);
|
|
}
|
|
|
|
public static function get_token():string {
|
|
return isset($_POST[self::TOKEN_NAME]) ? (string) $_POST[self::TOKEN_NAME] : '';
|
|
}
|
|
|
|
}
|