validate(); if (!empty($errors)) { die("Configuration Error: " . implode(', ', $errors)); } $config = [ 'baseUrl' => $configV3->getBaseUrl(), 'timeout' => $configV3->get('api.timeout'), 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ] ]; $collectionPath = __DIR__ . '/' . $configV3->get('postman_collection'); $testRunner = null; $error = null; $success = null; $currentTab = $_GET['tab'] ?? $_POST['tab'] ?? 'download'; try { if (file_exists($collectionPath)) { $testRunner = new TestRunner($collectionPath, $config); } else { $error = "Postman collection file not found: " . $collectionPath; } } catch (Exception $e) { $error = "Error initializing: " . $e->getMessage(); } // Initialize results storage if (!isset($_SESSION['workflow_results'])) { $_SESSION['workflow_results'] = []; } $results = &$_SESSION['workflow_results']; // Handle POST actions if ($_POST && $testRunner) { $action = $_POST['action'] ?? ''; try { switch ($action) { case 'debug_all_campaigns': // Check OAuth status first $oauth2Status = $testRunner->getOAuth2Status(); $results['oauth_debug'] = [ 'has_token' => $oauth2Status['has_token'] ?? false, 'expires_at' => $oauth2Status['expires_at'] ?? 'Unknown' ]; $statusManager = createStatusManager($testRunner); $response = $statusManager->searchAllCampaigns($testRunner); if ($response['success']) { $data = json_decode($response['body'], true); $campaigns = CampaignFormatter::getActionableCampaigns($response['body'], []); $results['debug_campaigns'] = $campaigns; $results['debug_raw'] = $data; $results['debug_search_response'] = [ 'http_code' => $response['http_code'], 'url' => $response['url'] ?? 'N/A', 'total_results' => $data['search_result_resource']['search_result']['total_hit_count'] ?? 0, 'response_body_preview' => substr($response['body'] ?? '', 0, 500) ]; $success = "Found " . count($campaigns) . " campaigns total (without status filter)"; } else { $error = "Debug search failed: HTTP " . ($response['http_code'] ?? 'N/A') . " - " . ($response['error'] ?? 'Unknown error'); $results['debug_search_response'] = [ 'http_code' => $response['http_code'], 'url' => $response['url'] ?? 'N/A', 'error' => $response['error'] ?? 'Unknown', 'response_preview' => substr($response['body'] ?? '', 0, 500) ]; } break; case 'load_campaigns_a1': $results['a1_campaigns'] = loadCampaignsByStatus($testRunner, 'A1'); $success = "Loaded " . count($results['a1_campaigns']) . " campaigns with status A1"; break; case 'select_campaign_a1': $campaignId = $_POST['campaign_id'] ?? ''; if ($campaignId && isset($results['a1_campaigns'])) { foreach ($results['a1_campaigns'] as $campaign) { if ($campaign['asset_id'] === $campaignId) { $results['selected_campaign'] = $campaign; $success = "Campaign selected: " . $campaign['campaign_name']; break; } } } break; case 'get_master_assets': if (isset($results['selected_campaign'])) { $campaignId = $results['selected_campaign']['asset_id']; $masterFolderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3); if ($masterFolderId) { $results['master_folder_id'] = $masterFolderId; $results['master_assets'] = getAssetsFromFolder($testRunner, $masterFolderId); $success = "Found Master Assets folder with " . count($results['master_assets']) . " assets"; } else { $error = "Master Assets folder not found in campaign"; } } break; case 'download_asset': $assetId = $_POST['asset_id'] ?? ''; $filename = $_POST['filename'] ?? ''; if ($assetId && isset($results['selected_campaign'])) { // Find the asset in our master_assets array to get its full data $assetData = null; if (isset($results['master_assets'])) { foreach ($results['master_assets'] as $asset) { if ($asset['asset_id'] === $assetId) { $assetData = $asset; break; } } } $result = downloadAsset($testRunner, $assetId, $filename, $results['selected_campaign']['campaign_id'], $assetData); $results['last_download'] = $result; if ($result['success']) { $success = "Downloaded: " . $result['filename']; } else { $error = "Download failed: " . $result['error']; } } break; case 'download_all_assets': if (isset($results['master_assets']) && isset($results['selected_campaign'])) { $downloadResults = downloadAllAssets($testRunner, $results['master_assets'], $results['selected_campaign']['campaign_id']); $results['bulk_download'] = $downloadResults; // Store master assets metadata for later upload reference $results['master_assets_metadata'] = $results['master_assets']; $success = "Downloaded {$downloadResults['successful']} of {$downloadResults['total']} assets"; } break; case 'reset_to_a1': $campaignId = $_POST['campaign_id'] ?? ''; if ($campaignId) { $statusManager = createStatusManager($testRunner); $statusResult = $statusManager->updateCampaignStatus($campaignId, 'A1'); if ($statusResult['success']) { $success = "Campaign reset to A1 status for testing"; // Clear session data so we can start fresh unset($results['selected_campaign']); unset($results['selected_campaign_a2']); unset($results['master_assets_metadata']); } else { $errorMsg = "Unknown error"; if (isset($statusResult['response']['body'])) { $responseData = json_decode($statusResult['response']['body'], true); if ($responseData && isset($responseData['exception_body'])) { $errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error'; } elseif ($responseData && isset($responseData['error'])) { $errorMsg = $responseData['error']; } } $error = "Failed to reset to A1 (HTTP {$statusResult['http_code']}): {$errorMsg}"; } } $currentTab = $_POST['tab'] ?? 'download'; break; case 'update_status_to_a2': if (isset($results['selected_campaign'])) { $statusManager = createStatusManager($testRunner); $statusResult = $statusManager->updateCampaignStatus( $results['selected_campaign']['asset_id'], 'A2' ); if ($statusResult['success']) { $results['status_update'] = $statusResult; $results['selected_campaign']['status'] = 'A2'; $success = "Campaign status updated to A2: Selected Master Assets sent to Agency"; } else { // Extract error details from API response $errorMsg = "Unknown error"; if (isset($statusResult['response']['body'])) { $responseData = json_decode($statusResult['response']['body'], true); if ($responseData && isset($responseData['exception_body'])) { $errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error'; } elseif ($responseData && isset($responseData['error'])) { $errorMsg = $responseData['error']; } } $error = "Failed to update status to A2 (HTTP {$statusResult['http_code']}): {$errorMsg}"; // Store full result for debugging $results['status_update_error'] = $statusResult; } } break; case 'load_campaigns_a2': $results['a2_campaigns'] = loadCampaignsByStatus($testRunner, 'A2'); $success = "Loaded " . count($results['a2_campaigns']) . " campaigns with status A2"; $currentTab = 'upload'; break; case 'select_campaign_a2': $campaignId = $_POST['campaign_id'] ?? ''; if ($campaignId && isset($results['a2_campaigns'])) { foreach ($results['a2_campaigns'] as $campaign) { if ($campaign['asset_id'] === $campaignId) { $results['selected_campaign_a2'] = $campaign; $success = "Campaign selected: " . $campaign['campaign_name']; $currentTab = 'upload'; break; } } } break; case 'get_upload_folder': if (isset($results['selected_campaign_a2'])) { $campaignId = $results['selected_campaign_a2']['asset_id']; // Find Final Assets or Localized Assets folder $uploadFolderId = findUploadFolder($testRunner, $campaignId, $configV3); if ($uploadFolderId) { $results['upload_folder_id'] = $uploadFolderId; $success = "Found upload target folder"; } else { $error = "Upload folder not found in campaign"; } } $currentTab = 'upload'; break; case 'upload_files': if (isset($_FILES['upload_files']) && isset($results['upload_folder_id'])) { // Use master assets metadata if available (from A1 campaign downloads) $masterMetadata = $results['master_assets_metadata'] ?? null; $uploadResults = uploadFiles($testRunner, $_FILES['upload_files'], $results['upload_folder_id'], $masterMetadata); $results['upload_results'] = $uploadResults; if ($uploadResults['successful'] > 0) { $success = "Uploaded {$uploadResults['successful']} of {$uploadResults['total']} files"; } else { $error = "All uploads failed"; } } $currentTab = 'upload'; break; case 'update_status_to_a3': if (isset($results['selected_campaign_a2'])) { $statusManager = createStatusManager($testRunner); $statusResult = $statusManager->updateCampaignStatus( $results['selected_campaign_a2']['asset_id'], 'A3' ); if ($statusResult['success']) { $results['status_update_a3'] = $statusResult; $success = "Campaign status updated to A3: Localized Asset received from Agency"; } else { // Extract error details from API response $errorMsg = "Unknown error"; if (isset($statusResult['response']['body'])) { $responseData = json_decode($statusResult['response']['body'], true); if ($responseData && isset($responseData['exception_body'])) { $errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error'; } elseif ($responseData && isset($responseData['error'])) { $errorMsg = $responseData['error']; } } $error = "Failed to update status to A3 (HTTP {$statusResult['http_code']}): {$errorMsg}"; $results['status_update_a3_error'] = $statusResult; } } $currentTab = 'upload'; break; case 'load_campaigns_a5': $results['a5_campaigns'] = loadCampaignsByStatus($testRunner, 'A5'); $success = "Loaded " . count($results['a5_campaigns']) . " campaigns with status A5"; $currentTab = 'rework'; break; case 'select_campaign_a5': $campaignId = $_POST['campaign_id'] ?? ''; if ($campaignId && isset($results['a5_campaigns'])) { foreach ($results['a5_campaigns'] as $campaign) { if ($campaign['asset_id'] === $campaignId) { $results['selected_campaign_a5'] = $campaign; $success = "Campaign selected: " . $campaign['campaign_name']; $currentTab = 'rework'; break; } } } break; case 'get_rework_assets': if (isset($results['selected_campaign_a5'])) { $campaignId = $results['selected_campaign_a5']['asset_id']; // Find folder with rework assets (could be Final Assets or Rework folder) $reworkFolderId = findUploadFolder($testRunner, $campaignId, $configV3); if ($reworkFolderId) { $results['rework_folder_id'] = $reworkFolderId; $results['rework_assets'] = getAssetsFromFolder($testRunner, $reworkFolderId); $success = "Found " . count($results['rework_assets']) . " assets needing rework"; } else { $error = "Rework assets folder not found"; } } $currentTab = 'rework'; break; case 'download_rework_asset': $assetId = $_POST['asset_id'] ?? ''; $filename = $_POST['filename'] ?? ''; if ($assetId && isset($results['selected_campaign_a5'])) { $assetData = null; if (isset($results['rework_assets'])) { foreach ($results['rework_assets'] as $asset) { if ($asset['asset_id'] === $assetId) { $assetData = $asset; break; } } } $result = downloadAsset($testRunner, $assetId, $filename, $results['selected_campaign_a5']['campaign_id'], $assetData); $results['last_rework_download'] = $result; if ($result['success']) { $success = "Downloaded rework asset: " . $result['filename']; } else { $error = "Download failed: " . $result['error']; } } $currentTab = 'rework'; break; case 'download_all_rework': if (isset($results['rework_assets']) && isset($results['selected_campaign_a5'])) { $downloadResults = downloadAllAssets($testRunner, $results['rework_assets'], $results['selected_campaign_a5']['campaign_id']); $results['rework_bulk_download'] = $downloadResults; $success = "Downloaded {$downloadResults['successful']} of {$downloadResults['total']} rework assets"; } $currentTab = 'rework'; break; case 'update_status_to_a6': if (isset($results['selected_campaign_a5'])) { $statusManager = createStatusManager($testRunner); $statusResult = $statusManager->updateCampaignStatus( $results['selected_campaign_a5']['asset_id'], 'A6' ); if ($statusResult['success']) { $results['status_update_a6'] = $statusResult; $success = "Campaign status updated to A6: Assets to be reworked received by the Agency"; } else { // Extract error details from API response $errorMsg = "Unknown error"; if (isset($statusResult['response']['body'])) { $responseData = json_decode($statusResult['response']['body'], true); if ($responseData && isset($responseData['exception_body'])) { $errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error'; } elseif ($responseData && isset($responseData['error'])) { $errorMsg = $responseData['error']; } } $error = "Failed to update status to A6 (HTTP {$statusResult['http_code']}): {$errorMsg}"; $results['status_update_a6_error'] = $statusResult; } } $currentTab = 'rework'; break; } } catch (Exception $e) { $error = "Action failed: " . $e->getMessage(); } } // Helper Functions function loadCampaignsByStatus($testRunner, $status) { // Search for ALL Local Adaptation campaigns (without status filter in API) // Then let CampaignFormatter filter by status in PHP $statusManager = createStatusManager($testRunner); $response = $statusManager->searchAllCampaigns($testRunner); if ($response['success']) { // Get ALL campaigns first $allCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], []); // Debug: Store all campaigns to see their statuses global $results; $results['debug_all_campaigns_count'] = count($allCampaigns); $results['debug_status_filter'] = $status; // Now filter by status $filteredCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], ['status' => $status]); $results['debug_filtered_count'] = count($filteredCampaigns); return $filteredCampaigns; } return []; } function findMasterAssetsFolder($testRunner, $campaignId, $configV3) { $masterFolderName = $configV3->getFolderName('master_assets'); $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { $name = strtolower($request['name']); if (strpos($name, 'retrieve master asset folder') !== false || strpos($name, 'master asset folder and final') !== false) { $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; $url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$campaignId}/", $url); $url = str_replace('{{baseUrl}}', $configV3->getBaseUrl(), $url); if (is_array($modifiedRequest['request']['url'])) { $modifiedRequest['request']['url']['raw'] = $url; } else { $modifiedRequest['request']['url'] = $url; } $result = $testRunner->runSingleTest($modifiedRequest, $index); if ($result['status'] === 'PASS') { $data = json_decode($result['response']['body'], true); $folders = $data['folder_children']['asset_list'] ?? []; foreach ($folders as $folder) { $folderName = extractFolderName($folder); if (strpos($folderName, 'Master') !== false || $folderName === $masterFolderName) { return $folder['asset_id']; } } } break; } } return null; } function extractFolderName($folder) { $nameFields = [ 'INER_NAME_GENERIC', 'ARTESIA.FIELD.NAME', 'FERRERO.FIELD.CAMPAIGN_NAME', 'ARTESIA.FIELD.TITLE' ]; if (isset($folder['metadata']['metadata_element_list'])) { foreach ($folder['metadata']['metadata_element_list'] as $category) { if (isset($category['metadata_element_list'])) { foreach ($category['metadata_element_list'] as $field) { if (in_array($field['id'], $nameFields) && isset($field['value']['value']['value'])) { return $field['value']['value']['value']; } } } } } return $folder['name'] ?? $folder['title'] ?? 'Unnamed'; } function getAssetsFromFolder($testRunner, $folderId) { $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { $name = strtolower($request['name']); if (strpos($name, 'retrieve all assets from') !== false) { $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; $url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$folderId}/", $url); if (is_array($modifiedRequest['request']['url'])) { $modifiedRequest['request']['url']['raw'] = $url; } else { $modifiedRequest['request']['url'] = $url; } $result = $testRunner->runSingleTest($modifiedRequest, $index); if ($result['status'] === 'PASS') { $data = json_decode($result['response']['body'], true); $assets = $data['folder_children']['asset_list'] ?? []; // Filter out folders, only return files return array_filter($assets, function($asset) { return ($asset['data_type'] ?? '') !== 'CONTAINER'; }); } break; } } return []; } function downloadAsset($testRunner, $assetId, $filename, $campaignId, $assetData = null) { $apiClient = new ApiClient(); $configV3 = new ConfigV3(); $apiClient->setBaseUrl($configV3->getBaseUrl()); // Get OAuth2 token $oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler'); $oauth2Handler->setAccessible(true); $oauth2HandlerInstance = $oauth2Handler->getValue($testRunner); if ($oauth2HandlerInstance) { $apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader()); } $renditionUrl = null; $debugInfo = []; // If we have asset data from folder listing, use it directly if ($assetData) { $debugInfo['using_cached_asset_data'] = true; // Look for rendition URL in asset_content_info from folder listing if (isset($assetData['asset_content_info']['master_content']['url'])) { $renditionUrl = $assetData['asset_content_info']['master_content']['url']; $debugInfo['found_master_content_url'] = true; } elseif (isset($assetData['asset_content_info'][0]['url'])) { $renditionUrl = $assetData['asset_content_info'][0]['url']; $debugInfo['found_array_url'] = true; } elseif (isset($assetData['asset_content_info']['url'])) { $renditionUrl = $assetData['asset_content_info']['url']; $debugInfo['found_direct_url'] = true; } $debugInfo['has_asset_content_info'] = isset($assetData['asset_content_info']); $debugInfo['asset_content_info_type'] = isset($assetData['asset_content_info']) ? gettype($assetData['asset_content_info']) : 'not set'; } // Fallback: Fetch asset metadata if not provided or rendition not found if (!$renditionUrl) { $debugInfo['fetching_from_api'] = true; $metadataRequest = [ 'method' => 'GET', 'url' => "/v6/assets/{$assetId}?load_type=full" ]; $metadataResponse = $apiClient->executeRequest($metadataRequest); if ($metadataResponse['success']) { $fetchedData = json_decode($metadataResponse['body'], true); $asset = $fetchedData['asset'] ?? $fetchedData; if (isset($asset['asset_content_info']['master_content']['url'])) { $renditionUrl = $asset['asset_content_info']['master_content']['url']; } elseif (isset($asset['asset_content_info'][0]['url'])) { $renditionUrl = $asset['asset_content_info'][0]['url']; } elseif (isset($asset['asset_content_info']['url'])) { $renditionUrl = $asset['asset_content_info']['url']; } $debugInfo['api_has_asset_content_info'] = isset($asset['asset_content_info']); } } // Try direct download if no rendition URL found if (!$renditionUrl) { $renditionUrl = "/v6/assets/{$assetId}/contents"; } // Clean up the URL - remove /otmmapi prefix if present (base URL already has it) $renditionUrl = str_replace('/otmmapi/', '/', $renditionUrl); $debugInfo['final_url'] = $renditionUrl; // Try to download - first attempt with original/master rendition $request = [ 'method' => 'GET', 'url' => $renditionUrl ]; $response = $apiClient->executeRequest($request); $attempts = [['url' => $renditionUrl, 'type' => 'original', 'http_code' => $response['http_code']]]; // If original fails and we have asset data, try preview/thumbnail renditions if ($response['success'] && !empty($response['body'])) { $jsonCheck = json_decode($response['body'], true); if ($jsonCheck && isset($jsonCheck['exception_body'])) { // Original failed, try alternative renditions from asset data $alternativeRenditions = []; if ($assetData && isset($assetData['asset_content_info'])) { $debugInfo['asset_content_info_count'] = count($assetData['asset_content_info']); foreach ($assetData['asset_content_info'] as $key => $contentInfo) { if (is_array($contentInfo)) { $rendType = $contentInfo['rendition_type'] ?? $key; $debugInfo['content_info_keys'][] = $key; if (isset($contentInfo['url'])) { // Add ALL renditions, not just preview/thumbnail $alternativeRenditions[] = [ 'url' => str_replace('/otmmapi/', '/', $contentInfo['url']), 'type' => $rendType ]; } } } $debugInfo['alternative_renditions_found'] = count($alternativeRenditions); } // Try alternative renditions foreach ($alternativeRenditions as $altRendition) { $altRequest = ['method' => 'GET', 'url' => $altRendition['url']]; $altResponse = $apiClient->executeRequest($altRequest); $attempts[] = ['url' => $altRendition['url'], 'type' => $altRendition['type'], 'http_code' => $altResponse['http_code']]; if ($altResponse['success'] && !empty($altResponse['body'])) { $altCheck = json_decode($altResponse['body'], true); if (!$altCheck || !isset($altCheck['exception_body'])) { // Success with alternative rendition! $response = $altResponse; $renditionUrl = $altRendition['url']; $debugInfo['used_rendition'] = $altRendition['type']; break; } } } // Still failed after all attempts $finalCheck = json_decode($response['body'], true); if ($finalCheck && isset($finalCheck['exception_body'])) { return [ 'success' => false, 'error' => $finalCheck['exception_body']['message'] ?? 'File not found in storage', 'http_code' => $finalCheck['exception_body']['http_response_code'] ?? 500, 'debug_message' => $finalCheck['exception_body']['debug_message'] ?? '', 'tried_url' => $renditionUrl, 'debug_info' => $debugInfo, 'all_attempts' => $attempts ]; } } $downloadPath = $configV3->getDownloadPath($campaignId); if (!is_dir($downloadPath)) { mkdir($downloadPath, 0755, true); } $safeFilename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename ?: "asset_{$assetId}"); $fullPath = $downloadPath . '/' . $safeFilename; $bytesWritten = file_put_contents($fullPath, $response['body']); return [ 'success' => $bytesWritten !== false, 'filename' => $safeFilename, 'filepath' => $fullPath, 'size' => $bytesWritten, 'asset_id' => $assetId, 'download_method' => 'rendition', 'rendition_url' => $renditionUrl ]; } return [ 'success' => false, 'error' => $response['error'] ?? 'Download failed', 'http_code' => $response['http_code'], 'tried_url' => $renditionUrl ]; } function downloadAllAssets($testRunner, $assets, $campaignId) { $results = [ 'total' => count($assets), 'successful' => 0, 'failed' => 0, 'details' => [] ]; foreach ($assets as $asset) { $filename = extractFolderName($asset); $result = downloadAsset($testRunner, $asset['asset_id'], $filename, $campaignId); if ($result['success']) { $results['successful']++; } else { $results['failed']++; } $results['details'][] = $result; } return $results; } function createStatusManager($testRunner) { $apiClient = new ApiClient(); $configV3 = new ConfigV3(); $apiClient->setBaseUrl($configV3->getBaseUrl()); $oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler'); $oauth2Handler->setAccessible(true); $oauth2HandlerInstance = $oauth2Handler->getValue($testRunner); if ($oauth2HandlerInstance) { $apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader()); } return new StatusManager($apiClient); } function findUploadFolder($testRunner, $campaignId, $configV3) { $finalFolderName = $configV3->getFolderName('final_assets'); $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { $name = strtolower($request['name']); if (strpos($name, 'retrieve master asset folder') !== false || strpos($name, 'master asset folder and final') !== false) { $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; $url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$campaignId}/", $url); $url = str_replace('{{baseUrl}}', $configV3->getBaseUrl(), $url); if (is_array($modifiedRequest['request']['url'])) { $modifiedRequest['request']['url']['raw'] = $url; } else { $modifiedRequest['request']['url'] = $url; } $result = $testRunner->runSingleTest($modifiedRequest, $index); if ($result['status'] === 'PASS') { $data = json_decode($result['response']['body'], true); $folders = $data['folder_children']['asset_list'] ?? []; foreach ($folders as $folder) { $folderName = extractFolderName($folder); // Look for Final Assets or Localized folder if (strpos($folderName, 'Final') !== false || strpos($folderName, 'Localized') !== false || $folderName === $finalFolderName) { return $folder['asset_id']; } } } break; } } return null; } function uploadFiles($testRunner, $uploadedFiles, $folderId, $masterAssetsMetadata = null) { $apiClient = new ApiClient(); $configV3 = new ConfigV3(); $apiClient->setBaseUrl($configV3->getBaseUrl()); $oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler'); $oauth2Handler->setAccessible(true); $oauth2HandlerInstance = $oauth2Handler->getValue($testRunner); if ($oauth2HandlerInstance) { $apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader()); } $uploader = new AssetUploader($apiClient, $folderId); $results = [ 'total' => 0, 'successful' => 0, 'failed' => 0, 'details' => [] ]; // Handle multiple file upload if (isset($uploadedFiles['tmp_name'])) { $fileCount = is_array($uploadedFiles['tmp_name']) ? count($uploadedFiles['tmp_name']) : 1; $results['total'] = $fileCount; for ($i = 0; $i < $fileCount; $i++) { $tmpName = is_array($uploadedFiles['tmp_name']) ? $uploadedFiles['tmp_name'][$i] : $uploadedFiles['tmp_name']; $fileName = is_array($uploadedFiles['name']) ? $uploadedFiles['name'][$i] : $uploadedFiles['name']; $fileError = is_array($uploadedFiles['error']) ? $uploadedFiles['error'][$i] : $uploadedFiles['error']; if ($fileError !== UPLOAD_ERR_OK) { $results['details'][] = [ 'success' => false, 'filename' => $fileName, 'error' => 'Upload error code: ' . $fileError ]; $results['failed']++; continue; } // Extract metadata from master asset if available $assetMetadata = null; if ($masterAssetsMetadata && is_array($masterAssetsMetadata)) { // Try to find matching master asset by filename or use first one $assetMetadata = $masterAssetsMetadata[0]['metadata'] ?? null; } $result = $uploader->uploadFile($tmpName, $folderId, [], $assetMetadata); if ($result['success']) { $results['successful']++; } else { $results['failed']++; } $results['details'][] = $result; } } return $results; } $oauth2Status = $testRunner ? $testRunner->getOAuth2Status() : null; $envInfo = $configV3->getEnvironmentInfo(); ?> Content Scaling Workflow V3

