Skip to content
Snippets Groups Projects
Commit b0271bef authored by Bernd Oliver Suenderhauf's avatar Bernd Oliver Suenderhauf
Browse files

Issue #1642268 by Pancho, Liam Morland: Allow duplicating a form with all its fields

parent 8b970c57
No related branches found
No related tags found
No related merge requests found
...@@ -62,6 +62,14 @@ entity.fillpdf_form.import_form: ...@@ -62,6 +62,14 @@ entity.fillpdf_form.import_form:
requirements: requirements:
_entity_access: fillpdf_form.view _entity_access: fillpdf_form.view
entity.fillpdf_form.duplicate_form:
path: '/admin/structure/fillpdf/{fillpdf_form}/duplicate'
defaults:
_entity_form: fillpdf_form.duplicate
_title: 'Duplicate FillPDF form configuration and field mappings'
requirements:
_entity_access: fillpdf_form.duplicate
entity.fillpdf_form_field.edit_form: entity.fillpdf_form_field.edit_form:
path: '/admin/structure/fillpdf/{fillpdf_form}/{fillpdf_form_field}' path: '/admin/structure/fillpdf/{fillpdf_form}/{fillpdf_form_field}'
defaults: defaults:
......
...@@ -23,6 +23,7 @@ use Drupal\fillpdf\Service\FillPdfAdminFormHelper; ...@@ -23,6 +23,7 @@ use Drupal\fillpdf\Service\FillPdfAdminFormHelper;
* "form" = { * "form" = {
* "edit" = "Drupal\fillpdf\Form\FillPdfFormForm", * "edit" = "Drupal\fillpdf\Form\FillPdfFormForm",
* "delete" = "Drupal\fillpdf\Form\FillPdfFormDeleteForm", * "delete" = "Drupal\fillpdf\Form\FillPdfFormDeleteForm",
* "duplicate" = "Drupal\fillpdf\Form\FillPdfFormDuplicateForm",
* "export" = "Drupal\fillpdf\Form\FillPdfFormExportForm", * "export" = "Drupal\fillpdf\Form\FillPdfFormExportForm",
* "import" = "Drupal\fillpdf\Form\FillPdfFormImportForm", * "import" = "Drupal\fillpdf\Form\FillPdfFormImportForm",
* }, * },
...@@ -40,6 +41,7 @@ use Drupal\fillpdf\Service\FillPdfAdminFormHelper; ...@@ -40,6 +41,7 @@ use Drupal\fillpdf\Service\FillPdfAdminFormHelper;
* "canonical" = "/admin/structure/fillpdf/{fillpdf_form}", * "canonical" = "/admin/structure/fillpdf/{fillpdf_form}",
* "edit-form" = "/admin/structure/fillpdf/{fillpdf_form}", * "edit-form" = "/admin/structure/fillpdf/{fillpdf_form}",
* "delete-form" = "/admin/structure/fillpdf/{fillpdf_form}/delete", * "delete-form" = "/admin/structure/fillpdf/{fillpdf_form}/delete",
* "duplicate-form" = "/admin/structure/fillpdf/{fillpdf_form}/duplicate",
* "export-form" = "/admin/structure/fillpdf/{fillpdf_form}/export", * "export-form" = "/admin/structure/fillpdf/{fillpdf_form}/export",
* "import-form" = "/admin/structure/fillpdf/{fillpdf_form}/import", * "import-form" = "/admin/structure/fillpdf/{fillpdf_form}/import",
* "collection" = "/admin/structure/fillpdf", * "collection" = "/admin/structure/fillpdf",
......
...@@ -21,6 +21,7 @@ class FillPdfFormAccessControlHandler extends EntityAccessControlHandler { ...@@ -21,6 +21,7 @@ class FillPdfFormAccessControlHandler extends EntityAccessControlHandler {
switch ($operation) { switch ($operation) {
case 'view': case 'view':
case 'update': case 'update':
case 'duplicate':
case 'delete': case 'delete':
return AccessResult::allowedIfHasPermission($account, 'administer pdfs'); return AccessResult::allowedIfHasPermission($account, 'administer pdfs');
default: default:
......
...@@ -22,6 +22,12 @@ class FillPdfFormListBuilder extends EntityListBuilder { ...@@ -22,6 +22,12 @@ class FillPdfFormListBuilder extends EntityListBuilder {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getDefaultOperations(EntityInterface $entity) { public function getDefaultOperations(EntityInterface $entity) {
$duplicate = [
'title' => t('Duplicate'),
'weight' => 10,
'url' => $this->ensureDestination($entity->toUrl('duplicate-form')),
];
$export = [ $export = [
'title' => t('Export configuration'), 'title' => t('Export configuration'),
'weight' => 20, 'weight' => 20,
...@@ -34,6 +40,7 @@ class FillPdfFormListBuilder extends EntityListBuilder { ...@@ -34,6 +40,7 @@ class FillPdfFormListBuilder extends EntityListBuilder {
]; ];
$operations = parent::getDefaultOperations($entity) + [ $operations = parent::getDefaultOperations($entity) + [
'duplicate' => $duplicate,
'export' => $export, 'export' => $export,
'import' => $import, 'import' => $import,
]; ];
......
<?php
namespace Drupal\fillpdf\Form;
use Drupal\Core\Entity\ContentEntityConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Form controller for the FillPdfForm duplicate form.
*
* @internal
*/
class FillPdfFormDuplicateForm extends ContentEntityConfirmFormBase {
/**
* The FillPdfForm being duplicated.
*
* @var \Drupal\fillpdf\FillPdfFormInterface
*/
protected $entity;
/**
* Returns the question to ask the user.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
* The form question. The page title will be set to this value.
*/
public function getQuestion() {
$label = trim($this->entity->label()) ?: $this->t('unnamed');
return $this->t('Create duplicate of %label?', ['%label' => $label]);
}
/**
* {@inheritdoc}
*/
public function getDescription() {
}
/**
* {@inheritdoc}
*/
public function getConfirmText() {
return $this->t('Save');
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
return $this->entity->toUrl();
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$label = trim($this->entity->label()) ?: $this->t('unnamed');
$form['new_admin_title'] = [
'#type' => 'textfield',
'#title' => $this->t('Administrative title'),
'#required' => TRUE,
'#size' => 32,
'#maxlength' => 255,
'#default_value' => $this->t('Duplicate of @label', ['@label' => $label]),
];
return $form;
}
/**
* {@inheritdoc}
*/
protected function actions(array $form, FormStateInterface $form_state) {
// @todo: This is a workaround by webform for Core issue #2582295
// "Confirmation cancel links are incorrect if installed in a subdirectory".
// Remove after a fix landed there.
// See: https://www.drupal.org/project/drupal/issues/2582295
// See: https://www.drupal.org/project/webform/issues/2899166
$request = $this->getRequest();
$destination = $request->query->get('destination');
if ($destination) {
// Remove subdirectory from destination.
$update_destination = preg_replace('/^' . preg_quote(base_path(), '/') . '/', '/', $destination);
$request->query->set('destination', $update_destination);
$actions = parent::actions($form, $form_state);
$request->query->set('destination', $destination);
return $actions;
}
else {
return parent::actions($form, $form_state);
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$new_form = $this->entity->createDuplicate();
$new_form->set('admin_title', $form_state->getValue('new_admin_title'));
$status = $new_form->save();
if ($status === SAVED_NEW) {
$form_fields = $this->entity->getFormFields();
foreach ($form_fields as $fillpdf_form_field) {
$duplicate_field = $fillpdf_form_field->createDuplicate();
$duplicate_field->set('fillpdf_form', $new_form->id());
$duplicate_field->save();
}
$this->getLogger('fillpdf')->notice('Duplicated FillPDF form %original_id to %new_id.', [
'%original_id' => $this->entity->id(),
'%new_id' => $new_form->id(),
]);
$this->messenger()->addStatus($this->t('FillPDF form has been duplicated.'));
return new RedirectResponse($new_form->toUrl()->toString());
}
}
}
<?php
namespace Drupal\Tests\fillpdf\Functional;
use Drupal\fillpdf\Entity\FillPdfForm;
use Drupal\fillpdf\Entity\FillPdfFormField;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\fillpdf\Traits\TestFillPdfTrait;
use Drupal\Core\Url;
/**
* @coversDefaultClass \Drupal\fillpdf\Form\FillPdfFormDuplicateForm
* @group fillpdf
*/
class FillPdfFormDuplicateFormTest extends BrowserTestBase {
use TestFillPdfTrait;
static public $modules = ['fillpdf_test'];
protected $profile = 'minimal';
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->configureFillPdf();
$this->initializeUser();
}
/**
* Tests the duplicate function.
*/
public function testDuplicateForm() {
$this->uploadTestPdf('fillpdf_test_v3.pdf');
$form_id = $this->getLatestFillPdfForm();
$template_fid = FillPdfForm::load($form_id)->fid->value;
// Verify the FillPdfForm's fields are stored.
$field_ids = \Drupal::entityQuery('fillpdf_form_field')->condition('fillpdf_form', $form_id)->execute();
$this->assertCount(4, $field_ids, "4 FillPdfFormFields have been created.");
// We're now on the edit form. Add an admin title.
$this->assertSession()->pageTextContains('New FillPDF form has been created.');
$admin_title = 'Test';
$this->drupalPostForm(NULL, ['admin_title[0][value]' => $admin_title], 'Save');
$this->assertSession()->pageTextContains("FillPDF Form $admin_title has been updated.");
// Go to the overview form, click duplicate but cancel to come back.
$overview_url = Url::fromRoute('fillpdf.forms_admin');
$this->drupalGet($overview_url);
$this->clickLink('Duplicate');
$this->assertSession()->pageTextContains("Create duplicate of $admin_title?");
$this->assertSession()->fieldValueEquals('new_admin_title', "Duplicate of $admin_title");
$this->clickLink('Cancel');
$this->assertSession()->addressEquals($overview_url);
// Back to the overview form, try again, and this time create a duplicate.
$this->clickLink('Duplicate');
$this->drupalPostForm(NULL, ['new_admin_title' => 'Another test'], 'Save');
$this->assertSession()->pageTextContains('FillPDF form has been duplicated.');
$this->assertSession()->addressEquals(Url::fromRoute('fillpdf.forms_admin'));
// Now verify the FillPdfForm and its fields have actually been duplicated,
// but are using the same template file.
$new_form_id = $this->getLatestFillPdfForm();
$this->assertNotEquals($new_form_id, $form_id);
$field_ids = \Drupal::entityQuery('fillpdf_form_field')->condition('fillpdf_form', $new_form_id)->execute();
foreach ($field_ids as $id) {
$this->assertNotNull(FillPdfFormField::load($id), "The FillPdfFormField #{$id} has ben duplicated.");
}
$this->assertEquals($template_fid, FillPdfForm::load($form_id)->fid->value);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment