PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC] ); $page = max(1, (int)($_GET['page'] ?? 1)); $pageSize = 10; $offset = ($page - 1) * $pageSize; // ===== 필터/검색 파라미터 ===== $writer = $_GET['writer'] ?? 'all'; // all | me $search = trim($_GET['q'] ?? ''); $status = $_GET['status'] ?? 'all'; $allowedStatus = ['new','review','deep','patch','done']; // 복수 구분(cat[]) — general | improvement | error | notice | admin $catsParam = $_GET['cat'] ?? []; if (!is_array($catsParam)) $catsParam = [$catsParam]; $allowedCats = ['general','improvement','error','notice','admin']; $cats = array_values(array_intersect($catsParam, $allowedCats)); // 유효값만 $me = $_SESSION['user']['loginIds'][0] ?? ''; $admin = function_exists('is_qna_admin') ? is_qna_admin() : false; // ===== WHERE 절 ===== $where = ['1']; $params = []; // 작성자(내 글만) if ($writer === 'me' && $me) { $where[] = 'login_id = ?'; $params[] = $me; } // 구분(cat[]) 필터 if (!empty($cats)) { $ph = implode(',', array_fill(0, count($cats), '?')); $where[] = "category IN ($ph)"; foreach ($cats as $c) $params[] = $c; } // 상태(status) 필터 — 관리자만 적용 if ($admin && $status !== 'all' && in_array($status, $allowedStatus, true)) { $where[] = 'status = ?'; $params[] = $status; } // 검색(제목+내용+작성자) if ($search !== '') { $where[] = '(title LIKE ? OR content LIKE ? OR user_name LIKE ? OR login_id LIKE ?)'; $params[] = "%{$search}%"; $params[] = "%{$search}%"; $params[] = "%{$search}%"; $params[] = "%{$search}%"; } // // 비밀글 가드: 관리자는 전체, 일반은 공개 OR 내 글만 // if (!$admin) { // $where[] = '(is_secret = 0 OR login_id = ?)'; // $params[] = $me; // } // ✅ 비밀글 가드 if (!$admin) { if ($me) { $where[] = '(is_secret = 0 OR login_id = ?)'; $params[] = $me; } else { $where[] = 'is_secret = 0'; } } // 전체 건수 $countSql = "SELECT COUNT(*) FROM qa_posts WHERE ".implode(' AND ', $where); $countStmt = $pdo->prepare($countSql); $countStmt->execute($params); $totalCount = (int)$countStmt->fetchColumn(); // 데이터 조회 (공지 상단 고정) $sql = " SELECT p.post_id, p.category, p.company, p.family_company, p.department, p.login_id, p.user_name, p.title, p.created_at, p.status, p.is_secret, p.is_read_admin, -- 댓글 개수 (SELECT COUNT(*) FROM qa_comments c WHERE c.post_id = p.post_id) AS comment_count, -- 첨부파일 개수 (SELECT COUNT(*) FROM qa_attachments a WHERE a.post_id = p.post_id) AS file_count FROM qa_posts p WHERE ".implode(' AND ', $where)." ORDER BY (p.category='notice') DESC, p.created_at DESC LIMIT {$offset}, {$pageSize}"; $stmt = $pdo->prepare($sql); $stmt->execute($params); $posts = $stmt->fetchAll(); foreach ($posts as &$row) { // 회사명 표시 조립 $displayCompany = $row['family_company'] ?: $row['company']; // if (!empty($row['department'])) { // $displayCompany .= ' / ' . $row['department']; // } $row['display_company'] = $displayCompany; // 작성자 이름 $row['display_name'] = get_admin_display_name( $row['login_id'], $row['user_name'] ?: $row['login_id'] ); // 상태값 가공: 공지사항이면 빈칸 if ($row['category'] === 'notice') { $row['status'] = ''; } // ✅ NEW 표시 여부 (24시간 기준) $createdTime = strtotime($row['created_at']); $row['is_new'] = ($createdTime >= strtotime('-24 hours')); } unset($row); $totalPages = (int)ceil($totalCount / $pageSize); // $me = $_SESSION['user']['loginIds'][0] ?? ''; include __DIR__ . '/../skin/qa/basic/descope_qa_list.skin.php';