145 Zeilen
5,1 KiB
PHP
145 Zeilen
5,1 KiB
PHP
<?php
|
|
/**
|
|
* Content Import - reads Markdown files from content/ and upserts into DB.
|
|
*/
|
|
|
|
function import_all_content($pdo) {
|
|
$stats = ['decks' => 0, 'cards' => 0, 'tutorials' => 0, 'cheatsheets' => 0];
|
|
|
|
$flashcard_dir = CONTENT_DIR . '/flashcards';
|
|
if (is_dir($flashcard_dir)) {
|
|
$sort = 0;
|
|
foreach (glob($flashcard_dir . '/deck-*.md') as $file) {
|
|
$count = import_flashcard_deck($pdo, $file, $sort++);
|
|
$stats['decks']++;
|
|
$stats['cards'] += $count;
|
|
}
|
|
}
|
|
|
|
$tutorial_dir = CONTENT_DIR . '/tutorials';
|
|
if (is_dir($tutorial_dir)) {
|
|
$sort = 0;
|
|
foreach (glob($tutorial_dir . '/*.md') as $file) {
|
|
$basename = basename($file);
|
|
if ($basename === 'onboarding-path.md' || $basename === 'progress.md') continue;
|
|
import_tutorial($pdo, $file, $sort++);
|
|
$stats['tutorials']++;
|
|
}
|
|
}
|
|
|
|
$cheatsheet_dir = CONTENT_DIR . '/cheatsheets';
|
|
if (is_dir($cheatsheet_dir)) {
|
|
foreach (glob($cheatsheet_dir . '/*-cheatsheet.md') as $file) {
|
|
import_cheatsheet($pdo, $file);
|
|
$stats['cheatsheets']++;
|
|
}
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
|
|
function import_flashcard_deck($pdo, $filepath, $deck_sort) {
|
|
$content = file_get_contents($filepath);
|
|
$basename = basename($filepath);
|
|
|
|
preg_match('/^# Flashcard Deck: (.+)$/m', $content, $m);
|
|
$deck_name = $m[1] ?? str_replace(['deck-', '.md'], '', $basename);
|
|
$slug = slugify($deck_name);
|
|
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO decks (slug, name, sort_order, source_file, updated_at)
|
|
VALUES (:slug, :name, :sort, :src, NOW())
|
|
ON CONFLICT (slug) DO UPDATE SET name = :name, sort_order = :sort, source_file = :src, updated_at = NOW()
|
|
RETURNING id
|
|
");
|
|
$stmt->execute([':slug' => $slug, ':name' => $deck_name, ':sort' => $deck_sort, ':src' => $basename]);
|
|
$deck_id = $stmt->fetchColumn();
|
|
|
|
// Parse cards
|
|
preg_match_all(
|
|
'/## Karte (\d+) \| (\w+)\s*\n\*\*Q:\*\*\s*(.+?)(?:\n)\*\*A:\*\*\s*(.+?)(?=\n---|\n## Karte|\n## Spaced|\Z)/s',
|
|
$content, $matches, PREG_SET_ORDER
|
|
);
|
|
|
|
// Delete old cards for this deck, then re-insert
|
|
$pdo->prepare("DELETE FROM cards WHERE deck_id = :did")->execute([':did' => $deck_id]);
|
|
|
|
$card_count = 0;
|
|
foreach ($matches as $i => $match) {
|
|
$level = strtolower(trim($match[2]));
|
|
$question = trim($match[3]);
|
|
$answer = trim($match[4]);
|
|
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO cards (deck_id, question, answer, level, sort_order, source_file)
|
|
VALUES (:did, :q, :a, :lvl, :sort, :src)
|
|
");
|
|
$stmt->execute([
|
|
':did' => $deck_id, ':q' => $question, ':a' => $answer,
|
|
':lvl' => $level, ':sort' => $i, ':src' => $basename
|
|
]);
|
|
$card_count++;
|
|
}
|
|
|
|
$pdo->prepare("UPDATE decks SET card_count = :c WHERE id = :id")
|
|
->execute([':c' => $card_count, ':id' => $deck_id]);
|
|
|
|
return $card_count;
|
|
}
|
|
|
|
function import_tutorial($pdo, $filepath, $sort_order) {
|
|
$content = file_get_contents($filepath);
|
|
$basename = basename($filepath);
|
|
|
|
preg_match('/^# (.+)$/m', $content, $m);
|
|
$title = $m[1] ?? str_replace('.md', '', $basename);
|
|
$slug = slugify($basename);
|
|
|
|
preg_match('/\*\*Dauer\*\*:\s*ca\.\s*(\d+)/i', $content, $dm);
|
|
$duration = $dm[1] ?? null;
|
|
|
|
preg_match('/\*\*Ziel\*\*:\s*(.+)$/m', $content, $desc);
|
|
$description = $desc[1] ?? '';
|
|
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO tutorials (slug, title, description, content_md, duration_min, sort_order, source_file, updated_at)
|
|
VALUES (:slug, :title, :desc, :content, :dur, :sort, :src, NOW())
|
|
ON CONFLICT (slug) DO UPDATE SET
|
|
title = :title, description = :desc, content_md = :content,
|
|
duration_min = :dur, sort_order = :sort, source_file = :src, updated_at = NOW()
|
|
");
|
|
$stmt->execute([
|
|
':slug' => $slug, ':title' => $title, ':desc' => $description,
|
|
':content' => $content, ':dur' => $duration,
|
|
':sort' => $sort_order, ':src' => $basename
|
|
]);
|
|
}
|
|
|
|
function import_cheatsheet($pdo, $filepath) {
|
|
$content = file_get_contents($filepath);
|
|
$basename = basename($filepath);
|
|
|
|
preg_match('/^# (.+)$/m', $content, $m);
|
|
$title = $m[1] ?? str_replace(['-cheatsheet', '.md'], ['', ''], $basename);
|
|
$slug = slugify($basename);
|
|
$category = ucfirst(str_replace(['-cheatsheet.md', '-'], ['', ' '], $basename));
|
|
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO cheatsheets (slug, title, category, content_md, source_file, updated_at)
|
|
VALUES (:slug, :title, :cat, :content, :src, NOW())
|
|
ON CONFLICT (slug) DO UPDATE SET
|
|
title = :title, category = :cat, content_md = :content, source_file = :src, updated_at = NOW()
|
|
");
|
|
$stmt->execute([
|
|
':slug' => $slug, ':title' => $title, ':cat' => $category,
|
|
':content' => $content, ':src' => $basename
|
|
]);
|
|
}
|
|
|
|
function slugify($text) {
|
|
$text = str_replace(['.md', 'deck-'], '', $text);
|
|
$text = strtolower($text);
|
|
$text = preg_replace('/[^a-z0-9\-]/', '-', $text);
|
|
$text = preg_replace('/-+/', '-', $text);
|
|
return trim($text, '-');
|
|
}
|