From e9967fa22781d922ba4eb8fb44fe72d200ac4b14 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 10 Nov 2025 21:04:10 +0000
Subject: [PATCH] =IconsManager.php update
---
inc/rest/routes/ContentRoutes.php | 255 ++++++++++++++++++++++++++++++---------------------
1 files changed, 150 insertions(+), 105 deletions(-)
diff --git a/inc/rest/routes/ContentRoutes.php b/inc/rest/routes/ContentRoutes.php
index ff056a9..dfa9cb6 100644
--- a/inc/rest/routes/ContentRoutes.php
+++ b/inc/rest/routes/ContentRoutes.php
@@ -25,14 +25,18 @@
protected string $post_type = '';
protected string $user_id = '';
+ //For Timeline-specific posts
+ protected array $timelineSharedFields = [];
+ protected array $timelineUniqueFields = [];
+
//TODO: Ensure we are handling the bulk operations for all processes
- //TODO: be sure to clear cache ($this->>cache->invalidateGroup($this->>cache_name)) on content update/create
//TODO: Also invalidate feed caches on updates!!
public function __construct()
{
$this->cache_name = 'user_content_'.get_current_user_id();
parent::__construct();
+
$this->action = 'dash-';
$this->operation_type = 'content_update';
add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
@@ -75,6 +79,32 @@
]);
}
+ protected function initTimelineFields(string $content):void
+ {
+ $content = jvbNoBase($content);
+ if (!Features::forContent($content)->has('is_timeline')){
+ return;
+ }
+ $config = Features::getConfig($content);
+ $this->fields = $config['fields'];
+
+ $this->timelineSharedFields = array_keys(array_filter($this->fields, function ($field) {
+ if (!array_key_exists('for_all', $field) || $field['for_all'] === false){
+ return true;
+ }
+ return false;
+ }));
+ array_unshift($this->timelineSharedFields, 'post_thumbnail');
+ array_unshift($this->timelineSharedFields, 'post_title');
+
+ $this->timelineUniqueFields = array_keys(array_filter($this->fields, function ($field) {
+ if (array_key_exists('for_all', $field) && $field['for_all'] === true) {
+ return true;
+ }
+ return false;
+ }));
+ }
+
/**
* Handle content update/creation
* @param WP_REST_Request $request
@@ -187,9 +217,6 @@
}
$post_type = str_replace('-', '_',jvbCheckBase($params['content']));
- $config = Features::getConfig($params['content']);
-
-
// Build query args
$args = [
@@ -396,14 +423,12 @@
}
- CacheManager::invalidateGroup($post_data['content']);
+ CacheManager::for($post_data['content'])->clear();
if (jvbSiteUsesFeedBlock()) {
- CacheManager::invalidateGroup($post_data['feed']);
+ CacheManager::for('feed')->clear();
}
}
-
- CacheManager::invalidateGroup('user_content');
if (jvbSiteHasNotifications()) {
$this->notifications = JVB()->notification();
$this->notifications->addNotification(
@@ -433,83 +458,109 @@
return ['success' => false, 'message' => 'No permission'];
}
- $rows = $post_data['fields'] ?? [];
- if (empty($rows)) {
- return ['success' => false, 'message' => 'No data'];
- }
+ $this->fields = jvbGetFields($post_data['content']);
+ $this->initTimelineFields($post_data['content']);
+ error_log('Received Data: '.print_r($post_data, true));
- $fields = jvbGetFields($post_data['content']);
-
- // First row = parent post
- $parent_row = array_shift($rows);
- if (($parent_row['id'] ?? null) != $parent_id) {
- return ['success' => false, 'message' => 'Parent ID mismatch'];
- }
-
- $allowedFields = array_filter($parent_row, function($key) use ($fields) {
- return array_key_exists($key, $fields);
+ // First, process the main fields that will apply to all posts
+ $sharedData = array_filter($post_data, function ($key) {
+ return in_array($key, $this->timelineSharedFields);
}, ARRAY_FILTER_USE_KEY);
- $parentMeta = new MetaManager($parent_id, 'post');
- $parentMeta->setAll($allowedFields);
+ //Next, process any individual posts, including any menu order changes
+ if (array_key_exists('timeline', $post_data) && is_array($post_data['timeline'])) {
+ $sharedTaxonomies = $sharedData;
+ unset($sharedTaxonomies['post_title']);
- // Get existing children to track deletions
- $existing_children = get_children([
- 'post_parent' => $parent_id,
- 'post_type' => jvbCheckBase($post_data['content']),
- 'fields' => 'ids'
- ]);
-
- $processed_ids = [];
-
- // Process remaining rows as children
- foreach ($rows as $index => $row_data) {
- $row_id = $row_data['id'] ?? null;
-
- // New child post
- if (!$row_id || str_starts_with($row_id, 'new')) {
- $child_id = wp_insert_post([
- 'post_type' => jvbCheckBase($post_data['content']),
- 'post_parent' => $parent_id,
- 'post_author' => $this->user_id,
- 'post_status' => $post_data['status'] ?? 'draft',
- 'menu_order' => $index
- ]);
+ //Ensure the parent post exists and is still first in the array
+ $index = array_search((string)$parent_id, array_column($post_data['timeline'], 'id'));
+ error_log('Found index: '.print_r($index, true));
+ if ($index === false) {
+ return [
+ 'success' => false,
+ 'message' => 'Missing parent id. This should not have happened'
+ ];
+ } elseif ($index !== 0) {
+ // Move that element to the start of the array
+ $item = $post_data['timeline'][$index];
+ unset($post_data['timeline'][$index]);
+ array_unshift($post_data['timeline'], $item);
}
- // Existing child post
- else {
- $child_id = (int) $row_id;
+ $errors = [];
+ $success = [];
+ // Get existing children to track deletions
+ $existing_children = get_children([
+ 'post_parent' => $parent_id,
+ 'post_type' => jvbCheckBase($post_data['content']),
+ 'fields' => 'ids'
+ ]);
+ //Iterate through the timeline posts
+ foreach($post_data['timeline'] as $order => $timeline) {
+ $allowedFields = array_filter($timeline, function($key) {
+ return in_array($key, $this->timelineUniqueFields);
+ }, ARRAY_FILTER_USE_KEY);
- // Verify ownership via parent
- if (!in_array($child_id, $existing_children)) {
- continue; // Skip if not actually a child of this parent
+ $allowedFields['post_title'] = $allowedFields['post_title'] ?? $sharedData['post_title'].' - Treatment #'.$order;
+ $allowedFields = array_merge($allowedFields, $sharedTaxonomies);
+ if (!array_key_exists('id', $timeline) || !is_numeric($timeline['id'])) {
+ $newChild = wp_insert_post([
+ 'post_author' => $this->user_id,
+ 'post_type' => jvbCheckBase($post_data['content']),
+ 'post_title' => $allowedFields['post_title'],
+ 'post_parent' => $parent_id,
+ 'menu_order' => $order
+ ]);
+ if (!$newChild || is_wp_error($newChild)) {
+ $errors[] = [
+ 'message' => 'Could not create child post',
+ 'data' => $timeline
+ ];
+ continue;
+ }
+ $timeline['id'] = $newChild;
}
- // Update menu_order (position may have changed)
- wp_update_post([
- 'ID' => $child_id,
- 'menu_order' => $index
- ]);
+ if (in_array((int)$timeline['id'], $existing_children)) {
+ unset($existing_children[array_search((int)$timeline['id'], $existing_children)]);
+ }
+
+ //Determine which fields to update
+ $meta = new MetaManager($timeline['id'], 'post');
+ $oldValues = $meta->getAll(array_keys($allowedFields));
+ $updateValues = array_filter($allowedFields, function($value, $key) use ($oldValues) {
+ return (!array_key_exists($key, $oldValues) || $value !== $oldValues[$key]);
+ }, ARRAY_FILTER_USE_BOTH);
+ $meta->setAll($updateValues);
+ //Update Menu Order, if applicable
+ if ((int) $timeline['id'] !== $parent_id) {
+ $post = get_post((int) $timeline['id']);
+ if ($post && $post->menu_order !== $order) {
+ $updated = wp_update_post([
+ 'ID' => $post->ID,
+ 'menu_order' => $order,
+ ]);
+ if (!$updated || is_wp_error($updated)) {
+ $errors[] = [
+ 'message' => 'Could not update timeline order for post',
+ 'data' => $timeline
+ ];
+ }
+ }
+ }
+ $success[] = $timeline['id'];
}
-
- // Update child meta
- $allowedChildFields = array_filter($row_data, function($key) use ($fields) {
- return array_key_exists($key, $fields) && $key !== 'id' && $key !== 'draggable';
- }, ARRAY_FILTER_USE_KEY);
-
- $childMeta = new MetaManager($child_id, 'post');
- $childMeta->setAll($allowedChildFields);
-
- $processed_ids[] = $child_id;
+ }
+ //Delete any remaining children that no longer exist
+ if (!empty($existing_children)) {
+ foreach ($existing_children as $ID) {
+ wp_delete_post($ID);
+ }
}
- // Delete removed children
- $deleted_ids = array_diff($existing_children, $processed_ids);
- foreach ($deleted_ids as $delete_id) {
- wp_delete_post($delete_id, true);
- }
-
- return ['success' => true, 'processed' => $processed_ids];
+ return ['success' => true, 'data' => [
+ 'success' => $success,
+ 'errors' => $errors
+ ]];
}
/**
@@ -590,9 +641,10 @@
*
* @return array
*/
- protected function prepareItem(WP_Post $post, $skip = false):array
+ protected function prepareItem(WP_Post $post, bool $skip = false, bool $fields = true):array
{
if (!$skip && Features::forContent($post->post_type)->has('is_timeline')) {
+ $this->initTimelineFields($post->post_type);
return $this->formatTimeline($post);
}
$this->meta = new MetaManager($post->ID, 'post');
@@ -605,7 +657,7 @@
'alt' => get_post_meta(get_post_thumbnail_id(), '_wp_attachment_image_alt', true),
'icon' => $this->post_type,
'taxonomies'=> [],
- 'fields' => $this->meta->getAll(),
+ 'fields' => ($fields) ? $this->meta->getAll() : [],
'images' => [],
];
@@ -633,12 +685,13 @@
return $data;
}
- protected function extractImages():array
+ protected function extractImages(array $fields = []):array
{
//Extract images
$images = [];
$get = [];
- foreach ($this->fields as $field => $config) {
+ $fields = (empty($fields)) ? $this->fields : $fields;
+ foreach ($fields as $field => $config) {
if ($config['type'] === 'gallery' || $config['type'] === 'image' || $field === 'post_thumbnail') {
$get[] = $field;
}
@@ -660,36 +713,29 @@
protected function formatTimeline(WP_Post $post):array
{
- $data = $this->prepareItem($post, true);
- $firstRow = $data['fields'];
- $firstRow['id'] = $post->ID;
- $firstRow['draggable'] = false;
- $fields = [$firstRow];
+ $item = $this->prepareItem($post, true, false);
+ //Step 1: Get the fields that apply to all posts
+ $mainMeta = new MetaManager($post->ID, 'post');
+ $item['fields'] = $mainMeta->getAll($this->timelineSharedFields);
- $children = get_children(['post_parent' => $post->ID, 'orderby' => 'menu_order']);
- $allImages = [];
+ //Step 2: Get the fields for each individual posts
+ $children = get_children(['post_parent' => $post->ID, 'orderby' => 'menu_order', 'post_status' => ['publish', 'draft'], 'fields'=> 'ids']);
+ array_unshift($children, $post->ID);
+ $subFields = [];
+ $images = [];
foreach ($children as $child) {
- $this->meta = new MetaManager($child->ID, 'post');
- $row = $this->meta->getAll(); // Store in variable first
- $row['id'] = $child->ID; // Add ID to the row
- $row['draggable'] = true; // Mark as draggable
- $fields[] = $row; // Then append to fields
+ $meta = new MetaManager($child, 'post');
+ $f = $meta->getAll($this->timelineUniqueFields);
+ $f = ['id' => $child] + $f;
+ $subFields[$f['post_thumbnail']] = $f;
- $images = $this->extractImages();
- if (!empty($images)) {
- $allImages = $allImages + $images;
- }
+ $images[$f['post_thumbnail']] = jvbImageData((int) $f['post_thumbnail']);
}
+ $item['fields']['timeline'] = $subFields;
+ $item['images'] = $item['images'] + $images;
- if (!empty($allImages)) {
- if (!array_key_exists('images', $data)) {
- $data['images'] = [];
- }
- $data['images'] = $data['images'] + $allImages;
- }
- $data['fields']['timeline'] = $fields;
- return $data;
+ return $item;
}
/**
@@ -839,9 +885,8 @@
}
//Clear cache
- CacheManager::invalidateGroup($data['content']);
- CacheManager::invalidateGroup('feed');
- CacheManager::invalidateGroup('user_content');
+ CacheManager::for($data['content'])->clear();
+ CacheManager::for('feed')->clear();
}
return [
--
Gitblit v1.10.0