Passed
Pull Request — master (#172)
by David
02:56
created

FindObjectsQueryFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
declare(strict_types=1);
3
4
namespace TheCodingMachine\TDBM\QueryFactory;
5
6
use Doctrine\Common\Cache\Cache;
7
use Doctrine\DBAL\Platforms\MySqlPlatform;
8
use Doctrine\DBAL\Schema\Schema;
9
use Mouf\Database\MagicQuery;
10
use TheCodingMachine\TDBM\InnerResultArray;
11
use TheCodingMachine\TDBM\OrderByAnalyzer;
12
use TheCodingMachine\TDBM\QueryFactory\SmartEagerLoad\PartialQueryFactory;
13
use TheCodingMachine\TDBM\QueryFactory\SmartEagerLoad\Query\PartialQuery;
14
use TheCodingMachine\TDBM\QueryFactory\SmartEagerLoad\Query\StaticPartialQuery;
15
use TheCodingMachine\TDBM\QueryFactory\SmartEagerLoad\StorageNode;
16
use TheCodingMachine\TDBM\TDBMService;
17
use function implode;
18
19
/**
20
 * This class is in charge of creating the MagicQuery SQL based on parameters passed to findObjects method.
21
 */
22
class FindObjectsQueryFactory extends AbstractQueryFactory implements PartialQueryFactory
23
{
24
    private $additionalTablesFetch;
25
    private $filterString;
26
    /**
27
     * @var Cache
28
     */
29
    private $cache;
30
31
    public function __construct(string $mainTable, array $additionalTablesFetch, $filterString, $orderBy, TDBMService $tdbmService, Schema $schema, OrderByAnalyzer $orderByAnalyzer, Cache $cache)
32
    {
33
        parent::__construct($tdbmService, $schema, $orderByAnalyzer, $mainTable, $orderBy);
34
        $this->additionalTablesFetch = $additionalTablesFetch;
35
        $this->filterString = $filterString;
36
        $this->cache = $cache;
37
    }
38
39
    protected function compute(): void
40
    {
41
        $key = 'FindObjectsQueryFactory_'.$this->mainTable.'__'.implode('_/_', $this->additionalTablesFetch).'__'.$this->filterString.'__'.$this->orderBy;
42
        if ($this->cache->contains($key)) {
43
            [
44
                $this->magicSql,
45
                $this->magicSqlCount,
46
                $this->columnDescList
47
            ] = $this->cache->fetch($key);
48
            return;
49
        }
50
51
        list($columnDescList, $columnsList, $orderString) = $this->getColumnsList($this->mainTable, $this->additionalTablesFetch, $this->orderBy, true);
52
53
        $sql = 'SELECT DISTINCT '.implode(', ', $columnsList).' FROM MAGICJOIN('.$this->mainTable.')';
54
55
        $pkColumnNames = $this->tdbmService->getPrimaryKeyColumns($this->mainTable);
56
        $mysqlPlatform = new MySqlPlatform();
57
        $pkColumnNames = array_map(function ($pkColumn) use ($mysqlPlatform) {
58
            return $mysqlPlatform->quoteIdentifier($this->mainTable).'.'.$mysqlPlatform->quoteIdentifier($pkColumn);
59
        }, $pkColumnNames);
60
61
        $subQuery = 'SELECT DISTINCT '.implode(', ', $pkColumnNames).' FROM MAGICJOIN('.$this->mainTable.')';
62
63
        if (count($pkColumnNames) === 1 || $this->tdbmService->getConnection()->getDatabasePlatform() instanceof MySqlPlatform) {
64
            $countSql = 'SELECT COUNT(DISTINCT '.implode(', ', $pkColumnNames).') FROM MAGICJOIN('.$this->mainTable.')';
65
        } else {
66
            $countSql = 'SELECT COUNT(*) FROM ('.$subQuery.') tmp';
67
        }
68
69
        if (!empty($this->filterString)) {
70
            $sql .= ' WHERE '.$this->filterString;
71
            $countSql .= ' WHERE '.$this->filterString;
72
            $subQuery .= ' WHERE '.$this->filterString;
73
        }
74
75
        if (!empty($orderString)) {
76
            $sql .= ' ORDER BY '.$orderString;
77
        }
78
79
        $this->magicSql = $sql;
80
        $this->magicSqlCount = $countSql;
81
        $this->magicSqlSubQuery = $subQuery;
82
        $this->columnDescList = $columnDescList;
83
84
        $this->cache->save($key, [
85
            $this->magicSql,
86
            $this->magicSqlCount,
87
            $this->columnDescList,
88
        ]);
89
    }
90
91
    /**
92
     * Generates a SQL query to be used as a sub-query.
93
     * @param array<string, mixed> $parameters
94
     */
95
    public function getPartialQuery(StorageNode $storageNode, MagicQuery $magicQuery, array $parameters): PartialQuery
96
    {
97
        $mysqlPlatform = new MySqlPlatform();
98
99
        // Special case: if the main table is part of an inheritance relationship, we need to get all related tables
100
        $relatedTables = $this->tdbmService->_getRelatedTablesByInheritance($this->mainTable);
101
        if (count($relatedTables) === 1) {
102
            $sql = 'FROM '.$mysqlPlatform->quoteIdentifier($this->mainTable);
103
        } else {
104
            // Let's use MagicQuery to build the query
105
            $sql = 'FROM MAGICJOIN('.$this->mainTable.')';
106
        }
107
108
        if (!empty($this->filterString)) {
109
            $sql .= ' WHERE '.$this->filterString;
110
        }
111
112
        return new StaticPartialQuery($sql, $parameters, $relatedTables, $storageNode, $magicQuery);
113
    }
114
}
115