ReferenceDataReader::read()   B
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 25
rs 8.5806
cc 4
eloc 15
nc 6
nop 0
1
<?php
2
3
namespace Pim\Bundle\CustomEntityBundle\MassEditConnector\Reader;
4
5
use Akeneo\Component\Batch\Model\StepExecution;
6
use Akeneo\Component\Batch\Item\AbstractConfigurableStepElement;
7
use Akeneo\Component\Batch\Item\ItemReaderInterface;
8
use Akeneo\Component\Batch\Step\StepExecutionAwareInterface;
9
use Doctrine\Common\Collections\ArrayCollection;
10
use Doctrine\ORM\EntityManager;
11
use Doctrine\ORM\EntityNotFoundException;
12
use Pim\Bundle\CustomEntityBundle\Entity\Repository\CustomEntityRepository;
13
use Pim\Component\Connector\Repository\JobConfigurationRepositoryInterface;
14
use Pim\Component\ReferenceData\ConfigurationRegistry;
15
use Symfony\Component\OptionsResolver\OptionsResolver;
16
17
/**
18
 * @author Romain Monceau <[email protected]>
19
 */
20
class ReferenceDataReader extends AbstractConfigurableStepElement implements
21
    ItemReaderInterface,
22
    StepExecutionAwareInterface
23
{
24
    /** @var StepExecution */
25
    protected $stepExecution;
26
27
    /** @var JobConfigurationRepositoryInterface */
28
    protected $jobConfigRepository;
29
30
    /** @var EntityManager */
31
    protected $em;
32
33
    /** @var ArrayCollection */
34
    protected $referenceDatas;
35
36
    /** @var  ConfigurationRegistry */
37
    protected $registry;
38
39
    /**
40
     * @param JobConfigurationRepositoryInterface $jobConfigRepository
41
     * @param EntityManager                       $em
42
     * @param ConfigurationRegistry               $registry
43
     */
44
    public function __construct(
45
        JobConfigurationRepositoryInterface $jobConfigRepository,
46
        EntityManager $em,
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $em. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
47
        ConfigurationRegistry $registry
48
    ) {
49
        $this->jobConfigRepository = $jobConfigRepository;
50
        $this->em = $em;
51
        $this->registry = $registry;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function read()
58
    {
59
        $config = $this->getJobConfiguration();
60
61
        $resolver = new OptionsResolver();
62
        $this->configureOptions($resolver);
63
        $config = $resolver->resolve($config);
64
65
        if (null === $this->referenceDatas) {
66
            if ($config['reference_data']) {
67
                $this->referenceDatas = $this->getReferenceDatas($config['reference_data'], $config['ids']);
68
            }
69
        }
70
71
        $result = $this->referenceDatas->current();
72
73
        if (!empty($result)) {
74
            $this->stepExecution->incrementSummaryInfo('read');
75
            $this->referenceDatas->next();
76
        } else {
77
            $result = null;
78
        }
79
80
        return $result;
81
    }
82
83
    /**
84
     * Get reference data entities from ids
85
     *
86
     * @param string $referenceDataName
87
     * @param array  $ids
88
     *
89
     * @return ArrayCollection
90
     */
91
    protected function getReferenceDatas($referenceDataName, array $ids)
92
    {
93
        $repository = $this->getRepository($referenceDataName);
94
95
        return $repository->findByIds($ids);
96
    }
97
98
    /**
99
     * @param string $referenceDataName
100
     *
101
     * @return CustomEntityRepository
102
     */
103
    protected function getRepository($referenceDataName)
104
    {
105
        return $this->em->getRepository($referenceDataName);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    protected function getJobConfiguration()
112
    {
113
        $jobExecution = $this->stepExecution->getJobExecution();
114
        $massEditJobConf = $this->jobConfigRepository->findOneBy(['jobExecution' => $jobExecution]);
115
116
        if (null === $massEditJobConf) {
117
            throw new EntityNotFoundException(sprintf(
0 ignored issues
show
Unused Code introduced by
The call to EntityNotFoundException::__construct() has too many arguments starting with sprintf('No JobConfigura...$jobExecution->getId()).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
118
                'No JobConfiguration found for jobExecution with id "%s"',
119
                $jobExecution->getId()
120
            ));
121
        }
122
123
        return json_decode(stripcslashes($massEditJobConf->getConfiguration()), true);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getConfigurationFields()
130
    {
131
        return [];
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function setStepExecution(StepExecution $stepExecution)
138
    {
139
        $this->stepExecution = $stepExecution;
140
    }
141
142
    /**
143
     * @param OptionsResolver $resolver
144
     */
145
    protected function configureOptions(OptionsResolver $resolver)
146
    {
147
        $allowedValues = array_map(function ($configuration) {
148
            return $configuration->getClass();
149
        }, $this->registry->all());
150
151
        $resolver->setRequired([
152
            'reference_data',
153
            'ids'
154
        ]);
155
        $resolver->setAllowedValues('reference_data', $allowedValues);
156
    }
157
}
158