You are here

FillPdfMergeTestCase.test in FillPDF 7

File

tests/FillPdfMergeTestCase.test
View source
<?php

/**
 * Tests that PDF population and token replacement works.
 */
class FillPdfMergeTestCase extends DrupalWebTestCase {
  use FillPdfTestHelper;
  protected $testNode;
  protected $testEntity;
  protected $nonPrivilegedUser;

  /**
   * {@inheritdoc}
   */
  public static function getInfo() {

    // Note: getInfo() strings are not translated with t().
    return array(
      'name' => 'FillPDF merging',
      'description' => 'Ensure that token and image replacement work.',
      'group' => 'FillPDF',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    $modules = array(
      'fillpdf',
      'fillpdf_test_webform',
      'entity_token',
      'fillpdf_test',
    );
    parent::setUp($modules);
    $this
      ->createPrivilegedUser();
    $this
      ->configureBackend();
    $existing_roles = array_keys($this->privilegedUser->roles);
    $granted_rid = end($existing_roles);
    user_role_change_permissions($granted_rid, array(
      'administer nodes' => TRUE,
      'access all webform results' => TRUE,
      'edit all webform submissions' => TRUE,
      'edit webform components' => TRUE,
    ));
    $this->nonPrivilegedUser = $this
      ->drupalCreateUser(array(
      'publish own pdfs',
    ));
  }

  /**
   * Test PDF merging.
   *
   * @throws \FieldException
   */
  public function testPdfMerging() {
    features_revert_module('fillpdf_test_webform');

    // Can we get to the Webform we created?
    $webform = webform_features_machine_name_load('fillpdf_test_webform');
    $this
      ->assertTrue(property_exists($webform, 'nid'), 'Webform properly loaded from Features.');
    $this
      ->createImageField('field_test_image', 'node', 'article');
    $files = $this
      ->drupalGetTestFiles('image');
    $image = reset($files);

    // Clear cache and grant more permissions to ensure ability to create nodes.
    $existing_roles = array_keys($this->privilegedUser->roles);
    $granted_rid = end($existing_roles);
    user_role_change_permissions($granted_rid, array(
      'create webform content' => TRUE,
      'create article content' => TRUE,
    ));
    $this->testNode = node_load($this
      ->createImageFieldEntity($image, 'field_test_image', 'node', 'article'));

    // Test with a node.
    $this
      ->uploadTestPdf();
    $fillpdf_form = fillpdf_load($this
      ->getLatestFillPdfForm());

    // Get the field definitions for the form that was created and configure
    // them.
    $fid = $fillpdf_form->fid;
    $fields = fillpdf_get_fields($fid);
    $this
      ->mapFillPdfFieldsToEntityFields('node', $fields, $fid);

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $fid,
        'nid' => $this->testNode->nid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($merge_result['fields']['TextField'], $this->testNode->title, 'PDF is populated with the title of the node.');

    // *******************************
    // *******************************
    // Ensure entity defaults don't overpower legacy nids in links or
    // fillpdf_merge_pdf() calls.
    // *******************************
    // *******************************
    $default_nid_test_node = node_load($this
      ->createImageFieldEntity($image, 'field_test_image', 'node', 'article'));

    // Test with a node.
    $this
      ->uploadTestPdf();
    $fillpdf_form_default = fillpdf_load($this
      ->getLatestFillPdfForm());
    $this
      ->drupalPost("admin/structure/fillpdf/{$fillpdf_form_default->fid}", array(
      'default_nid' => $default_nid_test_node->nid,
    ), t('Update'));

    // Get the field definitions for the form that was created and configure
    // them.
    $fid = $fillpdf_form_default->fid;
    $fields = fillpdf_get_fields($fid);
    $this
      ->mapFillPdfFieldsToEntityFields('node', $fields, $fillpdf_form_default->fid);

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $fillpdf_form_default->fid,
        'nid' => $this->testNode->nid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($merge_result['fields']['TextField'], $this->testNode->title, 'Regression test: PDF is populated with the title of the correct node, not the default.');

    // These tests cover the official (and some unofficial) ways of building
    // FillPDF Links for entities. Official: entity_id, entity_ids, entity_type
    // + entity_id. Unofficial: entity (synonym for entity_id), entities
    // (synonym for entity_ids). It doesn't test entity_type + entity, but that
    // should work too. It's not officially supported, though. It's just that
    // the contributed patch already had those working, and there was no good
    // reason to take them out and make it harder for people to update their
    // version of FillPDF later.
    $this->testEntity = node_load($this
      ->createImageFieldEntity($image, 'field_test_image', 'node', 'article'));

    // Test with a node.
    $this
      ->uploadTestPdf();
    $fillpdf_form_entity = fillpdf_load($this
      ->getLatestFillPdfForm());

    // Get the field definitions for the form that was created and configure
    // them.
    $entity_fid = $fillpdf_form_entity->fid;
    $entity_fields = fillpdf_get_fields($entity_fid);
    $this
      ->mapFillPdfFieldsToEntityFields('node', $entity_fields, $entity_fid);

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entity_id' => $this->testEntity->nid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $entity_merge_result_1 = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($entity_merge_result_1['fields']['TextField'], $this->testEntity->title, 'PDF is populated with the title of the node (via entity tokens
      and single-entity format).');

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entity' => "node:{$this->testEntity->nid}",
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $entity_merge_result_2 = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($entity_merge_result_2['fields']['TextField'], $this->testEntity->title, 'PDF is populated with the title of the node (via entity tokens
      and alternative single-entity format).');
    $this
      ->createImageField('field_term_image', 'taxonomy_term', 'tags');
    $term_image = file_save($image);

    // Test an actual entity token (taxonomy terms).
    $tid = $this
      ->createImageFieldEntity($term_image, 'field_term_image', 'taxonomy_term', 'tags', 'Test term');
    $test_term = taxonomy_term_load($tid);

    // Re-map the PDF fields so that the following tests will work.
    $this
      ->mapFillPdfFieldsToEntityFields('taxonomy_term', $entity_fields, $entity_fid);

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entity_ids' => array(
          "taxonomy_term:{$test_term->tid}",
        ),
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $entity_merge_result_3 = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($entity_merge_result_3['fields']['TextField'], $test_term->name, 'PDF is populated with the title of the taxonomy term.');
    $field_term_image = field_get_items('taxonomy_term', $test_term, 'field_term_image');
    $term_file = file_load($field_term_image[0]['fid']);
    $this
      ->assertEqual($entity_merge_result_3['images']['ImageField']['data'], base64_encode(file_get_contents($term_file->uri)), '(Entity mode) Encoded image matches known image.');
    $path_info = pathinfo($term_file->uri);
    $expected_file_hash = md5($path_info['filename']) . '.' . $path_info['extension'];
    $this
      ->assertEqual($entity_merge_result_3['images']['ImageField']['filenamehash'], $expected_file_hash, '(Entity mode) Hashed filename matches known hash.');
    $this
      ->assertEqual($entity_merge_result_3['fields']['ImageField'], '{image}' . drupal_realpath($term_file->uri), '(Entity mode) URI in metadata matches expected URI.');

    // Clean up, since we're reusing these variables again later in the same
    // test. They weren't worth renaming.
    unset($path_info, $expected_file_hash);

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entities' => array(
          "taxonomy_term:{$test_term->tid}",
        ),
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $entity_merge_result_4 = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($entity_merge_result_4['fields']['TextField'], $test_term->name, 'PDF is populated with the title of the taxonomy term.');

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entity_type' => 'taxonomy_term',
        'entity_id' => $test_term->tid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $entity_merge_result_5 = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($entity_merge_result_5['fields']['TextField'], $test_term->name, 'PDF is populated with the title of the taxonomy term (via
      simplified format).');

