DoctrineEntityExtractor::extract()   B
last analyzed

Complexity

Conditions 10
Paths 10

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 10.2217

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 10
eloc 23
c 1
b 1
f 0
nc 10
nop 0
dl 0
loc 37
ccs 20
cts 23
cp 0.8696
crap 10.2217
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Smart\EtlBundle\Extractor;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\EntityRepository;
7
use Doctrine\ORM\QueryBuilder;
8
use Smart\EtlBundle\Entity\ImportableInterface;
9
use Smart\EtlBundle\Exception\Extractor\EntityTypeNotHandledException;
10
use Symfony\Component\PropertyAccess\PropertyAccess;
11
use Symfony\Component\PropertyAccess\PropertyAccessor;
12
13
/**
14
 * Nicolas Bastien <[email protected]>
15
 */
16
class DoctrineEntityExtractor extends AbstractExtractor implements ExtractorInterface
17
{
18
    /**
19
     * @var EntityManager
20
     */
21
    protected $entityManager;
22
23
    /**
24
     * @var PropertyAccessor
25
     */
26
    protected $accessor;
27
28
    /**
29
     * @var string
30
     */
31
    protected $entityToExtract;
32
33
    /**
34
     * @var array
35
     */
36
    protected $propertiesToExtract;
37
38
    /**
39
     * @var QueryBuilder
40
     */
41
    protected $queryBuilder = null;
42
43 1
    public function __construct($entityManager)
44
    {
45 1
        $this->entityManager = $entityManager;
46 1
        $this->accessor = PropertyAccess::createPropertyAccessor();
47 1
    }
48
49
    /**
50
     * @param string $entityToExtract
51
     */
52 1
    public function setEntityToExtract($entityToExtract, array $propertiesToExtract)
53
    {
54 1
        $this->entityToExtract = $entityToExtract;
55 1
        $this->propertiesToExtract = $propertiesToExtract;
56 1
        $this->queryBuilder = null;
57 1
    }
58
59
    /**
60
     * @return QueryBuilder
61
     */
62 1
    public function getQueryBuilder()
63
    {
64 1
        if ($this->queryBuilder instanceof QueryBuilder) {
0 ignored issues
show
introduced by
$this->queryBuilder is always a sub-type of Doctrine\ORM\QueryBuilder.
Loading history...
65 1
            return $this->queryBuilder;
66
        }
67 1
        $repository = $this->entityManager->getRepository($this->entityToExtract);
68 1
        if (!$repository instanceof EntityRepository) {
69
            throw new \UnexpectedValueException("No repository found for class {$this->entityToExtract}");
70
        }
71 1
        $this->queryBuilder = $repository->createQueryBuilder('o');
72
73 1
        if ($this->queryBuilder === null) {
74
            throw new \BadMethodCallException('Invalid entityToExtract');
75
        }
76
77 1
        return $this->queryBuilder;
78
    }
79
80
    /**
81
     * @param QueryBuilder $queryBuilder
82
     */
83 1
    public function setQueryBuilder(QueryBuilder $queryBuilder)
84
    {
85 1
        $this->queryBuilder = $queryBuilder;
86 1
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91 1
    public function extract()
92
    {
93 1
        $entities = $this->getQueryBuilder()->getQuery()->getResult();
94
95 1
        $toReturn = [];
96
        //Replace relation references
97 1
        foreach ($entities as $key => $entity) {
98 1
            if (!$entity instanceof ImportableInterface) {
99
                throw new EntityTypeNotHandledException(get_class($entity));
100
            }
101 1
            $entityData = [];
102 1
            foreach ($this->propertiesToExtract as $property) {
103 1
                $value = $this->accessor->getValue($entity, $property);
104
105 1
                if ($this->isEntityRelation($value)) {
106 1
                    if (!$value instanceof ImportableInterface) {
107
                        throw new EntityTypeNotHandledException(get_class($value));
108
                    }
109 1
                    $entityData[$property] = '@' . $value->getImportId();
110 1
                } elseif ($value instanceof \Traversable) {
111 1
                    $entityData[$property] = [];
112 1
                    foreach ($value as $k => $v) {
113 1
                        if ($this->isEntityRelation($v)) {
114 1
                            if (!$v instanceof ImportableInterface) {
115
                                throw new EntityTypeNotHandledException(get_class($v));
116
                            }
117 1
                            $entityData[$property][$k] = '@' . $v->getImportId();
118
                        }
119
                    }
120
                } else {
121 1
                    $entityData[$property] = $value;
122
                }
123
            }
124 1
            $toReturn[$entity->getImportId()] = $entityData;
125
        }
126
127 1
        return $toReturn;
128
    }
129
130
    /**
131
     * Check if $propertyValue is an entity relation to process
132
     *
133
     * @param  mixed $propertyValue
134
     * @return bool
135
     */
136 1
    protected function isEntityRelation($propertyValue)
137
    {
138 1
        return (is_object($propertyValue) && !($propertyValue instanceof \DateTime) && !($propertyValue instanceof \Traversable));
139
    }
140
}
141