Completed
Push — master ( 38da89...7b8325 )
by Daniel
04:47
created

MySQLiAdvancedOutput::getForeignKeysToArray()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
c 9
b 0
f 0
dl 0
loc 16
rs 8.8571
cc 5
eloc 11
nc 2
nop 3
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\common_lib;
30
31
/**
32
 * usefull functions to get quick results
33
 *
34
 * @author Daniel Popiniuc
35
 */
36
trait MySQLiAdvancedOutput
37
{
38
39
    use MySQLiByDanielGPstructures;
40
41
    protected $advCache = null;
42
43
    /**
44
     * Establish Database and Table intended to work with
45
     * (in case the DB is ommited get the default one)
46
     *
47
     * @param string $tblSrc
48
     */
49
    private function establishDatabaseAndTable($tblSrc)
50
    {
51
        if (strpos($tblSrc, '.') === false) {
52
            if (!array_key_exists('workingDatabase', $this->advCache)) {
53
                $this->advCache['workingDatabase'] = $this->getMySqlCurrentDatabase();
54
            }
55
            return [$this->advCache['workingDatabase'], $tblSrc];
56
        }
57
        return explode('.', str_replace('`', '', $tblSrc));
58
    }
59
60
    /**
61
     * Returns the name of a field for displaying
62
     *
63
     * @param array $details
64
     * @return string
65
     */
66
    protected function getFieldNameForDisplay($details)
67
    {
68
        $tableUniqueId = $details['TABLE_SCHEMA'] . '.' . $details['TABLE_NAME'];
69
        if ($details['COLUMN_COMMENT'] != '') {
70
            return $details['COLUMN_COMMENT'];
71
        } elseif (isset($this->advCache['tableStructureLocales'][$tableUniqueId][$details['COLUMN_NAME']])) {
72
            return $this->advCache['tableStructureLocales'][$tableUniqueId][$details['COLUMN_NAME']];
73
        }
74
        return $details['COLUMN_NAME'];
75
    }
76
77
    /**
78
     * Returns a Enum or Set field to use in form
79
     *
80
     * @param string $tblSrc
81
     * @param string $fldType
82
     * @param array $val
83
     * @param array $iar
84
     * @return string
85
     */
86
    private function getFieldOutputEnumSet($tblSrc, $fldType, $val, $iar = [])
87
    {
88
        $adnlThings = $this->establishDefaultEnumSet($fldType);
89
        if (array_key_exists('readonly', $val)) {
90
            return $this->getFieldOutputEnumSetReadOnly($val, $adnlThings);
91
        }
92
        $inAdtnl = $adnlThings['additional'];
93
        if ($iar !== []) {
94
            $inAdtnl = array_merge($inAdtnl, $iar);
95
        }
96
        $vlSlct    = explode(',', $this->getFieldValue($val));
97
        $slctOptns = $this->getSetOrEnum2Array($tblSrc, $val['COLUMN_NAME']);
98
        return $this->setArrayToSelect($slctOptns, $vlSlct, $val['COLUMN_NAME'] . $adnlThings['suffix'], $inAdtnl);
99
    }
100
101
    /**
102
     * Returns a Numeric field 2 use in a form
103
     *
104
     * @param string $tblSrc
105
     * @param array $value
106
     * @param array $iar
107
     * @return string
108
     */
109
    private function getFieldOutputNumeric($tblSrc, $value, $iar = [])
110
    {
111
        if ($value['EXTRA'] == 'auto_increment') {
112
            return $this->getFieldOutputNumericAI($value, $iar);
113
        }
114
        $fkArray = $this->getForeignKeysToArray($this->advCache['workingDatabase'], $tblSrc, $value['COLUMN_NAME']);
115
        if (is_null($fkArray)) {
116
            $fldNos = $this->setFieldNumbers($value);
117
            return $this->getFieldOutputTT($value, min(50, $fldNos['l']), $iar);
118
        }
119
        return $this->getFieldOutputNumericNonFK($fkArray, $value, $iar);
120
    }
121
122
    /**
123
     * Handles creation of Auto Increment numeric field type output
124
     *
125
     * @param array $value
126
     * @param array $iar
127
     * @return string
128
     */
129
    private function getFieldOutputNumericAI($value, $iar = [])
130
    {
131
        if ($this->getFieldValue($value) == '') {
132
            $spF = ['id' => $value['COLUMN_NAME'], 'style' => 'font-style:italic;'];
133
            return $this->setStringIntoTag('auto-numar', 'span', $spF);
134
        }
135
        $inAdtnl = [
136
            'type'  => 'hidden',
137
            'name'  => $value['COLUMN_NAME'],
138
            'id'    => $value['COLUMN_NAME'],
139
            'value' => $this->getFieldValue($value),
140
        ];
141
        if ($iar !== []) {
142
            $inAdtnl = array_merge($inAdtnl, $iar);
143
        }
144
        return '<b>' . $this->getFieldValue($value) . '</b>' . $this->setStringIntoShortTag('input', $inAdtnl);
145
    }
146
147
    /**
148
     * Builds field output type for numeric types if not FK
149
     *
150
     * @param array $fkArray
151
     * @param array $value
152
     * @param array $iar
153
     * @return string
154
     */
155
    private function getFieldOutputNumericNonFK($fkArray, $value, $iar = [])
156
    {
157
        $query         = $this->sQueryGenericSelectKeyValue([
158
            $fkArray[$value['COLUMN_NAME']][1],
159
            $fkArray[$value['COLUMN_NAME']][2],
160
            $fkArray[$value['COLUMN_NAME']][0],
161
        ]);
162
        $selectOptions = $this->setMySQLquery2Server($query, 'array_key_value')['result'];
163
        $selectValue   = $this->getFieldValue($value);
164
        $inAdtnl       = ['size' => 1];
165
        if ($value['IS_NULLABLE'] == 'YES') {
166
            $inAdtnl = array_merge($inAdtnl, ['include_null']);
167
        }
168
        if ($iar !== []) {
169
            $inAdtnl = array_merge($inAdtnl, $iar);
170
        }
171
        return $this->setArrayToSelect($selectOptions, $selectValue, $value['COLUMN_NAME'], $inAdtnl);
172
    }
173
174
    /**
175
     * Returns a Char field 2 use in a form
176
     *
177
     * @param string $tbl
178
     * @param string $fieldType
179
     * @param array $value
180
     * @param array $iar
181
     * @return string
182
     */
183
    private function getFieldOutputText($tbl, $fieldType, $value, $iar = [])
184
    {
185
        if (!in_array($fieldType, ['char', 'tinytext', 'varchar'])) {
186
            return '';
187
        }
188
        $foreignKeysArray = $this->getFieldOutputTextPrerequisites($tbl, $value);
189
        if (!is_null($foreignKeysArray)) {
190
            return $this->getFieldOutputTextFK($foreignKeysArray, $value, $iar);
191
        }
192
        return $this->getFieldOutputTextNonFK($value, $iar);
193
    }
194
195
    /**
196
     * Returns a Text field 2 use in a form
197
     *
198
     * @param string $fieldType
199
     * @param array $value
200
     * @param array $iar
201
     * @return string
202
     */
203
    protected function getFieldOutputTextLarge($fieldType, $value, $iar = [])
204
    {
205
        if (!in_array($fieldType, ['blob', 'text'])) {
206
            return '';
207
        }
208
        $inAdtnl = [
209
            'name' => $value['COLUMN_NAME'],
210
            'id'   => $value['COLUMN_NAME'],
211
            'rows' => 4,
212
            'cols' => 55,
213
        ];
214
        if ($iar !== []) {
215
            $inAdtnl = array_merge($inAdtnl, $iar);
216
        }
217
        return $this->setStringIntoTag($this->getFieldValue($value), 'textarea', $inAdtnl);
218
    }
219
220
    /**
221
     * Prepares the text output fields
222
     *
223
     * @param string $tbl
224
     * @param array $value
225
     * @return null|array
226
     */
227
    private function getFieldOutputTextPrerequisites($tbl, $value)
228
    {
229
        $foreignKeysArray = null;
230
        if (($tbl != 'user_rights') && ($value['COLUMN_NAME'] != 'eid')) {
231
            $database = $this->advCache['workingDatabase'];
232
            if (strpos($tbl, '`.`')) {
233
                $database = substr($tbl, 0, strpos($tbl, '`.`'));
234
            }
235
            $foreignKeysArray = $this->getForeignKeysToArray($database, $tbl, $value['COLUMN_NAME']);
236
        }
237
        return $foreignKeysArray;
238
    }
239
240
    /**
241
     * Returns a Timestamp field 2 use in a form
242
     *
243
     * @param array $dtl
244
     * @param array $iar
245
     * @return string
246
     */
247
    private function getFieldOutputTimestamp($dtl, $iar = [])
248
    {
249
        if (($dtl['COLUMN_DEFAULT'] == 'CURRENT_TIMESTAMP') || ($dtl['EXTRA'] == 'on update CURRENT_TIMESTAMP')) {
250
            return $this->getTimestamping($dtl)['input'];
251
        }
252
        $input = $this->getFieldOutputTT($dtl, 19, $iar);
253
        if (!array_key_exists('readonly', $iar)) {
254
            $input .= $this->setCalendarControlWithTime($dtl['COLUMN_NAME']);
255
        }
256
        return $input;
257
    }
258
259
    /**
260
     * Returns a Year field 2 use in a form
261
     *
262
     * @param array $details
263
     * @param array $iar
264
     * @return string
265
     */
266
    private function getFieldOutputYear($tblName, $details, $iar)
267
    {
268
        $listOfValues = [];
269
        for ($cntr = 1901; $cntr <= 2155; $cntr++) {
270
            $listOfValues[$cntr] = $cntr;
271
        }
272
        if ($iar == []) {
273
            $slDflt = $this->getFieldValue($details);
274
            return $this->setArrayToSelect($listOfValues, $slDflt, $details['COLUMN_NAME'], ['size' => 1]);
275
        }
276
        return $this->getFieldOutputText($tblName, 'varchar', $details, $iar);
277
    }
278
279
    /**
280
     * Returns an array with fields referenced by a Foreign key
281
     *
282
     * @param string $database
283
     * @param string $tblName
284
     * @param string|array $oCol Only column(s) considered
285
     * @return array
286
     */
287
    private function getForeignKeysToArray($database, $tblName, $oCol = '')
288
    {
289
        $this->setTableForeignKeyCache($database, $this->fixTableSource($tblName));
290
        $aRt = null;
291
        $cnm = ['COLUMN_NAME', 'full_array_key_numbered', 'REFERENCED_TABLE_SCHEMA'];
292
        if (isset($this->advCache['tableFKs'][$database][$tblName])) {
293
            foreach ($this->advCache['tableFKs'][$database][$tblName] as $val) {
294
                if ($val[$cnm[0]] == $oCol) {
295
                    $tFd        = $this->setMySQLquery2Server($this->getForeignKeysQuery($val), $cmn[1])['result'];
0 ignored issues
show
Bug introduced by
The variable $cmn does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
296
                    $tgtFld     = '`' . ($tFd[0][$cnm[0]] == $val[$cnm[0]] ? $tFd[1][$cnm[0]] : $tFd[0][$cnm[0]]) . '`';
297
                    $aRt[$oCol] = [$this->glueDbTb($val[$cnm[2]], $val[$cnm[2]]), $val[$cnm[2]], $tgtFld];
298
                }
299
            }
300
        }
301
        return $aRt;
302
    }
303
304
    /**
305
     * Returns an array with possible values of a SET or ENUM column
306
     *
307
     * @param string $refTbl
308
     * @param string $refCol
309
     * @return array
310
     */
311
    protected function getSetOrEnum2Array($refTbl, $refCol)
312
    {
313
        $dat = $this->establishDatabaseAndTable($refTbl);
314
        foreach ($this->advCache['tableStructureCache'][$dat[0]][$dat[1]] as $vle) {
315
            if ($vle['COLUMN_NAME'] == $refCol) {
316
                $kVl = explode('\',\'', substr($vle['COLUMN_TYPE'], strlen($vle['DATA_TYPE']) + 2, -2));
317
                $fVl = array_combine($kVl, $kVl);
318
                if ($vle['IS_NULLABLE'] === 'YES') {
319
                    $fVl['NULL'] = '';
320
                }
321
            }
322
        }
323
        ksort($fVl);
324
        return $fVl;
325
    }
326
327
    /**
328
     * Returns a timestamp field value
329
     *
330
     * @param array $dtl
331
     * @return array
332
     */
333
    private function getTimestamping($dtl)
334
    {
335
        $fieldValue = $this->getFieldValue($dtl);
336
        $inM        = $this->setStringIntoTag($fieldValue, 'span');
337
        if (in_array($fieldValue, ['', 'CURRENT_TIMESTAMP', 'NULL'])) {
338
            $mCN = [
339
                'InsertDateTime'        => 'data/timpul ad. informatiei',
340
                'ModificationDateTime'  => 'data/timpul modificarii inf.',
341
                'modification_datetime' => 'data/timpul modificarii inf.',
342
            ];
343
            if (array_key_exists($dtl['COLUMN_NAME'], $mCN)) {
344
                $inM = $this->setStringIntoTag($mCN[$dtl['COLUMN_NAME']], 'span', ['style' => 'font-style:italic;']);
345
            }
346
        }
347
        $lbl = '<span class="fake_label">' . $this->getFieldNameForDisplay($dtl) . '</span>';
348
        return ['label' => $lbl, 'input' => $inM];
349
    }
350
351
    protected function setNeededFieldKnown($tblName, $dtls, $features)
352
    {
353
        $iar      = $this->handleFeatures($dtls['COLUMN_NAME'], $features);
354
        $sReturn  = '';
355
        $numTypes = ['bigint', 'int', 'mediumint', 'smallint', 'tinyint', 'float', 'double', 'decimal', 'numeric'];
356
        if (in_array($dtls['DATA_TYPE'], $numTypes)) {
357
            $sReturn = $this->getFieldOutputNumeric($tblName, $dtls, $iar);
358
        } elseif (in_array($dtls['DATA_TYPE'], ['char', 'tinytext', 'varchar', 'enum', 'set', 'text', 'blob'])) {
359
            $sReturn = $this->setNeededFieldTextRelated($tblName, $dtls, $iar);
360
        } elseif (in_array($dtls['DATA_TYPE'], ['date', 'datetime', 'time', 'timestamp', 'year'])) {
361
            $sReturn = $this->setNeededFieldSingleType($tblName, $dtls, $iar);
362
        }
363
        return $this->getFieldCompletionType($dtls) . $sReturn;
364
    }
365
366
    private function setNeededFieldSingleType($tblName, $dtls, $iar)
367
    {
368
        if ($dtls['DATA_TYPE'] == 'date') {
369
            return $this->getFieldOutputDate($dtls);
370
        } elseif ($dtls['DATA_TYPE'] == 'time') {
371
            return $this->getFieldOutputTime($dtls, $iar);
372
        } elseif (in_array($dtls['DATA_TYPE'], ['datetime', 'timestamp'])) {
373
            return $this->getFieldOutputTimestamp($dtls, $iar);
374
        }
375
        return $this->getFieldOutputYear($tblName, $dtls, $iar);
376
    }
377
378
    private function setNeededFieldTextRelated($tblName, $dtls, $iar)
379
    {
380
        if (in_array($dtls['DATA_TYPE'], ['char', 'tinytext', 'varchar'])) {
381
            return $this->getFieldOutputText($tblName, $dtls['DATA_TYPE'], $dtls, $iar);
382
        } elseif (in_array($dtls['DATA_TYPE'], ['text', 'blob'])) {
383
            return $this->getFieldOutputTextLarge($dtls['DATA_TYPE'], $dtls, $iar);
384
        }
385
        return $this->getFieldOutputEnumSet($tblName, $dtls['DATA_TYPE'], $dtls, $iar);
386
    }
387
388
    /**
389
     * create a Cache for given table to use it in many places
390
     *
391
     * @param string $tblSrc
392
     */
393
    protected function setTableCache($tblSrc)
394
    {
395
        $dat = $this->establishDatabaseAndTable($tblSrc);
396
        if (!isset($this->advCache['tableStructureCache'][$dat[0]][$dat[1]])) {
397
            $this->advCache['workingDatabase']                       = $dat[0];
398
            $this->advCache['tableStructureCache'][$dat[0]][$dat[1]] = $this->getMySQLlistColumns([
399
                'TABLE_SCHEMA' => $dat[0],
400
                'TABLE_NAME'   => $dat[1],
401
            ]);
402
            $this->setTableForeignKeyCache($dat[0], $dat[1]);
403
        }
404
    }
405
406
    private function setTableForeignKeyCache($dbName, $tblName)
407
    {
408
        $frgnKs = $this->getMySQLlistIndexes([
409
            'TABLE_SCHEMA'          => $dbName,
410
            'TABLE_NAME'            => $tblName,
411
            'REFERENCED_TABLE_NAME' => 'NOT NULL',
412
        ]);
413
        if (!is_null($frgnKs)) {
414
            $this->advCache['tableFKs'][$dbName][$tblName] = $frgnKs;
415
            $this->advCache['FKcol'][$dbName][$tblName]    = array_column($frgnKs, 'COLUMN_NAME', 'CONSTRAINT_NAME');
416
        }
417
    }
418
}
419