Skip to content
Snippets Groups Projects
Commit e07ea8c9 authored by Kevin Kaland's avatar Kevin Kaland
Browse files

Issue #2359213: Port value-replacement (transforms).

Snuck in a couple other fixes.
parent 04cd26a0
No related branches found
No related tags found
No related merge requests found
......@@ -90,3 +90,14 @@ function fillpdf_update_8103() {
$entity->save();
}
}
/**
* Add replacements fields.
*/
function fillpdf_update_8104() {
$edum = \Drupal::entityDefinitionUpdateManager();
$replacements = BaseFieldDefinition::create('string_long')
->setLabel(t('Replace word(s) with correct output values'))
->setDescription(FillPdfAdminFormHelper::getReplacementsDescription());
$edum->installFieldStorageDefinition('replacements', 'fillpdf_form', 'fillpdf_form', $replacements);
}
<?php
/**
* @file
* Contains \Drupal\fillpdf\Component\Helper\FillPdfMappingHelper.
*/
namespace Drupal\fillpdf\Component\Helper;
class FillPdfMappingHelper {
public static function parseReplacements($replacements_string) {
if (empty($replacements_string) !== TRUE) {
$standardized_replacements = str_replace(array("\r\n", "\r"), "\n", $replacements_string);
$lines = explode("\n", $standardized_replacements);
$return = array();
foreach ($lines as $replacement) {
if (!empty($replacement)) {
$split = explode('|', $replacement);
if (count($split) == 2) { // Sometimes it isn't; don't know why.
$return[$split[0]] = preg_replace('|<br />|', '
', $split[1]);
}
}
}
return $return;
}
else {
return array();
}
}
/**
* @param $value
* The value to replace. Must match the key in a replacements field exactly.
* @param $form_replacements
* A list of replacements with form-level priority.
* @param $field_replacements
* A list of replacements with field-level priority. These have precedence.
* @return string $value with any matching replacements applied.
*/
public static function transformString($value, $form_replacements, $field_replacements) {
if (empty($form_replacements) && empty($field_replacements)) {
return $value;
}
elseif (!empty($field_replacements) && isset($field_replacements[$value])) {
return $field_replacements[$value];
}
elseif (!empty($form_replacements) && isset($form_replacements[$value])) {
return $form_replacements[$value];
}
else {
return $value;
}
}
}
<?php
/**
* @file
* Contains \Drupal\fillpdf\Component\Helper\FillPdfMappingHelperInterface.
*/
namespace Drupal\fillpdf\Component\Helper;
interface FillPdfMappingHelperInterface {
}
......@@ -14,11 +14,10 @@ class FillPdf {
if (empty($pdftk_path)) {
$pdftk_path = 'pdftk';
}
$status = NULL;
$process = new Process($pdftk_path);
$process->run();
if (in_array($process->getExitCode(), [126, 127])) {
if (in_array($process->getExitCode(), [126, 127], TRUE)) {
return FALSE;
}
return TRUE;
......
......@@ -10,6 +10,7 @@ use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Utility\Token;
use Drupal\fillpdf\Component\Helper\FillPdfMappingHelper;
use Drupal\fillpdf\Entity\FillPdfForm;
use Drupal\fillpdf\Entity\FillPdfFormField;
use Drupal\fillpdf\FillPdfBackendManager;
......@@ -114,15 +115,29 @@ class HandlePdfController extends ControllerBase {
$fill_pattern = $field->value->value;
$replaced_string = $this->tokenResolver->replace($fill_pattern, $entities);
// Apply field transformations.
// Replace <br /> occurrences with newlines
$replaced_string = preg_replace('|<br />|', '
', $replaced_string);
$form_replacements = FillPdfMappingHelper::parseReplacements($fillpdf_form->replacements->value);
$field_replacements = FillPdfMappingHelper::parseReplacements($field->replacements->value);
$replaced_string = FillPdfMappingHelper::transformString($replaced_string, $form_replacements, $field_replacements);
$mapped_fields[$pdf_key] = $replaced_string;
}
}
$populated_pdf = $backend->populateWithFieldData($fillpdf_form, $field_mapping, $context, $entities);
$title_pattern = $fillpdf_form->title->value;
// Generate the filename of downloaded PDF from title of the PDF set in
// admin/structure/fillpdf/%fid
$context['filename'] = $this->buildFilename($title_pattern, $entities);
$populated_pdf = $backend->populateWithFieldData($fillpdf_form, $field_mapping, $context);
// @todo: When Rules integration ported, emit an event or whatever.
// TODO: figure out what to do about $token_objects. Should I make buildFilename manually re-run everything or just use the final entities passed of each type? Maybe just the latter, since that is what I do in D7. But it wouldn't be that hard to just use whatever helper function I make.
$action_response = $this->handlePopulatedPdf($fillpdf_form, $populated_pdf, $context, []);
return $action_response;
......@@ -152,9 +167,7 @@ class HandlePdfController extends ControllerBase {
$force_download = TRUE;
}
// Generate the filename of downloaded PDF from title of the PDF set in
// admin/structure/fillpdf/%fid
$output_name = $this->buildFilename($fillpdf_form->title->value, $entities);
$output_name = $context['filename'];
// Determine the appropriate action for the PDF.
$destination_path_set = !empty($fillpdf_form->destination_path->value);
......
......@@ -63,9 +63,7 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface {
->setLabel(t('The associated managed file.'))
->setDescription(t('The associated managed file.'));
// @todo: Figure out how to do this the right way...I get a router rebuild error if I use $url_generator->generateFromRoute()
$overview_url = Url::fromUri('base://admin/structure/fillpdf')->toString();
// @todo: what is wrong with the below?
$fields['admin_title'] = BaseFieldDefinition::create('string')
->setLabel(t('Administrative description'))
->setDescription(t('Enter the name of the form here, and it will be shown on the <a href="@overview_url">form overview page</a>. It has no effect on functionality, but it can help you identify which form configuration you want to edit.', ['@overview_url' => $overview_url]))
......@@ -82,12 +80,10 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface {
'weight' => 10,
]);
// @todo: Validate this with a custom constraint or whatever
$fields['default_entity_type'] = BaseFieldDefinition::create('string')
->setLabel(t('Default entity type'))
->setDescription(t('The type of the below entity ID.'));
// @todo: Validate this with a custom constraint, if possible
$fields['default_entity_id'] = BaseFieldDefinition::create('integer')
->setLabel(t('Default entity ID'))
->setDescription(t('The default entity ID to be filled from this FillPDF Form.'))
......@@ -96,7 +92,6 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface {
'weight' => 15,
]);
// @todo: set display options on this
$fields['destination_path'] = BaseFieldDefinition::create('string')
->setLabel(t('Where to save generated PDFs'))
->setDescription(t("<p>By default, filled PDFs are not saved to disk; they are simply sent
......@@ -143,6 +138,15 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface {
],
]);
// Restore database and make this be string_long instead like FillPdfFormField
$fields['replacements'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Change text before sending to PDF (Transform values)'))
->setDescription(FillPdfAdminFormHelper::getReplacementsDescription())
->setDisplayOptions('form', [
'type' => 'string_long',
'weight' => 40,
]);
return $fields;
}
......
......@@ -11,6 +11,7 @@ use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\fillpdf\FillPdfFormFieldInterface;
use Drupal\fillpdf\Service\FillPdfAdminFormHelper;
/**
* Defines the entity for managing PDF fields associated with uploaded FillPDF
......@@ -79,7 +80,6 @@ class FillPdfFormField extends ContentEntityBase implements FillPdfFormFieldInte
'type' => 'string_long',
]);
// @todo: convert meeeeeeee
$fields['value'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Fill pattern'))
->setDescription(t('Text and tokens with which to fill in the PDF.'))
......@@ -94,10 +94,9 @@ class FillPdfFormField extends ContentEntityBase implements FillPdfFormFieldInte
'type' => 'string_long',
]);
// @todo: Can I do better on field type here? Maybe a multi-value string field?
$fields['replacements'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Fill pattern transformations'))
->setDescription(t('Pipe-separated mapping of specific values to replace with other values.'))
->setLabel(t('Change text before sending to PDF (Transform values)'))
->setDescription(FillPdfAdminFormHelper::getReplacementsDescription())
->setDisplayOptions('form', [
'type' => 'string_long',
]);
......
......@@ -141,6 +141,8 @@ class FillPdfFormForm extends ContentEntityForm {
$form['destination_path']['#group'] = 'additional_settings';
$form['scheme']['#group'] = 'additional_settings';
$form['destination_redirect']['#group'] = 'additional_settings';
$form['replacements']['#group'] = 'additional_settings';
$form['replacements']['#weight'] = 1;
$form['fillpdf_fields']['fields'] = FillPdf::embedView('fillpdf_form_fields',
'block_1',
......
......@@ -43,4 +43,15 @@ class FillPdfAdminFormHelper implements FillPdfAdminFormHelperInterface {
];
}
public static function getReplacementsDescription() {
return t('<p>Tokens, such as those from CCK, sometimes output values that need additional
processing prior to being sent to the PDF. A common example is when a key within a CCK <em>Allowed values</em>
configuration does not match the field name or option value in the PDF that you would like to be selected but you
do not want to change the <em>Allowed values</em> key.</p><p>This field will replace any matching values with the
replacements you specify. Specify <strong>one replacement per line</strong> in the format
<em>original value|replacement value</em>. For example, <em>yes|Y</em> will fill the PDF with
<strong><em>Y</em></strong> anywhere that <strong><em>yes</em></strong> would have originally
been used. <p>Note that omitting the <em>replacement value</em> will replace <em>original value</em>
with a blank, essentially erasing it.</p>');
}
}
......@@ -48,7 +48,11 @@ class TokenResolver implements TokenResolverInterface {
}
}
return $this->token->replace($replaced_string, [], ['clear' => TRUE]);
// The entities might not have had values for all the tokens in the pattern.
// Ensure that any remaining tokens are cleared from the string so they
// don't get sent to the PDF.
$clean_replaced_string = $this->token->replace($replaced_string, [], ['clear' => TRUE]);
return $clean_replaced_string;
}
}
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