oauth = $oauth; $this->oauth->addScopes(self::DRIVE_SCOPES); } /** * List files and folders in Google Drive * @param string|null $folderId Parent folder ID (null for root) * @param array $options Additional query parameters * @return array * @throws \Exception */ public function listFiles(?string $folderId = null, array $options = []): array { try { $query = []; if ($folderId) { $query[] = "'{$folderId}' in parents"; } else { $query[] = "'root' in parents"; } // Add trashed=false to exclude deleted files $query[] = "trashed=false"; // Handle mime type filtering through options if (isset($options['mimeTypes'])) { $mimeTypes = array_map(function($type) { return "mimeType='" . $type . "'"; }, $options['mimeTypes']); $query[] = '(' . implode(' or ', $mimeTypes) . ')'; unset($options['mimeTypes']); // Remove from options to avoid duplication in params } $params = array_merge([ 'fields' => 'files(id, name, mimeType, size, modifiedTime, parents)', 'orderBy' => 'folder,name', // Sort folders first, then by name 'q' => implode(' and ', $query) ], $options); $response = $this->oauth->makeAuthenticatedRequest( self::DRIVE_API_BASE . '/files?' . http_build_query($params) ); return $response; } catch (\Exception $e) { if ($this->isAuthenticationError($e)) { throw new \Exception('Authentication required. Use getAuthorizationUrl() to start the auth flow.', 401); } throw $e; } } /** * Download a file by its ID * @param string $fileId * @param string|null $mimeType Optional mime type for export (useful for Google Docs) * @return string File content * @throws \Exception */ public function downloadFile(string $fileId, ?string $mimeType = null): string { try { // First, get file metadata to determine if it's a Google Workspace file $file = $this->getFile($fileId); $isGoogleWorkspaceFile = substr($file['mimeType'], 0, 23) === 'application/vnd.google-apps'; // For Google Sheets, always use export if ($file['mimeType'] === 'application/vnd.google-apps.spreadsheet') { $endpoint = self::DRIVE_API_BASE . '/files/' . $fileId . '/export'; $endpoint .= '?mimeType=' . urlencode('text/csv'); return $this->oauth->makeAuthenticatedRequest( $endpoint, 'GET', ['Accept: text/csv'], null, true ); } // For other files, use regular download $endpoint = self::DRIVE_API_BASE . '/files/' . $fileId; if ($isGoogleWorkspaceFile && $mimeType) { $endpoint .= '/export'; $endpoint .= '?mimeType=' . urlencode($mimeType); } else { $endpoint .= '?alt=media'; } return $this->oauth->makeAuthenticatedRequest( $endpoint, 'GET', ['Accept: */*'], null, true ); } catch (\Exception $e) { if ($this->isAuthenticationError($e)) { throw new \Exception('Authentication required. Use getAuthorizationUrl() to start the auth flow.', 401); } throw $e; } } /** * Get file metadata * @param string $fileId * @return array * @throws \Exception */ public function getFile(string $fileId): array { try { return $this->oauth->makeAuthenticatedRequest( self::DRIVE_API_BASE . '/files/' . $fileId . '?fields=id,name,mimeType,size,modifiedTime,parents' ); } catch (\Exception $e) { if ($this->isAuthenticationError($e)) { throw new \Exception('Authentication required. Use getAuthorizationUrl() to start the auth flow.', 401); } throw $e; } } /** * Get authorization URL to start OAuth flow * @param array $additionalParams * @return string */ public function getAuthorizationUrl(array $additionalParams = []): string { return $this->oauth->getAuthorizationUrl($additionalParams); } /** * Check if the error is related to authentication * @param \Exception $e * @return bool */ private function isAuthenticationError(\Exception $e): bool { return $e->getCode() === 401 || $e->getCode() === 403; } /** * Get common MIME types for Google Workspace files * @return array */ public static function getCommonExportMimeTypes(): array { return [ 'application/vnd.google-apps.spreadsheet' => [ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'csv' => 'text/csv', 'pdf' => 'application/pdf' ], 'application/vnd.google-apps.document' => [ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'pdf' => 'application/pdf', 'txt' => 'text/plain' ], 'application/vnd.google-apps.presentation' => [ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pdf' => 'application/pdf' ] ]; } } // Initialize the service // $oauth = new GoogleOAuth2($clientId, $clientSecret, $redirectUri); // $drive = new GoogleDrive($oauth);