Lines 85.00% 34 / 40
Methods 75.00% 3 / 4
Classes 0.00% 0 / 1
Covered by tests of size
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 alignTablePrefix 100.00% 2 / 2 100.00% 1 / 1 1
 alignTablePrefixByPattern 100.00% 8 / 8 100.00% 1 / 1 2
 buildInsertQueries 79.31% 23 / 29 0.00% 0 / 1 12.07
31readonly class DatabaseHelper
32{
33    /**
34     * Constructor.
35     */
36    public function __construct(
37        private Configuration $configuration,
38    ) {
39    }
40
41    /**
42     * Align the prefix of the table name used in the PMF backup file,
43     * from the (old) value of the system upon which the backup was performed
44     * to the (new) prefix of the system upon which the backup will be restored
45     * This alignment will be performed upon all the SQL query "patterns"
46     * provided within the PMF backup file.
47     */
48    public static function alignTablePrefix(string $query, string $oldValue, string $newValue): string
49    {
50        // Align DELETE FROM <prefix.tablename>
51        $query = self::alignTablePrefixByPattern($query, 'DELETE FROM', $oldValue, $newValue);
52        // Align INSERT INTO <prefix.tablename>
53        return self::alignTablePrefixByPattern($query, 'INSERT INTO', $oldValue, $newValue);
54    }
55
56    /**
57     * Align the prefix of the table name used in the PMF backup file,
58     * from the (old) value of the system upon which the backup was performed
59     * to the (new) prefix of the system upon which the backup will be restored.
60     * This alignment will be performed ONLY upon those given SQL queries starting
61     * with the given pattern.
62     */
63    private static function alignTablePrefixByPattern(
64        string $query,
65        string $startPattern,
66        string $oldValue,
67        string $newValue,
68    ): string {
69        $return = $query;
70        $matches = [];
71
72        Strings::preg_match_all('/^' . $startPattern . "\s+(\w+)(\s+|$)/i", $query, $matches);
73
74        if (($matches[1][0] ?? null) !== null) {
75            $oldTableFullName = (string) $matches[1][0];
76            $newTableFullName = $newValue . Strings::substr($oldTableFullName, Strings::strlen($oldValue));
77            $return = str_replace($oldTableFullName, $newTableFullName, $query);
78        }
79
80        return $return;
81    }
82
83    /**
84     * This function builds the queries for the backup.
85     *
86     * @return string[]
87     */
88    public function buildInsertQueries(string $query, string $table): array
89    {
90        $result = $this->configuration->getDb()->query($query);
91        if (!$result) {
92            return [];
93        }
94
95        $queries = [];
96
97        $queries[] = "\r\n-- Table: " . $table;
98
99        while (true) {
100            $row = $this->configuration->getDb()->fetchArray($result);
101            if ($row === false || $row === null || $row === []) {
102                break;
103            }
104
105            $columns = [];
106            $values = [];
107            foreach ($row as $key => $val) {
108                if (is_int($key)) {
109                    continue; // Fix for SQLite3
110                }
111
112                $columns[] = $key;
113                if ('rights' !== $key && is_numeric($val)) {
114                    $values[] = $val;
115                    continue;
116                }
117
118                if (is_null($val)) {
119                    $values[] = 'NULL';
120                    continue;
121                }
122
123                $values[] = sprintf("'%s'", $this->configuration->getDb()->escape((string) $val));
124            }
125
126            $queries[] = sprintf(
127                'INSERT INTO %s (%s) VALUES (%s);',
128                $table,
129                implode(',', $columns),
130                implode(',', $values),
131            );
132        }
133
134        return $queries;
135    }
136}