Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/dev/1.10' into 1.10
Browse files Browse the repository at this point in the history
  • Loading branch information
rgrebenchuk committed Feb 22, 2017
2 parents 776b604 + 7d549b3 commit 010c538
Show file tree
Hide file tree
Showing 27 changed files with 636 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/Oro/Bundle/ActionBundle/Resources/config/conditions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ services:
- { name: oro_action.condition, alias: not }

oro_action.expression.true:
class: Oro\Component\ConfigExpression\Condition\True
class: Oro\Component\ConfigExpression\Condition\TrueCondition
tags:
- { name: oro_action.condition, alias: "true" }

oro_action.expression.false:
class: Oro\Component\ConfigExpression\Condition\False
class: Oro\Component\ConfigExpression\Condition\FalseCondition
tags:
- { name: oro_action.condition, alias: "false" }

Expand Down
6 changes: 0 additions & 6 deletions src/Oro/Bundle/CalendarBundle/Resources/config/form.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ parameters:
oro_calendar.attendees_to_view_transformer.class: Oro\Bundle\CalendarBundle\Form\DataTransformer\AttendeesToViewTransformer
oro_calendar.user_ids_to_users.tranformer.class: Oro\Bundle\FormBundle\Form\DataTransformer\EntitiesToIdsTransformer
oro_calendar.recurrence.form.type.class: Oro\Bundle\CalendarBundle\Form\Type\RecurrenceFormType
oro_calendar.exception.form.type.class: Oro\Bundle\CalendarBundle\Form\Type\ExceptionFormType

services:
oro_calendar.calendar_event.form.type:
Expand Down Expand Up @@ -213,8 +212,3 @@ services:
- '@oro_calendar.model.recurrence'
tags:
- { name: form.type, alias: oro_calendar_event_recurrence }

oro_calendar.exception.form.type:
class: '%oro_calendar.exception.form.type.class%'
tags:
- { name: form.type, alias: oro_calendar_event_exception }
53 changes: 53 additions & 0 deletions src/Oro/Bundle/EmailBundle/Controller/EmailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,59 @@ public function threadWidgetAction(Email $entity)
];
}

/**
* Used on `My Emails` page to show emails thread with only emails being related to currently logged user.
*
* @Route("/view/user-thread/{id}", name="oro_email_user_thread_view", requirements={"id"="\d+"})
* @AclAncestor("oro_email_email_view")
* @Template("OroEmailBundle:Email/Thread:userEmails.html.twig")
*/
public function viewUserThreadAction(Email $entity)
{
$this->getEmailManager()->setSeenStatus($entity, true, true);

return ['entity' => $entity];
}

/**
* Used on `My Emails` page to show emails thread with only emails being related to currently logged user.
*
* @Route("/widget/user-thread/{id}", name="oro_email_user_thread_widget", requirements={"id"="\d+"})
* @Template("OroEmailBundle:Email/widget:thread.html.twig")
*/
public function userThreadWidgetAction(Email $entity)
{
$emails = [];
if ($this->getRequest()->get('showSingleEmail', false)) {
$emails[] = $entity;
} else {
$emails = $this->get('oro_email.email.thread.provider')->getUserThreadEmails(
$this->get('doctrine')->getManager(),
$entity,
$this->getUser(),
$this->get('oro_email.mailbox.manager')->findAvailableMailboxes(
$this->getUser(),
$this->get('security.token_storage')->getToken()->getOrganizationContext()
)
);
}

$emails = array_filter($emails, function ($email) {
return $this->get('security.context')->isGranted('VIEW', $email);
});
$this->loadEmailBody($emails);

return [
'entity' => $entity,
'thread' => $emails,
'target' => $this->getTargetEntity(),
'hasGrantReattach' => $this->isAttachmentCreationGranted(),
'routeParameters' => $this->getTargetEntityConfig(),
'renderContexts' => $this->getRequest()->get('renderContexts', true),
'defaultReplyButton' => $this->get('oro_config.user')->get('oro_email.default_button_reply')
];
}

