diff --git a/config/install/fillpdf.settings.yml b/config/install/fillpdf.settings.yml index 22e2228fd7db28c5d28f762307cb0f85dde5369a..b8819aba58411d26b4f57df812bf88abb0303257 100644 --- a/config/install/fillpdf.settings.yml +++ b/config/install/fillpdf.settings.yml @@ -1,3 +1,7 @@ +allowed_schemes: + - private +template_scheme: '' + remote_protocol: https # Should not contain a protocol. That's what the above is for. diff --git a/config/schema/fillpdf.schema.yml b/config/schema/fillpdf.schema.yml index e02dc285bce06d96b668fd3c49e2da72242687e7..375a721d71f2d13d82c3f291f4e392512c585fa6 100644 --- a/config/schema/fillpdf.schema.yml +++ b/config/schema/fillpdf.schema.yml @@ -10,9 +10,15 @@ fillpdf.settings: remote_endpoint: type: string label: 'FillPDF Service endpoint URL without protocol' - scheme: + allowed_schemes: + type: sequence + label: 'Allowed storage schemes' + sequence: + type: string + label: 'Allowed storage scheme' + template_scheme: type: string - label: 'Filesystem scheme for uploads' + label: 'Template storage scheme' local_service_endpoint: type: string label: 'Local FillPDF PDF API endpoint' diff --git a/css/fillpdf.form.css b/css/fillpdf.form.css new file mode 100644 index 0000000000000000000000000000000000000000..6ffcbeb596a833936633578451ad1a30a9f39c26 --- /dev/null +++ b/css/fillpdf.form.css @@ -0,0 +1,12 @@ +#edit-storage .form-wrapper { + display: inline-block; + vertical-align: top; +} + +#edit-storage .form-item { + margin-bottom: 0; +} + +#edit-scheme-wrapper { + padding-right: 1em; +} diff --git a/fillpdf.install b/fillpdf.install index 85fdba988de4a53757d675c53ab52525417e58bc..f32b4b30e1b7a01eadce40084c4aba2e6c589490 100644 --- a/fillpdf.install +++ b/fillpdf.install @@ -1,12 +1,16 @@ <?php + /** * @file * Install functions for FillPDF. */ -use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\fillpdf\Entity\FillPdfForm; use Drupal\fillpdf\Service\FillPdfAdminFormHelper; +use Drupal\Core\Link; /** * Add scheme field to FillPdfForm. @@ -127,3 +131,53 @@ function fillpdf_update_8106() { return t('Default FillPDF Service endpoint updated to fillpdf.io/xmlrpc.php.'); } + +/** + * Update storage scheme configuration. + */ +function fillpdf_update_8107() { + $config = \Drupal::configFactory()->getEditable('fillpdf.settings'); + + // Rename the 'scheme' key to 'template_scheme'. + if ($config->get('template_scheme') === NULL) { + $config->set('template_scheme', $config->get('scheme')); + } + $config->clear('scheme'); + + // Initialize the new 'allowed_schemes' key with all currently available + // storage schemes. + if ($config->get('allowed_schemes') === NULL) { + $available_schemes = array_keys(\Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)); + $config->set('allowed_schemes', $available_schemes)->save(); + } + $config->save(); + + return new TranslatableMarkup('All currently available file storage schemes were added to FillPDF configuration. Please review at %link.', [ + '%link' => Link::createFromRoute(new TranslatableMarkup('FillPDF settings'), 'fillpdf.forms_admin'), + ]); +} + +/** + * Update stored FillPDF forms to the changed storage logic. + */ +function fillpdf_update_8108() { + $fillpdf_forms = FillPdfForm::loadMultiple(); + + // Previously, populated PDF files were stored in the filesystem, if a + // 'destination_path' is set. Now it is stored, if 'scheme' is set, which + // previously was always the case. So for preexisting FillPdfForms without + // a 'destination_path', we need to unset 'scheme' to ensure nothing changes. + $updated_ids = []; + foreach ($fillpdf_forms as $id => $form) { + if (empty($form->get('destination_path'))) { + $status = $form->set('scheme', NULL)->save(); + if ($status === SAVED_UPDATED) { + $updated_ids[] = $id; + } + } + } + + return new TranslatableMarkup('The following FillPDF forms were updated: %list.', [ + '%list' => implode(', ', $updated_ids), + ]); +} diff --git a/fillpdf.libraries.yml b/fillpdf.libraries.yml new file mode 100644 index 0000000000000000000000000000000000000000..9fd14fc9dfbaf51bd0b4079fa95b4fabefdda702 --- /dev/null +++ b/fillpdf.libraries.yml @@ -0,0 +1,5 @@ +form: + version: VERSION + css: + theme: + css/fillpdf.form.css: {} diff --git a/src/Controller/HandlePdfController.php b/src/Controller/HandlePdfController.php index 99d9b4be4b167f59064ad84d8a68765da3b73688..de76bae17cd5f42a2044681b3c0720bdb3d91d4d 100644 --- a/src/Controller/HandlePdfController.php +++ b/src/Controller/HandlePdfController.php @@ -298,14 +298,16 @@ class HandlePdfController extends ControllerBase { // Determine the appropriate action for the PDF. $scheme = $fillpdf_form->getStorageScheme(); - $available_schemes = array_keys(\Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)); + $is_available = array_key_exists($scheme, \Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)); + $is_allowed = in_array($scheme, \Drupal::config('fillpdf.settings')->get('allowed_schemes') ?: []); - // The configured file storage scheme is no longer available. - if (!empty($scheme) && !in_array($scheme, $available_schemes)) { - $id = $fillpdf_form->id(); - // @todo: We can simpify this once an admin_title is #required, + if (empty($scheme)) { + $action_plugin_id = 'download'; + } + elseif (!$is_available || !$is_allowed) { + // @todo: We don't need the ID once an admin_title is #required, // see https://www.drupal.org/project/fillpdf/issues/3040776. - $label = $fillpdf_form->label() . " ({$id})"; + $label = $fillpdf_form->label() . " ({$fillpdf_form->id()})"; $this->getLogger('fillpdf')->critical('Saving a generated PDF file in unavailable storage scheme %scheme failed.', [ '%scheme' => "$scheme://", ]); @@ -315,17 +317,13 @@ class HandlePdfController extends ControllerBase { '@link' => Link::fromTextAndUrl($label, $fillpdf_form->toUrl())->toString(), ])); } - // Unset the scheme to make sure the file is only sent to the browser. - $scheme = NULL; + // Make sure the file is only sent to the browser. + $action_plugin_id = 'download'; } - - if (!empty($scheme) && !empty($fillpdf_form->getStoragePath())) { + else { $redirect = !empty($fillpdf_form->destination_redirect->value); $action_plugin_id = $redirect ? 'redirect' : 'save'; } - else { - $action_plugin_id = 'download'; - } // @todo: Remove in FillPDF 5.x. The filename is not part of the context and // is separately available anyway. diff --git a/src/Entity/FillPdfForm.php b/src/Entity/FillPdfForm.php index d6744653ff6339d7c6c79298b617640b7d450983..5fb5c0d234db4c2fa04146e9cb261189b47d253c 100644 --- a/src/Entity/FillPdfForm.php +++ b/src/Entity/FillPdfForm.php @@ -6,6 +6,8 @@ use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Drupal\fillpdf\FillPdfFormInterface; use Drupal\fillpdf\Service\FillPdfAdminFormHelper; @@ -92,41 +94,32 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface { $fields['default_entity_id'] = BaseFieldDefinition::create('integer'); $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 - directly to the browser for download. Enter a path here to change this behavior (tokens allowed). - <strong>Warning! Unless you include the &download=1 flag in the FillPDF URL, PDFs will only - be saved to disk <em>and won't</em> be sent to the browser as well.</strong></p><p>The path - you specify must be in the following format:<br /> - <ul> - <li><code>path/to/directory</code> (path will be treated as relative to - your <em>fillpdf</em> files subdirectory)</li> - filesystem)</li> - </ul> - Note that you are responsible for ensuring that the user under which PHP is running can write to this path. Do not include a trailing slash.</p>")) + ->setLabel(t('Destination path')) + ->setDescription(new TranslatableMarkup('You may specify a subdirectory for storing filled PDFs. This field supports tokens.')) ->setDisplayOptions('form', [ - 'type' => 'string', - 'weight' => 20, + 'type' => 'string_textfield', + 'weight' => 21, + 'settings' => [ + 'size' => 38, + ], ]); // @todo: add post_save_redirect field for where to send the browser by default after they generate a PDF $fields['scheme'] = BaseFieldDefinition::create('list_string') - ->setLabel('Storage system for generated PDFs') - ->setDescription(t('This setting is used as the storage/download method for generated PDFs. The use of public files is more efficient, but does not provide any access control. Changing this setting will require you to migrate associated files and data yourself and is not recommended after you have uploaded a template.')) + ->setLabel('File storage') ->setSettings([ - 'allowed_values_function' => [get_called_class(), 'getSchemeAllowedValues'], + 'allowed_values_function' => [get_called_class(), 'getStorageSchemeOptions'], ]) - ->setDefaultValueCallback(get_called_class() . '::getSchemeDefaultValue') - ->setRequired(TRUE) + ->setDefaultValueCallback(static::class . '::getStorageSchemeDefault') ->setDisplayOptions('form', [ - 'type' => 'options_buttons', - 'weight' => 25, + 'type' => 'options_select', + 'weight' => 20, ]); $fields['destination_redirect'] = BaseFieldDefinition::create('boolean') ->setLabel(t('Redirect browser directly to saved PDF')) - ->setDescription(t("<strong>This setting is applicable only if <em>Where to save generated PDFs</em> is set.</strong> Instead of redirecting your visitors to the front page, it will redirect them directly to the PDF. However, if you pass Drupal's <em>destination</em> query string parameter, that will override this setting.")) + ->setDescription(t("Instead of redirecting your visitors to the front page, this will redirect them directly to the PDF. However, if you pass Drupal's <em>destination</em> query string parameter, that will override this setting.")) ->setDisplayOptions('form', [ 'type' => 'boolean_checkbox', 'weight' => 30, @@ -196,11 +189,15 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface { * * @see ::baseFieldDefinitions() * - * @return array - * Stream wrapper descriptions, keyed by scheme. + * @return string[] + * Associative array of storage scheme descriptions, keyed by the scheme. */ - public static function getSchemeAllowedValues() { - return \Drupal::service('fillpdf.admin_form_helper')->schemeOptions(); + public static function getStorageSchemeOptions() { + $options = []; + foreach (self::getAllowedStorageSchemes() as $scheme) { + $options[$scheme] = $scheme . '://'; + } + return $options; } /** @@ -209,10 +206,23 @@ class FillPdfForm extends ContentEntityBase implements FillPdfFormInterface { * @see ::baseFieldDefinitions() * * @return string - * The system's default scheme. + * The initial default storage scheme. + */ + public static function getStorageSchemeDefault() { + $allowed = self::getAllowedStorageSchemes(); + return array_key_exists('private', $allowed) ? 'private' : key($allowed); + } + + /** + * Gets a list of all storage schemes that are both available and allowed. + * + * @return string[] + * List of storage schemes that are both available and allowed. */ - public static function getSchemeDefaultValue() { - return \Drupal::config('system.file')->get('default_scheme'); + protected static function getAllowedStorageSchemes() { + $available = array_keys(\Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)); + $allowed = \Drupal::config('fillpdf.settings')->get('allowed_schemes') ?: []; + return array_intersect($available, $allowed); } } diff --git a/src/FillPdfAdminFormHelperInterface.php b/src/FillPdfAdminFormHelperInterface.php index 745004f8902f0959a64bd1656dfa3e5364aec3e3..7a94166c47b3e3ca584bdc74844943623ae05c33 100644 --- a/src/FillPdfAdminFormHelperInterface.php +++ b/src/FillPdfAdminFormHelperInterface.php @@ -21,14 +21,17 @@ interface FillPdfAdminFormHelperInterface { public function getAdminTokenForm($token_types = 'all'); /** - * Returns acceptable file scheme options for use with FAPI radio buttons. + * Returns available file storage options for use with FAPI radio buttons. * * Any visible, writeable wrapper can potentially be used. * + * @param array $label_templates + * (optional) Associative array of label templates keyed by scheme name. + * * @return array * Stream wrapper descriptions, keyed by scheme. */ - public function schemeOptions(); + public function schemeOptions(array $label_templates = []); /** * Returns all FillPdfForms with template PDFs stored in a particular scheme. diff --git a/src/Form/FillPdfFormForm.php b/src/Form/FillPdfFormForm.php index 1844464174c89484711b45ac6d85b7b789d9d04f..02d64dbfe1c87fc953bf2c4bf25cb8abb825fd8e 100644 --- a/src/Form/FillPdfFormForm.php +++ b/src/Form/FillPdfFormForm.php @@ -158,9 +158,9 @@ class FillPdfFormForm extends ContentEntityForm { ], ]; - $is_ajax = $form_state->isRebuilding(); - - if ($is_ajax) { + // On AJAX-triggered rebuild, work with the user input instead of previously + // stored values. + if ($form_state->isRebuilding()) { $default_entity_type = $form_state->getValue('default_entity_type'); $default_entity_id = $form_state->getValue('default_entity_id'); } @@ -169,6 +169,7 @@ class FillPdfFormForm extends ContentEntityForm { $default_entity_id = count($stored_default_entity_id) ? $stored_default_entity_id->first()->value : NULL; } + // If a default entity type is set, allow selecting a default entity, too. if ($default_entity_type) { $default_entity = $default_entity_id ? $this->entityTypeManager->getStorage($default_entity_type)->load($default_entity_id) : NULL; @@ -205,9 +206,10 @@ class FillPdfFormForm extends ContentEntityForm { 'event' => 'autocompleteclose autocompletechange', 'wrapper' => 'test-entity-wrapper', 'progress' => ['type' => 'none'], - ] + ], ]; } + // No default entity type set, so just provide a wrapper for AJAX replace. else { $form['default_entity_id'] = [ '#type' => 'hidden', @@ -234,7 +236,7 @@ class FillPdfFormForm extends ContentEntityForm { ], ]; - $upload_location = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('scheme'), 'fillpdf'); + $upload_location = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('template_scheme'), 'fillpdf'); if (!file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY + FILE_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), @@ -276,22 +278,76 @@ class FillPdfFormForm extends ContentEntityForm { '#weight' => $pdf_info_weight, ]; + $available_schemes = $form['scheme']['widget']['#options']; + // If only one option is available, this is 'none', so there's nothing to + // chose. + if (count($available_schemes) == 1) { + $form['scheme']['#type'] = 'hidden'; + $form['destination_path']['#type'] = 'hidden'; + $form['destination_redirect']['#type'] = 'hidden'; + } + // Otherwise show the 'Storage and download' section. + 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', + ]; + + // @todo: Check for empty value after Core issue is fixed. + // See: https://www.drupal.org/project/drupal/issues/1585930 + $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, + ]; + } - $additional_setting_set = $entity->destination_path->value || $entity->destination_redirect->value; $form['additional_settings'] = [ '#type' => 'details', '#title' => $this->t('Additional settings'), '#weight' => $form['pdf_info']['#weight'] + 1, - '#open' => $additional_setting_set, ]; - - $form['destination_path']['#group'] = 'additional_settings'; - $form['destination_path']['token_tree'] = $this->adminFormHelper->getAdminTokenForm([$entity->default_entity_type->value]); - - $form['scheme']['#group'] = 'additional_settings'; - $form['destination_redirect']['#group'] = 'additional_settings'; $form['replacements']['#group'] = 'additional_settings'; - $form['replacements']['#weight'] = 1; // @todo: Add a button to let them attempt re-parsing if it failed. $form['fillpdf_fields']['fields'] = FillPdf::embedView('fillpdf_form_fields', diff --git a/src/Form/FillPdfOverviewForm.php b/src/Form/FillPdfOverviewForm.php index e59969d8a6c64ce556393c5394a78cca2e0f7576..360825e41b74ef59d2c3bddfce816cbb1327a486 100644 --- a/src/Form/FillPdfOverviewForm.php +++ b/src/Form/FillPdfOverviewForm.php @@ -141,7 +141,7 @@ class FillPdfOverviewForm extends FillPdfAdminFormBase { return $form; } - $upload_location = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('scheme'), 'fillpdf'); + $upload_location = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('template_scheme'), 'fillpdf'); if (!file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY + FILE_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), diff --git a/src/Form/FillPdfSettingsForm.php b/src/Form/FillPdfSettingsForm.php index c12f9094fb0cb72a9f00c239a1b48bfa59162879..3b184c3850f8ba6de27adbe0932eb254a673fc51 100644 --- a/src/Form/FillPdfSettingsForm.php +++ b/src/Form/FillPdfSettingsForm.php @@ -116,19 +116,40 @@ class FillPdfSettingsForm extends ConfigFormBase { $config = $this->config('fillpdf.settings'); - $config_scheme = $config->get('scheme'); - $schemes = $this->adminFormHelper->schemeOptions(); + // Get available scheme options. + $scheme_options = $this->adminFormHelper->schemeOptions([ + 'public' => $this->t('@scheme (discouraged)'), + 'private' => $this->t('@scheme (recommended)'), + ]); + $form['allowed_schemes'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Allowed file storages'), + '#default_value' => array_intersect(array_keys($scheme_options), $config->get('allowed_schemes')), + '#options' => $scheme_options, + '#description' => $this->t("You may choose one or more file storages to be available for storing generated PDF files with actual entity data; note that %public does not provide any access control.<br />If you don't choose any file storage, generated PDFs may only be sent to the browser instead of being stored.", [ + '%public' => $this->t('Public files'), + ]), + ]; + $form['advanced_storage'] = [ + '#type' => 'details', + '#title' => $this->t('Advanced storage settings'), + ]; + $file_default_scheme = file_default_scheme(); + $template_scheme_options = $this->adminFormHelper->schemeOptions([ + $file_default_scheme => $this->t('@scheme (site default)'), + ]); + $template_scheme = $config->get('template_scheme'); // Set an error if the previously configured scheme doesn't exist anymore. - if ($config_scheme && !array_key_exists($config_scheme, $schemes)) { - $error_message = $this->t('Your previously used file scheme %previous_scheme is no longer available on this Drupal site, see the %system_settings. Please reset your default to an existing file scheme.', [ - '%previous_scheme' => $config_scheme . '://', + if ($template_scheme && !array_key_exists($template_scheme, $template_scheme_options)) { + $error_message = $this->t('Your previously used file storage %previous_scheme is no longer available on this Drupal site, see the %system_settings. Please reset your default to an existing file storage.', [ + '%previous_scheme' => $template_scheme . '://', '%system_settings' => Link::createFromRoute($this->t('File system settings'), 'system.file_system_settings')->toString(), ]); // @todo: It would be helpful if we could use EntityQuery instead, see // https://www.drupal.org/project/fillpdf/issues/3043508. - $map = $this->adminFormHelper->getFormsByTemplateScheme($config_scheme); + $map = $this->adminFormHelper->getFormsByTemplateScheme($template_scheme); if ($count = count($map)) { $forms = FillPdfForm::loadMultiple(array_keys($map)); $items = []; @@ -150,15 +171,19 @@ class FillPdfSettingsForm extends ConfigFormBase { } $this->messenger()->addError(new FormattableMarkup($error_message, [])); - $this->logger('fillpdf')->critical('File scheme %previous_scheme is no longer available.' . $count ? " $count FillPDF forms are defunct." : ''); + $this->logger('fillpdf')->critical('File storage %previous_scheme is no longer available.' . $count ? " $count FillPDF forms are defunct." : '', [ + '%previous_scheme' => $template_scheme . '://', + ]); } - $form['scheme'] = [ + $form['advanced_storage']['template_scheme'] = [ '#type' => 'radios', - '#title' => $this->t('Template download method'), - '#default_value' => array_key_exists($config_scheme, $schemes) ? $config_scheme : $this->config('system.file')->get('default_scheme'), - '#options' => $schemes, - '#description' => $this->t('This setting is used as the download method for uploaded templates. The use of public files is more efficient, but does not provide any access control. Changing this setting will require you to migrate associated files and data yourself and is not recommended after you have uploaded a template.'), + '#title' => $this->t('Template storage'), + '#default_value' => array_key_exists($template_scheme, $template_scheme_options) ? $template_scheme : $file_default_scheme, + '#options' => $template_scheme_options, + '#description' => $this->t('This setting is used as the storage for uploaded templates; note that the use of %public is more efficient, but does not provide any access control.<br />Changing this setting will require you to migrate associated files and data yourself and is not recommended after you have uploaded a template.', [ + '%public' => t('Public files'), + ]), ]; $form['backend'] = [ @@ -292,12 +317,16 @@ class FillPdfSettingsForm extends ConfigFormBase { break; } - $uri = FillPdf::buildFileUri($form_state->getValue('scheme'), 'fillpdf'); - if (!file_prepare_directory($uri, FILE_CREATE_DIRECTORY + FILE_MODIFY_PERMISSIONS)) { - $error_message = $this->t('Could not automatically create the subdirectory %directory. Please check permissions before trying again.', [ - '%directory' => $this->fileSystem->realpath($uri), - ]); - $form_state->setErrorByName('scheme', $error_message); + $template_scheme = $form_state->getValue('template_scheme'); + $schemes_to_prepare = array_filter($form_state->getValue('allowed_schemes')) + [$template_scheme => $template_scheme]; + foreach ($schemes_to_prepare as $scheme) { + $uri = FillPdf::buildFileUri($scheme, 'fillpdf'); + if (!file_prepare_directory($uri, FILE_CREATE_DIRECTORY + FILE_MODIFY_PERMISSIONS)) { + $error_message = $this->t('Could not automatically create the subdirectory %directory. Please check permissions before trying again.', [ + '%directory' => $this->fileSystem->realpath($uri), + ]); + $form_state->setErrorByName('template_scheme', $error_message); + } } } @@ -309,7 +338,8 @@ class FillPdfSettingsForm extends ConfigFormBase { $values = $form_state->getValues(); $config = $this->config('fillpdf.settings'); - $config->set('scheme', $values['scheme']) + $config->set('allowed_schemes', array_keys(array_filter($values['allowed_schemes']))) + ->set('template_scheme', $values['template_scheme']) ->set('backend', $values['backend']); switch ($values['backend']) { diff --git a/src/Service/FillPdfAdminFormHelper.php b/src/Service/FillPdfAdminFormHelper.php index 9fbbd060206cc558304101aad490485cf2760f35..d11f8e21afd14f27d51d464ad1987178f41ef5cf 100644 --- a/src/Service/FillPdfAdminFormHelper.php +++ b/src/Service/FillPdfAdminFormHelper.php @@ -8,6 +8,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\fillpdf\FillPdfAdminFormHelperInterface; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\StringTranslation\TranslatableMarkup; /** @@ -82,20 +83,15 @@ class FillPdfAdminFormHelper implements FillPdfAdminFormHelperInterface { /** * {@inheritdoc} */ - public function schemeOptions() { - $site_default = $this->configFactory->get('system.file')->get('default_scheme'); - $streams = $this->streamWrapperManager; + public function schemeOptions(array $label_templates = []) { + $stream_wrapper_manager = $this->streamWrapperManager; $options = []; - foreach (array_keys($streams->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)) as $scheme) { - $name = $streams->getViaScheme($scheme)->getName(); - $description = $streams->getViaScheme($scheme)->getDescription(); - $string = '<strong>' . $name . '</strong>'; - if ($scheme == $site_default) { - $string .= ' (' . new TranslatableMarkup('site default') . ')'; - } - $string .= ': ' . $description; - $options[$scheme] = $string; + foreach (array_keys($stream_wrapper_manager->getWrappers(StreamWrapperInterface::WRITE_VISIBLE)) as $scheme) { + $label_template = array_key_exists($scheme, $label_templates) ? $label_templates[$scheme] : '@scheme'; + $options[$scheme] = new FormattableMarkup($label_template, [ + '@scheme' => new FormattableMarkup("<strong>@label</strong>", ['@label' => $stream_wrapper_manager->getViaScheme($scheme)->getName()]), + ]) . ': ' . $stream_wrapper_manager->getViaScheme($scheme)->getDescription(); } return $options; diff --git a/tests/src/Functional/FillPdfFormDeleteFormTest.php b/tests/src/Functional/FillPdfFormDeleteFormTest.php index c756059d0b6ffff8e027e38a799c254f87facbc1..e13436ce5e371ebfa192850c5f29e70063f930e6 100644 --- a/tests/src/Functional/FillPdfFormDeleteFormTest.php +++ b/tests/src/Functional/FillPdfFormDeleteFormTest.php @@ -25,7 +25,7 @@ class FillPdfFormDeleteFormTest extends BrowserTestBase { protected function setUp() { parent::setUp(); - $this->configureBackend(); + $this->configureFillPdf(); $this->initializeUser(); } diff --git a/tests/src/Functional/FillPdfFormFormTest.php b/tests/src/Functional/FillPdfFormFormTest.php index cc370cad2239b273677089a070400f558993a77c..193d9b7fc8ae670cdec45755b4a73099b96681bc 100644 --- a/tests/src/Functional/FillPdfFormFormTest.php +++ b/tests/src/Functional/FillPdfFormFormTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\fillpdf\Functional; +use Drupal\Core\Url; use Drupal\file\Entity\File; use Drupal\fillpdf\Entity\FillPdfForm; use Drupal\user\Entity\Role; @@ -80,6 +81,84 @@ class FillPdfFormFormTest extends FillPdfUploadTestBase { $this->assertUploadPdfFile(self::OP_SAVE, TRUE); } + /** + * Tests the FillPdfForm entity's edit form. + */ + public function testStorageSettings() { + $this->uploadTestPdf('fillpdf_test_v3.pdf'); + $form_id = $this->getLatestFillPdfForm(); + $previous_file_id = $this->getLastFileId(); + + $edit_form_url = Url::fromRoute('entity.fillpdf_form.edit_form', ['fillpdf_form' => $form_id]); + $generate_url = Url::fromRoute('fillpdf.populate_pdf', [], [ + 'query' => [ + 'fid' => $form_id, + 'entity_id' => "node:{$this->testNodes[1]->id()}", + ], + ]); + + // Check the initial storage settings. + $this->assertSession()->fieldValueEquals('scheme', '_none'); + foreach (['- None -', 'private://', 'public://'] as $option) { + $this->assertSession()->optionExists('scheme', $option); + } + $this->assertSession()->fieldValueEquals('destination_path[0][value]', ''); + $this->drupalGet($edit_form_url); + + // Now hit the generation route and make sure the PDF file is *not* stored. + $this->drupalGet($generate_url); + $this->assertEquals($previous_file_id, $this->getLastFileId(), 'Generated file is not stored.'); + + // Set the 'public' scheme and see if the 'destination_path' field appears. + $this->drupalPostForm($edit_form_url, ['scheme' => 'public'], self::OP_SAVE); + $this->assertSession()->fieldValueEquals('scheme', 'public'); + $this->assertSession()->pageTextContains('Destination path'); + + // Hit the generation route again and make sure this time the PDF file is + // stored in the public storage. + $this->drupalGet($generate_url); + $this->assertEquals(++$previous_file_id, $this->getLastFileId(), 'Generated file was stored.'); + $this->assertStringStartsWith('public://', File::load($this->getLastFileId())->getFileUri()); + + // Now disallow the public scheme and reload. + $this->configureFillPdf(['allowed_schemes' => ['private']]); + + // Reload and check if the public option has disappeared now. + $this->drupalGet($edit_form_url); + $this->assertSession()->fieldValueEquals('scheme', '_none'); + foreach (['- None -', 'private://'] as $option) { + $this->assertSession()->optionExists('scheme', $option); + } + $this->assertSession()->optionNotExists('scheme', 'public://'); + + // Hit the generation route once more and make sure the scheme has been + // unset, so the PDF file is *not* stored. + $this->drupalGet($generate_url); + $this->assertEquals($previous_file_id, $this->getLastFileId(), 'Generated file is not stored.'); + + // Set the 'private' scheme. + $this->drupalPostForm($edit_form_url, ['scheme' => 'private'], self::OP_SAVE); + $this->assertSession()->fieldValueEquals('scheme', 'private'); + + // Hit the generation route again and make sure this time the PDF file is + // stored in the private storage. + $this->drupalGet($generate_url); + $this->assertEquals(++$previous_file_id, $this->getLastFileId(), 'Generated file was stored.'); + $this->assertStringStartsWith('private://', File::load($this->getLastFileId())->getFileUri()); + + // Now disallow the private scheme as well and reload. + $this->configureFillPdf(['allowed_schemes' => []]); + $this->drupalGet($edit_form_url); + + // Check if the whole storage settings section has disappeared now. + $this->assertSession()->pageTextNotContains('Storage and download'); + + // Hit the generation route one last time and make sure the PDF file is + // again *not* stored. + $this->drupalGet($generate_url); + $this->assertEquals($previous_file_id, $this->getLastFileId(), 'Generated file is not stored.'); + } + /** * Tests proper registration of managed_files. */ diff --git a/tests/src/Functional/FillPdfSettingsFormTest.php b/tests/src/Functional/FillPdfSettingsFormTest.php index ac24735f0f39ed5f62971b8944391afd9725dd55..341d4c0ed6e13525f056d7b6a9cb83df0837b49d 100644 --- a/tests/src/Functional/FillPdfSettingsFormTest.php +++ b/tests/src/Functional/FillPdfSettingsFormTest.php @@ -42,7 +42,7 @@ class FillPdfSettingsFormTest extends BrowserTestBase { // 'fillpdf_service' backend. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->pageTextContains('Public files (site default)'); - $this->assertSession()->checkboxChecked('edit-scheme-public'); + $this->assertSession()->checkboxChecked('edit-template-scheme-public'); $this->assertSession()->checkboxChecked('edit-backend-fillpdf-service'); // Now set the site default to 'private'. @@ -55,21 +55,21 @@ class FillPdfSettingsFormTest extends BrowserTestBase { // while the backend should remain unchanged. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->pageTextContains('Private files (site default)'); - $this->assertSession()->checkboxChecked('edit-scheme-private'); + $this->assertSession()->checkboxChecked('edit-template-scheme-private'); $this->assertSession()->checkboxChecked('edit-backend-fillpdf-service'); } /** * Tests the scheme settings with the 'dummy_remote' stream wrapper. */ - public function testSettingsFormSchemeDummyRemote() { + public function testTemplateSchemeDummyRemote() { // FillPDF is not yet configured. // Verify the 'dummy_remote' stream wrapper is present on the form. $this->drupalGet(Url::fromRoute('fillpdf.settings')); - $this->assertSession()->elementExists('css', '#edit-scheme-dummy-remote'); + $this->assertSession()->elementExists('css', '#edit-template-scheme-dummy-remote'); // Programmatically configure 'dummy_remote' as new default scheme. - $this->configureBackend('dummy_remote'); + $this->configureFillPdf(['template_scheme' => 'dummy_remote']); // Now uninstall the file_test module with the dummy stream wrappers. $this->assertTrue(\Drupal::service('module_installer')->uninstall(['file_test']), "Module 'file_test' has been uninstalled."); @@ -77,26 +77,26 @@ class FillPdfSettingsFormTest extends BrowserTestBase { // Reload the page and verify that 'dummy_remote' is gone. $this->drupalGet(Url::fromRoute('fillpdf.settings')); - $this->assertSession()->elementNotExists('css', '#edit-scheme-dummy-remote'); - $this->assertSession()->pageTextContains('Your previously used file scheme dummy_remote:// is no longer available'); + $this->assertSession()->elementNotExists('css', '#edit-template-scheme-dummy-remote'); + $this->assertSession()->pageTextContains('Your previously used file storage dummy_remote:// is no longer available'); } /** * Tests the scheme settings with the 'private' stream wrapper. */ - public function testSettingsFormSchemePrivate() { + public function testTemplateSchemePrivate() { // FillPDF is not yet configured. // Configure FillPDF with the 'test' backend and the site default scheme, // which at this point is 'public'. - $this->configureBackend(); + $this->configureFillPdf(); // Now on the settings form, switch to the 'private' scheme. - $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), ['scheme' => 'private'], 'Save configuration'); + $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), ['template_scheme' => 'private'], 'Save configuration'); // Verify the new values have been submitted *and* successfully saved. $this->assertSession()->pageTextContains('The configuration options have been saved.'); - $this->assertSession()->fieldValueEquals('scheme', 'private'); - $this->assertEqual($this->config('fillpdf.settings')->get('scheme'), 'private'); + $this->assertSession()->fieldValueEquals('template_scheme', 'private'); + $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'private'); // Now remove the private path from settings.php and rebuild the container. $this->writeSettings([ @@ -111,29 +111,29 @@ class FillPdfSettingsFormTest extends BrowserTestBase { // Reload the page to verify the 'private' scheme is gone. $this->drupalGet(Url::fromRoute('fillpdf.settings')); - $this->assertSession()->elementNotExists('css', '#edit-scheme-private'); - $this->assertSession()->pageTextContains('Your previously used file scheme private:// is no longer available'); + $this->assertSession()->elementNotExists('css', '#edit-template-scheme-private'); + $this->assertSession()->pageTextContains('Your previously used file storage private:// is no longer available'); // Verify that the site default scheme, which at this point is 'public', is // preselected but not yet saved in config. - $this->assertSession()->fieldValueEquals('scheme', \Drupal::config('system.file')->get('default_scheme')); - $this->assertEqual($this->config('fillpdf.settings')->get('scheme'), 'private'); + $this->assertSession()->fieldValueEquals('template_scheme', file_default_scheme()); + $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'private'); } /** * Tests the scheme settings with the 'public' stream wrapper. */ - public function testSettingsFormSchemePublic() { + public function testTemplateSchemePublic() { // FillPDF is not yet configured. // Configure FillPDF with the 'test' backend and the site default scheme, // which at this point is 'public'. - $this->configureBackend(); + $this->configureFillPdf(); // On the settings page, verify the 'public' scheme is set both in the form // and in config. $this->drupalGet(Url::fromRoute('fillpdf.settings')); - $this->assertSession()->fieldValueEquals('scheme', 'public'); - $this->assertEqual($this->config('fillpdf.settings')->get('scheme'), 'public'); + $this->assertSession()->fieldValueEquals('template_scheme', 'public'); + $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'public'); // Verify the subdirectory doesn't exist yet. $directory = 'public://fillpdf'; @@ -159,7 +159,7 @@ class FillPdfSettingsFormTest extends BrowserTestBase { /** * Tests the backend settings with the 'fillpdf_service' backend. */ - public function testSettingsFormBackendFillPdfService() { + public function testBackendFillPdfService() { // FillPDF is not yet configured. The settings form is however initialized // with the 'fillpdf_service' backend. Save that configuration. $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), NULL, 'Save configuration'); @@ -183,11 +183,11 @@ class FillPdfSettingsFormTest extends BrowserTestBase { /** * Tests the backend settings with the 'pdftk' backend. */ - public function testSettingsFormBackendPdftk() { + public function testBackendPdftk() { // FillPDF is not yet configured. // Try configuring FillPDF with the 'pdftk' backend, yet an invalid path. $edit = [ - 'scheme' => 'private', + 'template_scheme' => 'private', 'backend' => 'pdftk', 'pdftk_path' => 'xyz', ]; @@ -207,7 +207,7 @@ class FillPdfSettingsFormTest extends BrowserTestBase { /** * Tests the backend settings with the 'test' backend. */ - public function testSettingsFormBackendTest() { + public function testBackendTest() { // FillPDF is not yet configured. // Go to the settings page and verify the autodetected 'test' backend is // present only once and with the form-altered label. @@ -219,7 +219,7 @@ class FillPdfSettingsFormTest extends BrowserTestBase { // for the form-altered 'example_setting' and the unrelated // 'fillpdf_service_api_key'. $edit = [ - 'scheme' => 'private', + 'template_scheme' => 'private', 'backend' => 'test', 'example_setting' => 'x', 'fillpdf_service_api_key' => 'Invalid, just playing around.', diff --git a/tests/src/Functional/FillPdfTestBase.php b/tests/src/Functional/FillPdfTestBase.php index 893e06d1b56d6b529a3600286ea7f65702cf1c03..f152a88c23081ec76f804ddccd3325da2c09d064 100644 --- a/tests/src/Functional/FillPdfTestBase.php +++ b/tests/src/Functional/FillPdfTestBase.php @@ -65,7 +65,7 @@ abstract class FillPdfTestBase extends ImageFieldTestBase { 'administer pdfs', ]); - $this->configureBackend(); + $this->configureFillPdf(); $this->backendServiceManager = $this->container->get('plugin.manager.fillpdf_backend_service'); diff --git a/tests/src/Functional/FillPdfUploadTestBase.php b/tests/src/Functional/FillPdfUploadTestBase.php index b1bf7bcc3b34630109a1e226e9db961c1a4a7c7f..3e9804d431b506bbb9316afab507a2b8c4052250 100644 --- a/tests/src/Functional/FillPdfUploadTestBase.php +++ b/tests/src/Functional/FillPdfUploadTestBase.php @@ -24,22 +24,30 @@ abstract class FillPdfUploadTestBase extends FileFieldTestBase { protected $profile = 'minimal'; /** - * @var Upload a file in the managed file widget. + * Upload a file in the managed file widget. + * + * @var string */ const OP_UPLOAD = 'Upload'; /** - * @var Remove a file from the managed file widget. + * Remove a file from the managed file widget. + * + * @var string */ const OP_REMOVE = 'Remove'; /** - * @var Create a new FillPdfForm. Submit button on FillPdfOverviewForm. + * Create a new FillPdfForm. Submit button on FillPdfOverviewForm. + * + * @var string */ const OP_CREATE = 'Create'; /** - * @var Save and update the FillPdfForm. Submit button on FillPdfFormForm. + * Save and update the FillPdfForm. Submit button on FillPdfFormForm. + * + * @var string */ const OP_SAVE = 'Save'; @@ -56,7 +64,7 @@ abstract class FillPdfUploadTestBase extends FileFieldTestBase { protected function setUp() { parent::setUp(); - $this->configureBackend(); + $this->configureFillPdf(); $this->initializeUser(); $this->testNodes[1] = $this->createNode([ @@ -105,7 +113,7 @@ abstract class FillPdfUploadTestBase extends FileFieldTestBase { * - FillPdfUploadTestBase::OP_UPLOAD (default), * - FillPdfUploadTestBase::OP_CREATE, or * - FillPdfUploadTestBase::OP_SAVE. - * @param boolean $filename_preexists + * @param bool $filename_preexists * (optional) Whether the testfile has previously been uploaded, so a file * with the same filename preexists. Defaults to FALSE. */ @@ -153,7 +161,7 @@ abstract class FillPdfUploadTestBase extends FileFieldTestBase { // Make sure the file is permanent and correctly placed. $this->assertFileIsPermanent($new_file); - $expected_file_uri = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('scheme'), "fillpdf/{$new_filename}"); + $expected_file_uri = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('template_scheme'), "fillpdf/{$new_filename}"); $this->assertEquals($new_file->getFileUri(), $expected_file_uri); break; @@ -164,7 +172,7 @@ abstract class FillPdfUploadTestBase extends FileFieldTestBase { // Make sure the file is permanent and correctly placed. $this->assertFileIsPermanent($new_file); - $expected_file_uri = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('scheme'), "fillpdf/{$new_filename}"); + $expected_file_uri = FillPdf::buildFileUri($this->config('fillpdf.settings')->get('template_scheme'), "fillpdf/{$new_filename}"); $this->assertEquals($new_file->getFileUri(), $expected_file_uri); break; } diff --git a/tests/src/Functional/HandlePdfControllerTest.php b/tests/src/Functional/HandlePdfControllerTest.php index 899537ec161ab953f42d3a226f9d5502bf9f0b4a..844e5c96c05fc2c7b905d56d4eecacdeef12208b 100644 --- a/tests/src/Functional/HandlePdfControllerTest.php +++ b/tests/src/Functional/HandlePdfControllerTest.php @@ -25,6 +25,7 @@ class HandlePdfControllerTest extends FillPdfUploadTestBase { $form_id = $this->getLatestFillPdfForm(); $edit = [ 'title[0][value]' => '[current-date:html_year]-[user:account-name]-[node:title].pdf', + 'scheme' => 'public', 'destination_path[0][value]' => '[current-date:html_year]-[user:account-name]-[node:title]', ]; $this->drupalPostForm("admin/structure/fillpdf/{$form_id}", $edit, 'Save'); @@ -102,10 +103,56 @@ class HandlePdfControllerTest extends FillPdfUploadTestBase { } } + /** + * Tests handling of an no longer allowed storage scheme. + */ + public function testStorageSchemeDisallowed() { + $this->uploadTestPdf('fillpdf_test_v3.pdf'); + $form_id = $this->getLatestFillPdfForm(); + $previous_file_id = $this->getLastFileId(); + $edit = [ + 'admin_title[0][value]' => 'Scheme test', + 'scheme' => 'public', + 'destination_path[0][value]' => 'test', + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); + + $fillpdf_route = Url::fromRoute('fillpdf.populate_pdf', [], [ + 'query' => [ + 'fid' => $form_id, + ], + ]); + + // Hit the generation route. Make sure we are redirected to the front page. + $this->drupalGet($fillpdf_route); + $this->assertSession()->addressNotEquals('/fillpdf'); + $this->assertSession()->statusCodeEquals(200); + // Get back to the front page and make sure the file was stored in the + // private storage. + $this->drupalGet('<front>'); + $this->assertSession()->pageTextNotContains('File storage scheme public:// is unavailable'); + $this->assertEquals(++$previous_file_id, $this->getLastFileId(), 'Generated file was stored.'); + $this->assertStringStartsWith('public://', File::load($this->getLastFileId())->getFileUri()); + + // Now disallow the public scheme. + $this->configureFillPdf(['allowed_schemes' => ['private']]); + + // Hit the generation route again. This time we should be redirected to the + // PDF file. Make sure no PHP error occured. + $this->drupalGet($fillpdf_route); + $this->assertSession()->addressEquals('/fillpdf'); + $this->assertSession()->statusCodeEquals(200); + // Get back to the front page and check if an error was set, and we didn't + // try to store the file. + $this->drupalGet('<front>'); + $this->assertSession()->pageTextContains("File storage scheme public:// is unavailable, so a PDF file generated from FillPDF form Scheme test ($form_id) could not be stored."); + $this->assertEquals($previous_file_id, $this->getLastFileId(), 'Generated file was not stored.'); + } + /** * Tests handling of an unavailable storage scheme. */ - public function testStorageSchemePrivate() { + public function testStorageSchemeUnavailable() { $this->uploadTestPdf('fillpdf_test_v3.pdf'); $form_id = $this->getLatestFillPdfForm(); $previous_file_id = $this->getLastFileId(); diff --git a/tests/src/Functional/PdfPopulationTest.php b/tests/src/Functional/PdfPopulationTest.php index e187d2f35df7a59c662663f7d5b04d0bcbce51f1..7ac1b28d8852676f4f073b1a2ef355c6380b79b1 100644 --- a/tests/src/Functional/PdfPopulationTest.php +++ b/tests/src/Functional/PdfPopulationTest.php @@ -31,7 +31,7 @@ class PdfPopulationTest extends FillPdfTestBase { protected function setUp() { parent::setUp(); - $this->configureBackend(); + $this->configureFillPdf(); $this->testNode = Node::load( $this->uploadNodeImage( diff --git a/tests/src/Traits/TestFillPdfTrait.php b/tests/src/Traits/TestFillPdfTrait.php index 3252e394fad489659835a1e246e73c4053b0dc70..e2bf3a54a7c1e8db175d91cde3519e3bfb42abee 100644 --- a/tests/src/Traits/TestFillPdfTrait.php +++ b/tests/src/Traits/TestFillPdfTrait.php @@ -10,28 +10,32 @@ namespace Drupal\Tests\fillpdf\Traits; trait TestFillPdfTrait { /** - * Configures the FillPdf test scheme and backend. + * Configures schemes and backend. * - * @param string $scheme - * (optional) The file system scheme to use for PDF templates. Defaults - * to the site default, which initially is 'public'. - * @param string $backend - * (optional) The backend to use. Defaults to 'test'. + * @param array $configuration + * (optional) Associative array containing configuration to be set. This may + * contain the following keys: + * - 'allowed_schemes': string[] (default: ['public', 'private'] + * - 'template_scheme': string (default: the site default) + * - 'backend': string (default: 'test') */ - protected function configureBackend($scheme = 'default', $backend = 'test') { + protected function configureFillPdf(array $configuration = []) { + // Merge in defaults. + $configuration += [ + 'allowed_schemes' => ['public', 'private'], + 'template_scheme' => file_default_scheme(), + 'backend' => 'test', + ]; + /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ $config_factory = $this->container->get('config.factory'); - // Get the site default scheme. - if ($scheme == 'default') { - $scheme = $config_factory->get('system.file')->get('default_scheme'); - } - // Set FillPDF backend and scheme. - $fillpdf_settings = $config_factory->getEditable('fillpdf.settings') - ->set('scheme', $scheme) - ->set('backend', $backend); - $fillpdf_settings->save(); + $config_factory->getEditable('fillpdf.settings') + ->set('allowed_schemes', $configuration['allowed_schemes']) + ->set('template_scheme', $configuration['template_scheme']) + ->set('backend', $configuration['backend']) + ->save(); } /** @@ -42,7 +46,7 @@ trait TestFillPdfTrait { // environment to run the Docker container at http://127.0.0.1:8085 if you // are developing for FillPDF and want to run this test. $edit = [ - 'scheme' => 'public', + 'template_scheme' => 'public', 'backend' => 'local_service', 'local_service_endpoint' => 'http://127.0.0.1:8085', ]; @@ -60,7 +64,7 @@ trait TestFillPdfTrait { protected function configureFillPdfServiceBackend($api_key, $api_endpoint = 'https://www.fillpdf.io') { // Configure FillPDF Service. $edit = [ - 'scheme' => 'public', + 'template_scheme' => 'public', 'backend' => 'fillpdf_service_v2', 'fillpdf_service_api_key' => $api_key, 'fillpdf_service_api_endpoint' => $api_endpoint, @@ -103,6 +107,7 @@ trait TestFillPdfTrait { * Gets the ID of the latest fillpdf_form stored. * * @return int + * ID of the lates FillPdf Form stored. */ protected function getLatestFillPdfForm() { $entity_query = $this->container->get('entity_type.manager')