You are here

webform_test.module in Webform 8.5

Same filename and directory in other branches
  1. 6.x tests/modules/webform_test/webform_test.module

Support module for webform related testing.

File

tests/modules/webform_test/webform_test.module
View source
<?php

/**
 * @file
 * Support module for webform related testing.
 */
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Url;
use Drupal\webform\Utility\WebformElementHelper;

/**
 * Test element callback that should be ignored.
 *
 * @param array $element
 *   An element.
 *
 * @return array
 *   An element.
 */
function webform_test_ignored_element_callback($element = NULL) {

  // Display error message when this callback is executed.
  if (is_array($element) && isset($element['#title'])) {
    $message = t('Callback not ignored for @title', [
      '@title' => $element['#title'],
    ]);
    \Drupal::messenger()
      ->addError($message);
    return $element;
  }
  else {
    $message = t('Callback not ignored');
    \Drupal::messenger()
      ->addError($message);
  }
}

/******************************************************************************/

// Generate elements.

/******************************************************************************/

/**
 * Implements hook_preprocess_HOOK().
 */
function webform_test_preprocess_page(&$variables) {
  if (!isset($_GET['generate']) && in_array(\Drupal::routeMatch()
    ->getRouteName(), [
    'entity.webform.canonical',
    'entity.webform.edit_form',
    'entity.webform.source_form',
  ]) && _webform_test_load_include(\Drupal::routeMatch()
    ->getRawParameter('webform'))) {
    $t_args = [
      ':href' => Url::fromRouteMatch(\Drupal::routeMatch())
        ->toString() . '?generate',
    ];
    \Drupal::messenger()
      ->addWarning(t('The below webform\'s elements are automatically generated and exported. You can regenerate the below elements by appending <a href=":href">?generate</a> to this page\'s URL.', $t_args));
  }
}

/**
 * Implements hook_preprocess_webform_confirmation().
 */
function webform_test_preprocess_webform_confirmation(array &$variables) {

  /** @var \Drupal\webform\WebformInterface $webform */
  $webform = $variables['webform'];
  switch ($webform
    ->id()) {
    case 'test_states_to_text':

      /** @var \Drupal\webform\WebformEntityConditionsManagerInterface $conditions_manager */
      $conditions_manager = \Drupal::service('webform.conditions_manager');
      $build = [];
      $elements = $webform
        ->getElementsInitializedAndFlattened();
      foreach ($elements as $element_key => $element) {
        if (isset($element['#states'])) {
          $build[$element_key] = [
            '#type' => 'item',
            '#title' => $element['#admin_title'],
            'text' => $conditions_manager
              ->toText($webform, $element['#states']),
          ];
        }
      }
      $variables['message'] = $build;
      return;
  }
}

/**
 * Implements hook_webform_load().
 */
function webform_test_webform_load(array $entities) {

  // If ?generate is passed to the current pages URL the test webform's elements
  // will get rebuilt.
  if (!isset($_GET['generate'])) {
    return;
  }
  foreach ($entities as $id => $entity) {
    $name = _webform_test_load_include($id);
    if ($name && function_exists('webform_test_' . $name)) {
      $function = 'webform_test_' . $name;
      $elements = $function($entity);
      $entity
        ->setElements($elements);

      // Issue: Unable to execute Webform::save().
      // $entity->save();
      // Workaround: Write the elements directory to webform config.
      \Drupal::configFactory()
        ->getEditable('webform.webform.' . $id)
        ->set('elements', Yaml::encode($elements))
        ->save();

      // Display message.
      \Drupal::messenger()
        ->addStatus(t('Generated elements for %title webform', [
        '%title' => $entity
          ->label(),
      ]));
    }
  }
}

/**
 * Load webform test include file.
 *
 * @param string $id
 *   The webform ID.
 *
 * @return string|bool
 *   The webform test generating name or FALSE if the webform has not test
 *   include file.
 */
function _webform_test_load_include($id) {
  if (preg_match('/^(test_form_(?:wizard_)?long|test_cards_long)_\\d+$/', $id, $match)) {
    $id = $match[1];
  }
  $include_base_path = drupal_get_path('module', 'webform_test') . '/includes';
  if (file_exists("{$include_base_path}/webform_test.{$id}.inc")) {
    module_load_include('inc', 'webform_test', 'includes/webform_test.' . $id);
    return $id;
  }
  else {
    return FALSE;
  }
}

/**
 * Get a preview/example element for a specified element type.
 *
 * @param string $type
 *   An element type.
 * @param array $options
 *   Options for generating the example element.
 *
 * @return array|bool
 *   An example element or FALSE if the element type can't have an example.
 */
