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..aaaf5f02c 100644 --- a/inc/cleantalk-pluggable.php +++ b/inc/cleantalk-pluggable.php @@ -1744,6 +1744,14 @@ 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..1a375e1ea --- /dev/null +++ b/lib/Cleantalk/Antispam/Integrations/EmailSubscribers.php @@ -0,0 +1,31 @@ +getArray(); + + return $data; + } + + public function doBlock($message) + { + die( + json_encode( + array( + 'apbct' => array( + 'blocked' => true, + 'comment' => $message, + 'stop_script' => apbct__stop_script_after_ajax_checking() + ) + ) + ) + ); + } +} 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()); + } +}