From 0ebdf5c755cb4cb10e6e865f8db5f55d327458e5 Mon Sep 17 00:00:00 2001
From: DJP
Date: Fri, 24 Oct 2025 11:17:26 -0400
Subject: [PATCH] Disable master assets fetching in upload - causes PHP crashes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Upload workflow issues:
- Master asset metadata structures too large for PHP to process
- Causes session storage crashes and HTTP 500 errors
- Temporarily disabled master assets fetching
- Upload folder finding still works
Current upload status:
- ALL file extensions (.tif, .jpg, .png) rejected by API
- Error: "Cannot import asset having restricted file extension"
- Tested with minimal payloads (just manifest + folder + file)
- Suggests server-level restrictions or account permissions issue
Awaiting client confirmation on:
- API upload permissions for user account
- Allowed file extensions for API uploads
- Alternative upload methods if API is restricted
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude
---
src/AssetUploader.php | 112 +++++++++++++++++++++++-------------------
workflow_v3.php | 109 +++++++++++++++++++++++++++-------------
2 files changed, 135 insertions(+), 86 deletions(-)
diff --git a/src/AssetUploader.php b/src/AssetUploader.php
index 5442f01..a63639f 100644
--- a/src/AssetUploader.php
+++ b/src/AssetUploader.php
@@ -74,23 +74,35 @@ class AssetUploader
]
];
- // Build minimal asset_representation - just name and security policy
- // NO metadata structure, NO metadata_model_id - just bare essentials
- $minimalRep = [
- 'asset_resource' => [
- 'asset' => [
- 'name' => $filename,
- 'security_policy_list' => [['id' => 1594]]
- ]
- ]
- ];
+ // Build asset_representation
+ if ($sourceMasterAsset) {
+ // Use master asset's full metadata structure
+ $assetRep = $this->buildAssetRepresentationFromMasterAsset($filename, $sourceMasterAsset);
- $postFields = [
- 'asset_representation' => json_encode($minimalRep),
- 'manifest' => json_encode($uploadManifest),
- 'parent_folder_id' => $folderId,
- 'files' => new \CURLFile($filePath, $mimeType, $filename)
- ];
+ $postFields = [
+ 'asset_representation' => json_encode($assetRep),
+ 'manifest' => json_encode($uploadManifest),
+ 'parent_folder_id' => $folderId,
+ 'files' => new \CURLFile($filePath, $mimeType, $filename)
+ ];
+ } else {
+ // No master asset - minimal representation (will likely fail)
+ $minimalRep = [
+ 'asset_resource' => [
+ 'asset' => [
+ 'name' => $filename,
+ 'security_policy_list' => [['id' => 1594]]
+ ]
+ ]
+ ];
+
+ $postFields = [
+ 'asset_representation' => json_encode($minimalRep),
+ 'manifest' => json_encode($uploadManifest),
+ 'parent_folder_id' => $folderId,
+ 'files' => new \CURLFile($filePath, $mimeType, $filename)
+ ];
+ }
// Get authorization header
$authHeader = '';
@@ -101,7 +113,7 @@ class AssetUploader
$authHeader = $headers['Authorization'];
}
- // Use curl directly for multipart upload
+ // Use curl directly for multipart upload with extended timeout
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
@@ -113,19 +125,31 @@ class AssetUploader
'Authorization: ' . $authHeader
],
CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_TIMEOUT => 120
+ CURLOPT_TIMEOUT => 300, // 5 minutes
+ CURLOPT_CONNECTTIMEOUT => 30
]);
- $response = curl_exec($ch);
+ // Execute with error suppression to prevent crashes
+ set_time_limit(300); // Give PHP 5 minutes
+ $response = @curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- $error = curl_error($ch);
+ $curlError = curl_error($ch);
curl_close($ch);
- if ($error) {
+ if ($curlError) {
return [
'success' => false,
'filename' => $filename,
- 'error' => 'CURL error: ' . $error,
+ 'error' => 'CURL error: ' . $curlError,
+ 'http_code' => 0
+ ];
+ }
+
+ if ($response === false) {
+ return [
+ 'success' => false,
+ 'filename' => $filename,
+ 'error' => 'Upload request failed - no response received',
'http_code' => 0
];
}
@@ -168,45 +192,31 @@ class AssetUploader
*/
private function buildAssetRepresentationFromMasterAsset($filename, $masterAsset)
{
- // Extract key fields from master asset
- $metadataModelId = $masterAsset['metadata_model_id'] ?? null;
- $securityPolicies = $masterAsset['security_policy_list'] ?? null;
- $metadata = $masterAsset['metadata'] ?? [];
+ // Extract ONLY the critical IDs - no metadata structure at all
+ $metadataModelId = $masterAsset['metadata_model_id'] ?? 'ECOMMERCE';
- // Debug: Log what we're using
- error_log("Upload Debug - Metadata Model ID: " . ($metadataModelId ?? 'NULL'));
- error_log("Upload Debug - Master Asset Keys: " . implode(', ', array_keys($masterAsset)));
+ // Simplify security policies to just IDs
+ $securityPolicyIds = [];
+ if (isset($masterAsset['security_policy_list'])) {
+ foreach ($masterAsset['security_policy_list'] as $policy) {
+ $securityPolicyIds[] = ['id' => $policy['id'] ?? 1594];
+ }
+ }
+ if (empty($securityPolicyIds)) {
+ $securityPolicyIds = [['id' => 1594]];
+ }
- // Build asset representation WITHOUT metadata_model_id
- // The metadata structure itself contains the model info
+ // Build minimal asset representation - NO metadata structure to avoid crash
$assetRep = [
'asset_resource' => [
'asset' => [
'name' => $filename,
- 'metadata' => $metadata,
- 'security_policy_list' => $securityPolicies ?: [['id' => 1594]]
+ 'metadata_model_id' => $metadataModelId,
+ 'security_policy_list' => $securityPolicyIds
]
]
];
- // DO NOT include metadata_model_id - it causes file extension restrictions
- // The metadata structure already has the model ID embedded in metadata.id
-
- // Update the ARTESIA.FIELD.ASSET NAME field in metadata if it exists
- if (isset($metadata['metadata_element_list'])) {
- foreach ($assetRep['asset_resource']['asset']['metadata']['metadata_element_list'] as &$category) {
- if (isset($category['metadata_element_list'])) {
- foreach ($category['metadata_element_list'] as &$field) {
- if ($field['id'] === 'ARTESIA.FIELD.ASSET NAME') {
- if (isset($field['value']['value']['value'])) {
- $field['value']['value']['value'] = $filename;
- }
- }
- }
- }
- }
- }
-
return $assetRep;
}
diff --git a/workflow_v3.php b/workflow_v3.php
index 9f28deb..6ba9977 100644
--- a/workflow_v3.php
+++ b/workflow_v3.php
@@ -263,15 +263,10 @@ if ($_POST && $testRunner) {
if ($uploadFolderId) {
$results['upload_folder_id'] = $uploadFolderId;
+ $success = "Found upload target folder";
- // ALSO get Master Assets to copy their metadata
- $masterFolderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3);
- if ($masterFolderId) {
- $results['master_assets_for_upload'] = getAssetsFromFolder($testRunner, $masterFolderId);
- $success = "Found upload folder and " . count($results['master_assets_for_upload']) . " master assets for metadata reference";
- } else {
- $success = "Found upload target folder (no master assets found)";
- }
+ // TODO: Master assets fetching disabled - causes PHP crashes due to metadata size
+ // Will re-enable once upload file extension issue is resolved
} else {
$error = "Upload folder not found in campaign";
}
@@ -281,34 +276,38 @@ if ($_POST && $testRunner) {
case 'upload_files':
if (isset($_FILES['upload_files']) && isset($results['upload_folder_id'])) {
- // Get selected master asset metadata if user chose one
- $selectedMasterAsset = null;
- $masterMetadataIndex = $_POST['master_metadata_index'] ?? '';
+ // Get selected master asset lightweight data
+ $selectedMasterAssetLight = null;
+ $masterMetadataIndex = $_POST['master_metadata_index'] ?? '0';
- // Use master_assets_for_upload (fetched in Upload workflow)
+ // Use master_assets_for_upload (lightweight version)
if ($masterMetadataIndex !== '' && isset($results['master_assets_for_upload'][$masterMetadataIndex])) {
- $selectedMasterAsset = $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
- $selectedMasterAsset = $results['master_assets_for_upload'][0];
+ $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
- if ($selectedMasterAsset) {
- $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';
+ $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' => extractFolderName($selectedMasterAsset),
- 'metadata_model_id' => $selectedMasterAsset['metadata_model_id'] ?? 'NOT FOUND',
- 'has_security_policies' => isset($selectedMasterAsset['security_policy_list']) ? 'YES' : 'NO',
- 'master_mime_type' => $selectedMasterAsset['mime_type'] ?? 'Unknown',
- 'upload_filename' => $uploadFileName,
- 'upload_detected_mime' => $uploadMimeType
- ];
- }
+ $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;
@@ -913,6 +912,36 @@ function findUploadFolder($testRunner, $campaignId, $configV3)
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 uploadFiles($testRunner, $uploadedFiles, $folderId, $selectedMasterAsset = null)
{
$apiClient = new ApiClient();
@@ -955,8 +984,8 @@ function uploadFiles($testRunner, $uploadedFiles, $folderId, $selectedMasterAsse
continue;
}
- // Pass the entire selected master asset (not just metadata)
- $result = $uploader->uploadFile($tmpName, $folderId, [], $selectedMasterAsset);
+ // Pass the entire selected master asset (not just metadata) and TestRunner
+ $result = $uploader->uploadFile($tmpName, $folderId, [], $selectedMasterAsset, $testRunner);
if ($result['success']) {
$results['successful']++;
@@ -1742,7 +1771,6 @@ $envInfo = $configV3->getEnvironmentInfo();
$masterAsset): ?>
-
@@ -1794,12 +1829,16 @@ $envInfo = $configV3->getEnvironmentInfo();
🔍 Upload Debug Info:
Your File: = htmlspecialchars($results['upload_debug']['upload_filename']) ?>
(= htmlspecialchars($results['upload_debug']['upload_detected_mime']) ?>)
+
Target Folder ID: = htmlspecialchars($results['upload_debug']['upload_folder_id']) ?>
Using Metadata From: = htmlspecialchars($results['upload_debug']['selected_master_name']) ?>
Master Asset ID: = htmlspecialchars($results['upload_debug']['selected_master_asset_id']) ?>
Metadata Model ID:
= htmlspecialchars($results['upload_debug']['metadata_model_id']) ?>
- Has Security Policies: = $results['upload_debug']['has_security_policies'] ?>
- Master MIME Type: = htmlspecialchars($results['upload_debug']['master_mime_type']) ?>
+ Has Security Policies: = $results['upload_debug']['has_security_policies'] ?> (= $results['upload_debug']['security_policy_count'] ?> policies)
+ Master MIME Type: = htmlspecialchars($results['upload_debug']['master_mime_type']) ?>
+
+
Sending: asset_representation (model ID + security policies only) + manifest + parent_folder_id + files
+
Note: Full metadata too large to send - using model ID inheritance instead