function _webform_test_get_element_preview($type, array $options = []) {
  static $skipped = [
    'webform_example_element',
    'webform_example_composite',
    'webform_test_offcanvas_width_element',
  ];

  // Skip certain elements that should never be included in test forms.
  if (in_array($type, $skipped)) {
    return FALSE;
  }
  $options += [
    'issues' => TRUE,
  ];

  /** @var \Drupal\webform\Plugin\WebformElementManagerInterface $element_manager */
  $element_manager = \Drupal::service('plugin.manager.webform.element');
  $webform_element = $element_manager
    ->createInstance($type);
  $element = $webform_element
    ->preview();
  if (empty($element)) {
    return FALSE;
  }

  // Skip custom options.
  // @see \Drupal\webform_options_custom\Entity\WebformOptionsCustom::getPreview
  if (isset($element['#type']) && $element['#type'] === 'webform_options_custom') {
    return FALSE;
  }

  // Add known issues to #description.
  if ($options['issues']) {
    $issues = _webform_test_issues();
    if (isset($issues[$type])) {
      $items = [];
      foreach ($issues[$type] as $issue_number => $issue_title) {
        $items[$issue_number] = "<a href=\"https://www.drupal.org/node/{$issue_number}\">Issue #{$issue_number}: {$issue_title}</a>";
      }
      $element['#description'] = '<b>' . t('Known Issues:') . '</b><br />' . implode('<br />', $items);
    }
  }

  // Remove markup so that the element can be serialized to YAML.
  WebformElementHelper::convertRenderMarkupToStrings($element);
  return $element;
}

/**
 * Get issues related to elements #states API.
 *
 * @return array
 *   Associative array containing issues related to elements #states API.
 */
function _webform_test_issues() {
  return [
    'submit' => [
      '1671190' => 'Use <button /> webform element type instead of <input type="submit" />',
    ],
    'datetime' => [
      '2419131' => '#states attribute does not work on #type datetime',
    ],
    'details' => [
      '2348851' => 'Regression: Allow HTML tags inside detail summary',
    ],
    'entity_autocomplete' => [
      '2826451' => 'TermSelection returning HTML characters in select list',
    ],
    'item' => [
      '783438' => '#states doesn\'t work for #type item',
    ],
    'managed_file' => [
      '2705471' => 'Webform states managed file fields',
      '2113931' => 'File Field design update',
      '2346893' => 'Duplicate Ajax wrapper around a file field',
      '2482783' => 'File upload errors not set or shown correctly',
    ],
    'password_confirm' => [
      '1427838' => 'password and password_confirm children do not pick up #states or #attributes',
    ],
    'select' => [
      '1426646' => '"-Select-" option is lost when webform elements uses \'#states\'',
      '1149078' => 'States API doesn\'t work with multiple select fields',
      '2791741' => 'FAPI states: fields aren\'t hidden initially when depending on multi-value selection',
    ],
    'radios' => [
      '2731991' => 'Setting required on radios marks all options required',
      '994360' => '#states cannot disable/enable radios and checkboxes',
      '2836364' => 'Wrapper attributes are not supported by composite elements, this includes radios, checkboxes, and buttons.',
    ],
    'checkboxes' => [
      '994360' => '#states cannot disable/enable radios and checkboxes',
      '2836364' => 'Wrapper attributes are not supported by composite elements, this includes radios, checkboxes, and buttons.',
    ],
    'text_format' => [
      '997826' => '#states doesn\'t work correctly with type text_format',
      '2625128' => 'Text format selection stays visible when using editor and a hidden webform state',
      '1954968' => 'Required CKEditor fields always fail HTML5 validation',
    ],
    'webform_markup' => [
      '2700667' => 'Notice: Undefined index: #type in drupal_process_states()',
    ],
    'webform_message' => [
      '77245' => 'A place for JavaScript status messages',
    ],
    'webform_time' => [
      '1838234' => 'Add jQuery Timepicker for the Time element of the datetime field',
    ],
  ];
}

Functions

Namesort descending Description
webform_test_ignored_element_callback Test element callback that should be ignored.
webform_test_preprocess_page Implements hook_preprocess_HOOK().
webform_test_preprocess_webform_confirmation Implements hook_preprocess_webform_confirmation().
webform_test_webform_load Implements hook_webform_load().
_webform_test_get_element_preview Get a preview/example element for a specified element type.
_webform_test_issues Get issues related to elements #states API.
_webform_test_load_include Load webform test include file.