Jake Vanderwerf
2026-09-18 a6413da67a4579866f0fd0323ddb23a7b6b9654a
inc/managers/queue/executors/ContentExecutor.php
@@ -1,10 +1,15 @@
<?php
namespace JVBase\managers\queue\executors;
use JVBase\managers\queue\{Executor, Operation, Progress, Result, Storage};
use DateTime;
use JVBase\managers\queue\{Executor, Operation, Progress, Result};
use JVBase\inc\managers\ErrorHelper;
use JVBase\managers\Errors;
use JVBase\managers\Roles;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
use Exception;
use WP_Post;
if (!defined('ABSPATH')) {
   exit;
@@ -16,14 +21,13 @@
 */
final class ContentExecutor implements Executor
{
   use ErrorHelper;
   private const HANDLED_TYPES = [
      'content_update',
//    'batch_creation',
   ];
   private int $userId;
   private string $postType;
   private array $fields = [];
   public function execute(Operation $operation, Progress $progress): Result
   {
@@ -43,15 +47,11 @@
         };
      } catch (Exception $e) {
         JVB()->error()->log(
            '[ContentExecutor]:execute',
            $e->getMessage(),
            [
               'operation_id'   => $operation->id,
               'operation_type' => $operation->type,
               'user_id'        => $operation->userId,
            ]
         );
         $this->logError($e->getMessage(), 'execute', [
            'operation_id'   => $operation->id,
            'operation_type' => $operation->type,
            'user_id'        => $operation->userId,
         ]);
         return new Result(
            outcome: 'failed',
@@ -67,10 +67,10 @@
   private function processContentUpdate(Operation $operation, array $data, Progress $progress): Result
   {
      $posts = $data['posts'] ?? [];
      error_log('Processing Content Update: '.print_r($posts, true));
      if (empty($posts)) {
         return new Result(
            outcome: 'failed',
            outcome: 'success',
            result: ['message' => 'No posts to update']
         );
      }
@@ -125,7 +125,7 @@
      // Send notification
//    if (jvbSiteHasNotifications()) {
//       JVB()->notification()->addNotification(
//       NotificationManager::getInstance()->addNotification(
//          $this->userId,
//          'content_update_complete',
//          null,
@@ -134,8 +134,8 @@
//    }
      $outcome = 'success';
      if (!empty($errors)) {
         $outcome = count($errors) === count($posts) ? 'failed' : 'partial';
      if (!empty($results['errors'])) {
         $outcome = count($results['success']) === count($posts) ? 'failed' : 'partial';
      }
      return new Result(
@@ -242,23 +242,17 @@
         }
      }
   }
   protected function maybeReorderTimeline(int $parentID):void
   protected function getTimelinePosts(int $parentID):array
   {
//    clean_post_cache($parentID);
      $parent = get_post($parentID);
      if (!$parent) {
         return;
         return [];
      }
      $children = get_children([
         'post_parent' => $parentID,
         'posts_per_page' => -1,
         'post_status' => ['publish', 'draft'],
      ]);
      $children = jvbTimelinePoints($parentID, $parent->post_type, ['publish', 'draft']);
      if (count($children) === 0) {
         return;
         return [];
      }
      $allPosts = array_merge([$parent], $children);
@@ -268,6 +262,22 @@
         return strtotime($a->post_date) <=> strtotime($b->post_date);
      });
      return $allPosts;
   }
   protected function maybeReorderTimeline(int $parentID):void
   {
//    clean_post_cache($parentID);
      $parent = get_post($parentID);
      if (!$parent) {
         return;
      }
      $allPosts = $this->getTimelinePosts($parentID);
      if (empty($allPosts)) {
         return;
      }
      // Check if order changed
      $needsReorder = false;
@@ -333,6 +343,10 @@
               }
            }
         }
         $isUpdate = $meta->get('is_update');
         if (!(bool) $isUpdate) {
            $meta->set('number', $index);
         }
         if ($lastKey === $index) {
            $latestTimestamp = strtotime($post->post_date);
@@ -346,7 +360,10 @@
      }
   }
   private function calculateTimeline(\WP_POST $previous, \WP_POST $current): ?string
   /**
    * @throws \DateMalformedStringException
    */
   private function calculateTimeline(WP_POST $previous, WP_POST $current): ?string
   {
      $previousDate = strtotime($previous->post_date);
      $currentDate = strtotime($current->post_date);
@@ -364,8 +381,8 @@
         return $weeks === 1 ? '1 Week' : $weeks . ' Weeks';
      }
      $previousDateTime = new \DateTime($previous->post_date);
      $currentDateTime = new \DateTime($current->post_date);
      $previousDateTime = new DateTime($previous->post_date);
      $currentDateTime = new DateTime($current->post_date);
      $interval = $previousDateTime->diff($currentDateTime);
      $months = ($interval->y * 12) + $interval->m;
