Add floating mode support

This commit is contained in:
Cooper Dalrymple
2026-06-09 12:53:19 -05:00
parent 401676e7f3
commit 6a6e8f3960
15 changed files with 341 additions and 22 deletions
+158 -6
View File
@@ -12,12 +12,15 @@ 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 {
@@ -25,28 +28,177 @@ final class Widget {
return Settings::get_instance_url('assets/widget.js');
}
public static function enqueue_assets():void {
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());
wp_enqueue_script(
self::HANDLE,
self::get_script_url()
);
}
if ($floating && !wp_script_is(self::FLOATING_HANDLE)) {
wp_enqueue_script(
self::FLOATING_HANDLE,
self::get_floating_script_url(),
[
self::HANDLE
]
);
}
if (!wp_style_is(self::HANDLE)) {
wp_enqueue_style(self::HANDLE, Plugin::get_url('assets/widget.css'));
wp_enqueue_style(
self::HANDLE,
Plugin::get_url('assets/widget.css')
);
}
}
public static function render(string $id = 'cap'):void {
public static function render(array $args = []):void {
if (!Settings::is_connected()) return;
self::enqueue_assets();
$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($id),
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);
while (true) {
$found = false;
foreach ($queries as $query) {
if ($tags->next_tag($query)) {
$found = true;
break;
}
}
if (!$found) break;
if (!is_null($args['type_name']) && !empty($args['type_name']) && $tags->get_attribute('type') !== $args['type_name']) continue;
foreach ($attributes as $name => $value) {
$tags->set_attribute($name, $value);
}
}
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
]
);
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] : '';
}