From 9ea8029a3f25b027b696bc7d6714d29d9d8116c9 Mon Sep 17 00:00:00 2001 From: Bernd Oliver Suenderhauf <bos@suenderhauf.de> Date: Mon, 17 Jun 2019 17:50:54 +0200 Subject: [PATCH] Issue #3047921 by Pancho: Turn default entity ID field into a select if no more than 25 entries --- src/Form/FillPdfFormForm.php | 106 ++++++++++++------- tests/src/Functional/FillPdfFormFormTest.php | 74 ++++++++----- 2 files changed, 111 insertions(+), 69 deletions(-) diff --git a/src/Form/FillPdfFormForm.php b/src/Form/FillPdfFormForm.php index 691261d..400be71 100644 --- a/src/Form/FillPdfFormForm.php +++ b/src/Form/FillPdfFormForm.php @@ -16,13 +16,17 @@ use Drupal\fillpdf\InputHelperInterface; use Drupal\fillpdf\SerializerInterface; use Drupal\fillpdf\TokenResolverInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Entity\EntityInterface; /** * Form controller for the FillPDFForm edit form. */ class FillPdfFormForm extends ContentEntityForm { + /** + * Maximum number of entities to be listed in a select. + */ + const SELECT_MAX = 25; + /** * The FillPdf admin form helper. * @@ -129,13 +133,13 @@ class FillPdfFormForm extends ContentEntityForm { public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); - /** @var \Drupal\fillpdf\FillPdfFormInterface $entity */ - $entity = $this->entity; + /** @var \Drupal\fillpdf\FillPdfFormInterface $fillpdf_form */ + $fillpdf_form = $this->entity; $form['title']['token_tree'] = $this->adminFormHelper->getAdminTokenForm(); // @todo: Encapsulate this logic into a ::getDefaultEntityType() method on FillPdfForm - $stored_default_entity_type = $entity->get('default_entity_type'); + $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'] = [ @@ -146,7 +150,7 @@ class FillPdfFormForm extends ContentEntityForm { '#weight' => 12.5, '#default_value' => $default_entity_type, '#ajax' => [ - 'callback' => '::ajaxUpdateIdAutocomplete', + 'callback' => '::ajaxUpdateEntityId', 'event' => 'change', 'wrapper' => 'test-entity-wrapper', 'progress' => ['type' => 'none'], @@ -160,15 +164,30 @@ class FillPdfFormForm extends ContentEntityForm { $default_entity_id = $form_state->getValue('default_entity_id'); } else { - $stored_default_entity_id = $entity->get('default_entity_id'); + $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 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; + $storage = $this->entityTypeManager->getStorage($default_entity_type); - if (!empty($default_entity) && $default_entity instanceof EntityInterface) { + $default_entity = $default_entity_id ? $storage->load($default_entity_id) : NULL; + if (!empty($default_entity)) { $description = $this->l( $this->t('Download this PDF template populated with data from the @type %label (@id).', [ '@type' => $default_entity_type, @@ -181,43 +200,50 @@ class FillPdfFormForm extends ContentEntityForm { ]) ); } + + $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 { - $description = $this->t('Enter the title of a %type to test populating the PDF template.', [ - '%type' => $default_entity_type, - ]); + $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, + ]; } - - $form['default_entity_id'] = [ - '#type' => 'entity_autocomplete', - '#title' => $this->t('Default entity'), - '#target_type' => $default_entity_type, - '#description' => $description, - '#weight' => 13, - '#default_value' => $default_entity, - '#prefix' => '<div id="test-entity-wrapper">', - '#suffix' => '</div>', - '#ajax' => [ - 'callback' => '::ajaxUpdateIdAutocomplete', - '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'] = [ + $form['default_entity_id'] += [ '#type' => 'hidden', - '#weight' => 13, - '#prefix' => '<div id="test-entity-wrapper">', - '#suffix' => '</div>', ]; } - $fid = $entity->id(); + $fid = $fillpdf_form->id(); /** @var \Drupal\file\FileInterface $file_entity */ - $file_entity = File::load($entity->get('file')->first()->target_id); + $file_entity = File::load($fillpdf_form->get('file')->first()->target_id); $pdf_info_weight = 0; $form['pdf_info'] = [ '#type' => 'fieldset', @@ -347,20 +373,20 @@ class FillPdfFormForm extends ContentEntityForm { // @todo: Add a button to let them attempt re-parsing if it failed. $form['fillpdf_fields']['fields'] = FillPdf::embedView('fillpdf_form_fields', 'block_1', - $entity->id()); + $fillpdf_form->id()); $form['fillpdf_fields']['#weight'] = 100; $form['export_fields'] = [ '#prefix' => '<div>', - '#markup' => $this->l($this->t('Export these field mappings'), Url::fromRoute('entity.fillpdf_form.export_form', ['fillpdf_form' => $entity->id()])), + '#markup' => $this->l($this->t('Export these field mappings'), Url::fromRoute('entity.fillpdf_form.export_form', ['fillpdf_form' => $fillpdf_form->id()])), '#suffix' => '</div>', '#weight' => 100, ]; $form['import_fields'] = [ '#prefix' => '<div>', - '#markup' => $this->l($this->t('Import a previous export into this PDF'), Url::fromRoute('entity.fillpdf_form.import_form', ['fillpdf_form' => $entity->id()])), + '#markup' => $this->l($this->t('Import a previous export into this PDF'), Url::fromRoute('entity.fillpdf_form.import_form', ['fillpdf_form' => $fillpdf_form->id()])), '#suffix' => '</div>', '#weight' => 100, ]; @@ -425,7 +451,7 @@ class FillPdfFormForm extends ContentEntityForm { * @return array * A render array containing the replacement form element. */ - public function ajaxUpdateIdAutocomplete(array &$form, FormStateInterface $form_state) { + 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') { @@ -499,9 +525,9 @@ class FillPdfFormForm extends ContentEntityForm { // Save custom form elements' values, resetting default_entity_id to NULL, // if not matching the default entity type. $default_entity_type = $form_state->getValue('default_entity_type'); - $default_entity_target_type = isset($form['default_entity_id']['#target_type']) ? $form['default_entity_id']['#target_type'] : NULL; + $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_type == $default_entity_target_type) ? $form_state->getValue('default_entity_id') : NULL) + ->set('default_entity_id', $default_entity_id) ->save(); } diff --git a/tests/src/Functional/FillPdfFormFormTest.php b/tests/src/Functional/FillPdfFormFormTest.php index a6a24a1..2382421 100644 --- a/tests/src/Functional/FillPdfFormFormTest.php +++ b/tests/src/Functional/FillPdfFormFormTest.php @@ -31,42 +31,58 @@ class FillPdfFormFormTest extends FillPdfUploadTestBase { public function testDefaultEntityId() { $this->uploadTestPdf('fillpdf_test_v3.pdf'); - // Default entity type is not yet given, so there should be no ID element. - $this->assertSession()->pageTextNotContains('Default entity ID'); + // Default entity type is not yet given, so the ID element should be hidden. + $this->assertSession()->hiddenFieldExists('default_entity_id'); - $testcases = []; - // Test case 0: no entity. - $testcases[1]['type'] = 'user'; - $testcases[1]['id'] = $this->adminUser->id(); - $testcases[1]['label'] = $this->adminUser->label(); - - $testcases[2]['type'] = 'node'; - $testcases[2]['id'] = $this->testNode->id(); - $testcases[2]['label'] = $this->testNode->label(); + // Create 25 more users to check the threshold. + for ($i = 0; $i < 25; $i++) { + $this->createUser(); + } - foreach ($testcases as $case) { - $type = $case['type']; - $id = $case['id']; - $label = $case['label']; + $testcases = [ + // Test case: no referenceable entity. + 'fillpdf_file_context' => [0, 0, ''], + // Test case: 1 referenceable entity. + 'node' => [1, $this->testNode->id(), $this->testNode->label()], + // Test case: 26 referenceable entities. + 'user' => [26, $this->adminUser->id(), $this->adminUser->label()], + ]; + foreach ($testcases as $type => list($count, $id, $label)) { // Set a default entity type and check if it's properly saved. $this->drupalPostForm(NULL, ['default_entity_type' => $type], self::OP_SAVE); $this->assertSession()->pageTextContains("FillPDF Form has been updated."); - $this->assertSession()->fieldValueEquals('edit-default-entity-type', $type); - - // Check the default entity ID autocomplete is present now and showing the - // correct description. - $this->assertSession()->fieldValueEquals('edit-default-entity-id', ''); - $this->assertSession()->pageTextContains("Enter the title of a $type to test populating the PDF template."); - - // Now set a default entity ID and check if the entity type is unchanged. - $this->drupalPostForm(NULL, ['default_entity_id' => $label], self::OP_SAVE); + $this->assertSession()->fieldValueEquals('default_entity_type', $type); + + // Check the default entity ID field is present but empty. + $this->assertSession()->fieldValueEquals('default_entity_id', NULL); + + if ($count == 0) { + $options = $this->assertSession()->selectExists('default_entity_id')->findAll('xpath', 'option'); + $this->assertCount(1, $options); + $this->assertEquals('', $options[0]->getValue()); + $this->assertEquals('- None -', $options[0]->getText()); + // Skip the rest and continue with the next test case. + continue; + } + elseif ($count <= 25) { + $this->assertSession()->pageTextContains("Choose a $type to test populating the PDF template."); + // Now enter an entity title. + $this->assertSession()->optionExists('default_entity_id', $id); + $this->drupalPostForm(NULL, ['default_entity_id' => $id], self::OP_SAVE); + $expected_value = $id; + } + else { + $this->assertSession()->pageTextContains("Enter the title of a $type to test populating the PDF template."); + // Now choose an entity and check the entity type is unchanged. + $this->drupalPostForm(NULL, ['default_entity_id' => $label], self::OP_SAVE); + $expected_value = "$label ($id)"; + } + + // Check entity type, entity ID and description. $this->assertSession()->pageTextContains("FillPDF Form has been updated."); - $this->assertSession()->fieldValueEquals('edit-default-entity-type', $type); - - // Check the default entity ID autocomplete is still present and showing - // the updated description with the link. - $this->assertSession()->fieldValueEquals('edit-default-entity-id', "$label ($id)"); + $this->assertSession()->fieldValueEquals('default_entity_type', $type); + $this->assertSession()->fieldValueEquals('default_entity_id', $expected_value); $this->assertSession()->linkExistsExact("Download this PDF template populated with data from the $type $label ($id)."); } } -- GitLab