| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- <?php
- // Αρχείο: /var/www/html/hockey-cms/index.php
- if (session_status() === PHP_SESSION_NONE) { session_start(); }
- require_once __DIR__ . '/vendor/autoload.php';
- require_once __DIR__ . '/config/database.php';
- // --- Μηχανισμός Αλλαγής Γλώσσας (Language Switcher) ---
- if (isset($_GET['lang']) && in_array($_GET['lang'], ['el', 'en'])) {
- $_SESSION['lang'] =$_GET['lang'];
- }
- $current_lang =$_SESSION['lang'] ?? 'el';
- // --- Εντοπισμός Ενεργού Theme ---
- $active_theme = 'default';
- try {
- $stmt =$pdo->query("SELECT value FROM settings WHERE `key` = 'active_theme'");
- $res =$stmt->fetchColumn();
- if ($res) { $active_theme =$res; }
- } catch (Exception $e) {}
- $theme_dir = __DIR__ . '/themes/' .$active_theme;
- if (!is_dir($theme_dir)) {
- $active_theme = 'default';$theme_dir = __DIR__ . '/themes/default';
- }
- // --- Αρχικοποίηση Twig ---
- $loader = new \Twig\Loader\FilesystemLoader($theme_dir);
- $twig = new \Twig\Environment($loader, ['cache' => false]);
- $twig->addGlobal('session',$_SESSION);
- $twig->addGlobal('current_lang',$current_lang);
- // --- Φόρτωση Δυναμικών Κειμένων Site ---
- $siteTexts = [];
- try {
- $text_column = ($current_lang === 'en') ? 'text_value_en' : 'text_value_el';
- $textsStmt =$pdo->query("SELECT text_key, {$text_column} as text_value FROM site_texts");
-
- while ($row = $textsStmt->fetch(PDO::FETCH_ASSOC)) {$siteTexts[$row['text_key']] =$row['text_value'];
- }
- } catch (Exception $e) {}
- $twig->addGlobal('text',$siteTexts);
- // --- Φόρτωση Logo Site ---
- $site_logo = '';
- try {
- $logoStmt =$pdo->prepare("SELECT value FROM settings WHERE `key` = 'site_logo'");
- $logoStmt->execute();
- $site_logo =$logoStmt->fetchColumn();
- } catch (Exception $e) {}
- $twig->addGlobal('site_logo',$site_logo);
- try {
- // --- Φόρτωση Κατηγοριών ---
- $categoriesRaw =$pdo->query("SELECT * FROM categories ORDER BY sort_order ASC, name_el ASC")->fetchAll(PDO::FETCH_ASSOC);
-
- $categories = [];
- foreach ($categoriesRaw as $cat) {$cat['display_name'] = ($current_lang === 'en' && !empty($cat['name_en'])) ? $cat['name_en'] :$cat['name_el'];
- $categories[] =$cat;
- }
-
- // --- Λήψη Παραμέτρων Φίλτρων & ΣΕΛΙΔΟΠΟΙΗΣΗΣ ---
- $category_id = isset($_GET['category_id']) ? (int)$_GET['category_id'] : 0;
- $sort = isset($_GET['sort']) ?$_GET['sort'] : 'newest';
- $min_price = (isset($_GET['min_price']) && is_numeric($_GET['min_price'])) ? (float)$_GET['min_price'] : null;
- $max_price = (isset($_GET['max_price']) && is_numeric($_GET['max_price'])) ? (float)$_GET['max_price'] : null;
- $search_query = isset($_GET['q']) ? trim($_GET['q']) : '';
- // Παράμετροι Σελιδοποίησης
- $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 30;
- if (!in_array($limit, [30, 50, 100])) { $limit = 30; } // Default & Safety$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
- if ($page < 1) {$page = 1; }
- $current_category_name = null;
- $category_attributes = [];
- // --- ΔΙΑΣΠΑΣΗ ΤΟΥ SQL QUERY (Για να μετράμε και το σύνολο) ---
- $sql_select = "SELECT p.id, p.sku, p.title, p.price, p.created_at, pi.image_path";
- $sql_from = " FROM products p LEFT JOIN product_images pi ON (p.id = pi.product_id AND pi.is_primary = 1)";
- $sql_where = " WHERE p.status = 'available'";
- $params = [];
- // 1. Φίλτρο Κατηγορίας
- if ($category_id > 0) {
- $catStmt =$pdo->prepare("SELECT name_el, name_en, attribute_group_id FROM categories WHERE id = ?");
- $catStmt->execute([$category_id]);
- $catData =$catStmt->fetch(PDO::FETCH_ASSOC);
-
- if ($catData) {
- $current_category_name = ($current_lang === 'en' && !empty($catData['name_en'])) ?$catData['name_en'] : $catData['name_el'];$sql_where .= " AND (p.category_id = ? OR p.category_id IN (SELECT id FROM categories WHERE parent_id = ?))";
- $params[] =$category_id;
- $params[] =$category_id;
- if ($catData['attribute_group_id']) {
- $attrStmt =$pdo->prepare("
- SELECT a.id, a.name as name_el, a.name_en, a.unit,
- (SELECT GROUP_CONCAT(DISTINCT value SEPARATOR '||') FROM product_attribute_values WHERE attribute_id = a.id) as distinct_values
- FROM attributes a
- WHERE a.group_id = ?
- ");
- $attrStmt->execute([$catData['attribute_group_id']]);
- $catAttrsRaw =$attrStmt->fetchAll(PDO::FETCH_ASSOC);
-
- foreach ($catAttrsRaw as $a) {$a['display_name'] = ($current_lang === 'en' && !empty($a['name_en'])) ? $a['name_en'] :$a['name_el'];
- $category_attributes[] =$a;
- }
- }
- }
- }
- // 2. Έξυπνο Φίλτρο Αναζήτησης (Βελτιωμένο)
- if ($search_query !== '') {
- $clean_query = preg_replace('/[^\p{L}\p{N}\s\-]/u', ' ',$search_query);
- $words = preg_split('/\s+/', mb_strtolower($clean_query, 'UTF-8'));
- $words = array_filter($words, function($w) { return mb_strlen(trim($w)) > 1; });
- if (!empty($words)) {$whereClauses = [];
- foreach ($words as $word) {$whereClauses[] = "(LOWER(COALESCE(p.sku, '')) LIKE CONCAT('%', ?, '%') OR LOWER(COALESCE(p.title, '')) LIKE CONCAT('%', ?, '%') OR LOWER(COALESCE(p.description, '')) LIKE CONCAT('%', ?, '%') OR LOWER(COALESCE(p.search_tags, '')) LIKE CONCAT('%', ?, '%'))";
- array_push($params, $word,$word, $word,$word);
- }
- $sql_where .= " AND (" . implode(" AND ", $whereClauses) . ")";
- }
- }
- // 3. Φίλτρο Τιμής
- if ($min_price !== null) {$sql_where .= " AND p.price >= ?"; $params[] =$min_price; }
- if ($max_price !== null) {$sql_where .= " AND p.price <= ?"; $params[] =$max_price; }
- // 4. Φίλτρο Δυναμικών Χαρακτηριστικών
- if (isset($_GET['attr']) && is_array($_GET['attr'])) {
- foreach ($_GET['attr'] as $attr_id =>$attr_val) {
- if (!empty($attr_val)) {$sql_where .= " AND EXISTS (SELECT 1 FROM product_attribute_values pav WHERE pav.product_id = p.id AND pav.attribute_id = ? AND pav.value = ?)";
- $params[] = (int)$attr_id;
- $params[] =$attr_val;
- }
- }
- }
- // --- ΜΕΤΡΗΣΗ ΣΥΝΟΛΙΚΩΝ ΠΡΟΪΟΝΤΩΝ ΓΙΑ ΣΕΛΙΔΟΠΟΙΗΣΗ ---
- $countSql = "SELECT COUNT(p.id)" . $sql_from .$sql_where;
- $stmtCount = $pdo->prepare($countSql);
- $stmtCount->execute($params);
- $total_products = (int)$stmtCount->fetchColumn();
- $total_pages = ceil($total_products / $limit);
- if ($page >$total_pages && $total_pages > 0) {$page = $total_pages; }$offset = ($page - 1) *$limit;
- // --- ΤΕΛΙΚΟ QUERY ΠΡΟΪΟΝΤΩΝ ΜΕ ΟΡΙΑ ---
- $sql =$sql_select . $sql_from .$sql_where;
- // 5. Ταξινόμηση
- if ($sort === 'price_asc') {$sql .= " ORDER BY p.price ASC"; }
- elseif ($sort === 'price_desc') {$sql .= " ORDER BY p.price DESC"; }
- else { $sql .= " ORDER BY p.id DESC"; }
- // 6. Προσθήκη Ορίων (Pagination)
- $sql .= " LIMIT " . $limit . " OFFSET " . $offset;
- // Εκτέλεση
- $stmt = $pdo->prepare($sql);
- $stmt->execute($params);
- $products =$stmt->fetchAll(PDO::FETCH_ASSOC);
- // --- ΕΝΣΩΜΑΤΩΣΗ ΧΑΡΑΚΤΗΡΙΣΤΙΚΩΝ ΣΤΑ ΠΡΟΪΟΝΤΑ ---
- if (!empty($products)) {
- $product_ids = array_column($products, 'id');
- $inQuery = implode(',', array_fill(0, count($product_ids), '?'));
-
- $attrValsStmt =$pdo->prepare("
- SELECT pav.product_id, a.name as name_el, a.name_en, a.unit, pav.value
- FROM product_attribute_values pav
- JOIN attributes a ON pav.attribute_id = a.id
- WHERE pav.product_id IN ($inQuery)
- ");
- $attrValsStmt->execute($product_ids);
- $all_attrs =$attrValsStmt->fetchAll(PDO::FETCH_ASSOC);
- $attrs_by_pid = [];
- foreach ($all_attrs as $attr) {$attr_name = ($current_lang === 'en' && !empty($attr['name_en'])) ? $attr['name_en'] :$attr['name_el'];
- $attrs_by_pid[$attr['product_id']][] = [
- 'name' => $attr_name,
- 'value' => $attr['value'],
- 'unit' => $attr['unit']
- ];
- }
- foreach ($products as &$prod) {$prod['attributes'] = $attrs_by_pid[$prod['id']] ?? [];
- }
- unset($prod);
- }
- // --- ΔΗΜΙΟΥΡΓΙΑ BASE URL ΓΙΑ ΤΑ ΚΟΥΜΠΙΑ ΣΕΛΙΔΟΠΟΙΗΣΗΣ ---
- $qs =$_GET;
- unset($qs['page']); // Αφαιρούμε το page για να το βάλει δυναμικά το Twig
- $base_qs = http_build_query($qs);$pagination_url = 'index.php?' . ($base_qs ? $base_qs . '&' : '') . 'page=';
- } catch (Exception $e) {
- die("Σφάλμα ανάγνωσης δεδομένων: " . $e->getMessage());
- }
- echo $twig->render('index.html.twig', [
- 'site_title' => 'Hockey Gear CMS',
- 'categories' => $categories,
- 'products' => $products,
- 'current_category_name' => $current_category_name,
- 'category_id' => $category_id,
- 'category_attributes' => $category_attributes,
- 'search_query' => $search_query,
- 'filters' => $_GET,
- // Νέες μεταβλητές Σελιδοποίησης
- 'current_page' => $page,
- 'total_pages' => $total_pages,
- 'limit' => $limit,
- 'total_products' => $total_products,
- 'pagination_url' => $pagination_url
- ]);
|