From 58e8ae0759ccfa97c478ccae4e0778bdce70966f Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 22 Jan 2026 22:40:02 +0000
Subject: [PATCH] =DirectoryManager.php updates, some javascript tweaks for CRUD.js, and minor style changes

---
 inc/rest/RestRouteManager.php |   64 +++++++++++++++++++++++++++++++-
 1 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/inc/rest/RestRouteManager.php b/inc/rest/RestRouteManager.php
index 96ccfb7..37db58e 100644
--- a/inc/rest/RestRouteManager.php
+++ b/inc/rest/RestRouteManager.php
@@ -1,11 +1,14 @@
 <?php
 namespace JVBase\rest;
 
+use DateTime;
+use DateTimeZone;
 use JVBase\JVB;
 use JVBase\rest\RateLimiter;
 use JVBase\managers\OperationQueue;
 use JVBase\managers\CacheManager;
 use JVBase\managers\NotificationManager;
+use JVBase\utility\Features;
 use WP_REST_Request;
 use WP_Error;
 use Exception;
@@ -36,7 +39,7 @@
     protected NotificationManager $notifications;
     protected string $cache_name ='';
     protected int $cache_ttl = 3600; //1 hour default
-
+	protected array $response_headers = [];
 
     // Error code constants for consistency
     const ERROR_MISSING_PARAMS = 'missing_parameters';
@@ -127,6 +130,32 @@
 		return true;
 	}
 
+	/**
+	 * Convert MySQL datetime to ISO 8601 timestamp with proper timezone
+	 */
+	public function formatTimestamp(?string $mysql_datetime): ?string
+	{
+		if (empty($mysql_datetime)) {
+			return null;
+		}
+
+		try {
+			// Get WordPress timezone - dates are stored in this timezone
+			$wp_timezone = wp_timezone();
+
+			// Parse the datetime in WordPress timezone
+			$date = new DateTime($mysql_datetime, $wp_timezone);
+
+			// Convert to UTC for API consistency
+			$date->setTimezone(new DateTimeZone('UTC'));
+
+			// Return ISO 8601 format
+			return $date->format('c');
+		} catch (Exception $e) {
+			return null;
+		}
+	}
+
 	protected function checkContent(string $content, bool $bool = false):string|bool
 	{
 		$result = JVB_CONTENT[$content]??JVB_TAXONOMY[$content]??JVB_USER[$content]??'';
@@ -315,7 +344,12 @@
                     $args['orderby'] = 'meta_value_num';
                     break;
                 default:
-                    $args['orderby'] = 'date';
+					if ($this->isTimeline($args, $data)) {
+						$args['meta_key'] = BASE . 'latest_date';
+						$args['orderby'] = 'meta_value_num';
+					}else {
+						$args['orderby'] = 'date';
+					}
             }
         }
 		$order = (array_key_exists('order', $data)) ? strtoupper($data['order']) : 'DESC';
@@ -324,6 +358,17 @@
         return $args;
     }
 
+	protected function isTimeline($args, $data):bool
+	{
+		$post_types = is_array($args['post_type']) ? $args['post_type'] : [$args['post_type']];
+		foreach ($post_types as $type) {
+			if (Features::forContent($type)->has('is_timeline')) {
+				return true;
+			}
+		}
+		return false;
+	}
+
     protected function applyDateFilters(array $args, array $data):array
     {
         if (!array_key_exists('date-filter', $data) && !array_key_exists('dateFrom', $data)) {
@@ -540,6 +585,7 @@
 	protected function error(string $message, string $code, int $status = 400, ?string $field = null): WP_REST_Response
 	{
 		$data = [
+			'success'	=> false,
 			'message' => $message,
 			'code' => $code
 		];
@@ -555,6 +601,7 @@
 	 */
 	protected function success(array $data, int $status = 200): WP_REST_Response
 	{
+		$data['success'] = true;
 		return new WP_REST_Response($data, $status);
 	}
 
@@ -906,6 +953,19 @@
 		$lock_key = 'op_lock_' . md5($operation_key);
 		delete_transient($lock_key);
 	}
+
+	protected function verifyTurnstile(string $token): bool
+	{
+		if (!Features::hasIntegration('cloudflare') || !JVB()->connect('cloudflare')->isSetUp()) {
+			return true;
+		}
+
+		if (empty($token)) {
+			return false;
+		}
+
+		return JVB()->connect('cloudflare')->verifyTurnstile($token);
+	}
 }
 //
 //Simple example:

--
Gitblit v1.10.0