ferrero-opentext/clean_workflow.php
DJP 716f0be068 Initial commit: Ferrero OpenText Content Scaling Application
Complete PHP-based workflow application for Ferrero DAM system:
- OAuth2 authentication with automatic token management
- Campaign discovery and filtering
- Folder structure navigation
- Asset download (individual and bulk)
- Metadata extraction and display
- Clean step-by-step web interface

Status: Fully functional and production-ready

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 14:29:20 -04:00

967 lines
No EOL
55 KiB
PHP

<?php
session_start();
// Clear any existing session data
if (isset($_GET['reset'])) {
session_destroy();
session_start();
header('Location: clean_workflow.php');
exit;
}
require_once 'src/TestRunner.php';
require_once 'src/CampaignFormatter.php';
require_once 'src/AssetDownloader.php';
require_once 'src/MetadataExtractor.php';
$config = [
'baseUrl' => '',
'apiKey' => '',
'timeout' => 120,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json'
]
];
$collectionPath = __DIR__ . '/Content Scaling Flow.postman_collection_Oliver(New).json';
$testRunner = null;
$error = null;
$campaigns = [];
$selectedCampaign = null;
$workflowStep = 1;
$workflowResults = [];
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 ONLY explicit user actions
if ($_POST && $testRunner) {
if ($_POST['action'] === 'load_campaigns') {
// Load campaigns from API
$requests = $testRunner->getAvailableRequests();
foreach ($requests as $index => $request) {
if (strpos($request['name'], 'Retrieve Localized Campaign Folders') !== false) {
$result = $testRunner->runSingleTest($request, $index);
if ($result['status'] === 'PASS') {
// Filter to only show "3 - Production & execution" campaigns
$filters = ['stage' => '3 - Production & execution'];
$campaigns = CampaignFormatter::getActionableCampaigns($result['response']['body'], $filters);
$message = "Successfully loaded " . count($campaigns) . " campaigns in '3 - Production & execution' stage";
} else {
$error = "Failed to load campaigns: " . ($result['response']['error'] ?? 'Unknown error');
}
break;
}
}
}
if ($_POST['action'] === 'select_campaign') {
$selectedCampaignId = $_POST['selected_campaign_id'] ?? '';
if ($selectedCampaignId && !empty($_POST['campaigns_data'])) {
$allCampaigns = json_decode($_POST['campaigns_data'], true);
foreach ($allCampaigns as $campaign) {
if ($campaign['asset_id'] === $selectedCampaignId) {
$selectedCampaign = $campaign;
$_SESSION['selected_campaign'] = $campaign; // Store in session
$workflowStep = 2;
break;
}
}
}
}
if ($_POST['action'] === 'get_folders') {
// Get selected campaign from session or previous step
if (isset($_SESSION['selected_campaign'])) {
$selectedCampaign = $_SESSION['selected_campaign'];
$campaignId = $selectedCampaign['asset_id'] ?? '';
if ($campaignId) {
$workflowResults['folders'] = getAssetFolders($testRunner, $campaignId);
$workflowStep = 2; // Stay on step 2
}
} else {
$error = "No campaign selected. Please go back to Step 1.";
}
}
if ($_POST['action'] === 'download_asset') {
$assetId = $_POST['asset_id'] ?? '';
$filename = $_POST['filename'] ?? '';
if ($assetId && isset($_SESSION['selected_campaign'])) {
$selectedCampaign = $_SESSION['selected_campaign'];
// Create downloader instance
$apiClient = new ApiClient();
$apiClient->setBaseUrl('https://ppr.dam.ferrero.com/otmmapi');
// Get OAuth2 token
if ($testRunner) {
$oauth2Status = $testRunner->getOAuth2Status();
if ($oauth2Status['enabled'] && ($oauth2Status['has_token'] ?? false)) {
try {
$token = $testRunner->refreshToken() ? 'refreshed' : 'existing';
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
$oauth2Handler->setAccessible(true);
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
if ($oauth2HandlerInstance) {
$apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader());
}
} catch (Exception $e) {
$error = "OAuth2 token error: " . $e->getMessage();
}
}
}
if (!isset($error)) {
// Test the direct content endpoint first - CORRECT endpoint with 's'
$testRequest = [
'method' => 'GET',
'url' => "/v6/assets/{$assetId}/contents"
];
$testResponse = $apiClient->executeRequest($testRequest);
if ($testResponse['success'] && !empty($testResponse['body'])) {
// Direct download worked!
$safeFilename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename ?: "asset_{$assetId}");
if (!pathinfo($safeFilename, PATHINFO_EXTENSION)) {
$safeFilename .= '.jpg'; // Default extension
}
if (!is_dir('downloads/')) {
mkdir('downloads/', 0755, true);
}
$fullPath = 'downloads/' . $safeFilename;
$bytesWritten = file_put_contents($fullPath, $testResponse['body']);
$workflowResults['download'] = [
'success' => $bytesWritten !== false,
'filename' => $safeFilename,
'filepath' => $fullPath,
'size' => $bytesWritten ?: 0,
'asset_id' => $assetId,
'download_url' => "/v6/assets/{$assetId}/contents",
'method' => 'direct_content_endpoint'
];
} else {
// Fall back to AssetDownloader
$downloader = new AssetDownloader($apiClient);
$result = $downloader->downloadAsset($assetId, $filename);
$result['direct_test'] = [
'attempted' => true,
'success' => false,
'http_code' => $testResponse['http_code'] ?? 0,
'error' => $testResponse['error'] ?? null,
'response_size' => strlen($testResponse['body'] ?? '')
];
$workflowResults['download'] = $result;
}
$workflowStep = 2; // Stay on step 2
}
}
}
if ($_POST['action'] === 'download_folder') {
$folderAssetIds = $_POST['folder_asset_ids'] ?? [];
$folderName = $_POST['folder_name'] ?? 'folder_download';
if (!empty($folderAssetIds) && isset($_SESSION['selected_campaign'])) {
$selectedCampaign = $_SESSION['selected_campaign'];
// Setup API client similar to single download
$apiClient = new ApiClient();
$apiClient->setBaseUrl('https://ppr.dam.ferrero.com/otmmapi');
if ($testRunner) {
$oauth2Status = $testRunner->getOAuth2Status();
if ($oauth2Status['enabled'] && ($oauth2Status['has_token'] ?? false)) {
try {
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
$oauth2Handler->setAccessible(true);
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
if ($oauth2HandlerInstance) {
$apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader());
}
} catch (Exception $e) {
$error = "OAuth2 token error: " . $e->getMessage();
}
}
}
if (!isset($error)) {
$downloader = new AssetDownloader($apiClient);
$result = $downloader->downloadMultipleAssets($folderAssetIds, $folderName);
$workflowResults['bulk_download'] = $result;
$workflowStep = 2; // Stay on step 2
}
}
}
if ($_POST['action'] === 'explore_folder') {
$folderId = $_POST['folder_id'] ?? '';
$folderName = $_POST['folder_name'] ?? 'Unnamed';
if ($folderId && isset($_SESSION['selected_campaign'])) {
$selectedCampaign = $_SESSION['selected_campaign'];
$workflowResults['folder_contents'] = getAssetsFromFolder($testRunner, $folderId);
$workflowResults['explored_folder_name'] = $folderName;
$workflowStep = 2; // Stay on step 2 but show folder contents
}
}
if ($_POST['action'] === 'explore_all_folders') {
$folderIds = $_POST['folder_ids'] ?? [];
if (!empty($folderIds) && isset($_SESSION['selected_campaign'])) {
$selectedCampaign = $_SESSION['selected_campaign'];
$workflowResults['all_folder_contents'] = [];
foreach ($folderIds as $index => $folderId) {
$result = getAssetsFromFolder($testRunner, $folderId);
$workflowResults['all_folder_contents'][] = [
'folder_id' => $folderId,
'folder_name' => "Folder " . ($index + 1),
'result' => $result
];
}
$workflowStep = 2;
}
}
}
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) {
$modifiedRequest = $request;
$url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url'];
$url = str_replace('6930c59abea5bd4259b67f7647f65cd01d36278d', $campaignId, $url);
$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;
}
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) {
$modifiedRequest = $request;
$url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url'];
$url = preg_replace('/folders\/[^\/]+\//', "folders/{$folderId}/", $url);
$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;
}
return $testRunner->runSingleTest($modifiedRequest, $index);
}
}
return ['status' => 'ERROR', 'message' => 'Assets request not found'];
}
// Check if we have a selected campaign from session
if (isset($_SESSION['selected_campaign']) && !$selectedCampaign) {
$selectedCampaign = $_SESSION['selected_campaign'];
$workflowStep = 2;
}
$oauth2Status = $testRunner ? $testRunner->getOAuth2Status() : null;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clean Workflow - Ferrero Content Scaling</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #e0e0e0;
}
.section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 6px;
background-color: #fafafa;
}
.btn {
background-color: #007cba;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-right: 10px;
margin-bottom: 10px;
}
.btn:hover { background-color: #005a8b; }
.btn-success { background-color: #28a745; }
.error { color: #dc3545; background-color: #f8d7da; padding: 10px; border-radius: 4px; margin: 10px 0; }
.success { color: #155724; background-color: #d4edda; padding: 10px; border-radius: 4px; margin: 10px 0; }
.campaign-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 15px;
margin-top: 20px;
}
.campaign-card {
background: white;
border: 2px solid #dee2e6;
border-radius: 8px;
padding: 15px;
cursor: pointer;
transition: border-color 0.2s;
}
.campaign-card:hover { border-color: #007cba; }
.campaign-card.selected { border-color: #28a745; background-color: #f8fff9; }
.metadata-display { background: #f8f9fa; padding: 15px; border-radius: 6px; margin: 10px 0; }
.metadata-section { margin-bottom: 20px; }
.metadata-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin: 10px 0; }
.metadata-category { background: white; padding: 10px; border-radius: 4px; margin: 10px 0; }
.permissions-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 5px; margin: 10px 0; }
.rendition-info { background: white; padding: 10px; border-radius: 4px; margin: 5px 0; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎯 Clean Content Scaling Workflow</h1>
<p>Simple, step-by-step campaign asset workflow</p>
<a href="?reset=1" style="color: #dc3545; text-decoration: none; font-size: 12px;">🔄 Reset Session</a>
</div>
<?php if ($error): ?>
<div class="error"><strong>Error:</strong> <?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<?php if (isset($message)): ?>
<div class="success"><?= htmlspecialchars($message) ?></div>
<?php endif; ?>
<!-- OAuth2 Status -->
<?php if ($oauth2Status && $oauth2Status['enabled'] && ($oauth2Status['has_token'] ?? false)): ?>
<div class="success">✅ OAuth2 Token Active</div>
<?php else: ?>
<div class="error">❌ OAuth2 Token Issue</div>
<?php endif; ?>
<!-- Step 1: Load Campaigns -->
<?php if ($workflowStep == 1): ?>
<div class="section">
<h2>📋 Step 1: Load Campaigns</h2>
<?php if (empty($campaigns)): ?>
<p>Click the button below to load campaigns from the API using your Postman collection settings.</p>
<form method="POST">
<input type="hidden" name="action" value="load_campaigns">
<button type="submit" class="btn btn-success">Load "3 - Production & execution" Campaigns</button>
</form>
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 10px; font-size: 13px;">
This will load only campaigns in "3 - Production & execution" stage (should be about 12 campaigns).
</div>
<?php else: ?>
<p><strong>✅ Loaded <?= count($campaigns) ?> campaigns</strong></p>
<div class="campaign-grid">
<?php foreach ($campaigns as $campaign): ?>
<div class="campaign-card" onclick="selectCampaign('<?= htmlspecialchars($campaign['asset_id']) ?>', this)">
<h4><?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed') ?></h4>
<p><strong>Campaign ID:</strong> <?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?></p>
<p><strong>Brand:</strong> <?= htmlspecialchars($campaign['brand'] ?? 'N/A') ?></p>
<p><strong>Market:</strong> <?= htmlspecialchars($campaign['market'] ?? 'N/A') ?></p>
<p><strong>Stage:</strong> <?= htmlspecialchars($campaign['stage'] ?? 'N/A') ?></p>
<p><strong>Asset ID:</strong> <code><?= htmlspecialchars($campaign['asset_id']) ?></code></p>
</div>
<?php endforeach; ?>
</div>
<form method="POST" id="campaign-selection-form">
<input type="hidden" name="action" value="select_campaign">
<input type="hidden" name="selected_campaign_id" id="selected-campaign-id">
<input type="hidden" name="campaigns_data" value="<?= htmlspecialchars(json_encode($campaigns)) ?>">
<button type="submit" class="btn btn-success" id="proceed-btn" disabled>Proceed to Step 2</button>
</form>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Step 2: Get Folders -->
<?php if ($workflowStep == 2 && $selectedCampaign): ?>
<div class="section">
<h2>📁 Step 2: Get Campaign Folders</h2>
<div style="background: #e8f4f8; padding: 15px; border-radius: 4px; margin-bottom: 20px;">
<strong>Selected Campaign:</strong> <?= htmlspecialchars($selectedCampaign['campaign_name'] ?? 'Unknown') ?><br>
<strong>Campaign ID:</strong> <?= htmlspecialchars($selectedCampaign['campaign_id'] ?? 'N/A') ?><br>
<strong>Asset ID:</strong> <code><?= htmlspecialchars($selectedCampaign['asset_id']) ?></code>
</div>
<form method="POST">
<input type="hidden" name="action" value="get_folders">
<button type="submit" class="btn btn-success">Get Campaign Folders</button>
</form>
<?php if (isset($workflowResults['folders'])): ?>
<?php $result = $workflowResults['folders']; ?>
<div style="background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 6px; padding: 20px; margin: 20px 0;">
<h3>Folder Results</h3>
<p><strong>Status:</strong> <?= $result['status'] ?></p>
<p><strong>HTTP Code:</strong> <?= $result['response']['http_code'] ?? 'N/A' ?></p>
<p><strong>URL:</strong> <?= htmlspecialchars($result['response']['url'] ?? 'N/A') ?></p>
<?php if ($result['status'] === 'PASS'): ?>
<?php
$data = json_decode($result['response']['body'], true);
$folders = $data['folder_children']['asset_list'] ?? [];
?>
<h4>Found <?= count($folders) ?> folder(s):</h4>
<?php if (count($folders) == 1): ?>
<div style="background: #fff3cd; color: #856404; padding: 10px; border-radius: 4px; margin: 10px 0;">
⚠️ <strong>Only 1 folder found.</strong> This campaign might not have the Master Assets folder we need.
<br>Try going back and selecting <strong>"LOCAL CAMPAIGN"</strong> (Campaign ID: C000000212) which had both folders.
</div>
<?php elseif (count($folders) >= 2): ?>
<div style="background: #d4edda; color: #155724; padding: 10px; border-radius: 4px; margin: 10px 0;">
✅ <strong>Great!</strong> Found <?= count($folders) ?> folders - this campaign has proper folder structure.
</div>
<?php endif; ?>
<?php foreach ($folders as $folder): ?>
<?php
// Better folder name extraction - try multiple name fields
$folderName = 'Unnamed';
// Try common name fields
$nameFields = [
'ARTESIA.FIELD.NAME',
'FERRERO.FIELD.CAMPAIGN_NAME',
'ARTESIA.FIELD.TITLE',
'FERRERO.FIELD.FOLDER_NAME',
'NAME'
];
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'])) {
$folderName = $field['value']['value']['value'];
break 2;
}
}
}
}
}
// Try standard fields
if ($folderName === 'Unnamed') {
$folderName = $folder['name'] ?? $folder['title'] ?? $folder['display_name'] ?? 'Folder';
}
// Add creation date to help identify
$createDate = substr($folder['date_imported'] ?? '', 0, 10); // Just date part
if ($folderName === 'Folder' || strlen($folderName) > 40) {
$folderName = "Folder (Created: {$createDate})";
}
?>
<div style="border: 1px solid #ddd; margin: 10px 0; padding: 15px; background: white; border-radius: 4px;">
<h4><?= htmlspecialchars($folderName) ?></h4>
<p><strong>Asset ID:</strong> <code><?= htmlspecialchars($folder['asset_id']) ?></code></p>
<p><strong>Type:</strong> <?= htmlspecialchars($folder['data_type'] ?? 'CONTAINER') ?></p>
<p><strong>Created:</strong> <?= htmlspecialchars($folder['date_imported'] ?? 'N/A') ?></p>
<form method="POST" style="display: inline; margin-right: 10px;">
<input type="hidden" name="action" value="explore_folder">
<input type="hidden" name="folder_id" value="<?= htmlspecialchars($folder['asset_id']) ?>">
<input type="hidden" name="folder_name" value="<?= htmlspecialchars($folderName) ?>">
<button type="submit" class="btn">Explore "<?= htmlspecialchars($folderName) ?>"</button>
</form>
</div>
<?php endforeach; ?>
<!-- Explore All Folders Button -->
<?php if (count($folders) > 1): ?>
<div style="margin-top: 20px; padding: 15px; background: #e8f4f8; border-radius: 4px;">
<form method="POST">
<input type="hidden" name="action" value="explore_all_folders">
<?php foreach ($folders as $folder): ?>
<input type="hidden" name="folder_ids[]" value="<?= htmlspecialchars($folder['asset_id']) ?>">
<?php endforeach; ?>
<button type="submit" class="btn btn-success">🔍 Explore All <?= count($folders) ?> Folders</button>
</form>
<p style="margin: 10px 0 0 0; font-size: 13px; color: #666;">
This will show contents of both folders side by side for comparison.
</p>
</div>
<?php endif; ?>
<?php else: ?>
<p><strong>Error:</strong> <?= htmlspecialchars($result['response']['error'] ?? 'Unknown error') ?></p>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Folder Contents -->
<?php if (isset($workflowResults['folder_contents'])): ?>
<?php $contentsResult = $workflowResults['folder_contents']; ?>
<div style="background: #f0f8ff; border: 1px solid #bee5eb; border-radius: 6px; padding: 20px; margin: 20px 0;">
<h3>📄 Folder Contents</h3>
<p><strong>Status:</strong> <?= $contentsResult['status'] ?></p>
<p><strong>HTTP Code:</strong> <?= $contentsResult['response']['http_code'] ?? 'N/A' ?></p>
<?php if ($contentsResult['status'] === 'PASS'): ?>
<?php
$contentsData = json_decode($contentsResult['response']['body'], true);
$assets = [];
// Check different possible structures
if (isset($contentsData['folder_children']['asset_list'])) {
$assets = $contentsData['folder_children']['asset_list'];
} elseif (isset($contentsData['items'])) {
$assets = $contentsData['items'];
} elseif (isset($contentsData['asset_list'])) {
$assets = $contentsData['asset_list'];
}
?>
<h4>Found <?= count($assets) ?> item(s) in this folder:</h4>
<?php if (!empty($assets)): ?>
<?php
$fileCount = 0;
$folderCount = 0;
$fileTypes = [];
foreach ($assets as $asset) {
if (($asset['data_type'] ?? '') === 'CONTAINER') {
$folderCount++;
} else {
$fileCount++;
$mimeType = $asset['mime_type'] ?? 'Unknown';
$fileTypes[$mimeType] = ($fileTypes[$mimeType] ?? 0) + 1;
}
}
?>
<div style="background: white; padding: 15px; border-radius: 4px; margin: 15px 0;">
<h5>📊 Summary:</h5>
<p><strong>📁 Subfolders:</strong> <?= $folderCount ?></p>
<p><strong>📄 Files:</strong> <?= $fileCount ?></p>
<?php if (!empty($fileTypes)): ?>
<p><strong>File Types:</strong></p>
<ul style="margin: 5px 0 0 20px;">
<?php foreach ($fileTypes as $type => $count): ?>
<li><?= htmlspecialchars($type) ?> (<?= $count ?> files)</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
<h5>Individual Items:</h5>
<?php foreach ($assets as $index => $asset): ?>
<?php
$assetName = 'Unnamed Asset';
if (isset($asset['metadata']['metadata_element_list'])) {
foreach ($asset['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' && isset($field['value']['value']['value'])) {
$assetName = $field['value']['value']['value'];
break 2;
}
}
}
}
}
if ($assetName === 'Unnamed Asset') {
$assetName = $asset['name'] ?? $asset['asset_id'] ?? 'Unknown';
}
?>
<div style="border: 1px solid #ddd; margin: 5px 0; padding: 10px; background: white; border-radius: 4px;">
<strong><?= $index + 1 ?>. <?= htmlspecialchars($assetName) ?></strong><br>
<strong>ID:</strong> <code><?= htmlspecialchars($asset['asset_id'] ?? 'N/A') ?></code><br>
<strong>Type:</strong> <?= htmlspecialchars($asset['data_type'] ?? 'Unknown') ?><br>
<?php if (isset($asset['mime_type'])): ?>
<strong>File Type:</strong> <?= htmlspecialchars($asset['mime_type']) ?><br>
<?php endif; ?>
<?php if (isset($asset['file_size'])): ?>
<strong>Size:</strong> <?= number_format($asset['file_size']) ?> bytes<br>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>This folder is empty.</p>
<?php endif; ?>
<?php else: ?>
<p><strong>Error:</strong> <?= htmlspecialchars($contentsResult['response']['error'] ?? 'Unknown error') ?></p>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- All Folders Contents Comparison -->
<?php if (isset($workflowResults['all_folder_contents'])): ?>
<div style="background: #f0f8ff; border: 1px solid #bee5eb; border-radius: 6px; padding: 20px; margin: 20px 0;">
<h3>📊 All Folders Comparison</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 20px;">
<?php foreach ($workflowResults['all_folder_contents'] as $folderData): ?>
<?php
$result = $folderData['result'];
$folderId = $folderData['folder_id'];
$folderName = $folderData['folder_name'];
?>
<div style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 15px;">
<h4>📁 <?= htmlspecialchars($folderName) ?></h4>
<p><strong>ID:</strong> <code><?= htmlspecialchars($folderId) ?></code></p>
<p><strong>Status:</strong> <?= $result['status'] ?></p>
<?php if ($result['status'] === 'PASS'): ?>
<?php
$data = json_decode($result['response']['body'], true);
$assets = [];
if (isset($data['folder_children']['asset_list'])) {
$assets = $data['folder_children']['asset_list'];
} elseif (isset($data['items'])) {
$assets = $data['items'];
}
$fileCount = 0;
$folderCount = 0;
$fileTypes = [];
foreach ($assets as $asset) {
if (($asset['data_type'] ?? '') === 'CONTAINER') {
$folderCount++;
} else {
$fileCount++;
$mimeType = $asset['mime_type'] ?? 'Unknown';
$fileTypes[$mimeType] = ($fileTypes[$mimeType] ?? 0) + 1;
}
}
?>
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 10px 0;">
<strong>📊 Contents:</strong><br>
📁 Subfolders: <?= $folderCount ?><br>
📄 Files: <?= $fileCount ?><br>
<?php if (!empty($fileTypes)): ?>
<strong>File Types:</strong><br>
<?php foreach ($fileTypes as $type => $count): ?>
• <?= htmlspecialchars($type) ?> (<?= $count ?>)<br>
<?php endforeach; ?>
<?php endif; ?>
</div>
<?php if ($fileCount > 0): ?>
<div style="background: #d4edda; color: #155724; padding: 10px; border-radius: 4px; margin: 10px 0;">
✅ <strong>This folder contains <?= $fileCount ?> files!</strong><br>
These are your source assets for content scaling.
</div>
<!-- Show actual filenames with download buttons -->
<div style="margin-top: 15px;">
<h6><strong>📄 File List with Download Options:</strong></h6>
<!-- Bulk Download Option -->
<?php
$downloadableAssets = [];
foreach ($assets as $asset) {
if (($asset['data_type'] ?? '') !== 'CONTAINER') {
$downloadableAssets[] = $asset['asset_id'];
}
}
?>
<?php if (!empty($downloadableAssets)): ?>
<div style="background: #d1ecf1; padding: 10px; border-radius: 4px; margin-bottom: 15px;">
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="download_folder">
<input type="hidden" name="folder_name" value="<?= htmlspecialchars($folderName) ?>">
<?php foreach ($downloadableAssets as $assetId): ?>
<input type="hidden" name="folder_asset_ids[]" value="<?= htmlspecialchars($assetId) ?>">
<?php endforeach; ?>
<button type="submit" class="btn btn-success">📥 Download All <?= count($downloadableAssets) ?> Files</button>
</form>
<span style="font-size: 12px; color: #666; margin-left: 10px;">
Downloads all files to: downloads/<?= htmlspecialchars($folderName) ?>/
</span>
</div>
<?php endif; ?>
<!-- Individual Files -->
<?php foreach ($assets as $asset): ?>
<?php if (($asset['data_type'] ?? '') !== 'CONTAINER'): ?>
<?php
$fileName = 'Unnamed File';
if (isset($asset['metadata']['metadata_element_list'])) {
foreach ($asset['metadata']['metadata_element_list'] as $category) {
if (isset($category['metadata_element_list'])) {
foreach ($category['metadata_element_list'] as $field) {
if ($field['id'] === 'ARTESIA.FIELD.NAME' && isset($field['value']['value']['value'])) {
$fileName = $field['value']['value']['value'];
break 2;
}
}
}
}
}
if ($fileName === 'Unnamed File') {
$fileName = $asset['name'] ?? $asset['asset_id'] ?? 'Unknown';
}
?>
<div style="background: #f8f9fa; padding: 10px; margin: 5px 0; border-radius: 4px; border: 1px solid #dee2e6;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="font-family: monospace; font-size: 12px;">
📄 <strong><?= htmlspecialchars($fileName) ?></strong><br>
&nbsp;&nbsp;&nbsp;ID: <?= htmlspecialchars($asset['asset_id'] ?? 'N/A') ?><br>
&nbsp;&nbsp;&nbsp;Type: <?= htmlspecialchars($asset['mime_type'] ?? 'Unknown') ?>
<?php if (isset($asset['file_size'])): ?>
&nbsp;&nbsp;&nbsp;Size: <?= number_format($asset['file_size']) ?> bytes
<?php endif; ?>
</div>
<div>
<form method="POST" style="display: inline; margin-right: 5px;">
<input type="hidden" name="action" value="download_asset">
<input type="hidden" name="asset_id" value="<?= htmlspecialchars($asset['asset_id']) ?>">
<input type="hidden" name="filename" value="<?= htmlspecialchars($fileName) ?>">
<button type="submit" class="btn" style="background: #28a745; font-size: 12px; padding: 6px 10px;">📥 Download</button>
</form>
<button onclick="showMetadata('<?= htmlspecialchars($asset['asset_id']) ?>')" class="btn" style="background: #17a2b8; color: white; font-size: 12px; padding: 6px 10px;">📋 Metadata</button>
<!-- Hidden metadata div -->
<div id="metadata-<?= htmlspecialchars($asset['asset_id']) ?>" style="display: none; margin-top: 15px;">
<?= MetadataExtractor::formatMetadataForDisplay(MetadataExtractor::extractAllMetadata($asset)) ?>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php elseif ($folderCount > 0): ?>
<div style="background: #fff3cd; color: #856404; padding: 10px; border-radius: 4px; margin: 10px 0;">
📁 Contains <?= $folderCount ?> subfolders<br>
Assets might be nested deeper.
</div>
<?php else: ?>
<div style="background: #f8d7da; color: #721c24; padding: 10px; border-radius: 4px; margin: 10px 0;">
❌ This folder appears empty.
</div>
<?php endif; ?>
<?php else: ?>
<p style="color: #dc3545;"><strong>Error exploring folder:</strong> <?= htmlspecialchars($result['response']['error'] ?? 'Unknown error') ?></p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- Download Results -->
<?php if (isset($workflowResults['download'])): ?>
<?php $downloadResult = $workflowResults['download']; ?>
<div style="background: <?= $downloadResult['success'] ? '#d4edda' : '#f8d7da' ?>; border: 1px solid <?= $downloadResult['success'] ? '#c3e6cb' : '#f5c6cb' ?>; border-radius: 6px; padding: 20px; margin: 20px 0;">
<h3><?= $downloadResult['success'] ? '✅' : '❌' ?> Asset Download Result</h3>
<?php if ($downloadResult['success']): ?>
<p><strong>✅ Download Successful!</strong></p>
<p><strong>File:</strong> <?= htmlspecialchars($downloadResult['filename']) ?></p>
<p><strong>Path:</strong> <?= htmlspecialchars($downloadResult['filepath']) ?></p>
<p><strong>Size:</strong> <?= number_format($downloadResult['size']) ?> bytes</p>
<p><strong>Asset ID:</strong> <code><?= htmlspecialchars($downloadResult['asset_id']) ?></code></p>
<?php else: ?>
<p><strong>❌ Download Failed</strong></p>
<p><strong>Error:</strong> <?= htmlspecialchars($downloadResult['error']) ?></p>
<?php if (isset($downloadResult['http_code'])): ?>
<p><strong>HTTP Code:</strong> <?= $downloadResult['http_code'] ?></p>
<?php endif; ?>
<!-- Debug Information - Always show for failures -->
<details style="margin-top: 15px;">
<summary><strong>🔍 Debug Information</strong></summary>
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 10px;">
<?php if (isset($downloadResult['debug_info'])): ?>
<h6>API Endpoint Attempts:</h6>
<?php foreach ($downloadResult['debug_info'] as $attempt): ?>
<div style="background: white; padding: 8px; margin: 5px 0; border-radius: 4px; border-left: 3px solid <?= $attempt['success'] ? '#28a745' : '#dc3545' ?>;">
<strong>Endpoint:</strong> <?= htmlspecialchars($attempt['endpoint']) ?><br>
<strong>Status:</strong> <?= $attempt['success'] ? 'SUCCESS' : 'FAILED' ?><br>
<strong>HTTP Code:</strong> <?= $attempt['http_code'] ?><br>
<strong>Response Size:</strong> <?= number_format($attempt['response_size']) ?> bytes<br>
<?php if ($attempt['error']): ?>
<strong>Error:</strong> <?= htmlspecialchars($attempt['error']) ?><br>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php else: ?>
<div style="background: #fff3cd; padding: 10px; border-radius: 4px;">
<strong>⚠️ No API debug info available</strong><br>
Error occurred before API calls were made. This suggests:
<ul style="margin: 10px 0 0 20px;">
<li>Asset data structure issue</li>
<li>Missing required fields in asset metadata</li>
<li>OAuth2 authentication not properly configured</li>
</ul>
</div>
<?php endif; ?>
</div>
</details>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Bulk Download Results -->
<?php if (isset($workflowResults['bulk_download'])): ?>
<?php $bulkResult = $workflowResults['bulk_download']; ?>
<div style="background: <?= $bulkResult['success'] ? '#d4edda' : '#f8d7da' ?>; border: 1px solid <?= $bulkResult['success'] ? '#c3e6cb' : '#f5c6cb' ?>; border-radius: 6px; padding: 20px; margin: 20px 0;">
<h3><?= $bulkResult['success'] ? '✅' : '❌' ?> Bulk Download Result</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 15px 0;">
<div><strong>Total Assets:</strong> <?= $bulkResult['total_assets'] ?></div>
<div><strong>Successful:</strong> <?= $bulkResult['successful_downloads'] ?></div>
<div><strong>Failed:</strong> <?= $bulkResult['failed_downloads'] ?></div>
<div><strong>Total Size:</strong> <?= number_format($bulkResult['total_size']) ?> bytes</div>
</div>
<p><strong>Download Folder:</strong> <?= htmlspecialchars($bulkResult['download_folder']) ?></p>
<!-- Individual Results with Debug -->
<details style="margin-top: 15px;">
<summary><strong>View Individual Download Results & Debug Info</strong></summary>
<div style="margin-top: 10px;">
<?php foreach ($bulkResult['individual_results'] as $index => $result): ?>
<div style="background: white; padding: 10px; margin: 5px 0; border-radius: 4px; border-left: 4px solid <?= $result['success'] ? '#28a745' : '#dc3545' ?>;">
<strong>File <?= $index + 1 ?>:</strong>
<?php if ($result['success']): ?>
✅ <?= htmlspecialchars($result['filename']) ?> (<?= number_format($result['size']) ?> bytes)
<?php else: ?>
❌ Failed - <?= htmlspecialchars($result['error']) ?>
<!-- Debug info for failed downloads -->
<?php if (isset($result['debug_info'])): ?>
<div style="background: #f8f9fa; padding: 8px; margin-top: 8px; border-radius: 4px; font-size: 11px;">
<strong>Debug Info:</strong><br>
<?php foreach ($result['debug_info'] as $attempt): ?>
• <?= htmlspecialchars($attempt['endpoint']) ?> →
<?= $attempt['success'] ? 'SUCCESS' : 'FAILED' ?>
(HTTP <?= $attempt['http_code'] ?>, <?= $attempt['response_size'] ?> bytes)
<?php if ($attempt['error']): ?>
<br>&nbsp;&nbsp;Error: <?= htmlspecialchars($attempt['error']) ?>
<?php endif ?>
<br>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endforeach; ?>
<!-- OAuth2 Status -->
<?php if (isset($bulkResult['oauth2_status'])): ?>
<div style="background: #e8f4f8; padding: 10px; margin-top: 10px; border-radius: 4px;">
<strong>OAuth2 Status During Download:</strong><br>
Enabled: <?= $bulkResult['oauth2_status']['enabled'] ? 'Yes' : 'No' ?><br>
Has Token: <?= ($bulkResult['oauth2_status']['has_token'] ?? false) ? 'Yes' : 'No' ?><br>
<?php if (isset($bulkResult['oauth2_status']['expires_at'])): ?>
Expires: <?= htmlspecialchars($bulkResult['oauth2_status']['expires_at']) ?><br>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</details>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<script>
function selectCampaign(campaignId, element) {
document.querySelectorAll('.campaign-card').forEach(card => {
card.classList.remove('selected');
});
element.classList.add('selected');
document.getElementById('selected-campaign-id').value = campaignId;
document.getElementById('proceed-btn').disabled = false;
}
function showMetadata(assetId) {
const metadataDiv = document.getElementById('metadata-' + assetId);
if (metadataDiv.style.display === 'none') {
metadataDiv.style.display = 'block';
} else {
metadataDiv.style.display = 'none';
}
}
function exploreFolder(folderId, folderName) {
alert('Explore folder: ' + folderName + ' (ID: ' + folderId + ')');
// TODO: Add folder exploration
}
</script>
</body>
</html>