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 '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; $success = "Downloaded {$downloadResults['successful']} of {$downloadResults['total']} assets"; } 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 { $error = "Failed to update status: " . ($statusResult['response']['error'] ?? 'Unknown error'); } } 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 'load_campaigns_a5': $results['a5_campaigns'] = loadCampaignsByStatus($testRunner, 'A5'); $success = "Loaded " . count($results['a5_campaigns']) . " campaigns with status A5"; $currentTab = 'rework'; break; } } catch (Exception $e) { $error = "Action failed: " . $e->getMessage(); } } // Helper Functions function loadCampaignsByStatus($testRunner, $status) { $statusManager = createStatusManager($testRunner); $response = $statusManager->searchCampaignsByStatus($status); if ($response['success']) { $data = json_decode($response['body'], true); return CampaignFormatter::getActionableCampaigns($response['body'], ['status' => $status]); } 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); } $oauth2Status = $testRunner ? $testRunner->getOAuth2Status() : null; $envInfo = $configV3->getEnvironmentInfo(); ?>
Status-based workflow management for Ferrero DAM
Load campaigns with status A1, download master assets, and update status to A2
Campaign ID: = htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?>
Asset ID: = htmlspecialchars($campaign['asset_id']) ?>
Brand: = htmlspecialchars($campaign['brand'] ?? 'N/A') ?>
Market: = htmlspecialchars($campaign['market'] ?? 'N/A') ?>
A1 - Ready for Localization
= htmlspecialchars($results['selected_campaign']['asset_id']) ?>
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.
Load campaigns with status A2, upload processed assets, and update status to A3
Load campaigns with status A5 (rework needed), download assets for rework, and update status to A6