search: index plat search_index.json, reconstruit sur chaque write
This commit is contained in:
@@ -116,6 +116,7 @@ class ArticleManager
|
||||
];
|
||||
$this->writeMeta($dir, $meta);
|
||||
file_put_contents($dir . '/index.md', ltrim($content));
|
||||
$this->rebuildSearchIndex();
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
@@ -174,6 +175,7 @@ class ArticleManager
|
||||
$dir = $this->dataDir . '/' . $uuid;
|
||||
$this->writeMeta($dir, $meta);
|
||||
file_put_contents($dir . '/index.md', ltrim($content));
|
||||
$this->rebuildSearchIndex();
|
||||
}
|
||||
|
||||
public function autosave(string $uuid, string $title, string $content, string $slug): bool
|
||||
@@ -543,6 +545,61 @@ class ArticleManager
|
||||
if (is_dir($dir)) {
|
||||
$this->removeDir($dir);
|
||||
}
|
||||
$this->rebuildSearchIndex();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// Index de recherche (fichier plat)
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
/**
|
||||
* Reconstruit search_index.json à partir de tous les articles.
|
||||
* Appelé automatiquement après chaque create/update/delete.
|
||||
*/
|
||||
public function rebuildSearchIndex(): void
|
||||
{
|
||||
$index = [];
|
||||
foreach ($this->getAll() as $article) {
|
||||
$index[] = [
|
||||
'uuid' => $article['uuid'],
|
||||
'slug' => $article['slug'] ?? '',
|
||||
'title' => $article['title'] ?? '',
|
||||
'category' => $article['category'] ?? '',
|
||||
'published' => $article['published'],
|
||||
'published_at' => $article['published_at'] ?? '',
|
||||
'updated_at' => $article['updated_at'] ?? '',
|
||||
'plain' => $this->stripForIndex($article['content'] ?? ''),
|
||||
];
|
||||
}
|
||||
file_put_contents(
|
||||
$this->dataDir . '/search_index.json',
|
||||
json_encode($index, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
|
||||
/** Retourne l'index pré-construit, ou null s'il n'existe pas encore. */
|
||||
public function getSearchIndex(): ?array
|
||||
{
|
||||
$path = $this->dataDir . '/search_index.json';
|
||||
if (!file_exists($path)) {
|
||||
return null;
|
||||
}
|
||||
$data = json_decode((string) file_get_contents($path), true);
|
||||
return is_array($data) ? $data : null;
|
||||
}
|
||||
|
||||
/** Retire la syntaxe Markdown pour stocker du texte brut dans l'index. */
|
||||
private function stripForIndex(string $md): string
|
||||
{
|
||||
$t = preg_replace('/!\[[^\]]*\]\([^)]+\)/', '', $md) ?? $md;
|
||||
$t = preg_replace('/\[([^\]]+)\]\([^)]+\)/', '$1', $t) ?? $t;
|
||||
$t = preg_replace('/```[\s\S]*?```/', '', $t) ?? $t;
|
||||
$t = preg_replace('/`[^`]+`/', '', $t) ?? $t;
|
||||
$t = preg_replace('/^#{1,6}\s*/m', '', $t) ?? $t;
|
||||
$t = preg_replace('/[*_~]{1,3}([^*_~]+)[*_~]{1,3}/', '$1', $t) ?? $t;
|
||||
$t = preg_replace('/^\s*[-*+|>]\s*/m', '', $t) ?? $t;
|
||||
$t = preg_replace('/\n{2,}/', ' ', $t) ?? $t;
|
||||
return trim($t);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
@@ -37,7 +37,8 @@ class SearchEngine
|
||||
|
||||
$results = [];
|
||||
foreach ($articles as $article) {
|
||||
$plain = $this->stripMarkdown($article['content'] ?? '');
|
||||
// 'plain' est pré-calculé dans search_index.json, sinon on stripe à la volée
|
||||
$plain = $article['plain'] ?? $this->stripMarkdown($article['content'] ?? '');
|
||||
$tWords = $this->tokenize($article['title'] ?? '');
|
||||
$cWords = $this->tokenize($article['category'] ?? '');
|
||||
$pWords = $this->tokenize($plain);
|
||||
|
||||
Reference in New Issue
Block a user