Completed
Push — 1.9 ( 482137...30c3e5 )
by
unknown
43:10
created

EmailDirectionProvider::getDirection()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 36
rs 5.3846
cc 8
eloc 18
nc 8
nop 2
1
<?php
2
3
namespace OroCRM\Bundle\ActivityContactBundle\Provider;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Doctrine\ORM\EntityManager;
7
use Doctrine\Common\Inflector\Inflector;
8
9
use Oro\Bundle\ActivityBundle\EntityConfig\ActivityScope;
10
use Oro\Bundle\EmailBundle\Entity\Email;
11
use Oro\Bundle\EmailBundle\Model\EmailHolderInterface;
12
use Oro\Bundle\EmailBundle\Tools\EmailHolderHelper;
13
use Oro\Bundle\EntityExtendBundle\Tools\ExtendHelper;
14
use Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider;
15
use Oro\Bundle\EntityBundle\ORM\DoctrineHelper;
16
17
use OroCRM\Bundle\ActivityContactBundle\Direction\DirectionProviderInterface;
18
use OroCRM\Bundle\MarketingListBundle\Provider\ContactInformationFieldsProvider;
19
20
/**
21
 * Class EmailDirectionProvider
22
 * @package OroCRM\Bundle\ActivityContactBundle\Provider
23
 */
24
class EmailDirectionProvider implements DirectionProviderInterface
25
{
26
    /**
27
     * @var ConfigProvider
28
     */
29
    protected $configProvider;
30
31
    /**
32
     * @var DoctrineHelper
33
     */
34
    protected $doctrineHelper;
35
36
    /**
37
     * @param ConfigProvider $configProvider
38
     * @param DoctrineHelper $doctrineHelper
39
     */
40
    public function __construct(
41
        ConfigProvider $configProvider,
42
        DoctrineHelper $doctrineHelper,
43
        EmailHolderHelper $emailHolderHelper
44
    ) {
45
        $this->configProvider = $configProvider;
46
        $this->doctrineHelper = $doctrineHelper;
47
        $this->emailHolderHelper = $emailHolderHelper;
0 ignored issues
show
Bug introduced by
The property emailHolderHelper does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function getSupportedClass()
54
    {
55
        return 'Oro\Bundle\EmailBundle\Entity\Email';
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function getDirection($activity, $target)
62
    {
63
        //check if target is entity created from admin part
64
        if (!$target instanceof EmailHolderInterface) {
65
            $metadata = $this->doctrineHelper->getEntityMetadata($target);
66
            $columns = $metadata->getColumnNames();
67
            $className = get_class($target);
68
69
            foreach ($columns as $column) {
70
                //check only columns with 'contact_information'
71
                if ($this->isEmailType($className, $column)) {
72
                    $getMethodName = "get" . Inflector::classify($column);
73
                    /** @var $activity Email */
74
                    if ($activity->getFromEmailAddress()->getEmail() === $target->$getMethodName()) {
75
                        return DirectionProviderInterface::DIRECTION_OUTGOING;
76
                    } else {
77
                        foreach ($activity->getTo() as $recipient) {
78
                            if ($recipient->getEmailAddress()->getEmail() === $target->$getMethodName()) {
79
                                return DirectionProviderInterface::DIRECTION_INCOMING;
80
                            }
81
                        }
82
                    }
83
                }
84
            }
85
86
            return DirectionProviderInterface::DIRECTION_UNKNOWN;
87
        }
88
89
        /** @var $activity Email */
90
        /** @var $target EmailHolderInterface */
91
        if ($activity->getFromEmailAddress()->getEmail() === $target->getEmail()) {
92
            return DirectionProviderInterface::DIRECTION_OUTGOING;
93
        }
94
95
        return DirectionProviderInterface::DIRECTION_INCOMING;
96
    }
97
98
    /**
99
     * @param string      $className
100
     * @param string|null $column
101
     *
102
     * @return bool
103
     */
104
    protected function isEmailType($className, $column)
105
    {
106
        if ($this->configProvider->hasConfig($className, $column)) {
107
            $fieldConfiguration = $this->configProvider->getConfig($className, $column);
108
            $type = $fieldConfiguration->get('contact_information');
109
110
            return $type == ContactInformationFieldsProvider::CONTACT_INFORMATION_SCOPE_EMAIL;
111
        }
112
113
        return false;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function isDirectionChanged($changeSet = [])
120
    {
121
        /**
122
         * For emails direction never can be changed at all.
123
         */
124
        return false;
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function getDate($activity)
131
    {
132
        /** @var $activity Email */
133
        return $activity->getSentAt() ? : new \DateTime('now', new \DateTimeZone('UTC'));
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 View Code Duplication
    public function getLastActivitiesDateForTarget(EntityManager $em, $target, $direction, $skipId = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        $result         = [];
142
        $resultActivity = $this->getLastActivity($em, $target, $skipId);
143
        if ($resultActivity) {
144
            $result['all'] = $this->getDate($resultActivity);
145
            if ($this->getDirection($resultActivity, $target) !== $direction) {
146
                $resultActivity = $this->getLastActivity($em, $target, $skipId, $direction);
147
                if ($resultActivity) {
148
                    $result['direction'] = $this->getDate($resultActivity);
149
                } else {
150
                    $result['direction'] = null;
151
                }
152
            } else {
153
                $result['direction'] = $result['all'];
154
            }
155
        }
156
157
        return $result;
158
    }
159
160
    /**
161
     * @param EntityManager $em
162
     * @param object        $target
163
     * @param integer       $skipId
164
     * @param string        $direction
165
     *
166
     * @return Email
167
     */
168
    protected function getLastActivity(EntityManager $em, $target, $skipId = null, $direction = null)
169
    {
170
        $qb = $em->getRepository('Oro\Bundle\EmailBundle\Entity\Email')
171
            ->createQueryBuilder('email')
172
            ->select('email')
173
            ->innerJoin(
174
                sprintf(
175
                    'email.%s',
176
                    ExtendHelper::buildAssociationName(ClassUtils::getClass($target), ActivityScope::ASSOCIATION_KIND)
177
                ),
178
                'target'
179
            )
180
            ->andWhere('target = :target')
181
            ->orderBy('email.sentAt', 'DESC')
182
            ->setMaxResults(1)
183
            ->setParameter('target', $target);
184
185
        if ($skipId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $skipId of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
186
            $qb->andWhere('email.id <> :skipId')
187
                ->setParameter('skipId', $skipId);
188
        }
189
190
        if ($direction && $target instanceof EmailHolderInterface) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $direction of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
191
            $operator = '!=';
192
            if ($direction === DirectionProviderInterface::DIRECTION_OUTGOING) {
193
                $operator = '=';
194
            }
195
196
            $qb->join('email.fromEmailAddress', 'fromEmailAddress')
197
                ->andWhere('fromEmailAddress.email ' . $operator . ':email')
198
                ->setParameter('email', $this->getTargetEmail($target));
199
        }
200
201
        return $qb->getQuery()->getOneOrNullResult();
202
    }
203
204
    /**
205
     * @param object $target
206
     * @return string
207
     */
208
    protected function getTargetEmail($target)
209
    {
210
        return $this->emailHolderHelper->getEmail($target);
211
    }
212
}
213