GNU/skin/board/maria_event/view/event.edit.update.php
<?php
include_once(__DIR__.'/../_common.php');

header('Content-Type: application/json; charset=utf-8');

if (!defined('_GNUBOARD_')) {
    echo json_encode(['ok' => false, 'message' => 'invalid']);
    exit;
}

if (!$is_admin) {
    echo json_encode(['ok' => false, 'message' => '권한이 없습니다.']);
    exit;
}

$bo_table = isset($_POST['bo_table']) ? preg_replace('/[^a-zA-Z0-9_]/', '', $_POST['bo_table']) : '';
$wr_id = isset($_POST['wr_id']) ? (int)$_POST['wr_id'] : 0;
$event_schema = isset($_POST['event_schema']) ? trim($_POST['event_schema']) : '';
$event_name = isset($_POST['event_name']) ? trim($_POST['event_name']) : '';
$status = isset($_POST['status']) ? strtoupper(trim($_POST['status'])) : 'ENABLE';
$event_type = isset($_POST['event_type']) ? strtoupper(trim($_POST['event_type'])) : 'RECURRING';
$interval_value = isset($_POST['interval_value']) ? (int)$_POST['interval_value'] : 0;
$interval_field = isset($_POST['interval_field']) ? strtoupper(trim($_POST['interval_field'])) : '';
$starts = isset($_POST['starts']) ? trim($_POST['starts']) : '';
$ends = isset($_POST['ends']) ? trim($_POST['ends']) : '';
$execute_at = isset($_POST['execute_at']) ? trim($_POST['execute_at']) : '';
$completion = isset($_POST['completion']) ? strtoupper(trim($_POST['completion'])) : 'NOT PRESERVE';
$definer = isset($_POST['definer']) ? trim($_POST['definer']) : '';
$event_comment = isset($_POST['event_comment']) ? trim($_POST['event_comment']) : '';
$event_definition = isset($_POST['event_definition']) ? trim($_POST['event_definition']) : '';

if ($bo_table === '' || $wr_id < 1 || $event_name === '' || $event_schema === '') {
    echo json_encode(['ok' => false, 'message' => '입력값 오류']);
    exit;
}

if (!preg_match('/^[A-Za-z0-9_]+$/', $event_schema) || !preg_match('/^[A-Za-z0-9_]+$/', $event_name)) {
    echo json_encode(['ok' => false, 'message' => '이벤트 식별자 오류']);
    exit;
}

$write_table = $g5['write_prefix'] . $bo_table;
$write = sql_fetch(" select wr_subject from {$write_table} where wr_id = '{$wr_id}' ");
if (!isset($write['wr_subject']) || trim($write['wr_subject']) !== $event_name) {
    echo json_encode(['ok' => false, 'message' => '이벤트 이름 불일치']);
    exit;
}

if ($event_definition === '') {
    echo json_encode(['ok' => false, 'message' => '정의 값은 비울 수 없습니다.']);
    exit;
}

$status = ($status === 'DISABLE') ? 'DISABLE' : 'ENABLE';
$event_type = ($event_type === 'ONE TIME') ? 'ONE TIME' : 'RECURRING';
$completion = ($completion === 'PRESERVE') ? 'PRESERVE' : 'NOT PRESERVE';

if (!preg_match('/^([^@\s`]+)@([^@\s`]+)$/', $definer, $definer_match)) {
    echo json_encode(['ok' => false, 'message' => '디파이너 형식은 user@host 입니다.']);
    exit;
}

$definer_user = str_replace('`', '``', $definer_match[1]);
$definer_host = str_replace('`', '``', $definer_match[2]);
$definer_sql = "`{$definer_user}`@`{$definer_host}`";

$normalize_dt = function($dt) {
    $dt = trim((string)$dt);
    if ($dt === '') return '';
    $dt = str_replace('T', ' ', $dt);
    if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $dt)) {
        $dt .= ':00';
    }
    if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $dt)) {
        return '';
    }
    return $dt;
};

$starts_dt = $normalize_dt($starts);
$ends_dt = $normalize_dt($ends);
$execute_at_dt = $normalize_dt($execute_at);

if ($event_type === 'ONE TIME') {
    if ($execute_at_dt === '') {
        echo json_encode(['ok' => false, 'message' => 'ONE TIME은 실행 시각(AT)이 필요합니다.']);
        exit;
    }
} else {
    $allowed_fields = ['SECOND','MINUTE','HOUR','DAY','WEEK','MONTH','YEAR'];
    if ($interval_value < 1 || !in_array($interval_field, $allowed_fields, true)) {
        echo json_encode(['ok' => false, 'message' => '실행 간격 값이 올바르지 않습니다.']);
        exit;
    }
}

$event_comment_sql = sql_escape_string($event_comment);

$sql_parts = [];
$sql_parts[] = "ALTER DEFINER={$definer_sql} EVENT `{$event_schema}`.`{$event_name}`";

if ($event_type === 'ONE TIME') {
    $sql_parts[] = "ON SCHEDULE AT '{$execute_at_dt}'";
} else {
    $schedule_sql = "ON SCHEDULE EVERY {$interval_value} {$interval_field}";
    if ($starts_dt !== '') {
        $schedule_sql .= " STARTS '{$starts_dt}'";
    }
    if ($ends_dt !== '') {
        $schedule_sql .= " ENDS '{$ends_dt}'";
    }
    $sql_parts[] = $schedule_sql;
}

$sql_parts[] = "ON COMPLETION {$completion}";
$sql_parts[] = $status;
$sql_parts[] = "COMMENT '{$event_comment_sql}'";
$sql_parts[] = "DO {$event_definition}";

$alter_sql = implode(' ', $sql_parts);
$result = sql_query($alter_sql, false);

if (!$result) {
    echo json_encode(['ok' => false, 'message' => 'ALTER EVENT 실패']);
    exit;
}

echo json_encode(['ok' => true]);