From 6336a19a31f201d1955c74b6761f6f718c41379a Mon Sep 17 00:00:00 2001 From: alexandergull Date: Fri, 27 Feb 2026 14:33:29 +0500 Subject: [PATCH 1/3] Upd. Connection reports. Email title edited. --- lib/Cleantalk/ApbctWP/ConnectionReports.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/Cleantalk/ApbctWP/ConnectionReports.php b/lib/Cleantalk/ApbctWP/ConnectionReports.php index dc8348003..14a18ef58 100644 --- a/lib/Cleantalk/ApbctWP/ConnectionReports.php +++ b/lib/Cleantalk/ApbctWP/ConnectionReports.php @@ -422,8 +422,6 @@ public function handleRequest( */ private function sendEmail(array $unsent_reports_ids, $is_cron_task = false) { - global $apbct; - $selection = $this->getReportsDataByIds($unsent_reports_ids); if (empty($selection)) { @@ -431,7 +429,7 @@ private function sendEmail(array $unsent_reports_ids, $is_cron_task = false) } $to = 'pluginreports@cleantalk.org'; - $subject = "Connection report for " . TT::toString(Server::get('HTTP_HOST')) . " v" . APBCT_VERSION; + $subject = "CleanTalk Service Report: Connection v" . APBCT_VERSION . " for " . TT::toString(Server::get('HTTP_HOST')) ; $message = $this->prepareEmailContent($selection, $is_cron_task); $headers = "Content-type: text/html; charset=utf-8 \r\n"; From 6b68720704fd8a38e18020101ee06e0ee18f9c1a Mon Sep 17 00:00:00 2001 From: alexandergull Date: Fri, 27 Feb 2026 14:44:23 +0500 Subject: [PATCH 2/3] Upd. Connection reports. Service id added. --- lib/Cleantalk/ApbctWP/ConnectionReports.php | 4 +++- lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Cleantalk/ApbctWP/ConnectionReports.php b/lib/Cleantalk/ApbctWP/ConnectionReports.php index 14a18ef58..d344bf3f3 100644 --- a/lib/Cleantalk/ApbctWP/ConnectionReports.php +++ b/lib/Cleantalk/ApbctWP/ConnectionReports.php @@ -429,7 +429,7 @@ private function sendEmail(array $unsent_reports_ids, $is_cron_task = false) } $to = 'pluginreports@cleantalk.org'; - $subject = "CleanTalk Service Report: Connection v" . APBCT_VERSION . " for " . TT::toString(Server::get('HTTP_HOST')) ; + $subject = "CleanTalk Service Report: Connection v" . APBCT_VERSION . " for " . Server::getString('HTTP_HOST') ; $message = $this->prepareEmailContent($selection, $is_cron_task); $headers = "Content-type: text/html; charset=utf-8 \r\n"; @@ -449,6 +449,7 @@ private function sendEmail(array $unsent_reports_ids, $is_cron_task = false) */ private function prepareEmailContent(array $selection, $is_cron_task = false) { + global $apbct; $stat_since = isset($this->reports_count['stat_since']) ? $this->reports_count['stat_since'] : ''; $total = isset($this->reports_count['total']) ? $this->reports_count['total'] : ''; $positive = isset($this->reports_count['positive']) ? $this->reports_count['positive'] : ''; @@ -487,6 +488,7 @@ private function prepareEmailContent(array $selection, $is_cron_task = false) $message .= '
'; $message .= '
' . ($is_cron_task ? 'This is a cron task.' : 'This is a manual task.') . '
'; + $message .= '
Site service_id: ' . $apbct->data['service_id'] . '
'; $message .= ''; return $message; diff --git a/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php b/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php index 10aea813f..1151456b1 100644 --- a/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php +++ b/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php @@ -88,7 +88,7 @@ private function sendSentinelEmail() } $to = 'pluginreports@cleantalk.org'; - $subject = "SFW failed updates report for " . TT::toString(Server::get('HTTP_HOST')) . " v" . APBCT_VERSION; + $subject = "CleanTalk Service Report: SFW v" . APBCT_VERSION . " for " . Server::getString('HTTP_HOST'); $message = ' @@ -167,6 +167,8 @@ private function sendSentinelEmail() $message .= '

There is no previous SFW failed update report.

'; } + $message .= '
Site service_id: ' . $apbct->data['service_id'] . '
'; + $message .= ''; $headers = "Content-type: text/html; charset=utf-8 \r\n"; From 7de9daa33f3f81d2e7fcb80279aa1a9ce851e529 Mon Sep 17 00:00:00 2001 From: alexandergull Date: Sat, 28 Feb 2026 23:20:56 +0500 Subject: [PATCH 3/3] Upd. SFW updates sentinel. Updated report. --- .../ApbctWP/Firewall/SFWUpdateSentinel.php | 291 +++++++++++------- lib/Cleantalk/Common/TextPlate.php | 130 ++++++++ .../Firewall/TestSFWUpdateSentinel.php | 210 ++++++++++--- tests/ApbctWP/Helper/testApbctWPHelper.php | 15 + .../TestCleantalkSettingsTemplates.php | 17 + 5 files changed, 509 insertions(+), 154 deletions(-) create mode 100644 lib/Cleantalk/Common/TextPlate.php diff --git a/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php b/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php index 1151456b1..2aa71e1e0 100644 --- a/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php +++ b/lib/Cleantalk/ApbctWP/Firewall/SFWUpdateSentinel.php @@ -2,11 +2,16 @@ namespace Cleantalk\ApbctWP\Firewall; +use Cleantalk\ApbctWP\Helper; +use Cleantalk\ApbctWP\State; use Cleantalk\ApbctWP\Variables\Server; +use Cleantalk\Common\TextPlate; use Cleantalk\Common\TT; class SFWUpdateSentinel { + use TextPlate; + /** * @var array */ @@ -14,11 +19,11 @@ class SFWUpdateSentinel /** * @var array */ - private $last_fw_stats = array(); /** + private $last_fw_stats = array(); + /** * @var int */ private $number_of_failed_updates_to_check; - /** * @var int */ @@ -59,7 +64,7 @@ public function seekId($id) * @param string $id firewall_updating_id * @return bool */ - private function hasIdAdded($id) + public function hasIdAdded($id) { return isset($this->sentinel_ids[$id]); } @@ -68,7 +73,7 @@ private function hasIdAdded($id) * Return list of seeking ids. * @return array */ - private function getSeekingIdsList() + public function getSeekingIdsList() { $this->getSentinelData(); return $this->sentinel_ids; @@ -76,119 +81,191 @@ private function getSeekingIdsList() /** * Send email with seeking id failed and last fw_stats + * @param array $ids_list */ - private function sendSentinelEmail() + public function sendSentinelEmail(array $ids_list) { + $this->getSentinelData(); + $from_email = ct_get_admin_email(); + $to_email = 'pluginreports@cleantalk.org'; + $subject = self::textPlateRender('CleanTalk Service Report: SFW v{{version}} for {{host}}', [ + 'host' => Server::getString('HTTP_HOST'), + 'version' => APBCT_VERSION, + ]); + $message = $this->prepareEmailContent($ids_list); + $headers = self::textPlateRender("Content-type: text/html; charset=utf-8\r\nFrom: {{mail}}", [ + 'mail' => $from_email, + ]); + $sent = @wp_mail($to_email, $subject, $message, $headers); + $this->updateSentinelStats($sent); + } + + /** + * Prepare content of email. + * @param array $idsList + * @return string + */ + public function prepareEmailContent(array $idsList): string + { + /** + * @var State $apbct + */ global $apbct; - $ids_list = $this->getSeekingIdsList(); + // HTML + $template = ' + + + CleanTalk SFW Report + + + +

There were {{failed_count}} unsuccessful SFW updates in a row:

+

Negative report:

+ + + {{failed_rows}} +
 FW update IDStarted date
+ +

Last FW stats:

+ {{fw_stats}}
+ +

Last queue details

+
{{queue}}
+ +

Remote SFW worker call test:{{test_rc_result}}

+

Key is OK:{{key_is_ok}}

+

License:{{license_status}}

+ +

This report is sent by cron task on: {{current_time}}

+
{{prev_report}}
+

Site service_id: {{service_id}}

+ + + '; + + //test RC + $test_rc_result = Helper::httpRequestRcToHostTest( + 'sfw_update__worker', + array( + 'spbc_remote_call_token' => md5(TT::toString($apbct->api_key)), + 'spbc_remote_call_action' => 'sfw_update__worker', + 'plugin_name' => 'apbct' + ) + ); + $test_rc_result = substr( + TT::toString($test_rc_result, 'INVALID RC RESULT'), + 0, + 300 + ); - if ( empty($ids_list) ) { - return false; - } + //license is active + $license_status = $apbct->data['moderate'] ? 'ACTIVE' : 'INACTIVE'; + + //key is ok + $key_is_ok = $apbct->data['key_is_ok'] ? 'TRUE' : 'FALSE'; + + return self::textPlateRender($template, [ + 'failed_count' => (string)count($idsList), + 'failed_rows' => $this->getFailedUpdatesHTML($idsList), + 'fw_stats' => $this->getFWStatsHTML(), + 'queue' => $this->getQueueJSONPretty(), + 'test_rc_result' => $test_rc_result, + 'license_status' => $license_status, + 'key_is_ok' => $key_is_ok, + 'current_time' => current_time('m-d-y H:i:s'), + 'prev_report' => $this->getPrevReportHTML($apbct->data), + 'service_id' => TT::toString($apbct->data['service_id']), + ]); + } - $to = 'pluginreports@cleantalk.org'; - $subject = "CleanTalk Service Report: SFW v" . APBCT_VERSION . " for " . Server::getString('HTTP_HOST'); - $message = ' - - - - - - -

- There were ' . count($ids_list) . ' unsuccesful SFW updates in a row: -

-

Negative report:

- - - - - - '; + /** + * Get failed updates HTML chunk. + * @param array $idsList + * @return string + */ + public function getFailedUpdatesHTML($idsList) + { + $failedRowsHtml = ''; $counter = 0; - - foreach ( $ids_list as $_id => $data ) { - $date = date('m-d-y H:i:s', TT::getArrayValueAsInt($data, 'started')); - $date = is_string($date) ? $date : 'Unknown date'; - $message .= '' - . '' - . '' - . '' - . ''; + foreach ($idsList as $id => $data) { + $date = date('m-d-y H:i:s', TT::getArrayValueAsInt($data, 'started')) ?: 'Unknown date'; + $failedRowsHtml .= self::textPlateRender( + '', + [ + 'index' => (string)($counter + 1), + 'id' => (string)$id, + 'date' => $date, + ] + ); } + return $failedRowsHtml; + } - $message .= '
 FW update IDStarted date
' . (++$counter) . '.' . $_id . '' . $date . '
{{index}}.{{id}}{{date}}
'; - $message .= '
'; - - $last_fw_stats_html = ''; - - foreach ( $this->last_fw_stats as $row_key => $value ) { - $last_fw_stats_html .= ''; - //clear root path - if ( $row_key === 'updating_folder' && !empty($value) ) { - preg_match('/^(.*?)[\/\\\]wp-content.*$/', $value, $to_delete); - if ( !empty($to_delete[1]) ) { - $value = str_replace($to_delete[1], "", $value); + /** + * Get Firewall Stats HTML chunk. + * @return string + */ + public function getFWStatsHTML() + { + $fwStatsHtml = ''; + foreach ($this->last_fw_stats as $key => $value) { + if ($key === 'updating_folder' && !empty($value)) { + preg_match('/^(.*?)[\/\\\]wp-content.*$/', $value, $matches); + if (!empty($matches[1])) { + $value = str_replace($matches[1], '', $value); } } - if ( !is_array($value) && !empty($value) ) { - $last_fw_stats_html .= ''; - } else { - $last_fw_stats_html .= ''; - } - $last_fw_stats_html .= ''; - } - - $last_fw_stats_html .= '
' . esc_html($row_key) . ': ' . esc_html($value) . 'No data
'; - - $message .= '

Last FW stats:

'; - $message .= '

' . $last_fw_stats_html . '

'; - $message .= '
'; - - $message .= '

This report is sent by cron task on: ' . current_time('m-d-y H:i:s') . '

'; - - $prev_date = !empty($apbct->data['sentinel_data']['prev_sent_try']['date']) - ? date('m-d-y H:i:s', $apbct->data['sentinel_data']['prev_sent_try']['date']) - : ''; - - if ( !empty($prev_date) ) { - $message .= '

Previous SFW failed update report were sent on ' . $prev_date . '

'; - } else { - $message .= '

There is no previous SFW failed update report.

'; + $fwStatsHtml .= self::textPlateRender( + '{{key}}:{{value}}', + [ + 'key' => $key, + 'value' => !is_array($value) && !empty($value) ? (string)$value : 'No data', + ] + ); } + return $fwStatsHtml; + } - $message .= '
Site service_id: ' . $apbct->data['service_id'] . '
'; - - $message .= ''; - - $headers = "Content-type: text/html; charset=utf-8 \r\n"; - $headers .= 'From: ' . ct_get_admin_email(); - - $sent = false; + /** + * Get previous reports HTML chunk. + * @return string + */ + public function getPrevReportHTML($apbct_data) + { + $prevDate = !empty($apbct_data['sentinel_data']['prev_sent_try']['date']) + ? date('m-d-y H:i:s', $apbct_data['sentinel_data']['prev_sent_try']['date']) + : 'unknown date'; + return !empty($prevDate) + ? "

Previous SFW failed update report was sent on {$prevDate}

" + : '

There is no previous SFW failed update report.

'; + } - /** @psalm-suppress UnusedFunctionCall */ - if ( wp_mail($to, $subject, $message, $headers) ) { - $sent = true; - } + /** + * Get JSON pretty string to show queue status. + * @return string + */ + public function getQueueJSONPretty() + { + $queue = get_option('cleantalk_sfw_update_queue'); + $queue = is_array($queue) ? $queue : array('Last queue not found or invalid.'); + $queue = json_encode($queue, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + return $queue !== false ? $queue : 'Can not construct queue JSON.'; + } - $apbct->data['sentinel_data']['prev_sent_try'] = !empty($apbct->data['sentinel_data']['last_sent_try']) - ? $apbct->data['sentinel_data']['last_sent_try'] - : false; + public function updateSentinelStats($sent) + { + global $apbct; - $apbct->data['sentinel_data']['last_sent_try'] = array( - 'date' => current_time('timestamp'), - 'success' => $sent - ); + $apbct->data['sentinel_data']['prev_sent_try'] = $apbct->data['sentinel_data']['last_sent_try'] ?? false; + $apbct->data['sentinel_data']['last_sent_try'] = [ + 'date' => current_time('timestamp'), + 'success' => $sent, + ]; $apbct->saveData(); } @@ -196,7 +273,7 @@ private function sendSentinelEmail() * Check if there are a number of unfinished firewall_updating_id on seek. * @return bool */ - private function hasNumberOfFailedUpdates($number) + public function hasNumberOfFailedUpdates($number) { if ( count($this->sentinel_ids) >= $number ) { return true; @@ -213,9 +290,13 @@ public function runWatchDog() global $apbct; $this->getSentinelData(); if ( $this->hasNumberOfFailedUpdates($this->number_of_failed_updates_to_check) ) { - if ( isset($apbct->settings['misc__send_connection_reports']) - && $apbct->settings['misc__send_connection_reports'] == 1 ) { - $this->sendSentinelEmail(); + $ids_list = $this->getSeekingIdsList(); + if ( + !empty($ids_list) && + isset($apbct->settings['misc__send_connection_reports']) && + $apbct->settings['misc__send_connection_reports'] == 1 + ) { + $this->sendSentinelEmail($ids_list); } //Clear and waiting for next unsucces FW updates $this->clearSentinelData(); diff --git a/lib/Cleantalk/Common/TextPlate.php b/lib/Cleantalk/Common/TextPlate.php new file mode 100644 index 000000000..970bafe3a --- /dev/null +++ b/lib/Cleantalk/Common/TextPlate.php @@ -0,0 +1,130 @@ + + * YourClass() { + * use TextPlate + * ... + * public function yourMethod() { + * $_text = 'Hello {{name}}!'; + * $_plate = ['name' => 'World']; + * $result = self::textPlateRender($_text, $_plate); + * } + * } + * + */ +trait TextPlate +{ + protected static $text_plate_left_brace = '{{'; + protected static $text_plate_right_brace = '}}'; + /** + * + * @param string $_text A template. + * @param array $_plate Replacements array. + * @param bool $trim Do trim? + * @return string + */ + public static function textPlateRender(string $_text, array $_plate, bool $trim = true): string + { + try { + $search = []; + $_text = $trim ? trim($_text) : $_text; + foreach ($_plate as $key => $value) { + $key = self::validatePlateKey($key, $_text); + $value = self::validatePlateValue($value, $key); + $search[self::getBraced($key)] = $value; + } + // fill + $result = strtr($_text, $search); + // validate + $result = self::validateResult($result); + } catch (\Exception $e) { + $result = self::getErrorString($e->getMessage()); + } + return $result; + } + + /** + * @param string $item + * @return string + */ + private static function getBraced(string $item): string + { + return static::$text_plate_left_brace . $item . static::$text_plate_right_brace; + } + + /** + * @param string $result + * @return string + * @throws \Exception + */ + private static function validateResult(string $result): string + { + $left_brace = preg_quote(static::$text_plate_left_brace, '#'); + $right_brace = preg_quote(static::$text_plate_right_brace, '#'); + $regexp = '#' . $left_brace . '\w+' . $right_brace . '#'; + $missed = ''; + preg_match_all($regexp, $result, $matches); + if (isset($matches[0])) { + $missed = implode(', ', $matches[0]); + } + if (!empty($missed)) { + throw new \Exception('UNFILLED PLACEHOLDER EXIST:' . $missed); + } + return $result; + } + + /** + * @param string $key + * @param string $_text + * @return string + * @throws \Exception + */ + private static function validatePlateKey(string $key, string $_text): string + { + if (strpos($_text, self::getBraced($key)) === false) { + throw new \Exception('NO PLACE FOR GIVEN PLACEHOLDER: ' . self::getBraced($key)); + } + return $key; + } + + /** + * @param $value + * @param $key + * @return string + * @throws \Exception + */ + private static function validatePlateValue($value, $key): string + { + if (!is_string($value)) { + throw new \Exception('INVALID PLACEHOLDER VALUE FOR GIVEN PLACEHOLDER: ' . $key); + } + return $value; + } + + /** + * @param string $error_string + * @return string + */ + private static function getErrorString(string $error_string): string + { + return 'TEXTPLATE_ERROR: ' . self::sanitizeError($error_string) . ', CALLED: ' . static::class; + } + + /** + * @param string $value + * @return string + */ + private static function sanitizeError(string $value): string + { + if (function_exists('esc_js')) { + $value = esc_js($value); + } + return $value; + } +} diff --git a/tests/ApbctWP/Firewall/TestSFWUpdateSentinel.php b/tests/ApbctWP/Firewall/TestSFWUpdateSentinel.php index 98dc598b7..cb3648f3a 100644 --- a/tests/ApbctWP/Firewall/TestSFWUpdateSentinel.php +++ b/tests/ApbctWP/Firewall/TestSFWUpdateSentinel.php @@ -1,16 +1,20 @@ apbct_copy = $apbct; $this->db = DB::getInstance(); $apbct = new State('cleantalk', array('settings', 'data', 'errors', 'remote_calls', 'stats', 'fw_stats')); $apbct->setSFWUpdateSentinel(); @@ -20,80 +24,188 @@ public function setUp(): void 'date' => 0, 'success' => false ); - $apbct->saveData(); - + //$apbct->saveData(); } - public function testAddingID() + protected function tearDown(): void { global $apbct; - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $this->assertIsInt($apbct->data['sentinel_data']['ids']['test_id_1']['started']); + $apbct = $this->apbct_copy; + + parent::tearDown(); } - public function testFinishID() + public function testSeekAndClear() { global $apbct; - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->clearSentinelData(); + + $s = new SFWUpdateSentinel(); + + $s->seekId('a'); + $s->seekId('b'); + + $this->assertCount(2, $apbct->data['sentinel_data']['ids']); + + $s->clearSentinelData(); + $this->assertEmpty($apbct->data['sentinel_data']['ids']); } - public function testNotEnoughUpdates() + public function testHasNumberOfFailedUpdatesBranches() { - global $apbct; - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->seekId('test_id_2'); - $apbct->sfw_update_sentinel->runWatchDog(); - $this->assertNotEmpty($apbct->data['sentinel_data']['ids']); - $this->assertFalse($apbct->data['sentinel_data']['last_sent_try']['success']); + $s = new SFWUpdateSentinel(); + + $s->seekId('1'); + $s->seekId('2'); + $s->seekId('3'); + + $this->assertTrue($s->hasNumberOfFailedUpdates(3)); + $this->assertFalse($s->hasNumberOfFailedUpdates(4)); + } + + public function testGetWatchDogCronPeriod() + { + $s = new SFWUpdateSentinel(); + + $this->assertEquals(43200, $s->getWatchDogCronPeriod()); } - public function testGoodUpdates() + public function testRunWatchDogDoesNothingIfNotEnoughIds() { global $apbct; - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->clearSentinelData(); - $apbct->sfw_update_sentinel->runWatchDog(); - $this->assertEmpty($apbct->data['sentinel_data']['ids']); + + $s = new SFWUpdateSentinel(); + $s->seekId('1'); + + $s->runWatchDog(); + + $this->assertEquals( + 0, + $apbct->data['sentinel_data']['last_sent_try']['date'] + ); } - public function testSeveralBadBeforeGoodUpdates() + public function testRunWatchDogDisabledInSettings() { global $apbct; - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->seekId('test_id_2'); - $apbct->sfw_update_sentinel->seekId('test_id_2'); - $apbct->sfw_update_sentinel->clearSentinelData(); - $apbct->sfw_update_sentinel->runWatchDog(); - $this->assertEmpty($apbct->data['sentinel_data']['ids']); + + $apbct->settings['misc__send_connection_reports'] = 0; + + $s = new SFWUpdateSentinel(); + $s->seekId('1'); + $s->seekId('2'); + $s->seekId('3'); + + $s->runWatchDog(); + + $this->assertEquals( + 0, + $apbct->data['sentinel_data']['last_sent_try']['date'] + ); } - public function testFailedUpdate() + public function testSuccessfulEmailSend() { global $apbct; + + $s = new SFWUpdateSentinel(); + $apbct->settings['misc__send_connection_reports'] = 1; - $apbct->saveSettings(); - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->seekId('test_id_2'); - $apbct->sfw_update_sentinel->seekId('test_id_3'); - $apbct->sfw_update_sentinel->runWatchDog(); - $this->assertEmpty($apbct->data['sentinel_data']['ids']); - $this->assertIsBool($apbct->data['sentinel_data']['last_sent_try']['success']); - $this->assertNotEquals($apbct->data['sentinel_data']['last_sent_try']['date'],0); + + $s->seekId('1'); + $s->seekId('2'); + $s->seekId('3'); + + $s->runWatchDog(); + + $this->assertNotEquals( + 0, + $apbct->data['sentinel_data']['last_sent_try']['date'] + ); + + $this->assertTrue( + $apbct->data['sentinel_data']['last_sent_try']['success'] + ); } - public function testDoNotSendReportIfDenied() + public function testFailedEmailSendBranch() { global $apbct; - $apbct->settings['misc__send_connection_reports'] = 0; - $apbct->saveSettings(); - $apbct->sfw_update_sentinel->seekId('test_id_1'); - $apbct->sfw_update_sentinel->seekId('test_id_2'); - $apbct->sfw_update_sentinel->seekId('test_id_3'); - $apbct->sfw_update_sentinel->runWatchDog(); - $this->assertEmpty($apbct->data['sentinel_data']['ids']); - $this->assertIsBool($apbct->data['sentinel_data']['last_sent_try']['success']); - $this->assertEquals($apbct->data['sentinel_data']['last_sent_try']['date'],0); + + $GLOBALS['__wp_mail_return'] = false; + + $s = new SFWUpdateSentinel(); + $s->seekId('1'); + $s->seekId('2'); + $s->seekId('3'); + + $s->runWatchDog(); + + $this->assertFalse( + $apbct->data['sentinel_data']['last_sent_try']['success'] + ); + + unset($GLOBALS['__wp_mail_return']); + } + + public function testHtmlGenerators() + { + global $apbct; + + $apbct->fw_stats = array + ( + 'firewall_updating' => 123, + 'updating_folder' => 'uploads\cleantalk_fw_files_for_blog_1', + 'firewall_updating_id' => null, + 'firewall_update_percent' => 0, + 'firewall_updating_last_start' => '2026-02-28 16:39:28', + 'expected_networks_count' => 0, + 'expected_networks_count_personal' => 1, + 'expected_ua_count' => 0, + 'expected_ua_count_personal' => 0, + 'update_mode' => 0, + 'reason_direct_update_log' => null, + 'multi_request_batch_size' => 10, + 'personal_lists_url_id' => '5486d23bc60dde935fd906d3145fd8bb', + 'common_lists_url_id' => '1aeb928b023fa748e81215fd551d108e', + 'calls' => 18 + ); + + $s = new SFWUpdateSentinel(); + + $s->seekId('abc'); + $html1 = $s->getFailedUpdatesHTML( + $apbct->data['sentinel_data']['ids'] + ); + $this->assertStringContainsString('abc', $html1); + + $html2 = $s->getFWStatsHTML(); + $this->assertStringContainsString('123', $html2); + $this->assertStringContainsString('2026-02-28 16:39:28', $html2); + $this->assertStringContainsString('reason_direct_update_log', $html2); + + $html3 = $s->getQueueJSONPretty(); + $this->assertIsString($html3); + $this->assertNotEmpty($html3); + $this->assertStringContainsString('Last queue not found or invalid.', $html3); + + update_option('cleantalk_sfw_update_queue', array( + 'stage' => 'some' + )); + $html3 = $s->getQueueJSONPretty(); + $this->assertIsString($html3); + $this->assertNotEmpty($html3); + $this->assertStringContainsString('some', $html3); + $this->assertStringContainsString('stage', $html3); + + $apbct->data['sentinel_data']['prev_sent_try'] = [ + 'date' => time(), + 'success' => true, + ]; + + update_option('cleantalk_sfw_update_queue', array()); + + $html4 = $s->getPrevReportHTML($apbct->data); + $this->assertStringContainsString('Previous', $html4); } } diff --git a/tests/ApbctWP/Helper/testApbctWPHelper.php b/tests/ApbctWP/Helper/testApbctWPHelper.php index 0a3cc49c3..15e8efff3 100644 --- a/tests/ApbctWP/Helper/testApbctWPHelper.php +++ b/tests/ApbctWP/Helper/testApbctWPHelper.php @@ -5,6 +5,21 @@ class testApbctWPHelper extends TestCase { + private $apbct_copy; + public function setUp(): void + { + global $apbct; + $this->apbct_copy = $apbct; + $apbct = new State('cleantalk', array('settings', 'data', 'errors', 'remote_calls', 'stats', 'fw_stats')); + } + + protected function tearDown(): void + { + global $apbct; + $apbct = $this->apbct_copy; + + parent::tearDown(); + } public function testHttpGetDataFromRemoteGzAndParseCsv() { $result = Helper::httpGetDataFromRemoteGzAndParseCsv(''); diff --git a/tests/ApbctWP/TestCleantalkSettingsTemplates.php b/tests/ApbctWP/TestCleantalkSettingsTemplates.php index 33981c698..830fb1c46 100644 --- a/tests/ApbctWP/TestCleantalkSettingsTemplates.php +++ b/tests/ApbctWP/TestCleantalkSettingsTemplates.php @@ -1,9 +1,26 @@ apbct_copy = $apbct; + $apbct = new State('cleantalk', array('settings', 'data', 'errors', 'remote_calls', 'stats', 'fw_stats')); + } + + protected function tearDown(): void + { + global $apbct; + $apbct = $this->apbct_copy; + + parent::tearDown(); + } public function testGet_options_template_ok() { $this->assertIsArray( CleantalkSettingsTemplates::getOptionsTemplate( getenv("CLEANTALK_TEST_API_KEY") ) ); }