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

3
namespace App\Command;
4

5
use App\Command\GoGoAbstractCommand;
6 7
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
8 9
use App\Document\MigrationState;
use App\Document\GoGoLogUpdate;
10 11
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Process\Process;
12 13 14 15 16
use Doctrine\ODM\MongoDB\DocumentManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use App\Services\AsyncService;

17 18 19 20 21 22
/**
 * Command to update database when schema need migration
 * Also provide some update message in the admin dashboard
 */
class MigrationCommand extends GoGoAbstractCommand
{
Sebastian Castro's avatar
Sebastian Castro committed
23 24 25 26
    // -----------------------------------------------------------------
    // DO NOT REMOVE A SINGLE ELEMENT OF THOSE ARRAYS, ONLY ADD NEW ONES
    // -----------------------------------------------------------------
    public $migrations = [
27
      // v2.4.6
Sebastian Castro's avatar
Sebastian Castro committed
28 29 30 31 32 33
      '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
34 35 36 37
    ];

    public $commands = [
      // v2.3.1
Sebastian Castro's avatar
Sebastian Castro committed
38
      "app:elements:updateJson all",
Sebastian Castro's avatar
Sebastian Castro committed
39
      // v2.3.4
Sebastian Castro's avatar
Sebastian Castro committed
40 41
      "app:elements:updateJson all",
      // v2.4.5
Sebastian Castro's avatar
Sebastian Castro committed
42
      "app:elements:updateJson all"
Sebastian Castro's avatar
Sebastian Castro committed
43 44 45 46 47 48 49 50
    ];

    public $messages = [
        // v2.3.0
        "Un champ <b>Image (url)</b> est maintenant disponible dans la confiugration du formulaire !",
        "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
Sebastian Castro's avatar
Sebastian Castro committed
51
        "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
52
        // v2.3.4
Sebastian Castro's avatar
Sebastian Castro committed
53 54
        "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.",
Sebastian Castro's avatar
Sebastian Castro committed
55 56 57
        "Vous pouvez maintenant configurer des mot clés à exclure dans la recherche des éléments. Rendez-vous dans Personnalisation -> La Carte -> Onglet Recherche",
        // v2.5
        "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
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

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

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

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

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

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

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

        $migrationState->setMigrationIndex(count($this->migrations));
Sebastian Castro's avatar
Sebastian Castro committed
140
        $migrationState->setCommandsIndex(count($this->commands));
141
        $migrationState->setMessagesIndex(count($this->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}'");
148
        return $process->run();
149 150
    }
}