perf: cache fichier pour les rétroliens, invalidé sur create/update/delete/link
This commit is contained in:
+73
-19
@@ -117,6 +117,7 @@ class ArticleManager
|
||||
$this->writeMeta($dir, $meta);
|
||||
file_put_contents($dir . '/index.md', ltrim($content));
|
||||
$this->rebuildSearchIndex();
|
||||
$this->rebuildBacklinksCache();
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
@@ -181,6 +182,7 @@ class ArticleManager
|
||||
$this->writeMeta($dir, $meta);
|
||||
file_put_contents($dir . '/index.md', ltrim($content));
|
||||
$this->rebuildSearchIndex();
|
||||
$this->rebuildBacklinksCache();
|
||||
}
|
||||
|
||||
public function autosave(string $uuid, string $title, string $content, string $slug): bool
|
||||
@@ -414,6 +416,7 @@ class ArticleManager
|
||||
}
|
||||
$meta['external_links'][] = $entry;
|
||||
$this->writeMeta($dir, $meta);
|
||||
$this->rebuildBacklinksCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -466,6 +469,7 @@ class ArticleManager
|
||||
static fn ($l) => $l['url'] !== $url
|
||||
));
|
||||
$this->writeMeta($dir, $meta);
|
||||
$this->rebuildBacklinksCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -547,6 +551,75 @@ class ArticleManager
|
||||
$this->removeDir($dir);
|
||||
}
|
||||
$this->rebuildSearchIndex();
|
||||
$this->rebuildBacklinksCache();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// Cache des rétroliens
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
private function backlinksPath(): string
|
||||
{
|
||||
return $this->dataDir . '/_cache/backlinks.json';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstruit le cache des rétroliens.
|
||||
* Produit un index slug → [article minimal, ...] pour tous les articles publiés
|
||||
* qui pointent vers un autre article interne via leurs external_links.
|
||||
*/
|
||||
public function rebuildBacklinksCache(): void
|
||||
{
|
||||
$cacheDir = $this->dataDir . '/_cache';
|
||||
if (!is_dir($cacheDir)) {
|
||||
mkdir($cacheDir, 0755, true);
|
||||
}
|
||||
|
||||
$index = [];
|
||||
foreach ($this->getAll(publishedOnly: true) as $article) {
|
||||
foreach ($article['external_links'] ?? [] as $link) {
|
||||
$path = rtrim(parse_url($link['url'] ?? '', PHP_URL_PATH) ?? '', '/');
|
||||
if (!preg_match('#^/post/([a-z0-9][a-z0-9-]*)$#', $path, $m)) {
|
||||
continue;
|
||||
}
|
||||
$target = $m[1];
|
||||
$index[$target][] = [
|
||||
'uuid' => $article['uuid'],
|
||||
'slug' => $article['slug'] ?? '',
|
||||
'title' => $article['title'] ?? '',
|
||||
'cover' => $article['cover'] ?? '',
|
||||
'category' => $article['category'] ?? '',
|
||||
'published_at' => $article['published_at'] ?? '',
|
||||
'created_at' => $article['created_at'] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
$this->backlinksPath(),
|
||||
json_encode($index, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les articles qui pointent vers /post/<slug>, depuis le cache.
|
||||
* Reconstruit le cache si absent.
|
||||
*/
|
||||
public function getBacklinks(string $slug, string $excludeUuid = ''): array
|
||||
{
|
||||
$path = $this->backlinksPath();
|
||||
if (!file_exists($path)) {
|
||||
$this->rebuildBacklinksCache();
|
||||
}
|
||||
$index = json_decode((string) file_get_contents($path), true);
|
||||
if (!is_array($index)) {
|
||||
return [];
|
||||
}
|
||||
$result = $index[$slug] ?? [];
|
||||
if ($excludeUuid !== '') {
|
||||
$result = array_values(array_filter($result, static fn ($a) => $a['uuid'] !== $excludeUuid));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
@@ -887,25 +960,6 @@ class ArticleManager
|
||||
/**
|
||||
* Retourne les articles publiés qui contiennent un lien vers /post/<slug>.
|
||||
*/
|
||||
public function getBacklinks(string $slug, string $excludeUuid = ''): array
|
||||
{
|
||||
$pattern = '/post/' . $slug;
|
||||
$result = [];
|
||||
foreach ($this->getAll(publishedOnly: true) as $article) {
|
||||
if ($excludeUuid !== '' && $article['uuid'] === $excludeUuid) {
|
||||
continue;
|
||||
}
|
||||
foreach ($article['external_links'] ?? [] as $link) {
|
||||
$path = parse_url($link['url'] ?? '', PHP_URL_PATH) ?? '';
|
||||
if ($path === $pattern || rtrim($path, '/') === $pattern) {
|
||||
$result[] = $article;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function removeDir(string $dir): void
|
||||
{
|
||||
foreach (scandir($dir) as $entry) {
|
||||
|
||||
Reference in New Issue
Block a user