Completed
Pull Request — v2 (#7)
by Guillaume
02:08 queued 11s
created

AbstractEntityService   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 61
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 2
dl 0
loc 61
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B setPropertiesToEntity() 0 32 6
1
<?php
2
3
namespace ETNA\Doctrine\Entity;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Symfony\Component\Validator\Validator\ValidatorInterface;
7
8
abstract class AbstractEntityService
9
{
10
    /** @var EntityManagerInterface L'entity manager */
11
    protected $em;
12
13
    /** @var ValidatorInterface Le service pour la validation des data */
14
    protected $validator;
15
16
    protected function __construct(EntityManagerInterface $em, ValidatorInterface $validator)
17
    {
18
        $this->em        = $em;
19
        $this->validator = $validator;
20
    }
21
22
    /**
23
     * Filtre les champs directs (pas les jointures) de $datas, en fonction des groupes de validation
24
     * Et rempli l'entité avec les données filtrées, et éventuellement re-typées.
25
26
     * Permet de scénariser les modifications d'entités grace aux groupes de validation.
27
     *
28
     * @see https://symfony.com/doc/current/validation/groups.html
29
     *
30
     * @param array          $datas
31
     * @param array          $validation_groups
32
     * @param AbstractEntity $entity
33
     *
34
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
35
     */
36
    protected function setPropertiesToEntity(array $datas, array $validation_groups, AbstractEntity $entity)
37
    {
38
        $filtered_datas            = [];
39
        $validation_field_metadata = $this->validator->getMetadataFor($entity)->members;
40
        $doctrine_field_metadata   = $this->em->getClassMetadata(get_class($entity))->fieldMappings;
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
41
        $all_fields                = array_keys($doctrine_field_metadata);
42
43
        foreach ($datas as $field_name => $data_value) {
44
            $constraints             = array_shift($validation_field_metadata[$field_name]);
45
            $field_validation_groups = array_keys($constraints->constraintsByGroup);
46
            $is_field_concerned      = !empty(array_intersect($validation_groups, $field_validation_groups));
47
48
            switch (true) {
49
                // Si la data concerne un champ qui ne fait pas parti de l'entité, on passe
50
                case !in_array($field_name, $all_fields) || !$is_field_concerned:
51
                    break;
52
                // Si la data concerne un champ date ou assimilé, et que c'est une string, on sette un DateTime
53
                case 1 === preg_match(
54
                    "#^(date|datetime|time)[a-z_]*$#",
55
                    $doctrine_field_metadata[$field_name]["type"]
56
                ) && is_string($data_value):
57
                    $filtered_datas[$field_name] = new \DateTime($data_value);
58
                    break;
59
                // Sinon on sette tel quel
60
                default:
61
                    $filtered_datas[$field_name] = $data_value;
62
                    break;
63
            }
64
        }
65
66
        $entity->setProperties($filtered_datas);
67
    }
68
}
69