Merge pull request #143 from GameServerPanel/copilot/fix-gsp-docs-link
This commit is contained in:
commit
d636f65647
7 changed files with 291 additions and 10 deletions
|
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
## 2026-05-09
|
||||
- **Billing docs + auto-provision/install reliability:** Updated Game Monitor and Support documentation links to always open `https://gameservers.world/docs/` (game-specific path when available) in a new tab, and hardened billing provisioning so existing `home_id` orders can retry install automatically via the shared gamemanager update trigger (no manual Update Server click required). Added structured provisioning logs (`modules/billing/logs/provisioning.log`) and enriched panel log context with order/invoice/user/home/home_cfg/mod/ip/port/mechanism/result/error fields; PayPal webhook renewals now auto-provision when an order still has no `home_id`.
|
||||
- **Payment success provisioning visibility:** Expanded `modules/billing/payment_success.php` to show per-order provisioning state (install started/pending/failed) using live order/home/IP-port/mod consistency checks, so users/admins can immediately see provisioning outcomes instead of silent failures.
|
||||
|
||||
## 2026-05-08
|
||||
- **Auto-install trigger + monthly-only billing pricing:** Refactored Game Monitor update/install into a shared callable (`modules/gamemanager/update_actions.php`) reused by billing provisioning so new paid/free/admin-created homes auto-trigger the same install/update path used by `m=gamemanager&p=update&update=refresh` without manual clicks. Billing now treats monthly pricing (`price_monthly`) as canonical across admin service config, add-to-cart, free checkout, PayPal capture, and provisioning end-date math (31-day months), while preserving legacy daily/yearly columns for backward compatibility.
|
||||
- **LiteFM PHP 8.3 compatibility and install-pending UX:** Removed deprecated `${var}` interpolation usage, guarded missing `fm_cwd_*` session keys and `dirname()` null paths, and replaced directory-not-found warning output with a clear message when server files are not installed yet.
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@
|
|||
- Complete a full pass over all `modules/billing/docs/*` game guides to standardize OS/Workshop/RCON capability statements against current XML-backed server support.
|
||||
- Add an automated billing provisioning integration test fixture that verifies arrange_ports exact/fallback allocation, duplicate-port protection, and home_id linkage after paid/free checkout.
|
||||
- Add a billing UI badge/filter that distinguishes "pending install" vs "installed" states directly in customer/server order views.
|
||||
- Add an admin billing orders "provisioning details" drawer that reads `modules/billing/logs/provisioning.log` and shows the latest mechanism/result/error per order without leaving the panel.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@ require_once __DIR__ . '/../../includes/lib_remote.php';
|
|||
require_once __DIR__ . '/../config_games/server_config_parser.php';
|
||||
require_once __DIR__ . '/../gamemanager/update_actions.php';
|
||||
|
||||
if (!defined('BILLING_INSTALL_MECHANISM')) {
|
||||
define('BILLING_INSTALL_MECHANISM', 'gamemanager_trigger_update_install');
|
||||
}
|
||||
if (!defined('BILLING_CPU_AFFINITY_NA')) {
|
||||
define('BILLING_CPU_AFFINITY_NA', 'NA');
|
||||
}
|
||||
if (!defined('BILLING_NICE_DEFAULT')) {
|
||||
define('BILLING_NICE_DEFAULT', '0');
|
||||
}
|
||||
|
||||
if (!function_exists('billing_generate_provision_password')) {
|
||||
function billing_generate_provision_password(int $bytes = 12)
|
||||
{
|
||||
|
|
@ -159,6 +169,47 @@ if (!function_exists('billing_resolve_mod_cfg_id')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!function_exists('billing_get_home_ip_port')) {
|
||||
function billing_get_home_ip_port($db, string $db_prefix, int $home_id): array
|
||||
{
|
||||
$row = $db->resultQuery(
|
||||
"SELECT ip_id, port
|
||||
FROM `{$db_prefix}home_ip_ports`
|
||||
WHERE home_id=" . $db->realEscapeSingle($home_id) . "
|
||||
ORDER BY ip_id ASC, port ASC
|
||||
LIMIT 1"
|
||||
);
|
||||
if (!empty($row[0])) {
|
||||
return array(
|
||||
'ok' => true,
|
||||
'ip_id' => intval($row[0]['ip_id'] ?? 0),
|
||||
'port' => intval($row[0]['port'] ?? 0),
|
||||
);
|
||||
}
|
||||
return array('ok' => false, 'ip_id' => 0, 'port' => 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('billing_write_provision_log')) {
|
||||
/**
|
||||
* Writes one JSON line per provisioning attempt to modules/billing/logs/provisioning.log.
|
||||
* Fields include order/invoice/user/home/home_cfg/mod/ip/port/mechanism/install_result/error/message.
|
||||
*/
|
||||
function billing_write_provision_log(array $context): void
|
||||
{
|
||||
$logDir = __DIR__ . '/logs';
|
||||
if (!is_dir($logDir)) {
|
||||
mkdir($logDir, 0755, true);
|
||||
}
|
||||
$status = strtoupper((string)($context['install_result'] ?? 'INFO'));
|
||||
$line = '[' . date('Y-m-d H:i:s') . '] [' . $status . '] ' . json_encode($context, JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||
$result = file_put_contents($logDir . '/provisioning.log', $line, FILE_APPEND | LOCK_EX);
|
||||
if ($result === false) {
|
||||
error_log('billing_write_provision_log: failed to append provisioning.log');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function exec_ogp_module()
|
||||
{
|
||||
global $db,$view,$settings,$table_prefix;
|
||||
|
|
@ -242,6 +293,26 @@ function exec_ogp_module()
|
|||
$user_id = $order['user_id'];
|
||||
$extended = isset($order['extended']) && $order['extended'] == "1" ? TRUE : FALSE;
|
||||
$alreadyProvisioned = !$extended && intval($order['home_id'] ?? 0) > 0;
|
||||
$provision_invoice_id = 0;
|
||||
$selected_ip_id = 0;
|
||||
$selected_port = 0;
|
||||
$selected_mod_id = 0;
|
||||
$resolved_mod_cfg_id = 0;
|
||||
$install_mechanism = BILLING_INSTALL_MECHANISM;
|
||||
$install_result = 'pending';
|
||||
$install_message = '';
|
||||
$install_attempted = false;
|
||||
$home_info = array();
|
||||
$invoiceRow = $db->resultQuery(
|
||||
"SELECT invoice_id
|
||||
FROM `{$db_prefix}billing_invoices`
|
||||
WHERE order_id=" . $db->realEscapeSingle($order_id) . "
|
||||
ORDER BY invoice_id DESC
|
||||
LIMIT 1"
|
||||
);
|
||||
if (!empty($invoiceRow[0]['invoice_id'])) {
|
||||
$provision_invoice_id = intval($invoiceRow[0]['invoice_id']);
|
||||
}
|
||||
//Query service info
|
||||
$service = $db->resultQuery( "SELECT *
|
||||
FROM `{$db_prefix}billing_services`
|
||||
|
|
@ -269,6 +340,17 @@ function exec_ogp_module()
|
|||
if(!$order_failed && $alreadyProvisioned)
|
||||
{
|
||||
$home_id = intval($order['home_id']);
|
||||
$home_info = $db->getGameHome($home_id);
|
||||
if (empty($home_info)) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Order #{$order_id} references home_id {$home_id} but server_homes row is missing.";
|
||||
$db->logger('BILLING PROVISION DATA INTEGRITY ERROR: ' . $order_failure_reason);
|
||||
}
|
||||
$existingIpPort = billing_get_home_ip_port($db, $db_prefix, intval($home_id));
|
||||
if (!empty($existingIpPort['ok'])) {
|
||||
$selected_ip_id = intval($existingIpPort['ip_id']);
|
||||
$selected_port = intval($existingIpPort['port']);
|
||||
}
|
||||
}
|
||||
elseif(!$order_failed && $extended)
|
||||
{
|
||||
|
|
@ -340,6 +422,11 @@ function exec_ogp_module()
|
|||
$order_failed = true;
|
||||
$order_failure_reason = (string)($allocatedPort['error'] ?? 'Port allocation failed.');
|
||||
$db->logger("Provisioning pending install for order #{$order_id}: {$order_failure_reason}");
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
} else {
|
||||
$selected_ip_id = intval($allocatedPort['ip_id'] ?? 0);
|
||||
$selected_port = intval($allocatedPort['port'] ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +437,8 @@ function exec_ogp_module()
|
|||
if (empty($modResolution['ok'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = (string)($modResolution['error'] ?? 'No mod profile available for base install.');
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
} else {
|
||||
$resolved_mod_cfg_id = intval($modResolution['mod_cfg_id']);
|
||||
}
|
||||
|
|
@ -360,11 +449,14 @@ function exec_ogp_module()
|
|||
if ($mod_id === false) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Could not attach mod_cfg_id {$resolved_mod_cfg_id} to home #{$home_id}.";
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
if (!$order_failed) {
|
||||
$db->updateGameModParams( $max_players, $extra_params, $cpu_affinity, $nice, $home_id, $resolved_mod_cfg_id );
|
||||
$db->assignHomeTo( "user", $user_id, $home_id, $access_rights );
|
||||
$selected_mod_id = intval($mod_id);
|
||||
}
|
||||
|
||||
//Get The home info without mods in 1 array (Necesary for remote connection).
|
||||
|
|
@ -373,6 +465,8 @@ function exec_ogp_module()
|
|||
if (empty($home_info)) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Could not load home info for home #{$home_id}.";
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -387,6 +481,8 @@ function exec_ogp_module()
|
|||
if (empty($home_info) || empty($home_info['mods'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Mods are not configured for home #{$home_id}; base install profile could not be resolved.";
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,6 +494,7 @@ function exec_ogp_module()
|
|||
}
|
||||
|
||||
if (!$order_failed) {
|
||||
$install_attempted = true;
|
||||
$autoInstall = gamemanager_trigger_update_install(
|
||||
$db,
|
||||
$home_info,
|
||||
|
|
@ -405,9 +502,22 @@ function exec_ogp_module()
|
|||
array('settings' => $settings)
|
||||
);
|
||||
$mod_id = intval($autoInstall['mod_id'] ?? $mod_id);
|
||||
$selected_mod_id = intval($mod_id);
|
||||
$install_message = (string)($autoInstall['message'] ?? '');
|
||||
if (!empty($autoInstall['already_running'])) {
|
||||
$install_result = 'already_running';
|
||||
} elseif (!empty($autoInstall['started'])) {
|
||||
$install_result = 'started';
|
||||
} elseif (!empty($autoInstall['completed'])) {
|
||||
$install_result = 'completed';
|
||||
} else {
|
||||
$install_result = 'pending';
|
||||
}
|
||||
if (empty($autoInstall['ok'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Server files have not been installed yet. " . ($autoInstall['message'] ?? 'Auto install could not be started.');
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
if (!$order_failed) {
|
||||
|
|
@ -443,6 +553,88 @@ function exec_ogp_module()
|
|||
|
||||
|
||||
}
|
||||
|
||||
// Retry install for orders that already have home_id but never triggered installation.
|
||||
if (!$order_failed && !$extended && !$install_attempted && intval($home_id) > 0) {
|
||||
if ($selected_ip_id <= 0 || $selected_port <= 0) {
|
||||
$existingIpPort = billing_get_home_ip_port($db, $db_prefix, intval($home_id));
|
||||
if (!empty($existingIpPort['ok'])) {
|
||||
$selected_ip_id = intval($existingIpPort['ip_id']);
|
||||
$selected_port = intval($existingIpPort['port']);
|
||||
} else {
|
||||
$allocatedPort = billing_allocate_home_port($db, $db_prefix, intval($home_id), intval($remote_server_id), intval($home_cfg_id));
|
||||
if (empty($allocatedPort['ok'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = (string)($allocatedPort['error'] ?? 'Port allocation failed for existing home.');
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
} else {
|
||||
$selected_ip_id = intval($allocatedPort['ip_id'] ?? 0);
|
||||
$selected_port = intval($allocatedPort['port'] ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$order_failed) {
|
||||
if (empty($home_info)) {
|
||||
$home_info = $db->getGameHome(intval($home_id));
|
||||
}
|
||||
if (empty($home_info)) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Could not load home info for home #{$home_id}.";
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
if (!$order_failed && empty($home_info['mods'])) {
|
||||
$modResolution = billing_resolve_mod_cfg_id($db, intval($home_cfg_id), intval($mod_cfg_id));
|
||||
if (empty($modResolution['ok'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = (string)($modResolution['error'] ?? "Mods are not configured for home #{$home_id}; base install profile could not be resolved.");
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
} else {
|
||||
$resolved_mod_cfg_id = intval($modResolution['mod_cfg_id']);
|
||||
$selected_mod_id = intval($db->addModToGameHome(intval($home_id), intval($resolved_mod_cfg_id)));
|
||||
if ($selected_mod_id <= 0) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Could not attach mod_cfg_id {$resolved_mod_cfg_id} to home #{$home_id}.";
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
} else {
|
||||
$db->updateGameModParams($max_players, '', BILLING_CPU_AFFINITY_NA, BILLING_NICE_DEFAULT, intval($home_id), intval($resolved_mod_cfg_id));
|
||||
$db->assignHomeTo("user", $user_id, intval($home_id), $access_rights);
|
||||
$home_info = $db->getGameHome(intval($home_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$order_failed) {
|
||||
$selected_mod_id = intval(gamemanager_choose_mod_id((array)$home_info, intval($selected_mod_id)));
|
||||
$install_attempted = true;
|
||||
$autoInstall = gamemanager_trigger_update_install(
|
||||
$db,
|
||||
(array)$home_info,
|
||||
intval($selected_mod_id),
|
||||
array('settings' => $settings)
|
||||
);
|
||||
$selected_mod_id = intval($autoInstall['mod_id'] ?? $selected_mod_id);
|
||||
$install_message = (string)($autoInstall['message'] ?? '');
|
||||
if (!empty($autoInstall['already_running'])) {
|
||||
$install_result = 'already_running';
|
||||
} elseif (!empty($autoInstall['started'])) {
|
||||
$install_result = 'started';
|
||||
} elseif (!empty($autoInstall['completed'])) {
|
||||
$install_result = 'completed';
|
||||
} else {
|
||||
$install_result = 'pending';
|
||||
}
|
||||
if (empty($autoInstall['ok'])) {
|
||||
$order_failed = true;
|
||||
$order_failure_reason = "Server files have not been installed yet. " . ($autoInstall['message'] ?? 'Auto install could not be started.');
|
||||
$install_result = 'failed';
|
||||
$install_message = $order_failure_reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set expiration date in panel database
|
||||
// Status values: Active (provisioned & current), Invoiced (renewal invoice open),
|
||||
// Expired (past due and awaiting deletion)
|
||||
|
|
@ -520,6 +712,35 @@ function exec_ogp_module()
|
|||
WHERE home_id = " . $db->realEscapeSingle($home_id));
|
||||
}
|
||||
|
||||
$provisionContext = array(
|
||||
'order_id' => intval($order_id),
|
||||
'invoice_id' => intval($provision_invoice_id),
|
||||
'user_id' => intval($user_id),
|
||||
'home_id' => intval($home_id),
|
||||
'home_cfg_id' => intval($home_cfg_id ?? 0),
|
||||
'mod_id' => intval($selected_mod_id),
|
||||
'ip_id' => intval($selected_ip_id),
|
||||
'port' => intval($selected_port),
|
||||
'mechanism' => $install_mechanism,
|
||||
'install_result' => $order_failed ? 'failed' : (string)$install_result,
|
||||
'error' => $order_failed ? (string)$order_failure_reason : '',
|
||||
'message' => (string)$install_message,
|
||||
);
|
||||
billing_write_provision_log($provisionContext);
|
||||
$db->logger(
|
||||
'BILLING PROVISION RESULT order_id=' . intval($order_id)
|
||||
. ' invoice_id=' . intval($provision_invoice_id)
|
||||
. ' user_id=' . intval($user_id)
|
||||
. ' home_id=' . intval($home_id)
|
||||
. ' home_cfg_id=' . intval($home_cfg_id ?? 0)
|
||||
. ' mod_id=' . intval($selected_mod_id)
|
||||
. ' ip_id=' . intval($selected_ip_id)
|
||||
. ' port=' . intval($selected_port)
|
||||
. ' mechanism=' . $install_mechanism
|
||||
. ' install_result=' . ($order_failed ? 'failed' : (string)$install_result)
|
||||
. ($order_failed ? ' error=' . (string)$order_failure_reason : '')
|
||||
);
|
||||
|
||||
if ($order_failed) {
|
||||
$failed_count++;
|
||||
$failed_messages[] = "Order #{$order_id}: {$order_failure_reason}";
|
||||
|
|
|
|||
|
|
@ -26,11 +26,35 @@ $db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (
|
|||
$orders = [];
|
||||
$total_paid = 0;
|
||||
|
||||
function billing_payment_success_provision_state(array $order): array
|
||||
{
|
||||
$homeId = intval($order['home_id'] ?? 0);
|
||||
$hasHome = intval($order['has_home'] ?? 0) > 0;
|
||||
$ipPortCount = intval($order['ip_port_count'] ?? 0);
|
||||
$modCount = intval($order['mod_count'] ?? 0);
|
||||
|
||||
if ($homeId <= 0) {
|
||||
return ['label' => 'PENDING', 'message' => 'Server record is queued for provisioning.', 'class' => 'status-badge status-pending'];
|
||||
}
|
||||
// home_id exists but server_homes row does not: orphaned consistency failure.
|
||||
if (!$hasHome) {
|
||||
return ['label' => 'FAILED', 'message' => 'Server setup failed. Please contact support with your order ID.', 'class' => 'status-badge status-failed'];
|
||||
}
|
||||
if ($ipPortCount <= 0 || $modCount <= 0) {
|
||||
return ['label' => 'PENDING', 'message' => 'Server created; install is pending final IP/mod setup.', 'class' => 'status-badge status-pending'];
|
||||
}
|
||||
return ['label' => 'INSTALL STARTED', 'message' => 'Server created and install/update trigger has been started or queued.', 'class' => 'status-badge'];
|
||||
}
|
||||
|
||||
if ($db && $user_id > 0) {
|
||||
// Get recent orders for this user (just paid)
|
||||
$query = "SELECT o.*, s.service_name
|
||||
$query = "SELECT o.*, s.service_name,
|
||||
CASE WHEN sh.home_id IS NULL THEN 0 ELSE 1 END AS has_home,
|
||||
(SELECT COUNT(*) FROM {$table_prefix}home_ip_ports hip WHERE hip.home_id = o.home_id) AS ip_port_count,
|
||||
(SELECT COUNT(*) FROM {$table_prefix}game_mods gm WHERE gm.home_id = o.home_id) AS mod_count
|
||||
FROM {$table_prefix}billing_orders o
|
||||
LEFT JOIN {$table_prefix}billing_services s ON o.service_id = s.service_id
|
||||
LEFT JOIN {$table_prefix}server_homes sh ON sh.home_id = o.home_id
|
||||
WHERE o.user_id = $user_id
|
||||
AND o.status = 'Active'
|
||||
ORDER BY o.order_date DESC
|
||||
|
|
@ -39,6 +63,7 @@ if ($db && $user_id > 0) {
|
|||
$result = mysqli_query($db, $query);
|
||||
if ($result) {
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$row['provision_state'] = billing_payment_success_provision_state($row);
|
||||
$orders[] = $row;
|
||||
$total_paid += floatval($row['price']);
|
||||
}
|
||||
|
|
@ -132,6 +157,12 @@ if ($db && $user_id > 0) {
|
|||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
.status-pending {
|
||||
background: #f0ad4e;
|
||||
}
|
||||
.status-failed {
|
||||
background: #d9534f;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 12px 24px;
|
||||
|
|
@ -192,6 +223,7 @@ if ($db && $user_id > 0) {
|
|||
<th>Game</th>
|
||||
<th>Duration</th>
|
||||
<th>Status</th>
|
||||
<th title="Server Setup Status" aria-label="Server Setup Status">Provisioning</th>
|
||||
<th style="text-align: right;">Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -203,6 +235,14 @@ if ($db && $user_id > 0) {
|
|||
<td><?php echo htmlspecialchars($order['service_name'] ?? 'Game Server'); ?></td>
|
||||
<td><?php echo htmlspecialchars($order['qty']); ?>x <?php echo htmlspecialchars($order['invoice_duration']); ?></td>
|
||||
<td><span class="status-badge">PAID</span></td>
|
||||
<td>
|
||||
<span class="<?php echo htmlspecialchars($order['provision_state']['class'] ?? 'status-badge'); ?>">
|
||||
<?php echo htmlspecialchars($order['provision_state']['label'] ?? 'PENDING'); ?>
|
||||
</span>
|
||||
<div style="margin-top:6px;color:#555;font-size:0.9em;">
|
||||
<?php echo htmlspecialchars($order['provision_state']['message'] ?? 'Provisioning state unavailable.'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td style="text-align: right; font-weight: 600; color: #28a745;">
|
||||
$<?php echo number_format(floatval($order['price']), 2); ?>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -556,7 +556,12 @@ function wh_fulfill_payment(mysqli $db, string $pfx, array $payment, string $bil
|
|||
mysqli_stmt_close($stmt);
|
||||
}
|
||||
$last_order_id = $order_id;
|
||||
wh_log('info', 'order_renewed', ['order_id' => $order_id, 'new_end' => $new_end]);
|
||||
$existing_home_id = intval($row['home_id'] ?? 0);
|
||||
wh_log('info', 'order_renewed', ['order_id' => $order_id, 'new_end' => $new_end, 'home_id' => $existing_home_id]);
|
||||
if ($existing_home_id <= 0) {
|
||||
$dir = ($billing_dir !== '') ? $billing_dir : dirname(__DIR__);
|
||||
wh_try_provision($dir, $order_id, $user_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// New order: create billing_orders row
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ require_once("modules/config_games/server_config_parser.php");
|
|||
require_once("includes/refreshed.php");
|
||||
require_once('includes/lib_remote.php');
|
||||
|
||||
if (!defined('GSP_WEBSITE_DOCS_BASE_URL')) {
|
||||
define('GSP_WEBSITE_DOCS_BASE_URL', 'https://gameservers.world/docs/');
|
||||
}
|
||||
|
||||
function renderParam($param, $last_param, $param_access_enabled, $home_id)
|
||||
{
|
||||
global $db;
|
||||
|
|
@ -156,14 +160,15 @@ function get_sync_name($server_xml)
|
|||
|
||||
function gsp_docs_url_for_game_key($game_key)
|
||||
{
|
||||
$baseDocsUrl = rtrim(GSP_WEBSITE_DOCS_BASE_URL, '/');
|
||||
$game_key = trim((string)$game_key);
|
||||
if ($game_key !== '') {
|
||||
$docPath = __DIR__ . '/../billing/docs/' . $game_key . '/index.php';
|
||||
if (is_file($docPath)) {
|
||||
return '/docs.php?action=view&doc=' . rawurlencode($game_key);
|
||||
return $baseDocsUrl . '/' . rawurlencode($game_key) . '/';
|
||||
}
|
||||
}
|
||||
return '/docs.php';
|
||||
return $baseDocsUrl . '/';
|
||||
}
|
||||
|
||||
function exec_ogp_module() {
|
||||
|
|
@ -272,7 +277,7 @@ $home_info = $db->getGameHomeWithoutMods($home_id);
|
|||
$show_all = FALSE;
|
||||
}
|
||||
|
||||
$docsTarget = '/docs.php';
|
||||
$docsTarget = GSP_WEBSITE_DOCS_BASE_URL;
|
||||
if (is_array($home_info) && !empty($home_info['game_key'])) {
|
||||
$docsTarget = gsp_docs_url_for_game_key($home_info['game_key']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,18 +20,23 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
if (!defined('GSP_WEBSITE_DOCS_BASE_URL')) {
|
||||
define('GSP_WEBSITE_DOCS_BASE_URL', 'https://gameservers.world/docs/');
|
||||
}
|
||||
|
||||
function gsp_support_docs_url_for_game_key($game_key)
|
||||
{
|
||||
$baseDocsUrl = rtrim(GSP_WEBSITE_DOCS_BASE_URL, '/');
|
||||
$game_key = trim((string)$game_key);
|
||||
if ($game_key !== '') {
|
||||
$docPath = __DIR__ . '/../billing/docs/' . $game_key . '/index.php';
|
||||
if (is_file($docPath)) {
|
||||
return '/docs.php?action=view&doc=' . rawurlencode($game_key);
|
||||
return $baseDocsUrl . '/' . rawurlencode($game_key) . '/';
|
||||
}
|
||||
}
|
||||
return '/docs.php';
|
||||
return $baseDocsUrl . '/';
|
||||
}
|
||||
|
||||
function exec_ogp_module() {
|
||||
|
|
@ -93,7 +98,7 @@ if (!empty($webhook)) {
|
|||
} // end if submit
|
||||
echo '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />';
|
||||
echo "<h2>".get_lang('support')."</h2>";
|
||||
$defaultDocsUrl = '/docs.php';
|
||||
$defaultDocsUrl = GSP_WEBSITE_DOCS_BASE_URL;
|
||||
if (!empty($server_homes) && is_array($server_homes)) {
|
||||
foreach ((array)$server_homes as $server_home_row) {
|
||||
if (!empty($server_home_row['game_key'])) {
|
||||
|
|
@ -167,7 +172,7 @@ if (!empty($webhook)) {
|
|||
$(document).ready(function(){
|
||||
function updateSupportDocLink(){
|
||||
var selected = $('#gameserver option:selected');
|
||||
var url = selected.data('doc-url') || '/docs.php';
|
||||
var url = selected.data('doc-url') || '<?php echo GSP_WEBSITE_DOCS_BASE_URL; ?>';
|
||||
$('#support-doc-link').attr('href', url);
|
||||
}
|
||||
$('#gameserver').on('change', updateSupportDocLink);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue