diff --git a/lib/API/API.php b/lib/API/API.php index 174c828553..ce86f0ce0e 100644 --- a/lib/API/API.php +++ b/lib/API/API.php @@ -3,6 +3,7 @@ namespace MailPoet\API; use MailPoet\Util\Helpers; use MailPoet\Util\Security; +use MailPoet\WP\Hooks; if(!defined('ABSPATH')) exit; @@ -40,7 +41,7 @@ class API { } function setupAjax() { - do_action('mailpoet_api_setup', array($this)); + Hooks::doAction('mailpoet_api_setup', array($this)); $this->getRequestData($_POST); diff --git a/lib/API/Endpoints/Newsletters.php b/lib/API/Endpoints/Newsletters.php index 4c68b9444a..6536f60b59 100644 --- a/lib/API/Endpoints/Newsletters.php +++ b/lib/API/Endpoints/Newsletters.php @@ -15,6 +15,7 @@ use MailPoet\Models\Subscriber; use MailPoet\Newsletter\Renderer\Renderer; use MailPoet\Newsletter\Scheduler\Scheduler; use MailPoet\Newsletter\Url as NewsletterUrl; +use MailPoet\WP\Hooks; if(!defined('ABSPATH')) exit; @@ -33,7 +34,7 @@ class Newsletters extends APIEndpoint { ->withSegments() ->withOptions() ->asArray(); - $newsletter = apply_filters('mailpoet_api_newsletters_get_after', $newsletter); + $newsletter = Hooks::applyFilters('mailpoet_api_newsletters_get_after', $newsletter); return $this->successResponse($newsletter); } } @@ -51,7 +52,7 @@ class Newsletters extends APIEndpoint { unset($data['options']); } - $data = apply_filters('mailpoet_api_newsletters_save_before', $data); + $data = Hooks::applyFilters('mailpoet_api_newsletters_save_before', $data); $newsletter = Newsletter::createOrUpdate($data); $errors = $newsletter->getErrors(); @@ -109,7 +110,7 @@ class Newsletters extends APIEndpoint { } } - do_action('mailpoet_api_newsletters_save_after', $newsletter); + Hooks::doAction('mailpoet_api_newsletters_save_after', $newsletter); return $this->successResponse($newsletter->asArray()); } @@ -208,7 +209,7 @@ class Newsletters extends APIEndpoint { if(!empty($errors)) { return $this->errorResponse($errors); } else { - do_action('mailpoet_api_newsletters_duplicate_after', $newsletter, $duplicate); + Hooks::doAction('mailpoet_api_newsletters_duplicate_after', $newsletter, $duplicate); return $this->successResponse( Newsletter::findOne($duplicate->id)->asArray(), array('count' => 1) diff --git a/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php b/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php index 1cdc914eae..aac13507a9 100644 --- a/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php +++ b/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php @@ -10,6 +10,7 @@ use MailPoet\Models\Setting; use MailPoet\Newsletter\Links\Links as NewsletterLinks; use MailPoet\Newsletter\Renderer\PostProcess\OpenTracking; use MailPoet\Util\Helpers; +use MailPoet\WP\Hooks; if(!defined('ABSPATH')) exit; @@ -36,7 +37,7 @@ class Newsletter { $this->tracking_image_inserted = OpenTracking::addTrackingImage(); // render newsletter $rendered_newsletter = $newsletter->render(); - $rendered_newsletter = apply_filters( + $rendered_newsletter = Hooks::applyFilters( 'mailpoet_sending_newsletter_render_after', $rendered_newsletter, $newsletter @@ -46,7 +47,7 @@ class Newsletter { } else { // render newsletter $rendered_newsletter = $newsletter->render(); - $rendered_newsletter = apply_filters( + $rendered_newsletter = Hooks::applyFilters( 'mailpoet_sending_newsletter_render_after', $rendered_newsletter, $newsletter diff --git a/lib/WP/Hooks.php b/lib/WP/Hooks.php new file mode 100644 index 0000000000..530c7895ac --- /dev/null +++ b/lib/WP/Hooks.php @@ -0,0 +1,28 @@ +errors[0]['message']) ->equals('This newsletter does not exist.'); + WPHooksHelper::interceptApplyFilters(); + $response = $router->get(array('id' => $this->newsletter->id)); expect($response->status)->equals(APIResponse::STATUS_OK); expect($response->data)->equals( @@ -51,6 +54,9 @@ class NewslettersTest extends MailPoetTest { ->withOptions() ->asArray() ); + $hook_name = 'mailpoet_api_newsletters_get_after'; + expect(WPHooksHelper::isFilterApplied($hook_name))->true(); + expect(WPHooksHelper::getFilterApplied($hook_name)[0])->internalType('array'); } function testItCanSaveANewNewsletter() { @@ -67,6 +73,9 @@ class NewslettersTest extends MailPoetTest { ) ); + WPHooksHelper::interceptApplyFilters(); + WPHooksHelper::interceptDoAction(); + $router = new Newsletters(); $response = $router->save($valid_data); $saved_newsletter = Newsletter::filter('filterWithOptions') @@ -76,6 +85,14 @@ class NewslettersTest extends MailPoetTest { // newsletter option should be saved expect($saved_newsletter->some_option)->equals('some_option_value'); + $hook_name = 'mailpoet_api_newsletters_save_before'; + expect(WPHooksHelper::isFilterApplied($hook_name))->true(); + expect(WPHooksHelper::getFilterApplied($hook_name)[0])->internalType('array'); + $hook_name = 'mailpoet_api_newsletters_save_after'; + expect(WPHooksHelper::isActionDone($hook_name))->true(); + expect(WPHooksHelper::getActionDone($hook_name)[0] instanceof Newsletter)->true(); + + $invalid_data = array( 'subject' => 'Missing newsletter type' ); @@ -305,6 +322,8 @@ class NewslettersTest extends MailPoetTest { } function testItCanDuplicateANewsletter() { + WPHooksHelper::interceptDoAction(); + $router = new Newsletters(); $response = $router->duplicate(array('id' => $this->newsletter->id)); expect($response->status)->equals(APIResponse::STATUS_OK); @@ -315,6 +334,10 @@ class NewslettersTest extends MailPoetTest { ); expect($response->meta['count'])->equals(1); + $hook_name = 'mailpoet_api_newsletters_duplicate_after'; + expect(WPHooksHelper::isActionDone($hook_name))->true(); + expect(WPHooksHelper::getActionDone($hook_name)[0] instanceof Newsletter)->true(); + $response = $router->duplicate(array('id' => $this->post_notification->id)); expect($response->status)->equals(APIResponse::STATUS_OK); expect($response->data)->equals( @@ -614,6 +637,7 @@ class NewslettersTest extends MailPoetTest { } function _after() { + WPHooksHelper::releaseAllHooks(); ORM::raw_execute('TRUNCATE ' . Newsletter::$_table); ORM::raw_execute('TRUNCATE ' . NewsletterSegment::$_table); ORM::raw_execute('TRUNCATE ' . NewsletterOptionField::$_table); diff --git a/tests/unit/Cron/Workers/SendingQueue/Tasks/NewsletterTest.php b/tests/unit/Cron/Workers/SendingQueue/Tasks/NewsletterTest.php index 0dabd266df..8e71d4d244 100644 --- a/tests/unit/Cron/Workers/SendingQueue/Tasks/NewsletterTest.php +++ b/tests/unit/Cron/Workers/SendingQueue/Tasks/NewsletterTest.php @@ -1,5 +1,6 @@ newsletter_task; $newsletter_task->tracking_enabled = true; $newsletter_task->getAndPreProcess($this->queue); @@ -58,9 +60,15 @@ class NewsletterTaskTest extends MailPoetTest { ->contains('[mailpoet_click_data]-' . $link->hash); expect($rendered_newsletter['html']) ->contains('[mailpoet_open_data]'); + + $hook_name = 'mailpoet_sending_newsletter_render_after'; + expect(WPHooksHelper::isFilterApplied($hook_name))->true(); + expect(WPHooksHelper::getFilterApplied($hook_name)[0])->internalType('array'); + expect(WPHooksHelper::getFilterApplied($hook_name)[1] instanceof Newsletter)->true(); } function testItDoesNotHashLinksAndInsertTrackingCodeWhenTrackingIsDisabled() { + WPHooksHelper::interceptApplyFilters(); $newsletter_task = $this->newsletter_task; $newsletter_task->tracking_enabled = false; $newsletter_task->getAndPreProcess($this->queue); @@ -73,6 +81,11 @@ class NewsletterTaskTest extends MailPoetTest { ->notContains('[mailpoet_click_data]'); expect($rendered_newsletter['html']) ->notContains('[mailpoet_open_data]'); + + $hook_name = 'mailpoet_sending_newsletter_render_after'; + expect(WPHooksHelper::isFilterApplied($hook_name))->true(); + expect(WPHooksHelper::getFilterApplied($hook_name)[0])->internalType('array'); + expect(WPHooksHelper::getFilterApplied($hook_name)[1] instanceof Newsletter)->true(); } function testItReturnsFalseAndDeletesNewsletterWhenPostNotificationContainsNoPostsn() { @@ -168,6 +181,7 @@ class NewsletterTaskTest extends MailPoetTest { } function _after() { + WPHooksHelper::releaseAllHooks(); ORM::raw_execute('TRUNCATE ' . Subscriber::$_table); ORM::raw_execute('TRUNCATE ' . Newsletter::$_table); ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table); diff --git a/tests/unit/Newsletter/Links/LinksTest.php b/tests/unit/Newsletter/Links/LinksTest.php index 18ab17cd4c..f1bc437122 100644 --- a/tests/unit/Newsletter/Links/LinksTest.php +++ b/tests/unit/Newsletter/Links/LinksTest.php @@ -49,6 +49,31 @@ class LinksTest extends MailPoetTest { expect($updated_content)->notContains('link'); } + function testItDoesNotReplaceUnprocessedLinks() { + $template = 'some site [link:some_link_shortcode]'; + $extracted_links = Links::extract($template); + + $processed_links = array( + 'http://link1.com' => array( + 'url' => 'http://link1.com', + 'processed_link' => 'replace by this' + ) + ); + + list($updated_content, $replaced_links) = + Links::replace($template, $extracted_links, $processed_links); + + // 1 links was replaced + expect(count($replaced_links))->equals(1); + // links in returned content were replaced with hashes + expect($updated_content) + ->contains('replace by this'); + expect($updated_content) + ->contains('[link:some_link_shortcode]'); + expect($updated_content)->notContains('http://link1.com'); + } + + function testItCreatesAndTransformsUrlDataObject() { $subscriber_email = 'test@example.com'; $data = array( diff --git a/tests/unit/WP/HooksTest.php b/tests/unit/WP/HooksTest.php new file mode 100644 index 0000000000..ff4caad0d7 --- /dev/null +++ b/tests/unit/WP/HooksTest.php @@ -0,0 +1,44 @@ +action = 'mailpoet_test_action'; + $this->filter = 'mailpoet_test_filter'; + } + + function testItCanProcessActions() { + $test_value = array('abc', 'def'); + $test_value2 = new StdClass; + $called = false; + + $callback = function ($value, $value2) use ($test_value, $test_value2, &$called) { + $called = true; + expect($value)->same($test_value); + expect($value2)->same($test_value2); + }; + + Hooks::addAction($this->action, $callback, 10, 2); + Hooks::doAction($this->action, $test_value, $test_value2); + + expect($called)->true(); + } + + function testItCanProcessFilters() { + $test_value = array('abc', 'def'); + + $called = false; + + $callback = function ($value) use ($test_value, &$called) { + $called = true; + return $test_value; + }; + + Hooks::addFilter($this->filter, $callback); + $result = Hooks::applyFilters($this->filter, $test_value); + + expect($called)->true(); + expect($result)->equals($test_value); + } +}