ferrero-opentext/src/BoxFileRetriever.php
DJP d3f3063eaf Fix Box integration issues
Added missing getAccessToken() method to BoxClient
Fixed BoxFileRetriever to properly initialize BoxClient with credentials from config

Changes:
- BoxClient: Added public getAccessToken() method
- BoxFileRetriever: Load Box config and extract clientID/clientSecret
- BoxFileRetriever: Pass credentials to BoxClient constructor

This fixes the 'Call to undefined method' error when loading Box files.

🤖 Generated with Claude Code
2025-10-29 16:12:22 -04:00

323 lines
9 KiB
PHP

<?php
require_once 'BoxClient.php';
/**
* BoxFileRetriever - List and Download Files from Box Folders
*
* This class handles:
* 1. Listing files in a Box folder
* 2. Getting file metadata
* 3. Downloading files to temp location
* 4. Extracting tracking IDs from filenames
*/
class BoxFileRetriever
{
private $boxClient;
private $tempDir;
public function __construct($boxConfigFile = 'Box-config.json')
{
// Load Box config
$configPath = __DIR__ . '/../' . $boxConfigFile;
if (!file_exists($configPath)) {
throw new Exception("Box config file not found: $configPath");
}
$config = json_decode(file_get_contents($configPath), true);
$clientId = $config['boxAppSettings']['clientID'] ?? null;
$clientSecret = $config['boxAppSettings']['clientSecret'] ?? null;
if (!$clientId || !$clientSecret) {
throw new Exception("Box config missing clientID or clientSecret");
}
// Initialize BoxClient with credentials
$this->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()
];
}
}
}