diff --git a/mailpoet/assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx b/mailpoet/assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx index 21c87b0e9d..e08c2ea8bb 100644 --- a/mailpoet/assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx +++ b/mailpoet/assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx @@ -57,8 +57,25 @@ function PlacementSettings({ settingsPlacementKey }: Props): JSX.Element { prefix = 'preview'; } + const placementSupportsArchives = settingsPlacementKey !== 'belowPosts'; + return ( <> + {placementSupportsArchives && ( + { + compose([ + changeFormSettings, + assocPath( + `formPlacement.${settingsPlacementKey}.homepage`, + newValue, + ), + ])(formSettings); + }} + /> + )} + {placementSupportsArchives && ( + <> + { + compose([ + changeFormSettings, + assocPath( + `formPlacement.${settingsPlacementKey}.tagArchives.all`, + newValue, + ), + cond([ + [ + // condition, if the predicate function is true the next compose is run + (): boolean => newValue, + compose([ + assocPath( + `formPlacement.${settingsPlacementKey}.tagArchives.selected`, + [], + ), // if enabled clear selected tags + ]), + ], + [(): boolean => !newValue, identity], // if disabled do nothing + ]), + ])(formSettings); + }} + /> +
+
+ { + const selected = + formSettings.formPlacement[settingsPlacementKey].tagArchives + .selected; + if (isEqual(selected, e.target.value)) { + return; + } + compose([ + changeFormSettings, + assocPath( + `formPlacement.${settingsPlacementKey}.tagArchives.selected`, + e.target.value, + ), + cond([ + [ + // only disable "All pages" toggle if not empty + (): boolean => !!e.target.value.length, + assocPath( + `formPlacement.${settingsPlacementKey}.tagArchives.all`, + false, + ), // disable all if some pages are selected + ], + [(): boolean => !e.target.value.length, identity], + ]), + ])(formSettings); + }} + field={{ + id: `${prefix}tagArchives`, + name: 'tagArchives', + values: tags, + multiple: true, + placeholder: MailPoet.I18n.t('selectSpecificArchiveTags'), + getLabel: (tag): void => tag.name, + selected: (): void => + formSettings.formPlacement[settingsPlacementKey].tagArchives + .selected, + }} + /> +
+
+ { + compose([ + changeFormSettings, + assocPath( + `formPlacement.${settingsPlacementKey}.categoryArchives.all`, + newValue, + ), + cond([ + [ + // condition, if the predicate function is true the next compose is run + (): boolean => newValue, + compose([ + assocPath( + `formPlacement.${settingsPlacementKey}.categoryArchives.selected`, + [], + ), // if enabled clear selected categories + ]), + ], + [(): boolean => !newValue, identity], // if disabled do nothing + ]), + ])(formSettings); + }} + /> +
+
+ { + const selected = + formSettings.formPlacement[settingsPlacementKey] + .categoryArchives.selected; + if (isEqual(selected, e.target.value)) { + return; + } + compose([ + changeFormSettings, + assocPath( + `formPlacement.${settingsPlacementKey}.categoryArchives.selected`, + e.target.value, + ), + cond([ + [ + // only disable "All pages" toggle if not empty + (): boolean => !!e.target.value.length, + assocPath( + `formPlacement.${settingsPlacementKey}.categoryArchives.all`, + false, + ), // disable all if some pages are selected + ], + [(): boolean => !e.target.value.length, identity], + ]), + ])(formSettings); + }} + field={{ + id: `${prefix}categoryArchives`, + name: 'categoryArchives', + values: categories, + multiple: true, + placeholder: MailPoet.I18n.t( + 'selectSpecificArchiveCategories', + ), + getLabel: (tag): void => tag.name, + selected: (): void => + formSettings.formPlacement[settingsPlacementKey] + .categoryArchives.selected, + }} + /> +
+
+ + )} ); } diff --git a/mailpoet/assets/js/src/form_editor/store/form_data_types.ts b/mailpoet/assets/js/src/form_editor/store/form_data_types.ts index 8cbabdbc43..c85f395c93 100644 --- a/mailpoet/assets/js/src/form_editor/store/form_data_types.ts +++ b/mailpoet/assets/js/src/form_editor/store/form_data_types.ts @@ -11,6 +11,9 @@ type FormPlacementBase = { tags: string[] | number[]; posts: { all: boolean | '' | '1'; selected: string[] }; pages: { all: boolean | '' | '1'; selected: string[] }; + homepage: boolean | '' | '1'; + tagArchives: { all: boolean | '' | '1'; selected: string[] }; + categoryArchives: { all: boolean | '' | '1'; selected: string[] }; }; export type FormSettingsType = { diff --git a/mailpoet/assets/js/src/form_editor/store/map_form_data_after_loading.jsx b/mailpoet/assets/js/src/form_editor/store/map_form_data_after_loading.jsx index 6cb5b49aa3..5ddf7fa773 100644 --- a/mailpoet/assets/js/src/form_editor/store/map_form_data_after_loading.jsx +++ b/mailpoet/assets/js/src/form_editor/store/map_form_data_after_loading.jsx @@ -45,6 +45,25 @@ export function mapFormDataAfterLoading(data) { ? data.settings.form_placement?.popup?.pages?.selected : [], }, + homepage: data.settings.form_placement?.popup?.homepage === '1', + tagArchives: { + all: data.settings.form_placement?.popup?.tagArchives?.all === '1', + selected: Array.isArray( + data.settings.form_placement?.popup?.tagArchives?.selected, + ) + ? data.settings.form_placement?.popup?.tagArchives?.selected + : [], + }, + categoryArchives: { + all: + data.settings.form_placement?.popup?.categoryArchives?.all === + '1', + selected: Array.isArray( + data.settings.form_placement?.popup?.categoryArchives?.selected, + ) + ? data.settings.form_placement?.popup?.categoryArchives?.selected + : [], + }, }, fixedBar: { enabled: data.settings.form_placement?.fixed_bar?.enabled === '1', @@ -85,6 +104,28 @@ export function mapFormDataAfterLoading(data) { ? data.settings.form_placement?.fixed_bar?.pages?.selected : [], }, + homepage: data.settings.form_placement?.fixed_bar?.homepage === '1', + tagArchives: { + all: + data.settings.form_placement?.fixed_bar?.tagArchives?.all === '1', + selected: Array.isArray( + data.settings.form_placement?.fixed_bar?.tagArchives?.selected, + ) + ? data.settings.form_placement?.fixed_bar?.tagArchives?.selected + : [], + }, + categoryArchives: { + all: + data.settings.form_placement?.fixed_bar?.categoryArchives?.all === + '1', + selected: Array.isArray( + data.settings.form_placement?.fixed_bar?.categoryArchives + ?.selected, + ) + ? data.settings.form_placement?.fixed_bar?.categoryArchives + ?.selected + : [], + }, }, belowPosts: { enabled: data.settings.form_placement?.below_posts?.enabled === '1', @@ -151,6 +192,28 @@ export function mapFormDataAfterLoading(data) { ? data.settings.form_placement?.slide_in?.pages?.selected : [], }, + homepage: data.settings.form_placement?.slide_in?.homepage === '1', + tagArchives: { + all: + data.settings.form_placement?.slide_in?.tagArchives?.all === '1', + selected: Array.isArray( + data.settings.form_placement?.slide_in?.tagArchives?.selected, + ) + ? data.settings.form_placement?.slide_in?.tagArchives?.selected + : [], + }, + categoryArchives: { + all: + data.settings.form_placement?.slide_in?.categoryArchives?.all === + '1', + selected: Array.isArray( + data.settings.form_placement?.slide_in?.categoryArchives + ?.selected, + ) + ? data.settings.form_placement?.slide_in?.categoryArchives + ?.selected + : [], + }, }, others: { styles: { diff --git a/mailpoet/assets/js/src/form_editor/store/map_form_data_before_saving.jsx b/mailpoet/assets/js/src/form_editor/store/map_form_data_before_saving.jsx index 463cb44a74..0b856c5bd6 100644 --- a/mailpoet/assets/js/src/form_editor/store/map_form_data_before_saving.jsx +++ b/mailpoet/assets/js/src/form_editor/store/map_form_data_before_saving.jsx @@ -32,6 +32,23 @@ export function mapFormDataBeforeSaving(data) { : '', selected: data.settings.formPlacement?.popup?.pages?.selected, }, + homepage: + data.settings.formPlacement?.popup?.homepage === true ? '1' : '', + tagArchives: { + all: + data.settings.formPlacement?.popup?.tagArchives?.all === true + ? '1' + : '', + selected: data.settings.formPlacement?.popup?.tagArchives?.selected, + }, + categoryArchives: { + all: + data.settings.formPlacement?.popup?.categoryArchives?.all === true + ? '1' + : '', + selected: + data.settings.formPlacement?.popup?.categoryArchives?.selected, + }, }, fixed_bar: { enabled: @@ -58,6 +75,25 @@ export function mapFormDataBeforeSaving(data) { : '', selected: data.settings.formPlacement?.fixedBar?.pages?.selected, }, + homepage: + data.settings.formPlacement?.fixedBar?.homepage === true ? '1' : '', + tagArchives: { + all: + data.settings.formPlacement?.fixedBar?.tagArchives?.all === true + ? '1' + : '', + selected: + data.settings.formPlacement?.fixedBar?.tagArchives?.selected, + }, + categoryArchives: { + all: + data.settings.formPlacement?.fixedBar?.categoryArchives?.all === + true + ? '1' + : '', + selected: + data.settings.formPlacement?.fixedBar?.categoryArchives?.selected, + }, }, below_posts: { enabled: @@ -107,6 +143,25 @@ export function mapFormDataBeforeSaving(data) { : '', selected: data.settings.formPlacement?.slideIn?.pages?.selected, }, + homepage: + data.settings.formPlacement?.slideIn?.homepage === true ? '1' : '', + tagArchives: { + all: + data.settings.formPlacement?.slideIn?.tagArchives?.all === true + ? '1' + : '', + selected: + data.settings.formPlacement?.slideIn?.tagArchives?.selected, + }, + categoryArchives: { + all: + data.settings.formPlacement?.slideIn?.categoryArchives?.all === + true + ? '1' + : '', + selected: + data.settings.formPlacement?.slideIn?.categoryArchives?.selected, + }, }, others: { styles: data.settings.formPlacement?.others?.styles, diff --git a/mailpoet/lib/Config/Hooks.php b/mailpoet/lib/Config/Hooks.php index 82c580726b..24ed0c181e 100644 --- a/mailpoet/lib/Config/Hooks.php +++ b/mailpoet/lib/Config/Hooks.php @@ -234,6 +234,10 @@ class Hooks { 'woocommerce_product_loop_end', [$this->displayFormInWPContent, 'wooProductListDisplay'] ); + $this->wp->addAction( + 'wp_footer', + [$this->displayFormInWPContent, 'maybeRenderFormsInFooter'] + ); } public function setupMailer() { diff --git a/mailpoet/lib/Form/DisplayFormInWPContent.php b/mailpoet/lib/Form/DisplayFormInWPContent.php index 441a695bb3..56e43131e9 100644 --- a/mailpoet/lib/Form/DisplayFormInWPContent.php +++ b/mailpoet/lib/Form/DisplayFormInWPContent.php @@ -61,6 +61,8 @@ class DisplayFormInWPContent { private $inWooProductLoop = false; + private $renderedDisplayTypes = []; + public function __construct( WPFunctions $wp, FormsRepository $formsRepository, @@ -81,43 +83,69 @@ class DisplayFormInWPContent { $this->woocommerceHelper = $woocommerceHelper; } - /** - * This takes input from an action and any plugin or theme can pass anything. - * We return string for regular content otherwise we just pass thru what comes. - * @param mixed $content - * @return string|mixed - */ - private function display($content = null) { - if (!is_string($content) || !$this->shouldDisplay()) return $content; - + private function getFormMarkup(): string { + $formMarkup = ''; $forms = $this->getForms(); if (count($forms) === 0) { - return $content; + return $formMarkup; + } + foreach ($forms as $displayType => $form) { + $formMarkup .= $this->getContentBellow($form, $displayType); } - $this->assetsController->setupFrontEndDependencies(); - $result = $content; - foreach ($forms as $displayType => $form) { - $result .= $this->getContentBellow($form, $displayType); - } - return $result; + return $formMarkup; } + /** + * Hooked to the_content filter + */ public function contentDisplay($content = null) { $this->inWooProductLoop = false; - return $this->display($content); + return $this->getContentWithFormMarkup($content); } + /** + * Hooked to woocommerce_product_loop_end filter + */ public function wooProductListDisplay($content = null) { $this->inWooProductLoop = true; - return $this->display($content); + return $this->getContentWithFormMarkup($content); + } + + private function getContentWithFormMarkup($content = null) { + if (!is_string($content) || !$this->shouldDisplay()) { + return $content; + } + $formsMarkup = $this->getFormMarkup(); + if ($formsMarkup === '') { + return $content; + } + $this->assetsController->setupFrontEndDependencies(); + return $content . $formsMarkup; + } + + /** + * Hooked to wp_footer action. + * + * @return void + */ + public function maybeRenderFormsInFooter(): void { + if ($this->wp->isArchive() || $this->wp->isFrontPage()) { + $formMarkup = $this->getFormMarkup(); + if (!empty($formMarkup)) { + $this->assetsController->setupFrontEndDependencies(); + // We are in control of the template and the data can be considered safe at this point + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPressDotOrg.sniffs.OutputEscaping.UnescapedOutputParameter + echo $formMarkup; + } + } } private function shouldDisplay(): bool { $result = true; // This is a fix Yoast plugin and Shapely theme compatibility // This is to make sure we only display once for each page - // Yast plugin calls `get_the_excerpt` which also triggers hook `the_content` we don't want to include our form in that + // Yoast plugin calls `get_the_excerpt` which also triggers hook `the_content` we don't want to include our form in that // Shapely calls the hook `the_content` multiple times on the page as well and we would display popup multiple times - not ideal if (!$this->wp->inTheLoop() || !$this->wp->isMainQuery()) { $result = $this->wp->applyFilters('mailpoet_display_form_is_main_loop', false); @@ -228,6 +256,7 @@ class DisplayFormInWPContent { // add API version $templateData['api_version'] = API::CURRENT_VERSION; + $this->renderedDisplayTypes[] = $displayType; return $this->templateRenderer->render('form/front_end_form.html', $templateData); } @@ -251,6 +280,9 @@ class DisplayFormInWPContent { } private function shouldDisplayFormType(FormEntity $form, string $formType): bool { + if ($this->wasDisplayTypeAlreadyRendered($formType)) { + return false; + } $settings = $form->getSettings(); // check the structure just to be sure @@ -267,6 +299,10 @@ class DisplayFormInWPContent { if (!$this->shouldDisplayFormForWPUser($form, $formType)) return false; + if ($this->wp->isFrontPage() && $this->shouldDisplayFormOnFrontPage($setup)) { + return true; + } + if ($this->wp->isSingular($this->wp->applyFilters('mailpoet_display_form_supported_post_types', self::SUPPORTED_POST_TYPES))) { if ($this->shouldDisplayFormOnPost($setup, 'posts')) return true; if ($this->shouldDisplayFormOnCategory($setup)) return true; @@ -277,6 +313,14 @@ class DisplayFormInWPContent { return true; } + if ($this->wp->isTag() || $this->wp->isTax('product_tag')) { + if ($this->shouldDisplayFormOnTagArchive($setup)) return true; + } + + if ($this->wp->isCategory() || $this->wp->isTax('product_cat')) { + if ($this->shouldDisplayFormOnCategoryArchive($setup)) return true; + } + if ($this->displayFormInProductListPage()) { // Allow form display on Woo Shop listing page if (is_null($this->wooShopPageId)) return false; @@ -313,4 +357,28 @@ class DisplayFormInWPContent { if ($this->wp->hasTerm($setup['tags'], 'product_tag')) return true; return false; } + + private function shouldDisplayFormOnFrontPage(array $setup): bool { + return ($setup['homepage'] ?? false) === '1'; + } + + private function shouldDisplayFormOnCategoryArchive($setup): bool { + if (!isset($setup['categoryArchives'])) return false; + if (($setup['categoryArchives']['all'] ?? false) === '1') return true; + $selectedCategories = $setup['categoryArchives']['selected'] ?? []; + if ($selectedCategories === []) return false; + return $this->wp->hasCategory($selectedCategories) || $this->wp->hasTerm($selectedCategories, 'product_cat'); + } + + private function shouldDisplayFormOnTagArchive($setup): bool { + if (!isset($setup['tagArchives'])) return false; + if (($setup['tagArchives']['all'] ?? false) === '1') return true; + $selectedTags = $setup['tagArchives']['selected'] ?? []; + if ($selectedTags === []) return false; + return $this->wp->hasTag($selectedTags) || $this->wp->hasTerm($selectedTags, 'product_tag'); + } + + private function wasDisplayTypeAlreadyRendered(string $displayType): bool { + return in_array($displayType, $this->renderedDisplayTypes); + } } diff --git a/mailpoet/lib/WP/Functions.php b/mailpoet/lib/WP/Functions.php index 8ea073b691..f5977ad3ae 100644 --- a/mailpoet/lib/WP/Functions.php +++ b/mailpoet/lib/WP/Functions.php @@ -643,6 +643,10 @@ class Functions { return is_main_query(); } + public function isFrontPage(): bool { + return is_front_page(); + } + public function getPrivacyPolicyUrl(): string { return get_privacy_policy_url(); } @@ -693,6 +697,18 @@ class Functions { return is_archive(); } + public function isTag($tag = '') { + return is_tag($tag); + } + + public function isCategory($category = '') { + return is_category($category); + } + + public function isTax($taxonomy = '', $term = '') { + return is_tax($taxonomy, $term); + } + /** * Determines whether the query is for an existing post type archive page. * diff --git a/mailpoet/tests/unit/Form/DisplayFormInWPContentTest.php b/mailpoet/tests/unit/Form/DisplayFormInWPContentTest.php index 7564afc1d4..5f64c2dcec 100644 --- a/mailpoet/tests/unit/Form/DisplayFormInWPContentTest.php +++ b/mailpoet/tests/unit/Form/DisplayFormInWPContentTest.php @@ -522,6 +522,198 @@ class DisplayFormInWPContentTest extends \MailPoetUnitTest { expect($result)->endsWith($formHtml); } + public function testDisplayFormOnAllTagArchives(): void { + $formHtml = '
'; + $this->wp->expects($this->any())->method('isTag')->willReturn(true); + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->assetsController->expects($this->once())->method('setupFrontEndDependencies'); + $this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'tagArchives' => ['all' => '1']], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals($formHtml); + } + + public function testItRendersOnlyForSpecificTagArchive(): void { + $formHtml = '
'; + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->wp->expects($this->any())->method('isTag')->willReturn(true); + $this->wp->expects($this->any())->method('hasTag')->willReturnCallback(function(array $tags) { + if (in_array('10', $tags)) { + return true; + } + + return false; + }); + $this->assetsController->expects($this->once())->method('setupFrontEndDependencies'); + $this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'tagArchives' => ['all' => '', 'selected' => ['10']]], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->any())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals($formHtml); + + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'categoryArchives' => ['all' => '', 'selected' => ['15']]], + ], + 'success_message' => 'Hello', + ]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals(''); + } + + public function testItDoesNotDisplayOnTagListingIfNotEnabled(): void { + $this->wp->expects($this->any())->method('isTag')->willReturn(true); + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->assetsController->expects($this->never())->method('setupFrontEndDependencies'); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'tagArchives' => ['all' => '']], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals(''); + } + + public function testDisplayFormOnAllCategoryArchives(): void { + $formHtml = '
'; + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->wp->expects($this->any())->method('isCategory')->willReturn(true); + $this->assetsController->expects($this->once())->method('setupFrontEndDependencies'); + $this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'categoryArchives' => ['all' => '1']], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals($formHtml); + } + + public function testItRendersOnlyForSpecificCategoryArchive(): void { + $formHtml = '
'; + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->wp->expects($this->any())->method('isCategory')->willReturn(true); + $this->wp->expects($this->any())->method('hasCategory')->willReturnCallback(function(array $categories) { + return in_array('10', $categories); + }); + $this->assetsController->expects($this->once())->method('setupFrontEndDependencies'); + $this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'categoryArchives' => ['all' => '', 'selected' => ['10']]], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->any())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals($formHtml); + + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'categoryArchives' => ['all' => '', 'selected' => ['15']]], + ], + 'success_message' => 'Hello', + ]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals(''); + } + + public function testItDoesNotDisplayOnCategoryListingIfNotEnabled(): void { + $this->wp->expects($this->any())->method('isArchive')->willReturn(true); + $this->wp->expects($this->any())->method('isCategory')->willReturn(true); + $this->assetsController->expects($this->never())->method('setupFrontEndDependencies'); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', '', 'categoryArchives' => ['all' => '']], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals(''); + } + + public function testItDisplaysOnHomepage(): void { + $formHtml = '
'; + $this->wp->expects($this->any())->method('isFrontPage')->willReturn(true); + $this->assetsController->expects($this->once())->method('setupFrontEndDependencies'); + $this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml); + $form = new FormEntity('My Form'); + $form->setSettings([ + 'segments' => ['3'], + 'form_placement' => [ + 'popup' => ['enabled' => '1', 'homepage' => '1'], + ], + 'success_message' => 'Hello', + ]); + $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); + $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); + + ob_start(); + $this->hook->maybeRenderFormsInFooter(); + $renderedFormHtml = ob_get_clean(); + expect($renderedFormHtml)->equals($formHtml); + } + public function testDoesNotAppendPopupFormIfLoggedInAndSubscribed() { $formHtml = '
'; $subscriber = new SubscriberEntity(); @@ -532,16 +724,16 @@ class DisplayFormInWPContentTest extends \MailPoetUnitTest { $this->assetsController->expects($this->never())->method('setupFrontEndDependencies'); $this->templateRenderer->expects($this->never())->method('render')->willReturn($formHtml); $this->wp - ->expects($this->never()) - ->method('setTransient'); + ->expects($this->never()) + ->method('setTransient'); $form = new FormEntity('My Form'); $form->setSettings([ - 'segments' => ['3'], - 'form_placement' => [ - 'below_posts' => ['enabled' => '', 'pages' => ['all' => ''], 'posts' => ['all' => '']], - 'popup' => ['enabled' => '1', 'pages' => ['all' => '1'], 'posts' => ['all' => '']], - ], - 'success_message' => 'Hello', + 'segments' => ['3'], + 'form_placement' => [ + 'below_posts' => ['enabled' => '', 'pages' => ['all' => ''], 'posts' => ['all' => '']], + 'popup' => ['enabled' => '1', 'pages' => ['all' => '1'], 'posts' => ['all' => '']], + ], + 'success_message' => 'Hello', ]); $form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]); $this->repository->expects($this->once())->method('findBy')->willReturn([$form]); diff --git a/mailpoet/views/form/editor.html b/mailpoet/views/form/editor.html index 315d005540..446f81c3ca 100644 --- a/mailpoet/views/form/editor.html +++ b/mailpoet/views/form/editor.html @@ -95,6 +95,7 @@ 'placeFormBellowPagesDescription': __('This form placement allows you to add this form at the end of all the pages or posts, below the content.'), 'placeFormOnAllPages': _x('Display on all pages', 'This is a text on a switch if a form should be displayed bellow all pages'), 'placeFormOnAllPosts': _x('Display on all posts/products', 'This is a text on a switch if a form should be displayed bellow all posts'), + 'placeFormOnHomepage': __('Display on the homepage'), 'placeFormOthers': _x('Others (widget)', 'Placement of the form using theme widget'), 'formPlacementDelay': _x('Display with a delay of', 'Label on a selection of different times'), 'formPlacementPlacementPosition': _x('Position', 'Placement of a fixed bar form, on top of the page or on the bottom'), @@ -133,7 +134,11 @@ 'customFieldTypeSelect': _x('Select', 'Form input type'), 'selectPage': _x('Select', 'It is a placeholder in the select box - verb'), 'displayOnCategories': __('Display on posts with these categories'), + 'displayOnAllCategoryArchives': __('Display on all post/product category archives'), 'displayOnTags': __('Display on posts with these tags'), + 'displayOnAllTagArchives': __('Display on all post/product tag archives'), + 'selectSpecificArchiveTags': __('Select specific tags'), + 'selectSpecificArchiveCategories': __('Select specific categories'), 'customFieldTypeDate': __('Date'), 'customFieldDateType': __('Type of date'), 'customFieldDateFormat': __('Order'),