Commit 88fb0217 authored by Sebastian Castro's avatar Sebastian Castro
Browse files

Add db migration system (also add messages for admins

parent bef9b46a
<?php
namespace Biopen\CoreBundle\Command;
use Biopen\SaasBundle\Command\GoGoAbstractCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Biopen\CoreBundle\Document\GoGoLogUpdate;
use Symfony\Component\Console\Input\InputArgument;
/**
* Command to update database when schema need migration
* Also provide some update message in the admin dashboard
*/
class AddMessageCommand extends GoGoAbstractCommand
{
protected function gogoConfigure()
{
$this->setName('gogolog:add:message')
->addArgument('message', InputArgument::REQUIRED, 'Message to add')
->setDescription('Update datatabse each time after code update');
}
protected function gogoExecute($em, InputInterface $input, OutputInterface $output)
{
$log = new GoGoLogUpdate('info', $input->getArgument('message'));
$em->persist($log);
$em->flush();
}
}
\ No newline at end of file
<?php
namespace Biopen\CoreBundle\Command;
use Biopen\SaasBundle\Command\GoGoAbstractCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Biopen\CoreBundle\Document\MigrationState;
use Biopen\CoreBundle\Document\GoGoLogUpdate;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Process\Process;
/**
* Command to update database when schema need migration
* Also provide some update message in the admin dashboard
*/
class MigrationCommand extends GoGoAbstractCommand
{
protected function gogoConfigure()
{
$this->setName('db:migrate')
->setDescription('Update datatabse each time after code update');
}
protected function gogoExecute($em, InputInterface $input, OutputInterface $output)
{
$migrationState = $em->createQueryBuilder('BiopenCoreBundle:MigrationState')->getQuery()->getSingleResult();
if ($migrationState == null) // Meaning the migration state was not yet in the place in the code
{
$migrationState = new MigrationState();
$em->persist($migrationState);
}
// Collecting the Database to be updated
$dbs = ['gogocarto_default'];
$dbNames = $em->createQueryBuilder('BiopenSaasBundle:Project')->select('domainName')->hydrate(false)->getQuery()->execute()->toArray();
foreach ($dbNames as $object) { $dbs[] = $object['domainName']; }
if (count($this->migrations) > $migrationState->getMigrationIndex()) {
$migrationsToRun = array_slice($this->migrations, $migrationState->getMigrationIndex());
foreach($dbs as $db) {
foreach($migrationsToRun as $migration) {
$this->runCommand($db, $migration);
}
}
$this->log(count($migrationsToRun) . " migrations performed");
} else {
$this->log("No Migrations to perform");
}
$asyncService = $this->getContainer()->get('biopen.async');
if (count($this->messages) > $migrationState->getMessagesIndex()) {
$messagesToAdd = array_slice($this->messages, $migrationState->getMessagesIndex());
foreach($dbs as $db) {
foreach($messagesToAdd as $message) {
// create a GoGoLogUpdate
$asyncService->callCommand('gogolog:add:message', ['"' . $message . '"'], $db);
}
}
$this->log(count($messagesToAdd) . " messages added to admin dashboard");
} else {
$this->log("No Messages to add to dashboard");
}
$migrationState->setMigrationIndex(count($this->migrations));
$migrationState->setMessagesIndex(count($this->messages));
$em->flush();
}
private function runCommand($db, $command)
{
$process = new Process("mongo {$db} --eval \"{$command}\"");
return $process->start();
}
// ---------------------------------------------------------------
// DO NOT REMOVE A SINGLE ELEMENT OF THIS ARRAY, ONLY ADD NEW ONES
// ---------------------------------------------------------------
public $migrations = [
// March 2019
// "db.Category.renameCollection('CategoryGroup')",
// "db.Option.renameCollection('Category')"
];
public $messages = [
"Un champ <b>Image (url)</b> est maintenant disponible dans la confiugration du formulaire !"
];
}
\ No newline at end of file
......@@ -121,7 +121,21 @@ class APIController extends GoGoController
{
$odm = $this->get('doctrine_mongodb')->getManager();
$qb = $odm->createQueryBuilder('BiopenCoreBundle:GoGoLog');
$qb->updateMany()->field('hidden')->equals(false)->field('hidden')->set(true)->getQuery()->execute();
$qb->updateMany()
->field('type')->notEqual('update')
->field('hidden')->equals(false)
->field('hidden')->set(true)->getQuery()->execute();
return $this->redirectToRoute('sonata_admin_dashboard');
}
public function hideAllMessagesAction()
{
$odm = $this->get('doctrine_mongodb')->getManager();
$qb = $odm->createQueryBuilder('BiopenCoreBundle:GoGoLogUpdate');
$qb->updateMany()
->field('type')->equals('update')
->field('hidden')->equals(false)
->field('hidden')->set(true)->getQuery()->execute();
return $this->redirectToRoute('sonata_admin_dashboard');
}
}
\ No newline at end of file
<?php
namespace Biopen\CoreBundle\DataFixtures\MongoDB;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Biopen\CoreBundle\Document\MigrationState;
use Biopen\CoreBundle\Command\MigrationCommand;
use joshtronic\LoremIpsum;
class LoadMigrationState implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$migrationState = new MigrationState();
$migrationCommand = new MigrationCommand();
$migrationState->setMigrationIndex(count($migrationCommand->migrations));
$migrationState->setMessagesIndex(count($migrationCommand->messages));
$manager->persist($migrationState);
$manager->flush();
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ abstract class GoGoLogLevel
*
* @MongoDB\InheritanceType("SINGLE_COLLECTION")
* @MongoDB\DiscriminatorField("type")
* @MongoDB\DiscriminatorMap({"standard"="GoGoLog", "import"="GoGoLogImport"})
* @MongoDB\DiscriminatorMap({"standard"="GoGoLog", "import"="GoGoLogImport", "update"="GoGoLogUpdate"})
* @MongoDB\DefaultDiscriminatorValue("standard")
*/
class GoGoLog
......@@ -75,6 +75,8 @@ class GoGoLog
$this->data = $data;
}
public function displayTimestamp() { return true; }
public function displayMessage()
{
return $this->getMessage();
......
<?php
namespace Biopen\CoreBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* Special log for code update messages
*
* @MongoDB\Document
*/
class GoGoLogUpdate extends GoGoLog
{
public function displayTimestamp() { return false; }
}
<?php
namespace Biopen\CoreBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* Keep a trace of the migrations already ran. See MigrationCommand
* @MongoDB\Document
*/
class MigrationState
{
/** @MongoDB\Id */
private $id;
/**
* @MongoDB\Field(type="int")
*/
private $migrationIndex = 0;
/**
* @MongoDB\Field(type="int")
*/
private $messagesIndex = 0;
/**
* Get id
*
* @return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set migrationIndex
*
* @param int $migrationIndex
* @return $this
*/
public function setMigrationIndex($migrationIndex)
{
$this->migrationIndex = $migrationIndex;
return $this;
}
/**
* Get migrationIndex
*
* @return int $migrationIndex
*/
public function getMigrationIndex()
{
return $this->migrationIndex;
}
/**
* Set messagesIndex
*
* @param int $messagesIndex
* @return $this
*/
public function setMessagesIndex($messagesIndex)
{
$this->messagesIndex = $messagesIndex;
return $this;
}
/**
* Get messagesIndex
*
* @return int $messagesIndex
*/
public function getMessagesIndex()
{
return $this->messagesIndex;
}
}
......@@ -32,3 +32,9 @@ biopen_api_log_hide_all:
defaults: { _controller: BiopenCoreBundle:API:hideAllLogs }
requirements:
methods: GET
biopen_api_message_hide_all:
path: /messages/hide-all
defaults: { _controller: BiopenCoreBundle:API:hideAllMessages }
requirements:
methods: GET
\ No newline at end of file
......@@ -46,10 +46,12 @@ class AsyncService
return $this->runProcess($commandline);
}
public function callCommand($commandName, $arguments = [])
public function callCommand($commandName, $arguments = [], $dbname = null)
{
$saasHelper = new SaasHelper();
$dbname = $saasHelper->getCurrentProjectCode();
if ($dbname === null) {
$saasHelper = new SaasHelper();
$dbname = $saasHelper->getCurrentProjectCode();
}
$commandline = $this->phpPath . ' ' . $this->consolePath . ' ' . $commandName;
foreach ($arguments as $key => $arg) {
......
......@@ -54,8 +54,13 @@ class MonitoringElementsBlockService extends AbstractBlockService
$activeUsersCount = $this->em->createQueryBuilder('BiopenCoreBundle:User')->field('enabled')->equals(true)->count()->getQuery()->execute();
$activeUsersNewsletterCount = $this->em->createQueryBuilder('BiopenCoreBundle:User')->field('enabled')->equals(true)
->field('newsletterFrequency')->gt(NewsletterFrequencyOptions::Never)->count()->getQuery()->execute();
$errors = $this->em->getRepository('BiopenCoreBundle:GoGoLog')->findBy(['type' => 'error', 'hidden' => false]);
$errors = $this->em->getRepository('BiopenCoreBundle:GoGoLog')->findBy(['level' => 'error', 'hidden' => false]);
usort( $errors, function ($a, $b) { return $b->getCreatedAt()->getTimestamp() - $a->getCreatedAt()->getTimestamp(); });
$messages = $this->em->getRepository('BiopenCoreBundle:GoGoLog')->findBy(['type' => 'update', 'hidden' => false]);
usort( $errors, function ($a, $b) { return $b->getCreatedAt()->getTimestamp() - $a->getCreatedAt()->getTimestamp(); });
// merge settings
$settings = $blockContext->getSettings();
......@@ -69,7 +74,8 @@ class MonitoringElementsBlockService extends AbstractBlockService
'visibleNonImportedCount' => $visibleNonImportedElements,
'activeUsersCount' => $activeUsersCount,
'activeUsersNewsletterCount' => $activeUsersNewsletterCount,
'errors' => $errors
'errors' => $errors,
'messages' => $messages
), $response);
}
}
\ No newline at end of file
{% extends sonata_block.templates.block_base %}
{% block block %}
{% if messages|length %}
<div class="sonata-block-logs box box-info">
<div class="box-header with-border">
<h3 class="box-title">Du nouveau sur GoGoCarto !</h3>
</div>
<div class="box-body" style="max-height: 500px; overflow: auto">
{% include '@BiopenAdmin/core_custom/custom-fields/display-logs.html.twig' with { logs: messages, dismissLog: true } %}
</div>
{% if messages|length > 4 %}
<div class="box-footer">
<a href="{{ path('biopen_api_message_hide_all') }}" class="btn btn-default btn-block"><i class="fa fa-list"></i> Supprimer tous les messages</a>
</div>
{% endif %}
</div>
{% endif %}
{% if errors|length %}
<div class="sonata-block-log-errors box box-danger">
<div class="sonata-block-logs box box-danger">
<div class="box-header with-border">
<h3 class="box-title">Des erreurs ont eu lieu récemment</h3>
</div>
......
......@@ -6,7 +6,10 @@
method : 'post',
url : url.replace("ID", $logId),
complete : function(data, status, object) {
if ($('.sonata-block-log-errors .alert').length == 0) $('.sonata-block-log-errors').hide();
$('.sonata-block-logs').each(function() {
if ($(this).find('.alert').length == 0) $(this).hide();
})
},
});
}
......@@ -19,7 +22,8 @@
{% if dismissLog is defined %}
<button type="button" class="close" data-dismiss="alert" aria-label="Fermer" onclick="hideLog({{log.id}})"><span aria-hidden="true" style="font-size: 1.6rem">Ne plus afficher</span></button>
{% endif %}
<strong>{{ log.createdAt|date("d/m/Y à H:i") }}</strong> - {{ log.displayMessage|raw }}
{% if log.displayTimestamp %}<strong>{{ log.createdAt|date("d/m/Y à H:i") }}</strong> - {% endif %}
{{ log.displayMessage|raw }}
</div>
{% endfor %}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment