// 1. Auto-Clean Architecture (SaaS Infrastructure Guard) $junkPatterns = ['fix_', 'test_', 'migration_', '.bak']; $archiveDir = __DIR__ . '/../archive/'; if (!is_dir($archiveDir)) mkdir($archiveDir, 0755, true); foreach (glob(__DIR__ . '/../*.php') as $file) { $filename = basename($file); foreach ($junkPatterns as $p) { if (strpos($filename, $p) !== false && $filename !== 'index.php') { rename($file, $archiveDir . $filename); } } } // 2. Core DB Access require_once __DIR__ . '/../config/database.php'; // 3. Lightweight AI Logic (Internal SEO Engine) function enhanceTextAI($text, $type = 'title') { if (empty($text)) return $text; $text = trim($text); if ($type === 'title') { // AI Logic: SEO keywords injection & Formatting $keywords = ['Luxueux', 'Exclusif', 'Prestige', 'Authentique']; if (!preg_match('/(Marrakech|Villas|Riads)/i', $text)) $text .= ' — Marrakech'; return ucwords(strtolower($text)); } if ($type === 'location') { // AI Logic: Unified Location Format (City, Area, Country) $parts = array_map('trim', explode(',', $text)); if (!in_array('Maroc', $parts)) $parts[] = 'Maroc'; return implode(', ', array_unique($parts)); } return $text; } // 2. Business Logic Execution $id = isset($_GET['id']) ? (int)$_GET['id'] : null; $slug = $_GET['slug'] ?? null; try { if ($slug) { $stmt = $pdo->prepare("SELECT * FROM properties WHERE slug = ?"); $stmt->execute([$slug]); } else { $stmt = $pdo->prepare("SELECT * FROM properties WHERE id = ?"); $stmt->execute([$id ?: 10]); // Default to 10 if nothing provided } $dbProperty = $stmt->fetch(); if ($dbProperty) { $id = $dbProperty['id']; // Update actual ID for sub-queries } } catch (Exception $e) { $dbProperty = null; } // Layer 404: Fail-fast Guard if (!$dbProperty) { http_response_code(404); die("

404

Propriété Introuvable

Retour à l'accueil
"); } // Data Aggregation (Safe fallback) try { // 3. Fetch Images Gallery $stmtImages = $pdo->prepare("SELECT image_url FROM property_images WHERE property_id = ? ORDER BY is_main DESC, id ASC"); $stmtImages->execute([$id]); $dbImages = $stmtImages->fetchAll(PDO::FETCH_COLUMN); // 4. Fetch Amenities $stmtAm = $pdo->prepare("SELECT a.name_fr as name, a.icon FROM amenities a JOIN property_amenities pa ON a.id = pa.amenity_id WHERE pa.property_id = ?"); $stmtAm->execute([$id]); $amenities = $stmtAm->fetchAll(); // 5. Reviews (Fetch from DB) $stmtRev = $pdo->prepare("SELECT r.*, u.name as user_name FROM reviews r LEFT JOIN users u ON r.guest_id = u.id WHERE r.property_id = ? AND r.is_visible = 1 ORDER BY r.created_at DESC"); $stmtRev->execute([$id]); $rawReviews = $stmtRev->fetchAll(); $dbReviews = array_map(function($r) { return [ 'name' => $r['guest_name'] ?: ($r['user_name'] ?: 'Voyageur'), 'rating' => (float)$r['rating_overall'], 'comment' => $r['comment'], 'date' => date('d/m/Y', strtotime($r['created_at'])) ]; }, $rawReviews); } catch (Exception $e) { $dbImages = []; $amenities = []; $dbReviews = []; } // 4. Sanitized Public Schema (Data Sanitization Layer) $property = [ 'id' => (int)$dbProperty['id'], 'title' => enhanceTextAI($dbProperty['title_fr'] ?? $dbProperty['name'], 'title'), 'price' => (float)($dbProperty['price_per_night'] ?? 0), 'old_price' => (float)($dbProperty['base_price'] ?? 0), 'description' => $dbProperty['description_fr'] ?? 'Un séjour d\'exception vous attend.', 'location' => enhanceTextAI($dbProperty['location_fr'] ?? 'Marrakech', 'location'), 'rating' => 4.95, 'images' => !empty($dbImages) ? array_map(function($path) { return (strpos($path, 'http') === 0) ? $path : rtrim(SITE_URL, '/') . '/' . ltrim($path, '/'); }, $dbImages) : ['/images/placeholder.webp'], 'amenities' => array_map(function($a) { return ['name' => htmlspecialchars($a['name']), 'icon' => htmlspecialchars($a['icon'])]; }, $amenities), 'reviews' => array_map(function($r) { return [ 'guest_name' => htmlspecialchars($r['guest_name'] ?: ($r['user_name'] ?: 'Voyageur')), 'rating_overall' => (float)$r['rating_overall'], 'comment' => htmlspecialchars($r['comment']), 'verified_stay' => (int)$r['verified_stay'] ]; }, $dbReviews), 'tax_amount' => (float)($dbProperty['tourist_tax_amount'] ?? 26), 'bf_price' => (float)($dbProperty['breakfast_price'] ?? 0), 'bf_mode' => $dbProperty['breakfast_mode'] ?? 'none' ]; // --- 🚀 PERFORMANCE LAYER: PRE-RENDER HERO --- $mainImg = !empty($dbImages) ? (strpos($dbImages[0], 'http') === 0 ? $dbImages[0] : rtrim(SITE_URL, '/') . '/' . ltrim($dbImages[0], '/')) : 'https://marrakechstyle-immo.com/images/slide-1.webp'; ?>
{/* React will mount here and take over interactivity */}