Completed
Push — master ( a959b5...b73961 )
by Alejandro
28s queued 12s
created

CreateDatabaseCommand::getLockConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Shlinkio\Shlink\CLI\Command\Db;
6
7
use Doctrine\DBAL\Connection;
8
use Shlinkio\Shlink\CLI\Util\ExitCodes;
9
use Symfony\Component\Console\Helper\ProcessHelper;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Console\Style\SymfonyStyle;
13
use Symfony\Component\Lock\Factory as Locker;
14
use Symfony\Component\Process\PhpExecutableFinder;
15
16
use function Functional\contains;
17
18
class CreateDatabaseCommand extends AbstractDatabaseCommand
19
{
20
    public const NAME = 'db:create';
21
    public const DOCTRINE_SCRIPT = 'vendor/doctrine/orm/bin/doctrine.php';
22
    public const DOCTRINE_CREATE_SCHEMA_COMMAND = 'orm:schema-tool:create';
23
24
    /** @var Connection */
25
    private $regularConn;
26
    /** @var Connection */
27
    private $noDbNameConn;
28
29 4
    public function __construct(
30
        Locker $locker,
31
        ProcessHelper $processHelper,
32
        PhpExecutableFinder $phpFinder,
33
        Connection $conn,
34
        Connection $noDbNameConn
35
    ) {
36 4
        parent::__construct($locker, $processHelper, $phpFinder);
37 4
        $this->regularConn = $conn;
38 4
        $this->noDbNameConn = $noDbNameConn;
39
    }
40
41 4
    protected function configure(): void
42
    {
43
        $this
44 4
            ->setName(self::NAME)
45 4
            ->setDescription(
46 4
                'Creates the database needed for shlink to work. It will do nothing if the database already exists'
47
            );
48
    }
49
50 4
    protected function lockedExecute(InputInterface $input, OutputInterface $output): int
51
    {
52 4
        $io = new SymfonyStyle($input, $output);
53
54 4
        $this->checkDbExists();
55
56 4
        if ($this->schemaExists()) {
57 3
            $io->success('Database already exists. Run "db:migrate" command to make sure it is up to date.');
58 3
            return ExitCodes::EXIT_SUCCESS;
59
        }
60
61
        // Create database
62 1
        $io->writeln('<fg=blue>Creating database tables...</>');
63 1
        $this->runPhpCommand($output, [self::DOCTRINE_SCRIPT, self::DOCTRINE_CREATE_SCHEMA_COMMAND]);
64 1
        $io->success('Database properly created!');
65
66 1
        return ExitCodes::EXIT_SUCCESS;
67
    }
68
69 4
    private function checkDbExists(): void
70
    {
71 4
        if ($this->regularConn->getDatabasePlatform()->getName() === 'sqlite') {
72 1
            return;
73
        }
74
75
        // In order to create the new database, we have to use a connection where the dbname was not set.
76
        // Otherwise, it will fail to connect and will not be able to create the new database
77 3
        $schemaManager = $this->noDbNameConn->getSchemaManager();
78 3
        $databases = $schemaManager->listDatabases();
79 3
        $shlinkDatabase = $this->regularConn->getDatabase();
80
81 3
        if (! contains($databases, $shlinkDatabase)) {
82 1
            $schemaManager->createDatabase($shlinkDatabase);
83
        }
84
    }
85
86 4
    private function schemaExists(): bool
87
    {
88
        // If at least one of the shlink tables exist, we will consider the database exists somehow.
89
        // Any inconsistency should be taken care by the migrations
90 4
        $schemaManager = $this->regularConn->getSchemaManager();
91 4
        return ! empty($schemaManager->listTableNames());
92
    }
93
}
94