MigrationCommand.php 8.31 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",
56 57
        // v3.0
        "Vous pouvez maintenant écrire des actualités qui seront incluses dans la newsletter automatique! Allez dans Mails/Newsletter -> Actualités"
Sebastian Castro's avatar
Sebastian Castro committed
58 59
    ];

60 61 62 63 64 65 66
    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
67

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

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

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

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

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

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

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

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

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