Files
2meet-data-optimizer/includes/notifications/class-tmdo-slack-notifier.php
T
wpdev 76c01e44df refactor: 全部 128 個生產檔加入 declare(strict_types=1)(PR-H)
對齊 A v3.2.0。型別強制會把隱式轉換變成 TypeError,所以一次全檔加入
並跑完整測試(unit 451 / integration 398 全綠,無迴歸)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 06:13:33 +08:00

81 lines
2.0 KiB
PHP

<?php
/**
* TMDO_Slack_Notifier — Slack incoming webhook channel (v2.5.0 M15).
*
* Settings: wpdo_slack_enabled, wpdo_slack_webhook, wpdo_slack_throttle_hours,
* wpdo_slack_severity. Webhook URL must start with https://hooks.slack.com/.
*
* @package WP_Data_Optimizer
*/
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Slack channel.
*/
class TMDO_Slack_Notifier extends TMDO_Abstract_Notifier {
/**
* Channel identifier used as option key prefix.
*
* @return string
*/
public static function channel_id(): string {
return 'slack';
}
/**
* Build Slack-specific context (webhook URL).
*
* @return array|null Null if webhook URL is missing or invalid.
*/
public static function build_context(): ?array {
$url = class_exists( 'TMDO_Crypto' )
? TMDO_Crypto::get_option( 'wpdo_slack_webhook' )
: (string) get_option( 'wpdo_slack_webhook', '' );
if ( '' === $url || strpos( $url, 'https://hooks.slack.com/' ) !== 0 ) {
return null;
}
return array( 'webhook_url' => $url );
}
/**
* Send alert via Slack incoming webhook.
*
* @param string $subject Alert subject / title.
* @param string $body Alert body text.
* @param array $context Channel context (webhook_url).
* @return bool True on HTTP 2xx response.
*/
public static function actually_send( string $subject, string $body, array $context ): bool {
$url = (string) ( $context['webhook_url'] ?? '' );
if ( '' === $url ) {
return false;
}
// Slack mrkdwn — bold subject + plaintext body in code block for readability.
$payload = wp_json_encode(
array(
'text' => "*{$subject}*\n```\n{$body}\n```",
)
);
$resp = wp_remote_post(
$url,
array(
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => $payload,
'timeout' => 5,
'blocking' => true,
)
);
if ( is_wp_error( $resp ) ) {
return false;
}
$code = (int) wp_remote_retrieve_response_code( $resp );
return $code >= 200 && $code < 300;
}
}