Includes backend API, public-v2 frontend, database migrations, Composer config, and deployment/implementation docs. Config files with credentials are excluded via .gitignore. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
381 lines
13 KiB
PHP
381 lines
13 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, POST, DELETE');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
|
// Load data from JSON files
|
|
$dataFile = __DIR__ . '/../backend/data.json';
|
|
$trackingFile = __DIR__ . '/../backend-v2/tracking_data.json';
|
|
|
|
function loadData() {
|
|
global $dataFile;
|
|
if (!file_exists($dataFile)) {
|
|
return ['error' => 'Data file not found'];
|
|
}
|
|
$json = file_get_contents($dataFile);
|
|
return json_decode($json, true);
|
|
}
|
|
|
|
function saveData($data) {
|
|
global $dataFile;
|
|
file_put_contents($dataFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
|
}
|
|
|
|
function loadTrackingData() {
|
|
global $trackingFile;
|
|
if (!file_exists($trackingFile)) {
|
|
return ['tracking_ids' => [], 'generated_ids' => []];
|
|
}
|
|
$json = file_get_contents($trackingFile);
|
|
return json_decode($json, true);
|
|
}
|
|
|
|
function saveTrackingData($data) {
|
|
global $trackingFile;
|
|
file_put_contents($trackingFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
|
}
|
|
|
|
function generateTrackingId() {
|
|
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
$trackingId = '';
|
|
for ($i = 0; $i < 6; $i++) {
|
|
$trackingId .= $characters[rand(0, strlen($characters) - 1)];
|
|
}
|
|
|
|
// Check if ID already exists
|
|
$trackingData = loadTrackingData();
|
|
if (isset($trackingData['tracking_ids'][$trackingId])) {
|
|
// If exists, generate a new one
|
|
return generateTrackingId();
|
|
}
|
|
|
|
return $trackingId;
|
|
}
|
|
|
|
// Get action from URL
|
|
$action = isset($_GET['action']) ? $_GET['action'] : '';
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
|
|
|
switch ($action) {
|
|
case 'data':
|
|
echo json_encode(loadData());
|
|
break;
|
|
|
|
case 'generate-tracking-id':
|
|
if ($method === 'GET') {
|
|
$trackingId = generateTrackingId();
|
|
echo json_encode(['tracking_id' => $trackingId]);
|
|
}
|
|
break;
|
|
|
|
case 'register-tracking-id':
|
|
if ($method === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$trackingId = $input['tracking_id'] ?? '';
|
|
$masterFilename = $input['master_filename'] ?? '';
|
|
$masterExtension = $input['master_extension'] ?? '';
|
|
$opentextId = $input['opentext_id'] ?? '';
|
|
$metadata = $input['metadata'] ?? [];
|
|
|
|
if (empty($trackingId) || empty($masterFilename)) {
|
|
echo json_encode(['error' => 'Tracking ID and master filename are required']);
|
|
exit;
|
|
}
|
|
|
|
$trackingData = loadTrackingData();
|
|
|
|
$trackingData['tracking_ids'][$trackingId] = [
|
|
'master_filename' => $masterFilename,
|
|
'master_extension' => $masterExtension,
|
|
'created_date' => date('Y-m-d'),
|
|
'opentext_id' => $opentextId,
|
|
'metadata' => $metadata
|
|
];
|
|
|
|
if (!in_array($trackingId, $trackingData['generated_ids'])) {
|
|
$trackingData['generated_ids'][] = $trackingId;
|
|
}
|
|
|
|
saveTrackingData($trackingData);
|
|
echo json_encode(['success' => true, 'message' => 'Tracking ID registered successfully']);
|
|
}
|
|
break;
|
|
|
|
case 'lookup-tracking-id':
|
|
if ($method === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$trackingId = $input['tracking_id'] ?? '';
|
|
|
|
if (empty($trackingId)) {
|
|
echo json_encode(['error' => 'Tracking ID is required']);
|
|
exit;
|
|
}
|
|
|
|
$trackingData = loadTrackingData();
|
|
|
|
if (isset($trackingData['tracking_ids'][$trackingId])) {
|
|
echo json_encode([
|
|
'success' => true,
|
|
'tracking_id' => $trackingId,
|
|
'data' => $trackingData['tracking_ids'][$trackingId]
|
|
]);
|
|
} else {
|
|
echo json_encode(['error' => 'Tracking ID not found']);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'build':
|
|
if ($method === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
$omgJobNumber = $input['omg_job_number'] ?? '';
|
|
$brandCode = strtoupper($input['brand_code'] ?? '');
|
|
$countryCode = strtoupper($input['country_code'] ?? '');
|
|
$languageCode = strtolower($input['language_code'] ?? '');
|
|
$subjectTitle = strtoupper($input['subject_title'] ?? '');
|
|
$assetType = strtoupper($input['asset_type'] ?? '');
|
|
$spotVersion = strtoupper($input['spot_version'] ?? '');
|
|
$seconds = $input['seconds'] ?? '';
|
|
$aspectRatio = $input['aspect_ratio'] ?? '';
|
|
$hasMaster = $input['has_master'] ?? false;
|
|
$trackingId = $input['tracking_id'] ?? '';
|
|
|
|
// Validation
|
|
$errors = [];
|
|
|
|
if (empty($omgJobNumber) || !ctype_digit($omgJobNumber) || strlen($omgJobNumber) > 10) {
|
|
$errors[] = 'OMG Job Number is required, must be numbers only, and max 10 digits';
|
|
}
|
|
|
|
if (empty($brandCode) || strlen($brandCode) < 2 || strlen($brandCode) > 5) {
|
|
$errors[] = 'Brand code must be 2-5 characters';
|
|
}
|
|
|
|
if (empty($countryCode) || strlen($countryCode) != 2) {
|
|
$errors[] = 'Country code must be exactly 2 characters';
|
|
}
|
|
|
|
if (empty($languageCode) || (strlen($languageCode) != 2 && strlen($languageCode) != 3)) {
|
|
$errors[] = 'Language code is required and must be 2-3 characters';
|
|
}
|
|
|
|
if (empty($subjectTitle) || strlen($subjectTitle) > 15) {
|
|
$errors[] = 'Subject title is required and must be max 15 characters';
|
|
}
|
|
|
|
if (empty($assetType) || strlen($assetType) != 3) {
|
|
$errors[] = 'Asset type must be exactly 3 characters';
|
|
}
|
|
|
|
if (empty($seconds)) {
|
|
$errors[] = 'Duration in seconds is required';
|
|
}
|
|
|
|
if (empty($aspectRatio)) {
|
|
$errors[] = 'Aspect ratio is required';
|
|
}
|
|
|
|
if (!empty($errors)) {
|
|
echo json_encode(['error' => implode(', ', $errors)]);
|
|
exit;
|
|
}
|
|
|
|
// Build filename - start with OMG Job Number, then brand, country, language
|
|
$parts = [$omgJobNumber, $brandCode, $countryCode, $languageCode, $subjectTitle, $assetType];
|
|
|
|
// Add spot version and MST if applicable
|
|
if ($hasMaster && !empty($spotVersion)) {
|
|
$parts[] = $spotVersion . '_MST';
|
|
} elseif (!empty($spotVersion)) {
|
|
$parts[] = $spotVersion;
|
|
} elseif ($hasMaster) {
|
|
$parts[] = 'MST';
|
|
}
|
|
|
|
// Add duration
|
|
$parts[] = $seconds . 'S';
|
|
|
|
// Add aspect ratio
|
|
$parts[] = $aspectRatio;
|
|
|
|
// Add tracking ID if provided
|
|
if (!empty($trackingId)) {
|
|
$parts[] = $trackingId;
|
|
}
|
|
|
|
$filename = implode('_', $parts);
|
|
|
|
// Calculate the final upload filename (without job number and tracking ID)
|
|
$uploadParts = [$brandCode, $countryCode, $languageCode, $subjectTitle, $assetType];
|
|
if ($hasMaster && !empty($spotVersion)) {
|
|
$uploadParts[] = $spotVersion . '_MST';
|
|
} elseif (!empty($spotVersion)) {
|
|
$uploadParts[] = $spotVersion;
|
|
} elseif ($hasMaster) {
|
|
$uploadParts[] = 'MST';
|
|
}
|
|
$uploadParts[] = $seconds . 'S';
|
|
$uploadParts[] = $aspectRatio;
|
|
$uploadFilename = implode('_', $uploadParts);
|
|
|
|
echo json_encode([
|
|
'filename' => $filename,
|
|
'upload_filename' => $uploadFilename,
|
|
'has_tracking_id' => !empty($trackingId)
|
|
]);
|
|
}
|
|
break;
|
|
|
|
case 'decode':
|
|
if ($method === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$filename = $input['filename'] ?? '';
|
|
|
|
if (empty($filename)) {
|
|
echo json_encode(['error' => 'Filename is required']);
|
|
exit;
|
|
}
|
|
|
|
// Remove file extension if present
|
|
$filename = preg_replace('/\.[^.]+$/', '', $filename);
|
|
|
|
// Split by underscore
|
|
$parts = explode('_', $filename);
|
|
|
|
if (count($parts) < 8) {
|
|
echo json_encode(['error' => 'Invalid filename format. Expected at least 8 parts separated by underscores (including language code)']);
|
|
exit;
|
|
}
|
|
|
|
// Parse components (with OMG Job Number at start and language code after country)
|
|
$result = [
|
|
'omg_job_number' => $parts[0],
|
|
'brand_code' => $parts[1],
|
|
'country_code' => $parts[2],
|
|
'language_code' => $parts[3],
|
|
'subject_title' => $parts[4],
|
|
'asset_type' => $parts[5],
|
|
'spot_version' => '',
|
|
'has_master' => false,
|
|
'seconds' => '',
|
|
'aspect_ratio' => '',
|
|
'tracking_id' => ''
|
|
];
|
|
|
|
// Handle optional spot version and MST
|
|
$currentIndex = 6;
|
|
|
|
while ($currentIndex < count($parts)) {
|
|
$part = $parts[$currentIndex];
|
|
|
|
// Check if it's the duration (ends with S and has numbers)
|
|
if (preg_match('/^\d+S$/', $part)) {
|
|
$result['seconds'] = rtrim($part, 'S');
|
|
$currentIndex++;
|
|
break;
|
|
}
|
|
// Check if it's MST
|
|
elseif ($part === 'MST') {
|
|
$result['has_master'] = true;
|
|
$currentIndex++;
|
|
}
|
|
// Otherwise it's a spot version
|
|
else {
|
|
$result['spot_version'] = $part;
|
|
$currentIndex++;
|
|
}
|
|
}
|
|
|
|
// Next part should be aspect ratio
|
|
if ($currentIndex < count($parts)) {
|
|
$result['aspect_ratio'] = $parts[$currentIndex];
|
|
$currentIndex++;
|
|
}
|
|
|
|
// Last part might be tracking ID (6 alphanumeric characters)
|
|
if ($currentIndex < count($parts) && preg_match('/^[a-zA-Z0-9]{6}$/', $parts[$currentIndex])) {
|
|
$result['tracking_id'] = $parts[$currentIndex];
|
|
}
|
|
|
|
// Load data to get full names
|
|
$data = loadData();
|
|
|
|
$result['brand_name'] = $data['brands'][$result['brand_code']] ?? 'Unknown Brand';
|
|
$result['country_name'] = $data['countries'][$result['country_code']] ?? 'Unknown Country';
|
|
$result['language_name'] = $data['languages'][$result['language_code']] ?? 'Unknown Language';
|
|
$result['asset_type_name'] = $data['asset_types'][$result['asset_type']] ?? 'Unknown Asset Type';
|
|
|
|
// If tracking ID exists, lookup metadata
|
|
if (!empty($result['tracking_id'])) {
|
|
$trackingData = loadTrackingData();
|
|
if (isset($trackingData['tracking_ids'][$result['tracking_id']])) {
|
|
$result['tracking_metadata'] = $trackingData['tracking_ids'][$result['tracking_id']];
|
|
}
|
|
}
|
|
|
|
echo json_encode($result);
|
|
}
|
|
break;
|
|
|
|
case 'simulate-upload':
|
|
if ($method === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$filename = $input['filename'] ?? '';
|
|
|
|
if (empty($filename)) {
|
|
echo json_encode(['error' => 'Filename is required']);
|
|
exit;
|
|
}
|
|
|
|
// Remove file extension if present
|
|
$ext = '';
|
|
if (preg_match('/(\.[^.]+)$/', $filename, $matches)) {
|
|
$ext = $matches[1];
|
|
$filename = preg_replace('/\.[^.]+$/', '', $filename);
|
|
}
|
|
|
|
// Split by underscore
|
|
$parts = explode('_', $filename);
|
|
|
|
// Remove job number (first part if it's all digits)
|
|
if (ctype_digit($parts[0])) {
|
|
array_shift($parts);
|
|
}
|
|
|
|
// Remove tracking ID (last part if it's 6 alphanumeric characters)
|
|
$trackingId = '';
|
|
if (count($parts) > 0 && preg_match('/^[a-zA-Z0-9]{6}$/', end($parts))) {
|
|
$trackingId = array_pop($parts);
|
|
}
|
|
|
|
$uploadFilename = implode('_', $parts) . $ext;
|
|
|
|
echo json_encode([
|
|
'original_filename' => $input['filename'],
|
|
'upload_filename' => $uploadFilename,
|
|
'stripped_job_number' => true,
|
|
'stripped_tracking_id' => !empty($trackingId),
|
|
'tracking_id' => $trackingId
|
|
]);
|
|
}
|
|
break;
|
|
|
|
case 'brands':
|
|
case 'countries':
|
|
case 'asset-types':
|
|
case 'languages':
|
|
// These endpoints remain the same as v1
|
|
if ($method === 'GET') {
|
|
$data = loadData();
|
|
$key = str_replace('-', '_', $action);
|
|
echo json_encode($data[$key] ?? []);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
echo json_encode(['error' => 'Invalid action']);
|
|
break;
|
|
}
|
|
?>
|