@@ -377,7 +394,7 @@
      return ($months === 1) ? '1 Month' : $months . ' Months';
   }
   private function swapTimelineParent(\WP_Post $oldParent, \WP_Post $newParent, array $allPosts): void
   private function swapTimelineParent(WP_Post $oldParent, WP_Post $newParent, array $allPosts): void
   {
      // Swap titles and content
      $originalTitle = $oldParent->post_title;
@@ -401,7 +418,7 @@
      ]);
      // Clear timeline taxonomy from new parent
      wp_set_object_terms($newParent->ID, [], BASE . 'timeline', false);
      wp_set_object_terms($newParent->ID, [], BASE . 'timeline');
      // Update all other posts to new parent
      foreach ($allPosts as $index => $post) {
@@ -446,11 +463,7 @@
         $meta = Meta::forPost($parentID);
         $values = $meta->getAll($shared);
         $children = get_children([
            'post_parent' => $parentID,
            'posts_per_page' => -1,
            'fields' => 'ids',
         ]);
         $children = jvbTimelinePoints($parentID, get_post_type($parentID), ['any']);
         if (empty($children)) {
            continue;
@@ -469,11 +482,8 @@
      });
      foreach ($updates as $parentID => $status) {
         $children = get_children([
            'post_parent'  => $parentID,
            'posts_per_page' => -1,
            'fields' => 'ids'
         ]);
         $children = jvbTimelinePoints($parentID, get_post_type($parentID), ['any']);
         if (!empty($children)) {
            foreach($children as $child) {
               if ($status === 'trash') {
@@ -503,6 +513,7 @@
            'post_title'  => $data['post_title'] ?? apply_filters('jvbDefaultTitle', '', $registrar->getSlug()),
            'post_status' => $data['status'] ?? 'draft',
         ]);
         error_log('Created new post: '.print_r($newId, true));
         if (!$newId || is_wp_error($newId)) {
            $results['errors'][$ID] = 'Could not create post';
@@ -540,6 +551,28 @@
            return !array_key_exists('for_all', $field) || !$field['for_all'];
         }));
         if (array_key_exists('timeline_gallery', $data)) {
            //This should only happen if we delete an image from the gallery
            $changes = explode(',', $data['timeline_gallery']);
            $timelinePosts = $this->getTimelinePosts($parentId);
            if (!empty($timelinePosts)) {
               $posts = array_map(function($item) { return $item->ID; }, $timelinePosts);
               $changed = false;
               foreach ($posts as $tID) {
                  if (!in_array($tID, $changes)) {
                     $changed = true;
                     wp_delete_post($tID, true);
                  }
               }
               if ($changed) {
                  $results['timelineParents'][] = $parentId;
               }
            }
         }
         if (array_key_exists('post_date', $data) && !in_array($parentId, $results['timelineParents'])) {
            $results['timelineParents'][] = $parentId;
         }
@@ -566,7 +599,7 @@
   {
      error_log('Handling term '.$ID.' with data: '.print_r($data, true));
      //Existing term update
      if ($registrar->hasFeature('is_ownable') && (!JVB()->roles()->isOwner($this->userId, $ID) && !JVB()->roles()->isManager($this->userId, $ID))) {
      if ($registrar->hasFeature('is_ownable') && (!Roles::getInstance()()->isOwner($this->userId, $ID) && !Roles::getInstance()()->isManager($this->userId, $ID))) {
         error_log('Term is ownable. User does not own this term.');
         $progress->failItem($ID, 'No permission to modify this term');
         $results['errors'][$ID] = 'No permission';