Issues (225)

MigrationVersions/20100101000200_MigrateV1ToV2.php (5 issues)

1
<?php
2
3
use Kaliop\eZMigrationBundle\API\MigrationInterface;
4
use Symfony\Component\DependencyInjection\ContainerInterface;
5
use Kaliop\eZMigrationBundle\API\Value\Migration;
6
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
7
use \eZ\Publish\Core\Persistence\Database\SelectQuery;
0 ignored issues
show
The type \eZ\Publish\Core\Persistence\Database\SelectQuery 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...
8
9
class MigrateV1ToV2 implements MigrationInterface
10
{
11
    private $container;
12
    private $dbHandler;
13
    private $activeBundles;
14
    private $legacyTableName;
15
    private $legacyMigrationsDir;
16
17
    // The API says we have to have a static method, but we like better non-static... :-P
18
    public static function execute(ContainerInterface $container)
19
    {
20
        $migration = new self($container);
21
        $migration->goForIt();
22
    }
23
24
    private function __construct(ContainerInterface $container)
25
    {
26
        $this->container = $container;
27
    }
28
29
    private function goForIt()
30
    {
31
        $this->legacyTableName = $this->container->getParameter('kaliop_bundle_migration.table_name');
32
        $this->legacyMigrationsDir = $this->container->get('ez_migration_bundle.helper.config.resolver')->getParameter('kaliop_bundle_migration.version_directory');
33
34
        $migrationStorageService = $this->container->get('ez_migration_bundle.storage_handler');
35
        $this->dbHandler = $this->container->get('ezpublish.connection');
36
37
        $this->activeBundles = array();
38
        foreach ($this->container->get('kernel')->getBundles() as $bundle)
39
        {
40
            $this->activeBundles[$bundle->getName()] = $bundle->getPath();
41
        }
42
43
        /** @var \Kaliop\eZMigrationBundle\Core\Helper\ConsoleIO $io */
44
        $io = $this->container->get('ez_migration_bundle.helper.console_io');
45
        // NB: in theory this could be null!
46
        $output = $io->getOutput();
47
48
        if (!$this->tableExist($this->legacyTableName))
49
        {
50
            $output->writeln("Nothing to update: v1 database table '{$this->legacyTableName}' not found");
51
            return;
52
        }
53
54
        $toMigrate = $this->loadLegacyMigrations();
55
        $output->writeln("<info>Found " . count($toMigrate) . ' migration versions in the v1 database table</info>');
56
57
        // we need to decide of a random time to stamp existing migrations. We use 'now - 1 minute'...
58
        $executionDate = time() - 60;
59
        foreach ($toMigrate as $legacyMigration) {
60
            $name = $legacyMigration['version'];
61
62
            $path = $this->getLegacyMigrationDefinition($legacyMigration['version'], $legacyMigration['bundle']);
63
            if ($path != false) {
64
                $name = basename($path);
65
                $content = file_get_contents($path);
66
                $md5 = md5($content);
67
            } else {
68
                $path = 'unknown';
69
                $content = '';
70
                $md5 = 'unknown';
71
            }
72
73
            // take care: what if the migration already exists in the v2 table ???
74
            $existingMigration = $migrationStorageService->loadMigration($name);
75
            if ($existingMigration != null) {
76
                $output->writeln("<info>Info for migration version: {$legacyMigration['bundle']} {$legacyMigration['version']} was already migrated, skipping it</info>");
77
                continue;
78
            }
79
80
            $migrationDefinition = new MigrationDefinition(
81
                $name, $path, $content, MigrationDefinition::STATUS_PARSED
82
            );
83
            $migrationStorageService->startMigration($migrationDefinition);
84
            $migration = new Migration(
85
                $name,
86
                $md5,
87
                $path,
88
                $executionDate,
89
                Migration::STATUS_DONE
90
            );
91
            $migrationStorageService->endMigration($migration);
92
93
            // we leave legacy info in the legacy table, in case someone wants to roll back in the future...
94
            //$this->deleteLegacyMigration($legacyMigration['version'], $legacyMigration['bundle']);
95
96
            $output->writeln("Updated info for migration version: {$legacyMigration['bundle']} {$legacyMigration['version']}");
97
        }
98
99
        $output->writeln("<info>All known legacy migration versions have been migrated to the v2 database table</info>");
100
    }
101
102
    private function tableExist($tableName)
103
    {
104
        /** @var \Doctrine\DBAL\Schema\AbstractSchemaManager $sm */
105
        $sm = $this->dbHandler->getConnection()->getSchemaManager();
106
        foreach ($sm->listTables() as $table) {
107
            if ($table->getName() == $tableName) {
108
                return true;
109
            }
110
        }
111
112
        return false;
113
    }
114
115
    private function loadLegacyMigrations()
116
    {
117
        /** @var \eZ\Publish\Core\Persistence\Database\SelectQuery $q */
118
        $q = $this->dbHandler->createSelectQuery();
119
        $q->select('version, bundle')
0 ignored issues
show
The call to eZ\Publish\Core\Persiste...e\SelectQuery::select() has too many arguments starting with 'version, bundle'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
        $q->/** @scrutinizer ignore-call */ 
120
            select('version, bundle')

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
120
            ->from($this->legacyTableName)
0 ignored issues
show
The call to eZ\Publish\Core\Persiste...ase\SelectQuery::from() has too many arguments starting with $this->legacyTableName. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
            ->/** @scrutinizer ignore-call */ from($this->legacyTableName)

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
121
            ->orderBy('version', SelectQuery::ASC);
122
        $stmt = $q->prepare();
123
        $stmt->execute();
124
        $results = $stmt->fetchAll();
125
126
        return $results;
127
    }
128
129
    private function deleteLegacyMigration($version, $bundle)
0 ignored issues
show
The method deleteLegacyMigration() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
130
    {
131
        $this->dbHandler->getConnection()->delete($this->legacyTableName, array('version' => $version, 'bundle' => $bundle));
132
    }
133
134
    /**
135
     * Attempts to find the migration definition file. If more than one matches, the 1st found is returned
136
     * @param string $version
137
     * @param string $bundle
138
     * @return string|false
139
     */
140
    private function getLegacyMigrationDefinition($version, $bundle)
141
    {
142
        if (!isset($this->activeBundles[$bundle])) {
143
            return false;
144
        }
145
146
        $versionsDir = $this->activeBundles[$bundle] . '/' . $this->legacyMigrationsDir;
147
        $versionDefinitions = glob($versionsDir . "/$version*");
148
149
        if (!is_array($versionDefinitions)) {
0 ignored issues
show
The condition is_array($versionDefinitions) is always true.
Loading history...
150
            return false;
151
        }
152
153
        foreach ($versionDefinitions as $key => $versionDefinition) {
154
            if (!in_array(pathinfo($versionDefinition, PATHINFO_EXTENSION), array('php', 'yml', 'sql'))) {
155
                unset($versionDefinitions[$key]);
156
            }
157
        }
158
159
        if (empty($versionDefinitions)) {
160
            return false;
161
        }
162
163
        return $versionDefinitions[0];
164
    }
165
}
166