$_SESSION['baseUrl'] ?? '', 'apiKey' => $_SESSION['apiKey'] ?? '', 'timeout' => 180, // Increase to 3 minutes 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ] ]; $collectionPath = __DIR__ . '/Content Scaling Flow.postman_collection_Oliver(New).json'; if (!file_exists($collectionPath)) { $collectionPath = __DIR__ . '/Content Scaling Flow_Oliver.Postman_Collection.json'; } $testRunner = null; $error = null; $actionableCampaigns = []; $selectedCampaign = null; $workflowStep = $_GET['step'] ?? 1; $workflowResults = []; $campaignFilters = []; $availableFilters = []; $allCampaignsData = null; try { if (file_exists($collectionPath)) { $testRunner = new TestRunner($collectionPath, $config); } else { $error = "Postman collection file not found"; } } catch (Exception $e) { $error = "Error initializing test runner: " . $e->getMessage(); } // Handle form submissions if ($_POST && $testRunner) { if ($_POST['action'] === 'update_config') { $_SESSION['baseUrl'] = $_POST['baseUrl'] ?? ''; $_SESSION['apiKey'] = $_POST['apiKey'] ?? ''; $config['baseUrl'] = $_SESSION['baseUrl']; $config['apiKey'] = $_SESSION['apiKey']; $testRunner->updateConfig($config); $message = "Configuration updated successfully"; } if ($_POST['action'] === 'load_campaigns') { // Step 1: Load campaigns $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { if (strpos($request['name'], 'Retrieve Localized Campaign Folders') !== false) { $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; // Use the original "Local Adaptation" search from Postman collection // This gives us the reliable 14 campaigns we know work // Replace {{baseUrl}} $baseUrl = 'https://ppr.dam.ferrero.com/otmmapi'; $url = str_replace('{{baseUrl}}', $baseUrl, $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') { $allCampaignsData = $result['response']['body']; $actionableCampaigns = CampaignFormatter::getActionableCampaigns($allCampaignsData); $workflowStep = 1; } else { // Try to recover partial response if we got data $responseBody = $result['response']['body'] ?? ''; if (!empty($responseBody) && strlen($responseBody) > 1000) { $dataSize = number_format(strlen($responseBody)); $message = "⚠️ Timeout occurred but received {$dataSize} bytes of data. Attempting recovery..."; // Save the partial response for analysis file_put_contents(__DIR__ . '/partial_response.json', $responseBody); // Advanced JSON recovery $fixedJson = $responseBody; // Try to find where the JSON breaks and truncate to last complete object $lastCompletePos = strrpos($fixedJson, '"}},{"type":"com.artesia'); if ($lastCompletePos !== false) { $fixedJson = substr($fixedJson, 0, $lastCompletePos + 3); // Keep the "} } // Add missing closing brackets $openBraces = substr_count($fixedJson, '{') - substr_count($fixedJson, '}'); $openBrackets = substr_count($fixedJson, '[') - substr_count($fixedJson, ']'); for ($i = 0; $i < $openBrackets; $i++) { $fixedJson .= ']'; } for ($i = 0; $i < $openBraces; $i++) { $fixedJson .= '}'; } $partialData = json_decode($fixedJson, true); if ($partialData && isset($partialData['search_result_resource'])) { $allCampaignsData = $fixedJson; $_SESSION['all_campaigns_data'] = $allCampaignsData; $availableFilters = CampaignFormatter::getAvailableFilterOptions($allCampaignsData); $actionableCampaigns = CampaignFormatter::getActionableCampaigns($allCampaignsData); $workflowStep = 1; $assetCount = count($partialData['search_result_resource']['asset_list'] ?? []); $message .= " ✅ Successfully recovered {$assetCount} campaigns from partial data! (Saved to partial_response.json)"; } else { $error = "Timeout: Received {$dataSize} bytes but couldn't parse as valid JSON. Try 'Load Filtered Campaigns' for smaller dataset."; } } else { $error = "Failed to load campaigns: " . ($result['response']['error'] ?? 'Unknown error'); } } break; } } } if ($_POST['action'] === 'select_campaign' && !empty($_POST['selected_campaign_id'])) { // Store selected campaign and move to step 2 $_SESSION['selected_campaign_id'] = $_POST['selected_campaign_id']; $_SESSION['actionable_campaigns'] = $_POST['campaigns_data'] ?? ''; $workflowStep = 2; } if ($_POST['action'] === 'get_folders') { // Step 2: Get Master Asset and Final Asset folders $campaignId = $_SESSION['selected_campaign_id'] ?? ''; if ($campaignId) { $workflowResults['folders'] = getAssetFolders($testRunner, $campaignId); $workflowStep = 2; } } if ($_POST['action'] === 'test_token') { // Test OAuth2 token and connection $tokenStatus = $testRunner->getOAuth2Status(); if ($tokenStatus['enabled'] && ($tokenStatus['has_token'] ?? false)) { // Test with a simple API call $testResult = $testRunner->testConnection('https://ppr.dam.ferrero.com/otmmapi/v6/users/current'); if ($testResult['success']) { $message = "✅ OAuth2 token is working. Connection successful."; } else { $error = "❌ OAuth2 token may be expired or invalid. Error: " . ($testResult['error'] ?? 'Connection failed'); } } else { $error = "❌ OAuth2 token not available or expired"; } } if ($_POST['action'] === 'back_to_step1') { // Clear session and go back to step 1 unset($_SESSION['selected_campaign_id']); unset($_SESSION['actionable_campaigns']); unset($_SESSION['master_folder_id']); $workflowStep = 1; $actionableCampaigns = []; $selectedCampaign = null; $workflowResults = []; } if ($_POST['action'] === 'get_assets') { // Step 3: Get assets from Master Asset folder $folderId = $_POST['master_folder_id'] ?? ''; if ($folderId) { $workflowResults['assets'] = getAssetsFromFolder($testRunner, $folderId); $_SESSION['master_folder_id'] = $folderId; $workflowStep = 3; } } if ($_POST['action'] === 'peek_folder') { // Peek inside folder to see what's there $folderId = $_POST['peek_folder_id'] ?? ''; if ($folderId) { $workflowResults['peek'] = getAssetsFromFolder($testRunner, $folderId); $workflowStep = 2; // Stay on step 2 but show peek results } } } // Load saved data from session if (isset($_SESSION['selected_campaign_id']) && !empty($_SESSION['actionable_campaigns'])) { $actionableCampaigns = json_decode($_SESSION['actionable_campaigns'], true) ?: []; $selectedCampaignId = $_SESSION['selected_campaign_id']; foreach ($actionableCampaigns as $campaign) { if ($campaign['asset_id'] === $selectedCampaignId) { $selectedCampaign = $campaign; break; } } } function getAssetFolders($testRunner, $campaignId) { $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { $name = strtolower($request['name']); if (strpos($name, 'master asset folder') !== false && strpos($name, 'final asset') !== false) { // Modify the request URL to use the specific campaign ID $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; // Replace placeholder with actual campaign ID $url = str_replace('6930c59abea5bd4259b67f7647f65cd01d36278d', $campaignId, $url); // Replace {{baseUrl}} with the actual base URL $baseUrl = 'https://ppr.dam.ferrero.com/otmmapi'; $url = str_replace('{{baseUrl}}', $baseUrl, $url); // If still relative, prepend base URL if (!preg_match('/^https?:\/\//', $url)) { $url = rtrim($baseUrl, '/') . '/' . ltrim($url, '/'); } if (is_array($modifiedRequest['request']['url'])) { $modifiedRequest['request']['url']['raw'] = $url; } else { $modifiedRequest['request']['url'] = $url; } return $testRunner->runSingleTest($modifiedRequest, $index); } } return ['status' => 'ERROR', 'message' => 'Asset folders request not found']; } function getAssetsFromFolder($testRunner, $folderId) { $requests = $testRunner->getAvailableRequests(); foreach ($requests as $index => $request) { $name = strtolower($request['name']); if (strpos($name, 'all assets from') !== false) { // Modify the request URL to use the specific folder ID $modifiedRequest = $request; $url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url']; // Replace placeholder with actual folder ID - need to find the right pattern $url = preg_replace('/folders\/[^\/]+\//', "folders/{$folderId}/", $url); // Replace {{baseUrl}} with the actual base URL $baseUrl = 'https://ppr.dam.ferrero.com/otmmapi'; $url = str_replace('{{baseUrl}}', $baseUrl, $url); // If still relative, prepend base URL if (!preg_match('/^https?:\/\//', $url)) { $url = rtrim($baseUrl, '/') . '/' . ltrim($url, '/'); } if (is_array($modifiedRequest['request']['url'])) { $modifiedRequest['request']['url']['raw'] = $url; } else { $modifiedRequest['request']['url'] = $url; } return $testRunner->runSingleTest($modifiedRequest, $index); } } return ['status' => 'ERROR', 'message' => 'Assets request not found']; } $oauth2Status = $testRunner ? $testRunner->getOAuth2Status() : null; $credentials = $testRunner ? $testRunner->getCredentials() : []; ?> Content Scaling Workflow

