From b38f03c0e7218762d90fa5092696b127f24f36db Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 25 Jan 2026 07:07:26 +0000
Subject: [PATCH] =Some logical flaws in Queue.php, Queue.js, ContentExecutor.php, UploadExecutor.php - particularly with timeline ordering, frontend queue updates, etc

---
 inc/rest/routes/ContentRoutes.php |  175 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 140 insertions(+), 35 deletions(-)

diff --git a/inc/rest/routes/ContentRoutes.php b/inc/rest/routes/ContentRoutes.php
index 3fc50bb..46c7d45 100644
--- a/inc/rest/routes/ContentRoutes.php
+++ b/inc/rest/routes/ContentRoutes.php
@@ -6,7 +6,7 @@
 use JVBase\managers\queue\executors\ContentExecutor;
 use JVBase\managers\queue\TypeConfig;
 use JVBase\rest\RestRouteManager;
-use JVBase\managers\CacheManager;
+use JVBase\managers\Cache;
 use JVBase\meta\MetaManager;
 use JVBase\utility\Features;
 use WP_Post;
@@ -37,7 +37,7 @@
 		$this->cache_name = 'user_content_' . get_current_user_id();
 		parent::__construct();
 		if (JVB_TESTING) {
-			$this->cache->clear();
+			$this->cache->flush();
 		}
 
 		$this->action = 'dash-';
@@ -166,7 +166,6 @@
 	public function handleContentUpdate(WP_REST_Request $request): WP_REST_Response
 	{
 		$data = $request->get_params();
-		error_log('Received data: ' . print_r($data, true));
 		$user_id = $data['user'];
 
 		if (!$this->userCheck($user_id)) {
@@ -257,6 +256,7 @@
 	{
 		$params = $request->get_params();
 		$user_id = $params['user'];
+
 		if (!$this->userCheck($user_id)) {
 			return new WP_REST_Response([
 				'success' => false,
@@ -316,12 +316,10 @@
 			$args['s'] = sanitize_text_field($params['search']);
 		}
 
+
 		$key = $this->cache->generateKey($args);
 		// Check HTTP cache headers with the specific content type
-		$content_type = $params['content'] ?? $params['type'];
-		$cache_check = $this->checkHeaders($request, $content_type, [
-			'filter_hash' => $key,
-		]);
+		$cache_check = $this->checkHeaders($request, $key);
 		if ($cache_check) {
 			return $cache_check;
 		}
@@ -347,7 +345,6 @@
 		$this->taxonomies = $this->getTaxonomies($this->post_type);
 		$posts = array_map([$this, 'prepareItem'], $query->posts);
 
-
 		$data = [
 			'items' => $posts,
 			'total' => $query->found_posts,
@@ -580,11 +577,6 @@
 				];
 
 			}
-
-			CacheManager::for($post_data['content'])->clear();
-			if (jvbSiteUsesFeedBlock()) {
-				CacheManager::for('feed')->clear();
-			}
 		}
 
 		if (jvbSiteHasNotifications()) {
@@ -786,20 +778,20 @@
 				$meta = new MetaManager($timeline['id'], 'post');
 				$oldValues = $meta->getAll(array_keys($allowedFields));
 
-				// Set number taxonomy to menu_order (always update for reordering)
-				if (!$is_parent) {
-					$number_value = $order;
-					$term = get_term_by('name', (string)$number_value, BASE . 'number');
-					if (!$term) {
-						$result = wp_insert_term((string)$number_value, BASE . 'number');
-						if ($result && !is_wp_error($result)) {
-							$term = $result['term_id'];
-						}
-					} else {
-						$term = $term->term_id;
-					}
-					$allowedFields['number'] = $term;
-				}
+//				// Set number taxonomy to menu_order (always update for reordering)
+//				if (!$is_parent) {
+//					$number_value = $order;
+//					$term = get_term_by('name', (string)$number_value, BASE . 'number');
+//					if (!$term) {
+//						$result = wp_insert_term((string)$number_value, BASE . 'number');
+//						if ($result && !is_wp_error($result)) {
+//							$term = $result['term_id'];
+//						}
+//					} else {
+//						$term = $term->term_id;
+//					}
+//					$allowedFields['number'] = $term;
+//				}
 
 				// Auto-timeline logic
 				if ($prevDate) {
@@ -828,7 +820,7 @@
 				$updateValues = array_filter($allowedFields, function ($value, $key) use ($oldValues) {
 					return (!array_key_exists($key, $oldValues) || $value !== $oldValues[$key]);
 				}, ARRAY_FILTER_USE_BOTH);
-				error_log('Setting values for ' . $timeline['id'] . ': ' . print_r($updateValues, true));
+
 
 				$meta->setAll($updateValues);
 				$timeline['id'] = (int)$timeline['id'];
@@ -845,8 +837,8 @@
 		}
 
 		if ($clearParent) {
-			$this->cache->clear();
-			CacheManager::onPostSave($parent_id, $parent_post);
+			$this->cache->flush();
+			Cache::onPostChange($parent_id, $parent_post);
 		}
 
 
@@ -1029,7 +1021,7 @@
 		}
 		$item['fields']['timeline'] = $subFields;
 		$item['images'] = $item['images'] + $images;
-
+		$item['number'] = $mainMeta->getValue('number');
 
 		return $item;
 	}
@@ -1179,10 +1171,6 @@
 //                            $queue->updateOperationProgress($operation->id, $key + 1, $total);
 						}
 					}
