Completed
Push — master ( 3d485f...407dff )
by Paweł
66:49
created

RevisionManager::publish()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 14
nc 5
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Publisher Revision Bundle.
7
 *
8
 * Copyright 2017 Sourcefabric z.u. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2015 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\RevisionBundle\Manager;
18
19
use Doctrine\ORM\EntityManagerInterface;
20
use SWP\Bundle\RevisionBundle\Event\RevisionPublishedEvent;
21
use SWP\Bundle\RevisionBundle\Events;
22
use SWP\Component\Revision\Manager\RevisionManagerInterface;
23
use SWP\Component\Revision\Context\RevisionContextInterface;
24
use SWP\Component\Storage\Factory\FactoryInterface;
25
use SWP\Component\Revision\Model\RevisionInterface;
26
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
27
28
class RevisionManager implements RevisionManagerInterface
29
{
30
    /**
31
     * @var FactoryInterface
32
     */
33
    protected $revisionFactory;
34
35
    /**
36
     * @var RevisionContextInterface
37
     */
38
    protected $revisionContext;
39
40
    /**
41
     * @var EntityManagerInterface
42
     */
43
    protected $objectManager;
44
45
    /**
46
     * @var EventDispatcherInterface
47
     */
48
    protected $eventDispatcher;
49
50
    /**
51
     * RevisionManager constructor.
52
     *
53
     * @param FactoryInterface         $revisionFactory
54
     * @param RevisionContextInterface $revisionContext
55
     * @param EventDispatcherInterface $eventDispatcher
56
     * @param EntityManagerInterface   $objectManager
57
     */
58
    public function __construct(
59
        FactoryInterface $revisionFactory,
60
        RevisionContextInterface $revisionContext,
61
        EventDispatcherInterface $eventDispatcher,
62
        EntityManagerInterface $objectManager
63
    ) {
64
        $this->revisionFactory = $revisionFactory;
65
        $this->revisionContext = $revisionContext;
66
        $this->eventDispatcher = $eventDispatcher;
67
        $this->objectManager = $objectManager;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73
    public function publish(RevisionInterface $revision, RevisionInterface $workingRevision = null): RevisionInterface
74
    {
75
        if ($revision->getStatus() !== RevisionInterface::STATE_NEW) {
76
            return $revision;
77
        }
78
79
        $revision->setStatus(RevisionInterface::STATE_PUBLISHED);
80
        if (null !== $previousRevision = $revision->getPrevious()) {
81
            $previousRevision->setStatus(RevisionInterface::STATE_REPLACED);
82
        }
83
        $revision->setPublishedAt(new \DateTime());
84
85
        if (null === $workingRevision) {
86
            $workingRevision = $this->create($revision);
87
        }
88
89
        $this->revisionContext->setWorkingRevision($workingRevision);
90
        $this->revisionContext->setPublishedRevision($revision);
91
        $this->objectManager->flush();
92
93
        $this->eventDispatcher->dispatch(Events::REVISION_PUBLISH, new RevisionPublishedEvent($revision));
94
95
        return $revision;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function rollback(RevisionInterface $revision): RevisionInterface
102
    {
103
        // TODO: Implement rollback() method.
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function create(RevisionInterface $previous = null): RevisionInterface
110
    {
111
        /** @var RevisionInterface $revision */
112
        $revision = $this->revisionFactory->create();
113
114
        if (null !== $previous) {
115
            $revision->setPrevious($previous);
116
            $this->objectManager->persist($previous);
117
            $revision->setTenantCode($previous->getTenantCode());
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 getTenantCode() does only exist in the following implementations of said interface: SWP\Bundle\CoreBundle\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...
118
        }
119
120
        $this->objectManager->persist($revision);
121
        $this->objectManager->flush();
122
123
        return $revision;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getRevisionContext(): RevisionContextInterface
130
    {
131
        return $this->revisionContext;
132
    }
133
}
134