$p['category'] === $category); } /** * Récupère un projet par son slug * @param string $slug Slug du projet * @return array|null Projet ou null si non trouvé */ function getProjectBySlug(string $slug): ?array { $projects = getProjects(); foreach ($projects as $project) { if ($project['slug'] === $slug) { return $project; } } return null; } /** * Récupère les technologies uniques de tous les projets * @return array Liste triée des technologies */ function getAllTechnologies(): array { $technologies = []; foreach (getProjects() as $project) { foreach ($project['technologies'] ?? [] as $tech) { if (!in_array($tech, $technologies)) { $technologies[] = $tech; } } } sort($technologies); return $technologies; } /** * Génère le HTML pour une image projet optimisée * Utilise pour WebP avec fallback JPG * * @param string $filename Nom du fichier image (ex: project-thumb.webp) * @param string $alt Texte alternatif * @param int $width Largeur en pixels * @param int $height Hauteur en pixels * @param bool $lazy Activer le lazy loading (défaut: true) * @param string $class Classes CSS additionnelles * @return string HTML de l'image */ function projectImage(string $filename, string $alt, int $width, int $height, bool $lazy = true, string $class = ''): string { $alt = htmlspecialchars($alt, ENT_QUOTES, 'UTF-8'); $class = htmlspecialchars($class, ENT_QUOTES, 'UTF-8'); $lazyAttr = $lazy ? 'loading="lazy"' : ''; // Détermine les chemins WebP et fallback $basePath = '/assets/img/projects/'; $webpFile = $filename; // Si le fichier n'est pas .webp, on essaie de trouver la version .webp if (!str_ends_with($filename, '.webp')) { $webpFile = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $filename); } // Fallback: remplace .webp par .jpg $fallbackFile = str_replace('.webp', '.jpg', $webpFile); // Image par défaut si fichier manquant $defaultImage = $basePath . 'default-project.svg'; return << {$alt} HTML; } /** * Compte les projets par technologie * @return array Tableau associatif [technologie => nombre] */ function getProjectCountByTech(): array { $projects = getProjects(); $count = []; foreach ($projects as $project) { foreach ($project['technologies'] ?? [] as $tech) { $count[$tech] = ($count[$tech] ?? 0) + 1; } } return $count; } /** * Récupère les projets utilisant une technologie * @param string $tech Nom de la technologie * @return array Projets filtrés */ function getProjectsByTech(string $tech): array { return array_filter(getProjects(), function($project) use ($tech) { return in_array($tech, $project['technologies'] ?? []); }); } /** * Retourne l'icône SVG d'un outil * @param string $icon Identifiant de l'outil * @return string SVG de l'icône */ function getToolIcon(string $icon): string { $icons = [ 'github' => '', 'vscode' => '', 'figma' => '', 'notion' => '', 'docker' => '', 'linux' => '', ]; return $icons[$icon] ?? ''; } /** * Récupère tous les témoignages * @return array Liste des témoignages */ function getTestimonials(): array { $data = loadJsonData('testimonials.json'); return $data['testimonials'] ?? []; } /** * Récupère les témoignages mis en avant * @return array Témoignages avec featured = true */ function getFeaturedTestimonials(): array { return array_filter(getTestimonials(), fn($t) => ($t['featured'] ?? false) === true); } /** * Récupère le témoignage lié à un projet * @param string $projectSlug Slug du projet * @return array|null Témoignage ou null si non trouvé */ function getTestimonialByProject(string $projectSlug): ?array { foreach (getTestimonials() as $testimonial) { if (($testimonial['project_slug'] ?? '') === $projectSlug) { return $testimonial; } } return null; }