diff --git a/src/Oro/Bundle/EmailBundle/Controller/EmailController.php b/src/Oro/Bundle/EmailBundle/Controller/EmailController.php index 3f580cc595d..e0fcecdc77d 100644 --- a/src/Oro/Bundle/EmailBundle/Controller/EmailController.php +++ b/src/Oro/Bundle/EmailBundle/Controller/EmailController.php @@ -577,7 +577,7 @@ public function autocompleteRecipientAction(Request $request) { $query = $request->query->get('query'); if ($request->query->get('search_by_id', false)) { - $emails = explode(',', $query); + $emails = EmailRecipientsHelper::extractFormRecipientIds($query); $results = array_map(function ($email) { $recipient = $this->getEmailRecipientsHelper()->createRecipientFromEmail($email); if ($recipient) { @@ -585,7 +585,7 @@ public function autocompleteRecipientAction(Request $request) } return [ - 'id' => $email, + 'id' => EmailRecipientsHelper::prepareFormRecipientIds($email), 'text' => $email, ]; }, $emails); diff --git a/src/Oro/Bundle/EmailBundle/Form/DataTransformer/EmailAddressRecipientsTransformer.php b/src/Oro/Bundle/EmailBundle/Form/DataTransformer/EmailAddressRecipientsTransformer.php new file mode 100644 index 00000000000..ad0a16dda06 --- /dev/null +++ b/src/Oro/Bundle/EmailBundle/Form/DataTransformer/EmailAddressRecipientsTransformer.php @@ -0,0 +1,36 @@ +cm = $cm; } + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->resetViewTransformers(); + $builder->addViewTransformer( + new EmailAddressRecipientsTransformer() + ); + } + /** * {@inheritdoc} */ @@ -61,6 +75,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'configs' => [ 'allowClear' => true, 'multiple' => true, + 'separator' => EmailRecipientsHelper::EMAIL_IDS_SEPARATOR, 'route_name' => 'oro_email_autocomplete_recipient', 'minimumInputLength' => $this->cm->get('oro_email.minimum_input_length'), 'per_page' => 100, diff --git a/src/Oro/Bundle/EmailBundle/Provider/EmailRecipientsHelper.php b/src/Oro/Bundle/EmailBundle/Provider/EmailRecipientsHelper.php index b1b08ffb978..d5675c164f9 100644 --- a/src/Oro/Bundle/EmailBundle/Provider/EmailRecipientsHelper.php +++ b/src/Oro/Bundle/EmailBundle/Provider/EmailRecipientsHelper.php @@ -30,6 +30,7 @@ class EmailRecipientsHelper { const ORGANIZATION_PROPERTY = 'organization'; + const EMAIL_IDS_SEPARATOR = ';'; /** @var AclHelper */ protected $aclHelper; @@ -167,9 +168,9 @@ public function createRecipientData(Recipient $recipient) } return [ - 'id' => $recipient->getId(), - 'text' => $recipient->getName(), - 'data' => json_encode($data), + 'id' => self::prepareFormRecipientIds($recipient->getId()), + 'text' => $recipient->getName(), + 'data' => json_encode($data), ]; } @@ -325,7 +326,7 @@ protected function recipientsFromResult(array $result, $entityClass) foreach ($result as $row) { $recipient = new CategorizedRecipient( $row['email'], - sprintf('%s <%s>', $row['name'], $row['email']), + sprintf('"%s" <%s>', $row['name'], $row['email']), new RecipientEntity( $entityClass, $row['entityId'], @@ -351,4 +352,44 @@ protected function getPropertyAccessor() return $this->propertyAccessor; } + + /** + * Prepares base64 encoded emails to be used as ids in recipients form for select2 component. + * + * @param array|string $ids + * @return string; + */ + public static function prepareFormRecipientIds($ids) + { + if (is_string($ids)) { + return base64_encode($ids); + } + + $ids = array_map("base64_encode", $ids); + + return implode(self::EMAIL_IDS_SEPARATOR, $ids); + } + + /** + * Extracts base64 encoded selected email values, that are used as ids in recipients form for select2 component. + * + * @param array|string $value + * @return array; + */ + public static function extractFormRecipientIds($value) + { + if (is_array($value)) { + return $value; + } + /* + * str_getcsv is used to cover the case if emails are pasted directly with ";" separator + * and it protects from ";" used in full email address. (example: "Recipient Name; Name2" ) + */ + $idsEncoded = str_getcsv($value, self::EMAIL_IDS_SEPARATOR); + $idsDecoded = array_map(function ($idEncoded) { + return base64_decode($idEncoded, true) ? : $idEncoded; + }, $idsEncoded); + + return $idsDecoded; + } } diff --git a/src/Oro/Bundle/EmailBundle/Tests/Functional/EmailControllerTest.php b/src/Oro/Bundle/EmailBundle/Tests/Functional/EmailControllerTest.php index 3624df05ead..b1f604073c1 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Functional/EmailControllerTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Functional/EmailControllerTest.php @@ -232,7 +232,9 @@ public function testReply() $this->assertEquals(1, $crawler->filter('div.widget-content input[name=\'oro_email_email[cc]\']')->count()); $this->assertEquals( 1, - $crawler->filter('div.widget-content input[value=\'' . $email->getFromName() . '\']')->count() + $crawler->filter('div.widget-content input[value=\'' + . base64_encode($email->getFromName()) + . '\']')->count() ); $cc = $email->getCc()->first()->getEmailAddress()->getEmail(); $this->assertEquals( @@ -258,12 +260,14 @@ public function testReplyAll() $this->assertEquals(1, $crawler->filter('div.widget-content input[name=\'oro_email_email[cc]\']')->count()); $this->assertEquals( 1, - $crawler->filter('div.widget-content input[value=\'' . $email->getFromName() . '\']')->count() + $crawler->filter('div.widget-content input[value=\'' + . base64_encode($email->getFromName()) + . '\']')->count() ); $cc = $email->getCc()->first()->getEmailAddress()->getEmail(); $this->assertEquals( 1, - $crawler->filter('div.widget-content input[value=\'' . $cc . '\']')->count() + $crawler->filter('div.widget-content input[value=\'' . base64_encode($cc) . '\']')->count() ); $bcc = $email->getBcc()->first()->getEmailAddress()->getEmail(); $this->assertEquals( diff --git a/src/Oro/Bundle/EmailBundle/Tests/Unit/Builder/Helper/EmailModelBuilderHelperTest.php b/src/Oro/Bundle/EmailBundle/Tests/Unit/Builder/Helper/EmailModelBuilderHelperTest.php index 9e80c7ffbf9..912c9170a96 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Unit/Builder/Helper/EmailModelBuilderHelperTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Unit/Builder/Helper/EmailModelBuilderHelperTest.php @@ -114,7 +114,7 @@ protected function setUp() public function testPreciseFullEmailAddressIsFullQualifiedName() { - $emailAddress = 'Admin '; + $emailAddress = '"Admin" '; $this->entityRoutingHelper->expects($this->never()) ->method('getEntity'); @@ -131,7 +131,7 @@ public function testPreciseFullEmailAddressIsFullQualifiedName() public function testPreciseFullEmailAddressViaRoutingHelper() { $emailAddress = 'someaddress@example.com'; - $expected = 'Admin '; + $expected = '"Admin" '; $ownerClass = 'Oro\Bundle\UserBundle\Entity\User'; $ownerId = 1; @@ -183,7 +183,7 @@ public function testPreciseFullEmailAddressViaRoutingHelperWithExcludeCurrentUse public function testPreciseFullEmailAddressViaAddressManager() { $emailAddress = 'someaddress@example.com'; - $expected = 'Admin '; + $expected = '"Admin" '; $ownerClass = 'Oro\Bundle\UserBundle\Entity\User'; $ownerId = null; @@ -307,19 +307,19 @@ public function preciseFullEmailAddressProvider() { return [ [ - 'FirstName LastName ', + '"FirstName LastName" ', 'test@example.com', null, null ], [ - 'FirstName LastName ', + '"FirstName LastName" ', 'test@example.com', 'Oro\Bundle\EmailBundle\Tests\Unit\Fixtures\Entity\TestUser', null ], [ - 'OwnerFirstName OwnerLastName ', + '"OwnerFirstName OwnerLastName" ', 'test@example.com', 'Oro\Bundle\EmailBundle\Tests\Unit\Fixtures\Entity\TestUser', 123 @@ -410,7 +410,7 @@ public function testBuildFullEmailAddress() $user = $this->getMock('Oro\Bundle\UserBundle\Entity\User'); $email = 'email'; $format = 'format'; - $expected = 'format '; + $expected = '"format" '; $user->expects($this->once()) ->method('getEmail') diff --git a/src/Oro/Bundle/EmailBundle/Tests/Unit/Provider/EmailRecipientsHelperTest.php b/src/Oro/Bundle/EmailBundle/Tests/Unit/Provider/EmailRecipientsHelperTest.php index 43e3f2d3f08..54f8c592fbd 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Unit/Provider/EmailRecipientsHelperTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Unit/Provider/EmailRecipientsHelperTest.php @@ -192,4 +192,56 @@ public function filterRecipientsDataProvider() ], ]; } + + /** + * @dataProvider prepareFormRecipientIdsDataProvider + */ + public function testPrepareFormRecipientIds($ids, $expectedResult) + { + $this->assertEquals($expectedResult, EmailRecipientsHelper::prepareFormRecipientIds($ids)); + } + + public function prepareFormRecipientIdsDataProvider() + { + return [ + [ + [ + '"Recipient1 Name; Name2" ', + '"Recipient2 Name, Name2" ' + ], + + base64_encode('"Recipient1 Name; Name2" ') . ';' + . base64_encode('"Recipient2 Name, Name2" ') + ] + ]; + } + + /** + * @dataProvider extractFormRecipientIdsDataProvider + */ + public function testExtractFormRecipientIds($value, $expectedResult) + { + $this->assertEquals($expectedResult, EmailRecipientsHelper::extractFormRecipientIds($value)); + } + + public function extractFormRecipientIdsDataProvider() + { + return [ + [ + base64_encode('"Recipient1 Name; Name2" ') . ';' + . base64_encode('"Recipient2 Name, Name2" '), + [ + '"Recipient1 Name; Name2" ', + '"Recipient2 Name, Name2" ' + ] + ], + [ + 'recipient1@example.com;recipient2@example.com', + [ + 'recipient1@example.com', + 'recipient2@example.com' + ] + ] + ]; + } } diff --git a/src/Oro/Bundle/EmailBundle/Tests/Unit/Tools/EmailAddressHelperTest.php b/src/Oro/Bundle/EmailBundle/Tests/Unit/Tools/EmailAddressHelperTest.php index 2f563b1389c..0bec6bfd28f 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Unit/Tools/EmailAddressHelperTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Unit/Tools/EmailAddressHelperTest.php @@ -91,8 +91,8 @@ public static function buildFullEmailAddressProvider() ['john@example.com', null, 'john@example.com'], ['john@example.com', '', 'john@example.com'], ['john@example.com', null, 'john@example.com'], - ['john@example.com', 'John Smith', 'John Smith '], - [' john@example.com ', ' John Smith ', 'John Smith '], + ['john@example.com', 'John Smith', '"John Smith" '], + [' john@example.com ', ' John Smith ', '"John Smith" '], ]; } @@ -126,7 +126,7 @@ public static function extractEmailAddressFirstNameProvider() { return [ ['John Smith IV. ', 'John'], - ['John Smith ', 'John'], + ['"John Smith" ', 'John'], ['John ', 'John'], ['john.smith@example.com', 'john'], ['john@example.com', 'john'], @@ -137,7 +137,7 @@ public static function extractEmailAddressLastNameProvider() { return [ ['John Smith IV. ', 'Smith IV.'], - ['John Smith ', 'Smith'], + ['"John Smith" ', 'Smith'], ['John ', 'example.com'], ['john.smith@example.com', 'smith'], ['john@example.com', 'example.com'], diff --git a/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTemplateTest.php b/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTemplateTest.php index 18a477aa472..9970214c8fd 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTemplateTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTemplateTest.php @@ -508,14 +508,14 @@ public function executeOptionsDataProvider() ], 'simple with name' => [ [ - 'from' => 'Test ', - 'to' => 'Test ', + 'from' => '"Test" ', + 'to' => '"Test" ', 'template' => 'test', 'entity' => new \stdClass(), ], [ - 'from' => 'Test ', - 'to' => ['Test '], + 'from' => '"Test" ', + 'to' => ['"Test" '], 'subject' => 'Test subject', 'body' => 'Test body', ] @@ -534,8 +534,8 @@ public function executeOptionsDataProvider() 'entity' => new \stdClass(), ], [ - 'from' => 'Test ', - 'to' => ['Test '], + 'from' => '"Test" ', + 'to' => ['"Test" '], 'subject' => 'Test subject', 'body' => 'Test body', ] @@ -554,8 +554,8 @@ public function executeOptionsDataProvider() 'entity' => new \stdClass(), ], [ - 'from' => '_Formatted ', - 'to' => ['_Formatted '], + 'from' => '"_Formatted" ', + 'to' => ['"_Formatted" '], 'subject' => 'Test subject', 'body' => 'Test body', ] @@ -572,18 +572,18 @@ public function executeOptionsDataProvider() 'email' => 'test@test.com' ], 'test@test.com', - 'Test ' + '"Test" ' ], 'template' => 'test', 'entity' => new \stdClass(), 'attribute' => 'attr' ], [ - 'from' => 'Test ', + 'from' => '"Test" ', 'to' => [ - 'Test ', + '"Test" ', 'test@test.com', - 'Test ' + '"Test" ' ], 'subject' => 'Test subject', 'body' => 'Test body', diff --git a/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTest.php b/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTest.php index 7bd612e5658..80323dcf7b8 100644 --- a/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTest.php +++ b/src/Oro/Bundle/EmailBundle/Tests/Unit/Workflow/Action/SendEmailTest.php @@ -313,14 +313,14 @@ public function executeOptionsDataProvider() ), 'simple with name' => array( array( - 'from' => 'Test ', - 'to' => 'Test ', + 'from' => '"Test" ', + 'to' => '"Test" ', 'subject' => 'test', 'body' => 'test' ), array( - 'from' => 'Test ', - 'to' => array('Test '), + 'from' => '"Test" ', + 'to' => array('"Test" '), 'subject' => 'test', 'body' => 'test' ) @@ -339,8 +339,8 @@ public function executeOptionsDataProvider() 'body' => 'test' ), array( - 'from' => 'Test ', - 'to' => array('Test '), + 'from' => '"Test" ', + 'to' => array('"Test" '), 'subject' => 'test', 'body' => 'test' ) @@ -359,8 +359,8 @@ public function executeOptionsDataProvider() 'body' => 'test' ), array( - 'from' => '_Formatted ', - 'to' => array('_Formatted '), + 'from' => '"_Formatted" ', + 'to' => array('"_Formatted" '), 'subject' => 'test', 'body' => 'test' ) @@ -377,18 +377,18 @@ public function executeOptionsDataProvider() 'email' => 'test@test.com' ), 'test@test.com', - 'Test ' + '"Test" ' ), 'subject' => 'test', 'body' => 'test', 'attribute' => 'attr' ), array( - 'from' => 'Test ', + 'from' => '"Test" ', 'to' => array( - 'Test ', + '"Test" ', 'test@test.com', - 'Test ' + '"Test" ' ), 'subject' => 'test', 'body' => 'test' diff --git a/src/Oro/Bundle/EmailBundle/Tools/EmailAddressHelper.php b/src/Oro/Bundle/EmailBundle/Tools/EmailAddressHelper.php index 1ccc015c925..fd17550f7bf 100644 --- a/src/Oro/Bundle/EmailBundle/Tools/EmailAddressHelper.php +++ b/src/Oro/Bundle/EmailBundle/Tools/EmailAddressHelper.php @@ -221,7 +221,7 @@ public function buildFullEmailAddress($pureEmailAddress, $emailAddressOwnerName) return trim($pureEmailAddress); } - return sprintf('%s <%s>', trim($emailAddressOwnerName), trim($pureEmailAddress)); + return sprintf('"%s" <%s>', trim($emailAddressOwnerName), trim($pureEmailAddress)); } /**