AbstractMultiPlatformMigration::getOldDBVersion()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 5
nop 0
dl 0
loc 16
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4
 *
5
 *  Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 *  This program is free software: you can redistribute it and/or modify
8
 *  it under the terms of the GNU Affero General Public License as published
9
 *  by the Free Software Foundation, either version 3 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU Affero General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU Affero General Public License
18
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace App\Migration;
22
23
use Doctrine\DBAL\Connection;
24
use Doctrine\DBAL\DBALException;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\DBALException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
26
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
27
use Doctrine\DBAL\Exception;
28
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
29
use Doctrine\DBAL\Platforms\MariaDBPlatform;
30
use Doctrine\DBAL\Platforms\MySQLPlatform;
31
use Doctrine\DBAL\Platforms\SqlitePlatform;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Platforms\SqlitePlatform was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use Doctrine\DBAL\Schema\Schema;
33
use Doctrine\Migrations\AbstractMigration;
34
use Psr\Log\LoggerInterface;
35
36
abstract class AbstractMultiPlatformMigration extends AbstractMigration
37
{
38
    public const ADMIN_PW_LENGTH = 10;
39
40
    protected bool $permissions_updated = false;
41
    protected string $admin_pw = '';
42
43
    protected LoggerInterface $logger;
44
45
    public function __construct(Connection $connection, LoggerInterface $logger)
46
    {
47
        $this->logger = $logger;
48
        AbstractMigration::__construct($connection, $logger);
49
    }
50
51
    public function up(Schema $schema): void
52
    {
53
        $db_type = $this->getDatabaseType();
54
55
        switch ($db_type) {
56
            case 'mysql':
57
                $this->mySQLUp($schema);
58
                break;
59
            case 'sqlite':
60
                $this->sqLiteUp($schema);
61
                break;
62
            default:
63
                $this->abortIf(true, "Database type '$db_type' is not supported!");
64
                break;
65
        }
66
    }
67
68
    public function down(Schema $schema): void
69
    {
70
        $db_type = $this->getDatabaseType();
71
72
        switch ($db_type) {
73
            case 'mysql':
74
                $this->mySQLDown($schema);
75
                break;
76
            case 'sqlite':
77
                $this->sqLiteDown($schema);
78
                break;
79
            default:
80
                $this->abortIf(true, "Database type is not supported!");
81
                break;
82
        }
83
    }
84
85
    /**
86
     * Gets the legacy Part-DB version number. Returns 0, if target database is not an legacy Part-DB database.
87
     */
88
    public function getOldDBVersion(): int
89
    {
90
        if ('mysql' !== $this->getDatabaseType()) {
91
            //Old Part-DB version only supported MySQL therefore only
92
            return 0;
93
        }
94
95
        try {
96
            $version = $this->connection->fetchOne("SELECT keyValue AS version FROM `internal` WHERE `keyName` = 'dbVersion'");
97
            if (is_bool($version)) {
98
                return 0;
99
            }
100
            return (int) $version;
101
        } catch (Exception $dBALException) {
102
            //when the table was not found, we can proceed, because we have an empty DB!
103
            return 0;
104
        }
105
    }
106
107
    /**
108
     * Returns the hash of a new random password, created for the initial admin user, which can be written to DB.
109
     * The plaintext version of the password will be outputed to user after this migration.
110
     */
111
    public function getInitalAdminPW(): string
112
    {
113
        if (empty($this->admin_pw)) {
114
            if (!empty($_ENV['INITIAL_ADMIN_PW'])) {
115
                $this->admin_pw = $_ENV['INITIAL_ADMIN_PW'];
116
            } else {
117
                $this->admin_pw = substr(md5(random_bytes(10)), 0, static::ADMIN_PW_LENGTH);
118
            }
119
        }
120
121
        //As we dont have access to container, just use the default PHP pw hash function
122
        return password_hash($this->admin_pw, PASSWORD_DEFAULT);
0 ignored issues
show
Bug Best Practice introduced by
The expression return password_hash($th...ation\PASSWORD_DEFAULT) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
123
    }
124
125
    public function printPermissionUpdateMessage(): void
126
    {
127
        $this->permissions_updated = true;
128
    }
129
130
    public function postUp(Schema $schema): void
131
    {
132
        parent::postUp($schema);
133
        if($this->permissions_updated) {
134
            $this->logger->warning('<question>[!!!] Permissions were updated! Please check if they fit your expectations!</question>');
135
        }
136
137
        if (!empty($this->admin_pw)) {
138
            $this->logger->warning('');
139
            $this->logger->warning('<bg=yellow;fg=black>The initial password for the "admin" user is: '.$this->admin_pw.'</>');
140
            $this->logger->warning('');
141
        }
142
    }
143
144
    /**
145
     * Returns the database type of the used database.
146
     * @return string|null Returns 'mysql' for MySQL/MariaDB and 'sqlite' for SQLite. Returns null if unknown type
147
     */
148
    public function getDatabaseType(): ?string
149
    {
150
        if ($this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
151
            return 'mysql';
152
        }
153
154
        if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
155
            return 'sqlite';
156
        }
157
158
        return null;
159
    }
160
161
    abstract public function mySQLUp(Schema $schema): void;
162
163
    abstract public function mySQLDown(Schema $schema): void;
164
165
    abstract public function sqLiteUp(Schema $schema): void;
166
167
    abstract public function sqLiteDown(Schema $schema): void;
168
}
169