Test Failed
Push — master ( c2139f...3d9e00 )
by Paweł
56:29
created

ContainerProvider::getContainerWidgets()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher Core Bundle.
5
 *
6
 * Copyright 2016 Sourcefabric z.ú. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2016 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Bundle\CoreBundle\Provider;
16
17
use Doctrine\ORM\PersistentCollection;
18
use Doctrine\ORM\Query;
19
use Doctrine\ORM\QueryBuilder;
20
use SWP\Component\Revision\Context\RevisionContext;
21
use SWP\Bundle\TemplatesSystemBundle\Provider\ContainerProvider as BaseContentProvider;
22
use SWP\Component\Common\Criteria\Criteria;
23
use SWP\Component\Revision\Model\RevisionInterface;
24
use SWP\Component\TemplatesSystem\Gimme\Model\ContainerInterface;
25
26
/**
27
 * Revisions Aware ContainerProvider.
28
 */
29
class ContainerProvider extends BaseContentProvider
30
{
31
    /**
32
     * @var RevisionContext
33
     */
34
    protected $revisionContext;
35
36
    /**
37
     * {@inheritdoc}
38
     */
39
    public function getQueryForAll(): Query
40
    {
41
        $criteria = new Criteria();
42
        $criteria->set('revision', $this->revisionContext->getCurrentRevision());
43
44
        return $this->containerRepository->getQueryByCriteria($criteria, [], 'r')->getQuery();
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function getOneByName(string $name)
51
    {
52
        /** @var PersistentCollection $containers */
53
        $containers = $this->addRevisionToQueryBuilder($this->containerRepository->getByName($name))
54
            ->getQuery()
55
            ->getResult();
56
57
        return $this->getContainerFromCollection($containers);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function getOneById($uuid)
64
    {
65
        $qb = $this->containerRepository->createQueryBuilder('c')
66
            ->andWhere('c.uuid = :uuid')
67
            ->setParameters([
68
                'uuid' => $uuid,
69
            ]);
70
71
        $containers = $this->addRevisionToQueryBuilder($qb)
72
            ->getQuery()
73
            ->getResult();
74
75
        return $this->getContainerFromCollection($containers);
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function getContainerWidgets(ContainerInterface $container): array
82
    {
83
        return $this->containerWidgetRepository
84
            ->getSortedWidgets(['container' => $container])
85
            ->getQuery()
86
            ->getResult();
87
    }
88
89
    /**
90
     * @param RevisionContext $revisionContext
91
     */
92
    public function setRevisionContext(RevisionContext $revisionContext)
93
    {
94
        $this->revisionContext = $revisionContext;
95
    }
96
97
    private function addRevisionToQueryBuilder(QueryBuilder $queryBuilder)
98
    {
99
        if (RevisionInterface::STATE_NEW === $this->revisionContext->getCurrentRevision()->getStatus()) {
100
            $queryBuilder->andWhere($queryBuilder->expr()->orX(
101
                $queryBuilder->expr()->eq('c.revision', $this->revisionContext->getPublishedRevision()->getId()),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SWP\Component\Revision\Model\RevisionInterface as the method getId() does only exist in the following implementations of said interface: SWP\Bundle\CoreBundle\Model\Revision, SWP\Bundle\RevisionBundle\Model\Revision.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
102
                $queryBuilder->expr()->eq('c.revision', $this->revisionContext->getCurrentRevision()->getId())
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SWP\Component\Revision\Model\RevisionInterface as the method getId() does only exist in the following implementations of said interface: SWP\Bundle\CoreBundle\Model\Revision, SWP\Bundle\RevisionBundle\Model\Revision.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
103
            ));
104
        } else {
105
            $queryBuilder
106
                ->andWhere('c.revision = :currentRevision')
107
                ->setParameter('currentRevision', $this->revisionContext->getCurrentRevision());
108
        }
109
110
        return $queryBuilder;
111
    }
112
113
    private function getContainerFromCollection($containers)
114
    {
115
        if (empty($containers)) {
116
            return;
117
        }
118
119
        if (count($containers) > 1) {
120
            /** @var \SWP\Bundle\CoreBundle\Model\ContainerInterface $container */
121
            foreach ($containers as $container) {
122
                if (RevisionInterface::STATE_NEW === $container->getRevision()->getStatus()) {
123
                    break;
124
                }
125
            }
126
        } else {
127
            $container = $containers[0];
128
        }
129
130
        return $container;
0 ignored issues
show
Bug introduced by
The variable $container does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
131
    }
132
}
133