Jake Vanderwerf
2026-02-17 a24a06002081ad71a78ffeff9072725ba39cf121
inc/registry/CheckCustomTables.php
@@ -35,7 +35,7 @@
      //Fetch the constants manually, in case they're not defined yet?
      $this->JVB_SITE = apply_filters('jvb_site', []);
      $this->JVB_MEMBERSHIP = apply_filters('jvb_membership', []);
      $this->JVB_CONTENT = apply_filters('jvb_content', []);
      $this->JVB_CONTENT = apply_filters('jvb_content',  []);
      $this->JVB_TAXONOMY = apply_filters('jvb_taxonomy', []);
      $this->JVB_USER = apply_filters('jvb_user', []);
@@ -103,7 +103,12 @@
         error_log('JVB: Starting table creation process');
         error_log('JVB: Memory usage at start: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');
         $tables = $calendar = $integrations = $karma = $stats = $invitable = $verifyEntry = $approval = $trackChanges = [];
         $tables = $calendar = $integrations = $karma = $stats = $verifyEntry = $approval = $trackChanges = [];
         $invitable = [
            'roles' => [],
            'terms' => []
         ];
         // Basic tables (these worked fine)
         try {
@@ -113,10 +118,9 @@
//                $tables = array_merge($tables, $this->umamiTracking());
//             }
            }
            if (array_key_exists('can_invite', $this->JVB_MEMBERSHIP) && is_array($this->JVB_MEMBERSHIP['can_invite'])) {
               foreach ($this->JVB_MEMBERSHIP['can_invite'] as $role => $canInvite) {
                  $invitable[$role]['can_invite'] = $canInvite;
               }
            if (array_key_exists('can_invite', $this->JVB_MEMBERSHIP) &&
               is_array($this->JVB_MEMBERSHIP['can_invite'])) {
               $invitable['roles'] = $this->JVB_MEMBERSHIP['can_invite'];
            }
//          if (jvbCheck('social', $this->JVB_SITE) || jvbCheck('gmb', $this->JVB_SITE) || jvbCheck('square', $this->JVB_SITE) || jvbCheck('helcim', $this->JVB_SITE)) {
@@ -208,9 +212,7 @@
               $trackChanges[$type] = $config;
            }
            if (array_key_exists('invitable', $config) && $config['invitable']) {
               foreach ($config['for_content'] as $content) {
                  $invitable[$content]['to_terms'][] = $type;
               }
               $invitable['terms'][] = $type;
            }
            if (array_key_exists('verify_entry', $config) && $config['verify_entry']) {
               $verifyEntry[$type] = $config;
@@ -295,17 +297,19 @@
         // RE-ENABLE other table types
         try {
            if (!empty($invitable)) {
               error_log('JVB: Creating invitation tables...');
            if (!empty($invitable['roles']) || !empty($invitable['terms'])) {
               error_log('JVB: Creating invitation table...');
               $invitationTables = $this->invitationTables($invitable);
               error_log('JVB: Invitation tables created: ' . count($invitationTables));
               error_log('JVB: Invitation table created: ' . count($invitationTables));
               $tables = array_merge($tables, $invitationTables);
               error_log('JVB: Memory after invitations: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');
            }
         } catch (Exception $e) {
            error_log("JVB: Error creating invitation tables: " . $e->getMessage());
            error_log("JVB: Error creating invitation table: " . $e->getMessage());
         }
         // Store config for later use
         update_option(BASE.'invitation_config', $invitable);
         try {
            if (!empty($approval)) {
               error_log('JVB: Creating approval tables...');
@@ -453,19 +457,20 @@
            `priority` ENUM('high', 'normal', 'low') DEFAULT 'normal',
            `state` enum('pending', 'scheduled', 'processing', 'completed') DEFAULT 'pending',
            `outcome` enum('pending', 'success', 'partial', 'failed','failed_permanent') DEFAULT 'pending',
            `outcome` enum('pending', 'success', 'partial', 'merged', 'failed', 'failed_permanent') DEFAULT 'pending',
         `retries` int(11) DEFAULT 0,
            `last_error_hash` CHAR(32) DEFAULT NULL,
            `error_message` text,
         `scheduled_at` datetime DEFAULT CURRENT_TIMESTAMP,
         `scheduled_at` datetime DEFAULT NULL,
            `started_at` datetime DEFAULT CURRENT_TIMESTAMP,
            `completed_at` datetime DEFAULT NULL,
            `metadata` JSON DEFAULT NULL,
            `result` JSON,
            `dependencies` JSON,
            `merged_into` VARCHAR(64) DEFAULT NULL,
            `user_dismissed` tinyint(1) DEFAULT 0,
            `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
@@ -1153,42 +1158,60 @@
        ];
    }
    protected function invitationTables($types)
    {
        $tables = [];
      foreach ($types as $role => $config) {
         $definitions = "(
                `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
                `name` varchar(255) NOT NULL,
                `email` varchar(255) NOT NULL,
                `invitation_token` varchar(64) NOT NULL,
                `status` enum('pending', 'accepted', 'rejected', 'expired','revoked') DEFAULT 'pending',
                `inviters` JSON NOT NULL,";
         foreach($config['to_terms']??[] as $term) {
            $definitions .= "`to_{$term}` {$this->termIDType} DEFAULT NULL,";
         }
         $definitions .= "`new_user_id` bigint(20) NOT 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,
                PRIMARY KEY (`id`),
                UNIQUE KEY `unique_email` (`email`),
                KEY `token_lookup` (`invitation_token`),
                KEY `status_expiry` (`status`, `expires_at`),
                KEY `name_status` (`name`, `status`)
            )";
         foreach($config['to_terms']??[] as $term) {
            $definitions .= "CONSTRAINT `{$this->base}_{$term}_link` FOREIGN KEY (`to_{$term}`)
                REFERENCES `{$this->wpdb->terms}` (`term_id`) ON DELETE CASCADE";
         }
         $tables['invitations_'.$role] = $definitions;
   protected function invitationTables(array $config): array
   {
      if (empty($config['roles']) && empty($config['terms'])) {
         return [];
      }
        return $tables;
    }
      $definitions = "(
        `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 COMMENT 'Role being invited to',
        `status` enum('pending','accepted','rejected','expired','revoked') DEFAULT 'pending',
        `inviters` JSON NOT NULL COMMENT 'Array of {user_id, invited_at}',
        `new_user_id` {$this->userIDType} 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,
        ";
      // Add term columns for all invitable taxonomies
      foreach ($config['terms'] ?? [] as $taxonomy) {
         $definitions .= "`to_{$taxonomy}` {$this->termIDType} DEFAULT NULL,";
      }
      $definitions .= "PRIMARY KEY (`id`),
        UNIQUE KEY `unique_email_role` (`email`, `invited_role`),
        KEY `token_lookup` (`invitation_token`),
        KEY `status_expiry` (`status`, `expires_at`),
        KEY `role_status` (`invited_role`, `status`),
        KEY `email_status` (`email`, `status`),
        ";
      // Add foreign key constraints for terms
      $constraints = [];
      foreach ($config['terms'] ?? [] as $taxonomy) {
         $constraints[] = "CONSTRAINT `{$this->base}invitations_{$taxonomy}_fk`
            FOREIGN KEY (`to_{$taxonomy}`)
            REFERENCES `{$this->wpdb->terms}` (`term_id`)
            ON DELETE SET NULL";
      }
      // Add user foreign key
      $constraints[] = "CONSTRAINT `{$this->base}invitations_user_fk`
        FOREIGN KEY (`new_user_id`)
        REFERENCES `{$this->userTable}` (`ID`)
        ON DELETE SET NULL";
      $definitions .= implode(',', $constraints);
      $definitions .= ")";
      return ['invitations' => $definitions];
   }
    protected function trackChangesTables($types)
    {