MigrationCommand.php 8.15 KB
Newer Older
1 2
<?php

3
namespace App\Command;
4

5
use App\Document\GoGoLogUpdate;
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
6 7
use App\Document\MigrationState;
use App\Services\AsyncService;
8 9
use Doctrine\ODM\MongoDB\DocumentManager;
use Psr\Log\LoggerInterface;
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
10 11 12
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
13 14
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

15 16
/**
 * Command to update database when schema need migration
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
17
 * Also provide some update message in the admin dashboard.
18 19 20
 */
class MigrationCommand extends GoGoAbstractCommand
{
Sebastian Castro's avatar
Sebastian Castro committed
21 22 23
    // -----------------------------------------------------------------
    // DO NOT REMOVE A SINGLE ELEMENT OF THOSE ARRAYS, ONLY ADD NEW ONES
    // -----------------------------------------------------------------
Alan Poulain's avatar
Alan Poulain committed
24
    public static $migrations = [
25
      // v2.4.6
Sebastian Castro's avatar
Sebastian Castro committed
26 27 28 29 30 31
      'db.TileLayer.updateMany({name:"cartodb"}, {$set: {attribution:"&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a> &copy; <a href=\"http://cartodb.com/attributions\">CartoDB</a>"}})',
      'db.TileLayer.updateMany({name:"hydda"}, {$set: {attribution:"Tiles courtesy of <a href=\"http://openstreetmap.se/\" target=\"_blank\">OpenStreetMap Sweden</a> &mdash; Map data &copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"}})',
      'db.TileLayer.updateMany({name:"wikimedia"}, {$set: {attribution:"<a href=\"https://wikimediafoundation.org/wiki/Maps_Terms_of_Use\">Wikimedia</a> | Map data © <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap contributors</a>"}})',
      'db.TileLayer.updateMany({name:"lyrk"}, {$set: {attribution:"&copy Lyrk | Map data &copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"}})',
      'db.TileLayer.updateMany({name:"osmfr"}, {$set: {attribution:"&copy; Openstreetmap France | &copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"}})',
      'db.TileLayer.updateMany({name:"stamenWaterColor"}, {$set: {attribution:"Map tiles by <a href=\"http://stamen.com\">Stamen Design</a>, <a href=\"http://creativecommons.org/licenses/by/3.0\">CC BY 3.0</a> &mdash; Map data &copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"}})',
Sebastian Castro's avatar
Sebastian Castro committed
32 33
    ];

Alan Poulain's avatar
Alan Poulain committed
34
    public static $commands = [
Sebastian Castro's avatar
Sebastian Castro committed
35
      // v2.3.1
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
36
      'app:elements:updateJson all',
Sebastian Castro's avatar
Sebastian Castro committed
37
      // v2.3.4
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
38
      'app:elements:updateJson all',
Sebastian Castro's avatar
Sebastian Castro committed
39
      // v2.4.5
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
40
      'app:elements:updateJson all',
Sebastian Castro's avatar
Sebastian Castro committed
41 42
    ];

Alan Poulain's avatar
Alan Poulain committed
43
    public static $messages = [
Sebastian Castro's avatar
Sebastian Castro committed
44
        // v2.3.0
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
45
        'Un champ <b>Image (url)</b> est maintenant disponible dans la confiugration du formulaire !',
Sebastian Castro's avatar
Sebastian Castro committed
46 47 48
        "Vous pouvez désormais customizer la popup qui s'affiche au survol d'un marqueur. Allez dans Personnalisation -> Marqueur / Popup",
        "Nouvelle option pour le menu (Personnalisation -> La Carte -> onglet Menu) : afficher à côté de chaque catégories le nombre d'élements disponible pour cette catégorie",
        // v2.3.1
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
49
        'Vous pouvez maintenant renseigner la licence qui protège vos données dans Personnalisation -> Configuration Générale',
Sebastian Castro's avatar
Sebastian Castro committed
50
        // v2.3.4
Sebastian Castro's avatar
Sebastian Castro committed
51 52
        "Amélioration du <b>système d'import</b>: vous pouvez maintenant faire correspondre les champs et les catégories avant d'importer. Des vidéos tutoriels ont été réalisés. <u>Merci de parcourir vos imports dynamiques pour les mettre à jour avec le nouveau système</u>",
        "<b>La gestion des permissions des utilisateurs fait peau neuve !</b> <u>Votre ancienne configuration ne sera peut être plus valide</u>. Veuillez vous rendre dans le <b>menu Utilisateurs pour mettre à jour les roles des utilisateurs et des groupes</b> d'utilisateurs.",
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
53
        'Vous pouvez maintenant configurer des mot clés à exclure dans la recherche des éléments. Rendez-vous dans Personnalisation -> La Carte -> Onglet Recherche',
Sebastian Castro's avatar
Sebastian Castro committed
54
        // v2.5
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
55
        "Il est maintenant possible de <b>téléverser des images et des fichiers</b> depuis le formulaire d'ajout d'un élément ! Paramétrez ces nouveaux champs dans Modèle de Données -> Formulaire",
Sebastian Castro's avatar
Sebastian Castro committed
56 57
    ];

58 59 60 61 62 63 64
    public function __construct(DocumentManager $dm, LoggerInterface $commandsLogger,
                               TokenStorageInterface $security,
                               AsyncService $asyncService)
    {
        $this->asyncService = $asyncService;
        parent::__construct($dm, $commandsLogger, $security);
    }
Sebastian Castro's avatar
Sebastian Castro committed
65

Alan Poulain's avatar
Alan Poulain committed
66
    protected function gogoConfigure(): void
67 68 69 70 71
    {
        $this->setName('db:migrate')
             ->setDescription('Update datatabse each time after code update');
    }

Alan Poulain's avatar
Alan Poulain committed
72
    protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
73
    {
74
        $migrationState = $dm->createQueryBuilder('App\Document\MigrationState')->getQuery()->getSingleResult();
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
75
        if (null == $migrationState) { // Meaning the migration state was not yet in the place in the code
76
            $migrationState = new MigrationState();
Sebastian Castro's avatar
Sebastian Castro committed
77
            $dm->persist($migrationState);
78 79
        }

80 81 82
        try {
            // Collecting the Database to be updated
            $dbs = ['gogocarto_default'];
83
            $dbNames = $dm->createQueryBuilder('App\Document\Project')->select('domainName')->hydrate(false)->getQuery()->execute()->toArray();
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
84 85 86
            foreach ($dbNames as $object) {
                $dbs[] = $object['domainName'];
            }
87

Alan Poulain's avatar
Alan Poulain committed
88 89
            if (count(self::$migrations) > $migrationState->getMigrationIndex()) {
                $migrationsToRun = array_slice(self::$migrations, $migrationState->getMigrationIndex());
Sebastian Castro's avatar
Sebastian Castro committed
90
                $migrationsToRun = array_unique($migrationsToRun);
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
91 92 93
                foreach ($dbs as $db) {
                    foreach ($migrationsToRun as $migration) {
                        $this->log('run migration '.$migration.' on project '.$db);
Sebastian Castro's avatar
Sebastian Castro committed
94
                        $this->runMongoCommand($db, $migration);
95
                    }
96
                }
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
97
                $this->log(count($migrationsToRun).' migrations performed');
98
            } else {
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
99
                $this->log('No Migrations to perform');
100 101
            }

102
            // run them syncronously otherwise all the command will be run at once
103
            $this->asyncService->setRunSynchronously(true);
Alan Poulain's avatar
Alan Poulain committed
104 105
            if (count(self::$commands) > $migrationState->getCommandsIndex()) {
                $commandsToRun = array_slice(self::$commands, $migrationState->getCommandsIndex());
106
                $commandsToRun = array_unique($commandsToRun);
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
107 108 109 110
                $this->log(count($commandsToRun).' commands to run');
                foreach ($dbs as $db) {
                    foreach ($commandsToRun as $command) {
                        $this->log('call command '.$command.' on project '.$db);
111
                        $this->asyncService->callCommand($command, [], $db);
112
                    }
113 114
                }
            } else {
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
115
                $this->log('No commands to run');
Sebastian Castro's avatar
Sebastian Castro committed
116 117
            }

Alan Poulain's avatar
Alan Poulain committed
118 119
            if (count(self::$messages) > $migrationState->getMessagesIndex()) {
                $messagesToAdd = array_slice(self::$messages, $migrationState->getMessagesIndex());
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
120 121 122 123
                $this->log(count($messagesToAdd).' messages to add');
                foreach ($dbs as $db) {
                    $this->log('add message on project '.$db);
                    foreach ($messagesToAdd as $message) {
124
                        // create a GoGoLogUpdate
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
125
                        $this->asyncService->callCommand('gogolog:add:message', ['"'.$message.'"'], $db);
126
                    }
127
                }
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
128
                $this->log(count($messagesToAdd).' messages added to admin dashboard');
129
            } else {
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
130
                $this->log('No Messages to add to dashboard');
131
            }
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
132 133 134
        } catch (\Exception $e) {
            $message = $e->getMessage().'</br>'.$e->getFile().' LINE '.$e->getLine();
            $this->error('Error performing migrations: '.$message);
135
        }
136

Alan Poulain's avatar
Alan Poulain committed
137 138 139
        $migrationState->setMigrationIndex(count(self::$migrations));
        $migrationState->setCommandsIndex(count(self::$commands));
        $migrationState->setMessagesIndex(count(self::$messages));
Sebastian Castro's avatar
Sebastian Castro committed
140
        $dm->flush();
141 142
    }

Sebastian Castro's avatar
Sebastian Castro committed
143
    private function runMongoCommand($db, $command)
144
    {
Sebastian Castro's avatar
Sebastian Castro committed
145
        $process = new Process("mongo {$db} --eval '{$command}'");
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
146

147
        return $process->run();
148
    }
Alan Poulain's avatar
Fix CS  
Alan Poulain committed
149
}