From a570fa164150d6a4ff3600ec21cba7cda26f5b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lys=C3=BD?= Date: Tue, 3 Dec 2024 19:58:59 +0100 Subject: [PATCH] Wrap personalization Tag token with square brackets Because Gutenberg RichText component does not render square brackets around the HTML comment. We need to append those brackets to tag tokens and expected them when we replace tags by their values. [MAILPOET-6354] --- .../class-personalization-tag.php | 5 +- .../src/Engine/class-personalizer.php | 4 +- .../integration/Engine/Personalizer_Test.php | 22 ++++----- .../Personalization_Tags_Registry_Test.php | 47 +++++++++++++++---- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php b/packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php index c03b4de946..2887f0cbe9 100644 --- a/packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php +++ b/packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php @@ -72,8 +72,9 @@ class Personalization_Tag { callable $callback, array $attributes = array() ) { - $this->name = $name; - $this->token = $token; + $this->name = $name; + // Because Gutenberg does not wrap the token with square brackets, we need to add them here. + $this->token = strpos( $token, '[' ) === 0 ? $token : "[$token]"; $this->category = $category; $this->callback = $callback; $this->attributes = $attributes; diff --git a/packages/php/email-editor/src/Engine/class-personalizer.php b/packages/php/email-editor/src/Engine/class-personalizer.php index 1a0791a523..3126836ce3 100644 --- a/packages/php/email-editor/src/Engine/class-personalizer.php +++ b/packages/php/email-editor/src/Engine/class-personalizer.php @@ -112,8 +112,8 @@ class Personalizer { ); // Step 1: Separate the tag and attributes. - if ( preg_match( '/^([a-zA-Z0-9\-\/]+)\s*(.*)$/', trim( $token ), $matches ) ) { - $result['token'] = $matches[1]; // The tag part (e.g., "mailpoet/subscriber-firstname"). + if ( preg_match( '/^\[([a-zA-Z0-9\-\/]+)\s*(.*?)\]$/', trim( $token ), $matches ) ) { + $result['token'] = "[{$matches[1]}]"; // The tag part (e.g., "[mailpoet/subscriber-firstname]"). $attributes_string = $matches[2]; // The attributes part (e.g., 'default="subscriber"'). // Step 2: Extract attributes from the attribute string. diff --git a/packages/php/email-editor/tests/integration/Engine/Personalizer_Test.php b/packages/php/email-editor/tests/integration/Engine/Personalizer_Test.php index f9871abe29..cca78c74d4 100644 --- a/packages/php/email-editor/tests/integration/Engine/Personalizer_Test.php +++ b/packages/php/email-editor/tests/integration/Engine/Personalizer_Test.php @@ -55,7 +55,7 @@ class Personalizer_Test extends \MailPoetTest { ); $this->personalizer->set_context( array( 'subscriber_name' => 'John' ) ); - $html_content = '

Hello, !

'; + $html_content = '

Hello, !

'; $this->assertSame( '

Hello, John!

', $this->personalizer->personalize_content( $html_content ) ); } @@ -67,7 +67,7 @@ class Personalizer_Test extends \MailPoetTest { $this->tags_registry->register( new Personalization_Tag( 'first_name', - 'user/firstname', + '[user/firstname]', 'Subscriber Info', function ( $context, $args ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- The $args parameter is not used in this test. return $context['subscriber_name'] ?? 'Default Name'; @@ -96,8 +96,8 @@ class Personalizer_Test extends \MailPoetTest { $html_content = '
-

Hello, !

-

Your email is .

+

Hello, !

+

Your email is .

'; @@ -117,9 +117,9 @@ class Personalizer_Test extends \MailPoetTest { * Test a missing tag in the registry. */ public function testMissingTagInRegistry(): void { - $html_content = '

Hello, !

'; + $html_content = '

Hello, !

'; $personalized_content = $this->personalizer->personalize_content( $html_content ); - $this->assertSame( '

Hello, !

', $personalized_content ); + $this->assertSame( '

Hello, !

', $personalized_content ); } /** @@ -129,7 +129,7 @@ class Personalizer_Test extends \MailPoetTest { $this->tags_registry->register( new Personalization_Tag( 'default_name', - 'user/firstname', + '[user/firstname]', 'Subscriber Info', function ( $context, $args ) { return $args['default'] ?? 'Default Name'; @@ -137,7 +137,7 @@ class Personalizer_Test extends \MailPoetTest { ) ); - $html_content = '

Hello, !

'; + $html_content = '

Hello, !

'; $this->assertSame( '

Hello, Guest!

', $this->personalizer->personalize_content( $html_content ) ); } @@ -148,7 +148,7 @@ class Personalizer_Test extends \MailPoetTest { $this->tags_registry->register( new Personalization_Tag( 'default_name', - 'user/firstname', + '[user/firstname]', 'Subscriber Info', function ( $context, $args ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- The $args parameter is not used in this test. return $context['user_name'] ?? 'Default Name'; @@ -159,10 +159,10 @@ class Personalizer_Test extends \MailPoetTest { $html_content = ' - Welcome, <!--user/firstname default="Guest"-->! + Welcome, <!--[user/firstname default="Guest"]-->! -

Hello, !

+

Hello, !

'; $this->personalizer->set_context( array( 'user_name' => 'John' ) ); diff --git a/packages/php/email-editor/tests/unit/Engine/PersonalizationTags/Personalization_Tags_Registry_Test.php b/packages/php/email-editor/tests/unit/Engine/PersonalizationTags/Personalization_Tags_Registry_Test.php index 53479290f0..79bcfac7a5 100644 --- a/packages/php/email-editor/tests/unit/Engine/PersonalizationTags/Personalization_Tags_Registry_Test.php +++ b/packages/php/email-editor/tests/unit/Engine/PersonalizationTags/Personalization_Tags_Registry_Test.php @@ -49,17 +49,46 @@ class PersonalizationTagsRegistryTest extends TestCase { ); // Retrieve the tag. - $tag = $this->registry->get_by_token( 'first_name' ); + $tag = $this->registry->get_by_token( '[first_name]' ); // Assert that the tag is registered correctly. $this->assertNotNull( $tag ); $this->assertSame( 'first_name_tag', $tag->get_name() ); - $this->assertSame( 'first_name', $tag->get_token() ); + $this->assertSame( '[first_name]', $tag->get_token() ); $this->assertSame( 'Subscriber Info', $tag->get_category() ); $this->assertSame( 'Personalized Value', $tag->execute_callback( array(), array() ) ); $this->assertSame( array( 'description' => 'First name of the subscriber' ), $tag->get_attributes() ); } + /** + * Register tag and retrieve it. + */ + public function testRegisterAndGetTagWithBrackets(): void { + $callback = function ( $context, $args ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- Callback parameters are required. + return 'Personalized Value'; + }; + + // Register a tag. + $this->registry->register( + new Personalization_Tag( + 'Last Name', + '[last_name]', + 'Subscriber Info', + $callback + ) + ); + + // Retrieve the tag. + $tag = $this->registry->get_by_token( '[last_name]' ); + + // Assert that the tag is registered correctly. + $this->assertNotNull( $tag ); + $this->assertSame( 'Last Name', $tag->get_name() ); + $this->assertSame( '[last_name]', $tag->get_token() ); + $this->assertSame( 'Subscriber Info', $tag->get_category() ); + $this->assertSame( 'Personalized Value', $tag->execute_callback( array(), array() ) ); + } + /** * Try to retrieve a tag that hasn't been registered. */ @@ -80,14 +109,14 @@ class PersonalizationTagsRegistryTest extends TestCase { }; // Register a tag. - $this->registry->register( new Personalization_Tag( 'tag1', 'tag-1', 'Category 1', $callback1 ) ); + $this->registry->register( new Personalization_Tag( 'tag1', '[tag-1]', 'Category 1', $callback1 ) ); // Attempt to register the same tag again. - $this->registry->register( new Personalization_Tag( 'tag2', 'tag-2', 'Category 2', $callback2 ) ); + $this->registry->register( new Personalization_Tag( 'tag2', '[tag-2]', 'Category 2', $callback2 ) ); // Retrieve the tag and ensure the first registration is preserved. /** @var Personalization_Tag $tag */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- used for phpstan - $tag = $this->registry->get_by_token( 'tag-1' ); + $tag = $this->registry->get_by_token( '[tag-1]' ); $this->assertSame( 'tag1', $tag->get_name() ); $this->assertSame( 'Category 1', $tag->get_category() ); $this->assertSame( 'Value 1', $tag->execute_callback( array(), array() ) ); @@ -102,16 +131,16 @@ class PersonalizationTagsRegistryTest extends TestCase { }; // Register multiple tags. - $this->registry->register( new Personalization_Tag( 'tag1', 'tag-1', 'Category 1', $callback ) ); - $this->registry->register( new Personalization_Tag( 'tag2', 'tag-2', 'Category 2', $callback ) ); + $this->registry->register( new Personalization_Tag( 'tag1', '[tag-1]', 'Category 1', $callback ) ); + $this->registry->register( new Personalization_Tag( 'tag2', '[tag-2]', 'Category 2', $callback ) ); // Retrieve all tags. $all_tags = $this->registry->get_all(); // Assert the number of registered tags. $this->assertCount( 2, $all_tags ); - $this->assertArrayHasKey( 'tag-1', $all_tags ); - $this->assertArrayHasKey( 'tag-2', $all_tags ); + $this->assertArrayHasKey( '[tag-1]', $all_tags ); + $this->assertArrayHasKey( '[tag-2]', $all_tags ); } /**