🎯 Content Scaling Workflow

Multi-step process to retrieve and download campaign assets

1
Select Campaign
2
Get Folders
3
Get Assets
4
Download
Error:

API Configuration

✅ OAuth2 Token Active - Expires:
❌ OAuth2 Token Issue
Client ID:

📋 Step 1: Load and Filter Campaigns

Load all campaigns and filter by stage, type, brand, or market

Info: This will load campaigns using the original "Local Adaptation" search from your Postman collection. These are the 14 reliable campaigns we've been working with.
Found "Local Adaptation" campaigns

Campaign ID:

Full Name:

Brand:

Market:

Asset ID:

📁 Step 2: Retrieve Asset Folders

Selected Campaign:
Campaign ID:
Asset ID:

Folders Request Result:

Status:

HTTP Code:

URL:

Debug - Response Structure:"; echo "
"; echo "Response keys: " . implode(', ', array_keys($foldersData ?? [])) . "
"; if (isset($foldersData['folder_children']['asset_list'])) { echo "Folder children count: " . count($foldersData['folder_children']['asset_list']) . "
"; echo "All folder names found: "; $allNames = []; foreach ($foldersData['folder_children']['asset_list'] as $item) { // Try to extract name from metadata $name = 'Unnamed'; if (isset($item['metadata']['metadata_element_list'])) { foreach ($item['metadata']['metadata_element_list'] as $category) { if (isset($category['metadata_element_list'])) { foreach ($category['metadata_element_list'] as $field) { if ($field['id'] === 'FERRERO.FIELD.CAMPAIGN_NAME' || $field['id'] === 'ARTESIA.FIELD.NAME') { if (isset($field['value']['value']['value'])) { $name = $field['value']['value']['value']; break 2; } } } } } } if ($name === 'Unnamed') { $name = $item['name'] ?? $item['asset_id'] ?? 'Unknown'; } $allNames[] = '"' . $name . '"'; } echo implode(', ', $allNames) . "
"; } echo "
"; echo "
"; echo "

