ferrero-opentext/workflow_v3.php

1145 lines
49 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
session_start();
// Clear session on reset
if (isset($_GET['reset']) || isset($_POST['reset'])) {
session_destroy();
session_start();
header('Location: workflow_v3.php');
exit;
}
// Clear specific workflow results
if (isset($_POST['clear_results'])) {
unset($_SESSION['workflow_results']);
$_SESSION['workflow_results'] = [];
header('Location: workflow_v3.php?tab=' . ($_POST['tab'] ?? 'download'));
exit;
}
require_once 'config_v3.php';
require_once 'src/TestRunner.php';
require_once 'src/CampaignFormatter.php';
require_once 'src/AssetDownloader.php';
require_once 'src/MetadataExtractor.php';
require_once 'src/StatusManager.php';
require_once 'src/ApiClient.php';
$configV3 = new ConfigV3();
$errors = $configV3->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();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Content Scaling Workflow V3</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: #f5f5f5;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
.header h1 { margin-bottom: 10px; }
.header p { opacity: 0.9; }
.env-info {
background: rgba(255,255,255,0.2);
padding: 10px;
border-radius: 4px;
margin-top: 15px;
font-size: 13px;
}
.tabs {
display: flex;
background: #f8f9fa;
border-bottom: 2px solid #dee2e6;
}
.tab {
flex: 1;
padding: 15px 20px;
text-align: center;
cursor: pointer;
border: none;
background: transparent;
font-size: 16px;
font-weight: 500;
color: #6c757d;
transition: all 0.3s;
}
.tab:hover { background: #e9ecef; }
.tab.active {
background: white;
color: #667eea;
border-bottom: 3px solid #667eea;
}
.tab-content {
padding: 30px;
display: none;
}
.tab-content.active { display: block; }
.alert {
padding: 12px 20px;
border-radius: 6px;
margin-bottom: 20px;
}
.alert-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
margin-right: 10px;
margin-bottom: 10px;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover { background: #5568d3; }
.btn-success {
background: #28a745;
color: white;
}
.btn-success:hover { background: #218838; }
.btn-danger {
background: #dc3545;
color: white;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.campaign-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
margin: 20px 0;
}
.campaign-card {
background: #f8f9fa;
border: 2px solid #dee2e6;
border-radius: 8px;
padding: 20px;
cursor: pointer;
transition: all 0.3s;
}
.campaign-card:hover {
border-color: #667eea;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
}
.campaign-card.selected {
border-color: #28a745;
background: #f8fff9;
}
.campaign-card h3 {
color: #333;
margin-bottom: 10px;
}
.campaign-card p {
margin: 5px 0;
font-size: 14px;
color: #666;
}
.asset-list {
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.asset-item {
background: white;
border: 1px solid #dee2e6;
border-radius: 6px;
padding: 15px;
margin: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.asset-info {
flex: 1;
}
.asset-actions {
display: flex;
gap: 10px;
}
.metadata-display {
background: #e9ecef;
padding: 15px;
border-radius: 6px;
margin-top: 10px;
font-size: 12px;
font-family: monospace;
max-height: 300px;
overflow-y: auto;
display: none;
}
.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.status-a1 { background: #fff3cd; color: #856404; }
.status-a2 { background: #cfe2ff; color: #084298; }
.status-a3 { background: #d1e7dd; color: #0f5132; }
.status-a5 { background: #f8d7da; color: #842029; }
.status-a6 { background: #e2d9f3; color: #432874; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎯 Content Scaling Workflow V3</h1>
<p>Status-based workflow management for Ferrero DAM</p>
<div class="env-info">
<strong>Environment:</strong> <?= htmlspecialchars($envInfo['description']) ?>
(<?= htmlspecialchars($envInfo['name']) ?>)
<br>
<strong>Base URL:</strong> <?= htmlspecialchars($envInfo['baseUrl']) ?>
</div>
</div>
<?php if ($error): ?>
<div style="padding: 20px;">
<div class="alert alert-error">
<strong>❌ Error:</strong> <?= htmlspecialchars($error) ?>
</div>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div style="padding: 20px;">
<div class="alert alert-success">
<strong>✅ Success:</strong> <?= htmlspecialchars($success) ?>
</div>
</div>
<?php endif; ?>
<?php if ($oauth2Status && $oauth2Status['enabled']): ?>
<div style="padding: 20px; padding-bottom: 0;">
<div class="alert alert-<?= ($oauth2Status['has_token'] ?? false) ? 'success' : 'error' ?>">
<?= ($oauth2Status['has_token'] ?? false) ? '✅ OAuth2 Token Active' : '❌ OAuth2 Token Issue' ?>
<?php if (($oauth2Status['has_token'] ?? false) && isset($oauth2Status['expires_at'])): ?>
- Expires: <?= htmlspecialchars($oauth2Status['expires_at']) ?>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<div class="tabs">
<button class="tab <?= $currentTab === 'download' ? 'active' : '' ?>"
onclick="switchTab('download')">
📥 Download Workflow (A1→A2)
</button>
<button class="tab <?= $currentTab === 'upload' ? 'active' : '' ?>"
onclick="switchTab('upload')">
📤 Upload Workflow (A2→A3)
</button>
<button class="tab <?= $currentTab === 'rework' ? 'active' : '' ?>"
onclick="switchTab('rework')">
🔄 Rework Workflow (A5→A6)
</button>
</div>
<!-- Download Workflow Tab -->
<div id="tab-download" class="tab-content <?= $currentTab === 'download' ? 'active' : '' ?>">
<h2>📥 Download Workflow: A1 → A2</h2>
<p style="color: #666; margin: 10px 0 20px 0;">
Load campaigns with status A1, download master assets, and update status to A2
</p>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="load_campaigns_a1">
<button type="submit" class="btn btn-primary">Load Campaigns with Status A1</button>
</form>
<?php if (!empty($results)): ?>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="clear_results" value="1">
<button type="submit" class="btn btn-secondary">🗑️ Clear Workflow Data</button>
</form>
<?php endif; ?>
<?php if (isset($results['a1_campaigns']) && !empty($results['a1_campaigns'])): ?>
<h3 style="margin-top: 30px;">Found <?= count($results['a1_campaigns']) ?> Campaigns</h3>
<div class="campaign-grid">
<?php foreach ($results['a1_campaigns'] as $campaign): ?>
<div class="campaign-card <?= (isset($results['selected_campaign']) && $results['selected_campaign']['asset_id'] === $campaign['asset_id']) ? 'selected' : '' ?>"
onclick="selectCampaign('<?= htmlspecialchars($campaign['asset_id']) ?>')">
<h3><?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed Campaign') ?></h3>
<p><strong>Campaign ID:</strong> <?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?></p>
<p><strong>Asset ID:</strong> <code style="font-size: 11px;"><?= htmlspecialchars($campaign['asset_id']) ?></code></p>
<p><strong>Brand:</strong> <?= htmlspecialchars($campaign['brand'] ?? 'N/A') ?></p>
<p><strong>Market:</strong> <?= htmlspecialchars($campaign['market'] ?? 'N/A') ?></p>
<p><span class="status-badge status-a1">A1 - Ready for Localization</span></p>
</div>
<?php endforeach; ?>
</div>
<form method="POST" id="select-campaign-form">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="select_campaign_a1">
<input type="hidden" name="campaign_id" id="selected-campaign-id">
<button type="submit" class="btn btn-success" id="select-campaign-btn" disabled>
Select Campaign & Continue
</button>
</form>
<?php endif; ?>
<?php if (isset($results['selected_campaign'])): ?>
<div class="alert alert-info" style="margin-top: 30px;">
<strong>Selected Campaign:</strong>
<?= htmlspecialchars($results['selected_campaign']['campaign_name']) ?>
(<?= htmlspecialchars($results['selected_campaign']['campaign_id']) ?>)
<br>
<small><strong>Asset ID:</strong> <code><?= htmlspecialchars($results['selected_campaign']['asset_id']) ?></code></small>
<br>
<a href="debug_assets.php?action=get_folders&campaign_id=<?= urlencode($results['selected_campaign']['asset_id']) ?>"
target="_blank" style="color: #667eea; font-size: 12px;">
🔍 Debug folder structure for this campaign
</a>
</div>
<form method="POST" style="margin-top: 20px;">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="get_master_assets">
<button type="submit" class="btn btn-primary">Get Master Assets</button>
</form>
<?php endif; ?>
<?php if (isset($results['master_assets']) && !empty($results['master_assets'])): ?>
<h3 style="margin-top: 30px;">Master Assets (<?= count($results['master_assets']) ?> files)</h3>
<form method="POST" style="margin: 20px 0;">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="download_all_assets">
<button type="submit" class="btn btn-success">📥 Download All Assets</button>
</form>
<div class="asset-list">
<?php foreach ($results['master_assets'] as $index => $asset): ?>
<?php
$assetName = extractFolderName($asset);
$assetId = $asset['asset_id'];
$metadataId = 'metadata-' . $index; // Use index instead of asset_id for simpler ID
?>
<div class="asset-item">
<div class="asset-info">
<strong><?= htmlspecialchars($assetName) ?></strong><br>
<small>ID: <?= htmlspecialchars($assetId) ?></small><br>
<small>Type: <?= htmlspecialchars($asset['mime_type'] ?? 'Unknown') ?></small>
<?php if (isset($asset['file_size'])): ?>
<small> | Size: <?= number_format($asset['file_size']) ?> bytes</small>
<?php endif; ?>
</div>
<div class="asset-actions">
<form method="POST" style="display: inline;">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="download_asset">
<input type="hidden" name="asset_id" value="<?= htmlspecialchars($assetId) ?>">
<input type="hidden" name="filename" value="<?= htmlspecialchars($assetName) ?>">
<button type="submit" class="btn btn-success">📥 Download</button>
</form>
<button class="btn btn-secondary"
onclick="toggleMetadata('<?= $metadataId ?>')">
📋 Metadata
</button>
</div>
</div>
<div id="<?= $metadataId ?>" class="metadata-display" style="display: none;">
<?php
$metadata = MetadataExtractor::extractAllMetadata($asset);
if (!empty($metadata)):
?>
<div style="font-size: 13px;">
<!-- Basic Info -->
<?php if (isset($metadata['basic'])): ?>
<div style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #667eea;">
<strong>📋 Basic Info:</strong><br>
<div style="margin-top: 8px; display: grid; grid-template-columns: 150px 1fr; gap: 5px;">
<?php foreach ($metadata['basic'] as $key => $value): ?>
<?php if ($value !== null): ?>
<div style="color: #666;"><?= ucwords(str_replace('_', ' ', $key)) ?>:</div>
<div><strong><?= htmlspecialchars($value) ?></strong></div>
<?php endif; ?>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- Content Info -->
<?php if (isset($metadata['content'])): ?>
<div style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #28a745;">
<strong>🖼️ Content Info:</strong><br>
<div style="margin-top: 8px; display: grid; grid-template-columns: 150px 1fr; gap: 5px;">
<?php foreach ($metadata['content'] as $key => $value): ?>
<?php if ($value !== null && $value !== -1): ?>
<div style="color: #666;"><?= ucwords(str_replace('_', ' ', $key)) ?>:</div>
<div><strong><?= is_string($value) ? htmlspecialchars($value) : $value ?></strong></div>
<?php endif; ?>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- Custom Fields by Category -->
<?php if (isset($metadata['custom_fields'])): ?>
<?php foreach ($metadata['custom_fields'] as $category => $fields): ?>
<?php if (!empty($fields)): ?>
<details style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #ffc107;">
<summary style="cursor: pointer; font-weight: 600; color: #333;">
📁 <?= htmlspecialchars($category) ?> (<?= count($fields) ?> fields)
</summary>
<div style="margin-top: 8px; display: grid; grid-template-columns: 200px 1fr; gap: 5px;">
<?php foreach ($fields as $fieldName => $fieldData): ?>
<div style="color: #666; padding-top: 4px;"><?= htmlspecialchars($fieldName) ?>:</div>
<div style="padding-top: 4px;">
<strong>
<?php
if (is_array($fieldData['value'])) {
echo htmlspecialchars(implode(', ', $fieldData['value']));
} else {
echo htmlspecialchars($fieldData['value']);
}
?>
</strong>
</div>
<?php endforeach; ?>
</div>
</details>
<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>
<!-- Permissions -->
<?php if (isset($metadata['permissions'])): ?>
<details style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #dc3545;">
<summary style="cursor: pointer; font-weight: 600; color: #333;">🔐 Permissions</summary>
<div style="margin-top: 8px; columns: 2;">
<?php foreach ($metadata['permissions'] as $perm => $value): ?>
<div style="padding: 2px 0;">
<?= $value ? '✅' : '❌' ?> <?= htmlspecialchars(preg_replace('/Permission$/', '', $perm)) ?>
</div>
<?php endforeach; ?>
</div>
</details>
<?php endif; ?>
<!-- Renditions -->
<?php if (isset($metadata['renditions'])): ?>
<details style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #17a2b8;">
<summary style="cursor: pointer; font-weight: 600; color: #333;">🎨 Renditions (<?= count($metadata['renditions']) ?>)</summary>
<div style="margin-top: 8px;">
<?php foreach ($metadata['renditions'] as $rendName => $rendData): ?>
<div style="background: #f8f9fa; padding: 8px; margin: 4px 0; border-radius: 3px;">
<strong><?= htmlspecialchars($rendName) ?></strong><br>
<small>Size: <?= number_format($rendData['content_size'] ?? 0) ?> bytes |
<?= $rendData['width'] ?? 0 ?>x<?= $rendData['height'] ?? 0 ?>px |
<?= htmlspecialchars($rendData['mime_type'] ?? 'N/A') ?></small>
</div>
<?php endforeach; ?>
</div>
</details>
<?php endif; ?>
</div>
<?php else: ?>
<p>No metadata available for this asset</p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<div style="margin-top: 30px; padding: 20px; background: #fff3cd; border-radius: 8px;">
<h4>⚠️ Update Status to A2</h4>
<p style="margin: 10px 0;">
Once all assets are downloaded (or attempted), update the campaign status to A2
(Selected Master Assets sent to Agency)
</p>
<p style="margin: 10px 0; font-size: 13px; color: #856404;">
<strong>Note:</strong> If files don't exist in storage (test environment), you can still
update the status to test the workflow progression.
</p>
<form method="POST">
<input type="hidden" name="tab" value="download">
<input type="hidden" name="action" value="update_status_to_a2">
<button type="submit" class="btn btn-success">Update Status: A1 → A2</button>
</form>
</div>
<?php endif; ?>
<?php if (isset($results['last_download'])): ?>
<?php $dl = $results['last_download']; ?>
<div class="alert alert-<?= $dl['success'] ? 'success' : 'error' ?>" style="margin-top: 20px;">
<?php if ($dl['success']): ?>
<strong>✅ Download Successful:</strong> <?= htmlspecialchars($dl['filename']) ?>
<br><small>Size: <?= number_format($dl['size']) ?> bytes | Path: <?= htmlspecialchars($dl['filepath']) ?></small>
<?php if (isset($dl['download_method'])): ?>
<br><small>Method: <?= htmlspecialchars($dl['download_method']) ?> | URL: <?= htmlspecialchars($dl['rendition_url'] ?? 'N/A') ?></small>
<?php endif; ?>
<?php else: ?>
<strong>❌ Download Failed:</strong> <?= htmlspecialchars($dl['error']) ?>
<br><small>HTTP Code: <?= $dl['http_code'] ?></small>
<?php if (isset($dl['tried_url'])): ?>
<br><small>Tried URL: <?= htmlspecialchars($dl['tried_url']) ?></small>
<?php endif; ?>
<?php if (isset($dl['debug_message'])): ?>
<br><small>Details: <?= htmlspecialchars($dl['debug_message']) ?></small>
<?php endif; ?>
<?php if (isset($dl['debug_info']) && !empty($dl['debug_info'])): ?>
<br><small>Debug: <?= htmlspecialchars(json_encode($dl['debug_info'])) ?></small>
<?php endif; ?>
<?php if (isset($dl['all_attempts']) && !empty($dl['all_attempts'])): ?>
<details style="margin-top: 10px;">
<summary style="cursor: pointer; font-size: 12px;">View all download attempts (<?= count($dl['all_attempts']) ?>)</summary>
<div style="margin-top: 8px; font-size: 11px;">
<?php foreach ($dl['all_attempts'] as $idx => $att): ?>
<div style="padding: 4px; background: #f8f9fa; margin: 2px 0; border-radius: 3px;">
<?= $idx + 1 ?>. [<?= htmlspecialchars($att['type']) ?>] <?= htmlspecialchars($att['url']) ?>
- HTTP <?= $att['http_code'] ?>
</div>
<?php endforeach; ?>
</div>
</details>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (isset($results['bulk_download'])): ?>
<div class="alert alert-<?= $results['bulk_download']['successful'] === $results['bulk_download']['total'] ? 'success' : 'error' ?>"
style="margin-top: 20px;">
<strong>Bulk Download Results:</strong>
<?= $results['bulk_download']['successful'] ?> of <?= $results['bulk_download']['total'] ?> assets downloaded successfully
<?php if ($results['bulk_download']['failed'] > 0): ?>
<br><small><?= $results['bulk_download']['failed'] ?> files failed (may not exist in storage)</small>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<!-- Upload Workflow Tab -->
<div id="tab-upload" class="tab-content <?= $currentTab === 'upload' ? 'active' : '' ?>">
<h2>📤 Upload Workflow: A2 → A3</h2>
<p style="color: #666; margin: 10px 0 20px 0;">
Load campaigns with status A2, upload processed assets, and update status to A3
</p>
<form method="POST">
<input type="hidden" name="tab" value="upload">
<input type="hidden" name="action" value="load_campaigns_a2">
<button type="submit" class="btn btn-primary">Load Campaigns with Status A2</button>
</form>
<div class="alert alert-info" style="margin-top: 20px;">
<strong> Coming Soon:</strong> Upload functionality will be implemented in next phase
</div>
</div>
<!-- Rework Workflow Tab -->
<div id="tab-rework" class="tab-content <?= $currentTab === 'rework' ? 'active' : '' ?>">
<h2>🔄 Rework Workflow: A5 → A6</h2>
<p style="color: #666; margin: 10px 0 20px 0;">
Load campaigns with status A5 (rework needed), download assets for rework, and update status to A6
</p>
<form method="POST">
<input type="hidden" name="tab" value="rework">
<input type="hidden" name="action" value="load_campaigns_a5">
<button type="submit" class="btn btn-primary">Load Campaigns with Status A5</button>
</form>
<div class="alert alert-info" style="margin-top: 20px;">
<strong> Coming Soon:</strong> Rework workflow will be implemented in next phase
</div>
</div>
</div>
<script>
function switchTab(tabName) {
// Update tabs
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
event.target.classList.add('active');
document.getElementById('tab-' + tabName).classList.add('active');
// Update URL without reload
const url = new URL(window.location);
url.searchParams.set('tab', tabName);
window.history.pushState({}, '', url);
}
function selectCampaign(campaignId) {
document.querySelectorAll('.campaign-card').forEach(card => {
card.classList.remove('selected');
});
event.currentTarget.classList.add('selected');
document.getElementById('selected-campaign-id').value = campaignId;
document.getElementById('select-campaign-btn').disabled = false;
}
function toggleMetadata(metadataId) {
const metadataDiv = document.getElementById(metadataId);
if (metadataDiv) {
metadataDiv.style.display = metadataDiv.style.display === 'none' ? 'block' : 'none';
}
}
</script>
</body>
</html>