feat(admin): settings page with token/chat/site-title, test button, retro, queue state
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Cf7stg;
|
||||
|
||||
final class Settings_Page
|
||||
{
|
||||
private const PAGE_SLUG = 'cf7stg-settings';
|
||||
private const NONCE = 'cf7stg_settings_nonce';
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
add_action('admin_menu', [$this, 'add_menu']);
|
||||
add_action('admin_post_cf7stg_save', [$this, 'handle_save']);
|
||||
add_action('admin_post_cf7stg_test', [$this, 'handle_test']);
|
||||
add_action('admin_post_cf7stg_retro', [$this, 'handle_retro']);
|
||||
add_action('admin_post_cf7stg_retry_failed', [$this, 'handle_retry_failed']);
|
||||
add_action('admin_post_cf7stg_purge_sent', [$this, 'handle_purge_sent']);
|
||||
}
|
||||
|
||||
public function add_menu(): void
|
||||
{
|
||||
add_options_page(
|
||||
'CF7 Spam → Telegram',
|
||||
'CF7 Spam → TG',
|
||||
'manage_options',
|
||||
self::PAGE_SLUG,
|
||||
[$this, 'render']
|
||||
);
|
||||
}
|
||||
|
||||
public function render(): void
|
||||
{
|
||||
if (!current_user_can('manage_options')) return;
|
||||
$page_slug = self::PAGE_SLUG;
|
||||
$nonce = self::NONCE;
|
||||
include CF7STG_PLUGIN_DIR . 'admin/views/settings.php';
|
||||
}
|
||||
|
||||
public function handle_save(): void
|
||||
{
|
||||
$this->guard('cf7stg_save');
|
||||
if (!Settings::is_bot_token_constant()) {
|
||||
$token = (string)($_POST['bot_token'] ?? '');
|
||||
if ($token !== '') Settings::set_bot_token($token);
|
||||
}
|
||||
if (!Settings::is_chat_id_constant()) {
|
||||
Settings::set_chat_id(sanitize_text_field((string)($_POST['chat_id'] ?? '')));
|
||||
}
|
||||
Settings::set_site_title(sanitize_text_field((string)($_POST['site_title'] ?? '')));
|
||||
$this->redirect_back(['saved' => 1]);
|
||||
}
|
||||
|
||||
public function handle_test(): void
|
||||
{
|
||||
$this->guard('cf7stg_test');
|
||||
try {
|
||||
TelegramClient::send_message(
|
||||
Settings::get_chat_id(),
|
||||
'✅ Тестовое сообщение из плагина CF7 Spam → Telegram ('
|
||||
. esc_html(Settings::get_site_title()) . ')'
|
||||
);
|
||||
Settings::set_last_test(['ok' => true, 'at' => current_time('mysql'), 'err' => '']);
|
||||
$this->redirect_back(['test' => 'ok']);
|
||||
} catch (TelegramException $e) {
|
||||
Settings::set_last_test(['ok' => false, 'at' => current_time('mysql'), 'err' => $e->getMessage()]);
|
||||
$this->redirect_back(['test' => 'err']);
|
||||
}
|
||||
}
|
||||
|
||||
public function handle_retro(): void
|
||||
{
|
||||
$this->guard('cf7stg_retro');
|
||||
$count = max(1, min(RetroImporter::MAX_COUNT, (int)($_POST['retro_count'] ?? 10)));
|
||||
$days = max(0, (int)($_POST['retro_days'] ?? 7));
|
||||
$repeat = !empty($_POST['retro_repeat']);
|
||||
$result = RetroImporter::import($count, $days, $repeat);
|
||||
$this->redirect_back(['retro_added' => (int)$result['added'], 'retro_skipped' => (int)$result['skipped']]);
|
||||
}
|
||||
|
||||
public function handle_retry_failed(): void
|
||||
{
|
||||
$this->guard('cf7stg_retry_failed');
|
||||
$n = Queue::retry_all_failed();
|
||||
$this->redirect_back(['retried' => $n]);
|
||||
}
|
||||
|
||||
public function handle_purge_sent(): void
|
||||
{
|
||||
$this->guard('cf7stg_purge_sent');
|
||||
$n = Queue::purge_sent();
|
||||
$this->redirect_back(['purged' => $n]);
|
||||
}
|
||||
|
||||
private function guard(string $action): void
|
||||
{
|
||||
if (!current_user_can('manage_options')) wp_die('forbidden');
|
||||
check_admin_referer($action, self::NONCE);
|
||||
}
|
||||
|
||||
private function redirect_back(array $extra = []): void
|
||||
{
|
||||
$url = add_query_arg(array_merge(['page' => self::PAGE_SLUG], $extra), admin_url('options-general.php'));
|
||||
wp_safe_redirect($url);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/** @var string $page_slug */
|
||||
/** @var string $nonce */
|
||||
$last_test = \Cf7stg\Settings::get_last_test();
|
||||
$pending = \Cf7stg\Queue::count_by_status(\Cf7stg\Queue::STATUS_PENDING);
|
||||
$sent24 = \Cf7stg\Queue::count_sent_last_24h();
|
||||
$failed = \Cf7stg\Queue::count_failed();
|
||||
|
||||
$notice = '';
|
||||
if (!empty($_GET['saved'])) $notice = '<div class="notice notice-success"><p>Настройки сохранены.</p></div>';
|
||||
if (($_GET['test'] ?? '') === 'ok') $notice = '<div class="notice notice-success"><p>Тестовое сообщение отправлено.</p></div>';
|
||||
if (($_GET['test'] ?? '') === 'err') $notice = '<div class="notice notice-error"><p>Ошибка отправки: ' . esc_html($last_test['err'] ?? '') . '</p></div>';
|
||||
if (isset($_GET['retro_added'])) $notice = '<div class="notice notice-success"><p>Добавлено в очередь: ' . (int)$_GET['retro_added'] . ', пропущено: ' . (int)$_GET['retro_skipped'] . '.</p></div>';
|
||||
if (isset($_GET['retried'])) $notice = '<div class="notice notice-success"><p>Перезапущено с ошибкой: ' . (int)$_GET['retried'] . '.</p></div>';
|
||||
if (isset($_GET['purged'])) $notice = '<div class="notice notice-success"><p>Удалено отправленных: ' . (int)$_GET['purged'] . '.</p></div>';
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>CF7 Spam → Telegram</h1>
|
||||
<?php echo $notice; ?>
|
||||
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
|
||||
<input type="hidden" name="action" value="cf7stg_save">
|
||||
<?php wp_nonce_field('cf7stg_save', $nonce); ?>
|
||||
<h2>Настройки Telegram</h2>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th><label for="bot_token">Bot Token</label></th>
|
||||
<td>
|
||||
<?php if (\Cf7stg\Settings::is_bot_token_constant()): ?>
|
||||
<em>Задано константой <code>SPAM2TG_BOT_TOKEN</code> в wp-config.php (readonly).</em>
|
||||
<?php else: ?>
|
||||
<input type="password" id="bot_token" name="bot_token" class="regular-text" autocomplete="off" placeholder="<?php echo \Cf7stg\Settings::get_bot_token() ? '(сохранён)' : ''; ?>">
|
||||
<p class="description">Можно задать константой <code>SPAM2TG_BOT_TOKEN</code> в wp-config.php вместо БД.</p>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="chat_id">Chat ID</label></th>
|
||||
<td>
|
||||
<?php if (\Cf7stg\Settings::is_chat_id_constant()): ?>
|
||||
<em>Задано константой <code>SPAM2TG_CHAT_ID</code> (readonly).</em>
|
||||
<?php else: ?>
|
||||
<input type="text" id="chat_id" name="chat_id" class="regular-text" value="<?php echo esc_attr(\Cf7stg\Settings::get_chat_id()); ?>">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="site_title">Заголовок сайта</label></th>
|
||||
<td>
|
||||
<input type="text" id="site_title" name="site_title" class="regular-text" value="<?php echo esc_attr((string)get_option(\Cf7stg\Settings::OPT_SITE_TITLE, '')); ?>" placeholder="<?php echo esc_attr(\Cf7stg\Settings::get_site_title()); ?>">
|
||||
<p class="description">Если пусто — используется домен (декодированный из Punycode).</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button('Сохранить настройки'); ?>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin-top:16px">
|
||||
<input type="hidden" name="action" value="cf7stg_test">
|
||||
<?php wp_nonce_field('cf7stg_test', $nonce); ?>
|
||||
<button type="submit" class="button">Отправить тестовое сообщение</button>
|
||||
<?php if (!empty($last_test)): ?>
|
||||
<span style="margin-left:12px">
|
||||
<?php if (!empty($last_test['ok'])): ?>
|
||||
✅ Последняя проверка: <?php echo esc_html((string)$last_test['at']); ?> — OK
|
||||
<?php else: ?>
|
||||
⚠️ Последняя проверка: <?php echo esc_html((string)$last_test['at']); ?> — <?php echo esc_html((string)$last_test['err']); ?>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Ретроспективная выгрузка из Flamingo</h2>
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
|
||||
<input type="hidden" name="action" value="cf7stg_retro">
|
||||
<?php wp_nonce_field('cf7stg_retro', $nonce); ?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>Количество записей</th>
|
||||
<td><input type="number" name="retro_count" value="10" min="1" max="50"> <span class="description">макс. 50</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Только за последние</th>
|
||||
<td><input type="number" name="retro_days" value="7" min="0"> дней <span class="description">(0 = без ограничения)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<td><label><input type="checkbox" name="retro_repeat" value="1"> Разрешить повтор уже отправленных</label></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button('Добавить в очередь', 'secondary'); ?>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Состояние очереди</h2>
|
||||
<p>В очереди (ожидают): <b><?php echo (int)$pending; ?></b> · Отправлено за сутки: <b><?php echo (int)$sent24; ?></b> · С ошибками: <b><?php echo (int)$failed; ?></b></p>
|
||||
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline-block;margin-right:8px">
|
||||
<input type="hidden" name="action" value="cf7stg_retry_failed">
|
||||
<?php wp_nonce_field('cf7stg_retry_failed', $nonce); ?>
|
||||
<button type="submit" class="button">Повторить все ошибочные</button>
|
||||
</form>
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline-block">
|
||||
<input type="hidden" name="action" value="cf7stg_purge_sent">
|
||||
<?php wp_nonce_field('cf7stg_purge_sent', $nonce); ?>
|
||||
<button type="submit" class="button">Очистить отправленные</button>
|
||||
</form>
|
||||
</div>
|
||||
Reference in New Issue
Block a user