View source
<?php
namespace Drupal\fillpdf\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\fillpdf\Component\Utility\FillPdf;
use Drupal\fillpdf\FillPdfAdminFormHelperInterface;
use Drupal\fillpdf\FillPdfLinkManipulatorInterface;
use Drupal\fillpdf\InputHelperInterface;
use Drupal\fillpdf\SerializerInterface;
use Drupal\fillpdf\TokenResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FillPdfFormForm extends ContentEntityForm {
const SELECT_MAX = 25;
protected $adminFormHelper;
protected $linkManipulator;
protected $inputHelper;
protected $serializer;
protected $fileSystem;
protected $tokenResolver;
public function __construct(EntityRepositoryInterface $entity_repository, FillPdfAdminFormHelperInterface $admin_form_helper, FillPdfLinkManipulatorInterface $link_manipulator, InputHelperInterface $input_helper, SerializerInterface $fillpdf_serializer, FileSystemInterface $file_system, EntityTypeManager $entity_type_manager, TokenResolverInterface $token_resolver, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->adminFormHelper = $admin_form_helper;
$this->linkManipulator = $link_manipulator;
$this->inputHelper = $input_helper;
$this->serializer = $fillpdf_serializer;
$this->fileSystem = $file_system;
$this->entityTypeManager = $entity_type_manager;
$this->tokenResolver = $token_resolver;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity.repository'), $container
->get('fillpdf.admin_form_helper'), $container
->get('fillpdf.link_manipulator'), $container
->get('fillpdf.input_helper'), $container
->get('fillpdf.serializer'), $container
->get('file_system'), $container
->get('entity_type.manager'), $container
->get('fillpdf.token_resolver'), $container
->get('entity_type.bundle.info'), $container
->get('datetime.time'));
}
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$fillpdf_form = $this->entity;
$form['title']['token_tree'] = $this->adminFormHelper
->getAdminTokenForm();
$stored_default_entity_type = $fillpdf_form
->get('default_entity_type');
$default_entity_type = count($stored_default_entity_type) ? $stored_default_entity_type
->first()->value : NULL;
$form['default_entity_type'] = [
'#type' => 'select',
'#title' => $this
->t('Default entity type'),
'#options' => $this
->getEntityTypeOptions(),
'#empty_option' => $this
->t('- None -'),
'#weight' => 12.5,
'#default_value' => $default_entity_type,
'#ajax' => [
'callback' => '::ajaxUpdateEntityId',
'event' => 'change',
'wrapper' => 'test-entity-wrapper',
'progress' => [
'type' => 'none',
],
],
];
if ($form_state
->isRebuilding()) {
$default_entity_type = $form_state
->getValue('default_entity_type');
$default_entity_id = $form_state
->getValue('default_entity_id');
}
else {
$stored_default_entity_id = $fillpdf_form
->get('default_entity_id');
$default_entity_id = count($stored_default_entity_id) ? $stored_default_entity_id
->first()->value : NULL;
}
$form['default_entity_id'] = [
'#title' => $this
->t('Default entity'),
'#target_type' => $default_entity_type,
'#weight' => 13,
'#prefix' => '<div id="test-entity-wrapper">',
'#suffix' => '</div>',
'#ajax' => [
'callback' => '::ajaxUpdateEntityId',
'event' => 'autocompleteclose autocompletechange',
'wrapper' => 'test-entity-wrapper',
'progress' => [
'type' => 'none',
],
],
];
if ($default_entity_type) {
$storage = $this->entityTypeManager
->getStorage($default_entity_type);
$default_entity = $default_entity_id ? $storage
->load($default_entity_id) : NULL;
if (!empty($default_entity)) {
$description = Link::fromTextAndUrl($this
->t('Download this PDF template populated with data from the @type %label (@id).', [
'@type' => $default_entity_type,
'%label' => $default_entity
->label(),
'@id' => $default_entity_id,
]), $this->linkManipulator
->generateLink([
'fid' => $this->entity
->id(),
'entity_ids' => [
$default_entity_type => [
$default_entity_id,
],
],
]))
->toString();
}
$entity_ids = $storage
->getQuery()
->range(0, self::SELECT_MAX + 1)
->execute();
if (count($entity_ids) > self::SELECT_MAX) {
if (!isset($description)) {
$description = $this
->t('Enter the title of a %type to test populating the PDF template.', [
'%type' => $default_entity_type,
]);
}
$form['default_entity_id'] += [
'#type' => 'entity_autocomplete',
'#default_value' => $default_entity,
'#description' => $description,
];
}
else {
$options = [];
foreach ($storage
->loadMultiple($entity_ids) as $id => $entity) {
$options[$id] = $entity
->label();
}
if (!isset($description)) {
$description = $this
->t('Choose a %type to test populating the PDF template.', [
'%type' => $default_entity_type,
]);
}
$form['default_entity_id'] += [
'#type' => 'select',
'#options' => $options,
'#empty_option' => $this
->t('- None -'),
'#default_value' => $default_entity_id,
'#description' => $description,
];
}
}
else {
$form['default_entity_id'] += [
'#type' => 'hidden',
];
}
$fid = $fillpdf_form
->id();
$file_entity = File::load($fillpdf_form
->get('file')
->first()->target_id);
$pdf_info_weight = 0;
$form['pdf_info'] = [
'#type' => 'fieldset',
'#title' => $this
->t('PDF form information'),
'#weight' => $form['default_entity_type']['#weight'] + 1,
'submitted_pdf' => [
'#type' => 'item',
'#title' => $this
->t('Uploaded PDF'),
'#description' => $file_entity
->getFileUri(),
'#weight' => $pdf_info_weight++,
],
];
$upload_location = FillPdf::buildFileUri($this
->config('fillpdf.settings')
->get('template_scheme'), 'fillpdf');
if (!$this->fileSystem
->prepareDirectory($upload_location, FileSystemInterface::CREATE_DIRECTORY + FileSystemInterface::MODIFY_PERMISSIONS)) {
$this
->messenger()
->addError($this
->t('The directory %directory does not exist or is not writable. Please check permissions.', [
'%directory' => $this->fileSystem
->realpath($upload_location),
]));
}
else {
$form['pdf_info']['upload_pdf'] = [
'#type' => 'managed_file',
'#title' => $this
->t('Update PDF template'),
'#accept' => 'application/pdf',
'#upload_validators' => [
'file_validate_extensions' => [
'pdf',
],
],
'#upload_location' => $upload_location,
'#description' => $this
->t('Update the PDF file used as template by this form.'),
'#weight' => $pdf_info_weight++,
];
}
$form['pdf_info']['sample_populate'] = [
'#type' => 'item',
'#title' => $this
->t('Sample PDF'),
'#description' => $this
->t('@link<br />If you have set a custom path on this PDF, the sample will be saved there silently.', [
'@link' => Link::fromTextAndUrl($this
->t('See which fields are which in this PDF.'), $this->linkManipulator
->generateLink([
'fid' => $fid,
'sample' => TRUE,
]))
->toString(),
]),
'#weight' => $pdf_info_weight++,
];
$form['pdf_info']['form_id'] = [
'#type' => 'item',
'#title' => $this
->t('Form info'),
'#description' => $this
->t('Form ID: [@fid]. Populate this form with entity IDs, such as %path . For more usage examples, see <a href="@documentation">the documentation</a>.', [
'@fid' => $fid,
'%path' => "/fillpdf?fid={$fid}&entity_ids[]=node:10&entity_ids[]=user:7",
'@documentation' => 'https://www.drupal.org/docs/8/modules/fillpdf/usage#makelink',
]),
'#weight' => $pdf_info_weight,
];
$available_schemes = $form['scheme']['widget']['#options'];
if (count($available_schemes) == 1) {
$form['scheme']['#type'] = 'hidden';
$form['destination_path']['#type'] = 'hidden';
$form['destination_redirect']['#type'] = 'hidden';
}
else {
$form['storage_download'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Storage and download'),
'#weight' => $form['pdf_info']['#weight'] + 1,
'#open' => TRUE,
'#attached' => [
'library' => [
'fillpdf/form',
],
],
];
$form['storage_download']['storage'] = [
'#type' => 'container',
];
$states_no_scheme = [
':input[name="scheme"]' => [
'value' => '_none',
],
];
$form['scheme']['#group'] = 'storage';
$form['destination_path']['#group'] = 'storage';
$form['destination_path']['widget']['0']['value']['#field_prefix'] = 'fillpdf/';
$form['destination_path']['#states'] = [
'invisible' => $states_no_scheme,
];
$form['destination_path']['token_tree'] = $this->adminFormHelper
->getAdminTokenForm();
$description = $this
->t('If filled PDFs should be automatically saved to disk, chose a file storage');
$description .= isset($available_schemes['public']) ? '; ' . $this
->t('note that %public storage does not provide any access control.', [
'%public' => 'public://',
]) : '.';
$description .= ' ' . $this
->t('Otherwise, filled PDFs are sent to the browser for download.');
$form['storage_download']['storage']['description_scheme_none'] = [
'#type' => 'item',
'#description' => $description,
'#weight' => 22,
'#states' => [
'visible' => $states_no_scheme,
],
];
$form['storage_download']['storage']['description_scheme_set'] = [
'#type' => 'item',
'#description' => $this
->t('As PDFs are saved to disk, make sure you include the <em>&download=1</em> flag to send them to the browser as well.'),
'#weight' => 23,
'#states' => [
'invisible' => $states_no_scheme,
],
];
$form['destination_redirect']['#group'] = 'storage_download';
$form['destination_redirect']['#states'] = [
'invisible' => $states_no_scheme,
];
}
$form['additional_settings'] = [
'#type' => 'details',
'#title' => $this
->t('Additional settings'),
'#weight' => $form['pdf_info']['#weight'] + 1,
'#open' => $fillpdf_form && (!empty($fillpdf_form->replacements->value) || !empty($fillpdf_form->pdftk_encryption->value) || !empty($fillpdf_form->permissions->value) || !empty($fillpdf_form->owner_password->value) || !empty($fillpdf_form->user_password->value)),
];
$form['replacements']['#group'] = 'additional_settings';
$form['additional_settings']['security'] = [
'#name' => 'security',
'#type' => 'details',
'#title' => t('PDF Security (currently only works with pdftk)'),
'#weight' => 100,
'#open' => $fillpdf_form && (!empty($fillpdf_form->pdftk_encryption->value) || !empty($fillpdf_form->permissions->value) || !empty($fillpdf_form->owner_password->value) || !empty($fillpdf_form->user_password->value)),
];
$form['pdftk_encryption']['#group'] = 'security';
$form['permissions']['#group'] = 'security';
$form['owner_password']['#group'] = 'security';
$form['user_password']['#group'] = 'security';
$form['fillpdf_fields']['fields'] = FillPdf::embedView('fillpdf_form_fields', 'block_1', $fillpdf_form
->id());
$form['fillpdf_fields']['#weight'] = 100;
$form['export_fields'] = [
'#prefix' => '<div>',
'#markup' => Link::fromTextAndUrl($this
->t('Export these field mappings'), Url::fromRoute('entity.fillpdf_form.export_form', [
'fillpdf_form' => $fillpdf_form
->id(),
]))
->toString(),
'#suffix' => '</div>',
'#weight' => 100,
];
$form['import_fields'] = [
'#prefix' => '<div>',
'#markup' => Link::fromTextAndUrl($this
->t('Import a previous export into this PDF'), Url::fromRoute('entity.fillpdf_form.import_form', [
'fillpdf_form' => $fillpdf_form
->id(),
]))
->toString(),
'#suffix' => '</div>',
'#weight' => 100,
];
return $form;
}
protected function getEntityTypeOptions() {
$token_info = $this->tokenResolver
->getTokenService()
->getInfo();
$entity_mapper = $this->tokenResolver
->getEntityMapper();
$all_tokens = $token_info['types'];
$options = [];
foreach ($this->entityTypeManager
->getDefinitions() as $entity_type => $definition) {
$token_type = $entity_mapper
->getTokenTypeForEntityType($entity_type, FALSE);
if (!$token_type || empty($all_tokens[$token_type])) {
continue;
}
$label = $definition
->getLabel();
$group_label = (string) $definition
->getGroupLabel();
$options[$group_label][$entity_type] = "{$entity_type} ({$label})";
}
foreach ($options as &$group_options) {
array_multisort($group_options, SORT_ASC, SORT_NATURAL);
}
$content = (string) $this
->t('Content', [], [
'context' => 'Entity type group',
]);
return [
$content => $options[$content],
] + $options;
}
public function ajaxUpdateEntityId(array &$form, FormStateInterface $form_state) {
$element = $form['default_entity_id'];
$triggering_element = reset($form_state
->getTriggeringElement()['#array_parents']);
if ($triggering_element == 'default_entity_type') {
unset($element['#value']);
}
return $element;
}
protected function actions(array $form, FormStateInterface $form_state) {
$actions = parent::actions($form, $form_state);
$route_info = $actions['delete']['#url'];
$route_info
->setOption('query', []);
$actions['delete']['#url'] = $route_info;
return $actions;
}
public function save(array $form, FormStateInterface $form_state) {
$entity = $this
->getEntity();
$this
->messenger()
->addStatus($this
->t('FillPDF Form %link has been updated.', [
'%link' => $entity
->toLink()
->toString(),
]));
if ($form_state
->getValue('upload_pdf')) {
$existing_fields = $entity
->getFormFields();
$new_file = File::load($form_state
->getValue('upload_pdf')['0']);
$new_file
->setPermanent();
$new_file
->save();
$entity->file = $new_file;
$new_fields = $this->inputHelper
->parseFields($entity);
$non_matching_fields = $this->serializer
->importFormFields($existing_fields, $new_fields, FALSE);
foreach ($new_fields as $field) {
$field
->save();
}
foreach ($existing_fields as $field) {
$field
->delete();
}
if (count($existing_fields)) {
$this
->messenger()
->addStatus($this
->t('Your previous field mappings have been transferred to the new PDF template you uploaded.'));
}
if (count($non_matching_fields)) {
$message = [
'#prefix' => $this
->t("These keys couldn't be found in the new PDF:"),
[
'#theme' => 'item_list',
'#items' => array_keys($non_matching_fields),
],
];
$this
->messenger()
->addWarning(\Drupal::service('renderer')
->render($message));
}
$this
->messenger()
->addStatus($this
->t('You might also want to update the <em>Filename pattern</em> field; this has not been changed.'));
}
$default_entity_type = $form_state
->getValue('default_entity_type');
$default_entity_id = $default_entity_type == $form['default_entity_id']['#target_type'] ? $form_state
->getValue('default_entity_id') : NULL;
$entity
->set('default_entity_type', $default_entity_type)
->set('default_entity_id', $default_entity_id)
->save();
}
}