Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -0,0 +1,58 @@
<?php
/**
* @file
* Callback functions for date, datetime, and time elements.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Datetime\DrupalDateTime;
/**
* Callback for custom datetime datepicker.
*
* @param array $element
* The element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Datetime\DrupalDateTime|null $date
* The date value.
*
* @see \Drupal\webform\Plugin\WebformElement\DateTime::prepare
*/
function _webform_datetime_datepicker(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Convert #type from datepicker to textfield.
if (isset($element['#date_date_element']) && $element['#date_date_element'] === 'datepicker') {
$element['date']['#type'] = 'textfield';
// Must manually set 'data-drupal-date-format' to trigger date picker.
// @see \Drupal\Core\Render\Element\Date::processDate
$element['date']['#attributes']['data-drupal-date-format'] = [$element['date']['#date_date_format']];
}
}
/**
* Callback for custom datetime timepicker.
*
* @param array $element
* The element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Datetime\DrupalDateTime|null $date
* The date value.
*
* @see \Drupal\webform\Plugin\WebformElement\DateTime::prepare
*/
function _webform_datetime_timepicker(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Convert #type from timepicker to textfield.
if (isset($element['#date_time_element']) && $element['#date_time_element'] === 'timepicker') {
$element['time']['#type'] = 'textfield';
}
// Must manually set 'data-webform-time-format' to trigger time picker.
// @see \Drupal\webform\Element\WebformTime::processWebformTime
$element['time']['#attributes']['data-webform-time-format'] = [$element['#date_time_format']];
// Attached custom timepicker library.
$element['time']['#attached']['library'][] = 'webform/webform.element.time';
}

View file

