Skip to content
Snippets Groups Projects
Commit b930b393 authored by Camille Simiand's avatar Camille Simiand
Browse files

Duplicate a capsule Form, method and template

parent e625c874
No related branches found
No related tags found
1 merge request!44tuleap-80-duplicate-a-capsule
<?xml version="1.0"?>
<!DOCTYPE rekall>
<project>
<video url="https://youtu.be/Ssm_mm8zyS0"/>
<document key="marker-1f10323d5f4a1c119e777e59c2f00dcc650e750d">
<meta ctg="Rekall-&gt;Author" cnt=""/>
<meta ctg="Rekall-&gt;Date/Time" cnt="2015:08:31 18:06:16"/>
<meta ctg="Rekall-&gt;Import Date" cnt="2015:08:31 18:06:16"/>
<meta ctg="Rekall User Infos-&gt;User Name" cnt=""/>
<meta ctg="Rekall-&gt;Location Name" cnt="48.867359621322265, 2.3618561655447228"/>
<meta ctg="Rekall-&gt;Location GPS" cnt="48.867359621322265, 2.3618561655447228"/>
<meta ctg="Rekall User Infos-&gt;User IP" cnt="127.0.0.1"/>
<meta ctg="Rekall-&gt;Comments" cnt=""/>
<meta ctg="Rekall-&gt;Keywords" cnt=""/>
<meta ctg="Rekall-&gt;Group" cnt=""/>
<meta ctg="Rekall-&gt;Visibility" cnt=""/>
<meta ctg="Rekall-&gt;Type" cnt="rekall/marker"/>
<meta ctg="Rekall-&gt;Flag" cnt="Marker"/>
<meta ctg="Rekall-&gt;Name" cnt="New note"/>
</document>
<tag key="marker-1f10323d5f4a1c119e777e59c2f00dcc650e750d" timeStart="0" timeEnd="10" version="0"/>
</project>
...@@ -5,12 +5,15 @@ namespace App\Controller; ...@@ -5,12 +5,15 @@ namespace App\Controller;
use App\Entity\Capsule; use App\Entity\Capsule;
use App\Entity\User; use App\Entity\User;
use App\Form\DeleteCapsuleFormType; use App\Form\DeleteCapsuleFormType;
use App\Form\DuplicateCapsuleFormType;
use App\Helper\StringHelper; use App\Helper\StringHelper;
use App\Repository\CapsuleRepository; use App\Repository\CapsuleRepository;
use App\Builder\CapsuleBuilder; use App\Builder\CapsuleBuilder;
use App\Form\CreateCapsuleFormType; use App\Form\CreateCapsuleFormType;
use Knp\Component\Pager\PaginatorInterface; use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
...@@ -62,25 +65,9 @@ class CapsuleController extends AbstractController ...@@ -62,25 +65,9 @@ class CapsuleController extends AbstractController
} }
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$new_date_time = new \DateTime();
$capsule_name = $form->get('name')->getData();
$video_url = htmlspecialchars($form->get('video_url')->getData()); $video_url = htmlspecialchars($form->get('video_url')->getData());
$password = StringHelper::generateRandomHashedString();
$preview_link = Uuid::v4();
$entityManager = $this->getDoctrine()->getManager(); $capsule = $this->createCapsuleInDB($form, $current_user);
$capsule_builder = new CapsuleBuilder();
$capsule = $capsule_builder
->withName($capsule_name)
->withCreationAuthor($current_user)
->withCreationDate($new_date_time)
->withLinkPath($preview_link)
->withUpdateDate($new_date_time)
->withPassword($password)
->createCapsule();
$entityManager->persist($capsule);
$entityManager->flush();
return $this->forward('App\Controller\ProjectController::create', [ return $this->forward('App\Controller\ProjectController::create', [
'capsule' => $capsule, 'capsule' => $capsule,
...@@ -189,4 +176,83 @@ class CapsuleController extends AbstractController ...@@ -189,4 +176,83 @@ class CapsuleController extends AbstractController
'capsule_name' => $capsule_name 'capsule_name' => $capsule_name
]); ]);
} }
/**
* @Route("/capsule/duplicate/{id}", name="duplicate_capsule")
*/
public function duplicate(
int $id,
Request $request,
Filesystem $file_system,
TranslatorInterface $translator
): Response {
$form = $this->createForm(DuplicateCapsuleFormType::class);
$form->handleRequest($request);
$current_user = $this->getUser();
if (! $current_user instanceof User) {
return $this->redirectToRoute('app_logout');
}
$entityManager = $this->getDoctrine()->getManager();
$parent_capsule = $entityManager->getRepository(Capsule::class)->find($id);
if (! $parent_capsule instanceof Capsule) {
throw new \Exception('The retrieved capsule is not an instance of Caspule.');
}
$parent_directory_name = $parent_capsule->getLinkPath();
$parent_directory_exists = $file_system->exists('../legacy/' . $parent_directory_name);
if (! $parent_directory_exists) {
$this->addFlash(
'project_does_not_exist',
$translator->trans(
'project.not_exist',
[
'capsule_name' => $parent_capsule->getName()
]
)
);
return $this->redirectToRoute('capsule_list');
}
if ($form->isSubmitted() && $form->isValid()) {
$capsule = $this->createCapsuleInDB($form, $current_user);
return $this->forward('App\Controller\ProjectController::duplicate', [
'capsule' => $capsule,
'parent_directory' => $parent_directory_name
]);
}
return $this->render('capsule/duplicate.html.twig', [
'duplicateCapsuleForm' => $form->createView(),
'capsule_name' => $parent_capsule->getName()
]);
}
private function createCapsuleInDB(FormInterface $form, User $current_user): Capsule
{
$new_date_time = new \DateTime();
$capsule_name = $form->get('name')->getData();
$password = StringHelper::generateRandomHashedString();
$preview_link = Uuid::v4();
$entityManager = $this->getDoctrine()->getManager();
$capsule_builder = new CapsuleBuilder();
$capsule = $capsule_builder
->withName($capsule_name)
->withCreationAuthor($current_user)
->withCreationDate($new_date_time)
->withLinkPath($preview_link)
->withUpdateDate($new_date_time)
->withPassword($password)
->createCapsule();
$entityManager->persist($capsule);
$entityManager->flush();
return $capsule;
}
} }
...@@ -7,6 +7,7 @@ use App\Exception\ZipArchiveNotOpeningException; ...@@ -7,6 +7,7 @@ use App\Exception\ZipArchiveNotOpeningException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Config\Util\Exception\XmlParsingException; use Symfony\Component\Config\Util\Exception\XmlParsingException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException; use Symfony\Component\Filesystem\Exception\FileNotFoundException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
...@@ -62,6 +63,52 @@ class ProjectController extends AbstractController ...@@ -62,6 +63,52 @@ class ProjectController extends AbstractController
return $this->redirectToRoute('capsule_list'); return $this->redirectToRoute('capsule_list');
} }
/**
* @Route("/project/duplicate", name="duplicate_project", methods={"POST"})
* @throws ZipArchiveNotOpeningException
*/
public function duplicate(
TranslatorInterface $translator,
Capsule $capsule,
string $parent_directory,
Filesystem $file_system
): Response {
chdir('../legacy/');
$capsule_name = $capsule->getName();
$capsule_directory = $capsule->getLinkPath();
if (file_exists($capsule_directory)) {
$this->addFlash(
'project_already_exists',
$translator->trans(
'project.already_exists',
[
'capsule_name' => $capsule_name
]
)
);
return $this->redirectToRoute('capsule_list');
}
$this->extractZipArchiveInNewCapsuleDirectory($capsule_directory);
$this->replaceTheWholeFileDirectoryWithParentOne($file_system, $parent_directory, $capsule_directory);
$this->createOrUpdatePasswordFile($capsule_directory, $capsule->getPassword());
$this->addFlash(
'capsule_duplicated_success',
$translator->trans(
'capsule.duplicate.success',
[
'capsule_name' => $capsule_name
]
)
);
return $this->redirectToRoute('capsule_list');
}
/** /**
* @throws ZipArchiveNotOpeningException The archive file doesn't exist. * @throws ZipArchiveNotOpeningException The archive file doesn't exist.
*/ */
...@@ -101,4 +148,18 @@ class ProjectController extends AbstractController ...@@ -101,4 +148,18 @@ class ProjectController extends AbstractController
$project_password_file = $capsule_directory . "/file/projectPassword.txt"; $project_password_file = $capsule_directory . "/file/projectPassword.txt";
file_put_contents($project_password_file, $password); file_put_contents($project_password_file, $password);
} }
private function replaceTheWholeFileDirectoryWithParentOne(
FileSystem $file_system,
string $parent_directory,
string $child_directory
): void {
$file_directory_path = '/file/';
$file_system->mirror(
$parent_directory . $file_directory_path,
$child_directory . $file_directory_path,
null,
['override' => true]
);
}
} }
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DuplicateCapsuleFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(
'name',
TextType::class,
['label' => 'capsule.duplicate.new_name']
)
->add(
'validate',
SubmitType::class,
['label' => 'general.validate']
);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([]);
}
}
{% extends 'layout.html.twig' %}
{% block title %}
{{ 'capsule.duplicate.title'|trans }}
-
{{ parent() }}
{% endblock %}
{% block body %}
<div>
<div class="row w-100 gx-0">
<div class="row-title-box">
<h3 class="row-title">
{{ 'capsule.duplicate.title_name'|trans({'%capsule_name%': capsule_name}) }}
</h3>
</div>
</div>
{# <div class="d-flex flex-column justify-content-center align-items-center">#}
{{ form_start(duplicateCapsuleForm, {'attr': {novalidate: 'novalidate', 'class': 'd-flex flex-column justify-content-center'}}) }}
{{ form_row(duplicateCapsuleForm.name, {'row_attr': {'class' : 'm-auto mb-4 col-6'}}) }}
{{ form_row(duplicateCapsuleForm.validate, {'row_attr': {'class' : 'm-auto mb-5 col-2'}}) }}
{{ form_end(duplicateCapsuleForm) }}
{# </div>#}
</div>
{% endblock %}
\ No newline at end of file
...@@ -40,6 +40,18 @@ ...@@ -40,6 +40,18 @@
{{ flashSuccess }} {{ flashSuccess }}
</div> </div>
{% endfor %} {% endfor %}
{% for flashWarning in app.flashes('project_does_not_exist') %}
<div class="text-center alert alert-warning col-5 mx-auto my-5" role="alert">
{{ flashWarning }}
</div>
{% endfor %}
{% for flashSuccess in app.flashes('capsule_duplicated_success') %}
<div class="text-center alert alert-success col-5 mx-auto my-5" role="alert">
{{ flashSuccess }}
</div>
{% endfor %}
</div> </div>
<div class="capsules-list d-flex flex-column m-6"> <div class="capsules-list d-flex flex-column m-6">
...@@ -75,7 +87,7 @@ ...@@ -75,7 +87,7 @@
</a> </a>
</div> </div>
<div class="list-item text-nowrap"> <div class="list-item text-nowrap">
<a href="" class="links text-decoration-none"> <a href="/capsule/duplicate/{{ capsule.getId() }}" class="links text-decoration-none">
<i class="far fa-clone m-2"></i> <i class="far fa-clone m-2"></i>
{{ 'capsule.duplicate.link'|trans }} {{ 'capsule.duplicate.link'|trans }}
</a> </a>
......
...@@ -7,6 +7,7 @@ general: ...@@ -7,6 +7,7 @@ general:
cancel_button: Cancel cancel_button: Cancel
link_expire: This link will expire in %expirationDuration% link_expire: This link will expire in %expirationDuration%
greeting: Cheers! greeting: Cheers!
validate: Validate
login: login:
account_disabled_feedback: Your user account is disabled. Please click on the link your receive by email to validate your registration. account_disabled_feedback: Your user account is disabled. Please click on the link your receive by email to validate your registration.
...@@ -70,6 +71,10 @@ capsule: ...@@ -70,6 +71,10 @@ capsule:
link: Edit capsule link: Edit capsule
duplicate: duplicate:
link: Duplicate capsule link: Duplicate capsule
title: Duplicate capsule
title_name: Duplicate capsule %capsule_name%
new_name: Enter the name of the new capsule
success: The capsule has been successfully duplicated into capsule_name. You can see it at the end of your list.
delete: delete:
link: Delete capsule link: Delete capsule
button: Delete button: Delete
...@@ -79,6 +84,7 @@ capsule: ...@@ -79,6 +84,7 @@ capsule:
project: project:
already_exists: Project capsule_name already exists so the capsule could not be created already_exists: Project capsule_name already exists so the capsule could not be created
not_exist: The project to duplicate does not exist
preview: preview:
loading: Project loading loading: Project loading
......
...@@ -7,6 +7,7 @@ general: ...@@ -7,6 +7,7 @@ general:
greeting: Salutation ! greeting: Salutation !
go_back_to_home_page: Page d'accueil go_back_to_home_page: Page d'accueil
cancel_button: Annuler cancel_button: Annuler
validate: Valider
login: login:
account_disabled_feedback: Le compte utilisateur a été désactivé. Veuillez cliquer sur le lien pour recevoir un courriel de validation account_disabled_feedback: Le compte utilisateur a été désactivé. Veuillez cliquer sur le lien pour recevoir un courriel de validation
...@@ -67,6 +68,10 @@ capsule: ...@@ -67,6 +68,10 @@ capsule:
link: Modifier la capsule link: Modifier la capsule
duplicate: duplicate:
link: Dupliquer la capsule link: Dupliquer la capsule
title: Dupliquer la capsule
title_name: Dupliquer la capsule %capsule_name%
new_name: Saisissez le nom de la nouvelle capsule
success: La capsule a bien été dupliquée en capsule_name. Vous la retrouverez à la suite des capsules.
delete: delete:
link: Supprimer la capsule link: Supprimer la capsule
not_found: Le projet n'existe pas not_found: Le projet n'existe pas
...@@ -77,6 +82,7 @@ capsule: ...@@ -77,6 +82,7 @@ capsule:
project: project:
already_exists: Le projet capsule_name existe déjà. La capsule n'a pas pu être créée already_exists: Le projet capsule_name existe déjà. La capsule n'a pas pu être créée
not_exist: Le projet a dupliquer n'existe pas
preview: preview:
loading: Projet en cours de chargement loading: Projet en cours de chargement
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment