/**
* Zeevou Reviews Carousel REST Endpoint
* Endpoint: /wp-json/zv/v1/reviews-carousel?per_page=30
*/
add_action(‘rest_api_init’, function () {
register_rest_route(‘zv/v1’, ‘/reviews-carousel’, array(
‘methods’ => WP_REST_Server::READABLE,
‘permission_callback’ => ‘__return_true’,
‘args’ => array(
‘per_page’ => array(
‘default’ => 30,
‘sanitize_callback’ => function ($value) {
$value = (int) $value;
if ($value < 1) $value = 1;
if ($value > 30) $value = 30;
return $value;
},
),
),
‘callback’ => ‘zv_reviews_carousel_rest_callback’,
));
});
function zv_reviews_carousel_rest_callback(WP_REST_Request $request) {
$per_page = (int) $request->get_param(‘per_page’);
if ($per_page < 1) $per_page = 30;
if ($per_page > 30) $per_page = 30;
$query = new WP_Query(array(
‘post_type’ => ‘reviews’, // your Pods CPT slug
‘post_status’ => ‘publish’,
‘posts_per_page’ => $per_page,
‘orderby’ => ‘date’,
‘order’ => ‘DESC’,
‘ignore_sticky_posts’ => true,
‘no_found_rows’ => true,
));
$items = array();
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$post_id = get_the_ID();
// Pods fields (Meta storage) – exact field names from your screenshot
$full_review = get_post_meta($post_id, ‘full_review’, true);
$stars_number_raw = get_post_meta($post_id, ‘start-rating-number-of-stars-out-of-5’, true); // decimal like 4.7
$person_name = get_post_meta($post_id, ‘name_of_the_person’, true);
$review_link = get_post_meta($post_id, ‘review_link’, true);
$review_label = get_post_meta($post_id, ‘review_label’, true);
$role_company = get_post_meta($post_id, ‘role_and_company’, true);
// Fallbacks
if ($person_name === ” || $person_name === null) {
$person_name = get_the_title($post_id);
}
if ($review_label === ” || $review_label === null) {
$review_label = ‘Read on Capterra’;
}
// Stars: use ONLY the decimal numeric field
$stars_number = 5.0; // fallback
if ($stars_number_raw !== ” && $stars_number_raw !== null && is_numeric($stars_number_raw)) {
$stars_number = (float) $stars_number_raw;
}
$stars_number = max(0, min(5, round($stars_number, 2)));
// Featured image (avatar)
$thumb_id = get_post_thumbnail_id($post_id);
$avatar_url = $thumb_id ? wp_get_attachment_image_url($thumb_id, ‘medium’) : ”;
$avatar_url_2x = $thumb_id ? wp_get_attachment_image_url($thumb_id, ‘medium_large’) : ”;
$avatar_alt = $thumb_id ? get_post_meta($thumb_id, ‘_wp_attachment_image_alt’, true) : ”;
if (!$avatar_alt) {
$avatar_alt = $person_name ? $person_name : ‘Reviewer avatar’;
}
$items[] = array(
‘id’ => $post_id,
‘date’ => get_post_time(‘c’, true, $post_id),
‘title’ => get_the_title($post_id),
‘permalink’ => get_permalink($post_id),
‘full_review’ => wp_strip_all_tags((string) $full_review),
‘stars’ => $stars_number, // decimal rating only from start-rating-number-of-stars-out-of-5
‘name_of_the_person’ => wp_strip_all_tags((string) $person_name),
‘review_link’ => esc_url_raw((string) $review_link),
‘review_label’ => wp_strip_all_tags((string) $review_label),
‘role_and_company’ => wp_strip_all_tags((string) $role_company),
‘featured_image’ => array(
‘url’ => esc_url_raw((string) $avatar_url),
‘url_2x’ => esc_url_raw((string) $avatar_url_2x),
‘alt’ => wp_strip_all_tags((string) $avatar_alt),
),
);
}
wp_reset_postdata();
}
return rest_ensure_response(array(
‘count’ => count($items),
‘items’ => $items,
));
}