Issues (3627)

CoreBundle/Doctrine/AbstractMauticMigration.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2014 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CoreBundle\Doctrine;
13
14
use Doctrine\DBAL\DBALException;
15
use Doctrine\DBAL\Schema\Schema;
16
use Doctrine\Migrations\AbstractMigration;
17
use Doctrine\Migrations\Exception\AbortMigration;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
22
abstract class AbstractMauticMigration extends AbstractMigration implements ContainerAwareInterface
23
{
24
    /**
25
     * @var ContainerInterface
26
     */
27
    protected $container;
28
29
    /**
30
     * Supported platforms.
31
     *
32
     * @var array
33
     */
34
    protected $supported = ['mysql'];
35
36
    /**
37
     * Database prefix.
38
     *
39
     * @var string
40
     */
41
    protected $prefix;
42
43
    /**
44
     * Database platform.
45
     *
46
     * @var string
47
     */
48
    protected $platform;
49
50
    /**
51
     * @var EntityManagerInterface
52
     */
53
    protected $entityManager;
54
55
    /**
56
     * @throws DBALException
57
     * @throws AbortMigration
58
     */
59
    public function up(Schema $schema): void
60
    {
61
        $platform = $this->connection->getDatabasePlatform()->getName();
62
63
        // Abort the migration if the platform is unsupported
64
        $this->abortIf(!in_array($platform, $this->supported), 'The database platform is unsupported for migrations');
65
66
        $function = $this->platform.'Up';
67
68
        if (method_exists($this, $function)) {
69
            $this->$function($schema);
70
        }
71
    }
72
73
    /**
74
     * @throws AbortMigration
75
     */
76
    public function down(Schema $schema): void
77
    {
78
        // Not supported
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     *
84
     * @throws DBALException
85
     */
86
    public function setContainer(ContainerInterface $container = null)
87
    {
88
        $this->container     = $container;
89
        $this->prefix        = $container->getParameter('mautic.db_table_prefix');
90
        $this->platform      = $this->connection->getDatabasePlatform()->getName();
91
        $this->entityManager = $this->container->get('doctrine')->getManager();
92
    }
93
94
    /**
95
     * Finds/creates the local name for constraints and indexes.
96
     *
97
     * @param $table
98
     * @param $type
99
     * @param $suffix
100
     *
101
     * @return string
102
     */
103
    protected function findPropertyName($table, $type, $suffix)
104
    {
105
        static $schemaManager;
106
        static $tables = [];
107
108
        if (empty($schemaManager)) {
109
            $schemaManager = $this->connection->getSchemaManager();
110
        }
111
112
        // Prepend prefix
113
        $table = $this->prefix.$table;
114
115
        if (!array_key_exists($table, $tables)) {
116
            $tables[$table] = [];
117
        }
118
119
        $type   = strtolower($type);
120
        $suffix = strtolower(substr($suffix, -4));
121
122
        switch ($type) {
123
            case 'fk':
124
                if (!array_key_exists('fk', $tables[$table])) {
125
                    $keys = $schemaManager->listTableForeignKeys($table);
126
                    /** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint $k */
127
                    foreach ($keys as $k) {
128
                        $name                       = strtolower($k->getName());
129
                        $key                        = substr($name, -4);
130
                        $tables[$table]['fk'][$key] = $name;
131
                    }
132
                }
133
134
                $localName = $tables[$table]['fk'][$suffix];
135
136
                break;
137
            case 'idx':
138
            case 'uniq':
139
                if (!array_key_exists('idx', $tables[$table])) {
140
                    $tables[$table]['idx'] = [
141
                        'idx'  => [],
142
                        'uniq' => [],
143
                    ];
144
145
                    $indexes = $schemaManager->listTableIndexes($table);
146
147
                    /** @var \Doctrine\DBAL\Schema\Index $i */
148
                    foreach ($indexes as $i) {
149
                        $name   = strtolower($i->getName());
150
                        $isIdx  = stripos($name, 'idx');
151
                        $isUniq = stripos($name, 'uniq');
152
153
                        if (false !== $isIdx || false !== $isUniq) {
154
                            $key     = substr($name, -4);
155
                            $keyType = (false !== $isIdx) ? 'idx' : 'uniq';
156
157
                            $tables[$table]['idx'][$keyType][$key] = $name;
158
                        }
159
                    }
160
                }
161
162
                $localName = $tables[$table]['idx'][$type][$suffix];
163
164
                break;
165
        }
166
167
        return strtoupper($localName);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $localName does not seem to be defined for all execution paths leading up to this point.
Loading history...
168
    }
169
170
    /**
171
     * Generate the  name for the property.
172
     *
173
     * @param $table
174
     * @param $type
175
     *
176
     * @return string
177
     */
178
    protected function generatePropertyName($table, $type, array $columnNames)
179
    {
180
        $columnNames = array_merge([$this->prefix.$table], $columnNames);
181
        $hash        = implode(
182
            '',
183
            array_map(
184
                function ($column) {
185
                    return dechex(crc32($column));
186
                },
187
                $columnNames
188
            )
189
        );
190
191
        return substr(strtoupper($type.'_'.$hash), 0, 63);
192
    }
193
194
    /**
195
     * Generate index and foreign constraint.
196
     *
197
     * @param $table
198
     *
199
     * @return array [idx, fk]
200
     */
201
    protected function generateKeys($table, array $columnNames)
202
    {
203
        return [
204
            $this->generatePropertyName($table, 'idx', $columnNames),
205
            $this->generatePropertyName($table, 'fk', $columnNames),
206
        ];
207
    }
208
209
    /**
210
     * Use this when you're doing a migration that
211
     * purposely does not have any SQL statements,
212
     * such as when moving data using the query builder.
213
     */
214
    protected function suppressNoSQLStatementError()
215
    {
216
        $this->addSql('SELECT "This migration did not generate select statements." AS purpose');
217
    }
218
}
219