Completed
Pull Request — 5.6 (#2830)
by Jeroen
14:14
created

PagePartRefRepository   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 188
Duplicated Lines 19.15 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 9
dl 36
loc 188
ccs 0
cts 83
cp 0
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A addPagePart() 0 26 4
A getPagePartRefs() 0 8 1
A getPageParts() 4 38 5
A copyPageParts() 0 16 3
A countPagePartsOfType() 17 17 1
A hasPageParts() 15 15 1
A getPagePart() 0 10 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 Kunstmaan\PagePartBundle\Repository;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\EntityRepository;
7
use Kunstmaan\AdminBundle\Entity\DeepCloneInterface;
8
use Kunstmaan\AdminBundle\Entity\EntityInterface;
9
use Kunstmaan\PagePartBundle\Entity\PagePartRef;
10
use Kunstmaan\PagePartBundle\Helper\HasPagePartsInterface;
11
use Kunstmaan\PagePartBundle\Helper\PagePartInterface;
12
use Kunstmaan\UtilitiesBundle\Helper\ClassLookup;
13
14
/**
15
 * PagePartRefRepository
16
 */
17
class PagePartRefRepository extends EntityRepository
18
{
19
    /**
20
     * @param HasPagePartsInterface $page               The page
21
     * @param PagePartInterface     $pagepart           The pagepart
22
     * @param int                   $sequencenumber     The sequence numer
23
     * @param string                $context            The context
24
     * @param bool                  $pushOtherPageParts Push other pageparts (sequence + 1)
25
     *
26
     * @return PagePartRef
27
     */
28
    public function addPagePart(HasPagePartsInterface $page, PagePartInterface $pagepart, $sequencenumber, $context = 'main', $pushOtherPageParts = true)
29
    {
30
        if ($pushOtherPageParts) {
31
            $pagepartrefs = $this->getPagePartRefs($page, $context);
32
            foreach ($pagepartrefs as $pagepartref) {
33
                if ($pagepartref->getSequencenumber() >= $sequencenumber) {
34
                    $pagepartref->setSequencenumber($pagepartref->getSequencenumber() + 1);
35
                    $this->getEntityManager()->persist($pagepartref);
36
                }
37
            }
38
        }
39
40
        $pagepartref = new PagePartRef();
41
        $pagepartref->setContext($context);
42
        $pageClassname = ClassLookup::getClass($page);
43
        $pagepartref->setPageEntityname($pageClassname);
44
        $pagepartref->setPageId($page->getId());
45
        $pagepartClassname = ClassLookup::getClass($pagepart);
46
        $pagepartref->setPagePartEntityname($pagepartClassname);
47
        $pagepartref->setPagePartId($pagepart->getId());
48
        $pagepartref->setSequencenumber($sequencenumber);
49
        $this->getEntityManager()->persist($pagepartref);
50
        $this->getEntityManager()->flush();
51
52
        return $pagepartref;
53
    }
54
55
    /**
56
     * @param HasPagePartsInterface $page    The page
57
     * @param string                $context The string
58
     *
59
     * @return PagePartRef[]
60
     */
61
    public function getPagePartRefs(HasPagePartsInterface $page, $context = 'main')
62
    {
63
        return $this->findBy([
64
            'pageId' => $page->getId(),
65
            'pageEntityname' => ClassLookup::getClass($page),
66
            'context' => $context,
67
        ], ['sequencenumber' => 'ASC']);
68
    }
69
70
    /**
71
     * @param HasPagePartsInterface $page    The page
72
     * @param string                $context The pagepart context
73
     *
74
     * @return PagePartInterface[]
75
     */
76
    public function getPageParts(HasPagePartsInterface $page, $context = 'main')
77
    {
78
        $pagepartrefs = $this->getPagePartRefs($page, $context);
79
80
        // Group pagepartrefs per type and remember the sorting order
81
        $types = $order = [];
82
        $counter = 1;
83
        foreach ($pagepartrefs as $pagepartref) {
84
            $types[$pagepartref->getPagePartEntityname()][] = $pagepartref->getPagePartId();
85
            $order[$pagepartref->getPagePartEntityname() . $pagepartref->getPagePartId()] = $counter;
86
            ++$counter;
87
        }
88
89
        // Fetch all the pageparts (only one query per pagepart type)
90
        $pageparts = [];
91 View Code Duplication
        foreach ($types as $classname => $ids) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
92
            $result = $this->getEntityManager()->getRepository($classname)->findBy(['id' => $ids]);
93
            $pageparts = array_merge($pageparts, $result);
94
        }
95
96
        // Order the pageparts
97
        usort($pageparts, function (EntityInterface $a, EntityInterface $b) use ($order) {
98
            $aPosition = $order[\get_class($a) . $a->getId()];
99
            $bPosition = $order[\get_class($b) . $b->getId()];
100
101
            if ($aPosition < $bPosition) {
102
                return -1;
103
            }
104
105
            if ($aPosition > $bPosition) {
106
                return 1;
107
            }
108
109
            return 0;
110
        });
111
112
        return $pageparts;
113
    }
114
115
    /**
116
     * @param EntityManager         $em       The entity manager
117
     * @param HasPagePartsInterface $fromPage The page from where you copy the pageparts
118
     * @param HasPagePartsInterface $toPage   The page to where you want to copy the pageparts
119
     * @param string                $context  The pagepart context
120
     */
121
    public function copyPageParts(EntityManager $em, HasPagePartsInterface $fromPage, HasPagePartsInterface $toPage, $context = 'main')
122
    {
123
        $fromPageParts = $this->getPageParts($fromPage, $context);
124
        $sequenceNumber = 1;
125
        foreach ($fromPageParts as $fromPagePart) {
126
            $toPagePart = clone $fromPagePart;
127
            $toPagePart->setId(null);
128
            if ($toPagePart instanceof DeepCloneInterface) {
129
                $toPagePart->deepClone();
130
            }
131
            $em->persist($toPagePart);
132
            $em->flush($toPagePart);
133
            $this->addPagePart($toPage, $toPagePart, $sequenceNumber, $context, false);
134
            ++$sequenceNumber;
135
        }
136
    }
137
138
    /**
139
     * @param HasPagePartsInterface $page              The page
140
     * @param string                $pagepartClassname The classname of the pagepart
141
     * @param string                $context           The context
142
     *
143
     * @return mixed
144
     */
145 View Code Duplication
    public function countPagePartsOfType(HasPagePartsInterface $page, $pagepartClassname, $context = 'main')
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...
146
    {
147
        $em = $this->getEntityManager();
148
        $pageClassname = ClassLookup::getClass($page);
149
150
        $sql = 'SELECT COUNT(pp.id) FROM KunstmaanPagePartBundle:PagePartRef pp
151
                 WHERE pp.pageEntityname = :pageEntityname
152
                   AND pp.pageId = :pageId
153
                   AND pp.pagePartEntityname = :pagePartEntityname
154
                   AND pp.context = :context';
155
156
        return $em->createQuery($sql)
157
                ->setParameter('pageEntityname', $pageClassname)
158
                ->setParameter('pageId', $page->getId())
159
                ->setParameter('pagePartEntityname', $pagepartClassname)
160
                ->setParameter('context', $context)->getSingleScalarResult();
161
    }
162
163
    /**
164
     * Test if entity has pageparts for the specified context
165
     *
166
     * @param HasPagePartsInterface $page    The page
167
     * @param string                $context The context
168
     *
169
     * @return bool
170
     */
171 View Code Duplication
    public function hasPageParts(HasPagePartsInterface $page, $context = 'main')
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...
172
    {
173
        $em = $this->getEntityManager();
174
        $pageClassname = ClassLookup::getClass($page);
175
176
        $sql = 'SELECT COUNT(pp.id) FROM KunstmaanPagePartBundle:PagePartRef pp
177
                 WHERE pp.pageEntityname = :pageEntityname
178
                   AND pp.pageId = :pageId
179
                   AND pp.context = :context';
180
181
        return $em->createQuery($sql)
182
                ->setParameter('pageEntityname', $pageClassname)
183
                ->setParameter('pageId', $page->getId())
184
                ->setParameter('context', $context)->getSingleScalarResult() != 0;
185
    }
186
187
    /**
188
     * @param int    $id             The id
189
     * @param string $context        The context
190
     * @param int    $sequenceNumber The sequence number
191
     *
192
     * @return PagePartInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be PagePartInterface|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
193
     */
194
    public function getPagePart($id, $context = 'main', $sequenceNumber)
195
    {
196
        $ppRef = $this->find($id);
197
        $ppRef->setContext($context);
198
        $ppRef->setSequenceNumber($sequenceNumber);
199
        $this->getEntityManager()->persist($ppRef);
0 ignored issues
show
Bug introduced by
It seems like $ppRef defined by $this->find($id) on line 196 can also be of type null; however, Doctrine\ORM\EntityManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
200
        $this->getEntityManager()->flush($ppRef);
201
202
        return $this->getEntityManager()->getRepository($ppRef->getPagePartEntityName())->find($ppRef->getPagePartId());
203
    }
204
}
205