From 47e77f9fac1155c536b2b87fec552c7fcce66fa6 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 01 Jun 2026 18:06:34 +0000
Subject: [PATCH] =Timeline block fixes. Next up: adding article schema classes

---
 inc/managers/InvitationsManager.php |   62 ++++++++++++++++++++++++++++++-
 1 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/inc/managers/InvitationsManager.php b/inc/managers/InvitationsManager.php
index 088556f..ccb2f2f 100644
--- a/inc/managers/InvitationsManager.php
+++ b/inc/managers/InvitationsManager.php
@@ -5,7 +5,7 @@
 use JVBase\managers\queue\executors\InvitationExecutor;
 use JVBase\managers\queue\TypeConfig;
 use JVBase\registrar\Registrar;
-use JVBase\utility\Features;
+use JVBase\base\Site;
 use WP_Error;
 
 if (!defined('ABSPATH')) {
@@ -20,9 +20,12 @@
 	protected Cache $cache;
 	public function __construct()
 	{
+		$this->defineTable();
+		if (!isset($this->table)) {
+			return;
+		}
 		$this->setInviteConfig();
 		$this->cache = Cache::for('invitations');
-		$this->table = CustomTable::for('invitations');
 		add_action('init', [$this, 'registerInvitationExecutors'], 5);
 
 		add_action('user_register', [$this, 'checkInvitation']);
@@ -31,6 +34,61 @@
 		add_filter(BASE . 'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
 	}
 
+	public function defineTable():void
+	{
+		$terms = Registrar::getFeatured('invitable', 'term');
+		$membership = Site::membership();
+		$roles = ($membership) ? Site::membership()->has('can_invite') :[];
+		if (empty($terms) && empty($roles)) {
+			return;
+		}
+
+		$table = CustomTable::for('invitations');
+		$columns = [
+			'id'				=> 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+			'name'				=> 'varchar(255) NOT NULL',
+			'email'				=> 'varchar(255) NOT NULL',
+			'invitation_token'	=> 'varchar(255) NOT NULL',
+			'invited_role'		=> 'varchar(50) NOT NULL',		//Role being invited to
+			'status'			=> "ENUM('pending','accepted','rejected','expired','revoked') DEFAULT 'pending'",
+			'inviters'			=> 'JSON NOT NULL', 			// Array of {user_id, invited_at}
+			'new_user_id'		=> $table->getUserIDType().' DEFAULT NULL',
+			'expires_at'		=> 'datetime NOT NULL',
+			'accepted_at'		=> 'datetime DEFAULT NULL',
+			'created_at'		=> 'datetime NOT NULL DEFAULT CURRENT_TIMESTAMP',
+			'updated_at'		=> 'datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'
+		];
+
+		foreach ($terms as $tax) {
+			$columns["to_{$tax}"] = $table->getTermIDType().' DEFAULT NULL';
+		}
+		$table->setColumns($columns);
+
+
+		$table->setKeys([
+			['key' => 'PRIMARY', 'value' => '(`id`)'],
+			['key' => 'UNIQUE', 'value' => '`unique_email_role` (`email`, `invited_role`)'],
+			'`token_lookup` (`invitation_token`)',
+			'`status_expiry` (`status`, `expires_at`)',
+			'`role_status` (`invited_role`, `status`)',
+			'`email_status` (`email`, `status`)'
+		]);
+		$constraints = [];
+		$base = BASE;
+		global $wpdb;
+		foreach ($terms as $tax) {
+			$constraints[] = "CONSTRAINT `{$base}invitations_{$tax}_fk` FOREIGN KEY (`to_{$tax}`) REFERENCES `{$wpdb->terms}` (`term_id`)
+            ON DELETE SET NULL";
+		}
+		$constraints[] = "CONSTRAINT `{$base}invitations_user_fk`  FOREIGN KEY (`new_user_id`) REFERENCES `{$table->getUserTable()}` (`ID`)
+        ON DELETE SET NULL";
+
+		$table->setConstraints($constraints);
+
+		$table->defineTable();
+		$this->table = $table;
+	}
+
 	protected function setInviteConfig():void
 	{
 		$this->inviteConfig = get_option(BASE.'invitation_config', [

--
Gitblit v1.10.0