The code below makes use of JReviews filter hooks to create a simple read-only API for listings and reviews. To get started, read the developers hooks documentation.
Once you have the code in place in overrides, to test the API, add the format=json
parameter to any listings or reviews page. For example:
Listings endpoint
https://domain.com/most-recent?format=json
Reviews endpoint
https://domain.com/latest-user-reviews?format=json
<?php
defined('MVC_FRAMEWORK') or die;
use Clickfwd\Hook\Filter;
class JreviewsHookRestApi
{
protected $routes;
public function __construct()
{
Filter::add('render_reviews', [$this, 'reviews']);
Filter::add('render_categories', [$this, 'listings']);
}
public function listings($output, $params)
{
if (! $this->isApiRequest()) {
return $output;
}
// Only continue if 'listings' were sent to the view
if (! isset($params['viewVars']['listings']))
{
return $output;
}
// List of listings for the current page
$listings = $params['viewVars']['listings'] ?? [];
$items = [];
foreach ($listings as $listing)
{
$items[] = $this->listingResource($listing);
}
return $this->send([
'items' => $items,
'pagination' => $this->pagination($params['viewVars']['pagination']),
]);
}
public function reviews($output, $params)
{
if (! $this->isApiRequest()) {
return $output;
}
// Only continue if 'reviews' were sent to the view
if (! isset($params['viewVars']['reviews']))
{
return $output;
}
S2App::import('Helper','routes','jreviews');
$this->routes = ClassRegistry::getClass('RoutesHelper');
// List of reviews for the current page
$reviews = $params['viewVars']['reviews'] ?? [];
$items = [];
foreach ($reviews as $review)
{
$items[] = $this->reviewResource($review);
}
return $this->send([
'items' => $items,
'pagination' => $this->pagination($params['viewVars']['pagination']),
]);
}
protected function isApiRequest()
{
$request = S2Object::make('request');
return $request->method() == 'GET' && $request->get('format') == 'json';
}
protected function listingResource($listing)
{
$url = cmsFramework::makeAbsUrl(cmsFramework::route($listing['Listing']['url']));
return [
'title' => $listing['Listing']['title'],
'href' => $url,
'summary' => $listing['Listing']['summary'] ?? null,
'image' => $this->imageResource($listing),
'thumbnail' => $this->thumbnailResource($listing),
'created' => $listing['Listing']['created'] ?? null,
'category' => $this->categoryResource($listing)
];
}
protected function reviewResource($review)
{
$url = $this->routes->reviewDiscuss('',$review,['listing'=>$review,'return_url'=>true]);
return [
'title' => $review['Review']['title'],
'href' => $url,
'comment' => $review['Review']['comments'],
'average_rating' => (float) ($review['Rating']['average_rating'] ?? null),
'created' => $review['Review']['created'],
'listing' => $this->listingResource($review),
];
}
protected function imageResource($item)
{
$image = $item['MainMedia']['media_url'] ?? $item['Media']['photo'][0] ?? null;
$categoryImage = !empty($item['MainMedia']['category'])
? cmsFramework::makeAbsUrl($item['MainMedia']['category'])
: null;
return $image ?? $categoryImage ?? null;
}
protected function thumbnailResource($item)
{
return $item['MainMedia']['media_info']['thumbnail']['640x640s']['url']
?? $this->imageResource($item);
}
protected function categoryResource($item)
{
return [
'title' => $item['Category']['title'],
];
}
protected function pagination($vars)
{
$total = $vars['total'];
$per_page = $vars['limit'];
$page = $vars['page'] !== '' ? $vars['page'] : 1;
$total_pages = ceil($total/$per_page);
return [
'total' => (int) $total,
'per_page' => $per_page,
'page' => $page,
'total_pages' => $total_pages,
'links' => $this->paginationPreviousNextLinks($page, $total_pages),
];
}
protected function paginationPreviousNextLinks($page, $pages)
{
$url = cmsFramework::makeAbsUrl(cmsFramework::getCurrentUrl());
$urlParts = parse_url($url);
$links = [];
if ($page > 1 && $pages > 1)
{
$links['previous'] = $this->pageLink($urlParts, $page - 1);
}
if ($page < $pages && $pages > 1)
{
$links['next'] = $this->pageLink($urlParts, $page + 1);
}
return $links;
}
protected function pageLink($urlParts, $page)
{
parse_str($urlParts['query'] ?? '', $queryString);
$queryString['format'] = 'json';
$baseUrl = $urlParts['scheme'].'://'.$urlParts['host'].$urlParts['path'];
return $baseUrl.'?'.http_build_query(array_merge($queryString,[S2_QVAR_PAGE => $page]));
}
protected function send($data)
{
header("Content-type: application/json");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
return json_encode($data);
}
}
new JreviewsHookRestApi();