Jake Vanderwerf
2026-08-28 5b50afdcafd150186ea5c7b0e1cad98065590b35
inc/rest/RestRouteManager.php
@@ -3,12 +3,13 @@
use DateTime;
use DateTimeZone;
use JVBase\JVB;
use JVBase\rest\RateLimiter;
use JVBase\integrations\services\Cloudflare;
use JVBase\managers\Errors;
use JVBase\registrar\Registrar;
use JVBase\managers\OperationQueue;
use JVBase\managers\Cache;
use JVBase\managers\NotificationManager;
use JVBase\utility\Features;
use JVBase\base\Site;
use WP_REST_Request;
use WP_Error;
use Exception;
@@ -70,10 +71,10 @@
     * @param string $nonceName nonce name to check
     * @param string|null $nonce optional additional nonce to check
     *
     * @return void|WP_Error
     */
    public function verifyNonce(WP_REST_Request $request, string $nonceName = 'wp_rest', string|null $nonce = null):mixed
    {
     * @return bool|WP_Error
    */
    public function verifyNonce(WP_REST_Request $request, string $nonceName = 'wp_rest', string|null $nonce = null): bool|WP_Error
   {
        $nonce = (!is_null($nonce)) ? $nonce :  $request->get_header('X-WP-Nonce');
        if (!wp_verify_nonce($nonce, $nonceName)) {
@@ -94,7 +95,7 @@
     *
     * @return bool|WP_Error Whether or not we can proceed
     */
    public function checkPermission(WP_REST_Request $request):bool
    public function checkPermission(WP_REST_Request $request):bool|WP_Error
    {
        // Check rate limits first
        if (!$this->rate_limiter->checkLimit($request)) {
@@ -111,7 +112,7 @@
            return false;
        }
        // Verify nonces
        $this->verifyNonce($request, 'wp_rest');
        $this->verifyNonce($request);
        if ($this->action!=='') {
            $this->verifyNonce($request, $this->action . $user_id, $request->get_header('action_nonce'));
        }
@@ -159,11 +160,7 @@
   protected function checkContent(string $content, bool $bool = false):string|bool
   {
      $result = JVB_CONTENT[$content]??JVB_TAXONOMY[$content]??JVB_USER[$content]??'';
      if ($bool) {
         return $result !== '';
      }
      return $result;
      return (bool)Registrar::getInstance($content);
   }
@@ -213,7 +210,7 @@
    protected function logError(string $message, array $context = [], string $severity = 'error')
    {
        try {
            JVB()->error()->log(
            Errors::getInstance()->log(
                'artist_invitations', // component
                $message,
                $context,
@@ -230,7 +227,7 @@
    */
   protected function checkUser(int $userID): bool
   {
      $cache = Cache::for('checkUser', DAY_IN_SECONDS)->connect('user');
      $cache = Cache::for('checkUser', 'user',DAY_IN_SECONDS);
      return $cache->remember($userID, function() use ($userID) {
         return (bool)get_userdata($userID);
@@ -242,7 +239,7 @@
    */
   protected function checkShop(int $shopID): bool
   {
      $cache = Cache::for('checkShop',DAY_IN_SECONDS)->connect('taxonomy');
      $cache = Cache::for('checkShop', 'term',DAY_IN_SECONDS);
      return $cache->remember($shopID, function() use ($shopID) {
         return (bool)term_exists($shopID, BASE . 'shop');
@@ -265,7 +262,7 @@
      }
      $taxonomy = jvbCheckBase($taxonomy);
      $cache = Cache::for('checkTerm', DAY_IN_SECONDS)->connect('taxonomy');
      $cache = Cache::for('checkTerm', 'term', DAY_IN_SECONDS);
      return $cache->remember($termID, function() use ($termID, $taxonomy) {
         return (bool)term_exists($termID, $taxonomy);
@@ -277,13 +274,19 @@
    */
   public function isVerifiedUser(int $user_id): bool
   {
      $cache = Cache::for('verifiedUsers', DAY_IN_SECONDS)->connect('user');
      $cache = Cache::for('verifiedUsers', 'user',DAY_IN_SECONDS);
      return $cache->remember($user_id, function() use ($user_id) {
         return user_can($user_id, 'skip_moderation');
      });
   }
   /**
    * @deprecated
    * @param array $args
    * @param array $data
    * @return array
    */
   protected function applyTaxonomyFilters(array $args, array $data):array
   {
      // Handle JSON-encoded taxonomy data
@@ -322,7 +325,7 @@
      // Keep existing author filtering logic
      $authorQuery = [];
      foreach (jvbAuthorUsers() as $type) {
      foreach (Registrar::withFeature('can_create', 'user') as $type) {
         if (array_key_exists($type, $data)) {
            $artist_ids = array_map(
               'absint',
@@ -352,7 +355,7 @@
      //Handle random
        if (array_key_exists('orderby', $data) && $data['orderby'] === 'random') {
            $current_seed = jvbGetRandomSeed();
            $current_seed = floor(time() / 1800);
            $args['orderby'] = 'RAND(' . $current_seed . ')';
            unset($args['order']);
            return $args;
@@ -417,19 +420,19 @@
      $content = jvbNoBase($post_type);
      // Get config for this content type
      $config = Features::getConfig($content);
      $config = Registrar::getInstance($content);
      if (!$config) {
         return null;
      }
      // Check if this orderby is a custom order
      $customOrders = $config['custom_order'] ?? [];
      $customOrders = $config->custom_order ?? [];
      if (empty($customOrders) || !isset($customOrders[$orderby])) {
         return null;
      }
      // Get field definition
      $fields = $config['fields'] ?? [];
      $fields = $config->getFields()??[];
      if (!isset($fields[$orderby])) {
         return null;
      }
@@ -478,12 +481,8 @@
   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;
      $areTimeline = array_map(function($type) { return BASE.$type; },Registrar::withFeature('is_timeline', 'post'));
      return !empty(array_intersect($post_types, $areTimeline));
   }
    protected function applyDateFilters(array $args, array $data):array
@@ -565,15 +564,13 @@
   }
   // ========== HTTP CACHING METHODS ==========
   /**
    * Check HTTP caching headers (ETag and If-Modified-Since)
    * Returns 304 Not Modified if content hasn't changed
    *
    * @param WP_REST_Request $request The REST request
    * @param string|array $content_types Content type(s) to check timestamps for
    * @param array $additional_params Additional params for ETag uniqueness (e.g., user_id, filters)
    * @return WP_REST_Response|null Returns 304 response if not modified, null to continue processing
    * @param WP_REST_Request $request
    * @param int|string|array $key Content type(s) to check timestamps for
    * @param string|array $group Additional params for ETag uniqueness (e.g., user_id, filters)
    * @return WP_REST_Response|false Returns 304 response if not modified, null to continue processing
    */
   protected function checkHeaders(
      WP_REST_Request $request,
@@ -590,12 +587,9 @@
         $key = $cache->generateKey($key);
      }
      // Prefer tag freshness if available
      $tags = $cache->getTags();
      $lastModified = $tags
         ? $cache->getLastModifiedForTags($tags)
         : $cache::lastModified($group);
      $lastModified = $cache::lastModified($group);
      if (!$lastModified) {
         return false;
@@ -923,13 +917,13 @@
      // Use existing error handler
      try {
         JVB()->error()->log(
         Errors::getInstance()->log(
            'security_audit',
            $event,
            $context,
            'info'
         );
      } catch (\Exception $e) {
      } catch (Exception $e) {
         // Fallback to error_log if handler fails
         error_log("Security Audit: {$event} - " . json_encode($context));
      }
@@ -1051,7 +1045,7 @@
   protected function verifyTurnstile(string $token): bool
   {
      if (!Features::hasIntegration('cloudflare') || !JVB()->connect('cloudflare')->isSetUp()) {
      if (!Site::hasIntegration('cloudflare') || !Cloudflare::getInstance()->isSetUp()) {
         return true;
      }
@@ -1059,6 +1053,6 @@
         return false;
      }
      return JVB()->connect('cloudflare')->verifyTurnstile($token);
      return Cloudflare::getInstance()->verifyTurnstile($token);
   }
}