From a8ff85042ffbfe94b678fd818c02deb613bfd116 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 07 Aug 2026 20:42:54 +0000
Subject: [PATCH] =Continuing on with Integrations setup. Working on PostMark now

---
 inc/integrations/services/Cloudflare.php |  186 ++++++++++++++--------------------------------
 1 files changed, 56 insertions(+), 130 deletions(-)

diff --git a/inc/integrations/services/Cloudflare.php b/inc/integrations/services/Cloudflare.php
index 1425725..168590b 100644
--- a/inc/integrations/services/Cloudflare.php
+++ b/inc/integrations/services/Cloudflare.php
@@ -1,95 +1,72 @@
 <?php
 
 namespace JVBase\integrations\services;
+use JVBase\integrations\Admin;
+use JVBase\integrations\Instance;
 use JVBase\integrations\Integrations;
+
 if (!defined('ABSPATH')) {
 	exit;
 }
 
 class Cloudflare extends Integrations
 {
-	private string $site_key;
-	private string $secret_key;
+	use Admin, Instance;
 	private string $theme = 'light';
 	private string $size = 'normal';
 
-	protected static array $instances = [];
-	public static function getInstance(?int $userID = null):self
-	{
-		$key = is_null($userID) ? 'base' : $userID;
-		if (!array_key_exists($key, self::$instances)) {
-			self::$instances[$key] = new self($userID);
-		}
-		return self::$instances[$key];
-	}
-
 	protected function __construct()
 	{
 		$this->service_name = 'cloudflare';
-		$this->title = 'Cloudflare Turnstile';
+		$this->title = 'Cloudflare';
 		$this->icon = 'cloud';
-		$this->apiBase = 'https://challenges.cloudflare.com';
-		$this->apiEndpoints = ['turnstile/v0/siteverify'];
 
-		$this->fields = [
-			'site_key'	=> [
-				'label'	=> 'Site Key',
-				'type'	=> 'text',
-				'placeholder'	=> 'Enter Public key for Turnstile widget display.',
-				'hint'	=> 'Public key for Turnstile widget',
-				'required'	=> true
-			],
-			'secret_key'	=> [
-				'label'	=> 'Secret Key',
-				'type'	=> 'text',
-				'subtype'	=> 'password',
-				'placeholder'	=> 'Enter Cloudflare Turnstile Secret Key',
-				'required'	=> true,
-				'hint'	=> 'Secret key for server-side verification'
-			]
-		];
+		$this->defineFields();
+		$this->defineInstructions();
+		parent::__construct();
+	}
 
+	protected function defineFields():void
+	{
+		$site_key = $this->addField('site_key', 'Site Key', 'text', 'manage_options');
+			$site_key->setRequired();
+			$site_key->setHint('Public key for Turnstile Widget');
+		$secret_key = $this->addField('secret_key', 'Secret Key', 'text', 'manage_options');
+			$secret_key->setRequired();
+			$secret_key->setSubType('password');
+			$secret_key->setHint('Secret key for server-side verification of Turnstile Widget');
+	}
+
+	protected function defineInstructions():void
+	{
 		$this->instructions = [
 			'Go to <a href="https://dash.cloudflare.com/?to=/:account/turnstile" target="_blank">Cloudflare Dashboard</a>',
 			'Create a new Turnstile widget',
 			'Add your domain to the widget settings',
 			'Copy the Site Key and Secret Key'
 		];
-
-		$this->advanced = [];
-		parent::__construct();
 	}
-
 	protected function initialize(): void
 	{
-		$this->site_key = $this->credentials['site_key'] ?? '';
-		$this->secret_key = $this->credentials['secret_key'] ?? '';
-		$this->theme = $this->credentials['theme'] ?? 'light';
-		$this->size = $this->credentials['size'] ?? 'normal';
-
+		// TODO: Implement initialize() method.
 	}
 
-	/**
-	 * Check if scripts should be enqueued
-	 */
-	public function shouldEnqueueScripts(): bool
+	public function getServiceDescription():string
 	{
-		return $this->isSetUp() && !is_admin();
+		return "Add Turnstile captcha protection to your forms and login pages to prevent spam and bot submissions.";
 	}
 
-	/**
-	 * Test connection by attempting a verification with an invalid token
-	 */
 	public function performConnectionTest(): bool
 	{
-		if (empty($this->site_key) || empty($this->secret_key)) {
+		$credentials = $this->loadCredentials();
+		if (!array_key_exists('site_key', $credentials) || !array_key_exists('secret_key', $credentials)) {
 			return false;
 		}
 
 		// Test with a dummy token to verify API connectivity
 		$response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
 			'body' => [
-				'secret' => $this->secret_key,
+				'secret' => $credentials['secret_key'],
 				'response' => 'test-token-connection-check'
 			],
 			'timeout' => 10
@@ -97,46 +74,14 @@
 
 		// We expect this to fail with success:false, but not with a connection error
 		if (is_wp_error($response)) {
-			$this->logError('Connection test failed: ', [
-				'message'  => $response->get_error_message()
-			]);
 			return false;
 		}
 
 		$result = json_decode(wp_remote_retrieve_body($response), true);
-
 		// If we get a response with success field (even if false), connection works
 		return array_key_exists('success', $result);
 	}
 
-	protected function validateCredentials(array $credentials): bool
-	{
-		if (empty($credentials['site_key'])) {
-			$this->logError('Missing Site Key', [
-				'method'	=> 'validateCredentials'
-			]);
-			return false;
-		}
-
-		if (empty($credentials['secret_key'])) {
-			$this->logError('Missing Secret Key', [
-				'method'	=> 'validateCredentials'
-			]);
-			return false;
-		}
-
-		// Validate format
-		if (!preg_match('/^[0-9a-zA-Z._-]+$/', $credentials['site_key'])) {
-
-			$this->logError('Invalid Site Key', [
-				'method'	=> 'validateCredentials'
-			]);
-			return false;
-		}
-
-		return true;
-	}
-
 	/**
 	 * Enqueue Turnstile script
 	 */
@@ -156,10 +101,10 @@
 	/**
 	 * Render Turnstile widget
 	 * Can be called directly: jvbConnect('cloudflare')->renderTurnstile()
+	 * Or Cloudflare::getInstance()->renderTurnstile()
 	 */
 	public function renderTurnstile(array|string $options = []): void
 	{
-		$this->ensureInitialized();
 		if (!$this->isSetUp()) {
 			return;
 		}
@@ -175,29 +120,36 @@
 			'wrapper_style' => 'margin: 1em 0;'
 		];
 
+		$cred = $this->loadCredentials();
 		$options = wp_parse_args($options, $defaults);
 
-		echo '<div class="' . esc_attr($options['wrapper_class']) . '" style="' . esc_attr($options['wrapper_style']) . '">';
-		echo '<div class="cf-turnstile" ';
-		echo 'data-sitekey="' . esc_attr($this->site_key) . '" ';
-		echo 'data-theme="' . esc_attr($options['theme']) . '" ';
-		echo 'data-size="' . esc_attr($options['size']) . '">';
-		echo '</div>';
-		echo '</div>';
+		echo sprintf(
+			'<div class="%s" style="%s">
+				<div class="cf-turnstile" data-sitekey="%s" data-theme="%s" data-size="%s"></div>
+			</div>',
+			esc_attr($options['wrapper_class']),
+			esc_attr($options['wrapper_style']),
+			$cred['site_key'],
+			$options['theme'],
+			$options['size']
+		);
 	}
 
 	/**
-	 * Verify Turnstile response
-	 * Can be called directly: JVB()->connect('cloudflare')->verifyTurnstile($token)
+	 * Verify the Turnstile response
+	 * Can be called directly via JVB()->connect('cloudflare')->verifyTurnstile($token)
+	 *   or Cloudflare::getInstance()->verifyTurnstile($token)
+	 * @param string|null $token
+	 * @param string $remote_ip
+	 * @return bool
 	 */
-	public function verifyTurnstile(?string $token = null, string $remote_ip = ''): bool
+	public function verifyTurnstile(?string $token = null, string $remote_ip = ''):bool
 	{
-		$this->ensureInitialized();
 		if (!$this->isSetUp()) {
-			return false;
+			return true;
 		}
 
-		// If no token provided, try to get from POST
+		// If no token provided, try to get it from $_POST
 		if (!$token && isset($_POST['cf-turnstile-response'])) {
 			$token = sanitize_text_field($_POST['cf-turnstile-response']);
 		}
@@ -206,61 +158,35 @@
 			return false;
 		}
 
+		$cred = $this->loadCredentials();
 		$data = [
-			'secret' => $this->secret_key,
-			'response' => $token
+			'secret'	=> $cred['secret_key'],
+			'response'	=> $token,
 		];
 
 		if (empty($remote_ip) && isset($_SERVER['REMOTE_ADDR'])) {
-			$remote_ip = $_SERVER['REMOTE_ADDR'];
+			$remote_ip = sanitize_text_field($_SERVER['REMOTE_ADDR']);
 		}
 
 		if (!empty($remote_ip)) {
 			$data['remoteip'] = $remote_ip;
 		}
-
 		$response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
 			'body' => $data,
 			'timeout' => 10
 		]);
 
 		if (is_wp_error($response)) {
-			$this->logError('Turnstile verification failed: ' . $response->get_error_message());
+			$this->logError('verifyTurnstile', 'Turnstile verification failed: ' . $response->get_error_message());
 			return false;
 		}
 
 		$result = json_decode(wp_remote_retrieve_body($response), true);
 
-		if (!($result['success'] ?? false)) {
+		if (!$result['success']??false) {
 			$error_codes = implode(', ', $result['error-codes'] ?? ['Unknown error']);
-			$this->logError('Turnstile verification failed: ' . $error_codes);
+			$this->logError('verifyTurnstile', 'Turnstile verification failed: ' . $error_codes);
 		}
-
 		return $result['success'] ?? false;
 	}
-
-	/**
-	 * Get site key for frontend use
-	 */
-	public function getSiteKey(): string
-	{
-		return $this->site_key;
-	}
-
-	/**
-	 * Get service description
-	 */
-	public function getServiceDescription(): string
-	{
-		return "Add Turnstile captcha protection to your forms and login pages to prevent spam and bot submissions.";
-	}
-
-	/**
-	 * These methods are not used by Cloudflare but must be implemented
-	 */
-	protected function getRequestHeaders(): array
-	{
-		// Cloudflare Turnstile uses POST parameters, not headers
-		return [];
-	}
 }

--
Gitblit v1.10.0