@ -0,0 +1,267 @@
<?php
/**
* @file
* Webform module editor file upload hooks.
*
* Because Webforms are config entities the editor.module's file uploading
* is not supported.
*
* The below code adds file upload support to Webform config entities and
* 'webform.settings' config.
*
* Below functions are copied from editor.module.
*/
use Drupal\Core\Config\Config;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\webform\WebformInterface;
use Drupal\Component\Utility\Html;
/******************************************************************************/
// Webform entity hooks.
/******************************************************************************/
/**
* Implements hook_webform_insert().
*
* @see editor_entity_insert()
*/
function webform_webform_insert(WebformInterface $webform) {
$uuids = _webform_get_config_entity_file_uuids($webform);
_webform_record_file_usage($uuids, $webform->getEntityTypeId(), $webform->id());
}
/**
* Implements hook_webform_update().
*
* @see editor_entity_update()
*/
function webform_webform_update(WebformInterface $webform) {
$original_uuids = _webform_get_config_entity_file_uuids($webform->original);
$uuids = _webform_get_config_entity_file_uuids($webform);
// Detect file usages that should be incremented.
$added_files = array_diff($uuids, $original_uuids);
_webform_record_file_usage($added_files, $webform->getEntityTypeId(), $webform->id());
// Detect file usages that should be decremented.
$removed_files = array_diff($original_uuids, $uuids);
_webform_delete_file_usage($removed_files, $webform->getEntityTypeId(), $webform->id(), 1);
}
/**
* Implements hook_webform_delete().
*
* @see editor_entity_delete()
*/
function webform_webform_delete(WebformInterface $webform) {
$uuids = _webform_get_config_entity_file_uuids($webform);
_webform_delete_file_usage($uuids, $webform->getEntityTypeId(), $webform->id(), 0);
}
/******************************************************************************/
// Webform config (settings) hooks.
// @see \Drupal\webform\Form\AdminConfig\WebformAdminConfigBaseForm::loadConfig
// @see \Drupal\webform\Form\AdminConfig\WebformAdminConfigBaseForm::saveConfig
/******************************************************************************/
/**
* Update config editor file references.
*
* @param \Drupal\Core\Config\Config $config
* An editable configuration object.
*/
function _webform_config_update(Config $config) {
$original_uuids = _webform_get_array_file_uuids($config->getOriginal());
$uuids = _webform_get_array_file_uuids($config->getRawData());
// Detect file usages that should be incremented.
$added_files = array_diff($uuids, $original_uuids);
_webform_record_file_usage($added_files, 'config', $config->getName());
// Detect file usages that should be decremented.
$removed_files = array_diff($original_uuids, $uuids);
_webform_delete_file_usage($removed_files, 'config', $config->getName(), 1);
}
/**
* Delete config editor file references.
*
* @param \Drupal\Core\Config\Config $config
* An editable configuration object.
*
* @see webform_uninstall()
*/
function _webform_config_delete(Config $config) {
$uuids = _webform_get_array_file_uuids($config->getRawData());
_webform_delete_file_usage($uuids, 'config', $config->getName(), 0);
}
/******************************************************************************/
// Config entity functions.
/******************************************************************************/
/**
* Finds all files referenced (data-entity-uuid) by config entity.
*
* @param \Drupal\Core\Config\Entity\ConfigEntityInterface $entity
* An entity whose fields to analyze.
*
* @return array
* An array of file entity UUIDs.
*
* @see _editor_get_file_uuids_by_field()
*/
function _webform_get_config_entity_file_uuids(ConfigEntityInterface $entity) {
return _webform_get_array_file_uuids($entity->toArray());
}
/******************************************************************************/
// Config settings functions.
/******************************************************************************/
/**
* Finds all files referenced (data-entity-uuid) in an associatve array.
*
* @param array $data
* An associative array.
*
* @return array
* An array of file entity UUIDs.
*
* @see _editor_get_file_uuids_by_field()
*/
function _webform_get_array_file_uuids(array $data) {
$text = Yaml::encode($data);
return _webform_parse_file_uuids($text);
}
/******************************************************************************/
// File usage functions.
/******************************************************************************/
/**
* Records file usage of files referenced by formatted text fields.
*
* Every referenced file that does not yet have the FILE_STATUS_PERMANENT state,
* will be given that state.
*
* @param array $uuids
* An array of file entity UUIDs.
* @param string $type
* The type of the object that contains the referenced file.
* @param string $id
* The unique ID of the object containing the referenced file.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*
* @see _editor_record_file_usage()
*/
function _webform_record_file_usage(array $uuids, $type, $id) {
if (empty($uuids) || !\Drupal::moduleHandler()->moduleExists('file')) {
return;
}
/** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
$file_usage = \Drupal::service('file.usage');
foreach ($uuids as $uuid) {
if ($file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid)) {
if ($file->status !== FILE_STATUS_PERMANENT) {
$file->status = FILE_STATUS_PERMANENT;
$file->save();
}
$file_usage->add($file, 'editor', $type, $id);
}
}
}
/**
* Deletes file usage of files referenced by formatted text fields.
*
* @param array $uuids
* An array of file entity UUIDs.
* @param string $type
* The type of the object that contains the referenced file.
* @param string $id
* The unique ID of the object containing the referenced file.
* @param int $count
* The number of references to delete. Should be 1 when deleting a single
* revision and 0 when deleting an entity entirely.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*
* @see \Drupal\file\FileUsage\FileUsageInterface::delete()
* @see _editor_delete_file_usage()
*/
function _webform_delete_file_usage(array $uuids, $type, $id, $count) {
if (empty($uuids) || !\Drupal::moduleHandler()->moduleExists('file')) {
return;
}
/** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
$file_usage = \Drupal::service('file.usage');
$make_unused_managed_files_temporary = \Drupal::config('webform.settings')->get('html_editor.make_unused_managed_files_temporary');
foreach ($uuids as $uuid) {
if ($file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid)) {
$file_usage->delete($file, 'editor', $type, $id, $count);
// Make unused files temporary.
if ($make_unused_managed_files_temporary && empty($file_usage->listUsage($file)) && !$file->isTemporary()) {
$file->setTemporary();
$file->save();
}
}
}
}
/******************************************************************************/
// File parsing functions.
/******************************************************************************/
/**
* Parse an HTML snippet for any linked file with data-entity-uuid attributes.
*
* @param string $text
* The partial (X)HTML snippet to load. Invalid markup will be corrected on
* import.
*
* @return array
* An array of all found UUIDs.
*
* @see _editor_parse_file_uuids()
*/
function _webform_parse_file_uuids($text) {
if (strpos($text, 'data-entity-uuid') === FALSE) {
return [];
}
$uuids = [];
// Get all images using a regex.
if (preg_match_all('/<img[^>]+>/', $text, $matches)) {
foreach ($matches[0] as $img) {
// Cleanup quotes escaped via YAML.
// Please note, calling stripslashes() twice because elements are
// double escaped.
$img = stripslashes(stripslashes($img));
// Create a DomElement so that we can parse the image's attributes.
$dom_node = Html::load($img)->getElementsByTagName('img')->item(0);
// Get the entity type and uuid.
$type = $dom_node->getAttribute('data-entity-type');
$uuid = $dom_node->getAttribute('data-entity-uuid');
// Check the image is a file entity with a uuid.
if ($type === 'file' && $uuid) {
$uuids[] = $uuid;
}
}
}
// Use array_unique() to collect one uuid per uploaded file.
// This prevents cut-n-pasted uploaded files from having multiple usages.
return array_unique($uuids);
}

View file

@ -0,0 +1,366 @@
<?php
/**
* @file
* Webform install helper functions.
*/
use Drupal\Core\Render\Element;
use Drupal\Core\Serialization\Yaml;
use Drupal\system\Entity\Action;
use Drupal\webform\Entity\Webform;
use Drupal\webform\WebformInterface;
/**
* Update admin settings to reflect changes in the default settings.
*
* If you are moving or updating any admin settings this must be explicitly
* done via an update hook.
*
* @param bool $reset
* If set TRUE old admin settings will be completely deleted.
*
* @see drush_webform_repair()
*/
function _webform_update_admin_settings($reset = FALSE) {
$admin_config = \Drupal::configFactory()->getEditable('webform.settings');
$current_settings = $admin_config->getRawData();
$admin_settings = Yaml::decode(file_get_contents(drupal_get_path('module', 'webform') . '/config/install/webform.settings.yml'));
// Note, admin settings are always grouped into associative array,
// except for the langcode.
foreach ($admin_settings as $group => $settings) {
// Handle the rare case the we are adding a new group the admin settings.
if (!isset($current_settings[$group])) {
continue;
}
// Completely copy the format, langcode, and third_party_settings.
if (in_array($group, ['format', 'langcode', 'third_party_settings'])) {
if (isset($current_settings[$group])) {
$admin_settings[$group] = $current_settings[$group];
}
}
elseif ($reset) {
// Copy only group's settings that are defined in admin settings.
// This will cause old settings to be completely deleted.
foreach ($settings as $name => $value) {
if (isset($current_settings[$group][$name])) {
$admin_settings[$group][$name] = $current_settings[$group][$name];
}
}
}
else {
// Loop through the group's settings and apply all existing settings to
// the default admin settings.
foreach ($current_settings[$group] as $name => $value) {
$admin_settings[$group][$name] = $value;
}
}
}
// If not reset, make sure all the current settings are preserved.
if (!$reset) {
$admin_settings += $current_settings;
}
$admin_config->setData($admin_settings)->save();
}
/**
* Update webform settings to reflect changes in the default settings.
*
* This function can be used to apply new webform settings to all existing
* webforms.
*
* @see \Drupal\webform\Entity\Webform::setSettings
*/
function _webform_update_webform_settings() {
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$data = $webform_config->getRawData();
$data = _webform_update_webform_setting($data);
$webform_config->setData($data)->save();
}
}
/**
* Update webform setting to reflect changes in the default settings.
*
* @param array $data
* A webform's raw configuration data from webform.webform.*.yml.
*
* @return array
* Updated raw configuration data.
*/
function _webform_update_webform_setting(array $data) {
$default_properties = [
'langcode' => 'en',
'status' => WebformInterface::STATUS_OPEN,
'dependencies' => [],
'open' => NULL,
'close' => NULL,
'weight' => 0,
'uid' => '',
'template' => FALSE,
'archive' => FALSE,
'id' => '',
'title' => '',
'description' => '',
'category' => '',
'elements' => '',
'css' => '',
'javascript' => '',
'settings' => [],
'access' => [],
'handlers' => [],
];
$default_settings = Webform::getDefaultSettings();
// Always apply the default properties.
$properties = $default_properties;
// Now apply defined properties.
foreach ($data as $name => $value) {
$properties[$name] = $value;
}
// Set properties.
$data = $properties;
// Always apply the default settings.
$settings = $default_settings;
// Now apply custom settings.
foreach ($data['settings'] as $name => $value) {
$settings[$name] = $value;
}
// Set settings.
$data['settings'] = $settings;
// Set access.
/** @var \Drupal\webform\WebformAccessRulesManagerInterface $access_rules_manager */
$access_rules_manager = \Drupal::service('webform.access_rules_manager');
$data['access'] += $access_rules_manager->getDefaultAccessRules();
return $data;
}
/**
* Update webform handler settings to reflect changes in a handler's default configuration.
*
* @see \Drupal\webform\Plugin\WebformHandlerInterface
*/
function _webform_update_webform_handler_settings() {
// Issue #2863986: Allow updating modules with new service dependencies.
\Drupal::service('kernel')->rebuildContainer();
// Get the default configuration (aka settings) for all handlers provided
// by the Webform module.
/** @var \Drupal\webform\Plugin\WebformHandlerManagerInterface $handler_manager */
$handler_manager = \Drupal::service('plugin.manager.webform.handler');
$definitions = $handler_manager->getDefinitions();
$default_handler_settings = [];
foreach ($definitions as $plugin_id => $definition) {
if (strpos($definition['provider'], 'webform_test_') === 0 || in_array($definition['provider'], ['webform', 'webform_scheduled_email'])) {
$default_handler_settings[$plugin_id] = $handler_manager->createInstance($plugin_id)->defaultConfiguration();
}
}
$config_factory = \Drupal::configFactory();
// Update 'webform.webform.*' configuration.
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
// Get data.
$data = $webform_config->getRawData();
// Apply the default handler settings.
$has_handler = FALSE;
foreach ($data['handlers'] as &$handler) {
if (!isset($default_handler_settings[$handler['id']])) {
continue;
}
$settings = $default_handler_settings[$handler['id']];
foreach ($handler['settings'] as $settings_key => $setting_value) {
$settings[$settings_key] = $setting_value;
}
if ($handler['settings'] != $settings) {
$has_handler = TRUE;
$handler['settings'] = $settings;
}
}
if ($has_handler) {
$webform_config->setData($data)->save();
}
}
}
/**
* Update webform options setting to reflect changes in the default settings.
*
* This function can be used to apply new webform options configuration to
* all existing webforms options.
*
* @see \Drupal\webform\Entity\WebformOptions
*/
function _webform_update_options_settings() {
$default_properties = [
'langcode' => 'en',
'status' => TRUE,
'dependencies' => [],
'id' => '',
'label' => '',
'category' => '',
'options' => '',
];
$config_factory = \Drupal::configFactory();
// Update 'webform.webform_options.*' configuration.
foreach ($config_factory->listAll('webform.webform_options.') as $webform_config_name) {
$webform_options_config = $config_factory->getEditable($webform_config_name);
// Get data.
$data = $webform_options_config->getRawData();
// Always apply the default properties.
$properties = $default_properties;
// Now apply defined properties.
foreach ($data as $name => $value) {
$properties[$name] = $value;
}
// Set properties.
$data = $properties;
// Save data.
$webform_options_config->setData($data)->save();
}
}
/**
* Update or install any new system.actions.* config entities.
*/
function _webform_update_actions() {
$files = file_scan_directory(drupal_get_path('module', 'webform') . '/config', '/^system.action..*\.yml$/');
foreach ($files as $path => $file) {
$action_id = str_replace('system.action.', '', $file->name);
$action = Action::load($action_id);
if (!$action) {
// Install new action.
$data = Yaml::decode(file_get_contents($path));
$action = Action::create($data);
$action->trustData()->save();
}
}
}
/**
* Update webform field storage definitions.
*
* @see \Drupal\webform\Plugin\Field\FieldType\WebformEntityReferenceItem::schema
*/
function _webform_update_field_storage_definitions() {
$manager = \Drupal::entityDefinitionUpdateManager();
/** @var \Drupal\field\FieldStorageConfigInterface[] $fields */
$fields = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->loadByProperties(['type' => 'webform']);
foreach ($fields as $field) {
$field_name = $field->getName();
$entity_type = $field->getTargetEntityTypeId();
$manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition($field_name, $entity_type));
}
}
/**
* Update webform submission storage schema.
*
* @see \Drupal\webform\WebformSubmissionStorageSchema
*/
function _webform_update_webform_submission_storage_schema() {
$manager = \Drupal::entityDefinitionUpdateManager();
$manager->updateEntityType($manager->getEntityType('webform_submission'));
}
/**
* Replace string in webform.settings.yml and webform.webform.*.yml.
*
* @param string $search
* String to be search for.
* @param string $replace
* String to be replace with.
*/
function _webform_update_string_replace($search, $replace) {
$config_factory = \Drupal::configFactory();
// Update 'webform.settings' configuration.
$settings_config = \Drupal::configFactory()->getEditable('webform.settings');
$yaml = Yaml::encode($settings_config->getRawData());
if (strpos($yaml, $search) !== FALSE) {
$yaml = str_replace($search, $replace, $yaml);
$settings_config->setData(Yaml::decode($yaml));
$settings_config->save();
}
// Update 'webform.webform.*' configuration.
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$yaml = Yaml::encode($webform_config->getRawData());
if (strpos($yaml, $search) !== FALSE) {
$yaml = str_replace($search, $replace, $yaml);
$webform_config->setData(Yaml::decode($yaml));
$webform_config->save();
}
}
}
/**
* Clear/remove selected webform element properties.
*
* @param array $properties
* An associative array of webform element properties.
*/
function _webform_update_elements_clear_properties(array $properties) {
$pattern = '/(?:' . implode('|', array_keys($properties)) . ')/';
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$data = $webform_config->getRawData();
// Make sure elements contains the properties.
if (!preg_match($pattern, $data['elements'])) {
continue;
}
$elements = Yaml::decode($data['elements']);
_webform_update_elements_clear_properties_recursive($elements, $properties);
$data['elements'] = Yaml::encode($elements);
$webform_config->setData($data);
$webform_config->save();
}
}
/**
* Recursively clear/remove selected webform element properties.
*
* @param array $element
* An element.
* @param array $properties
* An associative array of webform element properties.
*/
function _webform_update_elements_clear_properties_recursive(array &$element, array $properties) {
foreach ($properties as $property_name => $property_value) {
if (isset($element[$property_name]) && $element[$property_name] === $property_value) {
unset($element[$property_name]);
}
}
foreach (Element::children($element) as $key) {
if (is_array($element[$key])) {
_webform_update_elements_clear_properties_recursive($element[$key], $properties);
}
}
}

