From 3b83905603d44b1a08f8b2b36a605808ce686ad6 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 02 Jun 2026 00:46:48 +0000
Subject: [PATCH] =double checking schema outputs for legacytattooremoval

---
 inc/managers/ApprovalManager.php |  144 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 135 insertions(+), 9 deletions(-)

diff --git a/inc/managers/ApprovalManager.php b/inc/managers/ApprovalManager.php
index f381d58..42200e0 100644
--- a/inc/managers/ApprovalManager.php
+++ b/inc/managers/ApprovalManager.php
@@ -3,8 +3,8 @@
 
 
 use DateTime;
+use JVBase\base\Site;
 use JVBase\registrar\Registrar;
-use JVBase\managers\CustomTable;
 
 if (!defined('ABSPATH')) {
 	exit;
@@ -14,12 +14,20 @@
 	protected array $tables =[];
 	protected int $expiresAt = 21; //days for request
 	protected int $requiredVotes = 3; //Number of votes before a term is approved
+	protected bool $hasApproval = false;
 	public function __construct()
 	{
 		$this->defineTables();
 		if (empty($this->tables)) {
 			return;
 		}
+
+		$this->hasApproval = Site::membership() && Site::membership()->has('member_verified');
+		if ($this->hasApproval) {
+			add_action('user_register', [$this, 'handleRegistration'], 10, 2);
+		}
+
+		add_action('jvb_cleanup_expired_approvals', [$this, 'cleanupExpired']);
 	}
 
 	protected function defineTables():void
@@ -27,6 +35,7 @@
 		$types = Registrar::getFeatured('approve_new');
 		foreach ($types as $type) {
 			$requests = CustomTable::for("approval_{$type}_requests");
+			$registrar = Registrar::getInstance($type);
 
 			$requests->setColumns([
 				'id'				=> 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
@@ -54,9 +63,9 @@
 			]);
 			$base = BASE;
 			$requests->setConstraints([
-				"CONSTRAINTS `{$base}{$type}_approval_requester` FOREIGN KEY (`user_id`)
+				"CONSTRAINT `{$base}{$type}_approval_requester` FOREIGN KEY (`user_id`)
 				REFERENCES `{$requests->getUserTable()}` (`ID`) ON DELETE CASCADE",
-				"CONSTRAINTS `{$base}{$type}_approval_parent_term` FOREIGN KEY (`parent_id`)
+				"CONSTRAINT `{$base}{$type}_approval_parent_term` FOREIGN KEY (`parent_id`)
 				REFERENCES `{$requests->getTermTable()}` (`term_id`) ON DELETE CASCADE"
 			]);
 			$requests->defineTable();
@@ -81,7 +90,7 @@
 
 			$votes->setConstraints([
 				"CONSTRAINT `{$base}{$type}_user_approval_request` FOREIGN KEY (`request_id`)
-				REFERENCES `{$requests->getFullTableName()} (`id`) ON DELETE CASCADE",
+				REFERENCES `{$requests->getFullTableName()}` (`id`) ON DELETE CASCADE",
 				"CONSTRAINT `{$base}{$type}_user_approval_voter` FOREIGN KEY (`user_id`)
 				REFERENCES `{$votes->getUserTable()}` (`ID`) ON DELETE CASCADE"
 			]);
@@ -94,7 +103,23 @@
 			];
 		}
 	}
+	/**
+	 * Handler for user registration
+	 *
+	 * @param int $user_id New user ID
+	 * @param object $user the new user object
+	 *
+	 * @return void
+	 */
+	public function handleRegistration(int $user_id, object $user): void
+	{
+		$registrar = Registrar::getInstance(jvbUserRole($user_id));
 
+		if ($registrar && $registrar->hasFeature('approve_new')) {
+			$user->add_cap('skip_moderation', false);
+			$this->createApproval($user_id, $registrar->getSlug(), $user->display_name);
+		}
+	}
 	public function canApprove(int $userID, string $type):bool
 	{
 		$type = jvbNoBase($type);
@@ -198,6 +223,8 @@
 			return $this->response(false, 'Invalid vote');
 		}
 
+
+
 		$response = $votes->findOrCreate([
 			'request_id'	=> $request_id,
 			'user_id'		=> $userID
@@ -209,12 +236,37 @@
 		if (!$response) {
 			return $this->response(false, 'Could not store vote for some reason.');
 		}
+		$approvers = $request['approved_by'];
+		$rejectors = $request['rejected_By'];
+		$both = array_merge($approvers, $rejectors);
+
+		//See if the user has already voted
+		//If the user is changing their vote, proceed. If it's the same, we can bail early.
+		if (in_array($userID, $both)) {
+			switch ($vote) {
+				case 'reject':
+					if (in_array($userID, $approvers)) {
+						unset($approvers[array_search($userID, $approvers)]);
+					} else {
+						return $this->response(true, 'You already voted this way.');
+					}
+					break;
+				case 'approve':
+					if (in_array($userID, $rejectors)) {
+						unset($rejectors[array_search($userID, $rejectors)]);
+					} else {
+						return $this->response(true, 'You already voted this way.');
+					}
+			}
+		}
 
 		switch ($vote) {
 			case 'reject':
+				$rejectors[] = $userID;
 				$request['rejections']++;
 				break;
 			case 'approve':
+				$approvers[] = $userID;
 				$request['approvals']++;
 				break;
 			default:
@@ -227,8 +279,10 @@
 			$this->finalizeApproval($request_id, $type);
 		}
 		$updated = $requests->update([
-			'rejections'=> $request['rejections'],
-			'approvals'	=> $request['approvals']
+			'rejections'	=> $request['rejections'],
+			'approvals'		=> $request['approvals'],
+			'rejected_by'	=> $rejectors,
+			'approved_by'	=> $approvers
 		],
 		[
 			'request_id' => $request_id
@@ -298,7 +352,9 @@
 				$updatedID = $term['term_id'];
 			}
 		} elseif ($registrar->getType() === 'user') {
-
+			$user = get_userdata($request['user_id']);
+			$user->add_cap('skip_moderation', true);
+			update_user_meta($request['user_id'], BASE.'verification_date', current_time('mysql'));
 		}
 
 		$updates = [
@@ -314,7 +370,7 @@
 			]);
 
 
-		JVB()->notification()->addNotification($request['user_id'], $type.'approved', null, 'Your suggestion "'.$request['name'].'" was denied.');
+		JVB()->notification()->notify($request['user_id'], $type.'approved', null, 'Your suggestion "'.$request['name'].'" was denied.');
 	}
 	public function finalizeDenial(int $request_id, string $type):void
 	{
@@ -331,7 +387,7 @@
 				'request_id' => $request_id
 			]);
 
-		JVB()->notification()->addNotification($request['user_id'], $type.'denied', null, 'Your suggestion "'.$request['name'].'" was denied.');
+		JVB()->notification()->notify($request['user_id'], $type.'denied', null, 'Your suggestion "'.$request['name'].'" was denied.');
 	}
 
 	public function getApprovalRequests(int $userID, ?string $type = null):array
@@ -429,4 +485,74 @@
 			]
 		];
 	}
+
+	/**
+	 * Create artist approval request
+	 *
+	 * @param int $user_id User ID to be approved
+	 *
+	 * @return int|false Request ID or false on failure
+	 */
+	/**
+	 * Create artist approval request - REFACTORED
+	 */
+	public function createArtistApprovalRequest(int $user_id): int|false
+	{
+		$userRole = jvbUserRole($user_id);
+		$table = $this->tables[$userRole]['requests']??false;
+		if (!$table) {
+			return false;
+		}
+		return $table->transaction(function($table) use ($user_id) {
+			// Check for existing request
+			$existing = $table->where(['user_id' => $user_id])->first();
+
+			if ($existing) {
+				return $existing->id;
+			}
+
+			$user_data = get_userdata($user_id);
+
+			return $table->create([
+				'user_id' => $user_id,
+				'status' => 'pending',
+				'expires_at' => date('Y-m-d H:i:s', strtotime('+30 days')),
+				'current_approvals' => 0,
+				'current_rejections' => 0,
+				'required_approvals' => 3, // From config
+				'approved_by' => json_encode([]),
+				'rejected_by' => json_encode([]),
+			]);
+		});
+	}
+
+	public function getRequest(int $requestID, string $type):array|false
+	{
+		$table = $this->requests($type);
+		if (!$table) {
+			return false;
+		}
+		return $table->get(['id' => $requestID])??false;
+	}
+	public function getVotes(int $requestID, string $type):array|false
+	{
+		$table = $this->votes($type);
+		if (!$table) {
+			return false;
+		}
+		return $table->getMany(['request_id' => $requestID])??false;
+	}
+	public function cleanupExpired():void
+	{
+		$now = current_time('mysql');
+		foreach ($this->tables as $type => $tables) {
+			$tables['requests']->query(
+				"UPDATE {table}
+				SET status = 'expired'
+				WHERE status = 'pending'
+				AND expires_at <%s",
+				[$now]
+			);
+		}
+	}
 }

--
Gitblit v1.10.0