first commit 2
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
include_once('../../common.php');
|
||||
|
||||
if (!defined('G5_USE_SHOP') || !G5_USE_SHOP) {
|
||||
define('G5_USE_SHOP', true);
|
||||
}
|
||||
|
||||
include_once(G5_ADMIN_PATH.'/admin.lib.php');
|
||||
include_once(G5_LIB_PATH.'/shop.lib.php');
|
||||
|
||||
$g5['title'] = '구글 애드센스 관리';
|
||||
?>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* 상담 예약 관리 시스템 메뉴
|
||||
*/
|
||||
|
||||
if (!defined('_GNUBOARD_'))
|
||||
exit;
|
||||
|
||||
// 메뉴 구조: array('메뉴코드', '메뉴명', '링크', '메뉴 ID', '아이콘 클래스 (옵션)')
|
||||
$menu['menu860'] = array(
|
||||
// 💡 [개선] 메뉴 그룹 대표 아이콘 추가 (예: fa-comments)
|
||||
array('860000', '구글 ads 광고 관리', G5_ADMIN_URL . '/google_ads_manage/google_ads_list.php', 'google_ads_manage', 'fa-comments'),
|
||||
array('860100', '광고 리스트', G5_ADMIN_URL . '/google_ads_manage/google_ads_list.php', 'google_ads_manage_list'),
|
||||
array('860100', '솔류션 설치', G5_ADMIN_URL . '/google_ads_manage/install.php', 'google_ads_manage_install'),
|
||||
);
|
||||
?>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
//$sub_menu = '100900';
|
||||
include_once('./_common.php');
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
|
||||
$html_title = '구글 애드센스';
|
||||
$g5['title'] = $html_title . ' 관리';
|
||||
|
||||
if ($w == 'u') {
|
||||
$html_title .= ' 수정';
|
||||
$ga = sql_fetch("select * from g5_google_ads where ga_id = '$ga_id'");
|
||||
if (!$ga['ga_id']) alert('존재하지 않는 자료입니다.');
|
||||
} else {
|
||||
$html_title .= ' 입력';
|
||||
$ga = array(
|
||||
'ga_use' => 1,
|
||||
'ga_responsive' => 1,
|
||||
'ga_format' => 'auto'
|
||||
);
|
||||
}
|
||||
|
||||
include_once(G5_ADMIN_PATH.'/admin.head.php');
|
||||
?>
|
||||
|
||||
<form name="fgoogleads" action="./google_ads_form_update.php" method="post" onsubmit="return fgoogleads_submit(this);">
|
||||
<input type="hidden" name="w" value="<?php echo $w; ?>">
|
||||
<input type="hidden" name="ga_id" value="<?php echo $ga_id; ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption><?php echo $g5['title']; ?></caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="ga_name">광고 이름</label></th>
|
||||
<td>
|
||||
<input type="text" name="ga_name" value="<?php echo get_text($ga['ga_name']); ?>" id="ga_name" required class="required frm_input" size="50">
|
||||
<?php echo help("관리용 이름입니다. (예: 메인 상단, 뉴스 리스트 중간)"); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="ga_client_id">클라이언트 ID</label></th>
|
||||
<td>
|
||||
<input type="text" name="ga_client_id" value="<?php echo get_text($ga['ga_client_id']); ?>" id="ga_client_id" required class="required frm_input" size="50">
|
||||
<?php echo help("구글 애드센스 data-ad-client 값 (예: ca-pub-1234567890123456)"); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="ga_slot_id">슬롯 ID</label></th>
|
||||
<td>
|
||||
<input type="text" name="ga_slot_id" value="<?php echo get_text($ga['ga_slot_id']); ?>" id="ga_slot_id" required class="required frm_input" size="50">
|
||||
<?php echo help("구글 애드센스 data-ad-slot 값 (예: 1234567890)"); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="ga_format">광고 형식</label></th>
|
||||
<td>
|
||||
<select name="ga_format" id="ga_format">
|
||||
<option value="auto" <?php echo get_selected($ga['ga_format'], 'auto'); ?>>auto (자동)</option>
|
||||
<option value="fluid" <?php echo get_selected($ga['ga_format'], 'fluid'); ?>>fluid (유동적)</option>
|
||||
<option value="rectangle" <?php echo get_selected($ga['ga_format'], 'rectangle'); ?>>rectangle (직사각형)</option>
|
||||
<option value="horizontal" <?php echo get_selected($ga['ga_format'], 'horizontal'); ?>>horizontal (가로형)</option>
|
||||
<option value="vertical" <?php echo get_selected($ga['ga_format'], 'vertical'); ?>>vertical (세로형)</option>
|
||||
</select>
|
||||
<?php echo help("data-ad-format 값"); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">반응형 여부</th>
|
||||
<td>
|
||||
<input type="checkbox" name="ga_responsive" value="1" id="ga_responsive" <?php echo ($ga['ga_responsive'] ? 'checked' : ''); ?>>
|
||||
<label for="ga_responsive">사용 (data-full-width-responsive="true")</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">사용 여부</th>
|
||||
<td>
|
||||
<input type="checkbox" name="ga_use" value="1" id="ga_use" <?php echo ($ga['ga_use'] ? 'checked' : ''); ?>>
|
||||
<label for="ga_use">사용</label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="btn_fixed_top">
|
||||
<a href="./google_ads_list.php" class="btn btn_02">목록</a>
|
||||
<input type="submit" value="확인" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script>
|
||||
function fgoogleads_submit(f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH.'/admin.tail.php');
|
||||
?>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
$sub_menu = '100900';
|
||||
include_once('./_common.php');
|
||||
|
||||
check_admin_token();
|
||||
|
||||
if ($w == 'd') {
|
||||
auth_check_menu($auth, $sub_menu, 'd');
|
||||
$sql = " delete from g5_google_ads where ga_id = '$ga_id' ";
|
||||
sql_query($sql);
|
||||
} else {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
|
||||
$sql_common = "
|
||||
ga_name = '{$_POST['ga_name']}',
|
||||
ga_client_id = '{$_POST['ga_client_id']}',
|
||||
ga_slot_id = '{$_POST['ga_slot_id']}',
|
||||
ga_format = '{$_POST['ga_format']}',
|
||||
ga_responsive = '{$_POST['ga_responsive']}',
|
||||
ga_use = '{$_POST['ga_use']}'
|
||||
";
|
||||
|
||||
if ($w == '') {
|
||||
$sql_common .= ", ga_datetime = '".G5_TIME_YMDHIS."' ";
|
||||
$sql = " insert into g5_google_ads set {$sql_common} ";
|
||||
sql_query($sql);
|
||||
} else if ($w == 'u') {
|
||||
$sql = " update g5_google_ads set {$sql_common} where ga_id = '$ga_id' ";
|
||||
sql_query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
goto_url('./google_ads_list.php');
|
||||
?>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
$sub_menu = '100900';
|
||||
include_once('./_common.php');
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
$sql = "select * from g5_google_ads order by ga_id desc";
|
||||
$result = sql_query($sql);
|
||||
|
||||
include_once(G5_ADMIN_PATH.'/admin.head.php');
|
||||
?>
|
||||
|
||||
<div class="local_ov01 local_ov">
|
||||
<span class="btn_ov01"><span class="ov_txt"> 등록된 광고 수</span><span class="ov_num"> <?php echo sql_num_rows($result); ?>개</span></span>
|
||||
</div>
|
||||
|
||||
<div class="btn_fixed_top">
|
||||
<a href="./google_ads_form.php" class="btn btn_01">광고 추가</a>
|
||||
</div>
|
||||
|
||||
<div class="tbl_head01 tbl_wrap">
|
||||
<table>
|
||||
<caption><?php echo $g5['title']; ?> 목록</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">광고 이름</th>
|
||||
<th scope="col">클라이언트 ID</th>
|
||||
<th scope="col">슬롯 ID</th>
|
||||
<th scope="col">사용여부</th>
|
||||
<th scope="col">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php for ($i=0; $row=sql_fetch_array($result); $i++) { ?>
|
||||
<tr class="<?php echo $bg; ?>">
|
||||
<td class="td_num"><?php echo $row['ga_id']; ?></td>
|
||||
<td><?php echo $row['ga_name']; ?></td>
|
||||
<td><?php echo $row['ga_client_id']; ?></td>
|
||||
<td><?php echo $row['ga_slot_id']; ?></td>
|
||||
<td class="td_chk"><?php echo $row['ga_use'] ? '사용' : '미사용'; ?></td>
|
||||
<td class="td_mng td_mng_s">
|
||||
<a href="./google_ads_form.php?w=u&ga_id=<?php echo $row['ga_id']; ?>" class="btn btn_03">수정</a>
|
||||
<a href="./google_ads_form_update.php?w=d&ga_id=<?php echo $row['ga_id']; ?>" onclick="return delete_confirm(this);" class="btn btn_02">삭제</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php }
|
||||
if ($i == 0)
|
||||
echo '<tr><td colspan="6" class="empty_table">자료가 없습니다.</td></tr>';
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH.'/admin.tail.php');
|
||||
?>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
$sub_menu = '100900'; // 구글 애드센스 관리 메뉴 코드
|
||||
include_once('./_common.php');
|
||||
include_once(__DIR__ . '/lib/SchemaManager.class.php');
|
||||
|
||||
if (!$is_admin) {
|
||||
alert('관리자만 접근할 수 있습니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL 파일에서 테이블 이름을 추출하는 함수
|
||||
*/
|
||||
function get_tables_from_sql_file($filepath) {
|
||||
$tables = [];
|
||||
if (!file_exists($filepath)) return $tables;
|
||||
$lines = file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/CREATE TABLE(?: IF NOT EXISTS)? `([^`]+)`/i', $line, $matches)) {
|
||||
$tables[] = $matches[1];
|
||||
}
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
$g5['title'] = '구글 애드센스 관리 시스템 설치';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
$install_result = null;
|
||||
$delete_result = null;
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
$tables_to_check = get_tables_from_sql_file(__DIR__ . '/install.sql');
|
||||
|
||||
if ($action === 'install') {
|
||||
check_admin_token();
|
||||
try {
|
||||
$sql_file = __DIR__ . '/install.sql';
|
||||
$schemaManager = new SchemaManager($sql_file);
|
||||
$schemaManager->execute();
|
||||
$db_results = $schemaManager->get_results();
|
||||
$menu_msg = create_admin_menu_file();
|
||||
$install_result = ['db' => $db_results, 'menu' => $menu_msg];
|
||||
} catch (Exception $e) {
|
||||
$install_result['errors'][] = '설치 중 심각한 오류 발생: ' . $e->getMessage();
|
||||
}
|
||||
} else if ($action === 'delete') {
|
||||
check_admin_token();
|
||||
$delete_result = ['tables' => [], 'menu' => ''];
|
||||
$tables_to_delete = $tables_to_check;
|
||||
foreach ($tables_to_delete as $table) {
|
||||
sql_query("DROP TABLE IF EXISTS `{$table}`", false);
|
||||
$delete_result['tables'][] = $table;
|
||||
}
|
||||
$menu_file = G5_ADMIN_PATH . '/admin.menu860.google_ads_manage.php';
|
||||
if (file_exists($menu_file)) {
|
||||
if (@unlink($menu_file)) {
|
||||
$delete_result['menu'] = '메뉴 파일 삭제 성공';
|
||||
} else {
|
||||
$delete_result['menu'] = '메뉴 파일 삭제 실패 (권한 확인 필요)';
|
||||
}
|
||||
}
|
||||
// $delete_result['menu'] = '메뉴 항목은 admin.menu100.php에서 수동으로 제거해야 합니다.';
|
||||
}
|
||||
|
||||
function create_admin_menu_file() {
|
||||
$source_file = __DIR__ . '/admin.menu860.google_ads_manage.php';
|
||||
$target_file = G5_ADMIN_PATH . '/admin.menu860.google_ads_manage.php';
|
||||
if (!file_exists($source_file)) return "실패 (메뉴 원본 파일 없음)";
|
||||
if (file_exists($target_file)) return "성공 (이미 존재함)";
|
||||
if (@copy($source_file, $target_file)) return "성공";
|
||||
return "실패 (파일 복사 오류)";
|
||||
}
|
||||
|
||||
$existing_tables = [];
|
||||
foreach ($tables_to_check as $table) {
|
||||
if (sql_query("SHOW TABLES LIKE '$table'", false) && sql_num_rows(sql_query("SHOW TABLES LIKE '$table'", false)) > 0) {
|
||||
$existing_tables[] = $table;
|
||||
}
|
||||
}
|
||||
$is_installed = count($existing_tables) > 0;
|
||||
?>
|
||||
|
||||
<style>
|
||||
.install-container { max-width: 800px; margin: 20px auto; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
|
||||
.install-header { text-align: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 2px solid #AA20FF; }
|
||||
.install-header h1 { color: #AA20FF; margin-bottom: 10px; }
|
||||
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 30px 0; }
|
||||
.feature-card { padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px; text-align: center; }
|
||||
.feature-card i { font-size: 2em; color: #AA20FF; margin-bottom: 10px; }
|
||||
.status-table { width: 100%; border-collapse: collapse; margin: 20px 0; }
|
||||
.status-table th, .status-table td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
|
||||
.status-table th { background-color: #f8f9fa; font-weight: bold; }
|
||||
.status-ok { color: #28a745; font-weight: bold; }
|
||||
.status-missing { color: #dc3545; font-weight: bold; }
|
||||
.install-btn { display: block; width: 200px; margin: 30px auto; padding: 15px 30px; background: #AA20FF; color: white; text-align: center; text-decoration: none; border-radius: 5px; font-size: 16px; font-weight: bold; border: none; cursor: pointer; transition: background-color 0.3s; }
|
||||
.install-btn:hover { background: #8A1ACC; color: white; }
|
||||
.install-btn:disabled { background: #ccc; cursor: not-allowed; }
|
||||
.alert { padding: 15px; margin: 20px 0; border-radius: 5px; }
|
||||
.alert-success { background-color: #d4edda; border: 1px solid #c3e6cb; color: #155724; }
|
||||
.alert-info { background-color: #d1ecf1; border: 1px solid #bee5eb; color: #0c5460; }
|
||||
.alert-danger { background-color: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; }
|
||||
.btn-secondary { background: #6c757d; color: white; border-color: #6c757d; padding: 5px 10px; border-radius: 4px; text-decoration: none; }
|
||||
.btn-secondary:hover { background: #5a6268; }
|
||||
.btn-danger { background: #dc3545; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; }
|
||||
.btn-danger:hover { background: #c82333; }
|
||||
.button-group { display: flex; justify-content: center; align-items: center; gap: 10px; }
|
||||
</style>
|
||||
|
||||
<div class="install-container">
|
||||
<div class="install-header">
|
||||
<h1><i class="fa fa-ad"></i> 구글 애드센스 관리 시스템</h1>
|
||||
<p>사이트 내 광고를 효율적으로 관리하는 솔루션</p>
|
||||
</div>
|
||||
|
||||
<?php if ($install_result): ?>
|
||||
<div class="alert alert-success"><h4><i class="fa fa-check-circle"></i> 설치 작업 완료</h4><p>데이터베이스 및 메뉴 설정이 완료되었습니다.</p><p><a href="./google_ads_list.php" class="btn btn-primary">애드센스 관리로 이동</a></p></div>
|
||||
<?php elseif ($delete_result): ?>
|
||||
<div class="alert alert-danger"><h4><i class="fa fa-trash"></i> 삭제 작업 완료</h4><p>솔루션 관련 데이터와 파일이 삭제되었습니다.</p><ul><?php foreach($delete_result['tables'] as $tbl) echo "<li>{$tbl} 테이블 삭제됨</li>"; ?><li><?php echo $delete_result['menu']; ?></li></ul></div>
|
||||
<?php elseif ($is_installed): ?>
|
||||
<div class="alert alert-success"><h4><i class="fa fa-check-circle"></i> 설치 완료</h4><p>구글 애드센스 관리 시스템이 이미 설치되어 있습니다.</p><p><a href="./google_ads_list.php" class="btn btn-primary">애드센스 관리로 이동</a></p></div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info"><h4><i class="fa fa-info-circle"></i> 설치 필요</h4><p>애드센스 관리 시스템을 사용하기 위해 설치가 필요합니다.</p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3><i class="fa fa-database"></i> 설치 상태</h3>
|
||||
<table class="status-table">
|
||||
<thead><tr><th>테이블명</th><th>설명</th><th>상태</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($tables_to_check as $table): ?>
|
||||
<tr>
|
||||
<td><code><?php echo $table; ?></code></td>
|
||||
<td>광고 단위 정보</td>
|
||||
<td>
|
||||
<?php if (in_array($table, $existing_tables)): ?>
|
||||
<span class="status-ok"><i class="fa fa-check"></i> 설치됨</span>
|
||||
<?php else: ?>
|
||||
<span class="status-missing"><i class="fa fa-times"></i> 미설치</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php if (!$is_installed): ?>
|
||||
<form method="post" onsubmit="return confirm('솔루션을 설치하시겠습니까?');">
|
||||
<input type="hidden" name="action" value="install">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="install-btn"><i class="fa fa-download"></i> 솔루션 설치하기</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($is_installed && !$install_result && !$delete_result): ?>
|
||||
<div class="button-group" style="text-align: center; margin-top: 20px;">
|
||||
<form method="post" onsubmit="return confirm('기존 데이터는 유지되며, 변경된 DB 구조만 업데이트 됩니다. 진행하시겠습니까?');">
|
||||
<input type="hidden" name="action" value="install">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="btn btn-secondary"><i class="fa fa-sync"></i> 재설치 (업데이트)</button>
|
||||
</form>
|
||||
<form method="post" onsubmit="return confirm('정말로 솔루션을 삭제하시겠습니까? 모든 관련 데이터와 파일이 영구적으로 삭제됩니다.');">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="btn-danger"><i class="fa fa-trash"></i> 솔루션 삭제하기</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
?>
|
||||
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS `g5_google_ads` (
|
||||
`ga_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ga_name` varchar(255) NOT NULL DEFAULT '' COMMENT '광고 이름 (예: 메인 상단, 사이드바)',
|
||||
`ga_client_id` varchar(255) NOT NULL DEFAULT '' COMMENT '클라이언트 ID (ca-pub-...)',
|
||||
`ga_slot_id` varchar(255) NOT NULL DEFAULT '' COMMENT '광고 슬롯 ID',
|
||||
`ga_format` varchar(50) NOT NULL DEFAULT 'auto' COMMENT '광고 형식 (auto, fluid, rectangle 등)',
|
||||
`ga_responsive` tinyint(4) NOT NULL DEFAULT '1' COMMENT '반응형 여부',
|
||||
`ga_use` tinyint(4) NOT NULL DEFAULT '1' COMMENT '사용 여부',
|
||||
`ga_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록일시(변경일시)',
|
||||
PRIMARY KEY (`ga_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* SQL 파일을 기반으로 데이터베이스 스키마를 관리(생성/업데이트)하는 범용 클래스
|
||||
*/
|
||||
class SchemaManager
|
||||
{
|
||||
private $sql_file_path;
|
||||
private $results;
|
||||
private $conn; // DB 연결 객체를 저장할 변수
|
||||
|
||||
/**
|
||||
* 생성자
|
||||
* @param string $sql_file_path install.sql 파일의 절대 경로
|
||||
*/
|
||||
public function __construct($sql_file_path)
|
||||
{
|
||||
global $g5; // 그누보드 DB 연결 객체에 접근하기 위해 global 선언
|
||||
$this->conn = $g5['connect_db']; // DB 연결 객체를 저장
|
||||
|
||||
if (!file_exists($sql_file_path)) {
|
||||
throw new Exception($sql_file_path . ' 파일을 찾을 수 없습니다.');
|
||||
}
|
||||
$this->sql_file_path = $sql_file_path;
|
||||
$this->results = [
|
||||
'created' => [],
|
||||
'existing' => [],
|
||||
'updated' => [],
|
||||
'failed' => [],
|
||||
'errors' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 스키마 설치/업데이트를 실행합니다.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$sql_statements = $this->parse_sql_file();
|
||||
|
||||
foreach ($sql_statements as $stmt) {
|
||||
// CREATE TABLE 문인지 확인
|
||||
if (preg_match('/^CREATE\s+TABLE/i', $stmt)) {
|
||||
$schema = $this->parse_create_table_sql($stmt);
|
||||
if ($schema && !empty($schema['name'])) {
|
||||
$this->process_table_schema($stmt, $schema);
|
||||
}
|
||||
} else {
|
||||
// CREATE TABLE 문이 아닌 다른 SQL 문 (e.g. INSERT, UPDATE)
|
||||
mysqli_query($this->conn, $stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 처리 결과를 반환합니다.
|
||||
* @return array
|
||||
*/
|
||||
public function get_results()
|
||||
{
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 스키마를 처리합니다. (생성 또는 업데이트)
|
||||
* @param string $create_sql 전체 CREATE TABLE 구문
|
||||
* @param array $schema 파싱된 스키마 정보
|
||||
*/
|
||||
private function process_table_schema($create_sql, $schema)
|
||||
{
|
||||
$table_name = $schema['name'];
|
||||
|
||||
if ($this->table_exists($table_name)) {
|
||||
// 테이블이 존재하면, 컬럼 비교 및 추가/수정
|
||||
$this->results['existing'][] = $table_name;
|
||||
$this->update_table_columns($table_name, $schema['columns']);
|
||||
} else {
|
||||
// 테이블이 존재하지 않으면, 새로 생성
|
||||
if (mysqli_query($this->conn, $create_sql)) {
|
||||
$this->results['created'][] = $table_name;
|
||||
} else {
|
||||
$this->results['failed'][] = $table_name;
|
||||
$this->results['errors'][] = "<strong>{$table_name} 테이블 생성 실패</strong>: " . mysqli_error($this->conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블의 컬럼 구조를 업데이트합니다.
|
||||
* @param string $table_name
|
||||
* @param array $target_columns .sql 파일에 정의된 컬럼 목록
|
||||
*/
|
||||
private function update_table_columns($table_name, $target_columns)
|
||||
{
|
||||
$current_columns = $this->get_current_columns($table_name);
|
||||
$added_columns_in_table = [];
|
||||
|
||||
foreach ($target_columns as $col_name => $col_definition) {
|
||||
// 현재 테이블에 해당 컬럼이 없으면 추가
|
||||
if (!isset($current_columns[$col_name])) {
|
||||
$alter_sql = "ALTER TABLE `{$table_name}` ADD COLUMN `{$col_name}` {$col_definition}";
|
||||
if (mysqli_query($this->conn, $alter_sql)) {
|
||||
$added_columns_in_table[] = $col_name;
|
||||
} else {
|
||||
$this->results['failed'][] = "{$table_name} (컬럼: {$col_name})";
|
||||
$this->results['errors'][] = "<strong>{$table_name} 테이블에 '{$col_name}' 컬럼 추가 실패</strong>: " . mysqli_error($this->conn);
|
||||
}
|
||||
} else {
|
||||
// 💡 [핵심 수정] 컬럼이 이미 존재하면, 코멘트 등을 업데이트하기 위해 MODIFY 실행
|
||||
$alter_sql = "ALTER TABLE `{$table_name}` MODIFY COLUMN `{$col_name}` {$col_definition}";
|
||||
if (!mysqli_query($this->conn, $alter_sql)) {
|
||||
// MODIFY 실패 시 에러 기록
|
||||
$this->results['failed'][] = "{$table_name} (컬럼: {$col_name})";
|
||||
$this->results['errors'][] = "<strong>{$table_name} 테이블의 '{$col_name}' 컬럼 수정 실패</strong>: " . mysqli_error($this->conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($added_columns_in_table)) {
|
||||
$this->results['updated'][$table_name] = $added_columns_in_table;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL 파일을 읽고 각 구문으로 분리합니다.
|
||||
* @return array
|
||||
*/
|
||||
private function parse_sql_file()
|
||||
{
|
||||
$sql = file_get_contents($this->sql_file_path);
|
||||
// 주석 제거 (SQL 주석 '--' 와 C-style '/* ... */' 주석)
|
||||
$sql = preg_replace('/--.*/', '', $sql);
|
||||
$sql = preg_replace('!/\*.*?\*/!s', '', $sql);
|
||||
$sql = trim($sql);
|
||||
|
||||
// 세미콜론(;)을 기준으로 쿼리 분리
|
||||
return array_filter(array_map('trim', explode(';', $sql)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 존재 여부를 확인합니다.
|
||||
* @param string $table_name
|
||||
* @return bool
|
||||
*/
|
||||
private function table_exists($table_name)
|
||||
{
|
||||
$res = mysqli_query($this->conn, "SHOW TABLES LIKE '{$table_name}'");
|
||||
return mysqli_num_rows($res) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 DB에 있는 테이블의 컬럼 목록을 가져옵니다.
|
||||
* @param string $table_name
|
||||
* @return array
|
||||
*/
|
||||
private function get_current_columns($table_name)
|
||||
{
|
||||
$res = mysqli_query($this->conn, "SHOW COLUMNS FROM `{$table_name}`");
|
||||
$columns = [];
|
||||
while ($row = mysqli_fetch_array($res)) {
|
||||
$columns[$row['Field']] = true;
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* CREATE TABLE SQL 구문에서 테이블명과 컬럼 정의를 파싱합니다.
|
||||
* @param string $query CREATE TABLE 구문
|
||||
* @return array|null
|
||||
*/
|
||||
private function parse_create_table_sql($query)
|
||||
{
|
||||
$table_name = '';
|
||||
if (preg_match('/CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+`?(\w+)`?/i', $query, $matches)) {
|
||||
$table_name = $matches[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 괄호 안의 내용만 추출
|
||||
$start = strpos($query, '(');
|
||||
$end = strrpos($query, ')');
|
||||
if ($start === false || $end === false) {
|
||||
return ['name' => $table_name, 'columns' => []];
|
||||
}
|
||||
$content = substr($query, $start + 1, $end - $start - 1);
|
||||
|
||||
// 줄 단위로 분리
|
||||
$lines = explode("\n", $content);
|
||||
|
||||
$columns = [];
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line, " \t\n\r\0\x0B,"); // 양쪽 공백과 마지막 쉼표 제거
|
||||
|
||||
// 컬럼 정의 라인인지 확인 (첫 단어가 `column_name` 형태)
|
||||
if (preg_match('/^`(\w+)`\s+(.*)/i', $line, $match)) {
|
||||
$col_name = $match[1];
|
||||
$col_definition = $match[2];
|
||||
$columns[$col_name] = $col_definition;
|
||||
}
|
||||
}
|
||||
|
||||
return ['name' => $table_name, 'columns' => $columns];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user