$args['post_type'] ?? 'post', 'post_status' => $args['status'] ?? 'publish', 'posts_per_page' => min((int) ($args['per_page'] ?? 20), 100), 'paged' => (int) ($args['page'] ?? 1), 'orderby' => $args['orderby'] ?? 'date', 'order' => $args['order'] ?? 'DESC', ]; if (!empty($args['search'])) $queryArgs['s'] = $args['search']; if (!empty($args['author'])) $queryArgs['author'] = (int) $args['author']; if (!empty($args['category_id'])) $queryArgs['cat'] = (int) $args['category_id']; if (!empty($args['tag_id'])) $queryArgs['tag_id'] = (int) $args['tag_id']; if (!empty($args['after'])) $queryArgs['date_query'][] = ['after' => $args['after'], 'inclusive' => true]; if (!empty($args['before'])) $queryArgs['date_query'][] = ['before' => $args['before'], 'inclusive' => true]; $query = new \WP_Query($queryArgs); $posts = []; foreach ($query->posts as $post) { $posts[] = ['id' => $post->ID, 'title' => $post->post_title, 'status' => $post->post_status, 'date' => $post->post_date, 'author' => (int) $post->post_author, 'link' => get_permalink($post->ID), 'slug' => $post->post_name]; } return ['posts' => $posts, 'total' => $query->found_posts, 'pages' => $query->max_num_pages]; } public static function getPost(array $args): array { $post = get_post((int) $args['post_id']); if (!$post) throw new \RuntimeException("Post not found: {$args['post_id']}"); $categories = wp_get_post_categories($post->ID, ['fields' => 'all']); $tags = wp_get_post_tags($post->ID); $meta = get_post_meta($post->ID); $thumbnail = get_the_post_thumbnail_url($post->ID, 'full'); return [ 'id' => $post->ID, 'title' => $post->post_title, 'content' => $post->post_content, 'excerpt' => $post->post_excerpt, 'status' => $post->post_status, 'date' => $post->post_date, 'modified' => $post->post_modified, 'author' => (int) $post->post_author, 'slug' => $post->post_name, 'link' => get_permalink($post->ID), 'featured_image' => $thumbnail ?: null, 'categories' => array_map(fn($c) => ['id' => $c->term_id, 'name' => $c->name, 'slug' => $c->slug], $categories), 'tags' => array_map(fn($t) => ['id' => $t->term_id, 'name' => $t->name, 'slug' => $t->slug], $tags), 'meta' => array_map(fn($v) => count($v) === 1 ? $v[0] : $v, $meta), ]; } public static function createPost(array $args): array { $postData = [ 'post_title' => $args['title'], 'post_content' => $args['content'] ?? '', 'post_excerpt' => $args['excerpt'] ?? '', 'post_status' => $args['status'] ?? 'draft', 'post_author' => $args['author'] ?? get_current_user_id() ?: 1, 'post_name' => $args['slug'] ?? '', 'post_type' => $args['post_type'] ?? 'post', ]; $postId = wp_insert_post($postData, true); if (is_wp_error($postId)) throw new \RuntimeException($postId->get_error_message()); if (!empty($args['categories'])) wp_set_post_categories($postId, array_map('intval', $args['categories'])); if (!empty($args['tags'])) wp_set_post_tags($postId, array_map('intval', $args['tags'])); if (!empty($args['meta'])) foreach ($args['meta'] as $k => $v) update_post_meta($postId, $k, $v); if (!empty($args['featured_media'])) set_post_thumbnail($postId, (int) $args['featured_media']); // Return both 'post_id' and 'id' for compatibility return ['post_id' => $postId, 'id' => $postId, 'link' => get_permalink($postId), 'status' => $args['status'] ?? 'draft']; } public static function updatePost(array $args): array { $postId = (int) $args['post_id']; if (!get_post($postId)) throw new \RuntimeException("Post not found: {$postId}"); $postData = ['ID' => $postId]; if (isset($args['title'])) $postData['post_title'] = $args['title']; if (isset($args['content'])) $postData['post_content'] = $args['content']; if (isset($args['excerpt'])) $postData['post_excerpt'] = $args['excerpt']; if (isset($args['status'])) $postData['post_status'] = $args['status']; if (isset($args['slug'])) $postData['post_name'] = $args['slug']; $result = wp_update_post($postData, true); if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message()); if (!empty($args['categories'])) wp_set_post_categories($postId, array_map('intval', $args['categories'])); if (!empty($args['tags'])) wp_set_post_tags($postId, array_map('intval', $args['tags'])); if (!empty($args['meta'])) foreach ($args['meta'] as $k => $v) update_post_meta($postId, $k, $v); if (!empty($args['featured_media'])) set_post_thumbnail($postId, (int) $args['featured_media']); return ['post_id' => $postId, 'id' => $postId, 'updated' => true, 'link' => get_permalink($postId)]; } public static function deletePost(array $args): array { $postId = (int) $args['post_id']; $force = (bool) ($args['force'] ?? false); $result = wp_delete_post($postId, $force); if (!$result) throw new \RuntimeException("Failed to delete post: {$postId}"); return ['post_id' => $postId, 'id' => $postId, 'deleted' => true, 'permanent' => $force]; } public static function getPostMeta(array $args): array { $postId = (int) $args['post_id']; $key = $args['meta_key'] ?? ''; if ($key) return ['post_id' => $postId, 'meta_key' => $key, 'meta_value' => get_post_meta($postId, $key, true)]; $all = get_post_meta($postId); $flat = []; foreach ($all as $k => $v) $flat[$k] = is_array($v) && count($v) === 1 ? $v[0] : $v; return ['post_id' => $postId, 'meta' => $flat]; } public static function updatePostMeta(array $args): array { $postId = (int) $args['post_id']; update_post_meta($postId, sanitize_key($args['meta_key']), $args['meta_value']); return ['post_id' => $postId, 'meta_key' => $args['meta_key'], 'updated' => true]; } public static function deletePostMeta(array $args): array { $postId = (int) $args['post_id']; $result = delete_post_meta($postId, sanitize_key($args['meta_key'])); return ['post_id' => $postId, 'meta_key' => $args['meta_key'], 'deleted' => (bool) $result]; } public static function setFeaturedImage(array $args): array { $postId = (int) $args['post_id']; $mediaId = (int) $args['media_id']; // Verify the post exists if (!get_post($postId)) throw new \RuntimeException("Post not found: {$postId}"); // Verify the attachment exists (create a placeholder if it doesn't but is a valid integer) $attachment = get_post($mediaId); if (!$attachment || $attachment->post_type !== 'attachment') { throw new \RuntimeException("Attachment not found: {$mediaId}. Upload media first, then set featured image."); } $result = set_post_thumbnail($postId, $mediaId); if (!$result) throw new \RuntimeException("Failed to set featured image on post {$postId}"); return ['post_id' => $postId, 'media_id' => $mediaId, 'set' => true]; } public static function countPosts(array $args): array { $type = $args['post_type'] ?? 'post'; $counts = wp_count_posts($type); return ['post_type' => $type, 'counts' => (array) $counts]; } public static function getPostRevisions(array $args): array { $postId = (int) $args['post_id']; $post = get_post($postId); if (!$post) throw new \RuntimeException("Post not found: {$postId}"); $revisions = wp_get_post_revisions($postId); $result = []; foreach ($revisions as $rev) { $result[] = [ 'id' => $rev->ID, 'title' => $rev->post_title, 'date' => $rev->post_date, 'author' => (int) $rev->post_author, 'modified' => $rev->post_modified, ]; } return ['post_id' => $postId, 'revisions' => $result, 'total' => count($result)]; } public static function getPostTypes(array $args): array { $args_query = ['public' => true]; if (!empty($args['include_builtin']) && !$args['include_builtin']) { $args_query['_builtin'] = false; } $types = get_post_types($args_query, 'objects'); $result = []; foreach ($types as $type) { $result[] = [ 'name' => $type->name, 'label' => $type->label, 'singular' => $type->labels->singular_name ?? $type->label, 'has_archive' => (bool) $type->has_archive, 'public' => (bool) $type->public, 'hierarchical'=> (bool) $type->hierarchical, ]; } return ['post_types' => $result, 'total' => count($result)]; } public static function addPostTerms(array $args): array { $postId = (int) $args['post_id']; $taxonomy = $args['taxonomy']; $terms = $args['terms'] ?? []; $append = (bool) ($args['append'] ?? true); if (!get_post($postId)) throw new \RuntimeException("Post not found: {$postId}"); // Accept both term IDs and slugs $termIds = array_map(fn($t) => is_numeric($t) ? (int)$t : $t, $terms); $result = wp_set_object_terms($postId, $termIds, $taxonomy, $append); if (is_wp_error($result)) throw new \RuntimeException($result->get_error_message()); return ['post_id' => $postId, 'taxonomy' => $taxonomy, 'terms' => $result, 'appended' => $append]; } public static function restoreRevision(array $args): array { $revisionId = (int) $args['revision_id']; $revision = get_post($revisionId); if (!$revision) throw new \RuntimeException("Revision not found: {$revisionId}"); $result = wp_restore_post_revision($revisionId); if (!$result) throw new \RuntimeException("Failed to restore revision: {$revisionId}"); return ['revision_id' => $revisionId, 'post_id' => $revision->post_parent, 'restored' => true]; } }