/**
* @Route("/view-items", name="oro_email_items_view")
* @Template
Expand Down
158 changes: 152 additions & 6 deletions src/Oro/Bundle/EmailBundle/Datagrid/EmailQueryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Oro\Bundle\EmailBundle\Datagrid;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;

use Oro\Bundle\EmailBundle\Entity\Manager\MailboxManager;
Expand Down Expand Up @@ -67,18 +68,16 @@ public function prepareQuery(QueryBuilder $qb, $emailFromTableAlias = 'a')
*/
public function applyAcl(QueryBuilder $qb)
{
$user = $this->securityFacade->getLoggedUser();
$organization = $this->getOrganization();

$mailboxIds = $this->mailboxManager->findAvailableMailboxIds($user, $organization);

$exprs = [$qb->expr()->eq('eu.owner', ':owner')];

$organization = $this->getOrganization();
if ($organization) {
$exprs[] = $qb->expr()->eq('eu.organization ', ':organization');
$qb->setParameter('organization', $organization->getId());
}
$uoCheck = call_user_func_array([$qb->expr(), 'andX'], $exprs);

$mailboxIds = $this->getAvailableMailboxIds();
if (!empty($mailboxIds)) {
$qb->andWhere(
$qb->expr()->orX(
Expand All @@ -90,7 +89,154 @@ public function applyAcl(QueryBuilder $qb)
} else {
$qb->andWhere($uoCheck);
}
$qb->setParameter('owner', $user->getId());

$qb->setParameter('owner', $this->securityFacade->getLoggedUserId());
}

/**
* Apply custom ACL checks in case emails should be shown in threads view
* Adds additional WHERE condition:
*
* o0_.id IN (
* SELECT max(u.id)
* FROM OroEmailBundle:EmailUser as u
* INNER JOIN OroEmailBundle:Email as m on u.email_id = m.id
* WHERE
* m.thread_id is not null
* AND (
* (
* u.user_owner_id = {owner_id}
* AND u.organization_id = {organization_id}
* )
* OR u.mailbox_owner_id IN ( {allowed_mailboxes_ids} )
* )
* GROUP BY m.thread_id
* )
* OR (o3_.is_head = 1 AND o3_.thread_id is null)
*
* @param QueryBuilder $qb
*/
public function applyAclThreadsGrouping(QueryBuilder $qb)
{
$innerQb = $qb->getEntityManager()->createQueryBuilder();
$innerQb
->select('MAX(u.id)')
->from('OroEmailBundle:EmailUser', 'u')
->innerJoin('OroEmailBundle:Email', 'm', 'WITH', 'u.email = m.id')
->where(
$innerQb->expr()->andX(
$innerQb->expr()->isNotNull('m.thread'),
$this->getOwningExpression($innerQb->expr(), 'u')
)
)
->groupBy('m.thread');

$qb->andWhere(
$qb->expr()->orX(
$qb->expr()->in('eu.id', $innerQb->getDQL()),
$qb->expr()->andX(
$qb->expr()->isNull('e.thread'),
$qb->expr()->eq('e.head', 'TRUE')
)
)
);
}

/**
* In case threaded view, adds email counting (SELECT COUNT) expression.
*
* SELECT COUNT(eu.id)
* FROM oro_email_user AS eu
* INNER JOIN oro_email e ON (eu.email_id = e.id)
* WHERE
* e.thread_id = o3_.thread_id
* AND (
* (
* eu.user_owner_id = {owner_id}
* AND eu.organization_id = {organization_id}
* )
* OR eu.mailbox_owner_id IN ( {allowed_mailboxes_ids} )
* )
* AND o3_.thread_id IS NOT NULL -- `o3_` is alias for `oro_email` table from base query
* as thread_email_count
*
* @param QueryBuilder $qb
* @param bool $isThreadGroupingEnabled
*/
public function addEmailsCount(QueryBuilder $qb, $isThreadGroupingEnabled)
{
// in case threading view is disabled the default value for counting is `0`
$selectExpression = '0 AS thread_email_count';

if ($isThreadGroupingEnabled) {
$innerQb = $qb->getEntityManager()->createQueryBuilder();
$innerQb
->select('COUNT(emailUser.id)')
->from('OroEmailBundle:EmailUser', 'emailUser')
->innerJoin('OroEmailBundle:Email', 'email', 'WITH', 'emailUser.email = email.id')
->where(
$innerQb->expr()->andX(
$innerQb->expr()->isNotNull('e.thread'),
$innerQb->expr()->eq('email.thread', 'e.thread'),
$this->getOwningExpression($innerQb->expr(), 'emailUser')
)
);

$selectExpression = '(' . $innerQb->getDQL() . ') AS thread_email_count';
}

$qb->addSelect($selectExpression);
}

/**
* Builds owning expression part, being used in case of threaded emails view enabled.
*
* (
* eu.user_owner_id = {owner_id}
* AND eu.organization_id = {organization_id}
* )
* OR eu.mailbox_owner_id IN ( {allowed_mailboxes_ids} )
*
* @param Expr $expr
* @param string $tableAlias
*
* @return Expr\Andx|Expr\Comparison|Expr\Orx
*/
protected function getOwningExpression($expr, $tableAlias)
{
$user = $this->securityFacade->getLoggedUser();
$organization = $this->getOrganization();

if ($organization === null) {
$ownerExpression =
$expr->eq($tableAlias . '.owner', $user->getId());
} else {
$ownerExpression = $expr->andX(
$expr->eq($tableAlias . '.owner', $user->getId()),
$expr->eq($tableAlias . '.organization', $organization->getId())
);
}

$availableMailboxIds = $this->getAvailableMailboxIds();
if ($availableMailboxIds) {
return $expr->orX(
$ownerExpression,
$expr->in($tableAlias . '.mailboxOwner', $this->getAvailableMailboxIds())
);
} else {
return $ownerExpression;
}
}

/**
* @return array
*/
protected function getAvailableMailboxIds()
{
return $this->mailboxManager->findAvailableMailboxIds(
$this->securityFacade->getLoggedUser(),
$this->getOrganization()
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
namespace Oro\Bundle\EmailBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class OverrideServiceSwiftMailer implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
/* @var $definition \Symfony\Component\DependencyInjection\DefinitionDecorator */
$definition = $container->findDefinition('mailer');
$definition->addArgument(new Reference('oro_email.logger.link'));
}
}
47 changes: 47 additions & 0 deletions src/Oro/Bundle/EmailBundle/Entity/Provider/EmailThreadProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use Oro\Bundle\EmailBundle\Entity\Email;
use Oro\Bundle\EmailBundle\Entity\EmailThread;
use Oro\Bundle\UserBundle\Entity\User;

class EmailThreadProvider
{
Expand Down Expand Up @@ -118,4 +119,50 @@ public function getThreadEmails(EntityManager $entityManager, Email $entity)

return $result;
}

/**
* Get emails in thread by given email.
* Used on `My Emails` page to show emails thread with only emails being related to currently logged user.
*
* @param EntityManager $entityManager
* @param Email $entity
* @param User $user
* @param array $mailboxes
* @return array
*/
public function getUserThreadEmails(EntityManager $entityManager, Email $entity, User $user, $mailboxes = [])
{
$thread = $entity->getThread();
if ($thread) {
/** @var QueryBuilder $queryBuilder */
$queryBuilder = $entityManager->getRepository('OroEmailBundle:Email')->createQueryBuilder('e');
$queryBuilder->join('e.emailUsers', 'eu');

$criteria = new Criteria();
$criteria->where($criteria->expr()->eq('thread', $thread));
$criteria->orderBy(['sentAt' => Criteria::DESC]);

if ($mailboxes) {
$criteria->andWhere(
$criteria->expr()->orX(
$criteria->expr()->in('eu.mailboxOwner', $mailboxes),
$criteria->expr()->eq('eu.owner', $user)
)
);
} else {
$criteria->andWhere(
$criteria->expr()->eq('eu.owner', $user)
);
}

$result = $queryBuilder
->addCriteria($criteria)
->getQuery()
->getResult();
} else {
$result = [$entity];
}

return $result;
}
}
Loading

0 comments on commit 010c538

Please sign in to comment.