Tracker   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 31
eloc 58
c 1
b 0
f 0
dl 0
loc 157
rs 9.92

9 Methods

Rating   Name   Duplication   Size   Complexity  
A hasRelation() 0 3 1
A __construct() 0 3 1
A setRelation() 0 7 4
A getAggregateResults() 0 15 3
A getResultsForRelation() 0 15 3
B getColumnsFromRow() 0 18 7
B queryRelation() 0 24 7
A replaceRows() 0 3 1
A pluck() 0 11 4
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm\Entity;
5
6
use Sirius\Orm\Collection\Collection;
7
use Sirius\Orm\Mapper;
8
use Sirius\Orm\Query;
9
use Sirius\Orm\Relation\Aggregate;
10
use Sirius\Orm\Relation\Relation;
11
12
class Tracker
13
{
14
    protected $rows = [];
15
16
    /**
17
     * @var Mapper
18
     */
19
    protected $mapper;
20
21
    /**
22
     * @var array
23
     */
24
    protected $relations = [];
25
26
    /**
27
     * @var array
28
     */
29
    protected $relationCallback = [];
30
31
    /**
32
     * @var array
33
     */
34
    protected $relationNextLoad = [];
35
36
    /**
37
     * @var array
38
     */
39
    protected $relationResults = [];
40
41
    public function __construct(array $rows = [])
42
    {
43
        $this->rows   = $rows;
44
    }
45
46
    public function setRelation($name, Relation $relation, $callback, array $nextLoad = [], $overwrite = false)
47
    {
48
        if ($overwrite || ! isset($this->relations[$name])) {
49
            $this->relations[$name]        = $relation;
50
            $this->relationCallback[$name] = $callback;
51
            if (!empty($nextLoad)) {
52
                $this->relationNextLoad[$name] = $nextLoad;
53
            }
54
        }
55
    }
56
57
    public function hasRelation($name)
58
    {
59
        return isset($this->relations[$name]);
60
    }
61
62
    public function getResultsForRelation($name)
63
    {
64
        if (! isset($this->relations[$name])) {
65
            return [];
66
        }
67
68
        if (isset($this->relationResults[$name])) {
69
            return $this->relationResults[$name];
70
        }
71
72
        $results = $this->queryRelation($name);
73
74
        $this->relationResults[$name] = $results;
75
76
        return $this->relationResults[$name];
77
    }
78
79
    public function getAggregateResults(Aggregate $aggregate)
80
    {
81
        $name = $aggregate->getName();
82
83
        if (isset($this->aggregateResults[$name])) {
84
            return $this->aggregateResults[$name];
85
        }
86
87
        /** @var Query $query */
88
        $query         = $aggregate->getQuery($this);
89
90
        $results                      = $query->fetchAll();
91
        $this->aggregateResults[$name] = $results instanceof Collection ? $results->getValues() : $results;
0 ignored issues
show
Bug Best Practice introduced by
The property aggregateResults does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
introduced by
$results is never a sub-type of Sirius\Orm\Collection\Collection.
Loading history...
92
93
        return $this->aggregateResults[$name];
94
    }
95
96
    public function pluck($columns)
97
    {
98
        $result = [];
99
        foreach ($this->rows as $row) {
100
            $value = $this->getColumnsFromRow($row, $columns);
101
            if ($value && !in_array($value, $result)) {
102
                $result[] = $value;
103
            }
104
        }
105
106
        return $result;
107
    }
108
109
    protected function getColumnsFromRow($row, $columns)
110
    {
111
        if (is_array($columns) && count($columns) > 1) {
112
            $result = [];
113
            foreach ($columns as $column) {
114
                if ($row instanceof GenericEntity) {
115
                    $result[] = $row->{$column};
116
                } else {
117
                    $result[] = $row[$column] ?? null;
118
                }
119
            }
120
121
            return $result;
122
        }
123
124
        $column = is_array($columns) ? $columns[0] : $columns;
125
126
        return $row instanceof GenericEntity ? $row->{$column} : ($row[$column] ?? null);
127
    }
128
129
    /**
130
     * After the entities are created we use this method to swap the rows
131
     * with the actual entities to save some memory since rows can be quite big
132
     *
133
     * @param array $entities
134
     */
135
    public function replaceRows(array $entities)
136
    {
137
        $this->rows = $entities;
138
    }
139
140
    /**
141
     * @param $name
142
     *
143
     * @return array
144
     */
145
    protected function queryRelation($name)
146
    {
147
        /** @var Relation $relation */
148
        $relation = $this->relations[$name];
149
        /** @var Query $query */
150
        $query = $relation->getQuery($this);
151
152
        $queryCallback = $this->relationCallback[$name] ?? null;
153
        if ($queryCallback && is_callable($queryCallback)) {
154
            $query = $queryCallback($query);
155
        }
156
157
        $queryNextLoad = $this->relationNextLoad[$name] ?? [];
158
        if ($queryNextLoad && ! empty($queryNextLoad)) {
159
            foreach ($queryNextLoad as $next => $callback) {
160
                $query = $query->load([$next => $callback]);
161
            }
162
        }
163
164
        $results = $query->get();
165
        $results = $results instanceof Collection ? $results->getValues() : $results;
166
        $results = $relation->indexQueryResults($results);
167
168
        return $results;
169
    }
170
}
171