Completed
Push — 1.9 ( 30c3e5...ca8b96 )
by
unknown
42:25
created

LeadRepository   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 159
Duplicated Lines 18.87 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 5
dl 30
loc 159
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getOpportunitiesByLeadSource() 17 17 2
D processOpportunitiesByLeadSource() 0 43 9
A sumCount() 0 9 2
A sortByCountReverse() 0 12 3
A getLeadsCount() 0 6 1
A getNewLeadsCount() 0 8 1
A createLeadsCountQb() 13 13 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace OroCRM\Bundle\SalesBundle\Entity\Repository;
4
5
use DateTime;
6
7
use Doctrine\ORM\EntityRepository;
8
use Doctrine\ORM\QueryBuilder;
9
10
use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper;
11
12
class LeadRepository extends EntityRepository
13
{
14
    /**
15
     * Returns top $limit opportunities grouped by lead source
16
     *
17
     * @param  AclHelper $aclHelper
18
     * @param  int       $limit
19
     * @param  array     $dateRange
20
     * @return array     [itemCount, label]
21
     */
22 View Code Duplication
    public function getOpportunitiesByLeadSource(AclHelper $aclHelper, $limit = 10, $dateRange = 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...
23
    {
24
        $qb   = $this->createQueryBuilder('l')
25
            ->select('s.id as source, count(o.id) as itemCount')
26
            ->leftJoin('l.opportunities', 'o')
27
            ->leftJoin('l.source', 's')
28
            ->groupBy('source');
29
30
        if ($dateRange) {
31
            $qb->andWhere($qb->expr()->between('o.createdAt', ':dateStart', ':dateEnd'))
32
                ->setParameter('dateStart', $dateRange['start'])
33
                ->setParameter('dateEnd', $dateRange['end']);
34
        }
35
        $rows = $aclHelper->apply($qb)->getArrayResult();
36
37
        return $this->processOpportunitiesByLeadSource($rows, $limit);
38
    }
39
40
    /**
41
     * @param array $rows
42
     * @param int   $limit
43
     *
44
     * @return array
45
     */
46
    protected function processOpportunitiesByLeadSource(array $rows, $limit)
47
    {
48
        $result       = [];
49
        $unclassified = null;
50
        $others       = [];
51
52
        $this->sortByCountReverse($rows);
53
        foreach ($rows as $row) {
54
            if ($row['itemCount']) {
55
                if ($row['source'] === null) {
56
                    $unclassified = $row;
57
                } else {
58
                    if (count($result) < $limit) {
59
                        $result[] = $row;
60
                    } else {
61
                        $others[] = $row;
62
                    }
63
                }
64
            }
65
        }
66
67
        if ($unclassified) {
68
            if (count($result) === $limit) {
69
                // allocate space for 'unclassified' item
70
                array_unshift($others, array_pop($result));
71
            }
72
            // add 'unclassified' item to the top to avoid moving it to $others
73
            array_unshift($result, $unclassified);
74
        }
75
        if (!empty($others)) {
76
            if (count($result) === $limit) {
77
                // allocate space for 'others' item
78
                array_unshift($others, array_pop($result));
79
            }
80
            // add 'others' item
81
            $result[] = [
82
                'source'    => '',
83
                'itemCount' => $this->sumCount($others)
84
            ];
85
        }
86
87
        return $result;
88
    }
89
90
    /**
91
     * @param array $rows
92
     *
93
     * @return int
94
     */
95
    protected function sumCount(array $rows)
96
    {
97
        $result = 0;
98
        foreach ($rows as $row) {
99
            $result += $row['itemCount'];
100
        }
101
102
        return $result;
103
    }
104
105
    /**
106
     * @param array $rows
107
     */
108
    protected function sortByCountReverse(array &$rows)
109
    {
110
        usort(
111
            $rows,
112
            function ($a, $b) {
113
                if ($a['itemCount'] === $b['itemCount']) {
114
                    return 0;
115
                }
116
                return $a['itemCount'] < $b['itemCount'] ? 1 : -1;
117
            }
118
        );
119
    }
120
121
    /**
122
     * @param AclHelper $aclHelper
123
     * @param DateTime $start
124
     * @param DateTime $end
125
     *
126
     * @return int
127
     */
128
    public function getLeadsCount(AclHelper $aclHelper, DateTime $start, DateTime $end)
129
    {
130
        $qb = $this->createLeadsCountQb($start, $end);
131
132
        return $aclHelper->apply($qb)->getSingleScalarResult();
133
    }
134
135
    /**
136
     * @param AclHelper $aclHelper
137
     * @param DateTime $start
138
     * @param DateTime $end
139
     *
140
     * @return int
141
     */
142
    public function getNewLeadsCount(AclHelper $aclHelper, DateTime $start, DateTime $end)
143
    {
144
        $qb = $this->createLeadsCountQb($start, $end)
145
            ->andWhere('l.status = :status')
146
            ->setParameter('status', 'new');
147
148
        return $aclHelper->apply($qb)->getSingleScalarResult();
149
    }
150
151
    /**
152
     * @param DateTime $start
153
     * @param DateTime $end
154
     *
155
     * @return QueryBuilder
156
     */
157 View Code Duplication
    protected function createLeadsCountQb(DateTime $start, DateTime $end)
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...
158
    {
159
        $qb = $this->createQueryBuilder('l');
160
161
        $qb
162
            ->select('COUNT(DISTINCT l.id)')
163
            ->andWhere($qb->expr()->between('l.createdAt', ':start', ':end'))
164
            ->innerJoin('l.opportunities', 'o')
165
            ->setParameter('start', $start)
166
            ->setParameter('end', $end);
167
168
        return $qb;
169
    }
170
}
171