diff --git a/lib/Config/Hooks.php b/lib/Config/Hooks.php index f130df4328..6c9f51d725 100644 --- a/lib/Config/Hooks.php +++ b/lib/Config/Hooks.php @@ -3,6 +3,7 @@ namespace MailPoet\Config; use MailPoet\DynamicSegments\DynamicSegmentHooks; +use MailPoet\Form\DisplayFormInWPContent; use MailPoet\Mailer\WordPress\Replacer; use MailPoet\Mailer\WordPress\WordpressMailerReplacer; use MailPoet\Newsletter\Scheduler\PostNotificationScheduler; @@ -58,6 +59,9 @@ class Hooks { /** @var DynamicSegmentHooks */ private $dynamicSegmentHooks; + /** @var DisplayFormInWPContent */ + private $displayFormInWPContent; + public function __construct( Form $subscriptionForm, Comment $subscriptionComment, @@ -71,6 +75,7 @@ class Hooks { WooCommercePurchases $woocommercePurchases, PostNotificationScheduler $postNotificationScheduler, WordpressMailerReplacer $wordpressMailerReplacer, + DisplayFormInWPContent $displayFormInWPContent, DynamicSegmentHooks $dynamicSegmentHooks ) { $this->subscriptionForm = $subscriptionForm; @@ -86,6 +91,7 @@ class Hooks { $this->postNotificationScheduler = $postNotificationScheduler; $this->wordpressMailerReplacer = $wordpressMailerReplacer; $this->dynamicSegmentHooks = $dynamicSegmentHooks; + $this->displayFormInWPContent = $displayFormInWPContent; } public function init() { @@ -195,6 +201,10 @@ class Hooks { 'admin_post_nopriv_mailpoet_subscription_form', [$this->subscriptionForm, 'onSubmit'] ); + $this->wp->addFilter( + 'the_content', + [$this->displayFormInWPContent, 'display'] + ); } public function setupMailer() { diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 4e8aa5681e..b6769cee60 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -168,6 +168,7 @@ class ContainerConfigurator implements IContainerConfigurator { // Form $container->autowire(\MailPoet\Form\Util\FieldNameObfuscator::class)->setPublic(true); $container->autowire(\MailPoet\Form\AssetsController::class); + $container->autowire(\MailPoet\Form\DisplayFormInWPContent::class); $container->autowire(\MailPoet\Form\FormsRepository::class); $container->autowire(\MailPoet\Form\Util\Styles::class); // Helpscout diff --git a/lib/Form/DisplayFormInWPContent.php b/lib/Form/DisplayFormInWPContent.php new file mode 100644 index 0000000000..460de13365 --- /dev/null +++ b/lib/Form/DisplayFormInWPContent.php @@ -0,0 +1,56 @@ +wp = $wp; + $this->formsRepository = $formsRepository; + } + + // TODO remove transient in the api on form save + + public function display(string $content): string { + $result = $content; + if (!$this->wp->isSingle()) return $result; + $forms = $this->formsRepository->findAll(); + foreach ($forms as $form) { + $result .= $this->getContentBellow($form); + } + return $result; + } + + private function getContentBellow(FormEntity $form): string { + if (!$this->shouldDisplayFormBellowContent($form)) return ''; + return Renderer::render([ + 'body' => $form->getBody(), + 'styles' => $form->getStyles(), + ]); + } + + private function shouldDisplayFormBellowContent(FormEntity $form): bool { + $settings = $form->getSettings(); + if (!is_array($settings)) return false; + if (!isset($settings['placeFormBellowAllPosts'])) return false; + if ( + ($settings['placeFormBellowAllPosts'] === '1') + && !$this->wp->isPage() + ) return true; + if ( + ($settings['placeFormBellowAllPages'] === '1') + && $this->wp->isPage() + ) return true; + return false; + } + +} diff --git a/tests/unit/Form/DisplayFormInWPContentTest.php b/tests/unit/Form/DisplayFormInWPContentTest.php new file mode 100644 index 0000000000..fd48a2cc38 --- /dev/null +++ b/tests/unit/Form/DisplayFormInWPContentTest.php @@ -0,0 +1,167 @@ +createMock(SettingsController::class); + SettingsController::setInstance($settings); + + $this->repository = $this->createMock(FormsRepository::class); + $this->wp = $this->createMock(WPFunctions::class); + $this->hook = new DisplayFormInWPContent($this->wp, $this->repository); + } + + public function testAppendsRenderedFormAfterPostContent() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(true); + $this->wp->expects($this->any())->method('isPage')->willReturn(false); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '', + 'placeFormBellowAllPosts' => '1', + ]); + $form->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe!'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $this->repository->expects($this->once())->method('findAll')->willReturn([$form]); + + $result = $this->hook->display('content'); + expect($result)->notEquals('content'); + expect($result)->regExp('/content.*input type="submit"/is'); + } + + public function testDoesNotAppendFormIfDisabled() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(true); + $this->wp->expects($this->any())->method('isPage')->willReturn(false); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '', + 'placeFormBellowAllPosts' => '', + ]); + $form->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe!'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $this->repository->expects($this->once())->method('findAll')->willReturn([$form]); + + $result = $this->hook->display('content'); + expect($result)->equals('content'); + } + + public function testAppendsMultipleRenderedFormAfterPostContent() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(true); + $this->wp->expects($this->any())->method('isPage')->willReturn(false); + $form1 = new FormEntity('My Form'); + $form1->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '', + 'placeFormBellowAllPosts' => '1', + ]); + $form1->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe1'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $form2 = new FormEntity('My Form'); + $form2->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '', + 'placeFormBellowAllPosts' => '1', + ]); + $form2->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe2'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $this->repository->expects($this->once())->method('findAll')->willReturn([$form1, $form2]); + + $result = $this->hook->display('content'); + expect($result)->notEquals('content'); + expect($result)->regExp('/content.*input.*value="Subscribe1".*input.*value="Subscribe2"/is'); + } + + public function testDoesNotAppendFormIfNotOnSinglePage() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(false); + $this->repository->expects($this->never())->method('findAll'); + + $result = $this->hook->display('content'); + expect($result)->equals('content'); + } + + public function testDoesNotAppendFormIfNotOnPost() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(true); + $this->wp->expects($this->once())->method('isPage')->willReturn(true); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '', + 'placeFormBellowAllPosts' => '1', + ]); + $form->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe!'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $this->repository->expects($this->once())->method('findAll')->willReturn([$form]); + + $result = $this->hook->display('content'); + expect($result)->equals('content'); + } + + public function testAppendsRenderedFormAfterPageContent() { + $this->wp->expects($this->once())->method('isSingle')->willReturn(true); + $this->wp->expects($this->any())->method('isPage')->willReturn(true); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'placeFormBellowAllPages' => '1', + 'placeFormBellowAllPosts' => '', + ]); + $form->setBody([[ + 'type' => 'submit', + 'params' => ['label' => 'Subscribe!'], + 'id' => 'submit', + 'name' => 'Submit', + ]]); + $this->repository->expects($this->once())->method('findAll')->willReturn([$form]); + + $result = $this->hook->display('content'); + expect($result)->notEquals('content'); + expect($result)->regExp('/content.*input type="submit"/is'); + } + + public function testSetsTransientToImprovePerformance() { + + } + + public function testDoesNotQueryDatabaseIfTransientIsSet() { + + } + +}