Initial profile site commit
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
require_once __DIR__ . '/error_config.php';
|
||||
session_start();
|
||||
set_json_headers();
|
||||
|
||||
define('CATEGORIES_FILE', DATA_DIR . '/categories.json');
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
// 카테고리 정규화 (parent_id 필드 보장)
|
||||
function normalize_category($cat) {
|
||||
if (!isset($cat['parent_id'])) $cat['parent_id'] = null;
|
||||
if (!isset($cat['order'])) $cat['order'] = 0;
|
||||
if (!isset($cat['color'])) $cat['color'] = '#00f2ff';
|
||||
return $cat;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// GET: 카테고리 목록
|
||||
// =====================================================
|
||||
if ($method === 'GET') {
|
||||
$categories = read_json_safe(CATEGORIES_FILE) ?? [];
|
||||
$categories = array_map('normalize_category', $categories);
|
||||
|
||||
usort($categories, function($a, $b) {
|
||||
// parent끼리 먼저 정렬되도록
|
||||
$aParent = $a['parent_id'] ?? 0;
|
||||
$bParent = $b['parent_id'] ?? 0;
|
||||
if ($aParent !== $bParent) return $aParent - $bParent;
|
||||
return ($a['order'] ?? 0) - ($b['order'] ?? 0);
|
||||
});
|
||||
|
||||
json_response($categories);
|
||||
}
|
||||
|
||||
require_auth();
|
||||
|
||||
// =====================================================
|
||||
// POST: 카테고리 추가
|
||||
// =====================================================
|
||||
if ($method === 'POST') {
|
||||
$input = get_json_input();
|
||||
$name = trim($input['name'] ?? '');
|
||||
$color = trim($input['color'] ?? '#00f2ff');
|
||||
$parentId = isset($input['parent_id']) && $input['parent_id'] !== '' && $input['parent_id'] !== null
|
||||
? intval($input['parent_id'])
|
||||
: null;
|
||||
|
||||
if (empty($name)) {
|
||||
json_response(['error' => '카테고리 이름은 필수입니다'], 400);
|
||||
}
|
||||
|
||||
$categories = read_json_safe(CATEGORIES_FILE) ?? [];
|
||||
|
||||
// parent_id 유효성 검증
|
||||
if ($parentId !== null) {
|
||||
$parentFound = false;
|
||||
foreach ($categories as $c) {
|
||||
if (($c['id'] ?? 0) === $parentId) {
|
||||
// 부모가 또 다른 부모를 가지면 안 됨 (2단계로 제한)
|
||||
if (!empty($c['parent_id'])) {
|
||||
json_response(['error' => '서브 카테고리 아래에는 카테고리를 만들 수 없습니다'], 400);
|
||||
}
|
||||
$parentFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$parentFound) {
|
||||
json_response(['error' => '부모 카테고리를 찾을 수 없습니다'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
$maxId = 0;
|
||||
$maxOrder = 0;
|
||||
foreach ($categories as $c) {
|
||||
if (($c['id'] ?? 0) > $maxId) $maxId = $c['id'];
|
||||
// 같은 부모 내에서 max order
|
||||
if (($c['parent_id'] ?? null) === $parentId && ($c['order'] ?? 0) > $maxOrder) {
|
||||
$maxOrder = $c['order'];
|
||||
}
|
||||
}
|
||||
|
||||
$newCategory = [
|
||||
'id' => $maxId + 1,
|
||||
'name' => $name,
|
||||
'color' => $color,
|
||||
'parent_id' => $parentId,
|
||||
'order' => $maxOrder + 1
|
||||
];
|
||||
|
||||
$categories[] = $newCategory;
|
||||
|
||||
if (write_json_safe(CATEGORIES_FILE, $categories)) {
|
||||
json_response(['success' => true, 'category' => $newCategory]);
|
||||
} else {
|
||||
json_response(['error' => '저장에 실패했습니다'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// PUT: 카테고리 수정
|
||||
// =====================================================
|
||||
if ($method === 'PUT') {
|
||||
$input = get_json_input();
|
||||
$id = intval($input['id'] ?? 0);
|
||||
|
||||
if ($id <= 0) {
|
||||
json_response(['error' => '유효하지 않은 ID'], 400);
|
||||
}
|
||||
|
||||
$categories = read_json_safe(CATEGORIES_FILE) ?? [];
|
||||
$found = false;
|
||||
|
||||
foreach ($categories as $key => $cat) {
|
||||
if ($cat['id'] === $id) {
|
||||
if (isset($input['name'])) $categories[$key]['name'] = trim($input['name']);
|
||||
if (isset($input['color'])) $categories[$key]['color'] = trim($input['color']);
|
||||
if (isset($input['order'])) $categories[$key]['order'] = intval($input['order']);
|
||||
// parent_id 변경은 허용하되, 자식이 있는 경우 자식으로 만들지 못하게
|
||||
if (array_key_exists('parent_id', $input)) {
|
||||
$newParent = $input['parent_id'];
|
||||
$newParent = ($newParent === '' || $newParent === null) ? null : intval($newParent);
|
||||
|
||||
// 자기 자신을 부모로 설정 불가
|
||||
if ($newParent === $id) {
|
||||
json_response(['error' => '자기 자신을 부모로 설정할 수 없습니다'], 400);
|
||||
}
|
||||
|
||||
// 자식이 있는 카테고리는 다른 카테고리의 자식이 될 수 없음
|
||||
$hasChildren = false;
|
||||
foreach ($categories as $c) {
|
||||
if (($c['parent_id'] ?? null) === $id) {
|
||||
$hasChildren = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($newParent !== null && $hasChildren) {
|
||||
json_response(['error' => '하위 카테고리가 있는 카테고리는 다른 카테고리의 하위로 이동할 수 없습니다'], 400);
|
||||
}
|
||||
|
||||
$categories[$key]['parent_id'] = $newParent;
|
||||
}
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
json_response(['error' => '카테고리를 찾을 수 없습니다'], 404);
|
||||
}
|
||||
|
||||
if (write_json_safe(CATEGORIES_FILE, $categories)) {
|
||||
json_response(['success' => true]);
|
||||
} else {
|
||||
json_response(['error' => '저장에 실패했습니다'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// DELETE: 카테고리 삭제
|
||||
// =====================================================
|
||||
if ($method === 'DELETE') {
|
||||
$id = intval($_GET['id'] ?? 0);
|
||||
|
||||
if ($id <= 0) {
|
||||
json_response(['error' => '유효하지 않은 ID'], 400);
|
||||
}
|
||||
|
||||
$categories = read_json_safe(CATEGORIES_FILE) ?? [];
|
||||
|
||||
// 자식 카테고리 ID 수집
|
||||
$allIdsToDelete = [$id];
|
||||
foreach ($categories as $c) {
|
||||
if (($c['parent_id'] ?? null) === $id) {
|
||||
$allIdsToDelete[] = $c['id'];
|
||||
}
|
||||
}
|
||||
|
||||
// 해당 카테고리(들)을 사용하는 글이 있는지 확인
|
||||
$learnings = read_json_safe(DATA_DIR . '/learning.json') ?? [];
|
||||
$usedCount = 0;
|
||||
foreach ($learnings as $l) {
|
||||
if (in_array(($l['category_id'] ?? 0), $allIdsToDelete)) $usedCount++;
|
||||
}
|
||||
|
||||
if ($usedCount > 0) {
|
||||
$isParent = count($allIdsToDelete) > 1;
|
||||
$msg = $isParent
|
||||
? "이 카테고리(또는 하위 카테고리)를 사용하는 글이 {$usedCount}개 있습니다. 먼저 해당 글들을 다른 카테고리로 옮기거나 삭제해주세요."
|
||||
: "이 카테고리를 사용하는 글이 {$usedCount}개 있습니다. 먼저 해당 글들을 다른 카테고리로 옮기거나 삭제해주세요.";
|
||||
json_response(['error' => $msg], 400);
|
||||
}
|
||||
|
||||
$filtered = array_values(array_filter($categories, function($c) use ($allIdsToDelete) {
|
||||
return !in_array(($c['id'] ?? 0), $allIdsToDelete);
|
||||
}));
|
||||
|
||||
if (count($filtered) === count($categories)) {
|
||||
json_response(['error' => '카테고리를 찾을 수 없습니다'], 404);
|
||||
}
|
||||
|
||||
if (write_json_safe(CATEGORIES_FILE, $filtered)) {
|
||||
json_response(['success' => true, 'deleted_count' => count($allIdsToDelete)]);
|
||||
} else {
|
||||
json_response(['error' => '삭제에 실패했습니다'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
json_response(['error' => 'Method not allowed'], 405);
|
||||
Reference in New Issue
Block a user