Issues (188)

src/Select/RootLoader.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\ORM\Select;
6
7
use Cycle\Database\Query\SelectQuery;
8
use Cycle\Database\StatementInterface;
9
use Cycle\ORM\FactoryInterface;
10
use Cycle\ORM\Parser\AbstractNode;
11
use Cycle\ORM\Parser\RootNode;
12
use Cycle\ORM\Service\SourceProviderInterface;
13
use Cycle\ORM\SchemaInterface;
14
use Cycle\ORM\Select\Traits\ColumnsTrait;
15
use Cycle\ORM\Select\Traits\ScopeTrait;
16
17
/**
18
 * Primary ORM loader. Loader wraps at top of select query in order to modify it's conditions, joins
19
 * and etc based on nested loaders.
20
 *
21
 * Root load does not load constrain from ORM by default.
22
 *
23
 * @method RootNode createNode()
24
 *
25
 * @internal
26
 */
27
final class RootLoader extends AbstractLoader
28
{
29
    use ColumnsTrait;
30
    use ScopeTrait;
31
32
    protected array $options = [
33
        'load' => true,
34
        'scope' => true,
35
    ];
36
    private SelectQuery $query;
37
38
    /**
39
     * @param bool $loadRelations Define loading eager relations and JTI hierarchy.
40 6834
     */
41
    public function __construct(
42
        SchemaInterface $ormSchema,
43
        SourceProviderInterface $sourceProvider,
44
        FactoryInterface $factory,
45
        string $target,
46 6834
        bool $loadRelations = true,
47 6834
    ) {
48 6834
        parent::__construct($ormSchema, $sourceProvider, $factory, $target);
49
        $this->query = $this->source->getDatabase()->select()->from(
50 6834
            \sprintf('%s AS %s', $this->source->getTable(), $this->getAlias()),
51
        );
52 6834
        $this->columns = $this->normalizeColumns($this->define(SchemaInterface::COLUMNS));
53 1288
54
        if ($loadRelations) {
55
            foreach ($this->getEagerLoaders() as $relation) {
56
                $this->loadRelation($relation, [], false, true);
57
            }
58
        }
59
    }
60 3232
61
    public function getAlias(): string
62 3232
    {
63 3232
        return $this->target;
64
    }
65
66 6834
    /**
67
     * Primary column name list with table name like `table.column`.
68 6834
     *
69
     * @return string|string[]
70
     */
71
    public function getPK(): array|string
72
    {
73
        $pk = $this->define(SchemaInterface::PRIMARY_KEY);
74
        if (\is_array($pk)) {
75
            $result = [];
76 2152
            foreach ($pk as $key) {
77
                $result[] = $this->getAlias() . '.' . $this->fieldAlias($key);
78 2152
            }
79 2152
            return $result;
80 400
        }
81 400
82 400
        return $this->getAlias() . '.' . $this->fieldAlias($pk);
83
    }
84 400
85
    /**
86
     * Get list of primary fields.
87 1752
     *
88
     * @return list<non-empty-string>
0 ignored issues
show
The type Cycle\ORM\Select\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
89
     */
90
    public function getPrimaryFields(): array
91
    {
92
        return (array) $this->define(SchemaInterface::PRIMARY_KEY);
0 ignored issues
show
Bug Best Practice introduced by
The expression return (array)$this->def...Interface::PRIMARY_KEY) returns the type array which is incompatible with the documented return type Cycle\ORM\Select\list.
Loading history...
93 6834
    }
94
95 6834
    /**
96
     * Return base query associated with the loader.
97
     */
98
    public function getQuery(): SelectQuery
99
    {
100
        return $this->query;
101 6494
    }
102
103 6494
    /**
104
     * Compile query with all needed conditions, columns and etc.
105
     */
106 6382
    public function buildQuery(): SelectQuery
107
    {
108 6382
        return $this->configureQuery(clone $this->query);
109
    }
110 6334
111 6286
    public function loadData(AbstractNode $node, bool $includeRole = false): void
112
    {
113
        $statement = $this->buildQuery()->run();
114 6334
115
        foreach ($statement->fetchAll(StatementInterface::FETCH_NUM) as $row) {
116
            $node->parseRow(0, $row);
117 6334
        }
118 3154
119
        $statement->close();
120
121 6334
        // loading child datasets
122
        foreach ($this->load as $relation => $loader) {
123
            $loader->loadData($node->getNode($relation), $includeRole);
124 232
        }
125
126
        $this->loadHierarchy($node, $includeRole);
127 232
    }
128
129
    public function isLoaded(): bool
130 6494
    {
131
        // root loader is always loaded
132 6494
        return true;
133 6494
    }
134
135
    /**
136
     * Clone the underlying query.
137 6382
     */
138
    public function __clone()
139 6382
    {
140
        $this->query = clone $this->query;
141
        parent::__clone();
142
    }
143
144
    protected function configureQuery(SelectQuery $query): SelectQuery
145
    {
146
        return parent::configureQuery(
147
            $this->mountColumns($query, true, '', true),
148
        );
149
    }
150
151
    protected function initNode(): RootNode
152
    {
153
        return new RootNode($this->columnNames(), (array) $this->define(SchemaInterface::PRIMARY_KEY));
154
    }
155
}
156