Completed
Push — master ( 3af08b...23b599 )
by Daniel
03:02
created

FKchange::buildInputFormForFKscaling()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 14
rs 9.4286
cc 1
eloc 12
nc 1
nop 2
1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 Daniel Popiniuc
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
29
namespace danielgp\fk_scale_mysql;
30
31
/**
32
 * Description of FKchange
33
 *
34
 * @author Daniel Popiniuc <[email protected]>
35
 */
36
class FKchange
37
{
38
39
    use ConfigurationMySQL,
40
        ConfigurationForAction,
41
        \danielgp\common_lib\CommonCode,
42
        \danielgp\common_lib\MySQLiAdvancedOutput;
43
44
    private $applicationSpecificArray;
45
46
    public function __construct()
47
    {
48
        $rqst = new \Symfony\Component\HttpFoundation\Request;
49
        echo $this->setApplicationHeader()
50
        . $this->buildApplicationInterface(['SuperGlobals' => $rqst->createFromGlobals()])
51
        . $this->setFooterCommon();
52
    }
53
54
    private function buildApplicationInterface($inArray)
55
    {
56
        $mysqlConfig          = $this->configuredMySqlServer();
57
        $elToModify           = $this->targetElementsToModify(['SuperGlobals' => $inArray['SuperGlobals']]);
58
        $transmitedParameters = $this->countTransmitedParameters(['db', 'tbl', 'fld', 'dt']);
59
        $mConnection          = $this->connectToMySql($mysqlConfig);
60
        $sReturn              = [];
61
        $sReturn[]            = '<div class="tabber" id="tabberFKscaleMySQL">'
62
                . '<div class="tabbertab' . ($transmitedParameters ? '' : ' tabbertabdefault')
63
                . '" id="FKscaleMySQLparameters" title="Parameters for scaling">'
64
                . $this->buildInputFormForFKscaling($mysqlConfig, ['SuperGlobals' => $inArray['SuperGlobals']])
65
                . '</div><!-- end of Parameters tab -->';
66
        $sReturn[]            = $this->buildResultsTab($mConnection, $elToModify, $transmitedParameters);
67
        return implode('', $sReturn);
68
    }
69
70
    private function buildInputFormForFKscaling($mysqlConfig, $inArray)
71
    {
72
        $sReturn   = [];
73
        $sGb       = $inArray['SuperGlobals'];
74
        $sReturn[] = $this->buildInputs(['field' => 'db', 'label' => 'Database name to analyze'], $sGb);
75
        $sReturn[] = $this->buildInputs(['field' => 'tbl', 'label' => 'Table name to analyze'], $sGb);
76
        $sReturn[] = $this->buildInputs(['field' => 'fld', 'label' => 'Field name to analyze'], $sGb);
77
        $sReturn[] = $this->buildInputs(['field' => 'data', 'label' => 'Data name to analyze'], $sGb);
78
        $sReturn[] = '<input type="submit" value="Generate SQL queries for scaling" />';
79
        $sReturn[] = $this->displayMySqlConfiguration($mysqlConfig);
80
        return '<form method="get" action="' . filter_var($sGb->server->get('PHP_SELF'), FILTER_SANITIZE_URL) . '">'
81
                . implode('<br/>', $sReturn)
82
                . '</form>';
83
    }
84
85
    private function buildInputs($inArray, $sGb)
86
    {
87
        return '<label for="' . $inArray['field'] . 'Name">' . $inArray['label'] . ':</label>'
88
                . '<input type="text" id="' . $inArray['field'] . 'Name" name="' . $inArray['field']
89
                . '" placeholder="' . explode(' ', $inArray['label'])[0] . ' name" '
90
                . $this->returnInputsCleaned($inArray['field'], $sGb)
91
                . 'size="30" maxlength="64" class="labell" />';
92
    }
93
94
    private function buildResultsTab($mConnection, $elToModify, $transmitedParameters)
95
    {
96
        $sReturn             = [];
97
        $targetTableTextFlds = $this->getForeignKeys($elToModify);
98
        $sReturn[]           = '<div class="tabbertab' . ($transmitedParameters ? ' tabbertabdefault' : '')
99
                . '" id="FKscaleMySQLresults" title="Results">';
100
        if (is_array($targetTableTextFlds)) {
101
            $sReturn[]    = $this->createDropForeignKeysAndGetTargetColumnDefinition($targetTableTextFlds);
102
            $mainColArray = $this->packParameteresForMainChangeColumn($elToModify, $targetTableTextFlds);
103
            $sReturn[]    = $this->createChangeColumn($mainColArray, [
104
                'style'                => 'color:blue;font-weight:bold;',
105
                'includeOldColumnType' => true,
106
            ]);
107
            $sReturn[]    = $this->recreateFKs($elToModify, $targetTableTextFlds);
108
        } else {
109
            if (strlen($mConnection) === 0) {
110
                $sReturn[] = '<p style="color:red;">Check if provided parameters are correct '
111
                        . 'as the combination of Database. Table and Column name were not found as a Foreign Key!</p>';
112
            } else {
113
                $sReturn[] = '<p style="color:red;">Check your "configurationMySQL.php" file '
114
                        . 'for correct MySQL connection parameters '
115
                        . 'as the current ones were not able to be used to establish a connection!</p>';
116
            }
117
        }
118
        $sReturn[] = '</div><!-- end of FKscaleMySQLresults tab -->'
119
                . '</div><!-- tabberFKscaleMySQL -->';
120
        return implode('', $sReturn);
121
    }
122
123
    private function createChangeColumn($parameters, $aditionalFeatures = null)
124
    {
125
        return '<div style="'
126
                . (isset($aditionalFeatures['style']) ? $aditionalFeatures['style'] : 'color:blue;')
127
                . '">'
128
                . 'ALTER TABLE `' . $parameters['Database'] . '`.`' . $parameters['Table']
129
                . '` CHANGE `' . $parameters['Column'] . '` `' . $parameters['Column'] . '` '
130
                . $parameters['NewDataType'] . ' '
131
                . $this->setColumnDefinitionAditional($parameters['IsNullable'], $parameters['Default'])
132
                . (strlen($parameters['Extra']) > 0 ? ' AUTO_INCREMENT' : '')
133
                . (strlen($parameters['Comment']) > 0 ? ' COMMENT "' . $parameters['Comment'] . '"' : '')
134
                . ';'
135
                . (isset($aditionalFeatures['includeOldColumnType']) ? ' /* from '
136
                        . $parameters['OldDataType'] . ' */' : '')
137
                . '</div>';
138
    }
139
140
    private function createDropForeignKey($parameters)
141
    {
142
        return '<div style="color:red;">'
143
                . 'ALTER TABLE `' . $parameters['Database'] . '`.`' . $parameters['Table']
144
                . '` DROP FOREIGN KEY `' . $parameters['ForeignKeyName']
145
                . '`;'
146
                . '</div>';
147
    }
148
149
    private function createDropForeignKeysAndGetTargetColumnDefinition($targetTableTextFlds)
150
    {
151
        $sReturn = [];
152
        foreach ($targetTableTextFlds as $key => $value) {
153
            $sReturn[]                                    = $this->createDropForeignKey([
154
                'Database'       => $value['TABLE_SCHEMA'],
155
                'Table'          => $value['TABLE_NAME'],
156
                'ForeignKeyName' => $value['CONSTRAINT_NAME'],
157
            ]);
158
            $this->applicationSpecificArray['Cols'][$key] = $this->getMySQLlistColumns([
159
                'TABLE_SCHEMA' => $value['TABLE_SCHEMA'],
160
                'TABLE_NAME'   => $value['TABLE_NAME'],
161
                'COLUMN_NAME'  => $value['COLUMN_NAME'],
162
            ]);
163
        }
164
        return implode('', $sReturn);
165
    }
166
167
    private function createForeignKey($parameters)
168
    {
169
        return '<div style="color:green;">'
170
                . 'ALTER TABLE `' . $parameters['Database'] . '`.`' . $parameters['Table']
171
                . '` ADD CONSTRAINT `' . $parameters['ForeignKeyName'] . '` FOREIGN KEY (`'
172
                . $parameters['Column'] . '`) REFERENCES `' . $parameters['ReferencedDatabase'] . '`.`'
173
                . $parameters['ReferencedTable'] . '` (`' . $parameters['ReferencedColumn'] . '`) '
174
                . 'ON DELETE '
175
                . ($parameters['RuleDelete'] == 'NULL' ? 'SET NULL' : $parameters['RuleDelete']) . ' '
176
                . 'ON UPDATE '
177
                . ($parameters['RuleUpdate'] == 'NULL' ? 'SET NULL' : $parameters['RuleUpdate'])
178
                . ';'
179
                . '</div>';
180
    }
181
182
    private function displayMySqlConfiguration($mysqlConfig)
183
    {
184
        $styleForMySQLparams = 'color:green;font-weight:bold;font-style:italic;';
185
        return '<p>For security reasons the MySQL connection details are not available '
186
                . 'to be set/modified through the interface and must be set directly '
187
                . 'into the "configurationMySQL.php" file. Currently these settings are:<ul>'
188
                . '<li>Host name where MySQL server resides: <span style="' . $styleForMySQLparams . '">'
189
                . $mysqlConfig['host'] . '</span></li>'
190
                . '<li>MySQL port used: <span style="' . $styleForMySQLparams . '">'
191
                . $mysqlConfig['port'] . '</span></li>'
192
                . '<li>MySQL database to connect to: <span style="' . $styleForMySQLparams . '">'
193
                . $mysqlConfig['database'] . '</span></li>'
194
                . '<li>MySQL username used: <span style="' . $styleForMySQLparams . '">'
195
                . $mysqlConfig['username'] . '</span></li>'
196
                . '<li>MySQL password used: <span style="' . $styleForMySQLparams . '">'
197
                . 'cannot be disclosed due to security reasons</span></li>'
198
                . '</ul></p>';
199
    }
200
201
    private function getForeignKeys($elToModify)
202
    {
203
        $additionalFeatures = [
204
            'REFERENCED_TABLE_SCHEMA' => $elToModify['Database'],
205
            'REFERENCED_TABLE_NAME'   => $elToModify['Table'],
206
            'REFERENCED_COLUMN_NAME'  => $elToModify['Column'],
207
            'REFERENCED_TABLE_NAME'   => 'NOT NULL',
208
        ];
209
        $query              = $this->sQueryMySqlIndexes($additionalFeatures);
210
        return $this->setMySQLquery2Server($query, 'full_array_key_numbered')['result'];
211
    }
212
213
    private function packParameteresForMainChangeColumn($elToModify, $targetTableTextFlds)
214
    {
215
        $colToIdentify = [
216
            'TABLE_SCHEMA' => $elToModify['Database'],
217
            'TABLE_NAME'   => $elToModify['Table'],
218
            'COLUMN_NAME'  => $elToModify['Column'],
219
        ];
220
        $col           = $this->getMySQLlistColumns($colToIdentify);
221
        return [
222
            'Database'    => $targetTableTextFlds[0]['REFERENCED_TABLE_SCHEMA'],
223
            'Table'       => $targetTableTextFlds[0]['REFERENCED_TABLE_NAME'],
224
            'Column'      => $targetTableTextFlds[0]['REFERENCED_COLUMN_NAME'],
225
            'OldDataType' => strtoupper($col[0]['COLUMN_TYPE']) . ' '
226
            . $this->setColumnDefinitionAditional($col[0]['IS_NULLABLE'], $col[0]['COLUMN_DEFAULT'], $col[0]['EXTRA']),
227
            'NewDataType' => $elToModify['NewDataType'],
228
            'IsNullable'  => $col[0]['IS_NULLABLE'],
229
            'Default'     => $col[0]['COLUMN_DEFAULT'],
230
            'Extra'       => $col[0]['EXTRA'],
231
            'Comment'     => $col[0]['COLUMN_COMMENT'],
232
        ];
233
    }
234
235
    private function recreateFKs($elToModify, $targetTableTextFlds)
236
    {
237
        $sReturn = [];
238
        foreach ($targetTableTextFlds as $key => $value) {
239
            $sReturn[] = $this->createChangeColumn([
240
                'Database'    => $value['TABLE_SCHEMA'],
241
                'Table'       => $value['TABLE_NAME'],
242
                'Column'      => $value['COLUMN_NAME'],
243
                'NewDataType' => $elToModify['NewDataType'],
244
                'IsNullable'  => $this->applicationSpecificArray['Cols'][$key][0]['IS_NULLABLE'],
245
                'Default'     => $this->applicationSpecificArray['Cols'][$key][0]['COLUMN_DEFAULT'],
246
                'Extra'       => $this->applicationSpecificArray['Cols'][$key][0]['EXTRA'],
247
                'Comment'     => $this->applicationSpecificArray['Cols'][$key][0]['COLUMN_COMMENT'],
248
            ]);
249
            $sReturn[] = $this->createForeignKey([
250
                'Database'           => $value['TABLE_SCHEMA'],
251
                'Table'              => $value['TABLE_NAME'],
252
                'Column'             => $value['COLUMN_NAME'],
253
                'ForeignKeyName'     => $value['CONSTRAINT_NAME'],
254
                'ReferencedDatabase' => $value['REFERENCED_TABLE_SCHEMA'],
255
                'ReferencedTable'    => $value['REFERENCED_TABLE_NAME'],
256
                'ReferencedColumn'   => $value['REFERENCED_COLUMN_NAME'],
257
                'RuleDelete'         => $value['DELETE_RULE'],
258
                'RuleUpdate'         => $value['UPDATE_RULE'],
259
            ]);
260
        }
261
        return implode('', $sReturn);
262
    }
263
264
    private function returnInputsCleaned($inputFieldName, $sGb)
265
    {
266
        $sReturn = '';
267
        if (!is_null($sGb->get($inputFieldName))) {
268
            $sReturn = 'value="' . filter_var($sGb->get($inputFieldName), FILTER_SANITIZE_STRING) . '" ';
269
        }
270
        return $sReturn;
271
    }
272
273
    private function setApplicationHeader()
274
    {
275
        $pageTitle   = 'Foreign Keys Scale in MySQL';
276
        $headerArray = [
277
            'css'        => [
278
                'css/fk_scale_mysql.css',
279
            ],
280
            'javascript' => [
281
                'vendor/danielgp/common-lib/js/tabber/tabber-management.min.js',
282
                'vendor/danielgp/common-lib/js/tabber/tabber.min.js',
283
            ],
284
            'lang'       => 'en-US',
285
            'title'      => $pageTitle,
286
        ];
287
        return $this->setHeaderCommon($headerArray)
288
                . '<h1>' . $pageTitle . '</h1>';
289
    }
290
291
    private function setColumnDefinitionAditional($nullableYesNo, $defaultValue = '', $extra = '')
292
    {
293
        $columnDefAdtnl = '';
294
        switch ($nullableYesNo) {
295
            case 'NO':
296
                $columnDefAdtnl = 'NOT NULL DEFAULT "' . $defaultValue . '"';
297
                if (is_null($defaultValue)) {
298
                    $columnDefAdtnl = 'NOT NULL';
299
                }
300
                break;
301
            case 'YES':
302
                $columnDefAdtnl = 'DEFAULT "' . $defaultValue . '"';
303
                if ($defaultValue === null) {
304
                    $columnDefAdtnl = 'DEFAULT NULL';
305
                }
306
                break;
307
        }
308
        if ($extra == 'auto_increment') {
309
            $columnDefAdtnl .= ' AUTO_INCREMENT';
310
        }
311
        return $columnDefAdtnl;
312
    }
313
}
314