💡 Troubleshooting Missing Master Assets Folder:

"; echo "

Only seeing Final Assets folder? The Master Assets folder might be:

"; echo "
    "; echo "
  • In a parent/sibling folder: Navigate to campaign root and look for other folders
  • "; echo "
  • Named differently: Could be 'Source', 'Originals', 'Raw Assets', or numbered like '00. Master Assets'
  • "; echo "
  • Empty campaign: This campaign might not have source assets yet
  • "; echo "
  • Different structure: Some campaigns organize assets differently
  • "; echo "
"; echo "

Suggestions:

"; echo "
    "; echo "
  • Try exploring the Final Assets folder - it might contain both source and final assets
  • "; echo "
  • Go back and try a different campaign that might have both folders
  • "; echo "
  • Check if there are more folders not showing in this response
  • "; echo "
"; echo "
"; // Try multiple possible structures $folders = []; if (isset($foldersData['folder_children']['asset_list'])) { $folders = $foldersData['folder_children']['asset_list']; } elseif (isset($foldersData['items'])) { $folders = $foldersData['items']; } elseif (isset($foldersData['search_result_resource']['asset_list'])) { $folders = $foldersData['search_result_resource']['asset_list']; } elseif (isset($foldersData['asset_list'])) { $folders = $foldersData['asset_list']; } ?>

Found Folders ():

No folders found in the expected data structures.
View Raw Response
...
Folder:
Asset ID:
Type:
Created:
📁 MASTER ASSET FOLDER
📤 FINAL ASSET FOLDER
(Might contain source assets too) 📂 FOLDER
(Could be source or target folder - check contents)
Detected patterns: Source/Master Final/Output Generic | Name: ""

❌ Request Failed

Error:

Troubleshooting Tips:
  • Timeout Issue: The API is taking too long to respond
  • Network: Check internet connection
  • Token: OAuth2 token may have expired - try the "Test OAuth2 Token" button
  • API Load: Server might be busy - wait a minute and try again
Quick Fixes:

🔍 Peek Inside Folder Results:

Status:

HTTP Code:

📊 Quick Analysis:

Total Items Found:

📁 Subfolders:

📄 Assets:

File Types Found:

    $count): ?>
  • ()
🎯 Recommendation: 0): ?> ✅ This folder contains assets - proceed with "View Final Assets" 0): ?> 📁 This folder contains subfolders - assets might be nested deeper ❌ This folder appears empty - try a different campaign

No assets or subfolders found in this folder.

Error:

📄 Step 3: Master Asset Folder Contents

Assets Request Result:

Status:

HTTP Code:

URL:

Found Assets:

$asset): ?>
Asset :
ID:
Type:
File Type:
Size: bytes

Error: