You are here

yamlform.module in YAML Form 8

Enables the creation of forms and questionnaires.

File

yamlform.module
View source
<?php

/**
 * @file
 * Enables the creation of forms and questionnaires.
 */
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\yamlform\Entity\YamlForm;
use Drupal\yamlform\Plugin\YamlFormElement\ManagedFile;
use Drupal\yamlform\Utility\YamlFormArrayHelper;
use Drupal\yamlform\YamlFormInterface;
use Drupal\yamlform\YamlFormSubmissionForm;
module_load_include('inc', 'yamlform', 'includes/yamlform.libraries');
module_load_include('inc', 'yamlform', 'includes/yamlform.options');
module_load_include('inc', 'yamlform', 'includes/yamlform.translation');

/**
 * Return status for saving which deleted an existing item.
 */
const YAMLFORM_SAVED_DRAFT = 4;

/**
 * Implements hook_help().
 */
function yamlform_help($route_name, RouteMatchInterface $route_match) {

  // Get path from route match.
  $path = preg_replace('/^' . preg_quote(base_path(), '/') . '/', '/', Url::fromRouteMatch($route_match)
    ->setAbsolute(FALSE)
    ->toString());
  if (!in_array($route_name, [
    'system.modules_list',
  ]) && strpos($route_name, 'yamlform') === FALSE && strpos($path, '/yamlform') === FALSE) {
    return NULL;
  }

  /** @var \Drupal\yamlform\YamlFormHelpManagerInterface $help_manager */
  $help_manager = \Drupal::service('yamlform.help_manager');
  if ($route_name == 'help.page.yamlform') {
    $build = $help_manager
      ->buildIndex();
  }
  else {
    $build = $help_manager
      ->buildHelp($route_name, $route_match);
  }
  if ($build) {
    $renderer = \Drupal::service('renderer');
    $config = \Drupal::config('yamlform.settings');
    $renderer
      ->addCacheableDependency($build, $config);
    return $build;
  }
  else {
    return NULL;
  }
}

/**
 * Implements hook_modules_installed().
 */
function yamlform_modules_installed($modules) {

  // Add form paths when the path.module is being installed.
  if (in_array('path', $modules)) {

    /** @var \Drupal\yamlform\YamlFormInterface[] $yamlforms */
    $yamlforms = YamlForm::loadMultiple();
    foreach ($yamlforms as $yamlform) {
      $yamlform
        ->updatePaths();
    }
  }

  // Check HTML email provider support as modules are installed.

  /** @var \Drupal\yamlform\YamlFormEmailProviderInterface $email_provider */
  $email_provider = \Drupal::service('yamlform.email_provider');
  $email_provider
    ->check();
}

/**
 * Implements hook_modules_uninstalled().
 */
function yamlform_modules_uninstalled($modules) {

  // Remove uninstalled module's third party settings from admin settings.
  $config = \Drupal::configFactory()
    ->getEditable('yamlform.settings');
  $third_party_settings = $config
    ->get('third_party_settings');
  foreach ($modules as $module) {
    unset($third_party_settings[$module]);
  }
  $config
    ->set('third_party_settings', $third_party_settings);
  $config
    ->save();

  // Check HTML email provider support as modules are ininstalled.

  /** @var \Drupal\yamlform\YamlFormEmailProviderInterface $email_provider */
  $email_provider = \Drupal::service('yamlform.email_provider');
  $email_provider
    ->check();
}

/**
 * Implements hook_local_tasks_alter().
 */
function yamlform_local_tasks_alter(&$local_tasks) {
  if (isset($local_tasks['config_translation.local_tasks:entity.yamlform.config_translation_overview'])) {

    // Change 'Translate' base route from 'entity.yamlform.edit_form'
    // to 'entity.yamlform.canonical' because by default config entities don't
    // have canonical views but the form entity does.
    $local_tasks['config_translation.local_tasks:entity.yamlform.config_translation_overview']['title'] = 'Translate';
    $local_tasks['config_translation.local_tasks:entity.yamlform.config_translation_overview']['base_route'] = 'entity.yamlform.canonical';
  }
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function yamlform_menu_local_tasks_alter(&$data, $route_name) {
  if (strpos($route_name, 'entity.yamlform.') !== 0) {
    return;
  }

  // Change 'Translate yamlform' tab to be just label 'Translate'.
  if (isset($data['tabs'][0]['config_translation.local_tasks:entity.yamlform.config_translation_overview']['#link']['title'])) {
    $data['tabs'][0]['config_translation.local_tasks:entity.yamlform.config_translation_overview']['#link']['title'] = t('Translate');
  }
}

/**
 * Implements hook_form_alter().
 */
function yamlform_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (strpos($form_id, 'yamlform_') === FALSE || strpos($form_id, 'node_') === 0) {
    return;
  }
  $is_submission_form = $form_state
    ->getFormObject() instanceof YamlFormSubmissionForm;

  // Don't include details toggle all for submission forms.
  if (!$is_submission_form) {
    $form['#attributes']['class'][] = 'js-yamlform-details-toggle';
    $form['#attributes']['class'][] = 'yamlform-details-toggle';
    $form['#attached']['library'][] = 'yamlform/yamlform.element.details.toggle';
  }
  if ($is_submission_form) {
    $form['#after_build'][] = '_yamlform_form_after_build';
  }
}

/**
 * Alter form after build.
 */
function _yamlform_form_after_build($form, FormStateInterface $form_state) {
  $form_object = $form_state
    ->getFormObject();

  // Add contextual links and change theme wrapper to yamlform.html.twig
  // which includes 'title_prefix' and 'title_suffix' variables needed for
  // contextual links to appear.
  $form['#contextual_links']['yamlform'] = [
    'route_parameters' => [
      'yamlform' => $form_object
        ->getEntity()
        ->getYamlForm()
        ->id(),
    ],
  ];
  $form['#theme_wrappers'] = [
    'yamlform',
  ];
  return $form;
}

/**
 * Implements hook_system_breadcrumb_alter().
 */
function yamlform_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMatchInterface $route_match, array $context) {

  // Remove 'Forms' prefix from breadcrumb links generated path breadcrumbs.
  // @see \Drupal\system\PathBasedBreadcrumbBuilder
  $path = Url::fromRouteMatch($route_match)
    ->toString();
  if (strpos($path, '/admin/structure/yamlform/settings/') !== FALSE) {
    $links = $breadcrumb
      ->getLinks();
    foreach ($links as $link) {
      $text = $link
        ->getText();
      if (strpos($text, (string) t('Forms') . ' ') == 0) {
        $text = str_replace((string) t('Forms') . ': ', '', $text);
        $link
          ->setText(Unicode::ucfirst($text));
      }
    }
  }

  // Fix 'Help' breadcrumb text.
  if ($route_match
    ->getRouteName() == 'yamlform.help') {
    $links = $breadcrumb
      ->getLinks();
    $link = end($links);
    $link
      ->setText(t('Forms'));
  }
}

/**
 * Implements hook_entity_delete().
 */
function yamlform_entity_delete(EntityInterface $entity) {

  // Delete saved export settings for a form or source entity with the
  // yamlform field.
  if ($entity instanceof YamlFormInterface || method_exists($entity, 'hasField') && $entity
    ->hasField('yamlform')) {
    $name = 'yamlform.export.' . $entity
      ->getEntityTypeId() . '.' . $entity
      ->id();
    \Drupal::state()
      ->delete($name);
  }
}

/**
 * Implements hook_mail().
 */
function yamlform_mail($key, &$message, $params) {

  // Never send emails when using devel generate to create 1000's of
  // submissions.
  if (\Drupal::moduleHandler()
    ->moduleExists('devel_generate') && \Drupal\yamlform\Plugin\DevelGenerate\YamlFormSubmissionDevelGenerate::isGeneratingSubmissions()) {
    $message['send'] = FALSE;
  }
  $message['subject'] = $params['subject'];
  $message['body'][] = $params['body'];

  // Set the header's 'From' to the 'from_mail' so that the form's email from
  // value is used instead of site's email address.
  // See: \Drupal\Core\Mail\MailManager::mail.
  if (!empty($params['from_mail'])) {
    $message['from'] = $params['from_mail'];
    $message['headers']['From'] = $params['from_mail'];
    $message['headers']['Reply-to'] = $params['from_mail'];
    $message['headers']['Return-Path'] = $params['from_mail'];
  }
  if (!empty($params['cc_mail'])) {
    $message['headers']['Cc'] = $params['cc_mail'];
  }
  if (!empty($params['bcc_mail'])) {
    $message['headers']['Bcc'] = $params['bcc_mail'];
  }
}

/**
 * Implements hook_mail_alter().
 */
function yamlform_mail_alter(&$message) {

  // Drupal hardcodes all mail header as 'text/plain' so we need to set the
  // header's 'Content-type' to HTML if the EmailYamlFormHandler's
  // 'html' flag has been set.
  // @see \Drupal\Core\Mail\MailManager::mail()
  // @see \Drupal\yamlform\Plugin\YamlFormHandler\EmailYamlFormHandler::getMessage().
  if (strpos($message['id'], 'yamlform') === 0) {
    if ($message['params']['html']) {
      $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
    }
  }
}

/**
 * Implements hook_page_attachments().
 */
function yamlform_page_attachments(&$page) {
  $route_name = Drupal::routeMatch()
    ->getRouteName();
  $url = Url::fromRoute('<current>')
    ->toString();

  // Attach global libraries.
  if (preg_match('/^(yamlform\\.|^entity\\.([^.]+\\.)?yamlform)/', $route_name) || preg_match('#(/node/add/yamlform|/admin/help/yamlform)#', $url)) {

    // Attach theme specific library to yamlform routers so that we can tweak
    // the seven.theme.
    $theme = \Drupal::theme()
      ->getActiveTheme()
      ->getName();
    if (file_exists(drupal_get_path('module', 'yamlform') . "/css/yamlform.theme.{$theme}.css")) {
      $page['#attached']['library'][] = "yamlform/yamlform.theme.{$theme}";
    }

    // Attach details element save open/close library.
    if (\Drupal::config('yamlform.settings')
      ->get('ui.details_save')) {
      $page['#attached']['library'][] = 'yamlform/yamlform.element.details.save';
    }
  }

  // Attach codemirror library to block admin to ensure that the library
  // is loaded by the form block is placed using AJAX.
  if (\Drupal::routeMatch()
    ->getRouteName() == 'block.admin_display') {
    $page['#attached']['library'][] = 'yamlform/yamlform.codemirror.yaml';
  }
}

/**
 * Implements hook_css_alter().
 *
 * @see \Drupal\yamlform\YamlFormSubmissionForm::form
 */
function yamlform_css_alter(&$css, AttachedAssetsInterface $assets) {
  _yamlform_asset_alter($css, $assets, 'css', 'css');
}

/**
 * Implements hook_js_alter().
 *
 * @see \Drupal\yamlform\YamlFormSubmissionForm::form
 */
function yamlform_js_alter(&$javascript, AttachedAssetsInterface $assets) {
  _yamlform_asset_alter($javascript, $assets, 'javascript', 'js');
}

/**
 * Alter CSS or JavaScript assets to include custom form assets.
 *
 * Note: CSS and JavaScript are not aggregated or minified to make it easier
 * for themers to debug and custom their code.  We could write the CSS and JS
 * to the 'files/css' and 'files/js' using the hash key and aggregrate them.
 *
 * @param array $items
 *   An array of all CSS or JavaScript being presented on the page.
 * @param \Drupal\Core\Asset\AttachedAssetsInterface $assets
 *   The assets attached to the current response.
 * @param string $type
 *   The type of asset being attached.
 * @param string $extension
 *   The asset file extension being attached.
 */
function _yamlform_asset_alter(array &$items, AttachedAssetsInterface $assets, $type, $extension) {
  $settings = $assets
    ->getSettings();
  if (empty($settings['yamlform']['assets'][$type])) {
    return;
  }
  $path = drupal_get_path('module', 'yamlform');
  foreach ($settings['yamlform']['assets'][$type] as $id => $hash) {
    $key = "{$path}/{$extension}/yamlform.assets.{$extension}";
    if (isset($items[$key])) {
      $items[$key] = [
        'data' => base_path() . "yamlform/{$id}/assets/{$type}?v={$hash}",
        'group' => 1000,
        'weight' => 1000,
      ] + $items[$key];
    }
  }
}

/**
 * Implements hook_file_download().
 */
function yamlform_file_download($uri) {
  return ManagedFile::accessFileDownload($uri);
}

/**
 * Implements hook_theme().
 */
function yamlform_theme() {
  $info = [
    'yamlform_help' => [
      'variables' => [
        'info' => [],
      ],
    ],
    'yamlform_help_video_youtube' => [
      'variables' => [
        'youtube_id' => NULL,
      ],
    ],
    'yamlform' => [
      'render element' => 'element',
    ],
    'yamlform_actions' => [
      'render element' => 'element',
    ],
    'yamlform_handler_email_summary' => [
      'variables' => [
        'settings' => NULL,
        'handler' => [],
      ],
    ],
    'yamlform_handler_remote_post_summary' => [
      'variables' => [
        'settings' => NULL,
        'handler' => [],
      ],
    ],
    'yamlform_confirmation' => [
      'variables' => [
        'yamlform' => NULL,
        'source_entity' => NULL,
        'yamlform_submission' => NULL,
      ],
    ],
    'yamlform_submission_navigation' => [
      'variables' => [
        'yamlform_submission' => NULL,
      ],
    ],
    'yamlform_submission_information' => [
      'variables' => [
        'yamlform_submission' => NULL,
        'source_entity' => NULL,
        'open' => FALSE,
      ],
    ],
    'yamlform_submission_html' => [
      'variables' => [
        'yamlform_submission' => NULL,
        'source_entity' => NULL,
      ],
    ],
    'yamlform_submission_table' => [
      'variables' => [
        'yamlform_submission' => NULL,
        'source_entity' => NULL,
      ],
    ],
    'yamlform_submission_text' => [
      'variables' => [
        'yamlform_submission' => NULL,
        'source_entity' => NULL,
      ],
    ],
    'yamlform_submission_yaml' => [
      'variables' => [
        'yamlform_submission' => NULL,
        'source_entity' => NULL,
      ],
    ],
    'yamlform_element_base_html' => [
      'variables' => [
        'element' => [],
        'value' => NULL,
        'options' => [],
      ],
    ],
    'yamlform_element_base_text' => [
      'variables' => [
        'element' => [],
        'value' => NULL,
        'options' => [],
      ],
    ],
    'yamlform_container_base_html' => [
      'variables' => [
        'element' => [],
        'value' => NULL,
        'options' => [],
      ],
    ],
    'yamlform_container_base_text' => [
      'variables' => [
        'element' => [],
        'value' => NULL,
        'options' => [],
      ],
    ],
    'yamlform_element_color_value_swatch' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
      ],
    ],
    'yamlform_element_managed_file' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
        'file' => NULL,
      ],
    ],
    'yamlform_element_audio_file' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
        'file' => NULL,
      ],
    ],
    'yamlform_element_document_file' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
        'file' => NULL,
      ],
    ],
    'yamlform_element_image_file' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
        'file' => NULL,
      ],
    ],
    'yamlform_element_video_file' => [
      'variables' => [
        'element' => NULL,
        'value' => NULL,
        'options' => [],
        'file' => NULL,
      ],
    ],
    'yamlform_message' => [
      'render element' => 'element',
    ],
    'yamlform_composite_address' => [
      'render element' => 'element',
    ],
    'yamlform_composite_contact' => [
      'render element' => 'element',
    ],
    'yamlform_composite_creditcard' => [
      'render element' => 'element',
    ],
    'yamlform_composite_location' => [
      'render element' => 'element',
    ],
    'yamlform_composite_name' => [
      'render element' => 'element',
    ],
    'yamlform_codemirror' => [
      'variables' => [
        'code' => NULL,
        'type' => 'text',
      ],
    ],
    'yamlform_progress' => [
      'variables' => [
        'yamlform' => NULL,
        'current_page' => NULL,
      ],
    ],
    'yamlform_progress_bar' => [
      'variables' => [
        'yamlform' => NULL,
        'current_page' => NULL,
        'max_pages' => 10,
      ],
    ],
  ];

  // Since any rendering of a form is going to require 'yamlform.theme.inc'
  // we are going to just add it to every template.
  foreach ($info as &$template) {
    $template['file'] = 'includes/yamlform.theme.inc';
  }
  return $info;
}

/**
 * Implements hook_theme_registry_alter().
 */
function yamlform_theme_registry_alter(&$theme_registry) {

  // Allow attributes to be defined for status messages so that #states
  // can be added to messages.
  // @see \Drupal\yamlform\Element\YamlFormMessage
  if (!isset($theme_registry['status_messages']['variables']['attributes'])) {
    $theme_registry['status_messages']['variables']['attributes'] = [];
  }
}

/**
 * Implements hook_theme_suggestions_alter().
 */
function yamlform_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if (strpos($hook, 'yamlform_') !== 0) {
    return;
  }
  if (strpos($hook, 'yamlform_element_base_') === 0 || strpos($hook, 'yamlform_container_base_') === 0) {
    $element = $variables['element'];
    if (empty($element['#type'])) {
      return;
    }
    $type = $element['#type'];
    $name = $element['#yamlform_key'];
    $suggestions[] = $hook . '__' . $type;
    $suggestions[] = $hook . '__' . $type . '__' . $name;

    /** @var \Drupal\yamlform\YamlFormElementManagerInterface $element_manager */
    $element_manager = \Drupal::service('plugin.manager.yamlform.element');
    $element_handler = $element_manager
      ->createInstance($type);
    if ($format = $element_handler
      ->getFormat($element)) {
      $suggestions[] = $hook . '__' . $type . '__' . $format;
      $suggestions[] = $hook . '__' . $type . '__' . $name . '__' . $format;
    }
  }
  elseif (isset($variables['yamlform_submission'])) {

    /** @var \Drupal\yamlform\YamlFormSubmissionInterface $yamlform_submission */
    $yamlform_submission = $variables['yamlform_submission'];
    $yamlform = $yamlform_submission
      ->getYamlForm();
    $suggestions[] = $hook . '__' . $yamlform
      ->id();
  }
  elseif (isset($variables['yamlform'])) {

    /** @var \Drupal\yamlform\YamlFormInterface $yamlform */
    $yamlform = $variables['yamlform'];
    $suggestions[] = $hook . '__' . $yamlform
      ->id();
  }
}

/**
 * Prepares variables for checkboxes templates.
 *
 * @see \Drupal\yamlform\Plugin\YamlFormElement\OptionsBase
 */
function yamlform_preprocess_checkboxes(&$variables) {
  $element = $variables['element'];
  $options_display = !empty($element['#options_display']) ? $element['#options_display'] : 'one_column';
  $variables['attributes']['class'][] = 'yamlform-options-display-' . str_replace('_', '-', $options_display);
  $variables['#attached']['library'][] = 'yamlform/yamlform.options';
}

/**
 * Prepares variables for radios templates.
 *
 * @see \Drupal\yamlform\Plugin\YamlFormElement\OptionsBase
 */
function yamlform_preprocess_radios(&$variables) {
  yamlform_preprocess_checkboxes($variables);
}

/**
 * Adds JavaScript to change the state of an element based on another element.
 *
 * @param array $elements
 *   A renderable array element having a #states property as described above.
 * @param string $key
 *   The element property to add the states attribute to.
 *
 * @see drupal_process_states()
 */
function yamlform_process_states(&$elements, $key = '#attributes') {
  if (empty($elements['#states'])) {
    return;
  }
  $elements['#attached']['library'][] = 'core/drupal.states';
  $elements[$key]['data-drupal-states'] = Json::encode($elements['#states']);

  // Make sure to include target class for this container.
  if (empty($elements[$key]['class']) || !YamlFormArrayHelper::inArray([
    'js-form-item',
    'js-form-submit',
    'js-form-wrapper',
  ], $elements[$key]['class'])) {
    $elements[$key]['class'][] = 'js-form-item';
  }
}

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

// Private functions.

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

/**
 * Provides custom PHP error handling when form rendering is validated.
 *
 * Converts E_RECOVERABLE_ERROR to WARNING so that an exceptions can be thrown
 * and caught by
 * \Drupal\yamlform\YamlFormEntityElementsValidator::validateRendering().
 *
 * @param int $error_level
 *   The level of the error raised.
 * @param string $message
 *   The error message.
 * @param string $filename
 *   The filename that the error was raised in.
 * @param int $line
 *   The line number the error was raised at.
 * @param array $context
 *   An array that points to the active symbol table at the point the error
 *   occurred.
 *
 * @throws \ErrorException
 *   Throw ErrorException for E_RECOVERABLE_ERROR errors.
 *
 * @see \Drupal\yamlform\YamlFormEntityElementsValidator::validateRendering()
 */
function _yamlform_entity_element_validate_rendering_error_handler($error_level, $message, $filename, $line, array $context) {

  // From: http://stackoverflow.com/questions/15461611/php-try-catch-not-catching-all-exceptions
  if (E_RECOVERABLE_ERROR === $error_level) {

    // Allow Drupal to still log the error but convert it to a warning.
    _drupal_error_handler(E_WARNING, $message, $filename, $line, $context);
    throw new ErrorException($message, $error_level, 0, $filename, $line);
  }
  else {
    _drupal_error_handler($message, $message, $filename, $line, $context);
  }
}

/**
 * Implements hook_query_alter().
 *
 * Append EAV sort to yamlform_submission entity query.
 *
 * @see http://stackoverflow.com/questions/12893314/sorting-eav-database
 * @see \Drupal\yamlform\YamlFormSubmissionListBuilder::getEntityIds
 */
function yamlform_query_alter(AlterableInterface $query) {

  /** @var \Drupal\Core\Database\Query\SelectInterface $query */
  $name = $query
    ->getMetaData('yamlform_submission_element_name');
  if (!$name) {
    return;
  }
  $direction = $query
    ->getMetaData('yamlform_submission_element_direction');
  $property_name = $query
    ->getMetaData('yamlform_submission_element_property_name');
  $query
    ->distinct();
  $query
    ->addJoin('INNER', 'yamlform_submission_data', NULL, 'base_table.sid = yamlform_submission_data.sid');
  $query
    ->addField('yamlform_submission_data', 'value', 'value');
  $query
    ->condition('name', $name);
  if ($property_name) {
    $query
      ->condition('property', $property_name);
  }
  $query
    ->orderBy('value', $direction);
}

Functions

Namesort descending Description
yamlform_css_alter Implements hook_css_alter().
yamlform_entity_delete Implements hook_entity_delete().
yamlform_file_download Implements hook_file_download().
yamlform_form_alter Implements hook_form_alter().
yamlform_help Implements hook_help().
yamlform_js_alter Implements hook_js_alter().
yamlform_local_tasks_alter Implements hook_local_tasks_alter().
yamlform_mail Implements hook_mail().
yamlform_mail_alter Implements hook_mail_alter().
yamlform_menu_local_tasks_alter Implements hook_menu_local_tasks_alter().
yamlform_modules_installed Implements hook_modules_installed().
yamlform_modules_uninstalled Implements hook_modules_uninstalled().
yamlform_page_attachments Implements hook_page_attachments().
yamlform_preprocess_checkboxes Prepares variables for checkboxes templates.
yamlform_preprocess_radios Prepares variables for radios templates.
yamlform_process_states Adds JavaScript to change the state of an element based on another element.
yamlform_query_alter Implements hook_query_alter().
yamlform_system_breadcrumb_alter Implements hook_system_breadcrumb_alter().
yamlform_theme Implements hook_theme().
yamlform_theme_registry_alter Implements hook_theme_registry_alter().
yamlform_theme_suggestions_alter Implements hook_theme_suggestions_alter().
_yamlform_asset_alter Alter CSS or JavaScript assets to include custom form assets.
_yamlform_entity_element_validate_rendering_error_handler Provides custom PHP error handling when form rendering is validated.
_yamlform_form_after_build Alter form after build.

Constants

Namesort descending Description
YAMLFORM_SAVED_DRAFT Return status for saving which deleted an existing item.