View file

@ -0,0 +1,170 @@
<?php
/**
* @file
* Webform requirements.
*/
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Url;
use Drupal\webform\Plugin\WebformElement\ManagedFile;
/**
* Implements hook_requirements().
*/
function webform_requirements($phase) {
if ($phase != 'runtime') {
return [];
}
$requirements = [];
/****************************************************************************/
// Check HTML email handling.
/****************************************************************************/
/** @var \Drupal\webform\WebformEmailProviderInterface $email_provider */
$email_provider = \Drupal::service('webform.email_provider');
$mail_module_name = $email_provider->getModuleName();
$mail_plugin_id = $email_provider->getMailPluginId();
$mail_plugin_definition = $email_provider->getMailPluginDefinition();
if ($mail_module_name || $mail_plugin_id) {
$t_args = [
'@module' => $mail_module_name,
'@plugin_id' => $mail_plugin_id,
'@plugin_label' => $mail_plugin_definition['label'],
'@plugin_description' => $mail_plugin_definition['description'],
];
$requirements['webform_email'] = [
'title' => t('Webform: HTML email support'),
'value' => ($mail_module_name) ? t('Provided by the @module module.', $t_args) : t('Provided by @plugin_id mail plugin.', $t_args),
'description' => new FormattableMarkup('@plugin_label: @plugin_description', $t_args),
'severity' => REQUIREMENT_OK,
];
}
else {
$requirements['webform_email'] = [
'title' => t('Webform: HTML email support'),
'value' => t('Unable to determine email module and/or provider'),
'severity' => REQUIREMENT_ERROR,
];
}
/****************************************************************************/
// Check private file upload.
/****************************************************************************/
$scheme_options = ManagedFile::getVisibleStreamWrappers();
if (isset($scheme_options['private'])) {
$requirements['webform_file_private'] = [
'title' => t('Webform: Private files'),
'value' => t('Private file system is set.'),
];
}
else {
$requirements['webform_file_private'] = [
'title' => t('Webform: Private files'),
'value' => t('Private file system is not set.'),
'description' => t('This must be changed in <a href="https://www.drupal.org/documentation/modules/file">settings.php</a>. For more information see: <a href="https://www.drupal.org/psa-2016-003">DRUPAL-PSA-2016-003</a>'),
'severity' => REQUIREMENT_WARNING,
];
}
/****************************************************************************/
// Check external libraries.
/****************************************************************************/
/** @var \Drupal\webform\WebformLibrariesManagerInterface $libraries_manager */
$libraries_manager = \Drupal::service('webform.libraries_manager');
$requirements += $libraries_manager->requirements();
/****************************************************************************/
// Check Bootstrap theme.
/****************************************************************************/
if (\Drupal::config('webform.settings')->get('requirements.bootstrap')) {
$spam_protection = FALSE;
$themes = \Drupal::service('theme_handler')->listInfo();
foreach ($themes as $theme) {
if ((isset($theme->base_themes) && isset($theme->base_themes['bootstrap'])) || $theme == 'bootstrap') {
$spam_protection = TRUE;
}
}
if ($spam_protection) {
if (\Drupal::moduleHandler()->moduleExists('webform_bootstrap')) {
$requirements['webform_bootstrap'] = [
'title' => t('Webform: Bootstrap integration'),
'value' => t('Webform Bootstrap module installed.'),
];
}
else {
$requirements['webform_bootstrap'] = [
'title' => t('Webform: Bootstrap integration'),
'value' => t('Webform Bootstrap Integration module not installed.'),
'description' => t('The Webform Bootstrap module helps support Webform to Bootstrap integration. <a href=":href">Disable Webform Bootstrap Integration warning</a>', [':href' => Url::fromRoute('webform.config.advanced')->toString()]),
'severity' => REQUIREMENT_WARNING,
];
}
}
}
/****************************************************************************/
// Check SPAM protection.
/****************************************************************************/
if (\Drupal::config('webform.settings')->get('requirements.spam')) {
$spam_protection = FALSE;
$installed_projects = [
'#prefix' => '<p><hr/></p><dl>',
'#suffix' => '</dl>',
];
$available_projects = [
'#prefix' => '<p><hr/></p><dl>',
'#suffix' => '</dl>',
];
/** @var \Drupal\webform\WebformAddonsManagerInterface $addons_manager */
$addons_manager = \Drupal::service('webform.addons_manager');
$projects = $addons_manager->getProjects('spam');
foreach ($projects as $project_name => $project) {
$available_projects[$project_name] = [
'title' => [
'#type' => 'link',
'#title' => $project['title'],
'#url' => $project['url'],
'#prefix' => '<dt><strong>',
'#suffix' => '</strong></dt>',
],
'description' => [
'#markup' => $project['description'],
'#prefix' => '<dd>',
'#suffix' => '</dd>',
],
];
if (\Drupal::moduleHandler()->moduleExists($project_name)) {
$spam_protection = TRUE;
$installed_projects[$project_name] = $available_projects[$project_name];
}
}
if ($spam_protection) {
$requirements['webform_spam'] = [
'title' => t('Webform: SPAM protection'),
'value' => t('Webform SPAM protection module installed.'),
'description' => \Drupal::service('renderer')->renderPlain($installed_projects),
];
}
else {
$requirements['webform_spam'] = [
'title' => t('Webform: SPAM protection'),
'value' => t('Webform <a href=":href">SPAM protection module</a> missing. Please install one of the below modules.', [':href' => 'https://www.drupal.org/node/206787']),
'description' => \Drupal::service('renderer')->renderPlain($available_projects),
'severity' => REQUIREMENT_WARNING,
];
}
}
// Sort all requirements alphabetically.
ksort($requirements);
return $requirements;
}

File diff suppressed because it is too large Load diff

View file

@ -9,20 +9,50 @@
* Implements hook_library_info_alter().
*/
function webform_library_info_alter(&$libraries, $extension) {
// Only alter webform libraries.
if ($extension != 'webform') {
$webform_libraries_modules = \Drupal::moduleHandler()->getImplementations('webform_libraries_info');
$webform_libraries_modules[] = 'webform';
// Only alter modules that declare webform libraries.
// @see hook_webform_libraries_info()
if (!in_array($extension, $webform_libraries_modules)) {
return;
}
// Add off-canvas system tray to dialog dependencies.
if (isset($libraries['webform.admin.dialog']) && (floatval(\Drupal::VERSION) >= 8.3) && \Drupal::moduleHandler()->moduleExists('outside_in')) {
$libraries['webform.admin.dialog']['dependencies'][] = 'outside_in/drupal.off_canvas';
$libraries['webform.admin.dialog']['dependencies'][] = 'outside_in/drupal.outside_in';
// Prevent duplicate instances of the chosen plugin and use
// the chosen_lib.module's as the dependency.
if (isset($libraries['webform.element.chosen']) && \Drupal::moduleHandler()->moduleExists('chosen_lib')) {
$dependencies =& $libraries['webform.element.chosen']['dependencies'];
foreach ($dependencies as $index => $dependency) {
if ($dependency === 'webform/libraries.jquery.chosen') {
$dependencies[$index] = 'chosen_lib/chosen';
$dependencies[] = 'chosen_lib/chosen.css';
break;
}
}
}
/** @var \Drupal\webform\WebformLibrariesManagerInterface $libraries_manager */
$libraries_manager = \Drupal::service('webform.libraries_manager');
// Map /library/* paths to CDN.
// @see webform.libraries.yml.
foreach ($libraries as &$library) {
foreach ($libraries as $library_name => &$library) {
// Remove excluded libraries.
if ($libraries_manager->isExcluded($library_name)) {
unset($libraries[$library_name]);
continue;
}
if (!empty($library['dependencies'])) {
// Remove excluded libraries from dependencies.
foreach ($library['dependencies'] as $dependency_index => $dependency_name) {
if ($libraries_manager->isExcluded($dependency_name)) {
$library['dependencies'][$dependency_index] = NULL;
$library['dependencies'] = array_filter($library['dependencies']);
}
}
}
// Check CDN setting exists.
if (!isset($library['cdn'])) {
continue;
@ -58,12 +88,13 @@ function _webform_library_info_alter_recursive(array &$library, array $cdn) {
continue;
}
// Replace the CDN sources (ie /library/*) with the CDN URL destination
// Replace the CDN sources (i.e. /library/*) with the CDN URL destination
// (https://cdnjs.cloudflare.com/ajax/libs/*).
foreach ($cdn as $source => $destination) {
if (strpos($key, $source) === 0) {
$uri = str_replace($source, $destination, $key);
$library[$uri] = $value;
$library[$uri]['type'] = 'external';
unset($library[$key]);
break;
}

View file

@ -36,32 +36,40 @@ function webform_webform_options_range_alter(array &$options, array $element = [
* Implements hook_webform_options_WEBFORM_OPTIONS_ID_alter().
*/
function webform_webform_options_time_zones_alter(array &$options, array $element = []) {
$options = system_time_zones();
if (empty($options)) {
$options = system_time_zones();
}
}
/**
* Implements hook_webform_options_WEBFORM_OPTIONS_ID_alter().
*/
function webform_webform_options_country_codes_alter(array &$options, array $element = []) {
$options = CountryManager::getStandardList();
if (empty($options)) {
$options = CountryManager::getStandardList();
}
}
/**
* Implements hook_webform_options_WEBFORM_OPTIONS_ID_alter().
*/
function webform_webform_options_country_names_alter(array &$options, array $element = []) {
$countries = CountryManager::getStandardList();
$options = array_combine($countries, $countries);
if (empty($options)) {
$countries = CountryManager::getStandardList();
$options = array_combine($countries, $countries);
}
}
/**
* Implements hook_webform_options_WEBFORM_OPTIONS_ID_alter().
*/
function webform_webform_options_languages_alter(array &$options, array $element = []) {
$languages = LanguageManager::getStandardLanguageList();
unset($languages['en-x-simple']);
$options = [];
foreach ($languages as $language) {
$options[$language[0]] = $language[0];
if (empty($options)) {
$languages = LanguageManager::getStandardLanguageList();
unset($languages['en-x-simple']);
$options = [];
foreach ($languages as $language) {
$options[$language[0]] = $language[0];
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,14 +3,43 @@
/**
* @file
* Webform module translation hooks.
*
* @see webform_preprocess_table()
*/
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\webform\Entity\Webform;
use Drupal\webform\Utility\WebformYaml;
use Drupal\Core\Serialization\Yaml;
use Drupal\webform\Utility\WebformElementHelper;
/**
* Implements hook_form_FORM_ID_alter().
*/
function webform_form_locale_translate_edit_form_alter(&$form, FormStateInterface $form_state) {
// Don't allow YAML to be validated using locale string translation.
foreach (Element::children($form['strings']) as $key) {
$element =& $form['strings'][$key];
if ($element['original']
&& !empty($element['original']['#plain_text'])
&& preg_match("/'#[^']+':/", $element['original']['#plain_text'])
&& WebformYaml::isValid($element['original']['#plain_text'])) {
$element['original'] = [
'#theme' => 'webform_codemirror',
'#code' => $element['original']['#plain_text'],
'#type' => 'yaml',
];
$element['translations'] = [
'#type' => 'webform_message',
'#message_type' => 'warning',
'#message_message' => t("Webforms can only be translated via the Webform's (Configuration) Translate tab."),
];
}
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
@ -33,8 +62,8 @@ function webform_form_config_translation_add_form_alter(&$form, FormStateInterfa
$translation_langcode = $form_state->get('config_translation_language')->getId();;
$source_elements = $translation_manager->getSourceElements($webform);
$translation_elements = $translation_manager->getTranslationElements($webform, $translation_langcode);
$source_value = trim(Yaml::encode($source_elements));
$translation_value = trim(Yaml::encode($translation_elements));
$source_value = WebformYaml::encode($source_elements);
$translation_value = WebformYaml::encode($translation_elements);
_webform_form_config_translate_add_form_alter_yaml_element($config_element['elements'], $source_value, $translation_value);
@ -52,6 +81,10 @@ function webform_form_config_translation_add_form_alter(&$form, FormStateInterfa
* Validate callback; Validates and cleanups webform elements.
*/
function _webform_form_config_translate_add_form_validate(&$form, FormStateInterface $form_state) {
if ($form_state::hasAnyErrors()) {
return;
}
$values = $form_state->getValues();
$config_name = $form_state->get('webform_config_name');
@ -129,8 +162,77 @@ function _webform_form_config_translate_add_form_alter_yaml_element(array &$elem
$element['translation']['#type'] = 'webform_codemirror';
$element['translation']['#mode'] = 'yaml';
if ($translation_value) {
$element['translation']['#default_value'] = $translation_value;
$element['translation']['#default_value'] = WebformYaml::tidy($translation_value);
}
$element['translation']['#default_value'] = trim($element['translation']['#default_value']);
$element['#attached']['library'][] = 'webform/webform.admin.translation';
}
/******************************************************************************/
// Lingotek integration.
/******************************************************************************/
/**
* Implements hook_lingotek_config_entity_document_upload().
*/
function webform_lingotek_config_entity_document_upload(array &$source_data, ConfigEntityInterface &$entity, &$url) {
switch ($entity->getEntityTypeId()) {
case 'webform';
/** @var \Drupal\webform\WebformTranslationManagerInterface $translation_manager */
$translation_manager = \Drupal::service('webform.translation_manager');
// Replace elements with just the translatable properties
// (i.e. #title, #description, #options, etc…) so that Lingotek's
// translation services can correctly translate each element.
$translation_elements = $translation_manager->getTranslationElements($entity, $entity->language()->getId());
$source_data['elements'] = $translation_elements;
// Encode all [tokens].
$yaml = Yaml::encode($source_data);
$yaml = preg_replace_callback(
'/\[([a-z][^]]+)\]/',
function ($matches) {
return '[***' . base64_encode($matches[1]) . '***]';
},
$yaml
);
$source_data = Yaml::decode($yaml);
break;
case 'webform_options';
// Convert options YAML string to an associative array.
$source_data['options'] = Yaml::decode($source_data['options']);
break;
}
}
/**
* Implements hook_lingotek_config_entity_translation_presave().
*/
function webform_lingotek_config_entity_translation_presave(ConfigEntityInterface &$translation, $langcode, &$data) {
switch ($translation->getEntityTypeId()) {
case 'webform';
// Decode all [tokens].
$yaml = Yaml::encode($data);
$yaml = preg_replace_callback(
'/\[\*\*\*([^]]+)\*\*\*\]/',
function ($matches) {
return '[' . base64_decode($matches[1]) . ']';
},
$yaml
);
$data = Yaml::decode($yaml);
/** @var \Drupal\webform\WebformInterface $translation */
$translation->setElements($data['elements']);
$data['elements'] = Yaml::encode($data['elements']);
break;
case 'webform_options';
/** @var \Drupal\webform\WebformOptionsInterface $translation */
// Convert options associative array back to YAML string.
$translation->setOptions($data['options']);
$data['options'] = Yaml::encode($data['options']);
break;
}
}