Aggregate   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 18
eloc 42
c 1
b 0
f 1
dl 0
loc 97
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getQuery() 0 22 2
A attachLazyAggregateToEntity() 0 4 1
A entityMatchesRow() 0 14 5
A attachAggregateToEntity() 0 12 4
A isEagerLoad() 0 4 2
A __construct() 0 5 1
A isLazyLoad() 0 4 2
A getName() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm\Relation;
5
6
use Sirius\Orm\Entity\EntityInterface;
7
use Sirius\Orm\Entity\LazyAggregate;
8
use Sirius\Orm\Entity\Tracker;
9
use Sirius\Orm\Mapper;
10
use Sirius\Orm\Query;
11
12
class Aggregate
13
{
14
    /**
15
     * @var string
16
     */
17
    protected $name;
18
    /**
19
     * @var Relation
20
     */
21
    protected $relation;
22
    /**
23
     * @var array
24
     */
25
    protected $options;
26
27
    public function __construct(string $name, Relation $relation, array $options)
28
    {
29
        $this->name = $name;
30
        $this->relation = $relation;
31
        $this->options = $options;
32
    }
33
34
    public function getQuery(Tracker $tracker)
35
    {
36
        $keys = $this->relation->getKeyPairs();
37
38
        /** @var Query $query */
39
        $query = $this->relation->getQuery($tracker);
40
        $query->resetColumns();
41
        $query->columns(...array_values($keys));
42
        $query->columns(sprintf(
43
            '%s as %s',
44
            $this->options[RelationConfig::AGG_FUNCTION],
45
            $this->name
46
        ));
47
48
        $callback = $this->options[RelationConfig::AGG_CALLBACK] ?? null;
49
        if (is_callable($callback)) {
50
            $query = $callback($query);
51
        }
52
53
        $query->groupBy(...array_values($keys));
54
55
        return $query;
56
    }
57
58
    public function attachLazyAggregateToEntity(EntityInterface $entity, Tracker $tracker)
59
    {
60
        $valueLoader = new LazyAggregate($entity, $tracker, $this);
61
        $this->relation->getNativeMapper()->setEntityAttribute($entity, $this->name, $valueLoader);
62
    }
63
64
    public function attachAggregateToEntity(EntityInterface $entity, array $results)
65
    {
66
        $found = null;
67
        foreach ($results as $row) {
68
            if ($this->entityMatchesRow($entity, $row)) {
69
                $found = $row;
70
                break;
71
            }
72
        }
73
        $this->relation
74
            ->getNativeMapper()
75
            ->setEntityAttribute($entity, $this->name, $found ? $found[$this->name] : null);
76
    }
77
78
    public function isLazyLoad()
79
    {
80
        return !isset($this->options[RelationConfig::LOAD_STRATEGY]) ||
81
               $this->options[RelationConfig::LOAD_STRATEGY] == RelationConfig::LOAD_LAZY;
82
    }
83
84
    public function isEagerLoad()
85
    {
86
        return isset($this->options[RelationConfig::LOAD_STRATEGY]) &&
87
               $this->options[RelationConfig::LOAD_STRATEGY] == RelationConfig::LOAD_EAGER;
88
    }
89
90
    public function getName()
91
    {
92
        return $this->name;
93
    }
94
95
    private function entityMatchesRow(EntityInterface $entity, $row)
96
    {
97
        $keys = $this->relation->getKeyPairs();
98
        foreach ($keys as $nativeCol => $foreignCol) {
99
            $entityValue  = $this->relation->getNativeMapper()->getEntityAttribute($entity, $nativeCol);
100
            $rowValue = $row[$foreignCol];
101
            // if both native and foreign key values are present (not unlinked entities) they must be the same
102
            // otherwise we assume that the entities can be linked together
103
            if ($entityValue && $rowValue && $entityValue != $rowValue) {
104
                return false;
105
            }
106
        }
107
108
        return true;
109
    }
110
}
111