-
-					//Clear cache
-					CacheManager::for($data['content'])->clear();
-					CacheManager::for('feed')->clear();
 				}
 
 				return [
@@ -1203,4 +1191,121 @@
 
 		return $result;
 	}
+	// Add to ContentRoutes.php
+
+	/**
+	 * One-time migration: Set latest_date meta for all timeline posts
+	 * Call this once via WP-CLI or a temporary admin page
+	 *
+	 * Usage: add_action('admin_init', function() {
+	 *     if (current_user_can('manage_options')) {
+	 *         JVB()->routes('content')->migrateTimelineLatestDates();
+	 *     }
+	 * });
+	 */
+	public function migrateTimelineLatestDates(): array
+	{
+		global $wpdb;
+
+		$results = [
+			'processed' => 0,
+			'updated' => 0,
+			'skipped' => 0,
+			'errors' => []
+		];
+
+		// Get all timeline post types
+		$timeline_types = [];
+		foreach (JVB_CONTENT as $type => $config) {
+			if (Features::forContent($type)->has('is_timeline')) {
+				$timeline_types[] = BASE . $type;
+			}
+		}
+
+		if (empty($timeline_types)) {
+			return $results;
+		}
+
+		// Get all parent timeline posts
+		$args = [
+			'post_type' => $timeline_types,
+			'post_status' => ['publish', 'draft'],
+			'post_parent' => 0,
+			'posts_per_page' => -1,
+			'fields' => 'ids'
+		];
+
+		$parent_ids = get_posts($args);
+
+		foreach ($parent_ids as $parent_id) {
+			$results['processed']++;
+
+			try {
+				// Get all children including the parent
+				$children = get_children([
+					'post_parent' => $parent_id,
+					'post_status' => ['publish', 'draft'],
+					'orderby' => 'menu_order',
+					'order' => 'ASC',
+					'fields' => 'ids'
+				]);
+
+				// Add parent to the list
+				array_unshift($children, $parent_id);
+
+				// Find latest date among all posts
+				$latest_timestamp = 0;
+
+				foreach ($children as $post_id) {
+					$date = get_post_meta($post_id, BASE . 'date', true);
+
+					if ($date) {
+						$timestamp = strtotime($date);
+						if ($timestamp > $latest_timestamp) {
+							$latest_timestamp = $timestamp;
+						}
+					}
+				}
+
+				// Update parent with latest date
+				if ($latest_timestamp > 0) {
+					update_post_meta($parent_id, BASE . 'latest_date', $latest_timestamp);
+					$results['updated']++;
+					error_log("Updated post {$parent_id} with latest_date: {$latest_timestamp}");
+				} else {
+					// Fallback to parent post's post_date
+					$parent_post = get_post($parent_id);
+					$fallback_timestamp = strtotime($parent_post->post_date);
+
+					if ($fallback_timestamp > 0) {
+						update_post_meta($parent_id, BASE . 'latest_date', $fallback_timestamp);
+						$results['updated']++;
+						error_log("Updated post {$parent_id} with fallback latest_date: {$fallback_timestamp} (from post_date)");
+					} else {
+						$results['skipped']++;
+						error_log("No dates found for post {$parent_id}");
+					}
+				}
+
+			} catch (Exception $e) {
+				$results['errors'][] = [
+					'post_id' => $parent_id,
+					'error' => $e->getMessage()
+				];
+			}
+		}
+
+		error_log('Timeline migration complete: ' . print_r($results, true));
+		return $results;
+	}
 }
+
+
+//add_action('init', function() {
+////	delete_option('jvb_timeline_migrated');
+//	if (get_option('jvb_timeline_migrated')) {
+//		return;
+//	}
+//	JVB()->routes('content')->migrateTimelineLatestDates();
+//	update_option('jvb_timeline_migrated', true);
+//});

--
Gitblit v1.10.0