From f94860aacd6200fb24c9e7431eb379a368cb392d Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 10 Jul 2026 00:35:44 +0000
Subject: [PATCH] =Refactored CredentialsManager.php to utilize a CustomTable instance instead

---
 inc/integrations/CredentialsManager.php |  125 +++++++++++++++++------------------------
 1 files changed, 53 insertions(+), 72 deletions(-)

diff --git a/inc/integrations/CredentialsManager.php b/inc/integrations/CredentialsManager.php
index 66a982e..a3967a2 100644
--- a/inc/integrations/CredentialsManager.php
+++ b/inc/integrations/CredentialsManager.php
@@ -1,6 +1,8 @@
 <?php
 namespace JVBase\integrations;
 
+use JVBase\managers\CustomTable;
+
 if (!defined('ABSPATH')) {
 	exit;
 }
@@ -9,12 +11,39 @@
 {
 	private static ?CredentialsManager $instance = null;
 	private string $encryption_key;
-	private string $option_prefix = 'jvb_integration_';
-	private string $user_meta_prefix = 'jvb_integration_';
+	private CustomTable $table;
 
 	private function __construct()
 	{
-		$this->encryption_key = $this->getEncryptionKey();
+		$this->getEncryptionKey();
+		$this->defineTable();
+	}
+
+	protected function defineTable():void
+	{
+		$table = CustomTable::for('integrations');
+		$table->setColumns([
+			'id'			=> 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+			'user_id'		=> $table->getUserIDType().' NOT NULL',
+			'integration'	=> "ENUM('bluesky','cloudflare','facebook','google-maps','gmb','helcim','instagram','postmark','square','umami') NOT NULL",
+			'credentials'	=> 'varchar(255) DEFAULT NULL',
+			'created_at'	=> 'datetime DEFAULT CURRENT_TIMESTAMP',
+			'updated_at'	=> 'datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'
+		]);
+
+		$table->setKeys([
+			['key' => 'PRIMARY', 'value' => '(`id`)'],
+			['key' => 'UNIQUE', 'value' => '`user_integration` (`user_id`, `integration`)'],
+			'`user` (`user_id`)',
+		]);
+
+		$base = BASE;
+		$table->setConstraints([
+			"CONSTRAINT `{$base}integrations_user` FOREIGN KEY (`user_id`)
+			REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE"
+		]);
+		$table->defineTable();
+		$this->table = $table;
 	}
 
 	public static function getInstance(): CredentialsManager
@@ -30,18 +59,11 @@
 	 */
 	public function storeCredentials(string $service, array $credentials, ?int $userID = null): bool
 	{
-		$credentials['updated_at'] = time();
-		if ($userID) {
-			return $this->storeUserCredentials($service, $credentials, $userID);
-		}
-		$encrypted_data = $this->encrypt(json_encode($credentials));
-		return update_option($this->option_prefix . $service, $encrypted_data);
-	}
-
-	public function storeUserCredentials(string $service, array $credentials, int $userID): bool
-	{
-		$encrypted_data = $this->encrypt(json_encode($credentials));
-		return update_user_meta($userID, $this->user_meta_prefix . $service, $encrypted_data);
+		$find = $this->findBy($service, $userID);
+		$update = [
+			'credentials'	=> $this->encrypt(json_encode($credentials))
+		];
+		return (bool)$this->table->findOrCreate($find, $update);
 	}
 
 	/**
@@ -49,30 +71,13 @@
 	 */
 	public function getCredentials(string $service, ?int $userID = null): array
 	{
-		if ($userID) {
-			return $this->getUserCredentials($service, $userID);
-		}
-
-		$encrypted_data = get_option($this->option_prefix . $service, '');
-
-		if (empty($encrypted_data)) {
+		$find = $this->findBy($service, $userID);
+		$credentials = $this->table->pluck('credentials', $find);
+		if (empty($credentials)) {
 			return [];
 		}
-
-		$decrypted_data = $this->decrypt($encrypted_data);
-		return $decrypted_data ? json_decode($decrypted_data, true) : [];
-	}
-
-	public function getUserCredentials(string $service, int $userID): array
-	{
-		$encrypted_data = get_user_meta($userID, $this->user_meta_prefix . $service, true);
-
-		if (empty($encrypted_data)) {
-			return [];
-		}
-
-		$decrypted_data = $this->decrypt($encrypted_data);
-		return $decrypted_data ? json_decode($decrypted_data, true) : [];
+		$decrypted_data = $this->decrypt($credentials[0]);
+		return empty($decrypted_data) ? [] : json_decode($decrypted_data, true);
 	}
 
 	/**
@@ -80,16 +85,16 @@
 	 */
 	public function deleteCredentials(string $service, ?int $userID = null): bool
 	{
-
-		if ($userID) {
-			return $this->deleteUserCredentials($service, $userID);
-		}
-		return delete_option($this->option_prefix . $service);
+		$find = $this->findBy($service, $userID);
+		return $this->table->delete($find);
 	}
 
-	public function deleteUserCredentials(string $service, int $userID): bool
+	protected function findBy(string $service, ?int $userID = null):array
 	{
-		return delete_user_meta($userID, $this->user_meta_prefix . $service);
+		return [
+			'user_id'	=> is_null($userID) ? 0 : $userID,
+			'integration'=> $service
+		];
 	}
 
 	/**
@@ -97,31 +102,15 @@
 	 */
 	public function hasCredentials(string $service, ?int $userID = null): bool
 	{
-		if ($userID) {
-			return $this->hasUserCredentials($service, $userID);
-		}
-		return !empty(get_option($this->option_prefix . $service, ''));
-	}
-
-	public function hasUserCredentials(string $service, int $userID): bool
-	{
-		$encrypted_data = get_user_meta($userID, $this->user_meta_prefix . $service, true);
-		return !empty($encrypted_data);
+		return !empty($this->getCredentials($service, $userID));
 	}
 
 	/**
 	 * Get or create encryption key
 	 */
-	private function getEncryptionKey(): string
+	private function getEncryptionKey():void
 	{
-		$key = get_option('jvb_encryption_key');
-
-		if (!$key) {
-			$key = base64_encode(random_bytes(32));
-			update_option('jvb_encryption_key', $key);
-		}
-
-		return base64_decode($key);
+		$this->encryption_key = JVB_KEY;
 	}
 
 	/**
@@ -151,14 +140,6 @@
 	 */
 	public function getUsersWithCredentials(string $service): array
 	{
-		global $wpdb;
-
-		$meta_key = $this->user_meta_prefix . $service;
-		$results = $wpdb->get_results($wpdb->prepare(
-			"SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = %s",
-			$meta_key
-		));
-
-		return wp_list_pluck($results, 'user_id');
+		return $this->table->pluck('user_id', ['integration' => $service]);
 	}
 }

--
Gitblit v1.10.0