Completed
Push — master ( 1758db...0d3940 )
by Jordi Sala
02:09
created

src/Listener/ORM/MediaEventSubscriber.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\MediaBundle\Listener\ORM;
15
16
use Doctrine\Common\EventArgs;
17
use Doctrine\ORM\Events;
18
use Sonata\ClassificationBundle\Model\CategoryInterface;
19
use Sonata\MediaBundle\Listener\BaseMediaEventSubscriber;
20
use Sonata\MediaBundle\Model\MediaInterface;
21
22
/**
23
 * @final since sonata-project/media-bundle 3.21.0
24
 */
25
class MediaEventSubscriber extends BaseMediaEventSubscriber
26
{
27
    /**
28
     * @var CategoryInterface[]
29
     */
30
    protected $rootCategories;
31
32
    public function getSubscribedEvents()
33
    {
34
        return [
35
            Events::prePersist,
36
            Events::preUpdate,
37
            Events::preRemove,
38
            Events::postUpdate,
39
            Events::postRemove,
40
            Events::postPersist,
41
            Events::onClear,
42
        ];
43
    }
44
45
    public function onClear(): void
46
    {
47
        $this->rootCategories = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array<integer,object<Son...del\CategoryInterface>> of property $rootCategories.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
48
    }
49
50
    protected function recomputeSingleEntityChangeSet(EventArgs $args): void
51
    {
52
        $em = $args->getEntityManager();
53
54
        $em->getUnitOfWork()->recomputeSingleEntityChangeSet(
55
            $em->getClassMetadata(\get_class($args->getEntity())),
56
            $args->getEntity()
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class Doctrine\Common\EventArgs as the method getEntity() does only exist in the following sub-classes of Doctrine\Common\EventArgs: Doctrine\Common\Persiste...vent\LifecycleEventArgs, Doctrine\Common\Persiste...vent\PreUpdateEventArgs, Doctrine\ORM\Event\LifecycleEventArgs, Doctrine\ORM\Event\PreUpdateEventArgs, Doctrine\Persistence\Event\LifecycleEventArgs, Doctrine\Persistence\Event\PreUpdateEventArgs. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
57
        );
58
    }
59
60
    protected function getMedia(EventArgs $args)
61
    {
62
        $media = $args->getEntity();
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class Doctrine\Common\EventArgs as the method getEntity() does only exist in the following sub-classes of Doctrine\Common\EventArgs: Doctrine\Common\Persiste...vent\LifecycleEventArgs, Doctrine\Common\Persiste...vent\PreUpdateEventArgs, Doctrine\ORM\Event\LifecycleEventArgs, Doctrine\ORM\Event\PreUpdateEventArgs, Doctrine\Persistence\Event\LifecycleEventArgs, Doctrine\Persistence\Event\PreUpdateEventArgs. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
63
64
        if (!$media instanceof MediaInterface) {
65
            return $media;
66
        }
67
68
        if ($this->container->has('sonata.media.manager.category') && !$media->getCategory()) {
69
            $media->setCategory($this->getRootCategory($media));
70
        }
71
72
        return $media;
73
    }
74
75
    /**
76
     * @throws \RuntimeException
77
     *
78
     * @return CategoryInterface
79
     */
80
    protected function getRootCategory(MediaInterface $media)
81
    {
82
        if (!$this->rootCategories) {
83
            $this->rootCategories = $this->container->get('sonata.media.manager.category')->getRootCategories(false);
84
        }
85
86
        if (!\array_key_exists($media->getContext(), $this->rootCategories)) {
87
            throw new \RuntimeException(sprintf('There is no main category related to context: %s', $media->getContext()));
88
        }
89
90
        return $this->rootCategories[$media->getContext()];
91
    }
92
}
93