2020-06-13 23:58:59 +02:00
< ? php
2022-11-29 21:21:26 +01:00
/*
* This file is part of Part - DB ( https :// github . com / Part - DB / Part - DB - symfony ) .
*
* Copyright ( C ) 2019 - 2022 Jan Böhmer ( https :// github . com / jbtronics )
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2020-06-13 23:58:59 +02:00
2020-07-04 23:38:18 +02:00
namespace App\Migration ;
2020-06-13 23:58:59 +02:00
2020-07-04 23:38:18 +02:00
use Doctrine\DBAL\Connection ;
2020-06-13 23:58:59 +02:00
use Doctrine\DBAL\DBALException ;
2022-03-04 18:59:19 +01:00
use Doctrine\DBAL\Driver\AbstractMySQLDriver ;
2022-03-04 18:51:58 +01:00
use Doctrine\DBAL\Driver\AbstractSQLiteDriver ;
2022-03-04 13:03:12 +01:00
use Doctrine\DBAL\Exception ;
2022-03-04 18:51:58 +01:00
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform ;
2022-07-17 23:45:17 +02:00
use Doctrine\DBAL\Platforms\MariaDBPlatform ;
use Doctrine\DBAL\Platforms\MySQLPlatform ;
use Doctrine\DBAL\Platforms\SqlitePlatform ;
2020-06-13 23:58:59 +02:00
use Doctrine\DBAL\Schema\Schema ;
use Doctrine\Migrations\AbstractMigration ;
2020-07-04 23:38:18 +02:00
use Psr\Log\LoggerInterface ;
2020-06-13 23:58:59 +02:00
abstract class AbstractMultiPlatformMigration extends AbstractMigration
{
2020-06-14 22:29:15 +02:00
public const ADMIN_PW_LENGTH = 10 ;
2022-09-18 22:59:31 +02:00
protected string $admin_pw = '' ;
2020-06-14 21:17:57 +02:00
2022-09-18 22:59:31 +02:00
protected LoggerInterface $logger ;
2020-07-04 23:38:18 +02:00
public function __construct ( Connection $connection , LoggerInterface $logger )
{
$this -> logger = $logger ;
AbstractMigration :: __construct ( $connection , $logger );
}
2020-06-13 23:58:59 +02:00
public function up ( Schema $schema ) : void
{
2022-03-04 18:51:58 +01:00
$db_type = $this -> getDatabaseType ();
2020-06-13 23:58:59 +02:00
switch ( $db_type ) {
case 'mysql' :
$this -> mySQLUp ( $schema );
break ;
case 'sqlite' :
$this -> sqLiteUp ( $schema );
break ;
default :
$this -> abortIf ( true , " Database type ' $db_type ' is not supported! " );
break ;
}
}
public function down ( Schema $schema ) : void
{
2022-03-04 18:51:58 +01:00
$db_type = $this -> getDatabaseType ();
2020-06-13 23:58:59 +02:00
switch ( $db_type ) {
case 'mysql' :
$this -> mySQLDown ( $schema );
break ;
case 'sqlite' :
$this -> sqLiteDown ( $schema );
break ;
default :
2022-03-04 18:51:58 +01:00
$this -> abortIf ( true , " Database type is not supported! " );
2020-06-13 23:58:59 +02:00
break ;
}
}
/**
* Gets the legacy Part - DB version number . Returns 0 , if target database is not an legacy Part - DB database .
*/
public function getOldDBVersion () : int
{
2022-03-04 18:51:58 +01:00
if ( 'mysql' !== $this -> getDatabaseType ()) {
2020-06-13 23:58:59 +02:00
//Old Part-DB version only supported MySQL therefore only
return 0 ;
}
try {
2022-03-04 13:03:12 +01:00
$version = $this -> connection -> fetchOne ( " SELECT keyValue AS version FROM `internal` WHERE `keyName` = 'dbVersion' " );
if ( is_bool ( $version )) {
return 0 ;
}
return ( int ) $version ;
} catch ( Exception $dBALException ) {
2020-06-13 23:58:59 +02:00
//when the table was not found, we can proceed, because we have an empty DB!
return 0 ;
}
}
2020-06-14 22:29:15 +02:00
/**
* Returns the hash of a new random password , created for the initial admin user , which can be written to DB .
* The plaintext version of the password will be outputed to user after this migration .
*/
2020-06-13 23:58:59 +02:00
public function getInitalAdminPW () : string
{
2020-06-14 22:29:15 +02:00
if ( empty ( $this -> admin_pw )) {
if ( ! empty ( $_ENV [ 'INITIAL_ADMIN_PW' ])) {
$this -> admin_pw = $_ENV [ 'INITIAL_ADMIN_PW' ];
} else {
$this -> admin_pw = substr ( md5 ( random_bytes ( 10 )), 0 , static :: ADMIN_PW_LENGTH );
}
}
//As we dont have access to container, just use the default PHP pw hash function
return password_hash ( $this -> admin_pw , PASSWORD_DEFAULT );
2020-06-13 23:58:59 +02:00
}
2020-06-14 21:17:57 +02:00
public function postUp ( Schema $schema ) : void
{
parent :: postUp ( $schema );
2020-06-14 22:29:15 +02:00
if ( ! empty ( $this -> admin_pw )) {
2020-07-04 23:38:18 +02:00
$this -> logger -> warning ( '' );
2020-08-21 21:36:22 +02:00
$this -> logger -> warning ( '<bg=yellow;fg=black>The initial password for the "admin" user is: ' . $this -> admin_pw . '</>' );
2020-07-04 23:38:18 +02:00
$this -> logger -> warning ( '' );
2020-06-14 22:29:15 +02:00
}
2020-06-14 21:17:57 +02:00
}
2023-04-08 23:27:10 +02:00
/**
* Checks if a foreign key on a table exists in the database .
* This method is only supported for MySQL / MariaDB databases yet !
* @ param string $table
* @ param string $fk_name
* @ return bool Returns true , if the foreign key exists
* @ throws Exception
*/
public function doesFKExists ( string $table , string $fk_name ) : bool
{
$db_type = $this -> getDatabaseType ();
if ( $db_type !== 'mysql' ) {
throw new \RuntimeException ( 'This method is only supported for MySQL/MariaDB databases!' );
}
$sql = " SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = ' $fk_name ' AND TABLE_NAME = ' $table ' AND CONSTRAINT_TYPE = 'FOREIGN KEY' " ;
2023-04-08 23:32:38 +02:00
$result = ( int ) $this -> connection -> fetchOne ( $sql );
2023-04-08 23:27:10 +02:00
return $result > 0 ;
}
2022-03-04 18:51:58 +01:00
/**
* Returns the database type of the used database .
* @ return string | null Returns 'mysql' for MySQL / MariaDB and 'sqlite' for SQLite . Returns null if unknown type
*/
public function getDatabaseType () : ? string
{
2022-07-17 23:45:17 +02:00
if ( $this -> connection -> getDatabasePlatform () instanceof AbstractMySQLPlatform ) {
2022-03-04 18:51:58 +01:00
return 'mysql' ;
}
2022-07-17 23:45:17 +02:00
if ( $this -> connection -> getDatabasePlatform () instanceof SqlitePlatform ) {
2022-03-04 18:51:58 +01:00
return 'sqlite' ;
}
return null ;
}
2020-06-13 23:58:59 +02:00
abstract public function mySQLUp ( Schema $schema ) : void ;
abstract public function mySQLDown ( Schema $schema ) : void ;
abstract public function sqLiteUp ( Schema $schema ) : void ;
abstract public function sqLiteDown ( Schema $schema ) : void ;
2020-08-21 21:36:22 +02:00
}