auth = new HVAC_Google_Sheets_Auth(); if (class_exists('HVAC_Logger')) { $this->logger = new HVAC_Logger(); } } /** * Get or create the root "Upskill Training Sheets" folder */ public function get_root_folder_id() { if ($this->root_folder_id) { return $this->root_folder_id; } try { // First, search for existing folder $existing_folder = $this->find_folder_by_name(self::ROOT_FOLDER_NAME); if ($existing_folder) { $this->root_folder_id = $existing_folder['id']; $this->log_info("Found existing root folder: {$this->root_folder_id}"); // Ensure proper permissions are set $this->set_organization_permissions($this->root_folder_id); return $this->root_folder_id; } // Create new root folder $folder_data = array( 'name' => self::ROOT_FOLDER_NAME, 'mimeType' => 'application/vnd.google-apps.folder' ); $response = $this->auth->make_drive_api_request('POST', 'files', $folder_data); if (isset($response['id'])) { $this->root_folder_id = $response['id']; $this->log_info("Created root folder: {$this->root_folder_id}"); // Set organization permissions $this->set_organization_permissions($this->root_folder_id); // Make discoverable in search $this->make_folder_discoverable($this->root_folder_id); return $this->root_folder_id; } throw new Exception('Failed to create root folder'); } catch (Exception $e) { $this->log_error('Failed to get/create root folder: ' . $e->getMessage()); return false; } } /** * Get or create the "_Master Trainer" folder */ public function get_master_trainer_folder_id() { if ($this->master_folder_id) { return $this->master_folder_id; } $root_folder_id = $this->get_root_folder_id(); if (!$root_folder_id) { return false; } try { // Search for existing master trainer folder $existing_folder = $this->find_folder_by_name(self::MASTER_TRAINER_FOLDER_NAME, $root_folder_id); if ($existing_folder) { $this->master_folder_id = $existing_folder['id']; $this->log_info("Found existing master trainer folder: {$this->master_folder_id}"); return $this->master_folder_id; } // Create master trainer folder $folder_data = array( 'name' => self::MASTER_TRAINER_FOLDER_NAME, 'mimeType' => 'application/vnd.google-apps.folder', 'parents' => array($root_folder_id) ); $response = $this->auth->make_drive_api_request('POST', 'files', $folder_data); if (isset($response['id'])) { $this->master_folder_id = $response['id']; $this->log_info("Created master trainer folder: {$this->master_folder_id}"); return $this->master_folder_id; } throw new Exception('Failed to create master trainer folder'); } catch (Exception $e) { $this->log_error('Failed to get/create master trainer folder: ' . $e->getMessage()); return false; } } /** * Get or create an event-specific folder */ public function get_event_folder_id($event_id) { if (isset($this->event_folders[$event_id])) { return $this->event_folders[$event_id]; } $root_folder_id = $this->get_root_folder_id(); if (!$root_folder_id) { return false; } $event = get_post($event_id); if (!$event) { $this->log_error("Event not found: {$event_id}"); return false; } $folder_name = self::EVENT_FOLDER_PREFIX . $event->post_title; try { // Search for existing event folder $existing_folder = $this->find_folder_by_name($folder_name, $root_folder_id); if ($existing_folder) { $this->event_folders[$event_id] = $existing_folder['id']; $this->log_info("Found existing event folder for {$event_id}: {$existing_folder['id']}"); return $this->event_folders[$event_id]; } // Create event folder $folder_data = array( 'name' => $folder_name, 'mimeType' => 'application/vnd.google-apps.folder', 'parents' => array($root_folder_id) ); $response = $this->auth->make_drive_api_request('POST', 'files', $folder_data); if (isset($response['id'])) { $this->event_folders[$event_id] = $response['id']; $this->log_info("Created event folder for {$event_id}: {$response['id']}"); return $this->event_folders[$event_id]; } throw new Exception('Failed to create event folder'); } catch (Exception $e) { $this->log_error("Failed to get/create event folder for {$event_id}: " . $e->getMessage()); return false; } } /** * Set organization-wide permissions on a folder */ private function set_organization_permissions($folder_id) { try { // Set permissions for measureQuick.com organization $permission_data = array( 'role' => 'writer', 'type' => 'domain', 'domain' => 'measurequick.com', 'allowFileDiscovery' => true ); $response = $this->auth->make_drive_api_request('POST', "files/{$folder_id}/permissions", $permission_data); if (isset($response['id'])) { $this->log_info("Set organization permissions on folder: {$folder_id}"); return true; } throw new Exception('Failed to set permissions'); } catch (Exception $e) { $this->log_error("Failed to set organization permissions on {$folder_id}: " . $e->getMessage()); return false; } } /** * Make folder discoverable in Google Search */ private function make_folder_discoverable($folder_id) { try { // Update folder to be discoverable $folder_data = array( 'capabilities' => array( 'canAddChildren' => true, 'canListChildren' => true, 'canRemoveChildren' => true ), 'viewersCanCopyContent' => true, 'copyRequiresWriterPermission' => false ); $response = $this->auth->make_drive_api_request('PATCH', "files/{$folder_id}", $folder_data); if (isset($response['id'])) { $this->log_info("Made folder discoverable: {$folder_id}"); return true; } throw new Exception('Failed to make folder discoverable'); } catch (Exception $e) { $this->log_error("Failed to make folder discoverable {$folder_id}: " . $e->getMessage()); return false; } } /** * Find a folder by name, optionally within a parent folder */ private function find_folder_by_name($name, $parent_id = null) { try { $query = "name='{$name}' and mimeType='application/vnd.google-apps.folder' and trashed=false"; if ($parent_id) { $query .= " and '{$parent_id}' in parents"; } $response = $this->auth->make_drive_api_request('GET', 'files', null, array( 'q' => $query, 'fields' => 'files(id,name,parents)', 'pageSize' => 10 )); if (isset($response['files']) && count($response['files']) > 0) { return $response['files'][0]; // Return first match } return null; } catch (Exception $e) { $this->log_error("Failed to search for folder '{$name}': " . $e->getMessage()); return null; } } /** * Get folder structure overview */ public function get_folder_structure() { $structure = array( 'root' => array( 'name' => self::ROOT_FOLDER_NAME, 'id' => $this->get_root_folder_id(), 'url' => null ), 'master_trainer' => array( 'name' => self::MASTER_TRAINER_FOLDER_NAME, 'id' => $this->get_master_trainer_folder_id(), 'url' => null ), 'event_folders' => array() ); // Add URLs for existing folders if ($structure['root']['id']) { $structure['root']['url'] = "https://drive.google.com/drive/folders/{$structure['root']['id']}"; } if ($structure['master_trainer']['id']) { $structure['master_trainer']['url'] = "https://drive.google.com/drive/folders/{$structure['master_trainer']['id']}"; } return $structure; } /** * Verify and repair folder structure */ public function verify_folder_structure() { $results = array(); // Check root folder $root_id = $this->get_root_folder_id(); $results['root_folder'] = array( 'status' => $root_id ? 'exists' : 'missing', 'id' => $root_id, 'message' => $root_id ? 'Root folder found/created successfully' : 'Failed to create root folder' ); // Check master trainer folder if ($root_id) { $master_id = $this->get_master_trainer_folder_id(); $results['master_trainer_folder'] = array( 'status' => $master_id ? 'exists' : 'missing', 'id' => $master_id, 'message' => $master_id ? 'Master trainer folder found/created successfully' : 'Failed to create master trainer folder' ); } // Check permissions if ($root_id) { $permissions_ok = $this->verify_organization_permissions($root_id); $results['permissions'] = array( 'status' => $permissions_ok ? 'configured' : 'missing', 'message' => $permissions_ok ? 'Organization permissions configured' : 'Failed to configure organization permissions' ); } return $results; } /** * Verify organization permissions on a folder */ private function verify_organization_permissions($folder_id) { try { $response = $this->auth->make_drive_api_request('GET', "files/{$folder_id}/permissions"); if (isset($response['permissions'])) { foreach ($response['permissions'] as $permission) { if (isset($permission['domain']) && $permission['domain'] === 'measurequick.com' && $permission['role'] === 'writer') { return true; } } } return false; } catch (Exception $e) { $this->log_error("Failed to verify permissions on {$folder_id}: " . $e->getMessage()); return false; } } /** * Log info message */ private function log_info($message) { if ($this->logger) { $this->logger->info($message, 'Google Sheets Folders'); } } /** * Log error message */ private function log_error($message) { if ($this->logger) { $this->logger->error($message, 'Google Sheets Folders'); } } } ?>