132 lines
3.6 KiB
PHP
132 lines
3.6 KiB
PHP
<?php
|
|||
|
|
// Shared helper functions for the FlixCooks food blog.
|
||
|
|
|
||
|
|
function load_recipes(): array {
|
||
|
|
$path = __DIR__ . '/data/recipes.json';
|
||
|
|
if (!file_exists($path)) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
$json = file_get_contents($path);
|
||
|
|
$data = json_decode($json, true);
|
||
|
|
if (!is_array($data)) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($data as &$recipe) {
|
||
|
|
if (!empty($recipe['hero']) && is_string($recipe['hero'])) {
|
||
|
|
$recipe['hero'] = normalize_asset_path($recipe['hero']);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
unset($recipe);
|
||
|
|
|
||
|
|
return $data;
|
||
|
|
}
|
||
|
|
|
||
|
|
function save_recipes(array $recipes): bool {
|
||
|
|
$path = __DIR__ . '/data/recipes.json';
|
||
|
|
$json = json_encode($recipes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||
|
|
return (bool) file_put_contents($path, $json);
|
||
|
|
}
|
||
|
|
|
||
|
|
function slugify(string $text): string {
|
||
|
|
$text = strtolower($text);
|
||
|
|
$text = preg_replace('~[^a-z0-9]+~', '-', $text);
|
||
|
|
$text = trim($text, '-');
|
||
|
|
return $text ?: uniqid('recipe-');
|
||
|
|
}
|
||
|
|
|
||
|
|
function find_recipe_by_slug(array $recipes, string $slug): ?array {
|
||
|
|
foreach ($recipes as $recipe) {
|
||
|
|
if (($recipe['slug'] ?? '') === $slug) {
|
||
|
|
return $recipe;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function localize_recipe(array $recipe, string $lang): array {
|
||
|
|
$localized = $recipe;
|
||
|
|
$i18n = $recipe['i18n'][$lang] ?? ($recipe['i18n']['en'] ?? []);
|
||
|
|
foreach ($i18n as $key => $value) {
|
||
|
|
$localized[$key] = $value;
|
||
|
|
}
|
||
|
|
return $localized;
|
||
|
|
}
|
||
|
|
|
||
|
|
function localize_recipes(array $recipes, string $lang): array {
|
||
|
|
return array_map(function ($recipe) use ($lang) {
|
||
|
|
return localize_recipe($recipe, $lang);
|
||
|
|
}, $recipes);
|
||
|
|
}
|
||
|
|
|
||
|
|
function filter_recipes(array $recipes, ?string $query = null, ?string $tag = null, string $lang = 'en'): array {
|
||
|
|
$query = $query ? strtolower($query) : null;
|
||
|
|
$tag = $tag ? strtolower($tag) : null;
|
||
|
|
|
||
|
|
$localized = localize_recipes($recipes, $lang);
|
||
|
|
|
||
|
|
return array_values(array_filter($localized, function ($recipe) use ($query, $tag) {
|
||
|
|
$matchesQuery = true;
|
||
|
|
if ($query) {
|
||
|
|
$haystack = strtolower(($recipe['title'] ?? '') . ' ' . ($recipe['description'] ?? ''));
|
||
|
|
$matchesQuery = strpos($haystack, $query) !== false;
|
||
|
|
}
|
||
|
|
|
||
|
|
$matchesTag = true;
|
||
|
|
if ($tag) {
|
||
|
|
$tags = array_map('strtolower', $recipe['tags'] ?? []);
|
||
|
|
$matchesTag = in_array($tag, $tags, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $matchesQuery && $matchesTag;
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
|
||
|
|
function format_minutes(int $minutes): string {
|
||
|
|
if ($minutes < 60) {
|
||
|
|
return $minutes . ' min';
|
||
|
|
}
|
||
|
|
$hours = intdiv($minutes, 60);
|
||
|
|
$mins = $minutes % 60;
|
||
|
|
return $hours . ' hr' . ($hours > 1 ? 's ' : ' ') . ($mins ? $mins . ' min' : '');
|
||
|
|
}
|
||
|
|
|
||
|
|
function e(?string $value): string {
|
||
|
|
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
||
|
|
}
|
||
|
|
|
||
|
|
function normalize_asset_path(string $path): string {
|
||
|
|
if (!str_starts_with($path, '/assets/')) {
|
||
|
|
return $path;
|
||
|
|
}
|
||
|
|
|
||
|
|
$absolute = __DIR__ . $path;
|
||
|
|
if (file_exists($absolute)) {
|
||
|
|
return $path;
|
||
|
|
}
|
||
|
|
|
||
|
|
$dir = dirname($absolute);
|
||
|
|
$target = basename($absolute);
|
||
|
|
if (!is_dir($dir)) {
|
||
|
|
return $path;
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (scandir($dir) ?: [] as $entry) {
|
||
|
|
if (strcasecmp($entry, $target) === 0) {
|
||
|
|
return rtrim(dirname($path), '/') . '/' . $entry;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $path;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Build a URL to the current path with a specific language parameter, preserving other query params.
|
||
|
|
*/
|
||
|
|
function lang_url(string $lang): string {
|
||
|
|
$params = $_GET;
|
||
|
|
$params['lang'] = $lang;
|
||
|
|
$path = strtok($_SERVER['REQUEST_URI'], '?') ?: '/';
|
||
|
|
return $path . '?' . http_build_query($params);
|
||
|
|
}
|