Initial commit: 교육 프로젝트 배포

This commit is contained in:
송대일
2026-07-01 18:32:42 +09:00
commit be6dccd120
1483 changed files with 5082202 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/../db_conn.php';
require_once __DIR__ . '/common.php';
$sessionUser = api_get_session_user();
$memberId = (string)($sessionUser['member_id'] ?? $_SESSION['member_id'] ?? '');
$sysCompCode = (string)($sessionUser['sys_comp_code'] ?? $_SESSION['sys_comp_code'] ?? '');
if ($memberId === '' || $sysCompCode === '') {
http_response_code(401);
echo json_encode(['success' => false, 'message' => 'not_logged_in'], JSON_UNESCAPED_UNICODE);
exit;
}
try {
$pdo = db_conn();
$onboardingGroups = [
'CA200O01', 'CA200O02', 'CA200O03', 'CA200O04', 'CA200O05',
'CA200O06', 'CA200O07', 'CA200O08', 'CA200O09', 'CA200O10',
];
$placeholders = implode(',', array_fill(0, count($onboardingGroups), '?'));
$categoryMap = [
'CA200O01' => ['pieceId' => 1, 'group' => 3, 'area' => 'value'],
'CA200O02' => ['pieceId' => 2, 'group' => 2, 'area' => 'hanmac'],
'CA200O03' => ['pieceId' => 3, 'group' => 2, 'area' => 'hanmac'],
'CA200O04' => ['pieceId' => 4, 'group' => 2, 'area' => 'hanmac'],
'CA200O05' => ['pieceId' => 5, 'group' => 2, 'area' => 'hanmac'],
'CA200O06' => ['pieceId' => 6, 'group' => 3, 'area' => 'value'],
'CA200O07' => ['pieceId' => 7, 'group' => 4, 'area' => 'company'],
'CA200O08' => ['pieceId' => 8, 'group' => 4, 'area' => 'company'],
'CA200O09' => ['pieceId' => 9, 'group' => 1, 'area' => 'family'],
'CA200O10' => ['pieceId' => 10, 'group' => 1, 'area' => 'family'],
];
$chapterNameMap = [];
try {
$stmtCodes = $pdo->prepare("\n SELECT base_code, code_name\n FROM edu_codes\n WHERE group_code = 'CA200'\n AND base_code IN ('CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10')\n ORDER BY base_code\n ");
$stmtCodes->execute();
foreach (($stmtCodes->fetchAll(PDO::FETCH_ASSOC) ?: []) as $codeRow) {
$baseCode = (string)($codeRow['base_code'] ?? '');
$codeName = trim((string)($codeRow['code_name'] ?? ''));
if ($baseCode !== '' && $codeName !== '') {
$chapterNameMap[$baseCode] = $codeName;
}
}
} catch (Throwable $e) {
// 코드명 조회 실패 시 콘텐츠 제목으로 폴백한다.
}
$useContentHistories = true;
try {
$checkTable = $pdo->query("SHOW TABLES LIKE 'edu_content_histories'");
if (!$checkTable || $checkTable->rowCount() === 0) {
$useContentHistories = false;
}
} catch (Throwable $e) {
$useContentHistories = false;
}
if ($useContentHistories) {
try {
$stmt = $pdo->prepare("\n SELECT\n c.*,\n COALESCE(lh.watch_tm, 0) AS watch_tm,\n COALESCE(lh.content_tm, 0) AS content_tm,\n lh.completed_at AS lh_completed_at,\n CASE\n WHEN ch.content_id IS NULL THEN 'none'\n WHEN ch.completed_at IS NOT NULL THEN 'completed'\n ELSE 'in_progress'\n END AS learning_status\n FROM edu_contents c\n LEFT JOIN edu_learning_histories lh\n ON lh.content_id = c.content_id\n AND lh.member_id = ?\n AND lh.sys_comp_code = ?\n LEFT JOIN edu_content_histories ch\n ON ch.content_id = c.content_id\n AND ch.member_id = ?\n AND ch.sys_comp_code = ?\n WHERE c.category_group IN ($placeholders)\n ORDER BY FIELD(c.category_group, 'CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10'), COALESCE(NULLIF(c.sort_order, 0), 9999), c.content_id\n ");
$stmt->execute(array_merge([$memberId, $sysCompCode, $memberId, $sysCompCode], $onboardingGroups));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
$useContentHistories = false;
}
}
if (!$useContentHistories) {
$stmt = $pdo->prepare("\n SELECT\n c.*,\n COALESCE(lh.watch_tm, 0) AS watch_tm,\n COALESCE(lh.content_tm, 0) AS content_tm,\n lh.completed_at AS lh_completed_at,\n CASE\n WHEN lh.content_id IS NULL THEN 'none'\n WHEN lh.completed_at IS NOT NULL THEN 'completed'\n ELSE 'in_progress'\n END AS learning_status\n FROM edu_contents c\n LEFT JOIN edu_learning_histories lh\n ON lh.content_id = c.content_id\n AND lh.member_id = ?\n AND lh.sys_comp_code = ?\n WHERE c.category_group IN ($placeholders)\n ORDER BY FIELD(c.category_group, 'CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10'), COALESCE(NULLIF(c.sort_order, 0), 9999), c.content_id\n ");
$stmt->execute(array_merge([$memberId, $sysCompCode], $onboardingGroups));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
}
$chapterMap = [];
foreach ($rows as $index => $row) {
$categoryGroup = (string)($row['category_group'] ?? '');
if ($categoryGroup === '') {
continue;
}
$mapped = $categoryMap[$categoryGroup] ?? null;
$description = trim((string)($row['description'] ?? $row['description1'] ?? $row['description_1'] ?? $row['content_desc'] ?? $row['content_desc1'] ?? $row['content_description'] ?? $row['content_description1'] ?? ''));
$description2 = trim((string)($row['description2'] ?? $row['description_2'] ?? $row['content_desc2'] ?? $row['content_description2'] ?? ''));
if (!isset($chapterMap[$categoryGroup])) {
$chapterMap[$categoryGroup] = [
'id' => 0,
'name' => $chapterNameMap[$categoryGroup] ?? str_replace('[온보딩] ', '', (string)($row['title'] ?? '')),
'pieceId' => (int)($mapped['pieceId'] ?? ($index + 1)),
'type' => 'youtube',
'group' => (int)($mapped['group'] ?? 1),
'category_group' => $categoryGroup,
'area' => (string)($mapped['area'] ?? 'family'),
'lessons' => [],
];
}
$learningStatus = (string)($row['learning_status'] ?? 'none');
$chapterMap[$categoryGroup]['lessons'][] = [
'content_id' => (string)($row['content_id'] ?? ''),
'bookmark_content_id' => (string)($row['content_id'] ?? ''),
'comment_content_id' => (string)($row['content_id'] ?? ''),
'title' => (string)($row['title'] ?? ''),
'label' => str_replace('[온보딩] ', '', (string)($row['title'] ?? '')),
'description' => $description,
'description2' => $description2,
'url' => (string)($row['content_url'] ?? ''),
'completed' => ($learningStatus === 'completed'),
'learning_status' => $learningStatus,
'watch_tm' => (int)($row['watch_tm'] ?? 0),
'content_tm' => (int)($row['content_tm'] ?? 0),
'sort_order' => (int)($row['sort_order'] ?? 0),
'is_bookmarked' => false,
];
}
$bookmarkIds = [];
foreach ($chapterMap as $chapterItem) {
foreach (($chapterItem['lessons'] ?? []) as $lessonItem) {
$bookmarkId = trim((string)($lessonItem['bookmark_content_id'] ?? ''));
if ($bookmarkId !== '') {
$bookmarkIds[] = $bookmarkId;
}
}
}
$bookmarkIds = array_values(array_unique($bookmarkIds));
$wishlistMap = [];
if (!empty($bookmarkIds)) {
$wishlistPlaceholders = implode(',', array_fill(0, count($bookmarkIds), '?'));
$stmtWishlist = $pdo->prepare(
"SELECT content_id, is_active\n FROM edu_content_wishlist\n WHERE member_id = ?\n AND sys_comp_code = ?\n AND content_id IN ($wishlistPlaceholders)"
);
$stmtWishlist->execute(array_merge([$memberId, $sysCompCode], $bookmarkIds));
foreach (($stmtWishlist->fetchAll(PDO::FETCH_ASSOC) ?: []) as $wishlistRow) {
$wishlistMap[(string)$wishlistRow['content_id']] = ((string)($wishlistRow['is_active'] ?? '0') === '1');
}
}
$chapters = [];
foreach ($onboardingGroups as $groupCode) {
if (!isset($chapterMap[$groupCode])) {
continue;
}
$chapter = $chapterMap[$groupCode];
usort($chapter['lessons'], static function ($left, $right) {
$sortDiff = (int)($left['sort_order'] ?? 0) <=> (int)($right['sort_order'] ?? 0);
if ($sortDiff !== 0) {
return $sortDiff;
}
return strcmp((string)($left['content_id'] ?? ''), (string)($right['content_id'] ?? ''));
});
$chapter['id'] = count($chapters) + 1;
$chapter['lessons'] = array_map(static function ($lesson) use ($wishlistMap) {
$bookmarkId = trim((string)($lesson['bookmark_content_id'] ?? ''));
$lesson['is_bookmarked'] = ($bookmarkId !== '' && !empty($wishlistMap[$bookmarkId]));
unset($lesson['sort_order']);
return $lesson;
}, $chapter['lessons']);
$chapters[] = $chapter;
}
echo json_encode([
'success' => true,
'chapters' => $chapters,
], JSON_UNESCAPED_UNICODE);
} catch (Throwable $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'server_error',
], JSON_UNESCAPED_UNICODE);
}