đŸŽ¯ Content Scaling Workflow V3

Status-based workflow management for Ferrero DAM

Environment: ()
Base URL:
❌ Error:
✅ Success:
- Expires:

đŸ“Ĩ Download Workflow: A1 → A2

Load campaigns with status A1, download master assets, and update status to A2

🔍 Debug Results: Found Campaigns

OAuth Status: | Expires:

API Response: HTTP - Service Unavailable (Server may be down or OAuth token expired)
Total results from API:
URL:

View Response Body

Showing ALL campaigns without status filter to see their metadata fields:

$campaign): ?>
Campaign : () - Content Scaling Status:

Asset ID:

Campaign ID:

Content Scaling Status:

Brand:

Market:

View Full Raw Metadata

No campaigns returned from API (check OAuth status and response body above)

🔍 Debug Info:
Found total campaigns before filtering
Filtering for Content Scaling Status: ""
Campaigns after filtering:

Found Campaigns

Campaign ID:

Asset ID:

Brand:

Market:

Content Scaling Status: - Ready for Localization

Master Assets ( files)

$asset): ?>

ID:
Type: | Size: bytes

âš ī¸ Update Status to A2

Once all assets are downloaded (or attempted), update the campaign status to A2 (Selected Master Assets sent to Agency)

Note: If files don't exist in storage (test environment), you can still update the status to test the workflow progression.

