From 97e092fd94194665e868446f634bd56ff2e781f4 Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Tue, 9 Jun 2026 13:16:18 +0700 Subject: [PATCH 1/4] New. Integration. Integration with Email Subscribers --- inc/cleantalk-ajax.php | 9 ----- inc/cleantalk-integrations-by-hook.php | 5 +++ inc/cleantalk-pluggable.php | 7 ++++ .../Integrations/EmailSubscribers.php | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php diff --git a/inc/cleantalk-ajax.php b/inc/cleantalk-ajax.php index 785536fbe..48d12a792 100644 --- a/inc/cleantalk-ajax.php +++ b/inc/cleantalk-ajax.php @@ -724,15 +724,6 @@ function ct_ajax_hook($message_obj = null) throw new Exception($ct_result->comment); } - //ES Add subscriber - if ( Post::get('action') === 'es_add_subscriber' ) { - $result = array( - 'error' => 'unexpected-error', - ); - print json_encode($result); - die(); - } - //Convertplug. Strpos because action value dynamically changes and depends on mailing service if ( strpos(TT::toString(Post::get('action')), '_add_subscriber') !== false ) { $result = array( diff --git a/inc/cleantalk-integrations-by-hook.php b/inc/cleantalk-integrations-by-hook.php index 9aee99706..57aa4aded 100755 --- a/inc/cleantalk-integrations-by-hook.php +++ b/inc/cleantalk-integrations-by-hook.php @@ -510,6 +510,11 @@ 'setting' => 'forms__contact_forms_test', 'ajax' => true ), + 'EmailSubscribers' => array( + 'hook' => 'es_add_subscriber', + 'setting' => 'forms__contact_forms_test', + 'ajax' => true + ), ); add_action('plugins_loaded', function () use ($apbct_active_integrations) { diff --git a/inc/cleantalk-pluggable.php b/inc/cleantalk-pluggable.php index f2fa74442..7f3490824 100644 --- a/inc/cleantalk-pluggable.php +++ b/inc/cleantalk-pluggable.php @@ -1744,6 +1744,13 @@ class_exists('Cleantalk\Antispam\Integrations\CleantalkInternalForms') ) { return 'invoicing'; } + + // Email Subscribers by Icegram Express - skip subscribe action + if ( + apbct_is_plugin_active('email-subscribers/email-subscribers.php') && + Post::equal('action', 'es_add_subscriber') ) { + return 'Email Subscribers by Icegram Express - skip subscribe action'; + } } else { /*****************************************/ /* Here is non-ajax requests skipping */ diff --git a/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php b/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php new file mode 100644 index 000000000..978f4d50a --- /dev/null +++ b/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php @@ -0,0 +1,33 @@ +getArray(); + + return $data; + } + + public function doBlock($message) + { + die( + json_encode( + array( + 'apbct' => array( + 'blocked' => true, + 'comment' => $message, + 'stop_script' => 1 + ) + ) + ) + ); + } +} From 310b408680b6ef3a403b64c0abba4b3ffc1fe50a Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Tue, 9 Jun 2026 13:17:33 +0700 Subject: [PATCH 2/4] fix --- inc/cleantalk-pluggable.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/cleantalk-pluggable.php b/inc/cleantalk-pluggable.php index 7f3490824..aaaf5f02c 100644 --- a/inc/cleantalk-pluggable.php +++ b/inc/cleantalk-pluggable.php @@ -1748,7 +1748,8 @@ class_exists('Cleantalk\Antispam\Integrations\CleantalkInternalForms') // Email Subscribers by Icegram Express - skip subscribe action if ( apbct_is_plugin_active('email-subscribers/email-subscribers.php') && - Post::equal('action', 'es_add_subscriber') ) { + Post::equal('action', 'es_add_subscriber') + ) { return 'Email Subscribers by Icegram Express - skip subscribe action'; } } else { From 9eb4f4f903c016c182bceaed68348ea7107393bf Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Tue, 9 Jun 2026 13:29:46 +0700 Subject: [PATCH 3/4] Untit tests --- .../TestEmailSubscribers.php | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 tests/Antispam/IntegrationsByHook/TestEmailSubscribers.php diff --git a/tests/Antispam/IntegrationsByHook/TestEmailSubscribers.php b/tests/Antispam/IntegrationsByHook/TestEmailSubscribers.php new file mode 100644 index 000000000..160ede44a --- /dev/null +++ b/tests/Antispam/IntegrationsByHook/TestEmailSubscribers.php @@ -0,0 +1,202 @@ +integration = new EmailSubscribers(); + } + + protected function tearDown(): void + { + // Clean up global state + $_POST = []; + Post::getInstance()->variables = []; + parent::tearDown(); + } + + /** + * Test getDataForChecking with valid subscription data + */ + public function testGetDataForCheckingWithValidData() + { + $_POST = [ + 'esfpx_email' => 'stop_email@example.com', + 'esfpx_name' => 'asfsgaeer1111', + 'es' => 'subscribe', + 'esfpx_form_id' => '2', + 'esfpx_es_form_identifier' => 'f2-p6-n1', + 'esfpx_es_email_page' => '6', + 'esfpx_es_email_page_url' => 'https://osp65-wp7.local/?page_id=6', + 'esfpx_status' => 'Unconfirmed', + 'esfpx_es-subscribe' => 'c0b8a6d0be', + 'esfpx_es_hp_email' => '', + 'esfpx_lists' => ['59ac7ed122f5'], + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('stop_email@example.com', $result['email']); + $this->assertEquals('asfsgaeer1111', $result['nickname']); + } + + /** + * Test getDataForChecking with email only (no name) + */ + public function testGetDataForCheckingWithEmailOnly() + { + $_POST = [ + 'esfpx_email' => 'user@example.com', + 'es' => 'subscribe', + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('user@example.com', $result['email']); + $this->assertEquals('', $result['nickname']); + } + + /** + * Test getDataForChecking with name only (no email) + */ + public function testGetDataForCheckingWithNameOnly() + { + $_POST = [ + 'esfpx_name' => 'TestUser', + 'es' => 'subscribe', + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('', $result['email']); + $this->assertEquals('TestUser', $result['nickname']); + } + + /** + * Test getDataForChecking with empty POST data + */ + public function testGetDataForCheckingWithEmptyPost() + { + $_POST = []; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('', $result['email']); + $this->assertEquals('', $result['nickname']); + } + + /** + * Test getDataForChecking with special characters in name + */ + public function testGetDataForCheckingWithSpecialCharactersInName() + { + $_POST = [ + 'esfpx_email' => 'special@example.com', + 'esfpx_name' => "O'Brien Müller", + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('special@example.com', $result['email']); + $this->assertStringContainsString("O'Brien", $result['nickname']); + } + + /** + * Test getDataForChecking with empty strings for email and name + */ + public function testGetDataForCheckingWithEmptyStrings() + { + $_POST = [ + 'esfpx_email' => '', + 'esfpx_name' => '', + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('', $result['email']); + $this->assertEquals('', $result['nickname']); + } + + /** + * Test getDataForChecking preserves full POST data for ct_gfa_dto processing + */ + public function testGetDataForCheckingPreservesPostData() + { + $_POST = [ + 'esfpx_email' => 'test@example.com', + 'esfpx_name' => 'TestName', + 'esfpx_form_id' => '5', + 'esfpx_es_form_identifier' => 'f5-p10-n1', + 'esfpx_es_email_page' => '10', + 'esfpx_es_email_page_url' => 'https://example.com/?page_id=10', + 'esfpx_status' => 'Unconfirmed', + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('test@example.com', $result['email']); + $this->assertEquals('TestName', $result['nickname']); + } + + /** + * Test getDataForChecking with multiple lists + */ + public function testGetDataForCheckingWithMultipleLists() + { + $_POST = [ + 'esfpx_email' => 'multi@example.com', + 'esfpx_name' => 'MultiList', + 'esfpx_lists' => ['list1hash', 'list2hash', 'list3hash'], + 'action' => 'es_add_subscriber', + ]; + + $result = $this->integration->getDataForChecking(null); + + $this->assertIsArray($result); + $this->assertEquals('multi@example.com', $result['email']); + $this->assertEquals('MultiList', $result['nickname']); + } + + /** + * Test doBlock method exists and has correct signature + */ + public function testDoBlockMethodExists() + { + // Note: doBlock() uses die() which is difficult to test properly + // This test verifies that the method exists and can be called + $this->assertTrue(method_exists($this->integration, 'doBlock')); + } + + /** + * Test doBlock method has correct signature + */ + public function testDoBlockMethodSignature() + { + // Note: Testing die() properly requires process isolation + // We verify the method signature and expected behavior + $reflection = new \ReflectionMethod($this->integration, 'doBlock'); + $this->assertTrue($reflection->isPublic()); + $this->assertEquals(1, $reflection->getNumberOfParameters()); + } +} From cb88a987ab5cbc8163fe832d3e6f93f8e1b420f8 Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Tue, 9 Jun 2026 13:50:20 +0700 Subject: [PATCH 4/4] Fix reviewe copilot --- lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php b/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php index 978f4d50a..1a375e1ea 100644 --- a/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php +++ b/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php @@ -2,8 +2,6 @@ namespace Cleantalk\Antispam\Integrations; -use Cleantalk\ApbctWP\Variables\Post; - class EmailSubscribers extends IntegrationBase { public function getDataForChecking($argument) @@ -24,7 +22,7 @@ public function doBlock($message) 'apbct' => array( 'blocked' => true, 'comment' => $message, - 'stop_script' => 1 + 'stop_script' => apbct__stop_script_after_ajax_checking() ) ) )