AbstractProvider::save()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 2
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace DoS\ResourceBundle\Provider;
4
5
use Doctrine\Common\Persistence\ObjectManager;
6
use Sylius\Component\Resource\Factory\FactoryInterface;
7
use Sylius\Component\Resource\Model\ResourceInterface;
8
use Sylius\Component\Resource\Repository\RepositoryInterface;
9
10
/**
11
 * @author liverbool <[email protected]>
12
 */
13
abstract class AbstractProvider implements ProviderInterface
14
{
15
    /**
16
     * @var ObjectManager
17
     */
18
    protected $manager;
19
20
    /**
21
     * @var string
22
     */
23
    protected $dataClass;
24
25
    /**
26
     * @var RepositoryInterface
27
     */
28
    protected $repository;
29
30
    /**
31
     * @var FactoryInterface
32
     */
33
    protected $factory;
34
35
    public function __construct(
36
        RepositoryInterface $repository,
37
        FactoryInterface $factory,
38
        ObjectManager $manager = null,
39
        $dataClass = null
40
    ) {
41
        $this->repository = $repository;
42
        $this->factory = $factory;
43
        $this->manager = $manager ?: $repository->getManager();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Resourc...ory\RepositoryInterface as the method getManager() does only exist in the following implementations of said interface: DoS\ResourceBundle\Doctr...goDB\DocumentRepository, DoS\ResourceBundle\Doctrine\ORM\EntityRepository.

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...
44
        $this->dataClass = $dataClass ?: $repository->getEntityName();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Resourc...ory\RepositoryInterface as the method getEntityName() does only exist in the following implementations of said interface: DoS\ResourceBundle\Doctr...goDB\DocumentRepository, DoS\ResourceBundle\Doctrine\ORM\EntityRepository.

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...
45
    }
46
47
    /**
48
     * @return ResourceInterface
49
     */
50
    public function createNew()
51
    {
52
        return $this->factory->createNew();
53
    }
54
55
    /**
56
     * @param ResourceInterface $resource
57
     */
58
    public function persist(ResourceInterface $resource)
59
    {
60
        $this->manager->persist($resource);
61
    }
62
63
    /**
64
     * @param ResourceInterface|null $resource
65
     */
66
    public function flush(ResourceInterface $resource = null)
67
    {
68
        $this->manager->flush($resource);
69
    }
70
71
    /**
72
     * @param ResourceInterface $resource
73
     * @param bool $single
74
     */
75
    public function save(ResourceInterface $resource, $single = false)
76
    {
77
        $this->manager->persist($resource);
78
        $this->manager->flush($single ? $resource : null);
79
    }
80
81
    /**
82
     * @param ResourceInterface $resource
83
     */
84
    public function detach(ResourceInterface $resource)
85
    {
86
        $this->manager->detach($resource);
87
    }
88
89
    /**
90
     * @param ResourceInterface $resource
91
     */
92
    public function remove(ResourceInterface $resource)
93
    {
94
        $this->manager->remove($resource);
95
    }
96
97
    /**
98
     * @param null $objectName
99
     */
100
    public function clear($objectName = null)
101
    {
102
        $this->manager->clear($objectName);
103
    }
104
105
    /**
106
     * @param $id
107
     *
108
     * @return ResourceInterface
109
     */
110
    public function find($id)
111
    {
112
        return $this->repository->find($id);
113
    }
114
115
    /**
116
     * @return ResourceInterface[]
117
     */
118
    public function findAll()
119
    {
120
        return $this->repository->findAll();
121
    }
122
123
    /**
124
     * @param array $criteria
125
     * @param array|null $orderBy
126
     * @param null $limit
127
     * @param null $offset
128
     *
129
     * @return ResourceInterface[]
130
     */
131
    public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
132
    {
133
        return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
134
    }
135
136
    /**
137
     * @param array $criteria
138
     *
139
     * @return ResourceInterface[]
140
     */
141
    public function findOneBy(array $criteria)
142
    {
143
        return $this->repository->findOneBy($criteria);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->repository->findOneBy($criteria); of type object|null adds the type object to the return on line 143 which is incompatible with the return type declared by the interface DoS\ResourceBundle\Provi...derInterface::findOneBy of type Sylius\Component\Resourc...del\ResourceInterface[].
Loading history...
144
    }
145
}
146