Integrate Coolify API client and module for managing Coolify services, enhancing automation and deployment processes.
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace classes;
|
||||
|
||||
/**
|
||||
* Additive schema bootstrap for application release management.
|
||||
*
|
||||
* The legacy API does not have a centralized migration runner, so these
|
||||
* migrations must be safe to call from request handlers, tests, and cron.
|
||||
*/
|
||||
class release_manager_schema_bootstrap
|
||||
{
|
||||
private static bool $initialized = false;
|
||||
private static ?bool $tablesExist = null;
|
||||
|
||||
public static function ensureTables(): void
|
||||
{
|
||||
if (self::$initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $db;
|
||||
|
||||
$queries = [
|
||||
"CREATE TABLE IF NOT EXISTS release_channels (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
slug VARCHAR(64) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
description TEXT NULL,
|
||||
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
||||
default_channel TINYINT(1) NOT NULL DEFAULT 0,
|
||||
rollout_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00,
|
||||
frontend_base_url VARCHAR(512) NULL,
|
||||
api_base_url VARCHAR(512) NULL,
|
||||
replay_enabled TINYINT(1) NOT NULL DEFAULT 0,
|
||||
capture_level VARCHAR(32) NOT NULL DEFAULT 'metadata',
|
||||
retention_days INT NOT NULL DEFAULT 14,
|
||||
metadata_json LONGTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
UNIQUE KEY uq_release_channels_slug (slug),
|
||||
INDEX idx_release_channels_enabled (enabled, deleted_at),
|
||||
INDEX idx_release_channels_default (default_channel, deleted_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_versions (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
app VARCHAR(16) NOT NULL,
|
||||
repository VARCHAR(255) NULL,
|
||||
branch VARCHAR(128) NULL,
|
||||
commit_sha VARCHAR(64) NULL,
|
||||
tag VARCHAR(128) NULL,
|
||||
version_label VARCHAR(128) NULL,
|
||||
build_url VARCHAR(512) NULL,
|
||||
artifact_url VARCHAR(512) NULL,
|
||||
deployed_url VARCHAR(512) NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'discovered',
|
||||
metadata_json LONGTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deployed_at DATETIME NULL,
|
||||
INDEX idx_release_versions_app_status (app, status),
|
||||
INDEX idx_release_versions_commit (commit_sha),
|
||||
INDEX idx_release_versions_repo_branch (repository, branch)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_channel_versions (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NOT NULL,
|
||||
frontend_version_id BIGINT UNSIGNED NULL,
|
||||
api_version_id BIGINT UNSIGNED NULL,
|
||||
deployment_id BIGINT UNSIGNED NULL,
|
||||
service_set_id BIGINT UNSIGNED NULL,
|
||||
bundle_id BIGINT UNSIGNED NULL,
|
||||
actor_user_id INT NULL,
|
||||
active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
activated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_release_channel_versions_channel_active (channel_id, active),
|
||||
INDEX idx_release_channel_versions_frontend (frontend_version_id),
|
||||
INDEX idx_release_channel_versions_api (api_version_id),
|
||||
INDEX idx_release_channel_versions_deployment (deployment_id),
|
||||
INDEX idx_release_channel_versions_service_set (service_set_id),
|
||||
INDEX idx_release_channel_versions_bundle (bundle_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_assignments (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
subject_type VARCHAR(16) NOT NULL,
|
||||
subject_id VARCHAR(64) NOT NULL,
|
||||
channel_id BIGINT UNSIGNED NOT NULL,
|
||||
reason VARCHAR(255) NULL,
|
||||
expires_at DATETIME NULL,
|
||||
actor_user_id INT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
INDEX idx_release_assignments_subject (subject_type, subject_id, deleted_at, expires_at),
|
||||
INDEX idx_release_assignments_channel (channel_id, deleted_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_deployment_targets (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NOT NULL,
|
||||
app VARCHAR(16) NOT NULL,
|
||||
coolify_instance_id BIGINT UNSIGNED NULL,
|
||||
coolify_service_uuid VARCHAR(128) NULL,
|
||||
repository VARCHAR(255) NOT NULL,
|
||||
branch VARCHAR(128) NOT NULL DEFAULT 'main',
|
||||
auto_deploy TINYINT(1) NOT NULL DEFAULT 1,
|
||||
health_url VARCHAR(512) NULL,
|
||||
deploy_context_json LONGTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
INDEX idx_release_targets_channel_app (channel_id, app, deleted_at),
|
||||
INDEX idx_release_targets_repo_branch (repository, branch, auto_deploy, deleted_at),
|
||||
INDEX idx_release_targets_coolify (coolify_instance_id, coolify_service_uuid)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_service_sets (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
slug VARCHAR(64) NOT NULL,
|
||||
mode VARCHAR(32) NOT NULL DEFAULT 'attach_existing',
|
||||
source_service_set_id BIGINT UNSIGNED NULL,
|
||||
frontend_target_id BIGINT UNSIGNED NULL,
|
||||
api_target_id BIGINT UNSIGNED NULL,
|
||||
database_coolify_target_id BIGINT UNSIGNED NULL,
|
||||
redis_coolify_target_id BIGINT UNSIGNED NULL,
|
||||
minio_coolify_target_id BIGINT UNSIGNED NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'needs_configuration',
|
||||
health_json LONGTEXT NULL,
|
||||
metadata_json LONGTEXT NULL,
|
||||
actor_user_id INT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
UNIQUE KEY uq_release_service_sets_slug (slug),
|
||||
INDEX idx_release_service_sets_channel (channel_id, deleted_at),
|
||||
INDEX idx_release_service_sets_source (source_service_set_id),
|
||||
INDEX idx_release_service_sets_status (status, deleted_at),
|
||||
INDEX idx_release_service_sets_frontend_target (frontend_target_id),
|
||||
INDEX idx_release_service_sets_api_target (api_target_id),
|
||||
INDEX idx_release_service_sets_database_target (database_coolify_target_id),
|
||||
INDEX idx_release_service_sets_redis_target (redis_coolify_target_id),
|
||||
INDEX idx_release_service_sets_minio_target (minio_coolify_target_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_deployments (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NOT NULL,
|
||||
target_id BIGINT UNSIGNED NULL,
|
||||
version_id BIGINT UNSIGNED NULL,
|
||||
service_set_id BIGINT UNSIGNED NULL,
|
||||
bundle_id BIGINT UNSIGNED NULL,
|
||||
deployment_kind VARCHAR(32) NOT NULL DEFAULT 'single_app',
|
||||
app VARCHAR(16) NOT NULL,
|
||||
provider VARCHAR(32) NOT NULL DEFAULT 'coolify',
|
||||
repository VARCHAR(255) NULL,
|
||||
branch VARCHAR(128) NULL,
|
||||
commit_sha VARCHAR(64) NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'queued',
|
||||
provider_operation_id VARCHAR(128) NULL,
|
||||
deployment_url VARCHAR(512) NULL,
|
||||
actor_user_id INT NULL,
|
||||
requested_payload_json LONGTEXT NULL,
|
||||
result_json LONGTEXT NULL,
|
||||
error_message TEXT NULL,
|
||||
started_at DATETIME NULL,
|
||||
completed_at DATETIME NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_release_deployments_channel_status (channel_id, status),
|
||||
INDEX idx_release_deployments_target (target_id),
|
||||
INDEX idx_release_deployments_version (version_id),
|
||||
INDEX idx_release_deployments_service_set (service_set_id),
|
||||
INDEX idx_release_deployments_bundle (bundle_id),
|
||||
INDEX idx_release_deployments_kind (deployment_kind),
|
||||
INDEX idx_release_deployments_commit (commit_sha)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_bundles (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NOT NULL,
|
||||
service_set_id BIGINT UNSIGNED NOT NULL,
|
||||
version_label VARCHAR(128) NULL,
|
||||
frontend_version_id BIGINT UNSIGNED NULL,
|
||||
api_version_id BIGINT UNSIGNED NULL,
|
||||
frontend_deployment_id BIGINT UNSIGNED NULL,
|
||||
api_deployment_id BIGINT UNSIGNED NULL,
|
||||
frontend_repository VARCHAR(255) NULL,
|
||||
frontend_branch VARCHAR(128) NULL,
|
||||
frontend_commit_sha VARCHAR(64) NULL,
|
||||
api_repository VARCHAR(255) NULL,
|
||||
api_branch VARCHAR(128) NULL,
|
||||
api_commit_sha VARCHAR(64) NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'draft',
|
||||
deployment_result_json LONGTEXT NULL,
|
||||
metadata_json LONGTEXT NULL,
|
||||
actor_user_id INT NULL,
|
||||
deployed_at DATETIME NULL,
|
||||
promoted_at DATETIME NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
INDEX idx_release_bundles_channel_status (channel_id, status, deleted_at),
|
||||
INDEX idx_release_bundles_service_set (service_set_id, status, deleted_at),
|
||||
INDEX idx_release_bundles_frontend_version (frontend_version_id),
|
||||
INDEX idx_release_bundles_api_version (api_version_id),
|
||||
INDEX idx_release_bundles_frontend_deployment (frontend_deployment_id),
|
||||
INDEX idx_release_bundles_api_deployment (api_deployment_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_replay_targets (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
target_type VARCHAR(16) NOT NULL,
|
||||
target_id VARCHAR(64) NULL,
|
||||
channel_id BIGINT UNSIGNED NULL,
|
||||
capture_level VARCHAR(32) NOT NULL DEFAULT 'full_redacted',
|
||||
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
||||
expires_at DATETIME NULL,
|
||||
actor_user_id INT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
INDEX idx_release_replay_target (target_type, target_id, enabled, deleted_at, expires_at),
|
||||
INDEX idx_release_replay_channel (channel_id, enabled, deleted_at, expires_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_timeline_sessions (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
trace_id VARCHAR(64) NOT NULL,
|
||||
session_hash VARCHAR(64) NULL,
|
||||
principal_type VARCHAR(16) NULL,
|
||||
principal_id VARCHAR(64) NULL,
|
||||
customer_number INT NULL,
|
||||
channel_id BIGINT UNSIGNED NULL,
|
||||
channel_slug VARCHAR(64) NULL,
|
||||
frontend_version_id BIGINT UNSIGNED NULL,
|
||||
api_version_id BIGINT UNSIGNED NULL,
|
||||
user_agent VARCHAR(512) NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_release_timeline_trace (trace_id),
|
||||
INDEX idx_release_timeline_principal (principal_type, principal_id),
|
||||
INDEX idx_release_timeline_channel (channel_id, channel_slug),
|
||||
INDEX idx_release_timeline_customer (customer_number),
|
||||
INDEX idx_release_timeline_last_seen (last_seen_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_timeline_events (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
timeline_session_id BIGINT UNSIGNED NULL,
|
||||
trace_id VARCHAR(64) NOT NULL,
|
||||
event_type VARCHAR(64) NOT NULL,
|
||||
severity VARCHAR(16) NOT NULL DEFAULT 'info',
|
||||
module_key VARCHAR(64) NULL,
|
||||
route_path VARCHAR(255) NULL,
|
||||
component VARCHAR(255) NULL,
|
||||
request_id VARCHAR(128) NULL,
|
||||
occurred_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
payload_json LONGTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_release_timeline_events_session (timeline_session_id, occurred_at),
|
||||
INDEX idx_release_timeline_events_trace (trace_id, occurred_at),
|
||||
INDEX idx_release_timeline_events_type (event_type, severity),
|
||||
INDEX idx_release_timeline_events_module (module_key, occurred_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_module_health_snapshots (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NULL,
|
||||
module_key VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
reason VARCHAR(512) NULL,
|
||||
payload_json LONGTEXT NULL,
|
||||
checked_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_release_module_health_module (module_key, checked_at),
|
||||
INDEX idx_release_module_health_channel (channel_id, module_key, checked_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS release_audit_logs (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id BIGINT UNSIGNED NULL,
|
||||
deployment_id BIGINT UNSIGNED NULL,
|
||||
action VARCHAR(64) NOT NULL,
|
||||
actor_user_id INT NULL,
|
||||
severity VARCHAR(16) NOT NULL DEFAULT 'info',
|
||||
context_json LONGTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_release_audit_channel (channel_id, created_at),
|
||||
INDEX idx_release_audit_deployment (deployment_id),
|
||||
INDEX idx_release_audit_action (action)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
];
|
||||
|
||||
foreach ($queries as $sql) {
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
self::ensureColumn('release_channel_versions', 'service_set_id', 'BIGINT UNSIGNED NULL AFTER deployment_id');
|
||||
self::ensureColumn('release_channel_versions', 'bundle_id', 'BIGINT UNSIGNED NULL AFTER service_set_id');
|
||||
self::ensureColumn('release_deployments', 'service_set_id', 'BIGINT UNSIGNED NULL AFTER version_id');
|
||||
self::ensureColumn('release_deployments', 'bundle_id', 'BIGINT UNSIGNED NULL AFTER service_set_id');
|
||||
self::ensureColumn('release_deployments', 'deployment_kind', "VARCHAR(32) NOT NULL DEFAULT 'single_app' AFTER bundle_id");
|
||||
|
||||
self::ensureModuleConfigDefault('ReleaseManager', 'enabled', 'true', 'bool');
|
||||
self::ensureModuleConfigDefault('ReleaseManager', 'github_webhook_secret', '', 'string');
|
||||
self::ensureModuleConfigDefault('ReleaseManager', 'github_token', '', 'string');
|
||||
self::ensureModuleConfigDefault('ReleaseManager', 'github_api_url', 'https://api.github.com', 'string');
|
||||
self::ensureModuleConfigDefault('ReleaseManager', 'default_retention_days', '14', 'int');
|
||||
|
||||
self::ensureDefaultChannels();
|
||||
|
||||
self::$initialized = true;
|
||||
self::$tablesExist = true;
|
||||
}
|
||||
|
||||
public static function tablesExist(): bool
|
||||
{
|
||||
if (self::$tablesExist !== null) {
|
||||
return self::$tablesExist;
|
||||
}
|
||||
|
||||
global $db;
|
||||
|
||||
foreach ([
|
||||
'release_channels',
|
||||
'release_versions',
|
||||
'release_channel_versions',
|
||||
'release_assignments',
|
||||
'release_service_sets',
|
||||
'release_deployments',
|
||||
'release_bundles',
|
||||
'release_timeline_sessions',
|
||||
'release_timeline_events',
|
||||
] as $table) {
|
||||
$tableSql = $db->escape_string($table);
|
||||
$result = $db->query("SHOW TABLES LIKE '$tableSql'");
|
||||
if ($result === false || $result->num_rows === 0) {
|
||||
self::$tablesExist = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self::$tablesExist = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function ensureDefaultChannels(): void
|
||||
{
|
||||
global $db;
|
||||
|
||||
$channels = [
|
||||
['stable', 'Stable', 'Default production channel.', 1, 1, 'metadata'],
|
||||
['canary', 'Canary', 'Earliest production validation channel.', 1, 0, 'metadata'],
|
||||
['beta', 'Beta', 'Broader pre-stable rollout channel.', 1, 0, 'metadata'],
|
||||
['internal', 'Internal', 'Internal staff and superuser validation channel.', 1, 0, 'metadata'],
|
||||
];
|
||||
|
||||
foreach ($channels as [$slug, $name, $description, $enabled, $default, $captureLevel]) {
|
||||
$db->query(sprintf(
|
||||
"INSERT IGNORE INTO release_channels (slug, name, description, enabled, default_channel, capture_level)
|
||||
VALUES ('%s', '%s', '%s', %d, %d, '%s')",
|
||||
$db->escape_string($slug),
|
||||
$db->escape_string($name),
|
||||
$db->escape_string($description),
|
||||
(int)$enabled,
|
||||
(int)$default,
|
||||
$db->escape_string($captureLevel)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private static function ensureModuleConfigDefault(string $module, string $variable, string $value, string $type): void
|
||||
{
|
||||
global $db;
|
||||
|
||||
$moduleSql = $db->escape_string($module);
|
||||
$variableSql = $db->escape_string($variable);
|
||||
$result = $db->query("SELECT value FROM module_config WHERE module = '$moduleSql' AND variable = '$variableSql' LIMIT 1");
|
||||
if ($result !== false && $result->num_rows > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$valueSql = $db->escape_string($value);
|
||||
$typeSql = $db->escape_string($type);
|
||||
$db->query("INSERT INTO module_config (module, variable, value, type) VALUES ('$moduleSql', '$variableSql', '$valueSql', '$typeSql')");
|
||||
}
|
||||
|
||||
private static function ensureColumn(string $table, string $column, string $definition): void
|
||||
{
|
||||
global $db;
|
||||
|
||||
$table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
|
||||
$column = preg_replace('/[^a-zA-Z0-9_]/', '', $column);
|
||||
if ($table === '' || $column === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $db->query("SHOW COLUMNS FROM `$table` LIKE '$column'");
|
||||
if ($result !== false && $result->num_rows > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$db->query("ALTER TABLE `$table` ADD COLUMN `$column` $definition");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user