From 50c137179625c64852ca49458837422ab3f732db Mon Sep 17 00:00:00 2001 From: Timothy Mugo Date: Thu, 4 Jun 2026 21:40:00 +0300 Subject: [PATCH] feat (TCDICORE-559): implement custom posts api to support year filtering --- .../wp-react-custom-api.php | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/plugins/wp-react-custom-api/wp-react-custom-api.php b/plugins/wp-react-custom-api/wp-react-custom-api.php index 67116862..cc9ffc4f 100644 --- a/plugins/wp-react-custom-api/wp-react-custom-api.php +++ b/plugins/wp-react-custom-api/wp-react-custom-api.php @@ -71,6 +71,182 @@ function get_year_range_for_posts_callback() { return $years; } +function get_custom_posts_with_years_callback($request) { + $post_type = $request->get_param('post_type'); + if (empty($post_type)) { + $post_type = 'post'; + } + + // Backwards compatibility with frontend values that may pass WP collection names. + if ($post_type === 'posts') { + $post_type = 'post'; + } + + $post_type_object = get_post_type_object($post_type); + if (empty($post_type_object) || empty($post_type_object->show_in_rest)) { + return new WP_Error( + 'invalid_post_type', + __('Invalid or non-REST post type.', 'wp-react-custom-api'), + array('status' => 400) + ); + } + + $per_page = (int) $request->get_param('per_page'); + if ($per_page <= 0) { + $per_page = 10; + } + if ($per_page > 100) { + $per_page = 100; + } + + $page = (int) $request->get_param('page'); + if ($page <= 0) { + $page = 1; + } + + $order = strtoupper((string) $request->get_param('order')); + $order = in_array($order, array('ASC', 'DESC'), true) ? $order : 'DESC'; + + $orderby = (string) $request->get_param('orderby'); + if (empty($orderby)) { + $orderby = 'date'; + } + + $query_args = array( + 'post_type' => $post_type, + 'post_status' => 'publish', + 'posts_per_page' => $per_page, + 'paged' => $page, + 'orderby' => $orderby, + 'order' => $order, + 'no_found_rows' => false, + 'ignore_sticky_posts' => true, + ); + + $lang = $request->get_param('lang'); + if (!empty($lang)) { + $query_args['lang'] = sanitize_text_field($lang); + } + + $years = $request->get_param('years'); + $years_list = array(); + if (!empty($years)) { + $parsed_years = array_map('trim', explode(',', (string) $years)); + foreach ($parsed_years as $year) { + $year_number = (int) $year; + if ($year_number > 0) { + $years_list[] = $year_number; + } + } + $years_list = array_values(array_unique($years_list)); + } + + $after = $request->get_param('after'); + $before = $request->get_param('before'); + $date_query = array(); + + if (!empty($years_list)) { + $year_date_query = array('relation' => 'OR'); + foreach ($years_list as $year) { + $year_date_query[] = array( + 'year' => $year, + 'inclusive' => true, + ); + } + $date_query[] = $year_date_query; + } + + if (!empty($after) || !empty($before)) { + $range_query = array('inclusive' => true); + if (!empty($after)) { + $range_query['after'] = sanitize_text_field($after); + } + if (!empty($before)) { + $range_query['before'] = sanitize_text_field($before); + } + $date_query[] = $range_query; + } + + if (!empty($date_query)) { + if (count($date_query) > 1) { + $date_query['relation'] = 'AND'; + } + $query_args['date_query'] = $date_query; + } + + $reserved_params = array( + 'post_type', + 'per_page', + 'page', + 'lang', + 'after', + 'before', + 'orderby', + 'order', + 'years', + 'context', + '_fields', + ); + + $tax_query = array('relation' => 'AND'); + $all_params = $request->get_params(); + foreach ($all_params as $key => $value) { + if (in_array($key, $reserved_params, true)) { + continue; + } + + $taxonomy = get_taxonomy($key); + if (empty($taxonomy)) { + continue; + } + + $term_ids = array(); + $parsed_values = array_map('trim', explode(',', (string) $value)); + foreach ($parsed_values as $term_id) { + $term_id_number = (int) $term_id; + if ($term_id_number > 0) { + $term_ids[] = $term_id_number; + } + } + + $term_ids = array_values(array_unique($term_ids)); + if (empty($term_ids)) { + continue; + } + + $tax_query[] = array( + 'taxonomy' => $key, + 'field' => 'term_id', + 'terms' => $term_ids, + 'operator' => 'IN', + ); + } + + if (count($tax_query) > 1) { + $query_args['tax_query'] = $tax_query; + } + + $query = new WP_Query($query_args); + $controller = new WP_REST_Posts_Controller($post_type); + $item_request = new WP_REST_Request('GET'); + $item_request->set_param('context', 'view'); + + $items = array(); + foreach ($query->posts as $post) { + $prepared = $controller->prepare_item_for_response($post, $item_request); + $items[] = $controller->prepare_response_for_collection($prepared); + } + + $response = new WP_REST_Response($items); + $total_items = (int) $query->found_posts; + $total_pages = (int) $query->max_num_pages; + + $response->header('X-WP-Total', (string) $total_items); + $response->header('X-WP-TotalPages', (string) max(1, $total_pages)); + + return $response; +} + add_action('rest_api_init', function () { register_rest_route('util-api/v1', '/test', array( 'methods' => 'GET', @@ -84,4 +260,8 @@ function get_year_range_for_posts_callback() { 'methods' => 'GET', 'callback' => 'get_year_range_for_posts_callback', )); + register_rest_route('dg/v1', '/posts', array( + 'methods' => 'GET', + 'callback' => 'get_custom_posts_with_years_callback', + )); }); \ No newline at end of file