Skip to content

Commit

Permalink
feat!: __sitemap__ & __templates__ API routes
Browse files Browse the repository at this point in the history
  • Loading branch information
johannschopplich committed Feb 12, 2024
1 parent 34c274e commit 366dec1
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 146 deletions.
14 changes: 9 additions & 5 deletions src/classes/Api/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace JohannSchopplich\Headless\Api;

use Exception;
use Kirby\Cms\App;
use Kirby\Cms\File;
use Kirby\Exception\Exception;
use Kirby\Http\Response;
use Kirby\Toolkit\A;

Expand All @@ -15,7 +15,9 @@ class Api
*/
public static function createHandler(callable ...$fns)
{
$context = [];
$context = [
'kirby' => App::instance()
];

return function (...$args) use ($fns, $context) {
foreach ($fns as $fn) {
Expand All @@ -34,6 +36,8 @@ public static function createHandler(callable ...$fns)

/**
* Create an API response
*
* @remarks
* Enforces consistent JSON responses by wrapping Kirby's `Response` class
*/
public static function createResponse(int $code, $data = null): Response
Expand All @@ -57,7 +61,7 @@ public static function createResponse(int $code, $data = null): Response
/**
* Get the status message for the given code
*
* @throws \Exception
* @throws \Kirby\Exception\Exception
*/
private static function getStatusMessage(int $code): string
{
Expand Down Expand Up @@ -90,12 +94,12 @@ public static function createPreflightResponse(): Response
$kirby = App::instance();

return new Response('', null, 204, [
// 204 responses **must not** have a `Content-Length` header
// (https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2)
'Access-Control-Allow-Origin' => $kirby->option('headless.cors.allowOrigin', '*'),
'Access-Control-Allow-Methods' => $kirby->option('headless.cors.allowMethods', 'GET, POST, OPTIONS'),
'Access-Control-Allow-Headers' => $kirby->option('headless.cors.allowHeaders', 'Accept, Content-Type, Authorization, X-Language'),
'Access-Control-Max-Age' => $kirby->option('headless.cors.maxAge', '86400'),
// 204 responses **must not** have a `Content-Length` header
// (https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2)
]);
}
}
135 changes: 4 additions & 131 deletions src/classes/Api/Middlewares.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Kirby\Exception\NotFoundException;
use Kirby\Filesystem\F;
use Kirby\Http\Response;
use Kirby\Http\Uri;
use Kirby\Panel\Panel;
use Kirby\Toolkit\Str;

Expand Down Expand Up @@ -46,46 +45,7 @@ public static function tryResolveFiles(array $context, array $args)
}

/**
* Try to resolve global site data
*/
public static function tryResolveSite(array $context, array $args)
{
$kirby = App::instance();

// The `$args` array contains the route parameters
if ($kirby->multilang()) {
[$languageCode, $path] = $args;
} else {
[$path] = $args;
}

if ($path !== '_site') {
return;
}

$data = $kirby->cache('pages')->getOrSet(
'_site.headless.json',
function () use ($kirby) {
$template = $kirby->template('_site');

if (!$template->exists()) {
throw new NotFoundException([
'key' => 'template.default.notFound'
]);
}

return $template->render([
'kirby' => $kirby,
'site' => $kirby->site()
]);
}
);

return Response::json($data);
}

/**
* Try to resolve the page id
* Try to resolve the page ID
*/
public static function tryResolvePage(array $context, array $args)
{
Expand Down Expand Up @@ -118,7 +78,7 @@ public static function tryResolvePage(array $context, array $args)
$data = $cache->get($cacheKey);
}

// Fetch the page regularly
// Fetch the page data
if ($data === null) {
$template = $page->template();

Expand All @@ -139,93 +99,7 @@ public static function tryResolvePage(array $context, array $args)
}

/**
* Try to resolve the sitemap tree
*
* @return \Kirby\Http\Response|void
*/
public static function tryResolveSitemap(array $context, array $args)
{
$kirby = App::instance();

// The `$args` array contains the route parameters
if ($kirby->multilang()) {
[$languageCode, $path] = $args;
} else {
[$path] = $args;
}

if ($path !== '_sitemap') {
return;
}

$sitemap = [];
$cache = $kirby->cache('pages');
$cacheKey = '_sitemap.headless.json';
$sitemap = $cache->get($cacheKey);
$withoutBase = fn (string $url) => '/' . (new Uri($url))->path();

if ($sitemap === null) {
$isIndexable = option('headless.sitemap.isIndexable');
$excludeTemplates = option('headless.sitemap.exclude.templates', []);
$excludePages = option('headless.sitemap.exclude.pages', []);

if (is_callable($excludePages)) {
$excludePages = $excludePages();
}

foreach ($kirby->site()->index() as $item) {
/** @var \Kirby\Cms\Page $item */
if (in_array($item->intendedTemplate()->name(), $excludeTemplates, true)) {
continue;
}

if (preg_match('!^(?:' . implode('|', $excludePages) . ')$!i', $item->id())) {
continue;
}

$options = $item->blueprint()->options();
if (isset($options['sitemap']) && $options['sitemap'] === false) {
continue;
}

if (is_callable($isIndexable) && $isIndexable($item) === false) {
continue;
}

$url = [
'url' => $withoutBase($item->url()),
'modified' => $item->modified('Y-m-d', 'date')
];

if ($kirby->multilang()) {
$url['links'] = $kirby->languages()->map(fn ($lang) => [
// Support ISO 3166-1 Alpha 2 and ISO 639-1
'lang' => Str::slug(preg_replace(
'/\.utf-?8$/i',
'',
$lang->locale(LC_ALL) ?? $lang->code()
)),
'url' => $withoutBase($item->url($lang->code()))
])->values();

$url['links'][] = [
'lang' => 'x-default',
'url' => $withoutBase($item->url())
];
}

$sitemap[] = $url;
}

$cache?->set($cacheKey, $sitemap);
}

return Response::json($sitemap);
}

/**
* Checks if a bearer token was sent with the request and
* if it matches the one configured in `.env`
* Validates the bearer token sent with the request
*/
public static function hasBearerToken()
{
Expand Down Expand Up @@ -254,12 +128,11 @@ public static function hasBody(array $context)

if (empty($request->body()->data())) {
return Api::createResponse(400, [
'error' => 'No body was sent with the request'
'error' => 'Missing request body'
]);
}

$context['body'] = $request->body();
$context['query'] = $request->query();

return $context;
}
Expand Down
Loading

0 comments on commit 366dec1

Please sign in to comment.