Passed
Push — master ( ea0818...92b4a6 )
by Adrian
01:28
created

Tracker::getResultsForRelation()   B

Complexity

Conditions 9
Paths 10

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 27
rs 8.0555
cc 9
nc 10
nop 1
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 null;
66
        }
67
68
        if (isset($this->relationResults[$name])) {
69
            return $this->relationResults[$name];
70
        }
71
72
        /** @var Query $query */
73
        $query         = $this->relations[$name]->getQuery($this);
74
        $queryCallback = $this->relationCallback[$name] ?? null;
75
        if ($queryCallback && is_callable($queryCallback)) {
76
            $query = $queryCallback($query);
77
        }
78
        $queryNextLoad = $this->relationNextLoad[$name] ?? [];
79
        if ($queryNextLoad && !empty($queryNextLoad)) {
80
            foreach ($queryNextLoad as $next => $callback) {
81
                $query = $query->load([$next => $callback]);
82
            }
83
        }
84
85
        $results                      = $query->get();
86
        $this->relationResults[$name] = $results instanceof Collection ? $results->getValues() : $results;
87
88
        return $this->relationResults[$name];
89
    }
90
91
    public function getAggregateResults(Aggregate $aggregate)
92
    {
93
        $name = $aggregate->getName();
94
95
        if (isset($this->aggregateResults[$name])) {
96
            return $this->aggregateResults[$name];
97
        }
98
99
        /** @var Query $query */
100
        $query         = $aggregate->getQuery($this);
101
102
        $results                      = $query->fetchAll();
103
        $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...
104
105
        return $this->aggregateResults[$name];
106
    }
107
108
    public function pluck($columns)
109
    {
110
        $result = [];
111
        foreach ($this->rows as $row) {
112
            $value = $this->getColumnsFromRow($row, $columns);
113
            if ($value && !in_array($value, $result)) {
114
                $result[] = $value;
115
            }
116
        }
117
118
        /**
119
         * @todo check if array_unique() performs better
120
         */
121
        return $result;
122
    }
123
124
    protected function getColumnsFromRow($row, $columns)
125
    {
126
        if (is_array($columns) && count($columns) > 1) {
127
            $result = [];
128
            foreach ($columns as $column) {
129
                if ($row instanceof GenericEntity) {
130
                    $result[] = $row->get($column);
131
                } else {
132
                    $result[] = $row[$column] ?? null;
133
                }
134
            }
135
136
            return $result;
137
        }
138
139
        $column = is_array($columns) ? $columns[0] : $columns;
140
141
        return $row instanceof GenericEntity ? $row->get($column) : ($row[$column] ?? null);
142
    }
143
144
    /**
145
     * After the entities are created we use this method to swap the rows
146
     * with the actual entities to save some memory since rows can be quite big
147
     *
148
     * @param array $entities
149
     */
150
    public function replaceRows(array $entities)
151
    {
152
        $this->rows = $entities;
153
    }
154
}
155