boxClient = new BoxClient($clientId, $clientSecret); $this->tempDir = sys_get_temp_dir() . '/ferrero_box_downloads'; // Create temp directory if it doesn't exist if (!is_dir($this->tempDir)) { mkdir($this->tempDir, 0755, true); } } /** * List all files in a Box folder * * @param string $folderId Box folder ID * @return array List of files with metadata */ public function listFilesInFolder($folderId) { try { $accessToken = $this->boxClient->getAccessToken(); // Call Box API to list folder items $url = "https://api.box.com/2.0/folders/$folderId/items?fields=id,name,type,size,modified_at,description"; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $accessToken, 'Content-Type: application/json' ], CURLOPT_TIMEOUT => 60 ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error) { throw new Exception("Box API error: $error"); } if ($httpCode !== 200) { throw new Exception("Box API returned HTTP $httpCode: $response"); } $data = json_decode($response, true); if (!isset($data['entries'])) { throw new Exception("Invalid response from Box API"); } // Filter to only files (not folders) $files = []; foreach ($data['entries'] as $item) { if ($item['type'] === 'file') { $files[] = [ 'id' => $item['id'], 'name' => $item['name'], 'size' => $item['size'] ?? 0, 'modified_at' => $item['modified_at'] ?? null, 'description' => $item['description'] ?? '', 'box_url' => "https://app.box.com/file/{$item['id']}" ]; } } return [ 'success' => true, 'folder_id' => $folderId, 'file_count' => count($files), 'files' => $files ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), 'folder_id' => $folderId ]; } } /** * Get metadata for a specific file * * @param string $fileId Box file ID * @return array File metadata */ public function getFileMetadata($fileId) { try { $accessToken = $this->boxClient->getAccessToken(); $url = "https://api.box.com/2.0/files/$fileId?fields=id,name,type,size,modified_at,description,created_at,shared_link"; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $accessToken, 'Content-Type: application/json' ], CURLOPT_TIMEOUT => 30 ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { throw new Exception("Box API returned HTTP $httpCode"); } $data = json_decode($response, true); return [ 'success' => true, 'metadata' => $data ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage() ]; } } /** * Download a file from Box * * @param string $fileId Box file ID * @param string $filename Filename for local save * @return array Result with local path */ public function downloadFile($fileId, $filename) { try { $accessToken = $this->boxClient->getAccessToken(); // Download URL $url = "https://api.box.com/2.0/files/$fileId/content"; $localPath = $this->tempDir . '/' . $filename; // Download file $ch = curl_init(); $fp = fopen($localPath, 'w'); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $accessToken ], CURLOPT_FILE => $fp, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 300 ]); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); fclose($fp); if (!$result || $httpCode !== 200) { unlink($localPath); throw new Exception("Download failed with HTTP $httpCode"); } return [ 'success' => true, 'local_path' => $localPath, 'size' => filesize($localPath) ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage() ]; } } /** * Extract tracking ID from filename * * @param string $filename Full filename * @return string|null Tracking ID or null if not found */ public function extractTrackingId($filename) { // Remove extension $pathInfo = pathinfo($filename); $filenameWithoutExt = $pathInfo['filename']; // Split by underscore $parts = explode('_', $filenameWithoutExt); // Last part should be tracking ID (6 alphanumeric characters) if (count($parts) > 0) { $lastPart = end($parts); if (strlen($lastPart) === 6 && ctype_alnum($lastPart)) { return $lastPart; } } return null; } /** * List files with parsed tracking IDs * * @param string $folderId Box folder ID * @return array Files with tracking ID info */ public function listFilesWithTrackingIDs($folderId) { $result = $this->listFilesInFolder($folderId); if (!$result['success']) { return $result; } // Add tracking ID to each file foreach ($result['files'] as &$file) { $file['tracking_id'] = $this->extractTrackingId($file['name']); $file['has_tracking_id'] = !empty($file['tracking_id']); } return $result; } /** * Get temp directory path * * @return string */ public function getTempDir() { return $this->tempDir; } /** * Clean up temp directory * * @return bool */ public function cleanTempDir() { if (!is_dir($this->tempDir)) { return true; } $files = glob($this->tempDir . '/*'); foreach ($files as $file) { if (is_file($file)) { unlink($file); } } return true; } /** * Test Box connection * * @return array */ public function testConnection() { try { $accessToken = $this->boxClient->getAccessToken(); return [ 'success' => true, 'message' => 'Box connection successful', 'has_token' => !empty($accessToken) ]; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage() ]; } } }