feat(*): refactor metadata handling; move metadata to backend where possible, refine client views
This commit is contained in:
parent
929bc9f9f8
commit
9687509e4a
35 changed files with 506 additions and 339 deletions
|
@ -15,6 +15,8 @@ class ArtistFetcher extends PageFetcher
|
|||
|
||||
if (!$artist) return null;
|
||||
|
||||
$artist['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $artist);
|
||||
|
||||
return $artist;
|
||||
|
|
|
@ -15,6 +15,8 @@ class BookFetcher extends PageFetcher
|
|||
|
||||
if (!$book) return null;
|
||||
|
||||
$book['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $book);
|
||||
|
||||
return $book;
|
||||
|
|
|
@ -15,6 +15,8 @@ class GenreFetcher extends PageFetcher
|
|||
|
||||
if (!$genre) return null;
|
||||
|
||||
$genre['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $genre);
|
||||
|
||||
return $genre;
|
||||
|
|
22
api/Classes/GlobalsFetcher.php
Normal file
22
api/Classes/GlobalsFetcher.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Classes;
|
||||
|
||||
class GlobalsFetcher extends PageFetcher
|
||||
{
|
||||
public function fetch(): ?array
|
||||
{
|
||||
$cacheKey = "globals";
|
||||
$cached = $this->cacheGet($cacheKey);
|
||||
|
||||
if ($cached) return $cached;
|
||||
|
||||
$globals = $this->fetchFromApi("optimized_globals");
|
||||
|
||||
if (empty($globals)) return null;
|
||||
|
||||
$this->cacheSet($cacheKey, $globals[0]);
|
||||
|
||||
return $globals[0];
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ class MovieFetcher extends PageFetcher
|
|||
|
||||
if (!$movie) return null;
|
||||
|
||||
$movie['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $movie);
|
||||
|
||||
return $movie;
|
||||
|
|
|
@ -3,23 +3,29 @@
|
|||
namespace App\Classes;
|
||||
|
||||
use App\Classes\BaseHandler;
|
||||
use App\Classes\GlobalsFetcher;
|
||||
|
||||
abstract class PageFetcher extends BaseHandler
|
||||
{
|
||||
protected ?array $globals = null;
|
||||
|
||||
protected function cacheGet(string $key): mixed
|
||||
{
|
||||
return $this->cache && $this->cache->exists($key) ? json_decode($this->cache->get($key), true) : null;
|
||||
return $this->cache && $this->cache->exists($key)
|
||||
? json_decode($this->cache->get($key), true)
|
||||
: null;
|
||||
}
|
||||
|
||||
protected function cacheSet(string $key, mixed $value, int $ttl = 3600): void
|
||||
{
|
||||
if ($this->cache) $this->cache->setex($key, $ttl, json_encode($value));
|
||||
if ($this->cache) {
|
||||
$this->cache->setex($key, $ttl, json_encode($value));
|
||||
}
|
||||
}
|
||||
|
||||
protected function fetchSingleFromApi(string $endpoint, string $url): ?array
|
||||
{
|
||||
$data = $this->fetchFromApi($endpoint, "url=eq./{$url}");
|
||||
|
||||
return $data[0] ?? null;
|
||||
}
|
||||
|
||||
|
@ -27,4 +33,14 @@ abstract class PageFetcher extends BaseHandler
|
|||
{
|
||||
return $this->makeRequest("POST", $endpoint, ['json' => $body]);
|
||||
}
|
||||
|
||||
public function getGlobals(): ?array
|
||||
{
|
||||
if ($this->globals !== null) return $this->globals;
|
||||
|
||||
$fetcher = new GlobalsFetcher();
|
||||
$this->globals = $fetcher->fetch();
|
||||
|
||||
return $this->globals;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ class ShowFetcher extends PageFetcher
|
|||
|
||||
if (!$show) return null;
|
||||
|
||||
$show['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $show);
|
||||
|
||||
return $show;
|
||||
|
|
|
@ -20,6 +20,8 @@ class TagFetcher extends PageFetcher
|
|||
|
||||
if (!$results || count($results) === 0) return null;
|
||||
|
||||
$results[0]['globals'] = $this->getGlobals();
|
||||
|
||||
$this->cacheSet($cacheKey, $results);
|
||||
|
||||
return $results;
|
||||
|
|
14
composer.lock
generated
14
composer.lock
generated
|
@ -753,16 +753,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.5.1",
|
||||
"version": "v3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -775,7 +775,7 @@
|
|||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
"dev-main": "3.6-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -800,7 +800,7 @@
|
|||
"description": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -816,7 +816,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
"time": "2024-09-25T14:21:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "voku/html-min",
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import feeds from "./feeds.js"
|
||||
import general from "./general.js";
|
||||
import media from "./media.js";
|
||||
import metadata from "./metadata.js";
|
||||
import navigation from "./navigation.js";
|
||||
|
||||
export default {
|
||||
...feeds,
|
||||
...general,
|
||||
...media,
|
||||
...metadata,
|
||||
...navigation,
|
||||
};
|
||||
|
|
19
config/filters/metadata.js
Normal file
19
config/filters/metadata.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
export default {
|
||||
getMetadata: (data = {}, globals = {}, page = {}, title = "", description = "", schema = "") => {
|
||||
const metadata = data?.metadata;
|
||||
const baseUrl = globals.url || ""
|
||||
const ogPath = "/og/w800";
|
||||
const image = metadata?.open_graph_image || globals.metadata?.open_graph_image || globals.avatar;
|
||||
const rawTitle = title || page.title || metadata?.title || globals.site_name;
|
||||
const resolvedTitle = `${rawTitle} • ${globals.site_name}`;
|
||||
const resolvedDescription = description || metadata?.description || page.description || globals.site_description;
|
||||
const url = metadata?.url || (page.url ? `${baseUrl}${page.url}` : "#");
|
||||
|
||||
return {
|
||||
title: resolvedTitle,
|
||||
description: resolvedDescription,
|
||||
url,
|
||||
open_graph_image: `${baseUrl}${ogPath}${image}`
|
||||
};
|
||||
}
|
||||
};
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "coryd.dev",
|
||||
"version": "7.0.8",
|
||||
"version": "8.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "coryd.dev",
|
||||
"version": "7.0.8",
|
||||
"version": "8.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minisearch": "^7.1.2",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "coryd.dev",
|
||||
"version": "7.0.8",
|
||||
"version": "8.0.0",
|
||||
"description": "The source for my personal site. Built using 11ty (and other tools).",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
|
|
|
@ -165,12 +165,26 @@ SELECT
|
|||
END
|
||||
) AS feed,
|
||||
json_build_object(
|
||||
'title', p.title,
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(p.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN CONCAT('/', df.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN
|
||||
CONCAT('/', df.filename_disk)
|
||||
ELSE globals.metadata->>'open_graph_image'
|
||||
END,
|
||||
'url', CONCAT(globals.url, p.slug),
|
||||
'type', 'article'
|
||||
) AS metadata
|
||||
FROM posts p
|
||||
LEFT JOIN directus_files df ON p.image = df.id
|
||||
CROSS JOIN optimized_globals globals
|
||||
GROUP BY p.id, df.filename_disk, globals.cdn_url;
|
||||
GROUP BY p.id, df.filename_disk, globals.cdn_url, globals.site_name, globals.url, globals.metadata->>'open_graph_image';
|
||||
|
|
|
@ -5,11 +5,24 @@ SELECT
|
|||
p.permalink,
|
||||
p.description,
|
||||
json_build_object(
|
||||
'title', CONCAT(p.title, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(p.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', '\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN
|
||||
CONCAT('/', df.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
ELSE globals.metadata->>'open_graph_image'
|
||||
END,
|
||||
'url', CONCAT(globals.url, p.permalink),
|
||||
'type', 'page'
|
||||
) AS metadata,
|
||||
p.updated,
|
||||
(
|
||||
|
@ -62,4 +75,7 @@ FROM
|
|||
GROUP BY
|
||||
p.id,
|
||||
df.filename_disk,
|
||||
globals.cdn_url;
|
||||
globals.cdn_url,
|
||||
globals.site_name,
|
||||
globals.url,
|
||||
globals.metadata->>'open_graph_image';
|
||||
|
|
|
@ -173,12 +173,25 @@ SELECT
|
|||
END AS feed,
|
||||
(SELECT TO_CHAR(days_read, 'FM999G999G999') FROM reading_streak LIMIT 1) AS days_read,
|
||||
json_build_object(
|
||||
'title', CONCAT('Book • ', b.title, ' by ', b.author, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace( b.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN CONCAT('/', df.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
END,
|
||||
'url', CONCAT(globals.url, b.slug),
|
||||
'type', 'book'
|
||||
) AS metadata
|
||||
FROM books b
|
||||
LEFT JOIN directus_files df ON b.art = df.id
|
||||
CROSS JOIN optimized_globals globals
|
||||
GROUP BY b.id, df.filename_disk, globals.cdn_url;
|
||||
GROUP BY b.id, df.filename_disk, globals.cdn_url, globals.site_name, globals.url;
|
||||
|
|
|
@ -179,15 +179,28 @@ SELECT
|
|||
ELSE NULL
|
||||
END AS feed,
|
||||
json_build_object(
|
||||
'title', CONCAT('Movie • ', m.title, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(m.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df2.filename_disk IS NOT NULL AND df2.filename_disk != '' AND df2.filename_disk != '/' THEN
|
||||
CONCAT('/', df2.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
END,
|
||||
'url', CONCAT(globals.url, m.slug),
|
||||
'type', 'movie'
|
||||
) AS metadata
|
||||
FROM movies m
|
||||
LEFT JOIN directus_files df ON m.art = df.id
|
||||
LEFT JOIN directus_files df2 ON m.backdrop = df2.id
|
||||
CROSS JOIN optimized_globals globals
|
||||
GROUP BY m.id, df.filename_disk, df2.filename_disk, globals.cdn_url
|
||||
GROUP BY m.id, df.filename_disk, df2.filename_disk, globals.cdn_url, globals.site_name, globals.url
|
||||
ORDER BY m.last_watched DESC;
|
||||
|
|
|
@ -186,13 +186,26 @@ SELECT
|
|||
WHERE ra.artists_id = ar.id
|
||||
) AS related_artists,
|
||||
json_build_object(
|
||||
'title', CONCAT('Artist • ', ar.name_string, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(ar.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df.filename_disk IS NOT NULL AND df.filename_disk != '' AND df.filename_disk != '/' THEN CONCAT('/', df.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
END,
|
||||
'url', CONCAT(globals.url, ar.slug),
|
||||
'type', 'artist'
|
||||
) AS metadata
|
||||
FROM artists ar
|
||||
LEFT JOIN directus_files df ON ar.art = df.id
|
||||
LEFT JOIN genres g ON ar.genres = g.id
|
||||
CROSS JOIN optimized_globals globals
|
||||
GROUP BY ar.id, df.filename_disk, g.name, g.slug, g.emoji, globals.cdn_url;
|
||||
GROUP BY ar.id, df.filename_disk, g.name, g.slug, g.emoji, globals.cdn_url, globals.site_name, globals.url;
|
||||
|
|
|
@ -106,6 +106,20 @@ SELECT
|
|||
WHERE pg.genres_id = g.id
|
||||
) AS posts,
|
||||
json_build_object(
|
||||
'title', CONCAT('Genre • ', g.name, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
g.description,
|
||||
E'[*_`~#>-]', '', 'g'
|
||||
),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', (
|
||||
SELECT CONCAT('/', df_artist.filename_disk)
|
||||
FROM artists a
|
||||
|
@ -115,7 +129,9 @@ SELECT
|
|||
AND df_artist.filename_disk != ''
|
||||
ORDER BY a.total_plays DESC
|
||||
LIMIT 1
|
||||
)
|
||||
),
|
||||
'url', CONCAT(globals.url, g.slug),
|
||||
'type', 'genre'
|
||||
) AS metadata
|
||||
FROM genres g
|
||||
CROSS JOIN optimized_globals globals
|
||||
|
|
|
@ -179,15 +179,28 @@ SELECT
|
|||
) AS artists,
|
||||
MAX(e.last_watched_at) AS last_watched_at,
|
||||
json_build_object(
|
||||
'title', CONCAT('Show • ', s.title, ' • ', globals.site_name),
|
||||
'description', LEFT(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(s.description, E'[*_`~#>-]', '', 'g'),
|
||||
E'\\[(.*?)\\]\\((.*?)\\)', E'\\1', 'g'
|
||||
),
|
||||
E'!\\[(.*?)\\]\\((.*?)\\)', '', 'g'
|
||||
),
|
||||
250
|
||||
),
|
||||
'open_graph_image', CASE
|
||||
WHEN df_backdrop.filename_disk IS NOT NULL AND df_backdrop.filename_disk != '' AND df_backdrop.filename_disk != '/' THEN CONCAT('/', df_backdrop.filename_disk)
|
||||
ELSE NULL
|
||||
END
|
||||
END,
|
||||
'url', CONCAT(globals.url, s.slug),
|
||||
'type', 'show'
|
||||
) AS metadata
|
||||
FROM shows s
|
||||
LEFT JOIN episodes e ON s.id = e.show
|
||||
LEFT JOIN directus_files df_art ON s.art = df_art.id
|
||||
LEFT JOIN directus_files df_backdrop ON s.backdrop = df_backdrop.id
|
||||
CROSS JOIN optimized_globals globals
|
||||
GROUP BY s.id, df_art.filename_disk, df_backdrop.filename_disk, globals.cdn_url
|
||||
GROUP BY s.id, df_art.filename_disk, df_backdrop.filename_disk, globals.cdn_url, globals.site_name, globals.url
|
||||
ORDER BY MAX(e.last_watched_at) DESC;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
require_once "icons.php";
|
||||
require_once "media.php";
|
||||
require_once "metadata.php";
|
||||
require_once "paginator.php";
|
||||
require_once "routing.php";
|
||||
require_once "strings.php";
|
||||
|
|
33
server/utils/metadata.php
Normal file
33
server/utils/metadata.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
function setupPageMetadata(array $page, string $requestUri): array {
|
||||
$globals = $page['globals'] ?? [];
|
||||
|
||||
$title = htmlspecialchars($page["metadata"]["title"] ?? "", ENT_QUOTES, "UTF-8");
|
||||
$description = htmlspecialchars($page["metadata"]["description"] ?? "", ENT_QUOTES, "UTF-8");
|
||||
$image = htmlspecialchars(
|
||||
$page["metadata"]["open_graph_image"] ?? $globals["metadata"]["open_graph_image"] ?? "",
|
||||
ENT_QUOTES,
|
||||
"UTF-8"
|
||||
);
|
||||
$fullUrl = $globals["url"] . $requestUri;
|
||||
$oembedUrl = $globals["url"] . "/oembed" . $requestUri;
|
||||
|
||||
return [
|
||||
'pageTitle' => $title,
|
||||
'pageDescription' => $description,
|
||||
'ogImage' => $image,
|
||||
'fullUrl' => $fullUrl,
|
||||
'oembedUrl' => $oembedUrl,
|
||||
'globals' => $globals
|
||||
];
|
||||
}
|
||||
|
||||
function cleanMeta($value) {
|
||||
$value = trim($value ?? '');
|
||||
$value = str_replace(["\r", "\n"], ' ', $value);
|
||||
$value = preg_replace('/\s+/', ' ', $value);
|
||||
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
|
@ -68,11 +68,4 @@
|
|||
return $string . 's' . ($trailing ? $trailing : '');
|
||||
}
|
||||
|
||||
function cleanMeta($value) {
|
||||
$value = trim($value ?? '');
|
||||
$value = str_replace(["\r", "\n"], ' ', $value);
|
||||
$value = preg_replace('/\s+/', ' ', $value);
|
||||
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -11,18 +11,18 @@
|
|||
|
||||
if (strpos($url, "music/artists/") !== 0) redirectTo404();
|
||||
|
||||
$artist = (new ArtistFetcher())->fetch($url);
|
||||
$fetcher = new ArtistFetcher();
|
||||
$artist = $fetcher->fetch($url);
|
||||
|
||||
if (!$artist) redirectTo404();
|
||||
|
||||
$artist["description"] = parseMarkdown($artist["description"]);
|
||||
$pageTitle = htmlspecialchars("Artists • " . $artist["name"], ENT_QUOTES, "UTF-8");
|
||||
$pageDescription = truncateText(htmlspecialchars(strip_tags($artist["description"]), ENT_QUOTES, "UTF-8"), 250);
|
||||
$ogImage = htmlspecialchars($artist["metadata"]["open_graph_image"], ENT_QUOTES, "UTF-8");
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
$artist["description_html"] = parseMarkdown($artist["description"]);
|
||||
$artist["globals"] = $fetcher->getGlobals();
|
||||
$page = $artist;
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -11,18 +11,19 @@
|
|||
|
||||
if (!preg_match('/^reading\/books\/([\dXx-]+)$/', $url)) redirectTo404();
|
||||
|
||||
$book = (new BookFetcher())->fetch($url);
|
||||
$fetcher = new BookFetcher();
|
||||
$book = $fetcher->fetch($url);
|
||||
|
||||
if (!$book) redirectTo404();
|
||||
|
||||
$book["description"] = parseMarkdown($book["description"]);
|
||||
$pageTitle = htmlspecialchars("Books • {$book["title"]} by {$book["author"]}", ENT_QUOTES, "UTF-8");
|
||||
$pageDescription = truncateText(htmlspecialchars(strip_tags($book["description"]), ENT_QUOTES, "UTF-8"), 250);
|
||||
$ogImage = htmlspecialchars($book["metadata"]["open_graph_image"], ENT_QUOTES, "UTF-8");
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
$book["description_html"] = parseMarkdown($book["description"]);
|
||||
$book["globals"] = $fetcher->getGlobals();
|
||||
$page = $book;
|
||||
$globals = $page["globals"];
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -11,20 +11,19 @@
|
|||
|
||||
if (!preg_match('/^music\/genres\/[\w-]+$/', $url)) redirectTo404();
|
||||
|
||||
$genre = (new GenreFetcher())->fetch($url);
|
||||
$fetcher = new GenreFetcher();
|
||||
$genre = $fetcher->fetch($url);
|
||||
|
||||
if (!$genre) redirectTo404();
|
||||
|
||||
$pageTitle = htmlspecialchars("Genres • " . $genre["name"], ENT_QUOTES, "UTF-8");
|
||||
$pageDescription = truncateText(
|
||||
htmlspecialchars(strip_tags($genre["description"]), ENT_QUOTES, "UTF-8"),
|
||||
250
|
||||
);
|
||||
$ogImage = htmlspecialchars($genre["metadata"]["open_graph_image"] ?? "", ENT_QUOTES, "UTF-8");
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
$genre["globals"] = $fetcher->getGlobals();
|
||||
$page = $genre;
|
||||
$globals = $page["globals"];
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -11,18 +11,19 @@
|
|||
|
||||
if (!preg_match('/^watching\/movies\/[\w-]+$/', $url)) redirectTo404();
|
||||
|
||||
$movie = (new MovieFetcher())->fetch($url);
|
||||
$fetcher = new MovieFetcher();
|
||||
$movie = $fetcher->fetch($url);
|
||||
|
||||
if (!$movie) redirectTo404();
|
||||
|
||||
$movie["description"] = parseMarkdown($movie["description"]);
|
||||
$pageTitle = htmlspecialchars("Movies • " . $movie["title"], ENT_QUOTES, "UTF-8");
|
||||
$pageDescription = truncateText(htmlspecialchars(strip_tags($movie["description"]), ENT_QUOTES, "UTF-8"), 250);
|
||||
$ogImage = htmlspecialchars($movie["metadata"]["open_graph_image"], ENT_QUOTES, "UTF-8");
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
$movie["description_html"] = parseMarkdown($movie["description"]);
|
||||
$movie["globals"] = $fetcher->getGlobals();
|
||||
$page = $movie;
|
||||
$globals = $page["globals"];
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -11,20 +11,19 @@
|
|||
|
||||
if (!preg_match('/^watching\/shows\/[\w-]+$/', $url)) redirectTo404();
|
||||
|
||||
$show = (new ShowFetcher())->fetch($url);
|
||||
$fetcher = new ShowFetcher();
|
||||
$show = $fetcher->fetch($url);
|
||||
|
||||
if (!$show) redirectTo404();
|
||||
|
||||
$pageTitle = htmlspecialchars("Show • " . $show["title"], ENT_QUOTES, "UTF-8");
|
||||
$pageDescription = truncateText(
|
||||
htmlspecialchars(strip_tags($show["description"]), ENT_QUOTES, "UTF-8"),
|
||||
250
|
||||
);
|
||||
$ogImage = htmlspecialchars($show["metadata"]["open_graph_image"], ENT_QUOTES, "UTF-8");
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
$show["description_html"] = parseMarkdown($show["description"]);
|
||||
$show["globals"] = $fetcher->getGlobals();
|
||||
$page = $show;
|
||||
$globals = $page["globals"];
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
require __DIR__ . "/../server/utils/init.php";
|
||||
|
||||
use App\Classes\TagFetcher;
|
||||
use App\Classes\GlobalsFetcher;
|
||||
use voku\helper\HtmlMin;
|
||||
|
||||
$requestUri = $_SERVER["REQUEST_URI"];
|
||||
|
@ -25,9 +26,10 @@
|
|||
|
||||
if (!preg_match('/^[\p{L}\p{N} _\.\-\&]+$/u', $tag)) redirectTo404();
|
||||
|
||||
$page = isset($matches[2]) ? max(1, (int)$matches[2]) : 1;
|
||||
$pageNum = isset($matches[2]) ? max(1, (int)$matches[2]) : 1;
|
||||
$pageSize = 20;
|
||||
$tagged = (new TagFetcher())->fetch($tag, $page, $pageSize);
|
||||
$fetcher = new TagFetcher();
|
||||
$tagged = $fetcher->fetch($tag, $pageNum, $pageSize);
|
||||
|
||||
if (!$tagged || count($tagged) === 0) {
|
||||
header("Location: /404/", true, 302);
|
||||
|
@ -37,21 +39,32 @@
|
|||
$totalCount = $tagged[0]['total_count'] ?? 0;
|
||||
$totalPages = max(ceil($totalCount / $pageSize), 1);
|
||||
$pagination = [
|
||||
'pageNumber' => $page,
|
||||
'pageNumber' => $pageNum,
|
||||
'pages' => range(1, $totalPages),
|
||||
'href' => [
|
||||
'previous' => $page > 1 ? "/tags/{$tag}/" . ($page - 1) : null,
|
||||
'next' => $page < $totalPages ? "/tags/{$tag}/" . ($page + 1) : null
|
||||
'previous' => $pageNum > 1 ? "/tags/{$tag}/" . ($pageNum - 1) : null,
|
||||
'next' => $pageNum < $totalPages ? "/tags/{$tag}/" . ($pageNum + 1) : null
|
||||
],
|
||||
'links' => range(1, $totalPages)
|
||||
];
|
||||
$globals = (new GlobalsFetcher())->fetch();
|
||||
$page = [
|
||||
'tag' => $tag,
|
||||
'items' => $tagged,
|
||||
'pagination' => $pagination,
|
||||
'metadata' => [
|
||||
'title' => '#' . ucfirst($tag) . ' • ' . $globals['site_name'],
|
||||
'description' => 'All content tagged with #' . ucfirst($tag) . '.',
|
||||
'open_graph_image' => $globals['metadata']['open_graph_image'],
|
||||
'url' => $globals['url'] . $requestUri,
|
||||
'type' => 'tag'
|
||||
],
|
||||
'globals' => $globals
|
||||
];
|
||||
|
||||
$pageTitle = "#" . strtolower(ucfirst($tag));
|
||||
$pageDescription = "All content tagged with #" . strtolower(ucfirst($tag)) . ".";
|
||||
$fullUrl = "https://www.coryd.dev" . $requestUri;
|
||||
$oembedUrl = "https://www.coryd.dev/oembed" . $requestUri;
|
||||
|
||||
extract(setupPageMetadata($page, $requestUri));
|
||||
ob_start();
|
||||
header("Cache-Control: public, max-age=3600");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<title><?= cleanMeta($pageTitle ?? "{{ pageTitle }}") ?> • {{ globals.site_name }}</title>
|
||||
<meta name="description" content="<?= cleanMeta($pageDescription ?? '{{ pageDescription | escape }}') ?>" />
|
||||
<meta property="og:title" content="<?= cleanMeta($pageTitle ?? '{{ pageTitle }}') ?> • {{ globals.site_name }}" />
|
||||
<meta property="og:description" content="<?= cleanMeta($pageDescription ?? '{{ pageDescription | escape }}') ?>" />
|
||||
<meta property="og:image" content="{{ globals.url }}<?= cleanMeta("/og/w800/{% appVersion %}" . ($ogImage ?? '{{ ogImage }}')) ?>" />
|
||||
<meta property="og:url" content="<?= cleanMeta($fullUrl ?? '{{ fullUrl }}') ?>" />
|
||||
<link rel="alternate" type="application/json+oembed" href="<?= cleanMeta($oembedUrl ?? '{{ oembedUrl }}') ?>" title="<?= cleanMeta($pageTitle ?? '{{ pageTitle }}') ?> • {{ globals.site_name }}">
|
||||
<link rel="canonical" href="<?= cleanMeta($fullUrl ?? '{{ fullUrl }}') ?>" />
|
||||
<title><?= cleanMeta($page['metadata']['title']) ?></title>
|
||||
<meta name="description" content="<?= cleanMeta($page['metadata']['description']) ?>" />
|
||||
<meta property="og:title" content="<?= cleanMeta($page['metadata']['title']) ?>" />
|
||||
<meta property="og:description" content="<?= cleanMeta($page['metadata']['description']) ?>" />
|
||||
<meta property="og:image" content="<?= cleanMeta($globals['url'] . '/og/w800' . $page['metadata']['open_graph_image']) ?>" />
|
||||
<meta property="og:url" content="<?= cleanMeta($page['metadata']['url'] ?? $fullUrl) ?>" />
|
||||
<link rel="alternate" type="application/json+oembed" href="<?= cleanMeta($oembedUrl) ?>" title="<?= cleanMeta($page['metadata']['title']) ?>">
|
||||
<link rel="canonical" href="<?= cleanMeta($page['metadata']['url'] ?? $fullUrl) ?>" />
|
||||
<?php if (!empty($pagination)): ?>
|
||||
<?php if (!empty($pagination['href']['next'])): ?>
|
||||
<link rel="next" href="<?= cleanMeta($pagination['href']['next']) ?>">
|
||||
|
|
|
@ -1,102 +1,62 @@
|
|||
{%- assign fullUrl = globals.url | append: page.url -%}
|
||||
{%- assign oembedUrl = globals.url | append: "/oembed" | append: page.url -%}
|
||||
{%- capture appVersionString -%}{% appVersion %}{%- endcapture -%}
|
||||
{%- assign ogImageBaseUrl = globals.url | append: "/og/w800/" | append: appVersionString -%}
|
||||
{%- capture pageTitle -%}
|
||||
{%- if page.title -%}
|
||||
{{ page.title | append: ' • ' | append: globals.site_name }}
|
||||
{%- elsif title -%}
|
||||
{{ title | append: ' • ' | append: globals.site_name }}
|
||||
{%- else -%}
|
||||
{{ globals.site_name }}
|
||||
{%- endif -%}
|
||||
{%- endcapture -%}
|
||||
{%- capture pageDescription -%}
|
||||
{%- if page.description -%}
|
||||
{{ page.description }}
|
||||
{%- elsif description -%}
|
||||
{{ description }}
|
||||
{%- else -%}
|
||||
{{ globals.site_description }}
|
||||
{%- endif -%}
|
||||
{%- endcapture -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: globals.metadata.open_graph_image -%}
|
||||
{%- assign source = page -%}
|
||||
{%- case schema -%}
|
||||
{%- when 'artist' -%}
|
||||
{% render "fetchers/artist.php.liquid" %}
|
||||
{%- when 'genre' -%}
|
||||
{% render "fetchers/genre.php.liquid" %}
|
||||
{%- when 'book' -%}
|
||||
{% render "fetchers/book.php.liquid" %}
|
||||
{%- when 'movie' -%}
|
||||
{% render "fetchers/movie.php.liquid" %}
|
||||
{%- when 'show' -%}
|
||||
{% render "fetchers/show.php.liquid" %}
|
||||
{%- when 'tags' -%}
|
||||
{% render "fetchers/tags.php.liquid" %}
|
||||
{%- when 'artist', 'genre', 'book', 'movie', 'show', 'tags' -%}
|
||||
{% render "fetchers/{{ schema }}.php.liquid" %}
|
||||
{%- when 'blog' -%}
|
||||
{%- assign pageTitle = post.title -%}
|
||||
{%- assign pageDescription = post.description -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: post.metadata.open_graph_image -%}
|
||||
{%- assign source = post -%}
|
||||
{%- when 'music-index', 'music-week-artists' -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: music.week.artists[0].metadata.open_graph_image -%}
|
||||
{%- assign source = music.week.artists[0] -%}
|
||||
{%- when 'music-week-albums', 'music-week-tracks' -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: music.week.albums[0].metadata.open_graph_image -%}
|
||||
{%- assign source = music.week.albums[0] -%}
|
||||
{%- when 'music-month-artists' -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: music.month.artists[0].metadata.open_graph_image -%}
|
||||
{%- assign source = music.month.artists[0] -%}
|
||||
{%- when 'music-month-albums' -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: music.month.albums[0].metadata.open_graph_image -%}
|
||||
{%- assign source = music.month.albums[0] -%}
|
||||
{%- when 'music-releases' -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: albumReleases.upcoming[0].metadata.open_graph_image -%}
|
||||
{%- assign source = albumReleases.upcoming[0] -%}
|
||||
{%- when 'books' -%}
|
||||
{%- assign overviewBook = books.all | filterBooksByStatus: 'started' | reverse | first %}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: overviewBook.metadata.open_graph_image -%}
|
||||
{%- assign source = books.all | filterBooksByStatus: 'started' | reverse | first -%}
|
||||
{%- when 'reading-year' -%}
|
||||
{%- assign pageTitle = 'Books' | append: ' • ' | append: year.value | append: ' • ' | append: globals.site_name -%}
|
||||
{%- capture pageDescription -%}
|
||||
Here's what I read in {{ year.value }}.
|
||||
{%- endcapture -%}
|
||||
{%- assign bookData = year.data | filterBooksByStatus: 'finished' -%}
|
||||
{%- assign bookYear = bookData | shuffleArray | first -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: bookYear.metadata.open_graph_image -%}
|
||||
{%- assign title = 'Books • ' | append: year.value | append: ' • ' | append: globals.site_name -%}
|
||||
{%- assign description = "Here's what I read in " | append: year.value | append: '.' -%}
|
||||
{%- assign bookYear = year.data | filterBooksByStatus: 'finished' | shuffleArray | first -%}
|
||||
{%- assign source = bookYear -%}
|
||||
{%- when 'favorite-movies' -%}
|
||||
{%- assign favoriteMovie = movies.favorites | shuffleArray | first %}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: favoriteMovie.metadata.open_graph_image -%}
|
||||
{%- assign source = movies.favorites | shuffleArray | first -%}
|
||||
{%- when 'favorite-shows' -%}
|
||||
{%- assign favoriteShow = tv.favorites | shuffleArray | first %}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: favoriteShow.metadata.open_graph_image -%}
|
||||
{%- assign source = tv.favorites | shuffleArray | first -%}
|
||||
{%- when 'watching' -%}
|
||||
{%- assign mergedMovies = movies.recentlyWatched | mergeArray: movies.favorites %}
|
||||
{%- assign mergedShows = tv.recentlyWatched | mergeArray: tv.favorites %}
|
||||
{%- assign overviewWatched = mergedMovies | mergeArray: mergedShows | shuffleArray | first -%}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: overviewWatched.metadata.open_graph_image -%}
|
||||
{%- assign mergedMovies = movies.recentlyWatched | mergeArray: movies.favorites -%}
|
||||
{%- assign mergedShows = tv.recentlyWatched | mergeArray: tv.favorites -%}
|
||||
{%- assign source = mergedMovies | mergeArray: mergedShows | shuffleArray | first -%}
|
||||
{%- when 'upcoming-shows' -%}
|
||||
{%- assign upcomingShow = upcomingShows.watching | shuffleArray | first %}
|
||||
{%- assign ogImage = ogImageBaseUrl | append: upcomingShow.metadata.open_graph_image -%}
|
||||
{%- when 'page' -%}
|
||||
{%- assign pageDescription = page.description -%}
|
||||
{% endcase %}
|
||||
{%- assign source = upcomingShows.watching | shuffleArray | first -%}
|
||||
{%- endcase %}
|
||||
{%- assign meta = source | getMetadata: globals, page, title, description, schema -%}
|
||||
{%- assign fullUrl = meta.url -%}
|
||||
{%- assign oembedUrl = globals.url | append: "/oembed" | append: page.url -%}
|
||||
{%- if type == 'dynamic' -%}
|
||||
{% render "metadata/dynamic.php.liquid"
|
||||
fullUrl: fullUrl,
|
||||
oembedUrl: oembedUrl,
|
||||
pageTitle:pageTitle,
|
||||
pageDescription:pageDescription,
|
||||
ogImage:globals.metadata.open_graph_image,
|
||||
pageTitle: meta.title,
|
||||
pageDescription: meta.description,
|
||||
ogImage: meta.open_graph_image,
|
||||
globals: globals,
|
||||
%}
|
||||
{%- else -%}
|
||||
{% render "metadata/static.liquid"
|
||||
fullUrl: fullUrl,
|
||||
oembedUrl: oembedUrl,
|
||||
pageTitle:pageTitle,
|
||||
pageDescription:pageDescription,
|
||||
ogImage:ogImage,
|
||||
pageTitle: meta.title,
|
||||
pageDescription: meta.description,
|
||||
ogImage: meta.open_graph_image,
|
||||
globals: globals,
|
||||
%}
|
||||
{%- endif -%}
|
||||
{%- endif %}
|
||||
{% render "metadata/base.liquid"
|
||||
pageTitle:pageTitle,
|
||||
pageTitle: meta.title,
|
||||
globals: globals,
|
||||
eleventy: eleventy,
|
||||
appVersion: appVersion,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
{%- assign description = pageDescription | markdown | strip_html | htmlTruncate | escape -%}
|
||||
<title>{{ pageTitle }}</title>
|
||||
<meta name="description" content="{{ pageDescription | markdown | strip_html | htmlTruncate | escape }}" />
|
||||
<meta property="og:title" content="{{ pageTitle }}" />
|
||||
<meta name="description" content="{{ description }}" />
|
||||
<meta property="og:description" content="{{ description }}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:description" content="{{ pageDescription | markdown | strip_html | htmlTruncate | escape }}" />
|
||||
<meta property="og:type" content="{{ page.metadata.type | default: 'article' }}" />
|
||||
<meta property="og:url" content="{{ fullUrl }}" />
|
||||
<link rel="alternate" type="application/json+oembed" href="{{ oembedUrl }}" title="{{ pageTitle }}">
|
||||
<link rel="canonical" href="{{ fullUrl }}" />
|
||||
<meta property="og:image" content="{{ ogImage }}" />
|
||||
<link rel="alternate" type="application/json+oembed" href="{{ oembedUrl }}" title="{{ pageTitle }}" />
|
||||
<link rel="canonical" href="{{ fullUrl }}" />
|
||||
|
|
|
@ -3,7 +3,6 @@ title: Search
|
|||
permalink: /search/index.html
|
||||
description: Search through posts and other content on my site.
|
||||
---
|
||||
|
||||
<h2 class="page-title">Search</h2>
|
||||
<p>You can find <a href="/posts">posts</a>, <a href="/links">links</a>, <a href="/music/#artists">artists</a>, genres, <a href="/watching#movies">movies</a>, <a href="/watching#tv">shows</a> and <a href="/reading">books</a> via the field below (though it only surfaces movies and shows I've watched and books I've written something about). <a href="/tags">You can also browse my tags list</a>.</p>
|
||||
{% render "blocks/top-tags.liquid"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue