Completed
Branch master (5737c6)
by Rémi
02:51
created

SingleTableInheritanceScope::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
<?php
2
3
namespace Analogue\ORM\System;
4
5
use Analogue\ORM\EntityMap;
6
7
class SingleTableInheritanceScope implements ScopeInterface
8
{
9
    /**
10
     * Discriminator column name.
11
     *
12
     * @var string
13
     */
14
    protected $column;
15
16
    /**
17
     * Discriminator column allowed types.
18
     *
19
     * @var array
20
     */
21
    protected $types = [];
22
23
    public function __construct(EntityMap $entityMap)
24
    {
25
        // Putting the heavy logic in here, so we won't have
26
        // to go through it each time we reach for a query
27
        // builder.
28
29
        $this->column = $entityMap->getDiscriminatorColumn();
30
31
        // First we need to retrieve the base class & it's normalized
32
        // type string
33
        $class = $entityMap->getClass();
34
        $this->types[] = $this->getTypeStringForEntity($class, $entityMap);
35
36
        // Then, we parse all registered entities for any potential
37
        // child class.
38
        $classes = Manager::getInstance()->getRegisteredEntities();
39
40
        foreach ($classes as $otherClass => $entityMap) {
41
            if (is_subclass_of($otherClass, $class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
42
                $this->types[] = $this->getTypeStringForEntity($otherClass, $entityMap);
43
            }
44
        }
45
    }
46
47
    /**
48
     * Get the normalized value to use for query on discriminator column.
49
     *
50
     * @param string    $class
51
     * @param EntityMap $entityMap
52
     *
53
     * @return string
54
     */
55
    protected function getTypeStringForEntity($class, EntityMap $entityMap)
0 ignored issues
show
Unused Code introduced by
The parameter $class is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
56
    {
57
        $class = $entityMap->getClass();
58
59
        $type = array_keys(
60
            $entityMap->getDiscriminatorColumnMap(),
61
            $class
62
        );
63
64
        if (count($type) == 0) {
65
            return $class;
66
        }
67
68
        return $type[0];
69
    }
70
71
    /**
72
     * Apply the scope to a given Analogue query builder.
73
     *
74
     * @param \Analogue\ORM\System\Query $query
75
     *
76
     * @return void
77
     */
78
    public function apply(Query $query)
79
    {
80
        $query->whereIn($this->column, $this->types);
0 ignored issues
show
Documentation Bug introduced by
The method whereIn does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
81
    }
82
83
    /**
84
     * Remove the scope from the given Analogue query builder.
85
     *
86
     * @param mixed $query
87
     *
88
     * @return void
89
     */
90
    public function remove(Query $query)
91
    {
92
        $query = $query->getQuery();
93
94 View Code Duplication
        foreach ((array) $query->wheres as $key => $where) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
            if ($this->isSingleTableConstraint($where, $this->column)) {
96
                unset($query->wheres[$key]);
97
98
                $query->wheres = array_values($query->wheres);
99
            }
100
        }
101
    }
102
103
    /**
104
     * Determine if the given where clause is a single table inheritance constraint.
105
     *
106
     * @param array  $where
107
     * @param string $column
108
     *
109
     * @return bool
110
     */
111
    protected function isSingleTableConstraint(array $where, $column)
112
    {
113
        return $where['column'] == $column;
114
    }
115
}
116