GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 46e57d...ec86a4 )
by Christian
01:49
created

src/EventListener/ORM/SortableListener.php (1 issue)

1
<?php
2
3
/*
4
 * (c) Christian Gripp <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Core23\DoctrineExtensions\EventListener\ORM;
11
12
use Core23\DoctrineExtensions\Model\PositionAwareInterface;
13
use Core23\DoctrineExtensions\Model\Traits\SortableTrait;
14
use Doctrine\ORM\EntityManager;
15
use Doctrine\ORM\Event\LifecycleEventArgs;
16
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
17
use Doctrine\ORM\Event\PreUpdateEventArgs;
18
use Doctrine\ORM\Events;
19
use Doctrine\ORM\Mapping\ClassMetadata;
20
use Doctrine\ORM\Mapping\MappingException;
21
use Doctrine\ORM\NonUniqueResultException;
22
use Symfony\Component\PropertyAccess\PropertyAccess;
23
24
final class SortableListener extends AbstractListener
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function getSubscribedEvents()
30
    {
31
        return array(
32
            Events::prePersist,
33
            Events::preUpdate,
34
            Events::preRemove,
35
            Events::loadClassMetadata,
36
        );
37
    }
38
39
    /**
40
     * @param LifecycleEventArgs $args
41
     */
42
    public function prePersist(LifecycleEventArgs $args): void
43
    {
44
        if ($args->getEntity() instanceof PositionAwareInterface) {
45
            $this->uniquePosition($args);
46
        }
47
    }
48
49
    /**
50
     * @param PreUpdateEventArgs $args
51
     */
52
    public function preUpdate(PreUpdateEventArgs $args): void
53
    {
54
        if ($args->getEntity() instanceof PositionAwareInterface) {
55
            $position = $args->getEntity()->getPosition();
56
57
            if ($args->hasChangedField('position')) {
58
                $position = $args->getOldValue('position');
59
            }
60
61
            $this->uniquePosition($args, $position);
62
        }
63
    }
64
65
    /**
66
     * @param LifecycleEventArgs $args
67
     */
68
    public function preRemove(LifecycleEventArgs $args): void
69
    {
70
        $entity = $args->getEntity();
71
72
        if ($entity instanceof PositionAwareInterface) {
73
            $this->movePosition($args->getEntityManager(), $entity, -1);
74
        }
75
    }
76
77
    /**
78
     * @param LoadClassMetadataEventArgs $eventArgs
79
     *
80
     * @throws MappingException
81
     */
82
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void
83
    {
84
        $meta = $eventArgs->getClassMetadata();
85
86
        if (!$meta instanceof ClassMetadata) {
87
            throw new \LogicException(sprintf('Class metadata was no ORM but %s', get_class($meta)));
88
        }
89
90
        if (!$this->containsTrait($meta->getReflectionClass(), SortableTrait::class)) {
91
            return;
92
        }
93
94
        if (!$meta->hasField('position')) {
95
            $meta->mapField(array(
96
                'type'      => 'integer',
97
                'fieldName' => 'position',
98
            ));
99
        }
100
    }
101
102
    /**
103
     * @param LifecycleEventArgs $args
104
     * @param int|null           $oldPosition
105
     */
106
    private function uniquePosition(LifecycleEventArgs $args, ? int $oldPosition = null): void
107
    {
108
        $entity = $args->getEntity();
109
110
        if ($entity instanceof PositionAwareInterface) {
111
            if (null === $entity->getPosition()) {
112
                $position = $this->getNextPosition($args->getEntityManager(), $entity);
113
                $entity->setPosition($position);
114
            } elseif ($oldPosition && $oldPosition !== $entity->getPosition()) {
115
                $this->movePosition($args->getEntityManager(), $entity);
116
            }
117
        }
118
    }
119
120
    /**
121
     * @param EntityManager          $em
122
     * @param PositionAwareInterface $entity
123
     * @param int                    $direction
124
     */
125
    private function movePosition(EntityManager $em, PositionAwareInterface $entity, int $direction = 1): void
126
    {
127
        $uow   = $em->getUnitOfWork();
128
        $meta  = $em->getClassMetadata(get_class($entity));
129
130
        $qb = $em->createQueryBuilder()
131
            ->update($meta->getName(), 'e')
132
            ->set('e.position', 'e.position + '.$direction);
133
134
        if ($direction > 0) {
135
            $qb->andWhere('e.position <= :position')->setParameter('position', $entity->getPosition());
136
        } elseif ($direction < 0) {
137
            $qb->andWhere('e.position >= :position')->setParameter('position', $entity->getPosition());
138
        } else {
139
            return;
140
        }
141
142
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
143
144
        foreach ($entity->getPositionGroup() as $field) {
145
            $value = $propertyAccessor->getValue($entity, $field);
146
147
            if (is_object($value) && null === $uow->getSingleIdentifierValue($value)) {
148
                continue;
149
            }
150
151
            $qb->andWhere('e.'.$field.' = :'.$field)->setParameter($field, $value);
152
        }
153
154
        $qb->getQuery()->execute();
155
    }
156
157
    /**
158
     * @param EntityManager          $em
159
     * @param PositionAwareInterface $entity
160
     *
161
     * @return int
162
     */
163
    private function getNextPosition(EntityManager $em, PositionAwareInterface $entity): int
164
    {
165
        $meta = $em->getClassMetadata(get_class($entity));
166
167
        $qb = $em->createQueryBuilder()
168
            ->select('e')
169
            ->from($meta->getName(), 'e')
170
            ->addOrderBy('e.position', 'DESC')
171
            ->setMaxResults(1);
172
173
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
174
175
        foreach ($entity->getPositionGroup() as $field) {
176
            $value = $propertyAccessor->getValue($entity, $field);
177
            $qb->andWhere('e.'.$field.' = :'.$field)->setParameter($field, $value);
178
        }
179
180
        /* @var PositionAwareInterface $result */
181
        try {
182
            $result = $qb->getQuery()->getOneOrNullResult();
183
184
            return ($result ? $result->getPosition() : 0) + 1;
185
        } catch (NonUniqueResultException $ignored) {
186
        }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return integer. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
187
    }
188
}
189