$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 <<
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;
}