✨ feat(BackupCommand): Ajoute la commande de sauvegarde de la base de données et des uploads.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -33,3 +33,5 @@ coverage/
|
|||||||
.phpunit.cache
|
.phpunit.cache
|
||||||
/public/build
|
/public/build
|
||||||
script/demande/hosts.ini
|
script/demande/hosts.ini
|
||||||
|
backup/*.zip
|
||||||
|
backup/*.sql
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[webservers]
|
[webservers]
|
||||||
127.0.0.1 ansible_connection=local ansible_python_interpreter=/usr/bin/python3 path=/var/www/mainframe/app
|
127.0.0.1 ansible_connection=local ansible_python_interpreter=/usr/bin/python3 path=/var/www/mainframe/public
|
||||||
|
|||||||
0
backup/.gitignore
vendored
Normal file
0
backup/.gitignore
vendored
Normal file
@@ -72,7 +72,8 @@
|
|||||||
"twig/extra-bundle": "^3.21",
|
"twig/extra-bundle": "^3.21",
|
||||||
"twig/intl-extra": "^3.21",
|
"twig/intl-extra": "^3.21",
|
||||||
"twig/twig": "^3.21",
|
"twig/twig": "^3.21",
|
||||||
"vich/uploader-bundle": "^2.7"
|
"vich/uploader-bundle": "^2.7",
|
||||||
|
"ext-zip": "*"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
|
|||||||
121
src/Command/BackupCommand.php
Normal file
121
src/Command/BackupCommand.php
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Entity\Revendeur;
|
||||||
|
use App\Repository\RevendeurRepository;
|
||||||
|
use App\Service\Revendeur\RevendeurService;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
use Symfony\Component\Finder\Finder;
|
||||||
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
|
|
||||||
|
#[AsCommand(name: 'mainframe:backup', description: 'Backup command')]
|
||||||
|
class BackupCommand extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly KernelInterface $kernelInterface,
|
||||||
|
private readonly RevendeurService $revendeurService,
|
||||||
|
?string $name = null)
|
||||||
|
{
|
||||||
|
parent::__construct($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$io->title('Backup command');
|
||||||
|
|
||||||
|
$path = $this->kernelInterface->getProjectDir()."/backup";
|
||||||
|
$this->backuped($path);
|
||||||
|
|
||||||
|
$finder = new Finder();
|
||||||
|
$files = $finder->in($path)->files()->name('*.tar.gz');
|
||||||
|
$now = time();
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($now - $file->getMTime() > 60 * 60 * 24 * 7) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
private function backuped(string $backupPath): void
|
||||||
|
{
|
||||||
|
$database= $_ENV['DATABASE_URL'];
|
||||||
|
preg_match(
|
||||||
|
'/^postgres(?:ql)?:\\/\\/(.*?):(.*?)@(.*?):(\\d+)\\/(.*?)(?:\\?|$)/',
|
||||||
|
$database,
|
||||||
|
$matches
|
||||||
|
);
|
||||||
|
// À adapter selon ta configuration/env Symfony !
|
||||||
|
$user = $matches[1] ?? null;
|
||||||
|
$password = $matches[2] ?? null;
|
||||||
|
$host = $matches[3] ?? null;
|
||||||
|
$port = $matches[4] ?? null;
|
||||||
|
$db = $matches[5] ?? null;
|
||||||
|
|
||||||
|
$sqlFilename = sprintf('%s/pgsql_backup_%s.sql', $backupPath, date('Y-m-d_His'));
|
||||||
|
|
||||||
|
// Pour éviter les exposes de mdp dans commande : passer par env
|
||||||
|
putenv("PGPASSWORD={$password}");
|
||||||
|
|
||||||
|
// Option -F c pour backup custom compressé, -f pour destination
|
||||||
|
$command = sprintf(
|
||||||
|
'pg_dump -h %s -U %s -F c %s -f %s',
|
||||||
|
$host,
|
||||||
|
$user,
|
||||||
|
$db,
|
||||||
|
$sqlFilename
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exécution du backup
|
||||||
|
exec($command);
|
||||||
|
|
||||||
|
$zipFilename = sprintf('%s/backup_%s.zip', $backupPath, date('d-m-Y'));
|
||||||
|
// Création du ZIP et ajout du SQL dedans
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
if ($zip->open($zipFilename, \ZipArchive::CREATE) === true) {
|
||||||
|
// Le fichier dans le zip portera juste le nom du .sql
|
||||||
|
$zip->addFile($sqlFilename, basename($sqlFilename));
|
||||||
|
|
||||||
|
$vichUploadDirs = [
|
||||||
|
$this->kernelInterface->getProjectDir() . '/public/storage', // Exemple chemin upload
|
||||||
|
// ajouter d’autres chemins si besoin
|
||||||
|
];
|
||||||
|
foreach ($vichUploadDirs as $dir) {
|
||||||
|
$this->addDirToZip($zip, $dir, basename($dir));
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
unlink($sqlFilename);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addDirToZip(\ZipArchive $zip, string $folder, string $zipPath): void
|
||||||
|
{
|
||||||
|
$files = new \RecursiveIteratorIterator(
|
||||||
|
new \RecursiveDirectoryIterator($folder),
|
||||||
|
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($files as $name => $file) {
|
||||||
|
if (!$file->isDir()) {
|
||||||
|
$filePath = $file->getRealPath();
|
||||||
|
$relativePath = $zipPath . '/' . substr($filePath, strlen($folder) + 1);
|
||||||
|
$zip->addFile($filePath, $relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,6 +7,8 @@ use App\Form\Artemis\Revendeur\RevendeurType;
|
|||||||
use App\Service\Revendeur\RevendeurService;
|
use App\Service\Revendeur\RevendeurService;
|
||||||
use App\Service\Revendeur\SendLinkEvent;
|
use App\Service\Revendeur\SendLinkEvent;
|
||||||
use Cocur\Slugify\Slugify;
|
use Cocur\Slugify\Slugify;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@@ -16,11 +18,17 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||||||
class RevendeurController extends AbstractController
|
class RevendeurController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route(path: '/artemis/revendeur',name: 'artemis_revendeur')]
|
#[Route(path: '/artemis/revendeur',name: 'artemis_revendeur')]
|
||||||
public function revendeur(Request $request,EventDispatcherInterface $eventDispatcher,RevendeurService $revendeurService): Response
|
public function revendeur(EntityManagerInterface $entityManager,Request $request,EventDispatcherInterface $eventDispatcher,RevendeurService $revendeurService): Response
|
||||||
{
|
{
|
||||||
|
if($request->query->has('delete')) {
|
||||||
|
$revendeur = $revendeurService->get($request->query->get('id'));
|
||||||
|
$entityManager->remove($revendeur);
|
||||||
|
$entityManager->flush();
|
||||||
|
$this->addFlash("success","Revendeur supprimer");
|
||||||
|
return $this->redirectToRoute('artemis_revendeur');
|
||||||
|
}
|
||||||
if($request->query->has('sendLink')) {
|
if($request->query->has('sendLink')) {
|
||||||
$revendeur = $revendeurService->get($request->query->get('id'));
|
$revendeur = $revendeurService->get($request->query->get('id'));
|
||||||
$dns = $revendeur->getCode() . "-demande.esy-web.fr";
|
|
||||||
$eventSendLink = new SendLinkEvent($revendeur);
|
$eventSendLink = new SendLinkEvent($revendeur);
|
||||||
$eventDispatcher->dispatch($eventSendLink);
|
$eventDispatcher->dispatch($eventSendLink);
|
||||||
$this->addFlash("success","Le lien à été envoyée");
|
$this->addFlash("success","Le lien à été envoyée");
|
||||||
@@ -31,6 +39,11 @@ class RevendeurController extends AbstractController
|
|||||||
'revendeurLists' => $revendeurService->list(),
|
'revendeurLists' => $revendeurService->list(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
#[Route(path: '/artemis/revendeur/{id}',name: 'artemis_revendeur_view')]
|
||||||
|
public function revendeurVideo(EntityManagerInterface $entityManager,Request $request,EventDispatcherInterface $eventDispatcher,RevendeurService $revendeurService): Response
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
#[Route(path: '/artemis/revendeur/add',name: 'artemis_revendeur_add')]
|
#[Route(path: '/artemis/revendeur/add',name: 'artemis_revendeur_add')]
|
||||||
public function revendeurAdd(Request $request,RevendeurService $revendeurService): Response
|
public function revendeurAdd(Request $request,RevendeurService $revendeurService): Response
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
<td class="px-6 py-4 text-center text-sm">{{ revendeur.name }} {{ revendeur.surname }}</td>
|
<td class="px-6 py-4 text-center text-sm">{{ revendeur.name }} {{ revendeur.surname }}</td>
|
||||||
<td class="px-6 py-4 text-center text-sm">{{ revendeur.email }} {{ revendeur.phone }}</td>
|
<td class="px-6 py-4 text-center text-sm">{{ revendeur.email }} {{ revendeur.phone }}</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-center">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-center">
|
||||||
<a href="{{ path('artemis_revendeur',{id:revendeur.id}) }}&sendLink=1" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Modifier</a>
|
<a href="{{ path('artemis_revendeur_view',{id:revendeur.id}) }}" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Modifier</a>
|
||||||
<a href="{{ path('artemis_revendeur',{id:revendeur.id}) }}&sendLink=1" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Envoyée le lien du revendeur</a>
|
<a href="{{ path('artemis_revendeur',{id:revendeur.id}) }}&sendLink=1" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Envoyée le lien du revendeur</a>
|
||||||
<a target="_blank" href="{{ path('artemis_revendeur',{id:revendeur.id}) }}?open=1" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Voir le lien du revendeur</a>
|
<a target="_blank" href="https://{{ revendeur.code }}-demande.esy-web.fr" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded mr-2">Voir le lien du revendeur</a>
|
||||||
<a href="{{ path('artemis_revendeur',{id:revendeur.id}) }}?delete=1" class="bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded mr-2">Supprimer</a>
|
<a href="{{ path('artemis_revendeur',{id:revendeur.id}) }}?delete=1" class="bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded mr-2">Supprimer</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user