    // Test filename title generation. Configure it, merge the PDF without
    // handling, and then save it as a file and check the name.
    db_update('fillpdf_forms')
      ->fields(array(
      'destination_path' => 'output',
      'title' => 'Token_[term:name]_title',
      'destination_redirect' => 1,
    ))
      ->condition('fid', $entity_fid)
      ->execute();
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
        'entity' => "taxonomy_term:{$test_term->tid}",
      ),
    ));
    $where_are_we = $this
      ->getUrl();
    $path_parts = explode('/', parse_url($where_are_we, PHP_URL_PATH));
    $filename = end($path_parts);
    if (empty($filename)) {

      // Wait, are we the d.o. testbot? Who else turns off clean URLs?
      // Alright, then; try the query string instead.
      $raw_query = parse_url($where_are_we, PHP_URL_QUERY);
      parse_str($raw_query, $parse_query);
      if (isset($parse_query['q'])) {
        $query_parts = explode('/', $parse_query['q']);
        $filename = end($query_parts);
      }
    }
    $expected_filename = 'Token_Test_term_title.pdf';
    $args = array(
      '@actual' => $filename,
      '@expected' => $expected_filename,
      '@url' => $where_are_we,
    );
    $this
      ->assertEqual($expected_filename, $filename, t('Filename of generated file (@actual) matches specified entity token pattern (@expected). Current page URL: @url', $args));

    // Test that node access via entity access works.
    // Make a basic page.
    $entity_access_test_node = new stdClass();
    $entity_access_test_node->type = 'page';
    $entity_access_test_node->title = t('Entity access test');
    $entity_access_test_node->field_body = array(
      LANGUAGE_NONE => array(
        0 => array(
          'value' => 'This is test text.',
        ),
      ),
    );
    $entity_access_test_node->uid = 1;
    node_save($entity_access_test_node);

    // Upload a fresh PDF, since we changed some settings on the other one.
    $this
      ->uploadTestPdf();
    $entity_access_pdf = fillpdf_load($this
      ->getLatestFillPdfForm());

    // Get the field definitions for the form that was created and configure
    // them.
    $entity_access_fid = $entity_access_pdf->fid;
    $entity_access_fields = fillpdf_get_fields($entity_access_fid);
    $this
      ->mapFillPdfFieldsToEntityFields('node', $entity_access_fields, $entity_access_fid);
    $this
      ->drupalLogin($this->nonPrivilegedUser);
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_access_fid,
        'entity' => "node:{$entity_access_test_node->nid}",
      ),
    ));
    $this
      ->assertResponse(403, 'User must have access to base entity to fill in PDF.');

    // Restore privileged user.
    $this
      ->drupalLogin($this->privilegedUser);

    // Test classic default NID handling (turn off the Entity API module).
    // It's enough to disable entity_token without the parent entity module,
    // since we always check for entity_token specifically.
    module_disable(array(
      'entity_token',
    ));
    $this
      ->drupalPost("admin/structure/fillpdf/{$entity_access_fid}", array(
      'default_nid' => $entity_access_test_node->nid,
    ), t('Update'));

    // Ensure default_entity_type is NULL in the database, as this is a
    // regression to make sure old-style default_nid isn't broken.
    db_update('fillpdf_forms')
      ->condition('fid', $entity_access_fid)
      ->fields(array(
      'default_entity_type' => NULL,
    ))
      ->execute();
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_access_fid,
      ),
    ));
    $default_nid_merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual('Entity access test', $default_nid_merge_result['fields']['TextField'], 'Configured node properly used as default when no parameters specified.');

    // Re-enable Entity Tokens.
    module_enable(array(
      'entity_token',
    ));

    // Test default entity type/entity ID. We use the browser to set these to
    // ensure the fields are there.
    $this
      ->drupalPost("admin/structure/fillpdf/{$entity_fid}", array(
      'default_nid' => $test_term->tid,
      'default_entity_type' => 'taxonomy_term',
    ), t('Update'));
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $entity_fid,
      ),
    ));
    $default_entity_merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual('Test term', $default_entity_merge_result['fields']['TextField'], 'Test term set as default entity properly used when no parameters specified.');
    $field_test_image = field_get_items('node', $this->testNode, 'field_test_image');
    $node_file = file_load($field_test_image[0]['fid']);
    $this
      ->assertEqual($merge_result['images']['ImageField']['data'], base64_encode(file_get_contents($node_file->uri)), 'Encoded image matches known image.');
    $path_info = pathinfo($node_file->uri);
    $expected_file_hash = md5($path_info['filename']) . '.' . $path_info['extension'];
    $this
      ->assertEqual($merge_result['images']['ImageField']['filenamehash'], $expected_file_hash, 'Hashed filename matches known hash.');
    $this
      ->assertEqual($merge_result['fields']['ImageField'], '{image}' . drupal_realpath($node_file->uri), 'URI in metadata matches expected URI.');

    // Test the legacy [stamp] pseudo-token.
    $legacy_fields = fillpdf_get_fields($fid);
    foreach ($legacy_fields as $legacy_pdf_key => $legacy_field) {
      switch ($legacy_pdf_key) {
        case 'ImageField':
          $legacy_field['value'] = '[stamp:field_test_image]';
          break;
      }
      fillpdf_fields_create_update($fid, $legacy_pdf_key, $legacy_field, TRUE);
    }

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $fid,
        'nid' => $this->testNode->nid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $legacy_merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertTrue($legacy_merge_result['flatten'], 'PDF is set to be flattened.');
    $this
      ->assertEqual($legacy_merge_result['images']['ImageField']['data'], base64_encode(file_get_contents($node_file->uri)), 'Legacy: Encoded image matches known image.');
    $this
      ->assertEqual($legacy_merge_result['images']['ImageField']['filenamehash'], $expected_file_hash, 'Legacy: Hashed filename matches known hash.');
    $this
      ->assertEqual($legacy_merge_result['fields']['ImageField'], '{image}' . drupal_realpath($node_file->uri), 'Legacy: URI in metadata matches expected URI.');

    // Test Webform image filling.
    $this
      ->uploadTestPdf();
    $fillpdf_form2 = fillpdf_load($this
      ->getLatestFillPdfForm());

    // Create a test submission for our test Webform.
    $this
      ->drupalPost("node/{$webform->nid}", array(
      'files[submitted_image_field]' => drupal_realpath($image->uri),
    ), t('Submit'));

    // Get the submission.
    $url_parts = drupal_parse_url($this
      ->getUrl());
    module_load_include('inc', 'webform', 'includes/webform.submissions');
    $submission = webform_get_submission($webform->nid, $url_parts['query']['sid']);

    // Get the field definitions for the form that was created and configure
    // them.
    $wf_fields = fillpdf_get_fields($fillpdf_form2->fid);
    foreach ($wf_fields as $wf_pdf_key => $wf_field) {
      switch ($wf_pdf_key) {
        case 'ImageField':
          $wf_field['value'] = '[submission:values:image_field]';
          break;
        case 'TextField':
          $wf_field['value'] = '[node:title]';
          break;
      }
      fillpdf_fields_create_update($fillpdf_form2->fid, $wf_pdf_key, $wf_field, TRUE);
    }

    // Hit the FillPDF URL, check the results from the test fill method.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $fillpdf_form2->fid,
        'webforms[0][nid]' => $webform->nid,
        'webforms[0][sid]' => $submission->sid,
      ),
    ));

    // We don't actually care about downloading the fake PDF. We just want to
    // check what happened in the backend.
    $merge_result = variable_get('fillpdf_test_last_merge_metadata');
    $this
      ->assertEqual($merge_result['fields']['TextField'], $webform->title, 'PDF is populated with the title of the Webform node.');

    // Find the image_field component.
    $image_field_cid = NULL;
    foreach ($webform->webform['components'] as $cid => $component) {
      if ($component['form_key'] === 'image_field') {
        $image_field_cid = $cid;
        break;
      }
    }
    $webform_file = file_load($submission->data[$image_field_cid][0]);
    $this
      ->assertEqual($merge_result['images']['ImageField']['data'], base64_encode(file_get_contents($webform_file->uri)), 'Encoded image matches known image.');
    $path_info = pathinfo($webform_file->uri);
    $expected_file_hash = md5($path_info['filename']) . '.' . $path_info['extension'];
    $this
      ->assertEqual($merge_result['images']['ImageField']['filenamehash'], $expected_file_hash, 'Hashed filename matches known hash.');
    $this
      ->assertEqual($merge_result['fields']['ImageField'], '{image}' . drupal_realpath($webform_file->uri), 'URI in metadata matches expected URI.');
  }

  /**
   * Tests PDF merging using a local service.
   */
  public function testLocalServicePdfMerging() {
    $this
      ->configureLocalServiceBackend();
    if (!fillpdf_localservice_check()) {

      // We don't have access to the local service, so don't run any assertions.
      return;
    }

    // The testing UI doesn't clearly indicate that these tests are being run by
    // default because we delegate to backendTest(). This is a convenience
    // marker.
    $this
      ->assertTrue(TRUE, 'FillPDF LocalServer detected. Running tests.');
    $this
      ->backendTest();
  }

  /**
   * Tests PDF merging using a local install of pdftk.
   */
  public function testPdftkPdfMerging() {
    $this
      ->configurePdftkBackend();
    if (!fillpdf_pdftk_check()) {

      // No pdftk installed, so don't run any assertions.
      return;
    }

    // The testing UI doesn't clearly indicate that these tests are being run by
    // default because we delegate to backendTest(). This is a convenience
    // marker.
    $this
      ->assertTrue(TRUE, 'Detected pdftk. Running tests.');
    $this
      ->backendTest();
  }

  /**
   * Tests PDF merging.
   */
  protected function backendTest() {
    $this
      ->uploadTestPdf();
    $fillpdf_form = fillpdf_load($this
      ->getLatestFillPdfForm());

    // Get the field definitions for the form that was created and configure
    // them.
    $fields = fillpdf_get_fields($fillpdf_form->fid);
    $this
      ->assertFalse(empty($fields), 'PDF contained actual fields.');
    $this
      ->mapFillPdfFieldsToEntityFields('node', $fields, $fillpdf_form->fid);

    // Hit the generation callback, and check the results from merging.
    $this
      ->drupalGet('fillpdf', array(
      'query' => array(
        'fid' => $fillpdf_form->fid,
        'nid' => $this->testNode->nid,
      ),
    ));
    $maybe_pdf = $this
      ->drupalGetContent();
    $finfo = new \finfo(FILEINFO_MIME_TYPE);
    $this
      ->assertEqual('application/pdf', $finfo
      ->buffer($maybe_pdf));
  }

}

Classes

Namesort descending Description
FillPdfMergeTestCase Tests that PDF population and token replacement works.