NEW: Upload Workflow (A2→A3) - Load campaigns with status A2 (assets sent to agency) - Select campaign and find upload target folder (Final Assets) - Multi-file upload with drag-drop interface - AssetUploader class with multipart/form-data support - Upload files with metadata to DAM - Update status to A3 after upload NEW: Rework Workflow (A5→A6) - Load campaigns with status A5 (rework needed from agency) - Select campaign and get rework assets - Download individual or bulk rework assets - Beautiful metadata display - Update status to A6 when rework assets received Features: - Three complete workflow tabs (Download, Upload, Rework) - Status transitions: A1→A2, A2→A3, A5→A6 - Session-based workflow state management - Clear workflow data button for each tab - Campaign selection with visual feedback - Download confirmed working (tested with real asset) - OAuth2 auto-refresh throughout all workflows Technical: - AssetUploader class for multipart file uploads - Proper metadata JSON structure for uploads - Support for multiple file formats (JPG, PNG, PDF, AI, PSD, etc.) - Error handling for each workflow step - Beautiful UI with color-coded status badges Ready for testing with real campaign data! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
172 lines
5.1 KiB
PHP
172 lines
5.1 KiB
PHP
<?php
|
|
|
|
require_once 'ApiClient.php';
|
|
|
|
/**
|
|
* AssetUploader - Handles file uploads to Ferrero DAM
|
|
*/
|
|
class AssetUploader
|
|
{
|
|
private $apiClient;
|
|
private $targetFolderId;
|
|
|
|
public function __construct(ApiClient $apiClient, $targetFolderId = null)
|
|
{
|
|
$this->apiClient = $apiClient;
|
|
$this->targetFolderId = $targetFolderId;
|
|
}
|
|
|
|
/**
|
|
* Upload a file to DAM with metadata
|
|
*
|
|
* @param string $filePath Local file path
|
|
* @param string $folderId Target folder ID (campaign folder)
|
|
* @param array $metadata Optional metadata to set
|
|
* @return array Upload result
|
|
*/
|
|
public function uploadFile($filePath, $folderId, $metadata = [])
|
|
{
|
|
if (!file_exists($filePath)) {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'File not found: ' . $filePath
|
|
];
|
|
}
|
|
|
|
$filename = basename($filePath);
|
|
$mimeType = mime_content_type($filePath);
|
|
|
|
// Build multipart form data
|
|
$boundary = '----WebKitFormBoundary' . uniqid();
|
|
|
|
// Build asset representation JSON
|
|
$assetRepresentation = $this->buildAssetRepresentation($filename, $metadata);
|
|
|
|
// Build multipart body
|
|
$body = '';
|
|
|
|
// Add asset_representation part
|
|
$body .= "--{$boundary}\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"asset_representation\"\r\n";
|
|
$body .= "Content-Type: application/json\r\n\r\n";
|
|
$body .= json_encode($assetRepresentation) . "\r\n";
|
|
|
|
// Add parent_folder_id part
|
|
$body .= "--{$boundary}\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"parent_folder_id\"\r\n\r\n";
|
|
$body .= $folderId . "\r\n";
|
|
|
|
// Add file part
|
|
$body .= "--{$boundary}\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"file\"; filename=\"{$filename}\"\r\n";
|
|
$body .= "Content-Type: {$mimeType}\r\n\r\n";
|
|
$body .= file_get_contents($filePath) . "\r\n";
|
|
|
|
$body .= "--{$boundary}--\r\n";
|
|
|
|
// Make upload request
|
|
$request = [
|
|
'method' => 'POST',
|
|
'url' => '/v6/assets',
|
|
'body' => $body
|
|
];
|
|
|
|
// Set multipart content-type header
|
|
$this->apiClient->setHeader('Content-Type', "multipart/form-data; boundary={$boundary}");
|
|
|
|
$response = $this->apiClient->executeRequest($request);
|
|
|
|
if ($response['success'] && $response['http_code'] == 201) {
|
|
$responseData = json_decode($response['body'], true);
|
|
|
|
return [
|
|
'success' => true,
|
|
'asset_id' => $responseData['asset_resource_list']['asset_resource'][0]['asset']['asset_id'] ?? null,
|
|
'filename' => $filename,
|
|
'response' => $responseData
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Upload failed',
|
|
'http_code' => $response['http_code'],
|
|
'response' => $response['body']
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Build asset representation for upload
|
|
*/
|
|
private function buildAssetRepresentation($filename, $metadata = [])
|
|
{
|
|
$assetRep = [
|
|
'asset_resource' => [
|
|
'asset' => [
|
|
'metadata' => [
|
|
'metadata_element_list' => []
|
|
]
|
|
]
|
|
]
|
|
];
|
|
|
|
// Add filename metadata
|
|
$assetRep['asset_resource']['asset']['metadata']['metadata_element_list'][] = [
|
|
'id' => 'ARTESIA.FIELD.ASSET NAME',
|
|
'type' => 'com.artesia.metadata.MetadataField',
|
|
'value' => [
|
|
'cascading_domain_value' => false,
|
|
'domain_value' => false,
|
|
'value' => [
|
|
'type' => 'string',
|
|
'value' => $filename
|
|
]
|
|
]
|
|
];
|
|
|
|
// Add custom metadata fields
|
|
foreach ($metadata as $fieldId => $fieldValue) {
|
|
$assetRep['asset_resource']['asset']['metadata']['metadata_element_list'][] = [
|
|
'id' => $fieldId,
|
|
'type' => 'com.artesia.metadata.MetadataField',
|
|
'value' => [
|
|
'cascading_domain_value' => false,
|
|
'domain_value' => false,
|
|
'value' => [
|
|
'type' => 'string',
|
|
'value' => $fieldValue
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
return $assetRep;
|
|
}
|
|
|
|
/**
|
|
* Upload multiple files
|
|
*/
|
|
public function uploadMultipleFiles($files, $folderId, $metadata = [])
|
|
{
|
|
$results = [
|
|
'total' => count($files),
|
|
'successful' => 0,
|
|
'failed' => 0,
|
|
'details' => []
|
|
];
|
|
|
|
foreach ($files as $file) {
|
|
$result = $this->uploadFile($file, $folderId, $metadata);
|
|
|
|
if ($result['success']) {
|
|
$results['successful']++;
|
|
} else {
|
|
$results['failed']++;
|
|
}
|
|
|
|
$results['details'][] = $result;
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
}
|