âš ī¸ Status Update Debug Information:
View detailed error information
HTTP Status Code:
Folder ID:
Target Status:
API Response Body:
Request URL:
✅ Download Successful:
Size: bytes | Path:
Method: | URL: ❌ Download Failed:
HTTP Code:
Tried URL:
Details:
Debug:
View all download attempts ()
$att): ?>
. [] - HTTP
Bulk Download Results: of assets downloaded successfully 0): ?>
files failed (may not exist in storage)

📤 Upload Workflow: A2 → A3

Load campaigns with status A2 (assets sent to agency), upload processed files, and update status to A3

Found Campaigns

Campaign ID:

Asset ID:

Brand:

Market:

Content Scaling Status: - Assets Sent to Agency

Selected Campaign: ()
✅ Upload target folder found

Upload Processed Files

✅ Master asset metadata detected - uploads will inherit metadata from downloaded assets
â„šī¸ Note: For best results, complete the full workflow in one session: Download (A1) → Update to A2 → Upload (A2)
This preserves master asset metadata for the uploaded files.

Accepted formats: Images (JPG, PNG, GIF, TIFF), Documents (PDF, AI, PSD, EPS), Video (MOV, MP4, AVI), Archives (ZIP), Office (DOC, XLS, TXT)

Upload Results: of files uploaded successfully
View upload details
$detail): ?>
✅
Asset ID: ❌
Error:
HTTP Code:
View API Response
0): ?>

✅ Update Status to A3

Files have been uploaded. Update the campaign status to A3 (Localized Asset received from Agency)

🔄 Rework Workflow: A5 → A6

Load campaigns with status A5 (rework needed), download assets for rework, and update status to A6

Found Campaigns Needing Rework

Campaign ID:

Asset ID:

Brand:

Market:

Content Scaling Status: - Rework Needed

Selected Campaign: ()

Rework Assets ( files)

$asset): ?>

ID:
Type: | Size: bytes

âš ī¸ Update Status to A6

Once rework assets are downloaded, update the campaign status to A6 (Assets to be reworked received by the Agency)

✅ Download Successful:
Size: bytes ❌ Download Failed:
Bulk Download Results: of rework assets downloaded