Completed
Pull Request — 3.4 (#46)
by David
12:52 queued 01:27
created

TDBMSchemaAnalyzer   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 19
c 3
b 0
f 1
lcom 1
cbo 8
dl 0
loc 126
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getCachePrefix() 0 6 2
A getSchema() 0 12 3
B getPivotTableLinkedToTable() 0 22 5
C getIncomingForeignKeys() 0 25 8
1
<?php
2
namespace Mouf\Database\TDBM;
3
use Doctrine\Common\Cache\Cache;
4
use Doctrine\Common\Cache\VoidCache;
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Schema\Column;
7
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
8
use Doctrine\DBAL\Schema\Schema;
9
use Doctrine\DBAL\Schema\Table;
10
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer;
11
use Mouf\Database\TDBM\Utils\AbstractBeanPropertyDescriptor;
12
13
/**
14
 * This class is used to analyze the schema and return valuable information / hints.
15
 */
16
class TDBMSchemaAnalyzer
17
{
18
19
    private $connection;
20
21
    /**
22
     * @var Schema
23
     */
24
    private $schema;
25
26
    /**
27
     * @var string
28
     */
29
    private $cachePrefix;
30
31
    /**
32
     * @var Cache
33
     */
34
    private $cache;
35
36
    /**
37
     * @var SchemaAnalyzer
38
     */
39
    private $schemaAnalyzer;
40
41
    /**
42
     * @param Connection $connection The DBAL DB connection to use
43
     * @param Cache $cache A cache service to be used
44
     * @param SchemaAnalyzer $schemaAnalyzer The schema analyzer that will be used to find shortest paths...
45
     * 										 Will be automatically created if not passed.
46
     */
47
    public function __construct(Connection $connection, Cache $cache, SchemaAnalyzer $schemaAnalyzer) {
48
        $this->connection = $connection;
49
        $this->cache = $cache;
50
        $this->schemaAnalyzer = $schemaAnalyzer;
51
    }
52
53
    /**
54
     * Returns a unique ID for the current connection. Useful for namespacing cache entries in the current connection.
55
     * @return string
56
     */
57
    public function getCachePrefix() {
58
        if ($this->cachePrefix === null) {
59
            $this->cachePrefix = hash('md4', $this->connection->getHost()."-".$this->connection->getPort()."-".$this->connection->getDatabase()."-".$this->connection->getDriver()->getName());
60
        }
61
        return $this->cachePrefix;
62
    }
63
64
    /**
65
     * Returns the (cached) schema.
66
     *
67
     * @return Schema
68
     */
69
    public function getSchema() {
70
        if ($this->schema === null) {
71
            $cacheKey = $this->getCachePrefix().'_schema';
72
            if ($this->cache->contains($cacheKey)) {
73
                $this->schema = $this->cache->fetch($cacheKey);
74
            } else {
75
                $this->schema = $this->connection->getSchemaManager()->createSchema();
76
                $this->cache->save($cacheKey, $this->schema);
77
            }
78
        }
79
        return $this->schema;
80
    }
81
82
    /**
83
     * Returns the list of pivot tables linked to table $tableName
84
     * @param string $tableName
85
     * @return array|string[]
86
     */
87
    public function getPivotTableLinkedToTable($tableName) {
88
        $cacheKey = $this->getCachePrefix().'_pivottables_link';
89
        if ($this->cache->contains($cacheKey)) {
90
            return $this->cache->fetch($cacheKey);
91
        }
92
93
        $pivotTables = [];
94
95
        $junctionTables = $this->schemaAnalyzer->detectJunctionTables();
96
        foreach ($junctionTables as $table) {
97
            $fks = $table->getForeignKeys();
98
            foreach ($fks as $fk) {
99
                if ($fk->getForeignTableName() == $tableName) {
100
                    $pivotTables[] = $table->getName();
101
                    break;
102
                }
103
            }
104
        }
105
106
        $this->cache->save($cacheKey, $pivotTables);
107
        return $pivotTables;
108
    }
109
110
    /**
111
     * Returns the list of foreign keys pointing to the table represented by this bean, excluding foreign keys
112
     * from junction tables and from inheritance.
113
     *
114
     * @return ForeignKeyConstraint[]
115
     */
116
    public function getIncomingForeignKeys($tableName) {
117
118
        $junctionTables = $this->schemaAnalyzer->detectJunctionTables();
119
        $junctionTableNames = array_map(function(Table $table) { return $table->getName(); }, $junctionTables);
120
        $childrenRelationships = $this->schemaAnalyzer->getChildrenRelationships($tableName);
121
122
        $fks = [];
123
        foreach ($this->getSchema()->getTables() as $table) {
124
            foreach ($table->getForeignKeys() as $fk) {
125
                if ($fk->getForeignTableName() === $tableName) {
126
                    if (in_array($fk->getLocalTableName(), $junctionTableNames)) {
127
                        continue;
128
                    }
129
                    foreach ($childrenRelationships as $childFk) {
130
                        if ($fk->getLocalTableName() === $childFk->getLocalTableName() && $fk->getLocalColumns() === $childFk->getLocalColumns()) {
131
                            continue 2;
132
                        }
133
                    }
134
                    $fks[] = $fk;
135
                }
136
            }
137
        }
138
139
        return $fks;
140
    }
141
}
142