diff --git a/src/Oro/Bundle/ActivityListBundle/Resources/translations/messages.en.yml b/src/Oro/Bundle/ActivityListBundle/Resources/translations/messages.en.yml index 6d4a29cd4ec..1bf2dc643ed 100644 --- a/src/Oro/Bundle/ActivityListBundle/Resources/translations/messages.en.yml +++ b/src/Oro/Bundle/ActivityListBundle/Resources/translations/messages.en.yml @@ -38,7 +38,7 @@ oro: per_page.label: Items Per Page By Default email_threads: use_threads_in_activities: - label: Display Emails in Activities as + label: Display email conversations in activity lists as choices: non_threaded.label: Non-Threaded threaded.label: Threaded diff --git a/src/Oro/Bundle/AddressBundle/Resources/public/js/address/model.js b/src/Oro/Bundle/AddressBundle/Resources/public/js/address/model.js index c3e42cc39ac..17acc87152e 100644 --- a/src/Oro/Bundle/AddressBundle/Resources/public/js/address/model.js +++ b/src/Oro/Bundle/AddressBundle/Resources/public/js/address/model.js @@ -33,9 +33,28 @@ define([ }, getSearchableString: function() { - return this.get('country') + ', ' + - this.get('city') + ', ' + - this.get('street') + ' ' + (this.get('street2') || ''); + var address = ''; + + if (this.get('country')) { + address += this.get('country') + ', '; + } + if (this.get('region')) { + address += this.get('region') + ', '; + } + if (this.get('city')) { + address += this.get('city') + ', '; + } + if (this.get('street')) { + address += this.get('street') + ' '; + } + if (this.get('street2')) { + address += this.get('street2') + ' '; + } + if (this.get('postalCode')) { + address += this.get('postalCode') + ', '; + } + + return address; } }); }); diff --git a/src/Oro/Bundle/ApiBundle/Resources/doc/how_to.md b/src/Oro/Bundle/ApiBundle/Resources/doc/how_to.md index 7e8fedb64b5..7618438bfa6 100644 --- a/src/Oro/Bundle/ApiBundle/Resources/doc/how_to.md +++ b/src/Oro/Bundle/ApiBundle/Resources/doc/how_to.md @@ -25,6 +25,14 @@ oro_api: Acme\Bundle\ProductBundle\Product: ~ ``` +**Attention**: In version 2.0, use: + +```yaml +api: + entities: + Acme\Bundle\ProductBundle\Product: ~ +``` + Turn on API for entity disabled in Resources/config/oro/entity.yml ------------------------------------------------------------------ @@ -117,7 +125,7 @@ oro_api: Acme\Bundle\ProductBundle\Product: actions: delete: - excluded: true + exclude: true ``` Also, you can use short syntax: diff --git a/src/Oro/Bundle/BatchBundle/ORM/QueryBuilder/CountQueryBuilderOptimizer.php b/src/Oro/Bundle/BatchBundle/ORM/QueryBuilder/CountQueryBuilderOptimizer.php index 56cb89ed8eb..31ed4af4d3c 100644 --- a/src/Oro/Bundle/BatchBundle/ORM/QueryBuilder/CountQueryBuilderOptimizer.php +++ b/src/Oro/Bundle/BatchBundle/ORM/QueryBuilder/CountQueryBuilderOptimizer.php @@ -48,6 +48,7 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) * Get optimized query builder for count calculation. * * @param QueryBuilder $queryBuilder + * * @return QueryBuilder * @throws \Exception */ @@ -60,11 +61,9 @@ public function getCountQueryBuilder(QueryBuilder $queryBuilder) $this->context = null; return $qb; - } catch (\Exception $e) { + } finally { // make sure that a link to the context is removed even if an exception occurred $this->context = null; - // rethrow an exception - throw $e; } } @@ -159,43 +158,52 @@ protected function addJoins( $havingAliases = $this->qbTools->getUsedTableAliases($originalQueryParts['having']); $joinAliases = array_merge($whereAliases, $groupByAliases, $havingAliases); $joinAliases = array_unique($joinAliases); + $fromQueryPart = $originalQueryParts['from']; + $joinQueryPart = $originalQueryParts['join']; // this joins cannot be removed outside of this class $requiredJoinAliases = $joinAliases; - if ($useNonSymmetricJoins) { - $joinAliases = array_merge( - $joinAliases, - $this->getNonSymmetricJoinAliases( - $originalQueryParts['from'], - $originalQueryParts['join'], - $groupByAliases - ) - ); - } + $rootAliases = array_map( + function ($from) { + return $from->getAlias(); + }, + $fromQueryPart + ); + + $joinAliases = $this->addRequiredJoins( + $joinAliases, + $fromQueryPart, + $joinQueryPart, + $groupByAliases, + $useNonSymmetricJoins + ); + + $requiredJoinAliases = array_intersect( + array_diff($requiredJoinAliases, $rootAliases), + $this->context->getAliases() + ); + + $collectedAliases = $joinAliases; + $joinAliases = $this->dispatchQueryOptimizationEvent($joinAliases, $requiredJoinAliases); - $rootAliases = []; - /** @var Expr\From $from */ - foreach ($originalQueryParts['from'] as $from) { - $rootAliases[] = $from->getAlias(); - $joinAliases = array_merge( - $joinAliases, - $this->qbTools->getUsedJoinAliases($originalQueryParts['join'], $joinAliases, $from->getAlias()) + // additional check joins after the events in case if events change joins list + if (count($joinAliases) !== count($collectedAliases)) { + $joinAliases = $this->addRequiredJoins( + $requiredJoinAliases, + $fromQueryPart, + $this->removeAliasesFromQueryJoinParts($joinQueryPart, $joinAliases), + $groupByAliases, + $useNonSymmetricJoins ); } - $allAliases = $this->context->getAliases(); - $joinAliases = array_intersect(array_diff(array_unique($joinAliases), $rootAliases), $allAliases); - $requiredJoinAliases = array_intersect(array_diff($requiredJoinAliases, $rootAliases), $allAliases); - - $joinAliases = $this->dispatchQueryOptimizationEvent($joinAliases, $requiredJoinAliases); - foreach ($rootAliases as $rootAlias) { - if (!isset($originalQueryParts['join'][$rootAlias])) { + if (!isset($joinQueryPart[$rootAlias])) { continue; } /** @var Expr\Join $join */ - foreach ($originalQueryParts['join'][$rootAlias] as $join) { + foreach ($joinQueryPart[$rootAlias] as $join) { $alias = $join->getAlias(); // To count results number join all tables with inner join and required to tables if ($join->getJoinType() === Expr\Join::INNER_JOIN || in_array($alias, $joinAliases, true)) { @@ -421,6 +429,7 @@ protected function getAssociationType($entityClass, $associationName, $targetEnt * then them also should be selected as DISTINCT in optimized Query Builder. * * @param array $originalQueryParts + * * @return array */ protected function getFieldsToSelect(array $originalQueryParts) @@ -452,4 +461,76 @@ protected function getFieldsToSelect(array $originalQueryParts) return $fieldsToSelect; } + + /** + * Removes list of aliases from original query parts + * + * @param array $originalQueryParts + * @param array $joinAliases + * + * @return array + */ + protected function removeAliasesFromQueryJoinParts(array $originalQueryParts, array $joinAliases) + { + $filteredJoins = []; + foreach ($originalQueryParts as $root => $joins) { + foreach ($joins as $declaration) { + /** @var Expr\Join $name */ + $name = $declaration->getAlias(); + if (in_array($name, $joinAliases)) { + if (!array_key_exists($root, $filteredJoins)) { + $filteredJoins[$root] = []; + } + $filteredJoins[$root][] = $declaration; + } + } + } + + return $filteredJoins; + } + + /** + * Collect and add the joins should be added to query + * + * @param array $joinAliases + * @param array $fromQueryPart + * @param array $joinQueryPart + * @param array $groupByAliases + * @param boolean $useNonSymmetricJoins + * + * @return array + */ + protected function addRequiredJoins( + array $joinAliases, + array $fromQueryPart, + array $joinQueryPart, + array $groupByAliases, + $useNonSymmetricJoins + ) { + if ($useNonSymmetricJoins) { + $joinAliases = array_merge( + $joinAliases, + $this->getNonSymmetricJoinAliases( + $fromQueryPart, + $joinQueryPart, + $groupByAliases + ) + ); + } + + $rootAliases = []; + /** @var Expr\From $from */ + foreach ($fromQueryPart as $from) { + $rootAliases[] = $from->getAlias(); + $joinAliases = array_merge( + $joinAliases, + $this->qbTools->getUsedJoinAliases($joinQueryPart, $joinAliases, $from->getAlias()) + ); + } + + $allAliases = $this->context->getAliases(); + $joinAliases = array_intersect(array_diff(array_unique($joinAliases), $rootAliases), $allAliases); + + return $joinAliases; + } } diff --git a/src/Oro/Bundle/BatchBundle/Tests/Unit/ORM/QueryBuilder/CountQueryBuilderOptimizerTest.php b/src/Oro/Bundle/BatchBundle/Tests/Unit/ORM/QueryBuilder/CountQueryBuilderOptimizerTest.php index fc102fd3677..4ba76079302 100644 --- a/src/Oro/Bundle/BatchBundle/Tests/Unit/ORM/QueryBuilder/CountQueryBuilderOptimizerTest.php +++ b/src/Oro/Bundle/BatchBundle/Tests/Unit/ORM/QueryBuilder/CountQueryBuilderOptimizerTest.php @@ -8,8 +8,11 @@ use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + use Oro\Component\TestUtils\ORM\Mocks\EntityManagerMock; use Oro\Component\TestUtils\ORM\OrmTestCase; +use Oro\Bundle\BatchBundle\Event\CountQueryOptimizationEvent; use Oro\Bundle\BatchBundle\ORM\QueryBuilder\CountQueryBuilderOptimizer; class CountQueryBuilderOptimizerTest extends OrmTestCase @@ -534,4 +537,132 @@ public static function createQueryBuilder(EntityManager $entityManager) { return new QueryBuilder($entityManager); } + + /** + * @dataProvider getCountQueryBuilderDataProviderWithEventDispatcher + * + * @param callback $queryBuilder + * @param array $joinsToDelete + * @param string $expectedDql + */ + public function testGetCountQueryBuilderWithEventDispatcher($queryBuilder, array $joinsToDelete, $expectedDql) + { + $optimizer = new CountQueryBuilderOptimizer(); + $eventDispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); + $eventDispatcher->expects($this->once()) + ->method('dispatch') + ->willReturnCallback( + function ($eventName, CountQueryOptimizationEvent $event) use ($joinsToDelete) { + if (count($joinsToDelete)) { + foreach ($joinsToDelete as $deletedJoin) { + $event->removeJoinFromOptimizedQuery($deletedJoin); + } + } + } + ); + $optimizer->setEventDispatcher($eventDispatcher); + $countQb = $optimizer->getCountQueryBuilder(call_user_func($queryBuilder, $this->em)); + + $this->assertInstanceOf('Doctrine\ORM\QueryBuilder', $countQb); + // Check for expected DQL + $this->assertEquals($expectedDql, $countQb->getQuery()->getDQL()); + // Check that Optimized DQL can be converted to SQL + $this->assertNotEmpty($countQb->getQuery()->getSQL()); + } + + public function getCountQueryBuilderDataProviderWithEventDispatcher() + { + return [ + 'delete_one_join_table' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.businessUnits', 'bu', Join::WITH, 'bu.id = 456') + ->leftJoin('bu.users', 'o', Join::WITH, 'o.id = 123') + ->select('u.id, o.username'); + }, + ['o'], + 'expectedDQL' => 'SELECT u.id FROM Test:User u ' + . 'LEFT JOIN u.businessUnits bu WITH bu.id = 456' + ], + 'request_with_3th_join_table_without_deleting' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->select('u.id, o.username'); + }, + [], + 'expectedDQL' => 'SELECT u.id FROM Test:User u ' + . 'LEFT JOIN u.organization o WITH o.id = 456 ' + . 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123' + ], + 'request_with_3th_join_table_delete_main_join_table' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->select('u.id, o.username'); + }, + ['o'], + 'expectedDQL' => 'SELECT u.id FROM Test:User u LEFT ' + . 'JOIN u.organization o WITH o.id = 456 ' + . 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123' + ], + 'request_with_3th_join_table_delete_3th_join_table' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->select('u.id, o.username'); + }, + ['businessUnits'], + 'expectedDQL' => 'SELECT u.id FROM Test:User u' + ], + 'request_with_2_3th_join_tables_without_deleting' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123') + ->select('u.id, o.username'); + }, + [], + 'expectedDQL' => 'SELECT u.id FROM Test:User u ' + . 'LEFT JOIN u.organization o WITH o.id = 456 ' + . 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123 ' + . 'LEFT JOIN o.users users WITH users.id = 123' + ], + 'request_with_2_3th_join_tables_delete_3th_join_table' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123') + ->select('u.id, o.username'); + }, + ['businessUnits'], + 'expectedDQL' => 'SELECT u.id FROM Test:User u ' + . 'LEFT JOIN u.organization o WITH o.id = 456 ' + . 'LEFT JOIN o.users users WITH users.id = 123' + ], + 'request_with_2_3th_join_tables_delete_both_3th_join_table' => [ + 'queryBuilder' => function ($em) { + return self::createQueryBuilder($em) + ->from('Test:User', 'u') + ->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456') + ->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123') + ->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123') + ->select('u.id, o.username'); + }, + ['businessUnits', 'users'], + 'expectedDQL' => 'SELECT u.id FROM Test:User u' + ] + ]; + } } diff --git a/src/Oro/Bundle/ChartBundle/Resources/public/js/app/components/horizontal_bar-chart-component.js b/src/Oro/Bundle/ChartBundle/Resources/public/js/app/components/horizontal_bar-chart-component.js index 121f0482c24..eb21a340474 100644 --- a/src/Oro/Bundle/ChartBundle/Resources/public/js/app/components/horizontal_bar-chart-component.js +++ b/src/Oro/Bundle/ChartBundle/Resources/public/js/app/components/horizontal_bar-chart-component.js @@ -97,6 +97,15 @@ define(function(require) { } }, yaxis: { + ticks: function() { + var ticks = []; + for (var i in yLabels) { + if (yLabels[i]) { + ticks.push([i, yLabels[i]]); + } + } + return ticks; + }, tickFormatter: function(x) { return yLabels[parseInt(x)]; } diff --git a/src/Oro/Bundle/DataAuditBundle/Entity/Repository/AuditRepository.php b/src/Oro/Bundle/DataAuditBundle/Entity/Repository/AuditRepository.php index 7b6bab4cacd..d00be047f73 100644 --- a/src/Oro/Bundle/DataAuditBundle/Entity/Repository/AuditRepository.php +++ b/src/Oro/Bundle/DataAuditBundle/Entity/Repository/AuditRepository.php @@ -7,6 +7,11 @@ class AuditRepository extends LogEntryRepository { + /** + * @param object $entity + * + * @return \Doctrine\ORM\QueryBuilder + */ public function getLogEntriesQueryBuilder($entity) { $wrapped = new EntityWrapper($entity, $this->_em); diff --git a/src/Oro/Bundle/DataGridBundle/Resources/doc/backend/extensions/field_acl.md b/src/Oro/Bundle/DataGridBundle/Resources/doc/backend/extensions/field_acl.md index 9b141c475fd..610c0559bb8 100644 --- a/src/Oro/Bundle/DataGridBundle/Resources/doc/backend/extensions/field_acl.md +++ b/src/Oro/Bundle/DataGridBundle/Resources/doc/backend/extensions/field_acl.md @@ -1,7 +1,7 @@ Field ACL extension =================== -[Field ACL extension](../../../Extension/FieldAcl/FieldAclExtension.php) allows to check access to grid columns. Currently it is implemented only for ORM datasource. +[Field ACL extension](../../../../Extension/FieldAcl/FieldAclExtension.php) allows to check access to grid columns. Currently it is implemented only for ORM datasource. To enable field ACL protection for a column, you should use `field_acl` section in a datagrid declaration: diff --git a/src/Oro/Bundle/EmailBundle/DependencyInjection/Configuration.php b/src/Oro/Bundle/EmailBundle/DependencyInjection/Configuration.php index 388c244aa28..dbe332aafc0 100644 --- a/src/Oro/Bundle/EmailBundle/DependencyInjection/Configuration.php +++ b/src/Oro/Bundle/EmailBundle/DependencyInjection/Configuration.php @@ -54,7 +54,8 @@ public function getConfigTreeBuilder() 'attachment_sync_enable' => ['value' => true], 'attachment_sync_max_size' => ['value' => 50], 'attachment_preview_limit' => ['value' => 8], - 'sanitize_html' => ['value' => false] + 'sanitize_html' => ['value' => false], + 'threads_grouping' => ['value' => true] ] ); diff --git a/src/Oro/Bundle/EmailBundle/EventListener/Datagrid/EmailGridListener.php b/src/Oro/Bundle/EmailBundle/EventListener/Datagrid/EmailGridListener.php index 1bc00e2aa9d..d4d658e7924 100644 --- a/src/Oro/Bundle/EmailBundle/EventListener/Datagrid/EmailGridListener.php +++ b/src/Oro/Bundle/EmailBundle/EventListener/Datagrid/EmailGridListener.php @@ -14,6 +14,7 @@ use Oro\Bundle\DataGridBundle\Event\OrmResultBeforeQuery; use Oro\Bundle\EmailBundle\Datagrid\EmailQueryFactory; use Oro\Bundle\SecurityBundle\SecurityFacade; +use Oro\Bundle\ConfigBundle\Config\ConfigManager; class EmailGridListener { @@ -32,6 +33,11 @@ class EmailGridListener */ protected $gridViewManager; + /** + * @var ConfigManager + */ + protected $configManager; + /** * Stores join's root and alias if joins for filters are added - ['eu' => ['alias1']] * @@ -54,6 +60,14 @@ public function __construct( $this->gridViewManager = $gridViewManager; } + /** + * @param ConfigManager $configManager + */ + public function setConfigManager(ConfigManager $configManager) + { + $this->configManager = $configManager; + } + /** * @param OrmResultBeforeQuery $event */ @@ -92,6 +106,11 @@ public function onBuildAfter(BuildAfter $event) $queryBuilder->andWhere($queryBuilder->expr()->in('e.id', $emailIds)); } + if ($this->configManager && $this->configManager->get('oro_email.threads_grouping')) { + $queryBuilder->andWhere('e.head = :enabled')->setParameter('enabled', true); + $countQb->andWhere('e.head = :enabled')->setParameter('enabled', true); + } + $this->prepareQueryToFilter($parameters, $queryBuilder, $countQb); } diff --git a/src/Oro/Bundle/EmailBundle/Resources/config/datagrid.yml b/src/Oro/Bundle/EmailBundle/Resources/config/datagrid.yml index 854c99d5c28..da17864847a 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/config/datagrid.yml +++ b/src/Oro/Bundle/EmailBundle/Resources/config/datagrid.yml @@ -193,15 +193,6 @@ datagrid: email-grid: extends: base-email-grid - source: - count_query: - where: - and: - - e.head = true - query: - where: - and: - - e.head = true # joins for filters to, cc, bcc, folders, folder and mailbox processes dynamically in # Oro\Bundle\EmailBundle\EventListener\Datagrid\EmailGridListener for performance reasons filters: diff --git a/src/Oro/Bundle/EmailBundle/Resources/config/services.yml b/src/Oro/Bundle/EmailBundle/Resources/config/services.yml index 2c6b8b88243..678b1078d31 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/config/services.yml +++ b/src/Oro/Bundle/EmailBundle/Resources/config/services.yml @@ -568,6 +568,8 @@ services: tags: - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.after.base-email-grid, method: onBuildAfter } - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.before_query.base-email-grid, method: onResultBeforeQuery, priority: -255 } + calls: + - [setConfigManager, ['@oro_config.manager']] oro_email.listener.datagrid.activity: class: %oro_email.listener.datagrid.activity.class% diff --git a/src/Oro/Bundle/EmailBundle/Resources/config/system_configuration.yml b/src/Oro/Bundle/EmailBundle/Resources/config/system_configuration.yml index 06cfb36c835..09e6f4efd93 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/config/system_configuration.yml +++ b/src/Oro/Bundle/EmailBundle/Resources/config/system_configuration.yml @@ -135,6 +135,15 @@ oro_system_configuration: tooltip: oro.email.system_configuration.sanitize_html.tooltip required: true + oro_email.threads_grouping: + data_type: boolean + type: choice + options: + label: oro.email.system_configuration.email_threads.use_threads.label + choices: + - oro.email.system_configuration.email_threads.use_threads.choices.non_threaded.label + - oro.email.system_configuration.email_threads.use_threads.choices.threaded.label + tree: system_configuration: platform: @@ -169,6 +178,9 @@ oro_system_configuration: mailboxes: children: - oro_email.mailbox_grid + email_threads: + children: + - oro_email.threads_grouping user_configuration: platform: children: @@ -191,6 +203,9 @@ oro_system_configuration: user_mailbox: children: - oro_email.user_mailbox + email_threads: + children: + - oro_email.threads_grouping api_tree: signature_configuration: diff --git a/src/Oro/Bundle/EmailBundle/Resources/translations/messages.en.yml b/src/Oro/Bundle/EmailBundle/Resources/translations/messages.en.yml index 57c389976bc..a0673273a90 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/translations/messages.en.yml +++ b/src/Oro/Bundle/EmailBundle/Resources/translations/messages.en.yml @@ -51,6 +51,11 @@ oro: email_threads: label: Email Threads + use_threads: + label: Display email conversations as + choices: + non_threaded.label: Non-Threaded + threaded.label: Threaded attachment_configuration: label: Attachments diff --git a/src/Oro/Bundle/EmailBundle/Resources/translations/validators.en.yml b/src/Oro/Bundle/EmailBundle/Resources/translations/validators.en.yml index 1aa130a7b1e..0da88f9e0f5 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/translations/validators.en.yml +++ b/src/Oro/Bundle/EmailBundle/Resources/translations/validators.en.yml @@ -1,3 +1,8 @@ "The template for {{ field }} ({{ locale }}) has syntax error: {{ error }}": "The template for {{ field }} ({{ locale }}) has syntax error: {{ error }}" "This value contains not valid email address.": "This value contains not valid email address." "Recipient can not be empty": "Recipient can not be empty" + +oro: + email: + message: + mailbox_origin_constraint: At least one folder for sent emails is required. Make sure you clicked button "%button%" and there are some folders for incoming messages. diff --git a/src/Oro/Bundle/EmailBundle/Resources/views/Email/Datagrid/Property/contacts.html.twig b/src/Oro/Bundle/EmailBundle/Resources/views/Email/Datagrid/Property/contacts.html.twig index 4752ed49bc3..49557d64e25 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/views/Email/Datagrid/Property/contacts.html.twig +++ b/src/Oro/Bundle/EmailBundle/Resources/views/Email/Datagrid/Property/contacts.html.twig @@ -38,7 +38,7 @@ {{ EA.wrapTextToTag(firstLastRecipients, isNew) }} {% endif %} {% endif %} -{% if threadEmailCount > 1 %} +{% if oro_config_value('oro_email.threads_grouping') and threadEmailCount > 1 %} {{ EA.wrapTextToTag('(' ~ threadEmailCount ~ ')', isNew) }} {% endif %} diff --git a/src/Oro/Bundle/EmailBundle/Resources/views/Email/Thread/view.html.twig b/src/Oro/Bundle/EmailBundle/Resources/views/Email/Thread/view.html.twig index 6b88c64a84d..f28601d970c 100644 --- a/src/Oro/Bundle/EmailBundle/Resources/views/Email/Thread/view.html.twig +++ b/src/Oro/Bundle/EmailBundle/Resources/views/Email/Thread/view.html.twig @@ -49,7 +49,8 @@ {{ oro_widget_render({ 'widgetType': 'block', 'wid': 'thread-view', - 'url': path('oro_email_thread_widget', {'id': entity.id, 'renderContexts': false}), + 'url': path('oro_email_thread_widget', {'id': entity.id, 'renderContexts': false, + 'showSingleEmail': not oro_config_value('oro_email.threads_grouping')}), 'alias': 'thread-view', 'contextsRendered': true }) }} diff --git a/src/Oro/Bundle/EmailBundle/Validator/Constraints/MailboxOrigin.php b/src/Oro/Bundle/EmailBundle/Validator/Constraints/MailboxOrigin.php index 9c5e1fbcc8a..f0c68d92fe8 100644 --- a/src/Oro/Bundle/EmailBundle/Validator/Constraints/MailboxOrigin.php +++ b/src/Oro/Bundle/EmailBundle/Validator/Constraints/MailboxOrigin.php @@ -7,8 +7,7 @@ class MailboxOrigin extends Constraint { /** @var string */ - public $message = 'At least one folder for sent emails is required. ' - . 'Make sure you clicked button "%button%" and there are some folders for incoming messages.'; + public $message = 'oro.email.message.mailbox_origin_constraint'; /** * {@inheritdoc} diff --git a/src/Oro/Bundle/LocaleBundle/Resources/public/js/formatter/address.js b/src/Oro/Bundle/LocaleBundle/Resources/public/js/formatter/address.js index e4ec84de5fd..186b49065b2 100644 --- a/src/Oro/Bundle/LocaleBundle/Resources/public/js/formatter/address.js +++ b/src/Oro/Bundle/LocaleBundle/Resources/public/js/formatter/address.js @@ -37,7 +37,7 @@ define(['jquery', '../locale-settings', './name' if ('name' === lowerCaseKey) { value = nameFormatter.format(address, localeSettings.getCountryLocale(country)); } else if ('street' === lowerCaseKey) { - value = address.street + ' ' + (address.street2 || ''); + value = (address.street || '') + ' ' + (address.street2 || ''); } else if ('street1' === lowerCaseKey) { value = address.street; } else { diff --git a/src/Oro/Bundle/SecurityBundle/ORM/Walker/AclWalker.php b/src/Oro/Bundle/SecurityBundle/ORM/Walker/AclWalker.php index 962bf9ff0b1..4a85fdf33f2 100644 --- a/src/Oro/Bundle/SecurityBundle/ORM/Walker/AclWalker.php +++ b/src/Oro/Bundle/SecurityBundle/ORM/Walker/AclWalker.php @@ -107,7 +107,6 @@ protected function processSubRequests(SelectStatement $AST, AclConditionStorage } } - /** * @param ConditionalPrimary $factor * @param int $factorId @@ -125,7 +124,8 @@ protected function getSubSelectFromFactor(ConditionalPrimary $factor, $factorId, ->conditionalFactors[$factorId] ->simpleConditionalExpression ->subselect; - } elseif (isset($factor->conditionalExpression->conditionalTerms)) { + } elseif (isset($factor->conditionalExpression->conditionalTerms) + && isset($factor->conditionalExpression->conditionalTerms[$factorId]->simpleConditionalExpression)) { $subSelect = $factor ->conditionalExpression ->conditionalTerms[$factorId] @@ -204,7 +204,8 @@ protected function addAclToWhereClause($AST, array $whereConditions) $aclConditionalFactors = $this->aclConditionFactorBuilder->addWhereAclConditionalFactors( [], //default empty conditional factors $whereConditions, - $this->_getQuery() + $this->_getQuery(), + ['AST' => $AST] ); if (!empty($aclConditionalFactors)) {