Now Debug View shows assets with same rich metadata as A1→A2 Download tab: Asset Display Features: - Asset cards with name, ID, type, file size - "View Metadata" button for each asset - Expandable metadata sections: - 📋 Basic Info (brown border) - Brand, Country, Language, etc. - 🖼️ Content Info (green border) - Width, Height, Duration, etc. - 📁 Custom Fields by category (yellow border, collapsible) - Full Raw JSON (collapsible for complete asset data) Uses MetadataExtractor::extractAllMetadata() for rich data extraction. Workflow: 1. Select campaign 2. Click Master or Final button 3. See all assets in that folder 4. Click "View Metadata" on any asset 5. See complete metadata organized by category 6. Expand/collapse sections as needed 7. View raw JSON for debugging Perfect match to Download tab's proven UX pattern. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4354 lines
230 KiB
PHP
4354 lines
230 KiB
PHP
<?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';
|
||
require_once 'src/AssetUploader.php';
|
||
require_once 'src/AssetUploaderSimple.php';
|
||
require_once 'src/BoxClient.php';
|
||
require_once 'src/IDGenerator.php';
|
||
require_once 'src/DatabaseClient.php';
|
||
require_once 'src/FilenameParser.php';
|
||
require_once 'src/MetadataMerger.php';
|
||
require_once 'src/BoxFileRetriever.php';
|
||
require_once 'src/MetadataExtractorMVP.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 AJAX requests (return JSON)
|
||
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
|
||
header('Content-Type: application/json');
|
||
|
||
$action = $_POST['action'] ?? $_GET['action'] ?? '';
|
||
$response = ['success' => false, 'error' => 'Unknown action'];
|
||
|
||
try {
|
||
switch ($action) {
|
||
case 'box_list_files':
|
||
$folderId = $_POST['folder_id'] ?? '';
|
||
if (empty($folderId)) {
|
||
$response = ['success' => false, 'error' => 'Folder ID is required'];
|
||
break;
|
||
}
|
||
|
||
$retriever = new BoxFileRetriever();
|
||
$result = $retriever->listFilesWithTrackingIDs($folderId);
|
||
|
||
if ($result['success']) {
|
||
// Parse each filename
|
||
$parser = new FilenameParser();
|
||
foreach ($result['files'] as &$file) {
|
||
$parsed = $parser->parseFilename($file['name']);
|
||
$file['parsed'] = $parsed;
|
||
$file['is_valid'] = $parsed ? $parsed['is_valid'] : false;
|
||
$file['clean_filename'] = $parsed ? $parser->stripUploadComponents($file['name']) : $file['name'];
|
||
}
|
||
}
|
||
|
||
$response = $result;
|
||
break;
|
||
|
||
case 'parse_filename':
|
||
$filename = $_POST['filename'] ?? '';
|
||
if (empty($filename)) {
|
||
$response = ['success' => false, 'error' => 'Filename is required'];
|
||
break;
|
||
}
|
||
|
||
$parser = new FilenameParser();
|
||
$parsed = $parser->parseFilename($filename);
|
||
|
||
$response = [
|
||
'success' => true,
|
||
'parsed' => $parsed,
|
||
'clean_filename' => $parser->stripUploadComponents($filename)
|
||
];
|
||
break;
|
||
|
||
case 'load_master_metadata':
|
||
$trackingId = $_POST['tracking_id'] ?? '';
|
||
if (empty($trackingId)) {
|
||
$response = ['success' => false, 'error' => 'Tracking ID is required'];
|
||
break;
|
||
}
|
||
|
||
$db = new DatabaseClient();
|
||
$stmt = $db->getConnection()->prepare("
|
||
SELECT tracking_id, opentext_id, upload_directory, description,
|
||
brand_code, country_code, language_code, asset_type, full_metadata
|
||
FROM master_assets
|
||
WHERE tracking_id = :tracking_id AND status = 'active'
|
||
");
|
||
$stmt->execute(['tracking_id' => $trackingId]);
|
||
$masterAsset = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($masterAsset) {
|
||
// Decode full_metadata JSONB column (contains COMPLETE DAM metadata)
|
||
if (isset($masterAsset['full_metadata'])) {
|
||
$masterAsset['metadata'] = json_decode($masterAsset['full_metadata'], true);
|
||
} else {
|
||
$masterAsset['metadata'] = [];
|
||
}
|
||
|
||
$response = [
|
||
'success' => true,
|
||
'master_asset' => $masterAsset
|
||
];
|
||
} else {
|
||
$response = [
|
||
'success' => false,
|
||
'error' => "No master asset found for tracking ID: $trackingId"
|
||
];
|
||
}
|
||
break;
|
||
|
||
case 'merge_metadata':
|
||
$masterMetadata = json_decode($_POST['master_metadata'] ?? '{}', true);
|
||
$parsedFilename = json_decode($_POST['parsed_filename'] ?? '{}', true);
|
||
|
||
if (empty($masterMetadata) || empty($parsedFilename)) {
|
||
$response = ['success' => false, 'error' => 'Master metadata and parsed filename are required'];
|
||
break;
|
||
}
|
||
|
||
$merger = new MetadataMerger();
|
||
$merged = $merger->mergeMetadata($masterMetadata, $parsedFilename);
|
||
$editableFields = $merger->identifyEditableFields($merged);
|
||
|
||
$response = [
|
||
'success' => true,
|
||
'merged' => $merged,
|
||
'editable_fields' => $editableFields
|
||
];
|
||
break;
|
||
|
||
case 'upload_from_box':
|
||
// Main upload handler for Box files
|
||
$fileId = $_POST['file_id'] ?? '';
|
||
$filename = $_POST['filename'] ?? '';
|
||
$trackingId = $_POST['tracking_id'] ?? '';
|
||
|
||
if (empty($fileId) || empty($filename) || empty($trackingId)) {
|
||
$response = ['success' => false, 'error' => 'Missing required parameters'];
|
||
break;
|
||
}
|
||
|
||
try {
|
||
// 1. Parse filename first (validate V2 convention)
|
||
$parser = new FilenameParser();
|
||
$parsed = $parser->parseFilename($filename);
|
||
|
||
if (!$parsed || !$parsed['is_valid']) {
|
||
$errors = $parsed ? implode(', ', $parsed['validation_errors']) : 'Invalid filename';
|
||
$response = ['success' => false, 'error' => 'Invalid filename: ' . $errors];
|
||
break;
|
||
}
|
||
|
||
// 2. Load master metadata from database (FULL metadata from JSONB column)
|
||
$db = new DatabaseClient();
|
||
$stmt = $db->getConnection()->prepare("
|
||
SELECT tracking_id, opentext_id, upload_directory, description,
|
||
brand_code, country_code, language_code, asset_type, full_metadata
|
||
FROM master_assets
|
||
WHERE tracking_id = :tracking_id AND status = 'active'
|
||
");
|
||
$stmt->execute(['tracking_id' => $trackingId]);
|
||
$masterAsset = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$masterAsset) {
|
||
$response = ['success' => false, 'error' => "Master asset not found for tracking ID: $trackingId"];
|
||
break;
|
||
}
|
||
|
||
// Decode full_metadata JSONB column (contains COMPLETE DAM metadata - no truncation)
|
||
if (isset($masterAsset['full_metadata'])) {
|
||
$masterAsset['metadata'] = json_decode($masterAsset['full_metadata'], true);
|
||
error_log("Upload from Box: Loaded full metadata - size: " . strlen($masterAsset['full_metadata']) . " bytes");
|
||
} else {
|
||
$masterAsset['metadata'] = [];
|
||
error_log("Upload from Box: WARNING - No full_metadata found for tracking ID: $trackingId");
|
||
}
|
||
|
||
// Check if upload directory exists
|
||
if (empty($masterAsset['upload_directory'])) {
|
||
$response = ['success' => false, 'error' => 'Upload directory not found in master asset'];
|
||
break;
|
||
}
|
||
|
||
// 3. Download file from Box
|
||
$retriever = new BoxFileRetriever();
|
||
$downloadResult = $retriever->downloadFile($fileId, $filename);
|
||
|
||
if (!$downloadResult['success']) {
|
||
$response = ['success' => false, 'error' => 'Box download failed: ' . $downloadResult['error']];
|
||
break;
|
||
}
|
||
|
||
$localPath = $downloadResult['local_path'];
|
||
|
||
// 4. Extract video metadata from downloaded file (for width/height)
|
||
require_once 'src/VideoMetadataExtractor.php';
|
||
$videoExtractor = new VideoMetadataExtractor();
|
||
$videoMetadata = $videoExtractor->extractVideoMetadata($localPath);
|
||
|
||
// 5. Get clean filename (strip OMG Job Number & Tracking ID)
|
||
$cleanFilename = $parser->stripUploadComponents($filename);
|
||
|
||
if (!$cleanFilename) {
|
||
unlink($localPath);
|
||
$response = ['success' => false, 'error' => 'Failed to generate clean filename'];
|
||
break;
|
||
}
|
||
|
||
// 6. Extract ONLY MVP fields from master metadata + update from filename
|
||
$mvpExtractor = new MetadataExtractorMVP();
|
||
$assetRepresentation = $mvpExtractor->buildMVPAssetRepresentation(
|
||
$masterAsset,
|
||
$cleanFilename,
|
||
$parsed, // Parsed V2 filename for field extraction
|
||
$localPath // Local file for video metadata extraction
|
||
);
|
||
|
||
error_log("Upload from Box: Built MVP asset representation with clean filename: $cleanFilename");
|
||
|
||
// 7. Upload to DAM
|
||
$apiClient = new ApiClient();
|
||
$apiClient->setBaseUrl($configV3->getBaseUrl());
|
||
|
||
// Get OAuth token from TestRunner
|
||
if ($testRunner) {
|
||
$reflection = new ReflectionClass($testRunner);
|
||
$property = $reflection->getProperty('oauth2Handler');
|
||
$property->setAccessible(true);
|
||
$oauth2Handler = $property->getValue($testRunner);
|
||
|
||
if ($oauth2Handler) {
|
||
$accessToken = $oauth2Handler->getAccessToken();
|
||
$apiClient->setHeaders(['Authorization' => 'Bearer ' . $accessToken]);
|
||
}
|
||
}
|
||
|
||
// Rename temp file to clean filename before upload
|
||
$tempDir = dirname($localPath);
|
||
$cleanLocalPath = $tempDir . '/' . $cleanFilename;
|
||
|
||
if ($localPath !== $cleanLocalPath) {
|
||
rename($localPath, $cleanLocalPath);
|
||
$localPath = $cleanLocalPath;
|
||
}
|
||
|
||
$uploader = new AssetUploaderSimple($apiClient);
|
||
$uploadResult = $uploader->uploadWithMetadata(
|
||
$localPath,
|
||
$masterAsset['upload_directory'],
|
||
$assetRepresentation,
|
||
$videoMetadata // Pass video dimensions to upload manifest
|
||
);
|
||
|
||
// 8. Clean up temp file
|
||
if (file_exists($localPath)) {
|
||
unlink($localPath);
|
||
}
|
||
|
||
// 9. Return result
|
||
if ($uploadResult['success']) {
|
||
$response = [
|
||
'success' => true,
|
||
'filename' => $filename,
|
||
'clean_filename' => $cleanFilename,
|
||
'asset_id' => $uploadResult['asset_id'] ?? 'Unknown',
|
||
'tracking_id' => $trackingId,
|
||
'upload_folder' => $masterAsset['upload_directory'],
|
||
'master_asset_id' => $masterAsset['opentext_id'],
|
||
'http_code' => $uploadResult['http_code'] ?? 202,
|
||
'asset_representation' => $assetRepresentation // Include for download/view
|
||
];
|
||
} else {
|
||
$response = [
|
||
'success' => false,
|
||
'error' => 'Upload failed: ' . ($uploadResult['error'] ?? 'Unknown error'),
|
||
'filename' => $filename,
|
||
'http_code' => $uploadResult['http_code'] ?? 0
|
||
];
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
// Clean up on error
|
||
if (isset($localPath) && file_exists($localPath)) {
|
||
unlink($localPath);
|
||
}
|
||
$response = ['success' => false, 'error' => 'Upload exception: ' . $e->getMessage()];
|
||
}
|
||
break;
|
||
|
||
default:
|
||
$response = ['success' => false, 'error' => 'Unknown action: ' . $action];
|
||
}
|
||
} catch (Exception $e) {
|
||
$response = ['success' => false, 'error' => $e->getMessage()];
|
||
}
|
||
|
||
echo json_encode($response);
|
||
exit;
|
||
}
|
||
|
||
// Handle POST actions
|
||
if ($_POST && $testRunner) {
|
||
$action = $_POST['action'] ?? '';
|
||
|
||
try {
|
||
switch ($action) {
|
||
case 'debug_all_campaigns':
|
||
// Check OAuth status first
|
||
$oauth2Status = $testRunner->getOAuth2Status();
|
||
$results['oauth_debug'] = [
|
||
'has_token' => $oauth2Status['has_token'] ?? false,
|
||
'expires_at' => $oauth2Status['expires_at'] ?? 'Unknown'
|
||
];
|
||
|
||
$statusManager = createStatusManager($testRunner);
|
||
$response = $statusManager->searchAllCampaignTypes($testRunner);
|
||
|
||
if ($response['success']) {
|
||
$data = json_decode($response['body'], true);
|
||
$campaigns = CampaignFormatter::getActionableCampaigns($response['body'], []);
|
||
$results['debug_campaigns'] = $campaigns;
|
||
$results['debug_raw'] = $data;
|
||
$results['debug_search_response'] = [
|
||
'http_code' => $response['http_code'],
|
||
'url' => $response['url'] ?? 'N/A',
|
||
'total_results' => $data['search_result_resource']['search_result']['total_hit_count'] ?? 0,
|
||
'response_body_preview' => substr($response['body'] ?? '', 0, 500)
|
||
];
|
||
$success = "Found " . count($campaigns) . " campaigns total (Local Adaptation + Global comm)";
|
||
} else {
|
||
$error = "Debug search failed: HTTP " . ($response['http_code'] ?? 'N/A') . " - " . ($response['error'] ?? 'Unknown error');
|
||
$results['debug_search_response'] = [
|
||
'http_code' => $response['http_code'],
|
||
'url' => $response['url'] ?? 'N/A',
|
||
'error' => $response['error'] ?? 'Unknown',
|
||
'response_preview' => substr($response['body'] ?? '', 0, 500)
|
||
];
|
||
}
|
||
break;
|
||
|
||
case 'load_campaigns_a1':
|
||
$results['a1_campaigns'] = loadCampaignsByStatus($testRunner, 'A1');
|
||
$success = "Loaded " . count($results['a1_campaigns']) . " campaigns with status A1";
|
||
break;
|
||
|
||
case 'select_campaign_a1':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId && isset($results['a1_campaigns'])) {
|
||
foreach ($results['a1_campaigns'] as $campaign) {
|
||
if ($campaign['asset_id'] === $campaignId) {
|
||
$results['selected_campaign'] = $campaign;
|
||
$success = "Campaign selected: " . $campaign['campaign_name'];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'get_master_assets':
|
||
if (isset($results['selected_campaign'])) {
|
||
$campaignId = $results['selected_campaign']['asset_id'];
|
||
$masterFolderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3);
|
||
|
||
if ($masterFolderId) {
|
||
$results['master_folder_id'] = $masterFolderId;
|
||
$results['master_assets'] = getAssetsFromFolder($testRunner, $masterFolderId);
|
||
|
||
// ALSO find Final Assets folder ID for uploads (stored in DB)
|
||
$finalFolderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
if ($finalFolderId) {
|
||
$results['final_assets_folder_id'] = $finalFolderId;
|
||
$success = "Found Master Assets (" . count($results['master_assets']) . " files) and Final Assets folder";
|
||
} else {
|
||
$success = "Found Master Assets folder with " . count($results['master_assets']) . " assets";
|
||
}
|
||
} else {
|
||
$error = "Master Assets folder not found in campaign";
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'get_final_assets':
|
||
if (isset($results['selected_campaign'])) {
|
||
$campaignId = $results['selected_campaign']['asset_id'];
|
||
$finalFolderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
|
||
if ($finalFolderId) {
|
||
$results['final_assets_folder_id'] = $finalFolderId;
|
||
$results['final_assets'] = getAssetsFromFolder($testRunner, $finalFolderId);
|
||
$success = "Found Final Assets folder with " . count($results['final_assets']) . " assets";
|
||
} else {
|
||
$error = "Final 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_asset_metadata':
|
||
$assetId = $_POST['asset_id'] ?? '';
|
||
$filename = $_POST['filename'] ?? 'metadata.json';
|
||
|
||
if ($assetId && isset($results['master_assets'])) {
|
||
// Find the asset in master_assets
|
||
foreach ($results['master_assets'] as $asset) {
|
||
if ($asset['asset_id'] === $assetId) {
|
||
// Create JSON file
|
||
$jsonFilename = pathinfo($filename, PATHINFO_FILENAME) . '_metadata.json';
|
||
$jsonContent = json_encode($asset, JSON_PRETTY_PRINT);
|
||
|
||
// Send as download
|
||
header('Content-Type: application/json');
|
||
header('Content-Disposition: attachment; filename="' . $jsonFilename . '"');
|
||
header('Content-Length: ' . strlen($jsonContent));
|
||
echo $jsonContent;
|
||
exit;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'download_all_assets':
|
||
if (isset($results['master_assets']) && isset($results['selected_campaign'])) {
|
||
$downloadResults = downloadAllAssets($testRunner, $results['master_assets'], $results['selected_campaign']['campaign_id']);
|
||
$results['bulk_download'] = $downloadResults;
|
||
// Store master assets metadata for later upload reference
|
||
$results['master_assets_metadata'] = $results['master_assets'];
|
||
$success = "Downloaded {$downloadResults['successful']} of {$downloadResults['total']} assets";
|
||
}
|
||
break;
|
||
|
||
case 'download_and_upload_to_box':
|
||
if (isset($results['master_assets']) && isset($results['selected_campaign'])) {
|
||
$campaign = $results['selected_campaign'];
|
||
|
||
// Download from DAM
|
||
$downloadResults = downloadAllAssets($testRunner, $results['master_assets'], $campaign['campaign_id']);
|
||
|
||
// Upload to Box with upload folder ID
|
||
$boxResults = uploadAssetsToBox(
|
||
$downloadResults,
|
||
$campaign['campaign_id'],
|
||
$campaign['campaign_name'],
|
||
$results['master_assets'],
|
||
$results['final_assets_folder_id'] ?? null
|
||
);
|
||
|
||
$results['bulk_download'] = $downloadResults;
|
||
$results['box_upload'] = $boxResults;
|
||
|
||
$success = "Downloaded {$downloadResults['successful']} assets and uploaded {$boxResults['successful']} to Box";
|
||
}
|
||
break;
|
||
|
||
case 'reset_to_a1':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus($campaignId, 'A1');
|
||
|
||
if ($statusResult['success']) {
|
||
$success = "Campaign reset to A1 status for testing";
|
||
// Clear session data so we can start fresh
|
||
unset($results['selected_campaign']);
|
||
unset($results['selected_campaign_a2']);
|
||
unset($results['master_assets_metadata']);
|
||
} else {
|
||
$errorMsg = "Unknown error";
|
||
if (isset($statusResult['response']['body'])) {
|
||
$responseData = json_decode($statusResult['response']['body'], true);
|
||
if ($responseData && isset($responseData['exception_body'])) {
|
||
$errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error';
|
||
} elseif ($responseData && isset($responseData['error'])) {
|
||
$errorMsg = $responseData['error'];
|
||
}
|
||
}
|
||
$error = "Failed to reset to A1 (HTTP {$statusResult['http_code']}): {$errorMsg}";
|
||
}
|
||
}
|
||
$currentTab = $_POST['tab'] ?? 'download';
|
||
break;
|
||
|
||
case 'update_status_to_a2':
|
||
if (isset($results['selected_campaign'])) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus(
|
||
$results['selected_campaign']['asset_id'],
|
||
'A2'
|
||
);
|
||
|
||
if ($statusResult['success']) {
|
||
$results['status_update'] = $statusResult;
|
||
$results['selected_campaign']['status'] = 'A2';
|
||
$success = "Campaign status updated to A2: Selected Master Assets sent to Agency";
|
||
} else {
|
||
// Extract error details from API response
|
||
$errorMsg = "Unknown error";
|
||
if (isset($statusResult['response']['body'])) {
|
||
$responseData = json_decode($statusResult['response']['body'], true);
|
||
if ($responseData && isset($responseData['exception_body'])) {
|
||
$errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error';
|
||
} elseif ($responseData && isset($responseData['error'])) {
|
||
$errorMsg = $responseData['error'];
|
||
}
|
||
}
|
||
$error = "Failed to update status to A2 (HTTP {$statusResult['http_code']}): {$errorMsg}";
|
||
// Store full result for debugging
|
||
$results['status_update_error'] = $statusResult;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'load_campaigns_a2':
|
||
$results['a2_campaigns'] = loadCampaignsByStatus($testRunner, 'A2');
|
||
$success = "Loaded " . count($results['a2_campaigns']) . " campaigns with status A2";
|
||
$currentTab = 'upload';
|
||
break;
|
||
|
||
case 'select_campaign_a2':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId && isset($results['a2_campaigns'])) {
|
||
foreach ($results['a2_campaigns'] as $campaign) {
|
||
if ($campaign['asset_id'] === $campaignId) {
|
||
$results['selected_campaign_a2'] = $campaign;
|
||
$success = "Campaign selected: " . $campaign['campaign_name'];
|
||
$currentTab = 'upload';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'get_upload_folder':
|
||
if (isset($results['selected_campaign_a2'])) {
|
||
$campaignId = $results['selected_campaign_a2']['asset_id'];
|
||
|
||
// Find Final Assets or Localized Assets folder for upload
|
||
$uploadFolderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
|
||
if ($uploadFolderId) {
|
||
$results['upload_folder_id'] = $uploadFolderId;
|
||
|
||
// Get Master Assets to copy their metadata
|
||
try {
|
||
$masterFolderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3);
|
||
if ($masterFolderId) {
|
||
$fullMasterAssets = getAssetsFromFolder($testRunner, $masterFolderId);
|
||
|
||
// Store lightweight version - only IDs and basic info
|
||
$results['master_assets_for_upload'] = [];
|
||
if (!empty($fullMasterAssets)) {
|
||
foreach ($fullMasterAssets as $asset) {
|
||
// Only store minimal fields - no huge metadata structure
|
||
$lightAsset = [
|
||
'asset_id' => $asset['asset_id'] ?? null,
|
||
'name' => $asset['name'] ?? 'Unknown',
|
||
'mime_type' => $asset['mime_type'] ?? null
|
||
];
|
||
|
||
// Safely extract metadata_model_id if it exists
|
||
if (isset($asset['metadata_model_id'])) {
|
||
$lightAsset['metadata_model_id'] = $asset['metadata_model_id'];
|
||
}
|
||
|
||
// Safely extract security policy IDs only
|
||
if (isset($asset['security_policy_list']) && is_array($asset['security_policy_list'])) {
|
||
$policyIds = [];
|
||
foreach ($asset['security_policy_list'] as $policy) {
|
||
if (isset($policy['id'])) {
|
||
$policyIds[] = ['id' => $policy['id']];
|
||
}
|
||
}
|
||
if (!empty($policyIds)) {
|
||
$lightAsset['security_policy_list'] = $policyIds;
|
||
}
|
||
}
|
||
|
||
$results['master_assets_for_upload'][] = $lightAsset;
|
||
}
|
||
}
|
||
|
||
$success = "Found upload folder and " . count($results['master_assets_for_upload']) . " master assets for reference";
|
||
} else {
|
||
$success = "Found upload target folder (no master assets folder found)";
|
||
}
|
||
} catch (Exception $e) {
|
||
$success = "Found upload target folder (master assets error: " . $e->getMessage() . ")";
|
||
}
|
||
} else {
|
||
$error = "Upload folder not found in campaign";
|
||
}
|
||
}
|
||
$currentTab = 'upload';
|
||
break;
|
||
|
||
case 'test_upload_to_folder':
|
||
// Test upload to specific folder provided by Ferrero team
|
||
$testFolderId = $_POST['test_folder_id'] ?? 'e96080ba0cd1427d253a28a87504b6665eaa02cb';
|
||
|
||
if (isset($_FILES['test_upload_file'])) {
|
||
$tmpName = $_FILES['test_upload_file']['tmp_name'];
|
||
$fileName = $_FILES['test_upload_file']['name'];
|
||
$fileError = $_FILES['test_upload_file']['error'];
|
||
|
||
if ($fileError === UPLOAD_ERR_OK) {
|
||
$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());
|
||
}
|
||
|
||
// Use SIMPLE uploader that exactly matches standalone script
|
||
$uploader = new AssetUploaderSimple($apiClient);
|
||
|
||
// Create a copy with the actual filename
|
||
$actualFilePath = sys_get_temp_dir() . '/' . $fileName;
|
||
copy($tmpName, $actualFilePath);
|
||
|
||
$result = $uploader->uploadFile($actualFilePath, $testFolderId);
|
||
|
||
// Clean up
|
||
@unlink($actualFilePath);
|
||
|
||
$results['test_upload_result'] = $result;
|
||
$results['test_folder_id'] = $testFolderId;
|
||
|
||
if ($result['success']) {
|
||
$success = "✅ TEST UPLOAD SUCCESSFUL to folder {$testFolderId}!";
|
||
} else {
|
||
$error = "Test upload failed: " . $result['error'];
|
||
}
|
||
} else {
|
||
$error = "File upload error: " . $fileError;
|
||
}
|
||
}
|
||
$currentTab = 'upload';
|
||
break;
|
||
|
||
case 'upload_files':
|
||
if (isset($_FILES['upload_files']) && isset($results['upload_folder_id'])) {
|
||
// Get selected master asset lightweight data
|
||
$selectedMasterAssetLight = null;
|
||
$masterMetadataIndex = $_POST['master_metadata_index'] ?? '0';
|
||
|
||
// Use master_assets_for_upload (lightweight version)
|
||
if ($masterMetadataIndex !== '' && isset($results['master_assets_for_upload'][$masterMetadataIndex])) {
|
||
$selectedMasterAssetLight = $results['master_assets_for_upload'][$masterMetadataIndex];
|
||
} elseif (isset($results['master_assets_for_upload']) && !empty($results['master_assets_for_upload'])) {
|
||
// If no selection, use first master asset as default
|
||
$selectedMasterAssetLight = $results['master_assets_for_upload'][0];
|
||
}
|
||
|
||
// Use the lightweight master asset data directly
|
||
// Full metadata fetch causes crashes - we only need model ID and security policies
|
||
$selectedMasterAsset = $selectedMasterAssetLight;
|
||
|
||
// Store debug info about selected master asset and uploaded file
|
||
$uploadFileName = is_array($_FILES['upload_files']['name']) ? $_FILES['upload_files']['name'][0] : $_FILES['upload_files']['name'];
|
||
$uploadTmpName = is_array($_FILES['upload_files']['tmp_name']) ? $_FILES['upload_files']['tmp_name'][0] : $_FILES['upload_files']['tmp_name'];
|
||
$uploadMimeType = file_exists($uploadTmpName) ? mime_content_type($uploadTmpName) : 'Unknown';
|
||
|
||
$results['upload_debug'] = [
|
||
'selected_master_asset_id' => $selectedMasterAsset['asset_id'] ?? 'N/A',
|
||
'selected_master_name' => $selectedMasterAsset['name'] ?? 'N/A',
|
||
'metadata_model_id' => $selectedMasterAsset['metadata_model_id'] ?? 'NOT FOUND',
|
||
'has_security_policies' => isset($selectedMasterAsset['security_policy_list']) ? 'YES' : 'NO',
|
||
'security_policy_count' => isset($selectedMasterAsset['security_policy_list']) ? count($selectedMasterAsset['security_policy_list']) : 0,
|
||
'master_mime_type' => $selectedMasterAsset['mime_type'] ?? 'Unknown',
|
||
'upload_filename' => $uploadFileName,
|
||
'upload_detected_mime' => $uploadMimeType,
|
||
'upload_folder_id' => $results['upload_folder_id']
|
||
];
|
||
|
||
$uploadResults = uploadFiles($testRunner, $_FILES['upload_files'], $results['upload_folder_id'], $selectedMasterAsset);
|
||
$results['upload_results'] = $uploadResults;
|
||
|
||
if ($uploadResults['successful'] > 0) {
|
||
$success = "Uploaded {$uploadResults['successful']} of {$uploadResults['total']} files";
|
||
} else {
|
||
$error = "All uploads failed";
|
||
}
|
||
}
|
||
$currentTab = 'upload';
|
||
break;
|
||
|
||
case 'update_status_to_a3':
|
||
if (isset($results['selected_campaign_a2'])) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus(
|
||
$results['selected_campaign_a2']['asset_id'],
|
||
'A3'
|
||
);
|
||
|
||
if ($statusResult['success']) {
|
||
$results['status_update_a3'] = $statusResult;
|
||
$success = "Campaign status updated to A3: Localized Asset received from Agency";
|
||
} else {
|
||
// Extract error details from API response
|
||
$errorMsg = "Unknown error";
|
||
if (isset($statusResult['response']['body'])) {
|
||
$responseData = json_decode($statusResult['response']['body'], true);
|
||
if ($responseData && isset($responseData['exception_body'])) {
|
||
$errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error';
|
||
} elseif ($responseData && isset($responseData['error'])) {
|
||
$errorMsg = $responseData['error'];
|
||
}
|
||
}
|
||
$error = "Failed to update status to A3 (HTTP {$statusResult['http_code']}): {$errorMsg}";
|
||
$results['status_update_a3_error'] = $statusResult;
|
||
}
|
||
}
|
||
$currentTab = 'upload';
|
||
break;
|
||
|
||
case 'debug_all_campaigns_rework':
|
||
// Check OAuth status first
|
||
$oauth2Status = $testRunner->getOAuth2Status();
|
||
$results['oauth_debug_rework'] = [
|
||
'has_token' => $oauth2Status['has_token'] ?? false,
|
||
'expires_at' => $oauth2Status['expires_at'] ?? 'Unknown'
|
||
];
|
||
|
||
$statusManager = createStatusManager($testRunner);
|
||
$response = $statusManager->searchAllCampaigns($testRunner);
|
||
|
||
if ($response['success']) {
|
||
$data = json_decode($response['body'], true);
|
||
$campaigns = CampaignFormatter::getActionableCampaigns($response['body'], []);
|
||
$results['debug_campaigns_rework'] = $campaigns;
|
||
$results['debug_raw_rework'] = $data;
|
||
$results['debug_search_response_rework'] = [
|
||
'http_code' => $response['http_code'],
|
||
'url' => $response['url'] ?? 'N/A',
|
||
'total_results' => $data['search_result_resource']['search_result']['total_hit_count'] ?? 0,
|
||
'response_body_preview' => substr($response['body'] ?? '', 0, 500)
|
||
];
|
||
$success = "Found " . count($campaigns) . " campaigns total (without status filter)";
|
||
} else {
|
||
$error = "Debug search failed: HTTP " . ($response['http_code'] ?? 'N/A') . " - " . ($response['error'] ?? 'Unknown error');
|
||
$results['debug_search_response_rework'] = [
|
||
'http_code' => $response['http_code'],
|
||
'url' => $response['url'] ?? 'N/A',
|
||
'error' => $response['error'] ?? 'Unknown',
|
||
'response_preview' => substr($response['body'] ?? '', 0, 500)
|
||
];
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'reset_to_a5':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus($campaignId, 'A5');
|
||
|
||
if ($statusResult['success']) {
|
||
$success = "Campaign reset to A5 status for testing";
|
||
// Clear session data
|
||
unset($results['selected_campaign_a5']);
|
||
unset($results['rework_assets']);
|
||
} else {
|
||
$errorMsg = "Unknown error";
|
||
if (isset($statusResult['response']['body'])) {
|
||
$responseData = json_decode($statusResult['response']['body'], true);
|
||
if ($responseData && isset($responseData['exception_body'])) {
|
||
$errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error';
|
||
} elseif ($responseData && isset($responseData['error'])) {
|
||
$errorMsg = $responseData['error'];
|
||
}
|
||
}
|
||
$error = "Failed to reset to A5 (HTTP {$statusResult['http_code']}): {$errorMsg}";
|
||
}
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'load_campaigns_a5':
|
||
$results['a5_campaigns'] = loadCampaignsByStatus($testRunner, 'A5');
|
||
$success = "Loaded " . count($results['a5_campaigns']) . " campaigns with status A5";
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'select_campaign_a5':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId && isset($results['a5_campaigns'])) {
|
||
foreach ($results['a5_campaigns'] as $campaign) {
|
||
if ($campaign['asset_id'] === $campaignId) {
|
||
$results['selected_campaign_a5'] = $campaign;
|
||
$success = "Campaign selected: " . $campaign['campaign_name'];
|
||
$currentTab = 'rework';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'get_rework_assets':
|
||
if (isset($results['selected_campaign_a5'])) {
|
||
$campaignId = $results['selected_campaign_a5']['asset_id'];
|
||
// Find folder with rework assets (could be Final Assets or Rework folder)
|
||
$reworkFolderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
|
||
if ($reworkFolderId) {
|
||
$results['rework_folder_id'] = $reworkFolderId;
|
||
$results['rework_assets'] = getAssetsFromFolder($testRunner, $reworkFolderId);
|
||
$success = "Found " . count($results['rework_assets']) . " assets needing rework";
|
||
} else {
|
||
$error = "Rework assets folder not found";
|
||
}
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'download_rework_asset':
|
||
$assetId = $_POST['asset_id'] ?? '';
|
||
$filename = $_POST['filename'] ?? '';
|
||
|
||
if ($assetId && isset($results['selected_campaign_a5'])) {
|
||
$assetData = null;
|
||
if (isset($results['rework_assets'])) {
|
||
foreach ($results['rework_assets'] as $asset) {
|
||
if ($asset['asset_id'] === $assetId) {
|
||
$assetData = $asset;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
$result = downloadAsset($testRunner, $assetId, $filename, $results['selected_campaign_a5']['campaign_id'], $assetData);
|
||
$results['last_rework_download'] = $result;
|
||
|
||
if ($result['success']) {
|
||
$success = "Downloaded rework asset: " . $result['filename'];
|
||
} else {
|
||
$error = "Download failed: " . $result['error'];
|
||
}
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'download_all_rework':
|
||
if (isset($results['rework_assets']) && isset($results['selected_campaign_a5'])) {
|
||
$downloadResults = downloadAllAssets($testRunner, $results['rework_assets'], $results['selected_campaign_a5']['campaign_id']);
|
||
$results['rework_bulk_download'] = $downloadResults;
|
||
$success = "Downloaded {$downloadResults['successful']} of {$downloadResults['total']} rework assets";
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'update_status_to_a6':
|
||
if (isset($results['selected_campaign_a5'])) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus(
|
||
$results['selected_campaign_a5']['asset_id'],
|
||
'A6'
|
||
);
|
||
|
||
if ($statusResult['success']) {
|
||
$results['status_update_a6'] = $statusResult;
|
||
$success = "Campaign status updated to A6: Assets to be reworked received by the Agency";
|
||
} else {
|
||
// Extract error details from API response
|
||
$errorMsg = "Unknown error";
|
||
if (isset($statusResult['response']['body'])) {
|
||
$responseData = json_decode($statusResult['response']['body'], true);
|
||
if ($responseData && isset($responseData['exception_body'])) {
|
||
$errorMsg = $responseData['exception_body']['message'] ?? $responseData['exception_body']['debug_message'] ?? 'API Error';
|
||
} elseif ($responseData && isset($responseData['error'])) {
|
||
$errorMsg = $responseData['error'];
|
||
}
|
||
}
|
||
$error = "Failed to update status to A6 (HTTP {$statusResult['http_code']}): {$errorMsg}";
|
||
$results['status_update_a6_error'] = $statusResult;
|
||
}
|
||
}
|
||
$currentTab = 'rework';
|
||
break;
|
||
|
||
case 'load_campaigns_b1':
|
||
$results['b1_campaigns'] = loadCampaignsGlobal($testRunner, 'B1');
|
||
$success = "Loaded " . count($results['b1_campaigns']) . " Global campaigns with status B1";
|
||
break;
|
||
|
||
case 'select_campaign_b1':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId && isset($results['b1_campaigns'])) {
|
||
foreach ($results['b1_campaigns'] as $campaign) {
|
||
if ($campaign['asset_id'] === $campaignId) {
|
||
$results['selected_campaign_b1'] = $campaign;
|
||
$success = "Campaign selected: " . $campaign['campaign_name'];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
$currentTab = 'global-masters';
|
||
break;
|
||
|
||
case 'get_global_master_assets':
|
||
if (isset($results['selected_campaign_b1'])) {
|
||
$campaignId = $results['selected_campaign_b1']['asset_id'];
|
||
|
||
// B1 campaigns use "05. Final Assets" folder (not "01. Master Assets")
|
||
$finalAssetsFolderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
|
||
if ($finalAssetsFolderId) {
|
||
$results['global_master_folder_id'] = $finalAssetsFolderId;
|
||
$results['global_master_assets'] = getAssetsFromFolder($testRunner, $finalAssetsFolderId);
|
||
$success = "Found " . count($results['global_master_assets']) . " Global Master assets in Final Assets folder";
|
||
} else {
|
||
$error = "Final Assets folder not found in campaign (B1 campaigns use '05. Final Assets')";
|
||
}
|
||
}
|
||
$currentTab = 'global-masters';
|
||
break;
|
||
|
||
case 'update_status_to_b2':
|
||
$campaignId = $_POST['campaign_id'] ?? null;
|
||
if (!$campaignId && isset($results['selected_campaign_b1'])) {
|
||
$campaignId = $results['selected_campaign_b1']['asset_id'];
|
||
}
|
||
|
||
if ($campaignId) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus($campaignId, 'B2');
|
||
|
||
if ($statusResult['success']) {
|
||
$results['status_update_b2'] = $statusResult;
|
||
$success = "Campaign status updated to B2: Master campaign received from Agency";
|
||
} else {
|
||
$error = "Failed to update status to B2";
|
||
$results['status_update_b2_error'] = $statusResult;
|
||
}
|
||
}
|
||
$currentTab = 'global-masters';
|
||
break;
|
||
|
||
case 'reset_to_b1':
|
||
$campaignId = $_POST['campaign_id'] ?? '';
|
||
if ($campaignId) {
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus($campaignId, 'B1');
|
||
|
||
if ($statusResult['success']) {
|
||
$success = "Campaign status reset to B1";
|
||
unset($results['b1_campaigns']);
|
||
} else {
|
||
$error = "Failed to reset status to B1";
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'debug_all_global_campaigns':
|
||
$statusManager = createStatusManager($testRunner);
|
||
$response = $statusManager->searchGlobalCampaigns($testRunner);
|
||
|
||
if ($response['success']) {
|
||
$data = json_decode($response['body'], true);
|
||
$campaigns = CampaignFormatter::getActionableCampaigns($response['body'], []);
|
||
$results['debug_global_campaigns'] = $campaigns;
|
||
$success = "Found " . count($campaigns) . " Global campaigns total";
|
||
} else {
|
||
$error = "Debug search failed for Global campaigns";
|
||
}
|
||
break;
|
||
|
||
// Debug View Actions
|
||
case 'load_all_campaigns_debug':
|
||
$statusManager = createStatusManager($testRunner);
|
||
$allStatuses = ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'B1', 'B2'];
|
||
$allCampaigns = [];
|
||
|
||
foreach ($allStatuses as $status) {
|
||
$campaigns = loadCampaignsByStatus($testRunner, $status);
|
||
foreach ($campaigns as $campaign) {
|
||
$campaign['current_status'] = $status;
|
||
$allCampaigns[] = $campaign;
|
||
}
|
||
}
|
||
|
||
$results['debug_all_campaigns'] = $allCampaigns;
|
||
$success = "Loaded " . count($allCampaigns) . " campaigns across all statuses";
|
||
$currentTab = 'debug-view';
|
||
break;
|
||
|
||
case 'update_campaign_status_debug':
|
||
$selectedIndex = $_POST['selected_campaign'] ?? null;
|
||
$targetStatus = $_POST['target_status'] ?? null;
|
||
|
||
if ($selectedIndex !== null && $targetStatus && isset($results['debug_all_campaigns'][$selectedIndex])) {
|
||
$campaign = $results['debug_all_campaigns'][$selectedIndex];
|
||
$campaignId = $campaign['asset_id'];
|
||
$campaignName = $campaign['campaign_name'];
|
||
$campaignNumber = $campaign['campaign_id'] ?? 'N/A';
|
||
$oldStatus = $campaign['current_status'];
|
||
|
||
$statusManager = createStatusManager($testRunner);
|
||
$statusResult = $statusManager->updateCampaignStatus($campaignId, $targetStatus);
|
||
|
||
if ($statusResult['success']) {
|
||
$results['status_update_result'] = [
|
||
'success' => true,
|
||
'campaign_name' => $campaignName,
|
||
'campaign_number' => $campaignNumber,
|
||
'old_status' => $oldStatus,
|
||
'new_status' => $targetStatus
|
||
];
|
||
$success = "Campaign status updated: {$oldStatus} → {$targetStatus}";
|
||
unset($results['debug_all_campaigns']);
|
||
} else {
|
||
$results['status_update_result'] = [
|
||
'success' => false,
|
||
'error' => $statusResult['error'] ?? 'Unknown error',
|
||
'campaign_name' => $campaignName
|
||
];
|
||
$error = "Failed to update campaign status";
|
||
}
|
||
} else {
|
||
$error = "Please select a campaign and target status";
|
||
}
|
||
$currentTab = 'debug-view';
|
||
break;
|
||
|
||
case 'view_master_assets_folder':
|
||
case 'view_final_assets_folder':
|
||
$folderType = ($action === 'view_master_assets_folder') ? 'Master Assets' : 'Final Assets';
|
||
$folderName = ($action === 'view_master_assets_folder') ? '01. Master Assets' : '01. Final Assets';
|
||
|
||
$assetManager = createAssetManager($testRunner);
|
||
$searchResult = $assetManager->searchForFolder($folderName);
|
||
|
||
if ($searchResult['success'] && count($searchResult['folders']) > 0) {
|
||
$folderId = $searchResult['folders'][0]['id'];
|
||
$contentsResult = $assetManager->getFolderContents($folderId);
|
||
|
||
if ($contentsResult['success']) {
|
||
$items = $contentsResult['items'];
|
||
|
||
foreach ($items as &$item) {
|
||
if ($item['type'] === 'folder') {
|
||
$item['campaign_id'] = extractCampaignId($item);
|
||
$item['status'] = extractStatus($item);
|
||
}
|
||
}
|
||
|
||
$results['debug_folder_contents'] = [
|
||
'folder_name' => $folderName,
|
||
'folder_type' => $folderType,
|
||
'folder_id' => $folderId,
|
||
'items' => $items
|
||
];
|
||
$success = "Found " . count($items) . " items in {$folderName}";
|
||
} else {
|
||
$results['debug_folder_error'] = "Failed to load folder contents";
|
||
$error = $results['debug_folder_error'];
|
||
}
|
||
} else {
|
||
$results['debug_folder_error'] = "Folder '{$folderName}' not found";
|
||
$error = $results['debug_folder_error'];
|
||
}
|
||
$currentTab = 'debug-view';
|
||
break;
|
||
|
||
case 'select_campaign_and_view_folders':
|
||
$campaignIndex = $_POST['campaign_index'] ?? null;
|
||
$folderType = $_POST['folder_type'] ?? 'master';
|
||
|
||
if ($campaignIndex !== null && isset($results['debug_all_campaigns'][$campaignIndex])) {
|
||
$campaign = $results['debug_all_campaigns'][$campaignIndex];
|
||
$results['selected_campaign_debug'] = $campaign;
|
||
|
||
// Find the campaign's folder
|
||
$campaignId = $campaign['asset_id'];
|
||
$folderName = ($folderType === 'master') ? '01. Master Assets' : '01. Final Assets';
|
||
$results['debug_folder_view_type'] = $folderName;
|
||
|
||
// Use existing helper functions - EXACT same as Download tab
|
||
if ($folderType === 'master') {
|
||
$folderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3);
|
||
} else {
|
||
$folderId = findUploadFolder($testRunner, $campaignId, $configV3);
|
||
}
|
||
|
||
if ($folderId) {
|
||
// Get ALL assets from folder - same as Download tab
|
||
$assets = getAssetsFromFolder($testRunner, $folderId);
|
||
|
||
// Store assets directly (don't transform, keep original structure)
|
||
$results['debug_campaign_assets'] = $assets;
|
||
$results['debug_folder_id'] = $folderId;
|
||
$results['debug_folder_name'] = $folderName;
|
||
$results['debug_folder_type'] = ucfirst($folderType) . ' Assets';
|
||
$success = "Found " . count($assets) . " assets in {$folderName} for campaign " . ($campaign['campaign_id'] ?? '');
|
||
} else {
|
||
$results['debug_folder_error'] = "Folder '{$folderName}' not found in campaign";
|
||
$error = $results['debug_folder_error'];
|
||
}
|
||
} else {
|
||
$error = "Campaign not found";
|
||
}
|
||
$currentTab = 'debug-view';
|
||
break;
|
||
|
||
case 'view_folder_contents':
|
||
$folderId = $_POST['folder_id'] ?? '';
|
||
$folderName = $_POST['folder_name'] ?? 'Unknown Folder';
|
||
|
||
if ($folderId) {
|
||
$assetManager = createAssetManager($testRunner);
|
||
$contentsResult = $assetManager->getFolderContents($folderId);
|
||
|
||
if ($contentsResult['success']) {
|
||
$items = $contentsResult['items'];
|
||
|
||
foreach ($items as &$item) {
|
||
if ($item['type'] === 'folder') {
|
||
$item['campaign_id'] = extractCampaignId($item);
|
||
$item['status'] = extractStatus($item);
|
||
}
|
||
}
|
||
|
||
$results['debug_folder_contents'] = [
|
||
'folder_name' => $folderName,
|
||
'folder_type' => 'Subfolder',
|
||
'folder_id' => $folderId,
|
||
'items' => $items
|
||
];
|
||
$success = "Found " . count($items) . " items in {$folderName}";
|
||
} else {
|
||
$results['debug_folder_error'] = "Failed to load folder";
|
||
$error = $results['debug_folder_error'];
|
||
}
|
||
} else {
|
||
$error = "Folder ID is required";
|
||
}
|
||
$currentTab = 'debug-view';
|
||
break;
|
||
}
|
||
} catch (Exception $e) {
|
||
$error = "Action failed: " . $e->getMessage();
|
||
}
|
||
}
|
||
|
||
// Helper Functions
|
||
|
||
function extractCampaignId($folder)
|
||
{
|
||
if (isset($folder['metadata'])) {
|
||
foreach ($folder['metadata'] as $field) {
|
||
if (isset($field['id']) && $field['id'] === 'FERRERO.FIELD.CAMPAIGN ID') {
|
||
return $field['value']['value']['value'] ?? null;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function extractStatus($folder)
|
||
{
|
||
if (isset($folder['metadata'])) {
|
||
foreach ($folder['metadata'] as $field) {
|
||
if (isset($field['id']) && $field['id'] === 'CONTENT.SCALING.STATUS') {
|
||
return $field['value']['value']['value'] ?? null;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function extractStatusFromAsset($asset)
|
||
{
|
||
if (isset($asset['metadata']) && 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'] === 'CONTENT.SCALING.STATUS') {
|
||
return $field['value']['value']['value'] ?? null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function loadCampaignsByStatus($testRunner, $status)
|
||
{
|
||
// Search for ALL Local Adaptation campaigns (without status filter in API)
|
||
// Then let CampaignFormatter filter by status in PHP
|
||
$statusManager = createStatusManager($testRunner);
|
||
$response = $statusManager->searchAllCampaigns($testRunner);
|
||
|
||
if ($response['success']) {
|
||
// Get ALL campaigns first
|
||
$allCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], []);
|
||
|
||
// Debug: Store all campaigns to see their statuses
|
||
global $results;
|
||
$results['debug_all_campaigns_count'] = count($allCampaigns);
|
||
$results['debug_status_filter'] = $status;
|
||
|
||
// Now filter by status
|
||
$filteredCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], ['status' => $status]);
|
||
$results['debug_filtered_count'] = count($filteredCampaigns);
|
||
|
||
return $filteredCampaigns;
|
||
}
|
||
|
||
return [];
|
||
}
|
||
|
||
function loadCampaignsGlobal($testRunner, $status)
|
||
{
|
||
// Search for ALL Global comm campaigns
|
||
// Then filter by status in PHP
|
||
$statusManager = createStatusManager($testRunner);
|
||
$response = $statusManager->searchGlobalCampaigns($testRunner);
|
||
|
||
if ($response['success']) {
|
||
$allCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], []);
|
||
|
||
global $results;
|
||
$results['debug_all_global_count'] = count($allCampaigns);
|
||
$results['debug_status_filter_global'] = $status;
|
||
|
||
// Filter by status
|
||
$filteredCampaigns = CampaignFormatter::getActionableCampaigns($response['body'], ['status' => $status]);
|
||
$results['debug_filtered_global_count'] = count($filteredCampaigns);
|
||
|
||
return $filteredCampaigns;
|
||
}
|
||
|
||
return [];
|
||
}
|
||
|
||
function findMasterAssetsFolder($testRunner, $campaignId, $configV3)
|
||
{
|
||
$masterFolderName = $configV3->getFolderName('master_assets');
|
||
|
||
$requests = $testRunner->getAvailableRequests();
|
||
|
||
foreach ($requests as $index => $request) {
|
||
$name = strtolower($request['name']);
|
||
if (strpos($name, 'retrieve master asset folder') !== false ||
|
||
strpos($name, 'master asset folder and final') !== false) {
|
||
|
||
$modifiedRequest = $request;
|
||
$url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url'];
|
||
$url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$campaignId}/", $url);
|
||
$url = str_replace('{{baseUrl}}', $configV3->getBaseUrl(), $url);
|
||
|
||
if (is_array($modifiedRequest['request']['url'])) {
|
||
$modifiedRequest['request']['url']['raw'] = $url;
|
||
} else {
|
||
$modifiedRequest['request']['url'] = $url;
|
||
}
|
||
|
||
$result = $testRunner->runSingleTest($modifiedRequest, $index);
|
||
|
||
if ($result['status'] === 'PASS') {
|
||
$data = json_decode($result['response']['body'], true);
|
||
$folders = $data['folder_children']['asset_list'] ?? [];
|
||
|
||
foreach ($folders as $folder) {
|
||
$folderName = extractFolderName($folder);
|
||
if (strpos($folderName, 'Master') !== false || $folderName === $masterFolderName) {
|
||
return $folder['asset_id'];
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function extractFolderName($folder)
|
||
{
|
||
$nameFields = [
|
||
'INER_NAME_GENERIC',
|
||
'ARTESIA.FIELD.NAME',
|
||
'FERRERO.FIELD.CAMPAIGN_NAME',
|
||
'ARTESIA.FIELD.TITLE'
|
||
];
|
||
|
||
if (isset($folder['metadata']['metadata_element_list'])) {
|
||
foreach ($folder['metadata']['metadata_element_list'] as $category) {
|
||
if (isset($category['metadata_element_list'])) {
|
||
foreach ($category['metadata_element_list'] as $field) {
|
||
if (in_array($field['id'], $nameFields) && isset($field['value']['value']['value'])) {
|
||
return $field['value']['value']['value'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return $folder['name'] ?? $folder['title'] ?? 'Unnamed';
|
||
}
|
||
|
||
function getAssetsFromFolder($testRunner, $folderId)
|
||
{
|
||
$requests = $testRunner->getAvailableRequests();
|
||
|
||
foreach ($requests as $index => $request) {
|
||
$name = strtolower($request['name']);
|
||
if (strpos($name, 'retrieve all assets from') !== false) {
|
||
$modifiedRequest = $request;
|
||
$url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url'];
|
||
$url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$folderId}/", $url);
|
||
|
||
if (is_array($modifiedRequest['request']['url'])) {
|
||
$modifiedRequest['request']['url']['raw'] = $url;
|
||
} else {
|
||
$modifiedRequest['request']['url'] = $url;
|
||
}
|
||
|
||
$result = $testRunner->runSingleTest($modifiedRequest, $index);
|
||
|
||
if ($result['status'] === 'PASS') {
|
||
$data = json_decode($result['response']['body'], true);
|
||
$assets = $data['folder_children']['asset_list'] ?? [];
|
||
|
||
// Filter out folders, only return files
|
||
return array_filter($assets, function($asset) {
|
||
return ($asset['data_type'] ?? '') !== 'CONTAINER';
|
||
});
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
return [];
|
||
}
|
||
|
||
function downloadAsset($testRunner, $assetId, $filename, $campaignId, $assetData = null)
|
||
{
|
||
$apiClient = new ApiClient();
|
||
$configV3 = new ConfigV3();
|
||
$apiClient->setBaseUrl($configV3->getBaseUrl());
|
||
|
||
// Get OAuth2 token
|
||
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
|
||
$oauth2Handler->setAccessible(true);
|
||
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
|
||
if ($oauth2HandlerInstance) {
|
||
$apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader());
|
||
}
|
||
|
||
$renditionUrl = null;
|
||
$debugInfo = [];
|
||
|
||
// If we have asset data from folder listing, use it directly
|
||
if ($assetData) {
|
||
$debugInfo['using_cached_asset_data'] = true;
|
||
|
||
// Look for rendition URL in asset_content_info from folder listing
|
||
if (isset($assetData['asset_content_info']['master_content']['url'])) {
|
||
$renditionUrl = $assetData['asset_content_info']['master_content']['url'];
|
||
$debugInfo['found_master_content_url'] = true;
|
||
}
|
||
elseif (isset($assetData['asset_content_info'][0]['url'])) {
|
||
$renditionUrl = $assetData['asset_content_info'][0]['url'];
|
||
$debugInfo['found_array_url'] = true;
|
||
}
|
||
elseif (isset($assetData['asset_content_info']['url'])) {
|
||
$renditionUrl = $assetData['asset_content_info']['url'];
|
||
$debugInfo['found_direct_url'] = true;
|
||
}
|
||
|
||
$debugInfo['has_asset_content_info'] = isset($assetData['asset_content_info']);
|
||
$debugInfo['asset_content_info_type'] = isset($assetData['asset_content_info']) ? gettype($assetData['asset_content_info']) : 'not set';
|
||
}
|
||
|
||
// Fallback: Fetch asset metadata if not provided or rendition not found
|
||
if (!$renditionUrl) {
|
||
$debugInfo['fetching_from_api'] = true;
|
||
|
||
$metadataRequest = [
|
||
'method' => 'GET',
|
||
'url' => "/v6/assets/{$assetId}?load_type=full"
|
||
];
|
||
|
||
$metadataResponse = $apiClient->executeRequest($metadataRequest);
|
||
|
||
if ($metadataResponse['success']) {
|
||
$fetchedData = json_decode($metadataResponse['body'], true);
|
||
$asset = $fetchedData['asset'] ?? $fetchedData;
|
||
|
||
if (isset($asset['asset_content_info']['master_content']['url'])) {
|
||
$renditionUrl = $asset['asset_content_info']['master_content']['url'];
|
||
}
|
||
elseif (isset($asset['asset_content_info'][0]['url'])) {
|
||
$renditionUrl = $asset['asset_content_info'][0]['url'];
|
||
}
|
||
elseif (isset($asset['asset_content_info']['url'])) {
|
||
$renditionUrl = $asset['asset_content_info']['url'];
|
||
}
|
||
|
||
$debugInfo['api_has_asset_content_info'] = isset($asset['asset_content_info']);
|
||
}
|
||
}
|
||
|
||
// Try direct download if no rendition URL found
|
||
if (!$renditionUrl) {
|
||
$renditionUrl = "/v6/assets/{$assetId}/contents";
|
||
}
|
||
|
||
// Clean up the URL - remove /otmmapi prefix if present (base URL already has it)
|
||
$renditionUrl = str_replace('/otmmapi/', '/', $renditionUrl);
|
||
|
||
$debugInfo['final_url'] = $renditionUrl;
|
||
|
||
// Try to download - first attempt with original/master rendition
|
||
$request = [
|
||
'method' => 'GET',
|
||
'url' => $renditionUrl
|
||
];
|
||
|
||
$response = $apiClient->executeRequest($request);
|
||
$attempts = [['url' => $renditionUrl, 'type' => 'original', 'http_code' => $response['http_code']]];
|
||
|
||
// If original fails and we have asset data, try preview/thumbnail renditions
|
||
if ($response['success'] && !empty($response['body'])) {
|
||
$jsonCheck = json_decode($response['body'], true);
|
||
|
||
if ($jsonCheck && isset($jsonCheck['exception_body'])) {
|
||
// Original failed, try alternative renditions from asset data
|
||
$alternativeRenditions = [];
|
||
|
||
if ($assetData && isset($assetData['asset_content_info'])) {
|
||
$debugInfo['asset_content_info_count'] = count($assetData['asset_content_info']);
|
||
|
||
foreach ($assetData['asset_content_info'] as $key => $contentInfo) {
|
||
if (is_array($contentInfo)) {
|
||
$rendType = $contentInfo['rendition_type'] ?? $key;
|
||
$debugInfo['content_info_keys'][] = $key;
|
||
|
||
if (isset($contentInfo['url'])) {
|
||
// Add ALL renditions, not just preview/thumbnail
|
||
$alternativeRenditions[] = [
|
||
'url' => str_replace('/otmmapi/', '/', $contentInfo['url']),
|
||
'type' => $rendType
|
||
];
|
||
}
|
||
}
|
||
}
|
||
|
||
$debugInfo['alternative_renditions_found'] = count($alternativeRenditions);
|
||
}
|
||
|
||
// Try alternative renditions
|
||
foreach ($alternativeRenditions as $altRendition) {
|
||
$altRequest = ['method' => 'GET', 'url' => $altRendition['url']];
|
||
$altResponse = $apiClient->executeRequest($altRequest);
|
||
$attempts[] = ['url' => $altRendition['url'], 'type' => $altRendition['type'], 'http_code' => $altResponse['http_code']];
|
||
|
||
if ($altResponse['success'] && !empty($altResponse['body'])) {
|
||
$altCheck = json_decode($altResponse['body'], true);
|
||
if (!$altCheck || !isset($altCheck['exception_body'])) {
|
||
// Success with alternative rendition!
|
||
$response = $altResponse;
|
||
$renditionUrl = $altRendition['url'];
|
||
$debugInfo['used_rendition'] = $altRendition['type'];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Still failed after all attempts
|
||
$finalCheck = json_decode($response['body'], true);
|
||
if ($finalCheck && isset($finalCheck['exception_body'])) {
|
||
return [
|
||
'success' => false,
|
||
'error' => $finalCheck['exception_body']['message'] ?? 'File not found in storage',
|
||
'http_code' => $finalCheck['exception_body']['http_response_code'] ?? 500,
|
||
'debug_message' => $finalCheck['exception_body']['debug_message'] ?? '',
|
||
'tried_url' => $renditionUrl,
|
||
'debug_info' => $debugInfo,
|
||
'all_attempts' => $attempts
|
||
];
|
||
}
|
||
}
|
||
|
||
$downloadPath = $configV3->getDownloadPath($campaignId);
|
||
|
||
if (!is_dir($downloadPath)) {
|
||
mkdir($downloadPath, 0755, true);
|
||
}
|
||
|
||
$safeFilename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename ?: "asset_{$assetId}");
|
||
$fullPath = $downloadPath . '/' . $safeFilename;
|
||
$bytesWritten = file_put_contents($fullPath, $response['body']);
|
||
|
||
return [
|
||
'success' => $bytesWritten !== false,
|
||
'filename' => $safeFilename,
|
||
'filepath' => $fullPath,
|
||
'size' => $bytesWritten,
|
||
'asset_id' => $assetId,
|
||
'download_method' => 'rendition',
|
||
'rendition_url' => $renditionUrl
|
||
];
|
||
}
|
||
|
||
return [
|
||
'success' => false,
|
||
'error' => $response['error'] ?? 'Download failed',
|
||
'http_code' => $response['http_code'],
|
||
'tried_url' => $renditionUrl
|
||
];
|
||
}
|
||
|
||
function downloadAllAssets($testRunner, $assets, $campaignId)
|
||
{
|
||
$results = [
|
||
'total' => count($assets),
|
||
'successful' => 0,
|
||
'failed' => 0,
|
||
'details' => []
|
||
];
|
||
|
||
foreach ($assets as $asset) {
|
||
$filename = extractFolderName($asset);
|
||
$result = downloadAsset($testRunner, $asset['asset_id'], $filename, $campaignId);
|
||
|
||
if ($result['success']) {
|
||
$results['successful']++;
|
||
} else {
|
||
$results['failed']++;
|
||
}
|
||
|
||
$results['details'][] = $result;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
|
||
function createStatusManager($testRunner)
|
||
{
|
||
$apiClient = new ApiClient();
|
||
$configV3 = new ConfigV3();
|
||
$apiClient->setBaseUrl($configV3->getBaseUrl());
|
||
|
||
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
|
||
$oauth2Handler->setAccessible(true);
|
||
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
|
||
if ($oauth2HandlerInstance) {
|
||
$apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader());
|
||
}
|
||
|
||
return new StatusManager($apiClient);
|
||
}
|
||
|
||
function findUploadFolder($testRunner, $campaignId, $configV3)
|
||
{
|
||
$finalFolderName = $configV3->getFolderName('final_assets');
|
||
|
||
$requests = $testRunner->getAvailableRequests();
|
||
|
||
foreach ($requests as $index => $request) {
|
||
$name = strtolower($request['name']);
|
||
if (strpos($name, 'retrieve master asset folder') !== false ||
|
||
strpos($name, 'master asset folder and final') !== false) {
|
||
|
||
$modifiedRequest = $request;
|
||
$url = is_array($request['request']['url']) ? $request['request']['url']['raw'] : $request['request']['url'];
|
||
$url = preg_replace('/folders\/[a-f0-9]+\//', "folders/{$campaignId}/", $url);
|
||
$url = str_replace('{{baseUrl}}', $configV3->getBaseUrl(), $url);
|
||
|
||
if (is_array($modifiedRequest['request']['url'])) {
|
||
$modifiedRequest['request']['url']['raw'] = $url;
|
||
} else {
|
||
$modifiedRequest['request']['url'] = $url;
|
||
}
|
||
|
||
$result = $testRunner->runSingleTest($modifiedRequest, $index);
|
||
|
||
if ($result['status'] === 'PASS') {
|
||
$data = json_decode($result['response']['body'], true);
|
||
$folders = $data['folder_children']['asset_list'] ?? [];
|
||
|
||
foreach ($folders as $folder) {
|
||
$folderName = extractFolderName($folder);
|
||
// Look for Final Assets or Localized folder
|
||
if (strpos($folderName, 'Final') !== false ||
|
||
strpos($folderName, 'Localized') !== false ||
|
||
$folderName === $finalFolderName) {
|
||
return $folder['asset_id'];
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function fetchFullAssetMetadata($testRunner, $assetId)
|
||
{
|
||
$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());
|
||
}
|
||
|
||
// Fetch full asset with metadata
|
||
$request = [
|
||
'method' => 'GET',
|
||
'url' => "/v6/assets/{$assetId}?load_type=full"
|
||
];
|
||
|
||
$response = $apiClient->executeRequest($request);
|
||
|
||
if ($response['success']) {
|
||
$data = json_decode($response['body'], true);
|
||
return $data['asset'] ?? null;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function uploadAssetsToBox($downloadResults, $campaignId, $campaignName, $masterAssets, $uploadFolderId = null)
|
||
{
|
||
// Debug
|
||
error_log("Box Upload: Starting with " . count($downloadResults['details'] ?? []) . " downloads");
|
||
|
||
// Load Box credentials and use JWT authentication
|
||
$boxConfig = json_decode(file_get_contents(__DIR__ . '/Box-config.json'), true);
|
||
$clientId = $boxConfig['boxAppSettings']['clientID'];
|
||
$clientSecret = $boxConfig['boxAppSettings']['clientSecret'];
|
||
|
||
$boxClient = new BoxClient($clientId, $clientSecret);
|
||
$idGenerator = new IDGenerator(true); // Use database for ID generation
|
||
$dbClient = new DatabaseClient();
|
||
|
||
// Test Box connection first
|
||
$connectionTest = $boxClient->testConnection();
|
||
error_log("Box Connection Test: " . ($connectionTest['success'] ? 'SUCCESS' : 'FAILED'));
|
||
|
||
if (!$connectionTest['success']) {
|
||
return [
|
||
'success' => false,
|
||
'error' => 'Box connection failed. Check developer token.',
|
||
'total' => 0,
|
||
'successful' => 0,
|
||
'failed' => 0
|
||
];
|
||
}
|
||
|
||
// Create campaign folder in Box
|
||
$folderResult = $boxClient->createCampaignFolder($campaignId, $campaignName);
|
||
error_log("Box Folder Creation: " . ($folderResult['success'] ? 'SUCCESS' : 'FAILED'));
|
||
|
||
if (!$folderResult['success']) {
|
||
return [
|
||
'success' => false,
|
||
'error' => 'Failed to create Box folder: ' . ($folderResult['error'] ?? 'Unknown'),
|
||
'total' => 0,
|
||
'successful' => 0,
|
||
'failed' => 0
|
||
];
|
||
}
|
||
|
||
$boxFolderId = $folderResult['folder_id'];
|
||
|
||
$downloadDetails = $downloadResults['details'] ?? [];
|
||
error_log("Box Upload: Processing " . count($downloadDetails) . " files");
|
||
error_log("Box Upload: Upload folder ID passed: " . ($uploadFolderId ?? 'NULL'));
|
||
error_log("Box Upload: Master assets count: " . count($masterAssets));
|
||
|
||
$results = [
|
||
'total' => count($downloadDetails),
|
||
'successful' => 0,
|
||
'failed' => 0,
|
||
'details' => [],
|
||
'box_folder_id' => $boxFolderId,
|
||
'box_folder_name' => $folderResult['folder_name']
|
||
];
|
||
|
||
// Upload each successfully downloaded file to Box
|
||
foreach ($downloadDetails as $index => $download) {
|
||
if (!$download['success']) {
|
||
$results['details'][] = [
|
||
'success' => false,
|
||
'filename' => $download['filename'] ?? 'Unknown',
|
||
'error' => 'Download failed'
|
||
];
|
||
$results['failed']++;
|
||
continue;
|
||
}
|
||
|
||
// Generate unique ID
|
||
$idResult = $idGenerator->generateId();
|
||
$uniqueId = $idResult['id'];
|
||
|
||
// Get asset metadata - use numeric index to match download order
|
||
$assetMetadata = $masterAssets[$index] ?? [];
|
||
error_log("Box Upload: Asset index " . $index . " has " . count(array_keys($assetMetadata)) . " keys");
|
||
|
||
// Upload to Box
|
||
$boxUploadResult = $boxClient->uploadFile(
|
||
$download['filepath'],
|
||
$download['filename'],
|
||
$uniqueId,
|
||
$boxFolderId,
|
||
$assetMetadata
|
||
);
|
||
|
||
if ($boxUploadResult['success']) {
|
||
$results['successful']++;
|
||
|
||
// Store in database with upload folder ID
|
||
error_log("Box Upload: Storing in DB with upload folder: " . ($uploadFolderId ?? 'NULL'));
|
||
|
||
$dbResult = $dbClient->storeMasterAsset(
|
||
$uniqueId,
|
||
$assetMetadata,
|
||
$boxUploadResult['file_id'],
|
||
$boxUploadResult['box_url'],
|
||
$uploadFolderId // MISSING PARAMETER - was causing NULL!
|
||
);
|
||
|
||
$results['details'][] = [
|
||
'success' => true,
|
||
'original_filename' => $download['filename'],
|
||
'box_filename' => $boxUploadResult['filename'],
|
||
'unique_id' => $uniqueId,
|
||
'box_file_id' => $boxUploadResult['file_id'],
|
||
'box_url' => $boxUploadResult['box_url'],
|
||
'db_stored' => $dbResult['success'] ?? false,
|
||
'id_source' => $idResult['source'] ?? 'unknown'
|
||
];
|
||
} else {
|
||
$results['failed']++;
|
||
$results['details'][] = [
|
||
'success' => false,
|
||
'filename' => $download['filename'],
|
||
'error' => $boxUploadResult['error'] ?? 'Unknown error'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
|
||
function uploadFiles($testRunner, $uploadedFiles, $folderId, $selectedMasterAsset = null)
|
||
{
|
||
$apiClient = new ApiClient();
|
||
$configV3 = new ConfigV3();
|
||
$apiClient->setBaseUrl($configV3->getBaseUrl());
|
||
|
||
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
|
||
$oauth2Handler->setAccessible(true);
|
||
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
|
||
if ($oauth2HandlerInstance) {
|
||
$apiClient->setHeader('Authorization', $oauth2HandlerInstance->getAuthHeader());
|
||
}
|
||
|
||
// Use SIMPLE uploader that works!
|
||
$uploader = new AssetUploaderSimple($apiClient);
|
||
|
||
$results = [
|
||
'total' => 0,
|
||
'successful' => 0,
|
||
'failed' => 0,
|
||
'details' => []
|
||
];
|
||
|
||
// Handle multiple file upload
|
||
if (isset($uploadedFiles['tmp_name'])) {
|
||
$fileCount = is_array($uploadedFiles['tmp_name']) ? count($uploadedFiles['tmp_name']) : 1;
|
||
$results['total'] = $fileCount;
|
||
|
||
for ($i = 0; $i < $fileCount; $i++) {
|
||
$tmpName = is_array($uploadedFiles['tmp_name']) ? $uploadedFiles['tmp_name'][$i] : $uploadedFiles['tmp_name'];
|
||
$fileName = is_array($uploadedFiles['name']) ? $uploadedFiles['name'][$i] : $uploadedFiles['name'];
|
||
$fileError = is_array($uploadedFiles['error']) ? $uploadedFiles['error'][$i] : $uploadedFiles['error'];
|
||
|
||
if ($fileError !== UPLOAD_ERR_OK) {
|
||
$results['details'][] = [
|
||
'success' => false,
|
||
'filename' => $fileName,
|
||
'error' => 'Upload error code: ' . $fileError
|
||
];
|
||
$results['failed']++;
|
||
continue;
|
||
}
|
||
|
||
// Create temp file with actual filename (not phpXXXXX)
|
||
$actualFilePath = sys_get_temp_dir() . '/' . $fileName;
|
||
copy($tmpName, $actualFilePath);
|
||
|
||
$result = $uploader->uploadFile($actualFilePath, $folderId);
|
||
|
||
// Clean up
|
||
@unlink($actualFilePath);
|
||
|
||
if ($result['success']) {
|
||
$results['successful']++;
|
||
} else {
|
||
$results['failed']++;
|
||
}
|
||
|
||
$results['details'][] = $result;
|
||
}
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
|
||
$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>Ferrero Content Scaling Workflow</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
body {
|
||
font-family: 'Montserrat', -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, #431b06 0%, #6b2d10 100%);
|
||
color: white;
|
||
padding: 30px;
|
||
text-align: center;
|
||
}
|
||
|
||
.header h1 {
|
||
margin-bottom: 10px;
|
||
font-weight: 600;
|
||
letter-spacing: -0.5px;
|
||
}
|
||
.header p {
|
||
opacity: 0.9;
|
||
font-weight: 300;
|
||
}
|
||
|
||
.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: #431b06;
|
||
border-bottom: 3px solid #431b06;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.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: #431b06;
|
||
color: white;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.btn-primary:hover { background: #6b2d10; }
|
||
|
||
.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: #431b06;
|
||
box-shadow: 0 4px 12px rgba(67, 27, 6, 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>
|
||
<button class="tab <?= $currentTab === 'box-upload' ? 'active' : '' ?>"
|
||
onclick="switchTab('box-upload')">
|
||
📦 Upload from Box (A2→A3)
|
||
</button>
|
||
<button class="tab <?= $currentTab === 'global-masters' ? 'active' : '' ?>"
|
||
onclick="switchTab('global-masters')">
|
||
🌍 Global Masters (B1→B2)
|
||
</button>
|
||
<button class="tab <?= $currentTab === 'debug-view' ? 'active' : '' ?>"
|
||
onclick="switchTab('debug-view')">
|
||
🔧 Debug View
|
||
</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 (Content Scaling Status = A1)</button>
|
||
</form>
|
||
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="download">
|
||
<input type="hidden" name="action" value="debug_all_campaigns">
|
||
<button type="submit" class="btn btn-secondary">🔍 Debug: Load ALL Campaigns (no filter)</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['debug_campaigns']) || isset($results['debug_search_response'])): ?>
|
||
<div class="alert alert-<?= ($results['debug_search_response']['http_code'] ?? 0) == 503 ? 'error' : 'info' ?>" style="margin-top: 30px;">
|
||
<h3>🔍 Debug Results: Found <?= count($results['debug_campaigns'] ?? []) ?> Campaigns</h3>
|
||
|
||
<?php if (isset($results['oauth_debug'])): ?>
|
||
<p style="font-size: 13px; margin: 10px 0; padding: 10px; background: white; border-radius: 4px;">
|
||
<strong>OAuth Status:</strong>
|
||
<?= $results['oauth_debug']['has_token'] ? '✅ Token Active' : '❌ No Token' ?> |
|
||
Expires: <?= htmlspecialchars($results['oauth_debug']['expires_at']) ?>
|
||
</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['debug_search_response'])): ?>
|
||
<p style="font-size: 13px; margin: 10px 0; padding: 10px; background: white; border-radius: 4px;">
|
||
<strong>API Response:</strong> HTTP <?= $results['debug_search_response']['http_code'] ?>
|
||
<?php if ($results['debug_search_response']['http_code'] == 503): ?>
|
||
<span style="color: #dc3545; font-weight: bold;">- Service Unavailable (Server may be down or OAuth token expired)</span>
|
||
<?php endif; ?>
|
||
<br>
|
||
<strong>Total results from API:</strong> <?= $results['debug_search_response']['total_results'] ?? 0 ?><br>
|
||
<strong>URL:</strong> <code style="font-size: 11px;"><?= htmlspecialchars($results['debug_search_response']['url']) ?></code>
|
||
<?php if (isset($results['debug_search_response']['response_body_preview'])): ?>
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer;">View Response Body</summary>
|
||
<pre style="font-size: 11px; background: #f8f9fa; padding: 10px; margin-top: 5px;"><?= htmlspecialchars($results['debug_search_response']['response_body_preview']) ?></pre>
|
||
</details>
|
||
<?php endif; ?>
|
||
</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($results['debug_campaigns'])): ?>
|
||
<p>Showing ALL campaigns without status filter to see their metadata fields:</p>
|
||
|
||
<?php foreach ($results['debug_campaigns'] as $idx => $campaign): ?>
|
||
<details style="margin: 15px 0; background: white; padding: 15px; border-radius: 6px;">
|
||
<summary style="cursor: pointer; font-weight: 600;">
|
||
Campaign <?= $idx + 1 ?>: <?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed') ?>
|
||
(<?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?>)
|
||
- Content Scaling Status: <span class="status-badge status-<?= strtolower($campaign['status'] ?? 'unknown') ?>"><?= htmlspecialchars($campaign['status'] ?? 'NOT FOUND') ?></span>
|
||
</summary>
|
||
<div style="margin-top: 15px;">
|
||
<p><strong>Asset ID:</strong> <?= htmlspecialchars($campaign['asset_id']) ?></p>
|
||
<p><strong>Campaign ID:</strong> <?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?></p>
|
||
<p><strong>Content Scaling Status:</strong> <?= htmlspecialchars($campaign['status'] ?? 'NOT FOUND') ?></p>
|
||
<p><strong>Brand:</strong> <?= htmlspecialchars($campaign['brand'] ?? 'N/A') ?></p>
|
||
<p><strong>Market:</strong> <?= htmlspecialchars($campaign['market'] ?? 'N/A') ?></p>
|
||
|
||
<form method="POST" style="margin-top: 15px; display: inline-block;">
|
||
<input type="hidden" name="tab" value="download">
|
||
<input type="hidden" name="action" value="reset_to_a1">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-danger" onclick="return confirm('Reset campaign <?= htmlspecialchars($campaign['campaign_name']) ?> to A1 status?')">
|
||
🔄 Reset to A1 (for testing)
|
||
</button>
|
||
</form>
|
||
|
||
<?php if ($campaign['status'] === 'B1'): ?>
|
||
<form method="POST" style="margin-top: 15px; display: inline-block; margin-left: 10px;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="update_status_to_b2">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-success" onclick="return confirm('Update campaign <?= htmlspecialchars($campaign['campaign_name']) ?> to B2 status?')">
|
||
✅ Update B1 → B2
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($campaign['status'] === 'B2'): ?>
|
||
<form method="POST" style="margin-top: 15px; display: inline-block; margin-left: 10px;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="reset_to_b1">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-warning" onclick="return confirm('Reset campaign <?= htmlspecialchars($campaign['campaign_name']) ?> to B1 status?')">
|
||
🔄 Reset B2 → B1 (for testing)
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer; font-size: 13px;">View Full Raw Metadata</summary>
|
||
<pre style="background: #f0f0f0; padding: 10px; border-radius: 4px; overflow: auto; max-height: 400px; font-size: 11px; margin-top: 10px;"><?= htmlspecialchars(json_encode($campaign, JSON_PRETTY_PRINT)) ?></pre>
|
||
</details>
|
||
</div>
|
||
</details>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<p style="margin-top: 15px;">No campaigns returned from API (check OAuth status and response body above)</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['debug_all_campaigns_count'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 20px;">
|
||
<strong>🔍 Debug Info:</strong><br>
|
||
Found <?= $results['debug_all_campaigns_count'] ?> total campaigns before filtering<br>
|
||
Filtering for Content Scaling Status: "<?= htmlspecialchars($results['debug_status_filter']) ?>"<br>
|
||
Campaigns after filtering: <?= $results['debug_filtered_count'] ?>
|
||
</div>
|
||
<?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><strong>Content Scaling Status:</strong> <span class="status-badge status-a1"><?= htmlspecialchars($campaign['status'] ?? 'N/A') ?> - 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: #431b06; font-size: 12px;">
|
||
🔍 Debug folder structure for this campaign
|
||
</a>
|
||
</div>
|
||
|
||
<form method="POST" style="margin-top: 20px; display: inline-block; margin-right: 10px;">
|
||
<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>
|
||
|
||
<form method="POST" style="margin-top: 20px; display: inline-block;">
|
||
<input type="hidden" name="tab" value="download">
|
||
<input type="hidden" name="action" value="get_final_assets">
|
||
<button type="submit" class="btn btn-success">Get Final Assets (Uploaded)</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; display: inline-block; margin-right: 10px;">
|
||
<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>
|
||
|
||
<form method="POST" style="margin: 20px 0; display: inline-block;">
|
||
<input type="hidden" name="tab" value="download">
|
||
<input type="hidden" name="action" value="download_and_upload_to_box">
|
||
<button type="submit" class="btn btn-primary">📥📦 Download & Upload to Box</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>
|
||
<form method="POST" style="display: inline;">
|
||
<input type="hidden" name="tab" value="download">
|
||
<input type="hidden" name="action" value="download_asset_metadata">
|
||
<input type="hidden" name="asset_id" value="<?= htmlspecialchars($assetId) ?>">
|
||
<input type="hidden" name="filename" value="<?= htmlspecialchars($assetName) ?>">
|
||
<button type="submit" class="btn btn-secondary">💾 JSON</button>
|
||
</form>
|
||
<button class="btn btn-secondary"
|
||
onclick="toggleMetadata('<?= $metadataId ?>')">
|
||
📋 View
|
||
</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 #431b06;">
|
||
<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; ?>
|
||
|
||
<!-- CREATIVEX Fields -->
|
||
<?php if (isset($metadata['creativex_fields']) && !empty($metadata['creativex_fields'])): ?>
|
||
<details style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #9b59b6;">
|
||
<summary style="cursor: pointer; font-weight: 600; color: #333;">🎯 CREATIVEX Fields (<?= count($metadata['creativex_fields']) ?>)</summary>
|
||
<div style="margin-top: 8px; display: grid; grid-template-columns: 250px 1fr; gap: 5px;">
|
||
<?php foreach ($metadata['creativex_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>
|
||
<br><small style="color: #999;"><?= htmlspecialchars($fieldData['id']) ?></small>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</details>
|
||
<?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['final_assets']) && !empty($results['final_assets'])): ?>
|
||
<h3 style="margin-top: 30px;">Final Assets / Uploaded Assets (<?= count($results['final_assets']) ?> files)</h3>
|
||
<p style="color: #666; font-size: 14px; margin: 10px 0;">
|
||
These are the localized/processed assets that have been uploaded back to the DAM.
|
||
</p>
|
||
|
||
<div class="asset-list">
|
||
<?php foreach ($results['final_assets'] as $index => $asset): ?>
|
||
<?php
|
||
$assetName = extractFolderName($asset);
|
||
$assetId = $asset['asset_id'];
|
||
$metadataId = 'final-metadata-' . $index;
|
||
?>
|
||
<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; ?>
|
||
<?php if (isset($asset['metadata_model_id'])): ?>
|
||
<br><small style="color: #28a745;">✅ Model: <?= htmlspecialchars($asset['metadata_model_id']) ?></small>
|
||
<?php endif; ?>
|
||
</div>
|
||
<div class="asset-actions">
|
||
<button class="btn btn-secondary"
|
||
onclick="toggleMetadata('<?= $metadataId ?>')">
|
||
📋 View 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 #28a745;">
|
||
<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): ?>
|
||
<div style="color: #666;"><?= ucwords(str_replace('_', ' ', $key)) ?>:</div>
|
||
<div><strong><?= htmlspecialchars($value) ?></strong></div>
|
||
<?php endif; ?>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- Custom Metadata Fields (by Category) - SAME FORMAT AS MASTER -->
|
||
<?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; ?>
|
||
|
||
<!-- CREATIVEX Fields (Final Assets) -->
|
||
<?php if (isset($metadata['creativex_fields']) && !empty($metadata['creativex_fields'])): ?>
|
||
<details open style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #9b59b6;">
|
||
<summary style="cursor: pointer; font-weight: 600; color: #333;">🎯 CREATIVEX Fields (<?= count($metadata['creativex_fields']) ?>)</summary>
|
||
<div style="margin-top: 8px; display: grid; grid-template-columns: 250px 1fr; gap: 5px;">
|
||
<?php foreach ($metadata['creativex_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>
|
||
<br><small style="color: #999;"><?= htmlspecialchars($fieldData['id']) ?></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>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['status_update_error'])): ?>
|
||
<div class="alert alert-error" style="margin-top: 20px;">
|
||
<strong>⚠️ Status Update Debug Information:</strong>
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer; font-weight: 600;">View detailed error information</summary>
|
||
<div style="margin-top: 10px; font-size: 12px; font-family: monospace;">
|
||
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 5px 0;">
|
||
<strong>HTTP Status Code:</strong> <?= htmlspecialchars($results['status_update_error']['http_code']) ?>
|
||
</div>
|
||
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 5px 0;">
|
||
<strong>Folder ID:</strong> <?= htmlspecialchars($results['status_update_error']['folder_id']) ?>
|
||
</div>
|
||
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 5px 0;">
|
||
<strong>Target Status:</strong> <?= htmlspecialchars($results['status_update_error']['new_status']) ?>
|
||
</div>
|
||
<?php if (isset($results['status_update_error']['response']['body'])): ?>
|
||
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 5px 0;">
|
||
<strong>API Response Body:</strong>
|
||
<pre style="margin-top: 5px; white-space: pre-wrap; word-wrap: break-word;"><?= htmlspecialchars($results['status_update_error']['response']['body']) ?></pre>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if (isset($results['status_update_error']['response']['url'])): ?>
|
||
<div style="background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 5px 0;">
|
||
<strong>Request URL:</strong> <?= htmlspecialchars($results['status_update_error']['response']['url']) ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</details>
|
||
</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; ?>
|
||
|
||
<?php if (isset($results['box_upload'])): ?>
|
||
<div class="alert alert-<?= $results['box_upload']['successful'] > 0 ? 'success' : 'error' ?>" style="margin-top: 20px;">
|
||
<strong>📦 Box Upload Results:</strong>
|
||
<?= $results['box_upload']['successful'] ?> of <?= $results['box_upload']['total'] ?> files uploaded to Box
|
||
<br><strong>Box Folder:</strong> <?= htmlspecialchars($results['box_upload']['box_folder_name'] ?? 'N/A') ?>
|
||
<br><strong>Folder ID:</strong> <code><?= htmlspecialchars($results['box_upload']['box_folder_id'] ?? 'N/A') ?></code>
|
||
|
||
<?php if (!empty($results['box_upload']['details'])): ?>
|
||
<details style="margin-top: 15px;">
|
||
<summary style="cursor: pointer;">View Box upload details</summary>
|
||
<div style="margin-top: 10px;">
|
||
<?php foreach ($results['box_upload']['details'] as $detail): ?>
|
||
<div style="padding: 8px; margin: 5px 0; background: white; border-radius: 4px;">
|
||
<?php if ($detail['success']): ?>
|
||
✅ <strong><?= htmlspecialchars($detail['original_filename']) ?></strong>
|
||
→ <?= htmlspecialchars($detail['box_filename']) ?>
|
||
<br><small>
|
||
Tracking ID: <code style="background: #d4edda; padding: 2px 6px; border-radius: 3px; font-weight: bold;"><?= htmlspecialchars($detail['unique_id']) ?></code> |
|
||
<a href="<?= htmlspecialchars($detail['box_url']) ?>" target="_blank" style="color: #007bff;">📦 View in Box</a>
|
||
<?php if (isset($detail['db_stored'])): ?>
|
||
| DB: <?= $detail['db_stored'] ? '✅ Stored' : '❌ Failed' ?>
|
||
<?php endif; ?>
|
||
<?php if (isset($detail['id_source'])): ?>
|
||
| ID Source: <?= htmlspecialchars($detail['id_source']) ?>
|
||
<?php endif; ?>
|
||
</small>
|
||
<?php else: ?>
|
||
❌ <?= htmlspecialchars($detail['filename']) ?>
|
||
<br><small>Error: <?= htmlspecialchars($detail['error']) ?></small>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</details>
|
||
<?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 (assets sent to agency), upload processed files, and update status to A3
|
||
</p>
|
||
|
||
<!-- Test Upload Section -->
|
||
<div style="background: #fff3cd; border: 2px solid #ffc107; border-radius: 8px; padding: 20px; margin-bottom: 30px;">
|
||
<h3 style="color: #856404;">🧪 Test Upload to Specific Folder</h3>
|
||
<p style="color: #856404; margin: 10px 0;">
|
||
Upload directly to a folder ID for testing (bypasses campaign workflow)
|
||
</p>
|
||
|
||
<?php if ($oauth2Status && ($oauth2Status['has_token'] ?? false)): ?>
|
||
<details style="background: white; padding: 10px; border-radius: 4px; margin-bottom: 15px;">
|
||
<summary style="cursor: pointer; font-weight: 600; color: #856404;">
|
||
📋 Copy OAuth Token for Standalone Test
|
||
</summary>
|
||
<div style="margin-top: 10px;">
|
||
<p style="font-size: 12px; color: #666;">
|
||
Use this token with: <code>php test_upload_standalone.php "token"</code>
|
||
</p>
|
||
<textarea readonly onclick="this.select()"
|
||
style="width: 100%; height: 80px; font-family: monospace; font-size: 11px; padding: 5px; margin-top: 5px;"><?php
|
||
$oauth2Handler = new ReflectionProperty($testRunner, 'oauth2Handler');
|
||
$oauth2Handler->setAccessible(true);
|
||
$oauth2HandlerInstance = $oauth2Handler->getValue($testRunner);
|
||
if ($oauth2HandlerInstance) {
|
||
$authHeader = $oauth2HandlerInstance->getAuthHeader();
|
||
echo str_replace('Bearer ', '', $authHeader);
|
||
}
|
||
?></textarea>
|
||
</div>
|
||
</details>
|
||
<?php endif; ?>
|
||
|
||
<form method="POST" enctype="multipart/form-data">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="test_upload_to_folder">
|
||
|
||
<div style="margin: 15px 0;">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: 600;">Target Folder ID:</label>
|
||
<input type="text" name="test_folder_id"
|
||
value="e96080ba0cd1427d253a28a87504b6665eaa02cb"
|
||
style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-family: monospace;">
|
||
</div>
|
||
|
||
<div style="margin: 15px 0;">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: 600;">Select file to upload:</label>
|
||
<input type="file" name="test_upload_file" required
|
||
style="padding: 10px; border: 2px solid #ffc107; border-radius: 6px; width: 100%; background: white;">
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary">🧪 Test Upload to This Folder</button>
|
||
</form>
|
||
|
||
<?php if (isset($results['test_upload_result'])): ?>
|
||
<?php $tr = $results['test_upload_result']; ?>
|
||
<div class="alert alert-<?= $tr['success'] ? 'success' : 'error' ?>" style="margin-top: 20px;">
|
||
<?php if ($tr['success']): ?>
|
||
<strong>✅ TEST UPLOAD SUCCESSFUL!</strong><br>
|
||
Filename: <?= htmlspecialchars($tr['filename']) ?><br>
|
||
Asset ID: <?= htmlspecialchars($tr['asset_id'] ?? 'N/A') ?><br>
|
||
Folder: <?= htmlspecialchars($results['test_folder_id']) ?>
|
||
<?php else: ?>
|
||
<strong>❌ Test Upload Failed:</strong> <?= htmlspecialchars($tr['error']) ?><br>
|
||
HTTP Code: <?= $tr['http_code'] ?><br>
|
||
Folder: <?= htmlspecialchars($results['test_folder_id']) ?>
|
||
<?php if (isset($tr['response_body'])): ?>
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer;">View API Response</summary>
|
||
<pre style="font-size: 11px; background: white; padding: 10px; margin-top: 5px;"><?= htmlspecialchars($tr['response_body']) ?></pre>
|
||
</details>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<hr style="margin: 30px 0;">
|
||
<!-- End Test Upload Section -->
|
||
|
||
<form method="POST" style="display: inline-block;">
|
||
<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 (Content Scaling Status = A2)</button>
|
||
</form>
|
||
|
||
<?php if (!empty($results) && $currentTab === 'upload'): ?>
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<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['a2_campaigns']) && !empty($results['a2_campaigns'])): ?>
|
||
<h3 style="margin-top: 30px;">Found <?= count($results['a2_campaigns']) ?> Campaigns</h3>
|
||
<div class="campaign-grid">
|
||
<?php foreach ($results['a2_campaigns'] as $campaign): ?>
|
||
<div class="campaign-card <?= (isset($results['selected_campaign_a2']) && $results['selected_campaign_a2']['asset_id'] === $campaign['asset_id']) ? 'selected' : '' ?>"
|
||
onclick="selectCampaignA2('<?= 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><strong>Content Scaling Status:</strong> <span class="status-badge status-a2"><?= htmlspecialchars($campaign['status'] ?? 'N/A') ?> - Assets Sent to Agency</span></p>
|
||
|
||
<form method="POST" style="margin-top: 10px;" onclick="event.stopPropagation();">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="reset_to_a1">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-danger" style="font-size: 12px; padding: 8px 12px;" onclick="return confirm('Reset <?= htmlspecialchars($campaign['campaign_name']) ?> to A1 for testing?')">
|
||
🔄 Reset to A1
|
||
</button>
|
||
</form>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<form method="POST" id="select-campaign-a2-form">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="select_campaign_a2">
|
||
<input type="hidden" name="campaign_id" id="selected-campaign-a2-id">
|
||
<button type="submit" class="btn btn-success" id="select-campaign-a2-btn" disabled>
|
||
Select Campaign & Continue
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['selected_campaign_a2'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 30px;">
|
||
<strong>Selected Campaign:</strong>
|
||
<?= htmlspecialchars($results['selected_campaign_a2']['campaign_name']) ?>
|
||
(<?= htmlspecialchars($results['selected_campaign_a2']['campaign_id']) ?>)
|
||
</div>
|
||
|
||
<?php if (!isset($results['upload_folder_id'])): ?>
|
||
<form method="POST" style="margin-top: 20px;">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="get_upload_folder">
|
||
<button type="submit" class="btn btn-primary">Find Upload Folder & Get Master Assets Metadata</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['upload_folder_id'])): ?>
|
||
<div class="alert alert-success" style="margin-top: 20px;">
|
||
✅ Upload target folder found
|
||
</div>
|
||
|
||
<h3 style="margin-top: 30px;">Upload Processed Files</h3>
|
||
|
||
<?php if (isset($results['master_assets_for_upload']) && !empty($results['master_assets_for_upload'])): ?>
|
||
<div class="alert alert-success" style="margin-bottom: 20px;">
|
||
✅ Found <?= count($results['master_assets_for_upload']) ?> master assets from this campaign
|
||
</div>
|
||
|
||
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
|
||
<h4>📋 Select Master Asset Metadata to Use:</h4>
|
||
<p style="color: #666; margin: 10px 0;">
|
||
Choose which master asset's metadata structure to use for your upload.
|
||
Your uploaded file will inherit all metadata (model, security, fields) from the selected master asset.
|
||
Only the filename will be updated to match your new file.
|
||
</p>
|
||
|
||
<?php foreach ($results['master_assets_for_upload'] as $idx => $masterAsset): ?>
|
||
<div style="background: white; border: 2px solid #dee2e6; border-radius: 6px; padding: 15px; margin: 10px 0;">
|
||
<label style="display: flex; align-items: center; cursor: pointer;">
|
||
<input type="radio" name="selected_master_metadata" value="<?= $idx ?>"
|
||
onchange="selectMasterMetadata(<?= $idx ?>)"
|
||
<?= $idx === 0 ? 'checked' : '' ?>
|
||
style="margin-right: 10px; transform: scale(1.3);">
|
||
<div>
|
||
<strong><?= htmlspecialchars($masterAsset['name'] ?? 'Unknown') ?></strong><br>
|
||
<small>Asset ID: <?= htmlspecialchars($masterAsset['asset_id']) ?></small><br>
|
||
<small>Type: <?= htmlspecialchars($masterAsset['mime_type'] ?? 'Unknown') ?></small>
|
||
<?php if (isset($masterAsset['metadata_model_id'])): ?>
|
||
<br><small style="color: #28a745;">✅ Model: <?= htmlspecialchars($masterAsset['metadata_model_id']) ?></small>
|
||
<?php else: ?>
|
||
<br><small style="color: #dc3545;">⚠️ No Metadata Model ID</small>
|
||
<?php endif; ?>
|
||
<?php if (isset($masterAsset['security_policy_list'])): ?>
|
||
<br><small style="color: #28a745;">✅ <?= count($masterAsset['security_policy_list']) ?> Security Policies</small>
|
||
<?php else: ?>
|
||
<br><small style="color: #dc3545;">⚠️ No Security Policies</small>
|
||
<?php endif; ?>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="alert alert-info" style="margin-bottom: 20px;">
|
||
ℹ️ <strong>Note:</strong> No master assets found.
|
||
<br>Click "Find Upload Folder" above to fetch master assets from this campaign.
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form method="POST" enctype="multipart/form-data">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="upload_files">
|
||
<input type="hidden" name="master_metadata_index" id="master-metadata-index" value="0">
|
||
|
||
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
||
<label style="display: block; margin-bottom: 10px; font-weight: 600;">
|
||
Select files to upload:
|
||
</label>
|
||
<input type="file" name="upload_files[]" multiple
|
||
accept=".jpg,.jpeg,.png,.gif,.pdf,.ai,.psd,.eps,.tif,.tiff,.mov,.mp4,.avi,.zip,.txt,.doc,.docx,.xls,.xlsx"
|
||
style="padding: 10px; border: 2px dashed #431b06; border-radius: 6px; width: 100%; background: white;">
|
||
<p style="font-size: 13px; color: #666; margin-top: 10px;">
|
||
Accepted formats: Images (JPG, PNG, GIF, TIFF), Documents (PDF, AI, PSD, EPS), Video (MOV, MP4, AVI), Archives (ZIP), Office (DOC, XLS, TXT)
|
||
</p>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-success">📤 Upload Files to DAM</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['upload_debug'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 20px;">
|
||
<strong>🔍 Upload Debug Info:</strong><br>
|
||
<strong>Your File:</strong> <?= htmlspecialchars($results['upload_debug']['upload_filename']) ?>
|
||
(<?= htmlspecialchars($results['upload_debug']['upload_detected_mime']) ?>)<br>
|
||
<strong>Target Folder ID:</strong> <?= htmlspecialchars($results['upload_debug']['upload_folder_id']) ?><br>
|
||
<hr style="margin: 10px 0;">
|
||
<strong>Using Metadata From:</strong> <?= htmlspecialchars($results['upload_debug']['selected_master_name']) ?><br>
|
||
Master Asset ID: <?= htmlspecialchars($results['upload_debug']['selected_master_asset_id']) ?><br>
|
||
Metadata Model ID: <strong><?= htmlspecialchars($results['upload_debug']['metadata_model_id']) ?></strong><br>
|
||
Has Security Policies: <?= $results['upload_debug']['has_security_policies'] ?> (<?= $results['upload_debug']['security_policy_count'] ?> policies)<br>
|
||
Master MIME Type: <?= htmlspecialchars($results['upload_debug']['master_mime_type']) ?><br>
|
||
<hr style="margin: 10px 0;">
|
||
<strong>Sending:</strong> asset_representation (model ID + security policies only) + manifest + parent_folder_id + files<br>
|
||
<small>Note: Full metadata too large to send - using model ID inheritance instead</small>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['upload_results'])): ?>
|
||
<?php $ur = $results['upload_results']; ?>
|
||
<div class="alert alert-<?= $ur['successful'] > 0 ? 'success' : 'error' ?>" style="margin-top: 20px;">
|
||
<strong>Upload Results:</strong>
|
||
<?= $ur['successful'] ?> of <?= $ur['total'] ?> files uploaded successfully
|
||
|
||
<?php if (!empty($ur['details'])): ?>
|
||
<details style="margin-top: 15px;">
|
||
<summary style="cursor: pointer;">View upload details</summary>
|
||
<div style="margin-top: 10px;">
|
||
<?php foreach ($ur['details'] as $idx => $detail): ?>
|
||
<div style="padding: 8px; margin: 5px 0; background: white; border-radius: 4px;">
|
||
<?php if ($detail['success']): ?>
|
||
✅ <?= htmlspecialchars($detail['filename']) ?>
|
||
<br><small>Asset ID: <?= htmlspecialchars($detail['asset_id'] ?? 'N/A') ?></small>
|
||
<?php else: ?>
|
||
❌ <?= htmlspecialchars($detail['filename'] ?? 'Unknown') ?>
|
||
<br><small style="color: #dc3545;"><strong>Error:</strong> <?= htmlspecialchars($detail['error']) ?></small>
|
||
<?php if (isset($detail['http_code'])): ?>
|
||
<br><small>HTTP Code: <?= $detail['http_code'] ?></small>
|
||
<?php endif; ?>
|
||
<?php if (isset($detail['response_body']) && !empty($detail['response_body'])): ?>
|
||
<details style="margin-top: 5px;">
|
||
<summary style="cursor: pointer; font-size: 11px;">View API Response</summary>
|
||
<pre style="font-size: 10px; background: #f8f9fa; padding: 5px; margin-top: 5px; max-height: 200px; overflow: auto;"><?= htmlspecialchars($detail['response_body']) ?></pre>
|
||
</details>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</details>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if ($ur['successful'] > 0): ?>
|
||
<div style="margin-top: 30px; padding: 20px; background: #d4edda; border-radius: 8px;">
|
||
<h4>✅ Update Status to A3</h4>
|
||
<p style="margin: 10px 0;">
|
||
Files have been uploaded. Update the campaign status to A3
|
||
(Localized Asset received from Agency)
|
||
</p>
|
||
<form method="POST">
|
||
<input type="hidden" name="tab" value="upload">
|
||
<input type="hidden" name="action" value="update_status_to_a3">
|
||
<button type="submit" class="btn btn-success">Update Status: A2 → A3</button>
|
||
</form>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
</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" style="display: inline-block;">
|
||
<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 (Content Scaling Status = A5)</button>
|
||
</form>
|
||
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="debug_all_campaigns_rework">
|
||
<button type="submit" class="btn btn-secondary">🔍 Debug: Load ALL Campaigns (no filter)</button>
|
||
</form>
|
||
|
||
<?php if (!empty($results) && $currentTab === 'rework'): ?>
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<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['debug_campaigns_rework']) || isset($results['debug_search_response_rework'])): ?>
|
||
<div class="alert alert-<?= ($results['debug_search_response_rework']['http_code'] ?? 0) == 503 ? 'error' : 'info' ?>" style="margin-top: 30px;">
|
||
<h3>🔍 Debug Results: Found <?= count($results['debug_campaigns_rework'] ?? []) ?> Campaigns</h3>
|
||
|
||
<?php if (isset($results['oauth_debug_rework'])): ?>
|
||
<p style="font-size: 13px; margin: 10px 0; padding: 10px; background: white; border-radius: 4px;">
|
||
<strong>OAuth Status:</strong>
|
||
<?= $results['oauth_debug_rework']['has_token'] ? '✅ Token Active' : '❌ No Token' ?> |
|
||
Expires: <?= htmlspecialchars($results['oauth_debug_rework']['expires_at']) ?>
|
||
</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['debug_search_response_rework'])): ?>
|
||
<p style="font-size: 13px; margin: 10px 0; padding: 10px; background: white; border-radius: 4px;">
|
||
<strong>API Response:</strong> HTTP <?= $results['debug_search_response_rework']['http_code'] ?>
|
||
<?php if ($results['debug_search_response_rework']['http_code'] == 503): ?>
|
||
<span style="color: #dc3545; font-weight: bold;">- Service Unavailable</span>
|
||
<?php endif; ?>
|
||
<br>
|
||
<strong>Total results from API:</strong> <?= $results['debug_search_response_rework']['total_results'] ?? 0 ?><br>
|
||
<strong>URL:</strong> <code style="font-size: 11px;"><?= htmlspecialchars($results['debug_search_response_rework']['url']) ?></code>
|
||
</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($results['debug_campaigns_rework'])): ?>
|
||
<p>Showing ALL campaigns - use reset button to change any to A5 for testing:</p>
|
||
|
||
<?php foreach ($results['debug_campaigns_rework'] as $idx => $campaign): ?>
|
||
<details style="margin: 15px 0; background: white; padding: 15px; border-radius: 6px;">
|
||
<summary style="cursor: pointer; font-weight: 600;">
|
||
Campaign <?= $idx + 1 ?>: <?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed') ?>
|
||
(<?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?>)
|
||
- Content Scaling Status: <span class="status-badge status-<?= strtolower($campaign['status'] ?? 'unknown') ?>"><?= htmlspecialchars($campaign['status'] ?? 'NOT FOUND') ?></span>
|
||
</summary>
|
||
<div style="margin-top: 15px;">
|
||
<p><strong>Asset ID:</strong> <?= htmlspecialchars($campaign['asset_id']) ?></p>
|
||
<p><strong>Campaign ID:</strong> <?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?></p>
|
||
<p><strong>Content Scaling Status:</strong> <?= htmlspecialchars($campaign['status'] ?? 'NOT FOUND') ?></p>
|
||
<p><strong>Brand:</strong> <?= htmlspecialchars($campaign['brand'] ?? 'N/A') ?></p>
|
||
<p><strong>Market:</strong> <?= htmlspecialchars($campaign['market'] ?? 'N/A') ?></p>
|
||
|
||
<form method="POST" style="margin-top: 15px; display: inline-block;">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="reset_to_a5">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-danger" onclick="return confirm('Reset campaign <?= htmlspecialchars($campaign['campaign_name']) ?> to A5 status?')">
|
||
🔄 Reset to A5 (for testing)
|
||
</button>
|
||
</form>
|
||
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer; font-size: 13px;">View Full Raw Metadata</summary>
|
||
<pre style="background: #f0f0f0; padding: 10px; border-radius: 4px; overflow: auto; max-height: 400px; font-size: 11px; margin-top: 10px;"><?= htmlspecialchars(json_encode($campaign, JSON_PRETTY_PRINT)) ?></pre>
|
||
</details>
|
||
</div>
|
||
</details>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<p style="margin-top: 15px;">No campaigns returned from API (check OAuth status and response above)</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['a5_campaigns']) && !empty($results['a5_campaigns'])): ?>
|
||
<h3 style="margin-top: 30px;">Found <?= count($results['a5_campaigns']) ?> Campaigns Needing Rework</h3>
|
||
<div class="campaign-grid">
|
||
<?php foreach ($results['a5_campaigns'] as $campaign): ?>
|
||
<div class="campaign-card <?= (isset($results['selected_campaign_a5']) && $results['selected_campaign_a5']['asset_id'] === $campaign['asset_id']) ? 'selected' : '' ?>"
|
||
onclick="selectCampaignA5('<?= 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><strong>Content Scaling Status:</strong> <span class="status-badge status-a5"><?= htmlspecialchars($campaign['status'] ?? 'N/A') ?> - Rework Needed</span></p>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<form method="POST" id="select-campaign-a5-form">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="select_campaign_a5">
|
||
<input type="hidden" name="campaign_id" id="selected-campaign-a5-id">
|
||
<button type="submit" class="btn btn-success" id="select-campaign-a5-btn" disabled>
|
||
Select Campaign & Continue
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['selected_campaign_a5'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 30px;">
|
||
<strong>Selected Campaign:</strong>
|
||
<?= htmlspecialchars($results['selected_campaign_a5']['campaign_name']) ?>
|
||
(<?= htmlspecialchars($results['selected_campaign_a5']['campaign_id']) ?>)
|
||
</div>
|
||
|
||
<form method="POST" style="margin-top: 20px;">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="get_rework_assets">
|
||
<button type="submit" class="btn btn-primary">Get Rework Assets</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['rework_assets']) && !empty($results['rework_assets'])): ?>
|
||
<h3 style="margin-top: 30px;">Rework Assets (<?= count($results['rework_assets']) ?> files)</h3>
|
||
|
||
<form method="POST" style="margin: 20px 0;">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="download_all_rework">
|
||
<button type="submit" class="btn btn-success">📥 Download All Rework Assets</button>
|
||
</form>
|
||
|
||
<div class="asset-list">
|
||
<?php foreach ($results['rework_assets'] as $index => $asset): ?>
|
||
<?php
|
||
$assetName = extractFolderName($asset);
|
||
$assetId = $asset['asset_id'];
|
||
$metadataId = 'rework-metadata-' . $index;
|
||
?>
|
||
<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="rework">
|
||
<input type="hidden" name="action" value="download_rework_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;">
|
||
<!-- Same metadata display as download tab -->
|
||
<?php if (isset($metadata['basic'])): ?>
|
||
<div style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #431b06;">
|
||
<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; ?>
|
||
</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 A6</h4>
|
||
<p style="margin: 10px 0;">
|
||
Once rework assets are downloaded, update the campaign status to A6
|
||
(Assets to be reworked received by the Agency)
|
||
</p>
|
||
<form method="POST">
|
||
<input type="hidden" name="tab" value="rework">
|
||
<input type="hidden" name="action" value="update_status_to_a6">
|
||
<button type="submit" class="btn btn-success">Update Status: A5 → A6</button>
|
||
</form>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['last_rework_download'])): ?>
|
||
<?php $dl = $results['last_rework_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</small>
|
||
<?php else: ?>
|
||
<strong>❌ Download Failed:</strong> <?= htmlspecialchars($dl['error']) ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['rework_bulk_download'])): ?>
|
||
<div class="alert alert-success" style="margin-top: 20px;">
|
||
<strong>Bulk Download Results:</strong>
|
||
<?= $results['rework_bulk_download']['successful'] ?> of <?= $results['rework_bulk_download']['total'] ?> rework assets downloaded
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- Upload from Box Workflow Tab -->
|
||
<div id="tab-box-upload" class="tab-content <?= $currentTab === 'box-upload' ? 'active' : '' ?>">
|
||
<h2>📦 Upload from Box: A2 → A3</h2>
|
||
<p style="color: #666; margin: 10px 0 20px 0;">
|
||
Load files from a Box folder, parse V2 filenames, merge metadata, and upload to DAM
|
||
</p>
|
||
|
||
<!-- Box Folder Input -->
|
||
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
|
||
<h3>Step 1: Load Files from Box Folder</h3>
|
||
<div style="margin-top: 15px;">
|
||
<label for="box-folder-id" style="display: block; margin-bottom: 5px; font-weight: 600;">
|
||
Box Folder ID:
|
||
</label>
|
||
<div style="display: flex; gap: 10px;">
|
||
<input type="text"
|
||
id="box-folder-id"
|
||
placeholder="e.g., 348304357505"
|
||
value="348526703108"
|
||
style="flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||
<button type="button"
|
||
class="btn btn-primary"
|
||
onclick="loadBoxFiles()">
|
||
Load Files
|
||
</button>
|
||
</div>
|
||
<p style="margin-top: 8px; font-size: 13px; color: #666;">
|
||
Enter the Box Folder ID containing files ready for upload. Files must follow the V2 naming convention.
|
||
</p>
|
||
</div>
|
||
<div id="box-loading" style="display: none; margin-top: 15px; padding: 15px; background: #fff3cd; border-radius: 4px;">
|
||
<strong>⏳ Loading files from Box...</strong>
|
||
</div>
|
||
<div id="box-error" style="display: none; margin-top: 15px;" class="alert alert-error"></div>
|
||
</div>
|
||
|
||
<!-- File List Table -->
|
||
<div id="box-files-container" style="display: none;">
|
||
<h3>Step 2: Select Files to Upload</h3>
|
||
<p style="color: #666; margin-bottom: 15px;">
|
||
Review parsed filenames and select files to upload. ✅ Valid | ❌ Invalid
|
||
</p>
|
||
|
||
<div style="overflow-x: auto; background: white; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
|
||
<table style="width: 100%; border-collapse: collapse;">
|
||
<thead style="background: #f8f9fa;">
|
||
<tr>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">
|
||
<input type="checkbox" id="select-all-files" onclick="toggleAllFiles(this)">
|
||
</th>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">Filename</th>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">Tracking ID</th>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">Valid</th>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">Size</th>
|
||
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="box-files-list">
|
||
<!-- Populated by JavaScript -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div style="margin-top: 20px; display: flex; gap: 10px;">
|
||
<button type="button"
|
||
class="btn btn-success"
|
||
onclick="uploadSelectedFiles()"
|
||
id="upload-selected-btn">
|
||
Upload Selected Files
|
||
</button>
|
||
<button type="button"
|
||
class="btn btn-secondary"
|
||
onclick="clearBoxFiles()">
|
||
Clear
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Upload Progress -->
|
||
<div id="upload-progress-container" style="display: none; margin-top: 20px;">
|
||
<h3>Upload Progress</h3>
|
||
<div id="upload-progress-list"></div>
|
||
</div>
|
||
|
||
<!-- Upload Results -->
|
||
<div id="upload-results-container" style="display: none; margin-top: 20px;">
|
||
<h3>Upload Results</h3>
|
||
<div id="upload-results-summary" class="alert alert-info"></div>
|
||
<div id="upload-results-details"></div>
|
||
</div>
|
||
</div>
|
||
<!-- Global Masters B1→B2 Workflow Tab -->
|
||
<div id="tab-global-masters" class="tab-content <?= $currentTab === 'global-masters' ? 'active' : '' ?>">
|
||
<h2>🌍 Global Masters Workflow: B1 → B2</h2>
|
||
<p style="color: #666; margin: 10px 0 20px 0;">
|
||
Download Global Master assets for re-mastering workflow
|
||
</p>
|
||
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="load_campaigns_b1">
|
||
<button type="submit" class="btn btn-primary">Load Campaigns (Content Scaling Status = B1)</button>
|
||
</form>
|
||
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="debug_all_global_campaigns">
|
||
<button type="submit" class="btn btn-secondary">🔍 Debug: Load ALL Global Campaigns</button>
|
||
</form>
|
||
|
||
<?php if (!empty($results) && $currentTab === 'global-masters'): ?>
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<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['selected_campaign_b1'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 30px;">
|
||
<strong>Selected Campaign:</strong>
|
||
<?= htmlspecialchars($results['selected_campaign_b1']['campaign_name']) ?>
|
||
(<?= htmlspecialchars($results['selected_campaign_b1']['campaign_id'] ?? 'N/A') ?>)
|
||
<br>
|
||
<small><strong>Asset ID:</strong> <code><?= htmlspecialchars($results['selected_campaign_b1']['asset_id']) ?></code></small>
|
||
<br>
|
||
<small><strong>Type:</strong> Global Masters</small>
|
||
<br>
|
||
<a href="debug_assets.php?action=get_folders&campaign_id=<?= urlencode($results['selected_campaign_b1']['asset_id']) ?>"
|
||
target="_blank" style="color: #431b06; font-size: 12px;">
|
||
🔍 Debug folder structure for this campaign
|
||
</a>
|
||
</div>
|
||
|
||
<form method="POST" style="margin-top: 20px;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="get_global_master_assets">
|
||
<button type="submit" class="btn btn-primary">Get Global Master Assets</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['global_master_assets']) && !empty($results['global_master_assets'])): ?>
|
||
<h3 style="margin-top: 30px;">Global Master Assets (<?= count($results['global_master_assets']) ?> files)</h3>
|
||
<div class="asset-list">
|
||
<?php foreach ($results['global_master_assets'] as $index => $asset): ?>
|
||
<?php
|
||
$assetName = extractFolderName($asset);
|
||
$assetId = $asset['asset_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>
|
||
</div>
|
||
<div class="asset-actions">
|
||
<button class="btn btn-secondary">📋 View Metadata</button>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['debug_global_campaigns']) && !empty($results['debug_global_campaigns'])): ?>
|
||
<div class="alert alert-info" style="margin-top: 30px;">
|
||
<h3>🔍 Debug Results: Found <?= count($results['debug_global_campaigns']) ?> Global Campaigns</h3>
|
||
<?php foreach ($results['debug_global_campaigns'] as $campaign): ?>
|
||
<details style="margin: 15px 0; background: white; padding: 15px; border-radius: 6px;">
|
||
<summary style="cursor: pointer; font-weight: 600;">
|
||
<?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed') ?>
|
||
- Status: <span class="status-badge"><?= htmlspecialchars($campaign['status'] ?? 'N/A') ?></span>
|
||
</summary>
|
||
<div style="margin-top: 15px;">
|
||
<p><strong>Campaign Type:</strong> <?= htmlspecialchars($campaign['campaign_type'] ?? 'N/A') ?></p>
|
||
<p><strong>Status:</strong> <?= htmlspecialchars($campaign['status'] ?? 'N/A') ?></p>
|
||
<p><strong>Asset ID:</strong> <?= htmlspecialchars($campaign['asset_id']) ?></p>
|
||
|
||
<?php if ($campaign['status'] === 'B1'): ?>
|
||
<form method="POST" style="margin-top: 15px; display: inline-block;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="update_status_to_b2">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-success" onclick="return confirm('Update <?= htmlspecialchars($campaign['campaign_name']) ?> to B2?')">
|
||
✅ Update B1 → B2
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($campaign['status'] === 'B2'): ?>
|
||
<form method="POST" style="margin-top: 15px; display: inline-block;">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="reset_to_b1">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-warning" onclick="return confirm('Reset <?= htmlspecialchars($campaign['campaign_name']) ?> to B1?')">
|
||
🔄 Reset B2 → B1
|
||
</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
</details>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['selected_campaign_b1'])): ?>
|
||
|
||
<div style="margin-top: 30px; padding: 20px; background: #fff3cd; border-radius: 8px;">
|
||
<h4>⚠️ Update Status to B2</h4>
|
||
<p style="margin: 10px 0;">
|
||
Once all Global Master assets are downloaded and sent to Agency, update the campaign status to B2
|
||
</p>
|
||
<form method="POST">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="update_status_to_b2">
|
||
<button type="submit" class="btn btn-success">Update Status: B1 → B2</button>
|
||
</form>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['b1_campaigns']) && !empty($results['b1_campaigns'])): ?>
|
||
<h3 style="margin-top: 30px;">Found <?= count($results['b1_campaigns']) ?> Global Campaigns (B1)</h3>
|
||
<div class="campaign-grid">
|
||
<?php foreach ($results['b1_campaigns'] as $campaign): ?>
|
||
<div class="campaign-card">
|
||
<h3><?= htmlspecialchars($campaign['campaign_name'] ?? 'Unnamed Campaign') ?></h3>
|
||
<p><strong>Campaign ID:</strong> <?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?></p>
|
||
<p><strong>Status:</strong> <span class="status-badge status-b1">B1</span></p>
|
||
<p><strong>Type:</strong> <?= htmlspecialchars($campaign['campaign_type'] ?? 'Global comm') ?></p>
|
||
<form method="POST">
|
||
<input type="hidden" name="tab" value="global-masters">
|
||
<input type="hidden" name="action" value="select_campaign_b1">
|
||
<input type="hidden" name="campaign_id" value="<?= htmlspecialchars($campaign['asset_id']) ?>">
|
||
<button type="submit" class="btn btn-success">Select Campaign</button>
|
||
</form>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- Debug View Tab -->
|
||
<div id="tab-debug-view" class="tab-content <?= $currentTab === 'debug-view' ? 'active' : '' ?>">
|
||
<h2>🔧 Debug View</h2>
|
||
<p style="color: #666; margin: 10px 0 20px 0; font-weight: 300;">
|
||
Campaign status management and folder inspection tools for testing workflows
|
||
</p>
|
||
|
||
<!-- Section 1: Campaign Status Management -->
|
||
<div style="background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||
<h3 style="margin-top: 0; color: #431b06; font-weight: 600;">📋 Campaign Status Management</h3>
|
||
|
||
<div style="margin-bottom: 20px;">
|
||
<form method="POST" style="display: inline-block; margin-right: 10px;">
|
||
<input type="hidden" name="tab" value="debug-view">
|
||
<input type="hidden" name="action" value="load_all_campaigns_debug">
|
||
<button type="submit" class="btn btn-primary">Load All Campaigns (All Statuses)</button>
|
||
</form>
|
||
|
||
<?php if (isset($results['debug_all_campaigns']) || isset($results['debug_folder_contents'])): ?>
|
||
<form method="POST" style="display: inline-block;">
|
||
<input type="hidden" name="tab" value="debug-view">
|
||
<input type="hidden" name="clear_results" value="1">
|
||
<button type="submit" class="btn btn-secondary">🗑️ Reset / Clear Results</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if (isset($results['debug_all_campaigns'])): ?>
|
||
<div class="alert alert-info">
|
||
<strong>Found <?= count($results['debug_all_campaigns']) ?> campaigns</strong>
|
||
</div>
|
||
|
||
<?php if (count($results['debug_all_campaigns']) > 0): ?>
|
||
<!-- Two separate forms: one for status update, one for folder viewing -->
|
||
|
||
<!-- Status Update Form -->
|
||
<form method="POST" id="status-update-form">
|
||
<input type="hidden" name="tab" value="debug-view">
|
||
<input type="hidden" name="action" value="update_campaign_status_debug">
|
||
|
||
<div style="overflow-x: auto;">
|
||
<table class="results-table" style="width: 100%; margin-top: 20px; table-layout: fixed;">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 60px; text-align: center;">Select</th>
|
||
<th style="width: 40%;">Campaign Name</th>
|
||
<th style="width: 150px;">Campaign Number</th>
|
||
<th style="width: 120px; text-align: center;">Current Status</th>
|
||
<th style="width: 150px;">Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($results['debug_all_campaigns'] as $index => $campaign): ?>
|
||
<tr>
|
||
<td style="text-align: center; vertical-align: middle;">
|
||
<input type="radio"
|
||
name="selected_campaign"
|
||
value="<?= $index ?>"
|
||
id="campaign_<?= $index ?>"
|
||
onchange="handleCampaignSelection(<?= $index ?>)">
|
||
</td>
|
||
<td style="vertical-align: middle;">
|
||
<label for="campaign_<?= $index ?>" style="cursor: pointer; display: block; padding: 5px 0; font-weight: 400;">
|
||
<?= htmlspecialchars($campaign['campaign_name']) ?>
|
||
</label>
|
||
</td>
|
||
<td style="vertical-align: middle;">
|
||
<label for="campaign_<?= $index ?>" style="cursor: pointer; display: block; padding: 5px 0;">
|
||
<?= htmlspecialchars($campaign['campaign_id'] ?? 'N/A') ?>
|
||
</label>
|
||
</td>
|
||
<td style="text-align: center; vertical-align: middle;">
|
||
<label for="campaign_<?= $index ?>" style="cursor: pointer; display: block; padding: 5px 0;">
|
||
<span class="badge badge-info"><?= htmlspecialchars($campaign['current_status']) ?></span>
|
||
</label>
|
||
</td>
|
||
<td style="vertical-align: middle;">
|
||
<div id="actions_<?= $index ?>" style="display: none;">
|
||
<button type="button" onclick="viewCampaignFolder(<?= $index ?>, 'master')" class="btn btn-secondary" style="font-size: 13px; padding: 8px 12px; margin-right: 6px; font-weight: 500;">
|
||
📂 Master
|
||
</button>
|
||
<button type="button" onclick="viewCampaignFolder(<?= $index ?>, 'final')" class="btn btn-secondary" style="font-size: 13px; padding: 8px 12px; font-weight: 500;">
|
||
📂 Final
|
||
</button>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div style="margin-top: 20px; padding: 15px; background: #f8f9fa; border-radius: 4px;">
|
||
<label for="target_status" style="font-weight: 600; margin-right: 10px;">
|
||
Update selected campaign to:
|
||
</label>
|
||
<select name="target_status" id="target_status" required style="padding: 8px; font-size: 14px; border-radius: 4px; border: 1px solid #ddd; font-family: 'Montserrat', sans-serif;">
|
||
<option value="">-- Select Status --</option>
|
||
<option value="A1">A1</option>
|
||
<option value="A2">A2</option>
|
||
<option value="A3">A3</option>
|
||
<option value="A4">A4</option>
|
||
<option value="A5">A5</option>
|
||
<option value="A6">A6</option>
|
||
<option value="B1">B1</option>
|
||
<option value="B2">B2</option>
|
||
</select>
|
||
|
||
<button type="submit" class="btn btn-warning" style="margin-left: 20px;">
|
||
Update Campaign Status
|
||
</button>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- Hidden forms for folder viewing -->
|
||
<?php foreach ($results['debug_all_campaigns'] as $index => $campaign): ?>
|
||
<form method="POST" id="view-master-<?= $index ?>" style="display: none;">
|
||
<input type="hidden" name="tab" value="debug-view">
|
||
<input type="hidden" name="action" value="select_campaign_and_view_folders">
|
||
<input type="hidden" name="campaign_index" value="<?= $index ?>">
|
||
<input type="hidden" name="folder_type" value="master">
|
||
</form>
|
||
<form method="POST" id="view-final-<?= $index ?>" style="display: none;">
|
||
<input type="hidden" name="tab" value="debug-view">
|
||
<input type="hidden" name="action" value="select_campaign_and_view_folders">
|
||
<input type="hidden" name="campaign_index" value="<?= $index ?>">
|
||
<input type="hidden" name="folder_type" value="final">
|
||
</form>
|
||
<?php endforeach; ?>
|
||
|
||
<script>
|
||
function handleCampaignSelection(index) {
|
||
console.log('Selected campaign index:', index);
|
||
// Hide all action buttons
|
||
document.querySelectorAll('[id^="actions_"]').forEach(el => el.style.display = 'none');
|
||
// Show actions for selected campaign
|
||
const actionsDiv = document.getElementById('actions_' + index);
|
||
if (actionsDiv) {
|
||
actionsDiv.style.display = 'block';
|
||
console.log('Showing actions for campaign', index);
|
||
} else {
|
||
console.error('Actions div not found for index', index);
|
||
}
|
||
}
|
||
|
||
function viewCampaignFolder(index, folderType) {
|
||
console.log('Viewing folder:', folderType, 'for campaign', index);
|
||
const formId = 'view-' + folderType + '-' + index;
|
||
const form = document.getElementById(formId);
|
||
if (form) {
|
||
console.log('Submitting form:', formId);
|
||
form.submit();
|
||
} else {
|
||
console.error('Form not found:', formId);
|
||
alert('Error: Form not found. Please try reloading the page.');
|
||
}
|
||
}
|
||
</script>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['status_update_result'])): ?>
|
||
<div class="alert alert-<?= $results['status_update_result']['success'] ? 'success' : 'error' ?>" style="margin-top: 20px;">
|
||
<?php if ($results['status_update_result']['success']): ?>
|
||
<h4>✓ Campaign Status Updated Successfully</h4>
|
||
<p><strong>Campaign:</strong> <?= htmlspecialchars($results['status_update_result']['campaign_name']) ?></p>
|
||
<p><strong>Number:</strong> <?= htmlspecialchars($results['status_update_result']['campaign_number']) ?></p>
|
||
<p><strong>Previous Status:</strong> <?= htmlspecialchars($results['status_update_result']['old_status']) ?></p>
|
||
<p><strong>New Status:</strong> <?= htmlspecialchars($results['status_update_result']['new_status']) ?></p>
|
||
<?php else: ?>
|
||
<h4>✗ Status Update Failed</h4>
|
||
<p><strong>Error:</strong> htmlspecialchars($results['status_update_result']['error']) ?></p>
|
||
<p><strong>Campaign:</strong> <?= htmlspecialchars($results['status_update_result']['campaign_name'] ?? 'N/A') ?></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- Section 2: Campaign Folder Contents -->
|
||
<?php if (isset($results['selected_campaign_debug']) && isset($results['debug_campaign_assets'])): ?>
|
||
<div style="background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||
<h3 style="margin-top: 0; color: #431b06; font-weight: 600;">
|
||
📁 <?= htmlspecialchars($results['selected_campaign_debug']['campaign_name']) ?>
|
||
</h3>
|
||
<p style="color: #666; font-size: 14px; font-weight: 300;">
|
||
Campaign: <?= htmlspecialchars($results['selected_campaign_debug']['campaign_id'] ?? 'N/A') ?> |
|
||
Status: <span class="badge badge-info"><?= htmlspecialchars($results['selected_campaign_debug']['current_status']) ?></span>
|
||
</p>
|
||
<p style="color: #666; font-size: 13px; font-weight: 300; margin-top: 5px;">
|
||
Viewing: <?= htmlspecialchars($results['debug_folder_view_type'] ?? 'Folder Contents') ?>
|
||
</p>
|
||
|
||
<div class="alert alert-info" style="margin-bottom: 20px;">
|
||
<h4><?= htmlspecialchars($results['debug_folder_name'] ?? 'Folder') ?></h4>
|
||
<p><strong>Folder Type:</strong> <?= htmlspecialchars($results['debug_folder_type'] ?? 'Assets') ?></p>
|
||
<p><strong>Total Assets:</strong> <?= count($results['debug_campaign_assets']) ?></p>
|
||
</div>
|
||
|
||
<?php if (count($results['debug_campaign_assets']) > 0): ?>
|
||
<div class="asset-list">
|
||
<?php foreach ($results['debug_campaign_assets'] as $index => $asset): ?>
|
||
<?php
|
||
$assetName = extractFolderName($asset);
|
||
$assetId = $asset['asset_id'];
|
||
$metadataId = 'debug-metadata-' . $index;
|
||
?>
|
||
<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">
|
||
<button class="btn btn-secondary"
|
||
onclick="toggleMetadata('<?= $metadataId ?>')">
|
||
📋 View 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;">
|
||
<?php if (isset($metadata['basic'])): ?>
|
||
<div style="background: white; padding: 12px; margin: 8px 0; border-radius: 4px; border-left: 4px solid #431b06;">
|
||
<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; ?>
|
||
|
||
<?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; ?>
|
||
|
||
<?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; ?>
|
||
|
||
<details style="margin-top: 10px;">
|
||
<summary style="cursor: pointer; font-size: 13px;">View Full Raw JSON</summary>
|
||
<pre style="background: #f0f0f0; padding: 10px; border-radius: 4px; overflow: auto; max-height: 400px; font-size: 11px; margin-top: 10px;"><?= htmlspecialchars(json_encode($asset, JSON_PRETTY_PRINT)) ?></pre>
|
||
</details>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<p style="color: #999; font-style: italic;">No assets found in this folder</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($results['debug_folder_error'])): ?>
|
||
<div class="alert alert-error">
|
||
<h4>Error Loading Folder</h4>
|
||
<p><?= htmlspecialchars($results['debug_folder_error']) ?></p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</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';
|
||
}
|
||
}
|
||
|
||
function selectCampaignA2(campaignId) {
|
||
document.querySelectorAll('.campaign-card').forEach(card => {
|
||
card.classList.remove('selected');
|
||
});
|
||
|
||
event.currentTarget.classList.add('selected');
|
||
document.getElementById('selected-campaign-a2-id').value = campaignId;
|
||
document.getElementById('select-campaign-a2-btn').disabled = false;
|
||
}
|
||
|
||
function selectCampaignA5(campaignId) {
|
||
document.querySelectorAll('.campaign-card').forEach(card => {
|
||
card.classList.remove('selected');
|
||
});
|
||
|
||
event.currentTarget.classList.add('selected');
|
||
document.getElementById('selected-campaign-a5-id').value = campaignId;
|
||
document.getElementById('select-campaign-a5-btn').disabled = false;
|
||
}
|
||
|
||
function selectMasterMetadata(index) {
|
||
document.getElementById('master-metadata-index').value = index;
|
||
}
|
||
|
||
// Upload from Box functions
|
||
let boxFilesData = [];
|
||
let uploadResults = [];
|
||
|
||
function loadBoxFiles() {
|
||
const folderId = document.getElementById('box-folder-id').value.trim();
|
||
|
||
if (!folderId) {
|
||
showBoxError('Please enter a Box Folder ID');
|
||
return;
|
||
}
|
||
|
||
// Show loading
|
||
document.getElementById('box-loading').style.display = 'block';
|
||
document.getElementById('box-error').style.display = 'none';
|
||
document.getElementById('box-files-container').style.display = 'none';
|
||
|
||
// Make AJAX request
|
||
fetch('workflow_v3.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
},
|
||
body: 'action=box_list_files&folder_id=' + encodeURIComponent(folderId)
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
document.getElementById('box-loading').style.display = 'none';
|
||
|
||
if (data.success) {
|
||
boxFilesData = data.files;
|
||
displayBoxFiles(data.files);
|
||
} else {
|
||
showBoxError(data.error || 'Failed to load files from Box');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
document.getElementById('box-loading').style.display = 'none';
|
||
showBoxError('Error: ' + error.message);
|
||
});
|
||
}
|
||
|
||
function displayBoxFiles(files) {
|
||
if (!files || files.length === 0) {
|
||
showBoxError('No files found in Box folder');
|
||
return;
|
||
}
|
||
|
||
const tbody = document.getElementById('box-files-list');
|
||
tbody.innerHTML = '';
|
||
|
||
files.forEach((file, index) => {
|
||
const row = document.createElement('tr');
|
||
row.style.borderBottom = '1px solid #dee2e6';
|
||
|
||
const isValid = file.is_valid && file.has_tracking_id;
|
||
const validIcon = isValid ? '✅' : '❌';
|
||
const validColor = isValid ? '#28a745' : '#dc3545';
|
||
|
||
row.innerHTML = `
|
||
<td style="padding: 12px;">
|
||
<input type="checkbox"
|
||
class="file-checkbox"
|
||
data-index="${index}"
|
||
${isValid ? '' : 'disabled'}
|
||
onclick="updateUploadButton()">
|
||
</td>
|
||
<td style="padding: 12px;">
|
||
<div style="font-weight: 600;">${escapeHtml(file.name)}</div>
|
||
${file.clean_filename && file.clean_filename !== file.name ?
|
||
`<div style="font-size: 12px; color: #666; margin-top: 4px;">
|
||
Upload as: ${escapeHtml(file.clean_filename)}
|
||
</div>` : ''}
|
||
${!isValid && file.parsed && file.parsed.validation_errors ?
|
||
`<div style="font-size: 11px; color: #dc3545; margin-top: 4px;">
|
||
${file.parsed.validation_errors.join(', ')}
|
||
</div>` : ''}
|
||
</td>
|
||
<td style="padding: 12px;">
|
||
${file.tracking_id ?
|
||
`<span style="font-family: monospace; background: #e9ecef; padding: 2px 6px; border-radius: 3px;">${escapeHtml(file.tracking_id)}</span>` :
|
||
'<span style="color: #999;">None</span>'}
|
||
</td>
|
||
<td style="padding: 12px; color: ${validColor}; font-weight: 600;">
|
||
${validIcon} ${isValid ? 'Valid' : 'Invalid'}
|
||
</td>
|
||
<td style="padding: 12px;">
|
||
${formatFileSize(file.size)}
|
||
</td>
|
||
<td style="padding: 12px;">
|
||
<a href="${file.box_url}" target="_blank" style="color: #007bff; text-decoration: none;">
|
||
View in Box
|
||
</a>
|
||
</td>
|
||
`;
|
||
|
||
tbody.appendChild(row);
|
||
});
|
||
|
||
document.getElementById('box-files-container').style.display = 'block';
|
||
updateUploadButton();
|
||
}
|
||
|
||
function toggleAllFiles(checkbox) {
|
||
document.querySelectorAll('.file-checkbox:not(:disabled)').forEach(cb => {
|
||
cb.checked = checkbox.checked;
|
||
});
|
||
updateUploadButton();
|
||
}
|
||
|
||
function updateUploadButton() {
|
||
const checkedCount = document.querySelectorAll('.file-checkbox:checked').length;
|
||
const btn = document.getElementById('upload-selected-btn');
|
||
btn.disabled = checkedCount === 0;
|
||
btn.textContent = `Upload Selected Files (${checkedCount})`;
|
||
}
|
||
|
||
function uploadSelectedFiles() {
|
||
const checkboxes = document.querySelectorAll('.file-checkbox:checked');
|
||
if (checkboxes.length === 0) {
|
||
alert('Please select at least one file to upload');
|
||
return;
|
||
}
|
||
|
||
// Get selected files
|
||
const selectedFiles = [];
|
||
checkboxes.forEach(cb => {
|
||
const index = parseInt(cb.dataset.index);
|
||
selectedFiles.push(boxFilesData[index]);
|
||
});
|
||
|
||
// Show progress container
|
||
document.getElementById('upload-progress-container').style.display = 'block';
|
||
document.getElementById('upload-results-container').style.display = 'none';
|
||
document.getElementById('upload-progress-list').innerHTML = '';
|
||
|
||
// Disable upload button
|
||
document.getElementById('upload-selected-btn').disabled = true;
|
||
|
||
// Upload files sequentially
|
||
uploadFilesSequentially(selectedFiles, 0, []);
|
||
}
|
||
|
||
function uploadFilesSequentially(files, index, results) {
|
||
if (index >= files.length) {
|
||
// All files processed - show results
|
||
showUploadResults(results);
|
||
return;
|
||
}
|
||
|
||
const file = files[index];
|
||
const progressList = document.getElementById('upload-progress-list');
|
||
|
||
// Add progress item
|
||
const progressItem = document.createElement('div');
|
||
progressItem.id = `progress-${index}`;
|
||
progressItem.style.padding = '10px';
|
||
progressItem.style.marginBottom = '5px';
|
||
progressItem.style.background = '#fff3cd';
|
||
progressItem.style.borderRadius = '4px';
|
||
progressItem.style.border = '1px solid #ffc107';
|
||
progressItem.innerHTML = `
|
||
<strong>${index + 1}/${files.length}:</strong> ${escapeHtml(file.name)}<br>
|
||
<small>⏳ Uploading to DAM...</small>
|
||
`;
|
||
progressList.appendChild(progressItem);
|
||
|
||
// Upload this file
|
||
fetch('workflow_v3.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
'X-Requested-With': 'XMLHttpRequest'
|
||
},
|
||
body: `action=upload_from_box&file_id=${encodeURIComponent(file.id)}&filename=${encodeURIComponent(file.name)}&tracking_id=${encodeURIComponent(file.tracking_id)}`
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
progressItem.style.background = '#d4edda';
|
||
progressItem.style.border = '1px solid #28a745';
|
||
progressItem.innerHTML = `
|
||
<strong>${index + 1}/${files.length}:</strong> ${escapeHtml(file.name)}<br>
|
||
<small style="color: #28a745;">✅ Uploaded as: ${escapeHtml(data.clean_filename)}</small><br>
|
||
<small style="color: #666;">Asset ID: ${data.asset_id} | Folder: ${data.upload_folder}</small><br>
|
||
<small><a href="debug_assets.php?action=get_assets&folder_id=${data.upload_folder}" target="_blank" style="color: #007bff;">
|
||
🔍 View in Final Assets Folder
|
||
</a></small>
|
||
`;
|
||
|
||
results.push({
|
||
filename: file.name,
|
||
success: true,
|
||
asset_id: data.asset_id,
|
||
clean_filename: data.clean_filename,
|
||
upload_folder: data.upload_folder,
|
||
master_asset_id: data.master_asset_id,
|
||
asset_representation: data.asset_representation
|
||
});
|
||
} else {
|
||
progressItem.style.background = '#f8d7da';
|
||
progressItem.style.border = '1px solid #dc3545';
|
||
progressItem.innerHTML = `
|
||
<strong>${index + 1}/${files.length}:</strong> ${escapeHtml(file.name)}<br>
|
||
<small style="color: #dc3545;">❌ Error: ${escapeHtml(data.error)}</small>
|
||
`;
|
||
|
||
results.push({
|
||
filename: file.name,
|
||
success: false,
|
||
error: data.error
|
||
});
|
||
}
|
||
|
||
// Upload next file
|
||
setTimeout(() => uploadFilesSequentially(files, index + 1, results), 500);
|
||
})
|
||
.catch(error => {
|
||
progressItem.style.background = '#f8d7da';
|
||
progressItem.style.border = '1px solid #dc3545';
|
||
progressItem.innerHTML = `
|
||
<strong>${index + 1}/${files.length}:</strong> ${escapeHtml(file.name)}<br>
|
||
<small style="color: #dc3545;">❌ Error: ${escapeHtml(error.message)}</small>
|
||
`;
|
||
|
||
results.push({
|
||
filename: file.name,
|
||
success: false,
|
||
error: error.message
|
||
});
|
||
|
||
// Continue with next file
|
||
setTimeout(() => uploadFilesSequentially(files, index + 1, results), 500);
|
||
});
|
||
}
|
||
|
||
function showUploadResults(results) {
|
||
// Store results globally for download/view functions
|
||
uploadResults = results;
|
||
|
||
const successCount = results.filter(r => r.success).length;
|
||
const failCount = results.length - successCount;
|
||
|
||
// Show results container
|
||
document.getElementById('upload-results-container').style.display = 'block';
|
||
|
||
const summaryDiv = document.getElementById('upload-results-summary');
|
||
summaryDiv.className = successCount === results.length ? 'alert alert-success' : 'alert alert-warning';
|
||
summaryDiv.innerHTML = `
|
||
<strong>Upload Complete!</strong><br>
|
||
✅ ${successCount} succeeded | ❌ ${failCount} failed | Total: ${results.length}
|
||
`;
|
||
|
||
// Show details
|
||
const detailsDiv = document.getElementById('upload-results-details');
|
||
detailsDiv.innerHTML = '';
|
||
|
||
if (successCount > 0) {
|
||
const successDiv = document.createElement('div');
|
||
successDiv.style.marginTop = '15px';
|
||
successDiv.innerHTML = '<h4 style="color: #28a745;">✅ Successful Uploads:</h4>';
|
||
|
||
results.filter(r => r.success).forEach((result, idx) => {
|
||
const item = document.createElement('div');
|
||
item.style.padding = '10px';
|
||
item.style.marginTop = '5px';
|
||
item.style.background = '#d4edda';
|
||
item.style.borderRadius = '4px';
|
||
item.style.border = '1px solid #28a745';
|
||
item.innerHTML = `
|
||
<strong>${escapeHtml(result.filename)}</strong><br>
|
||
<small>Clean filename: ${escapeHtml(result.clean_filename)}</small><br>
|
||
<small>Asset ID: ${result.asset_id}</small><br>
|
||
<button onclick="downloadAssetRepresentation(${idx})" class="btn btn-secondary" style="font-size: 11px; padding: 4px 8px; margin-top: 8px;">
|
||
💾 Download Asset Representation JSON
|
||
</button>
|
||
<button onclick="viewAssetRepresentation(${idx})" class="btn btn-secondary" style="font-size: 11px; padding: 4px 8px; margin-top: 8px; margin-left: 5px;">
|
||
👁️ View JSON
|
||
</button>
|
||
`;
|
||
successDiv.appendChild(item);
|
||
});
|
||
|
||
detailsDiv.appendChild(successDiv);
|
||
}
|
||
|
||
if (failCount > 0) {
|
||
const failDiv = document.createElement('div');
|
||
failDiv.style.marginTop = '15px';
|
||
failDiv.innerHTML = '<h4 style="color: #dc3545;">❌ Failed Uploads:</h4>';
|
||
|
||
results.filter(r => !r.success).forEach(result => {
|
||
const item = document.createElement('div');
|
||
item.style.padding = '10px';
|
||
item.style.marginTop = '5px';
|
||
item.style.background = '#f8d7da';
|
||
item.style.borderRadius = '4px';
|
||
item.style.border = '1px solid #dc3545';
|
||
item.innerHTML = `
|
||
<strong>${escapeHtml(result.filename)}</strong><br>
|
||
<small style="color: #dc3545;">Error: ${escapeHtml(result.error)}</small>
|
||
`;
|
||
failDiv.appendChild(item);
|
||
});
|
||
|
||
detailsDiv.appendChild(failDiv);
|
||
}
|
||
|
||
// Re-enable upload button
|
||
document.getElementById('upload-selected-btn').disabled = false;
|
||
}
|
||
|
||
function clearBoxFiles() {
|
||
boxFilesData = [];
|
||
document.getElementById('box-files-list').innerHTML = '';
|
||
document.getElementById('box-files-container').style.display = 'none';
|
||
document.getElementById('upload-progress-container').style.display = 'none';
|
||
document.getElementById('upload-results-container').style.display = 'none';
|
||
document.getElementById('box-folder-id').value = '';
|
||
}
|
||
|
||
function showBoxError(message) {
|
||
const errorDiv = document.getElementById('box-error');
|
||
errorDiv.textContent = message;
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
|
||
function escapeHtml(text) {
|
||
const div = document.createElement('div');
|
||
div.textContent = text;
|
||
return div.innerHTML;
|
||
}
|
||
|
||
function formatFileSize(bytes) {
|
||
if (bytes < 1024) return bytes + ' B';
|
||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
||
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
||
}
|
||
|
||
function downloadAssetRepresentation(index) {
|
||
const successResults = uploadResults.filter(r => r.success);
|
||
if (!successResults[index] || !successResults[index].asset_representation) {
|
||
alert('Asset representation not available');
|
||
return;
|
||
}
|
||
|
||
const result = successResults[index];
|
||
const json = JSON.stringify(result.asset_representation, null, 2);
|
||
const blob = new Blob([json], { type: 'application/json' });
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `asset_representation_${result.asset_id}.json`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
URL.revokeObjectURL(url);
|
||
}
|
||
|
||
function viewAssetRepresentation(index) {
|
||
const successResults = uploadResults.filter(r => r.success);
|
||
if (!successResults[index] || !successResults[index].asset_representation) {
|
||
alert('Asset representation not available');
|
||
return;
|
||
}
|
||
|
||
const result = successResults[index];
|
||
const json = JSON.stringify(result.asset_representation, null, 2);
|
||
|
||
// Create modal to show JSON
|
||
const modal = document.createElement('div');
|
||
modal.style.cssText = 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); z-index: 10000; display: flex; align-items: center; justify-content: center; padding: 20px;';
|
||
modal.innerHTML = `
|
||
<div style="background: white; border-radius: 8px; max-width: 900px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column;">
|
||
<div style="padding: 20px; border-bottom: 1px solid #ddd; display: flex; justify-content: space-between; align-items: center;">
|
||
<h3 style="margin: 0;">Asset Representation JSON - Asset ${result.asset_id}</h3>
|
||
<button onclick="this.closest('div').parentElement.parentElement.remove()" class="btn btn-secondary">Close</button>
|
||
</div>
|
||
<div style="padding: 20px; overflow: auto;">
|
||
<pre style="background: #f8f9fa; padding: 15px; border-radius: 6px; font-size: 12px; margin: 0;">${escapeHtml(json)}</pre>
|
||
</div>
|
||
</div>
|
||
`;
|
||
document.body.appendChild(modal);
|
||
modal.onclick = function(e) {
|
||
if (e.target === modal) modal.remove();
|
||
};
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|