Passed
Push — develop ( 0d7fb1...8577d6 )
by Alejandro
09:01 queued 01:01
created

Version20201102113208::resolveOneApiKeyId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
dl 0
loc 13
rs 10
c 1
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkMigrations;
6
7
use Cake\Chronos\Chronos;
8
use Doctrine\DBAL\Driver\Result;
9
use Doctrine\DBAL\Schema\Schema;
10
use Doctrine\DBAL\Types\Types;
11
use Doctrine\Migrations\AbstractMigration;
12
13
final class Version20201102113208 extends AbstractMigration
14
{
15
    private const API_KEY_COLUMN = 'author_api_key_id';
16
17
    public function up(Schema $schema): void
18
    {
19
        $shortUrls = $schema->getTable('short_urls');
20
        $this->skipIf($shortUrls->hasColumn(self::API_KEY_COLUMN));
21
22
        $shortUrls->addColumn(self::API_KEY_COLUMN, Types::BIGINT, [
23
            'unsigned' => true,
24
            'notnull' => false,
25
        ]);
26
27
        $shortUrls->addForeignKeyConstraint('api_keys', [self::API_KEY_COLUMN], ['id'], [
28
            'onDelete' => 'SET NULL',
29
            'onUpdate' => 'RESTRICT',
30
        ], 'FK_' . self::API_KEY_COLUMN);
31
    }
32
33
    public function postUp(Schema $schema): void
34
    {
35
        // If there's only one API key and it's active, link all existing URLs with it
36
        $qb = $this->connection->createQueryBuilder();
37
        $qb->select('id')
38
           ->from('api_keys')
39
           ->where($qb->expr()->eq('enabled', ':enabled'))
40
           ->andWhere($qb->expr()->or(
41
               $qb->expr()->isNull('expiration_date'),
42
               $qb->expr()->gt('expiration_date', ':expiration'),
43
           ))
44
           ->setParameters([
45
               'enabled' => true,
46
               'expiration' => Chronos::now()->toDateTimeString(),
47
           ]);
48
49
        /** @var Result $result */
50
        $result = $qb->execute();
51
        $id = $this->resolveOneApiKeyId($result);
52
        if ($id === null) {
53
            return;
54
        }
55
56
        $qb = $this->connection->createQueryBuilder();
57
        $qb->update('short_urls')
58
           ->set(self::API_KEY_COLUMN, ':apiKeyId')
59
           ->setParameter('apiKeyId', $id)
60
           ->execute();
61
    }
62
63
    private function resolveOneApiKeyId(Result $result): ?string
64
    {
65
        $results = [];
66
        while ($row = $result->fetchAssociative()) {
67
            // As soon as we have to iterate more than once, then we cannot resolve a single API key
68
            if (! empty($results)) {
69
                return null;
70
            }
71
72
            $results[] = $row['id'] ?? null;
73
        }
74
75
        return $results[0] ?? null;
76
    }
77
78
    public function down(Schema $schema): void
79
    {
80
        $shortUrls = $schema->getTable('short_urls');
81
        $this->skipIf(! $shortUrls->hasColumn(self::API_KEY_COLUMN));
82
83
        $shortUrls->removeForeignKey('FK_' . self::API_KEY_COLUMN);
84
        $shortUrls->dropColumn(self::API_KEY_COLUMN);
85
    }
86
}
87