From 5b50afdcafd150186ea5c7b0e1cad98065590b35 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 28 Aug 2026 18:44:28 +0000
Subject: [PATCH] =A few more phpStorm suggestions, mainly in PHPDocs
---
inc/rest/routes/UploadRoutes.php | 641 +++++++--------------------------------------------------
1 files changed, 83 insertions(+), 558 deletions(-)
diff --git a/inc/rest/routes/UploadRoutes.php b/inc/rest/routes/UploadRoutes.php
index f1db7a0..4b3128e 100644
--- a/inc/rest/routes/UploadRoutes.php
+++ b/inc/rest/routes/UploadRoutes.php
@@ -1,17 +1,17 @@
<?php
namespace JVBase\rest\routes;
-use JVBase\managers\queue\executors\UploadExecutor;
-use JVBase\managers\queue\TypeConfig;
+use JVBase\Instance;
+use JVBase\managers\Errors;
+use JVBase\managers\queue\Queue;
+use JVBase\registrar\Registrar;
use JVBase\rest\PermissionHandler;
use JVBase\rest\Rest;
use JVBase\meta\Meta;
use JVBase\managers\UploadManager;
use JVBase\rest\Route;
-use JVBase\utility\Features;
use WP_REST_Request;
use WP_REST_Response;
-use WP_Error;
use Exception;
if (!defined('ABSPATH')) {
@@ -19,67 +19,15 @@
}
class UploadRoutes extends Rest
{
+ use Instance;
public function __construct()
{
parent::__construct();
- add_action('init', [$this, 'registerUploadExecutors'], 5);
}
- /**
- * Register upload operation types with the queue's TypeRegistry
- */
- public function registerUploadExecutors(): void
- {
- $registry = JVB()->queue()->registry();
- $executor = new UploadExecutor();
- // Image uploads - chunked at 5 files
- $registry->register('image_upload', new TypeConfig(
- executor: $executor,
- chunkKey: 'secured_files',
- chunkSize: 5
- ));
-
- // Video uploads - one at a time (heavy processing)
- $registry->register('video_upload', new TypeConfig(
- executor: $executor,
- chunkKey: 'secured_files',
- chunkSize: 1
- ));
-
- // Document uploads - chunked at 10
- $registry->register('document_upload', new TypeConfig(
- executor: $executor,
- chunkKey: 'secured_files',
- chunkSize: 10
- ));
-
- // Metadata updates
- $registry->register('update_image_meta', new TypeConfig(
- executor: $executor
- ));
-
- // Cleanup - chunked at 5
- $registry->register('temporary_cleanup', new TypeConfig(
- executor: $executor,
- chunkKey: 'files',
- chunkSize: 5
- ));
-
- // Attach to content (depends on upload completing)
- $registry->register('attach_upload_to_content', new TypeConfig(
- executor: $executor
- ));
-
- // Process upload groups into posts
- $registry->register('process_upload_groups', new TypeConfig(
- executor: $executor,
- chunkKey: 'posts',
- chunkSize: 5
- ));
- }
/**
* Registers upload routes
@@ -100,7 +48,6 @@
->args([
'id' => 'string|required',
'content' => 'string|required',
- 'user' => 'int|required'
])
->register();
@@ -109,8 +56,8 @@
->auth(PermissionHandler::combine(['nonce']))
->rateLimit(30)
->args([
- 'user' => 'int|required',
- 'items' => 'array|required'
+ 'items' => 'array|required',
+ 'id' => 'string'
])
->register();
}
@@ -119,11 +66,15 @@
* Build the main $context for UploadManager from the $request params
* @param WP_REST_Request $request
* @return array
+ * @throws Exception
+ * @throws Exception
*/
protected function buildUploadArgs(WP_REST_Request $request):array
{
$data = $request->get_params();
$args = [];
+ $registrar = Registrar::getInstance($data['content']??'');
+
foreach ($data as $key => $value) {
switch ($key) {
case 'depends_on':
@@ -134,15 +85,25 @@
case 'item_id':
if (is_numeric($value)) {
$args['item_id'] = absint($value);
- if (!array_key_exists('post_id', $args)) {
- $args['post_id'] = absint($value);
+ if ($registrar) {
+ switch ($registrar->getType()) {
+ case 'post':
+ $args['post_id'] = absint($value);
+ break;
+ case 'term':
+ $args['term_id'] = absint($value);
+ break;
+ case 'user':
+ $args['user_id'] = absint($value);
+ break;
+ }
}
}
break;
// Post Type/Taxonomy
case 'content':
- $key = str_replace('-', '_', $key);
- if ($value === 'options' || array_key_exists($value, JVB_CONTENT) || Features::forTaxonomy($key)->has('is_content')) {
+ $value = str_replace('-', '_', $value);
+ if ($value === 'options' || $registrar) {
$args['content'] = $value;
}
break;
@@ -156,15 +117,13 @@
break;
// User ID
case 'user':
- if ($this->userCheck($value)) {
- $args['user'] = (int) $value;
- if (!array_key_exists('post_id', $args) &&
- !array_key_exists('post_id', $data) &&
- !array_key_exists('term_id', $data) &&
- !array_key_exists('item_id', $data)) {
- $args['post_id'] = (int)get_user_meta((int) $value, BASE.'link', true);
- }
+ if (!array_key_exists('post_id', $args) &&
+ !array_key_exists('post_id', $data) &&
+ !array_key_exists('term_id', $data) &&
+ !array_key_exists('item_id', $data)) {
+ $args['post_id'] = (int)get_user_meta((int) $value, BASE.'profile_link', true);
}
+
break;
// Operation ID
case 'id':
@@ -243,13 +202,13 @@
case 'field_key':
case 'field_type':
case 'subtype':
- case 'item_id':
case 'context':
if (is_string($value)) {
$args[$key] = sanitize_text_field($value);
}
break;
}
+ $args['user'] = get_current_user_id();
}
return $args;
}
@@ -268,8 +227,8 @@
$files = $request->get_file_params();
$args = $this->buildUploadArgs($request);
-
- if (!$args['user']) {
+ $userID = get_current_user_id();
+ if (!$userID) {
return $this->unauthorized();
}
if (!$args['content']) {
@@ -291,7 +250,7 @@
} catch (Exception $e) {
// Error handling...
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[UploadRoutes]:handleUploadRequest',
$e->getMessage(),
[
@@ -309,7 +268,7 @@
*/
protected function secureFiles(array $files, array $args): array
{
- $uploader = new UploadManager();
+ $uploader = UploadManager::getInstance();
$secured_files = [];
$errors = [];
@@ -395,9 +354,11 @@
$chunkSize = 10;
}
- JVB()->queue()->queueOperation(
+ error_log('Queueing Operation: '.print_r($operation_type, true));
+ error_log('With ID: '.print_r($args['upload'], true));
+ $queuedProcessing = Queue::getInstance()->queueOperation(
$operation_type,
- $args['user'],
+ get_current_user_id(),
array_merge(
['secured_files' => $secured_data['files']],
$args
@@ -409,39 +370,29 @@
]
);
+ error_log('queuedProcessing operation: '.print_r($queuedProcessing, true));
+
+ $uploadOpId = $queuedProcessing['operation_id'];
+
if ($args['mode'] !== 'selection') {
- $dependencies = [$args['upload']];
- if (!empty($args['depends_on'])) {
- $dependencies[] = $args['depends_on'];
+
+ // Only create attach_upload_to_content if the upload was NOT merged.
+ // When merged, the original upload's attach_upload_to_content
+ // will handle all files after the merged image_upload completes.
+ if (!$queuedProcessing['updated_existing']) {
+ Queue::getInstance()->queueOperation(
+ 'attach_upload_to_content',
+ get_current_user_id(),
+ $args,
+ [
+ 'priority' => 'high',
+ 'operation_id' => $args['id'],
+ 'depends_on' => [$uploadOpId]
+ ]
+ );
}
-
- JVB()->queue()->queueOperation(
- 'attach_upload_to_content',
- $args['user'],
- $args,
- [
- 'priority' => 'high',
- 'operation_id' => $args['id'],
- 'depends_on' => $dependencies
- ]
- );
}
- JVB()->queue()->queueOperation(
- 'temporary_cleanup',
- $args['user'],
- [
- 'files' => $secured_data['files'],
- 'context' => $args,
- ],
- [
- 'priority' => 'low',
- 'chunk_size' => 5,
- 'chunk_key' => 'files',
- 'depends_on' => $args['upload']
- ]
- );
-
return $args['id'];
}
@@ -459,145 +410,8 @@
};
}
- /**
- * Step 3: Process operation from queue
- * Called by OperationQueue
- * @param WP_Error|array $result
- * @param object $operation
- * @param array $data
- *
- * @return array|WP_Error
- */
- public function processOperation(array $result, object $operation, array $data): array
- {
- // Only handle our operation types
- $handled_types = [
- 'image_upload',
- 'video_upload',
- 'document_upload',
- 'update_metadata',
- 'temporary_cleanup',
- 'attach_upload_to_content',
- 'process_upload_groups'
- ];
- if (!in_array($operation->type, $handled_types)) {
- return $result; // Not our operation, pass through
- }
- try {
- // Route to appropriate handler
- $handler_result = match($operation->type) {
- 'image_upload' => $this->processImageUpload($operation, $data),
- 'video_upload' => $this->processVideoUpload($operation, $data),
- 'document_upload' => $this->processDocumentUpload($operation, $data),
- 'update_metadata' => $this->processUploadMeta($result, $operation, $data),
- 'temporary_cleanup' => $this->processTemporaryCleanup($result, $operation, $data),
- 'attach_upload_to_content' => $this->processAttachToContent($operation, $data),
- 'process_upload_groups' => $this->processUploadGroups($result, $operation, $data),
- default => new WP_Error('unknown_type', 'Unknown operation type')
- };
-
- // Handle WP_Error
- if (is_wp_error($handler_result)) {
- return [
- 'success' => false,
- 'result' => $handler_result->get_error_message()
- ];
- }
-
- return $handler_result;
-
- } catch (Exception $e) {
- JVB()->error()->log(
- '[UploadRoutes]:processOperation',
- $e->getMessage(),
- [
- 'operation_id' => $operation->id,
- 'operation_type' => $operation->type
- ]
- );
-
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
- /**
- * Standardize processing result
- */
- protected function standardizeResult(array $result): array
- {
- return [
- 'attachment_id' => $result['attachment_id'],
- 'url' => $result['url'],
- 'file' => $result['file'],
- 'upload_id' => $result['upload_id'] ?? null
- ];
- }
-
- protected function processAttachToContent(object $operation, array $data): array
- {
- try {
- // Get the results from the upload operation
- $upload_results = JVB()->queue()->getOperationValue($data['upload'], 'result', true);
-
- if (empty($upload_results)) {
- throw new Exception('No upload results found for operation: ' . $data['upload']);
- }
-
- if (empty($data['post_id']) || str_starts_with((string)($data['item_id'] ?? ''), 'new')) {
- foreach ($operation->dependencies as $depId) {
- $dep = JVB()->queue()->get($depId);
- if ($dep && $dep->type === 'content_update' && !empty($dep->result['new_posts'])) {
- $itemId = $data['item_id'] ?? null;
- if ($itemId && isset($dep->result['new_posts'][$itemId])) {
- $data['post_id'] = $dep->result['new_posts'][$itemId];
- break;
- }
- }
- }
-
- if (empty($data['post_id'])) {
- throw new Exception('Could not resolve post_id from dependencies');
- }
- }
-
- // Now attach to the specified content
- if (!empty($data['field_name'])) {
- $this->updateFieldValue($data, $upload_results);
- }
-
- return [
- 'success' => true,
- 'result' => 'Attachments linked to content'
- ];
-
- } catch (Exception $e) {
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
-
- /**
- * Cleanup temporary files after processing
- */
- protected function cleanupTempFiles(array $secured_files, int $user_id): void
- {
- $uploader = new UploadManager();
-
- foreach ($secured_files as $secured) {
- if (!empty($secured['temp_path']) && file_exists($secured['temp_path'])) {
- @unlink($secured['temp_path']);
- }
- }
-
- // Clean up empty directories
- $uploader->cleanupEmptyTempDirs($user_id);
- }
/**
* Update field value with new attachment IDs
@@ -614,7 +428,7 @@
} elseif (array_key_exists('term_id', $data)) {
$meta = Meta::forTerm($data['term_id']);
} else {
- $link = (int)get_user_meta($data['user'], BASE.'link');
+ $link = (int)get_user_meta($data['user'], BASE.'profile_link');
$meta = Meta::forPost($link);
}
@@ -627,162 +441,8 @@
// Update with comma-separated string
$meta->set($data['field_name'], implode(',', $all_ids));
- $meta->save();
}
- /**
- * Generic file upload processor - works for images, videos, documents
- */
- protected function processFileUpload(object $operation, array $data, string $file_type): WP_Error|array
- {
- try {
- $uploader = new UploadManager();
- $processed_results = [];
- $config = $this->getFieldConfig($data);
-
- $args = $data;
- unset($args['secured_files']);
-
- foreach ($data['secured_files'] as $secured_file) {
- $result = $uploader->processUpload(
- $secured_file['temp_path'],
- array_merge(
- $config,
- [
- 'file_type' => $file_type,
- 'user_id' => $operation->user_id,
- 'post_id' => (int)($data['post_id'] ?? 0),
- 'term_id' => (int)($data['term_id'] ?? 0),
- 'original_name' => $secured_file['original_name'],
- 'mime_type' => $secured_file['mime_type'],
- 'content' => $data['content'] ?? '',
- ]
- )
- );
-
- if (!is_wp_error($result)) {
- $standardized = $this->standardizeResult($result);
-
- // Use embedded upload_id from the secured file itself
- $standardized['upload_id'] = $secured_file['upload_id'] ?? null;
-
- if ($standardized['upload_id']) {
- $processed_results[$standardized['upload_id']] = $standardized;
- } else {
- $processed_results[] = $standardized;
- }
-
- // Apply frontend metadata if provided
- if (!empty($secured_file['metadata'])) {
- $this->applyMeta($standardized['attachment_id'], $secured_file['metadata']);
- }
- }
- }
-
- $this->handleUploadDestination($data, $processed_results);
-
- // Cleanup temporary files
- $this->cleanupTempFiles($data['secured_files'], $operation->user_id);
-
- return [
- 'success' => true,
- 'result' => $processed_results
- ];
-
- } catch (Exception $e) {
- JVB()->error()->log(
- '[UploadRoutes]:processFileUpload',
- $e->getMessage(),
- [
- 'operation_id' => $operation->id,
- 'file_type' => $file_type,
- 'user_id' => $operation->user_id
- ]
- );
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
-
- /**
- * Process image uploads
- */
- protected function processImageUpload(object $operation, array $data): WP_Error|array
- {
- return $this->processFileUpload($operation, $data, 'image');
- }
-
- /**
- * Process video uploads
- */
- protected function processVideoUpload(object $operation, array $data): WP_Error|array
- {
- return $this->processFileUpload($operation, $data, 'video');
- }
-
- /**
- * Process document uploads
- */
- protected function processDocumentUpload(object $operation, array $data): WP_Error|array
- {
- return $this->processFileUpload($operation, $data, 'document');
- }
-
- /**
- * Process temporary cleanup operation
- * Called by OperationQueue for 'temporary_cleanup' operations
- *
- * @param array $result
- * @param object $operation
- * @param array $data
- * @return array
- */
- protected function processTemporaryCleanup(array $result, object $operation, array $data): array
- {
- try {
- // Cleanup temporary files if they exist
- if (!empty($data['secured_files'])) {
- $this->cleanupTempFiles($data['secured_files'], $operation->user_id);
- }
-
- // If specific temp paths provided
- if (!empty($data['temp_paths']) && is_array($data['temp_paths'])) {
- foreach ($data['temp_paths'] as $temp_path) {
- if (file_exists($temp_path)) {
- @unlink($temp_path);
- }
- }
- }
-
- // Cleanup empty temp directories for this user
- if (!empty($operation->user_id)) {
- $uploader = new UploadManager();
- $uploader->cleanupEmptyTempDirs($operation->user_id);
- }
-
- return [
- 'success' => true,
- 'result' => 'Temporary files cleaned up successfully'
- ];
-
- } catch (Exception $e) {
- JVB()->error()->log(
- '[UploadRoutes]:processTemporaryCleanup',
- $e->getMessage(),
- [
- 'operation_id' => $operation->id,
- 'user_id' => $operation->user_id
- ]
- );
-
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
/**
* Handle metadata update requests
@@ -812,10 +472,12 @@
if (!empty($attachments)) {
error_log('Attachments: '.print_r($attachments, true));
- return $this->queueMetaUpdate($attachments, $data['user']);
+ return $this->queueMetaUpdate($attachments, absint($data['user']), sanitize_text_field($data['id']??''));
}
+
+
return $this->sendResponse(
false,
['error_code' => 'missing_identifiers'],
@@ -823,7 +485,7 @@
);
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[UploadRoutes]:handleMetadataUpdate',
$e->getMessage(),
[
@@ -882,9 +544,9 @@
/**
* Queue metadata update with dependency on upload operation
*/
- protected function queueMetaUpdate(array $data, int $user): WP_REST_Response
+ protected function queueMetaUpdate(array $data, int $user, ?string $operationId = null): WP_REST_Response
{
- $queue = JVB()->queue();
+ $queue = Queue::getInstance();
$depends_on = [];
$errors = [];
$original = count($data);
@@ -893,95 +555,30 @@
$depends_on[] = $info['depends_on'];
}
}
+ $queueData = [
+ 'depends_on' => $depends_on,
+ ];
+ if ($operationId) {
+ $queueData['operation_id'] = $operationId;
+ }
$operationID = $queue->queueOperation(
'update_image_meta',
$user,
$data,
- [
- 'depends_on' => $depends_on,
- ]
+ $queueData
);
return $this->sendResponse(
true,
[
- 'operation_id' => $operationID,
+ 'operation_id' => $operationID['operation_id']??$operationId,
'message' => "Successfully queued ".count($data)." of {$original} meta updates"
],
'Metadata update queued - will apply after upload completes'
);
}
- /**
- * Process metadata update operation (called by queue processor)
- */
- public function processUploadMeta(WP_Error|array $result, object $operation, array $data): WP_Error|array
- {
- try {
- if (!is_array($operation->depends_on)) {
- $operation->depends_on = [$operation->depends_on];
- }
- $updated_count = 0;
- $errors = [];
- foreach ($operation->depends_on as $dependency) {
- $operationData = JVB()->queue()->getOperation($dependency);
- if (!$operationData || $operationData->state !== 'completed') {
- throw new Exception('Original upload operation not found or not completed');
- }
- $uploadResults = json_decode($operationData->result, true);
- if (!$uploadResults || !$uploadResults['success']) {
- throw new Exception('Original upload operation failed');
- }
- $attachmentsToUpdate = array_filter($data, function ($item) use ($dependency) {
- return $item['depends_on'] === $dependency;
- });
-
- $uploadIDToAttachment = $this->buildUploadToAttachmentMapping(
- array_keys($attachmentsToUpdate),
- $uploadResults['data']
- );
-
- if (empty($uploadIDToAttachment)) {
- throw new Exception('No valid upload ID to attachment ID mappings found');
- }
-
- foreach ($uploadIDToAttachment as $uploadId => $attachmentId) {
- try {
- $this->applyMeta($attachmentId, $attachmentsToUpdate[$uploadId]);
- $updated_count++;
- } catch (Exception $e) {
- $errors[] = "Upload {$uploadId} (Attachment {$attachmentId}): " . $e->getMessage();
- }
- }
- }
-
- return [
- 'success' => $updated_count > 0,
- 'result' => [
- 'updated_count' => $updated_count,
- 'mappings' => $uploadIDToAttachment,
- 'errors' => $errors,
- 'message' => "Applied metadata to {$updated_count} attachment(s)"
- ]
- ];
-
- } catch (Exception $e) {
- JVB()->error()->log(
- '[UploadRoutes]:processUploadMeta',
- $e->getMessage(),
- [
- 'operation_id' => $operation->id,
- 'original_operation_id' => $data['original_operation_id'] ?? 'unknown'
- ]
- );
-
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
protected function applyMeta(int $attachment_id, array $metadata): void
{
@@ -1007,31 +604,9 @@
}
/**
- * Build mapping from frontend upload IDs to WordPress attachment IDs
- */
- protected function buildUploadToAttachmentMapping(array $upload_ids, array $results): array
- {
- $mapping = [];
-
- foreach ($results as $result) {
- if (!isset($result['upload_id']) || !isset($result['attachment_id'])) {
- continue;
- }
-
- $upload_id = $result['upload_id'];
- $attachment_id = $result['attachment_id'];
-
- // Validate that this upload_id was requested
- if (in_array($upload_id, $upload_ids)) {
- $mapping[$upload_id] = $attachment_id;
- }
- }
-
- return $mapping;
- }
-
- /**
- * Verify user has access to attachment
+ * @param int $attachment_id
+ * @param int $user_id
+ * @return bool
*/
protected function verifyAttachmentAccess(int $attachment_id, int $user_id): bool
{
@@ -1046,59 +621,9 @@
}
/**
- * Get field configuration for upload processing
- */
- protected function getFieldConfig(array $data): array
- {
- static $config_cache = [];
-
- $cache_key = md5(json_encode([
- $args['content'] ?? '',
- $args['field_name'] ?? ''
- ]));
-
- if (isset($config_cache[$cache_key])) {
- return $config_cache[$cache_key];
- }
-
- $config = [
- 'allowed_types' => null,
- 'max_size' => null,
- 'convert' => 'webp',
- 'quality' => 80,
- 'create_thumbnails' => true,
- ];
-
- // Get field definition from registry if available
- if (!empty($args['content']) && !empty($args['field_name'])) {
- $content_type = $args['content'];
- $field_name = $args['field_name'];
-
- if (array_key_exists($content_type, JVB_CONTENT)) {
- $content_fields = JVB_CONTENT[$content_type]['fields'] ?? [];
- if (array_key_exists($field_name, $content_fields)) {
- $field_def = $content_fields[$field_name];
-
- // Extract relevant config from field definition
- $config = array_merge($config, [
- 'allowed_types' => $field_def['accepted_types'] ?? null,
- 'max_size' => $field_def['max_size'] ?? null,
- 'convert' => $field_def['convert'] ?? 'webp',
- 'quality' => $field_def['quality'] ?? 80,
- 'create_thumbnails' => $field_def['create_thumbnails'] ?? true,
- ]);
- }
- }
- }
-
- $config_cache[$cache_key] = $config;
- return $config;
- }
-
-
-
- /**
* Get files info for error logging
+ * @param array $files
+ * @return array
*/
protected function getFilesInfo(array $files): array
{
@@ -1131,7 +656,7 @@
$files = $request->get_file_params();
$args = $this->buildUploadArgs($request);
- if (!array_key_exists('user', $args) || $args['user'] === 0){
+ if (!$args['user']) {
return $this->unauthorized();
}
if (!array_key_exists('content', $args) || empty($args['content'])) {
@@ -1157,7 +682,7 @@
$chunkSize = 10;
}
- JVB()->queue()->queueOperation(
+ Queue::getInstance()->queueOperation(
$operation_type,
$args['user'],
array_merge(
@@ -1171,7 +696,7 @@
]
);
- $ID = JVB()->queue()->queueOperation(
+ $ID = Queue::getInstance()->queueOperation(
'process_upload_groups',
$args['user'],
$args,
@@ -1185,7 +710,7 @@
return $this->queued($ID['operation_id'], 'Files uploaded and posts queued for creation');
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[UploadRoutes]:handleGroupingRequest',
$e->getMessage(),
[
--
Gitblit v1.10.0