Completed
Push — master ( 471c75...7adc8e )
by
unknown
62:57 queued 43:39
created

SqlReader   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 38
dl 0
loc 118
rs 10
c 0
b 0
f 0
wmc 23

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getTablesDefinitionString() 0 20 5
A __construct() 0 4 1
C getStatementArray() 0 36 15
A getInsertStatementArray() 0 3 1
A getCreateTableStatementArray() 0 3 1
1
<?php
2
declare(strict_types = 1);
3
namespace TYPO3\CMS\Core\Database\Schema;
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
use Psr\EventDispatcher\EventDispatcherInterface;
19
use TYPO3\CMS\Core\Database\Event\AlterTableDefinitionStatementsEvent;
20
use TYPO3\CMS\Core\Package\PackageManager;
21
22
/**
23
 * Helper methods to handle raw SQL input and transform it into individual statements
24
 * for further processing.
25
 *
26
 * @internal
27
 */
28
class SqlReader
29
{
30
    /**
31
     * @var EventDispatcherInterface
32
     */
33
    protected $eventDispatcher;
34
35
    /**
36
     * @var PackageManager
37
     */
38
    protected $packageManager;
39
40
    /**
41
     * @param EventDispatcherInterface $eventDispatcher
42
     * @param PackageManager $packageManager
43
     * @throws \InvalidArgumentException
44
     */
45
    public function __construct(EventDispatcherInterface $eventDispatcher, PackageManager $packageManager)
46
    {
47
        $this->eventDispatcher = $eventDispatcher;
48
        $this->packageManager = $packageManager;
49
    }
50
51
    /**
52
     * Cycle through all loaded extensions and get full table definitions as concatenated string
53
     *
54
     * @param bool $withStatic TRUE if sql from ext_tables_static+adt.sql should be loaded, too.
55
     * @return string Concatenated SQL of loaded extensions ext_tables.sql
56
     */
57
    public function getTablesDefinitionString(bool $withStatic = false): string
58
    {
59
        $sqlString = [];
60
61
        // Find all ext_tables.sql of loaded extensions
62
        foreach ($this->packageManager->getActivePackages() as $package) {
63
            $packagePath = $package->getPackagePath();
64
            if (@file_exists($packagePath . 'ext_tables.sql')) {
65
                $sqlString[] = file_get_contents($packagePath . 'ext_tables.sql');
66
            }
67
            if ($withStatic && @file_exists($packagePath . 'ext_tables_static+adt.sql')) {
68
                $sqlString[] = file_get_contents($packagePath . 'ext_tables_static+adt.sql');
69
            }
70
        }
71
72
        /** @var AlterTableDefinitionStatementsEvent $event */
73
        $event = $this->eventDispatcher->dispatch(new AlterTableDefinitionStatementsEvent($sqlString));
74
        $sqlString = $event->getSqlData();
75
76
        return implode(LF . LF, $sqlString);
77
    }
78
79
    /**
80
     * Returns an array where every entry is a single SQL-statement.
81
     * Input must be formatted like an ordinary MySQL dump file. Every statements needs to be terminated by a ';'
82
     * and there may only be one statement (or partial statement) per line.
83
     *
84
     * @param string $dumpContent The SQL dump content.
85
     * @param string $queryRegex Regex to select which statements to return.
86
     * @return array Array of SQL statements
87
     */
88
    public function getStatementArray(string $dumpContent, string $queryRegex = null): array
89
    {
90
        $statementArray = [];
91
        $statementArrayPointer = 0;
92
        $isInMultilineComment = false;
93
        foreach (explode(LF, $dumpContent) as $lineContent) {
94
            $lineContent = trim($lineContent);
95
96
            // Skip empty lines and comments
97
            if ($lineContent === '' || $lineContent[0] === '#' || strpos($lineContent, '--') === 0 ||
98
                strpos($lineContent, '/*') === 0 || substr($lineContent, -2) === '*/' || $isInMultilineComment
99
            ) {
100
                // skip c style multiline comments
101
                if (strpos($lineContent, '/*') === 0 && substr($lineContent, -2) !== '*/') {
102
                    $isInMultilineComment = true;
103
                }
104
                if (substr($lineContent, -2) === '*/') {
105
                    $isInMultilineComment = false;
106
                }
107
                continue;
108
            }
109
110
            $statementArray[$statementArrayPointer] = ($statementArray[$statementArrayPointer] ?? '') . $lineContent;
111
112
            if (substr($lineContent, -1) === ';') {
113
                $statement = trim($statementArray[$statementArrayPointer]);
114
                if (!$statement || ($queryRegex && !preg_match('/' . $queryRegex . '/i', $statement))) {
115
                    unset($statementArray[$statementArrayPointer]);
116
                }
117
                $statementArrayPointer++;
118
            } else {
119
                $statementArray[$statementArrayPointer] .= ' ';
120
            }
121
        }
122
123
        return $statementArray;
124
    }
125
126
    /**
127
     * Extract only INSERT statements from SQL dump
128
     *
129
     * @param string $dumpContent
130
     * @return array
131
     */
132
    public function getInsertStatementArray(string $dumpContent): array
133
    {
134
        return $this->getStatementArray($dumpContent, '^INSERT');
135
    }
136
137
    /**
138
     * Extract only CREATE TABLE statements from SQL dump
139
     *
140
     * @param string $dumpContent
141
     * @return array
142
     */
143
    public function getCreateTableStatementArray(string $dumpContent): array
144
    {
145
        return $this->getStatementArray($dumpContent, '^CREATE TABLE');
146
    }
147
}
148