This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/web/modules/contrib/webform/webform.install
2017-03-16 15:29:07 +00:00

555 lines
18 KiB
Plaintext

<?php
/**
* @file
* Install, update and uninstall functions for the Webform module.
*/
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Database\Database;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Render\Element;
use Drupal\system\Entity\Action;
use Drupal\webform\Entity\Webform;
use Drupal\webform\WebformInterface;
use Drupal\webform\Plugin\WebformElement\ManagedFile;
/**
* Implements hook_uninstall().
*/
function webform_uninstall() {
// Issue #2793597: uninstall error You have requested a non-existent service
// "webform.email_provider".
// Workaround: Don't use the webform.email_provider in hook_uninstall().
// @see \Drupal\webform\WebformEmailProvider::uninstall()
$config = \Drupal::configFactory()->getEditable('system.mail');
$mail_plugins = $config->get('interface');
unset($mail_plugins['webform']);
$config->set('interface', $mail_plugins)->save();
}
/**
* 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');
$email_provider->check();
$module = $email_provider->getModuleName();
$mail_plugin_id = $email_provider->getMailPluginId();
$mail_plugin_definition = $email_provider->getMailPluginDefinition();
if ($module || $mail_plugin_id) {
$t_args = [
'@module' => $module,
'@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' => ($module) ? 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 third party libraries status.
/** @var \Drupal\webform\WebformLibrariesManagerInterface $libraries_manager */
$libraries_manager = \Drupal::service('webform.libraries_manager');
$requirements += $libraries_manager->requirements();
return $requirements;
}
/******************************************************************************/
// Helper functions
/******************************************************************************/
/**
* Update admin settings to reflect changes in the default settings.
*
* This function is used to apply new admin settings (in webform.settings.yml).
* If you are moving or updating any admin settings this must be explicitly
* done via an update hook.
*/
function _webform_update_admin_settings() {
$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];
}
}
else {
// Loop through the group's settings and apply all existing settings to
// the default admin settings.
foreach ($settings as $name => $value) {
if (isset($current_settings[$group][$name])) {
$admin_settings[$group][$name] = $current_settings[$group][$name];
}
}
}
}
$admin_config->setData($admin_settings)->save();
}
/**
* Update webform setting 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_form_settings() {
$default_properties = [
'langcode' => 'en',
'status' => WebformInterface::STATUS_OPEN,
'open' => NULL,
'close' => NULL,
'dependencies' => [],
'uid' => '',
'template' => FALSE,
'id' => '',
'title' => '',
'description' => '',
'elements' => '',
'css' => '',
'javascript' => '',
'settings' => [],
'access' => [],
'handlers' => [],
];
$default_settings = Webform::getDefaultSettings();
$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();
// 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;
// Save data.
$webform_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 hooks.
/******************************************************************************/
/**
* Issue #2834203: Convert webform field target_id to 32 characters.
*/
function webform_update_8001() {
$database_schema = \Drupal::database()->schema();
$schema = \Drupal::keyValue('entity.storage_schema.sql')->getAll();
foreach ($schema as $item_name => $item) {
foreach ($item as $table_name => $table_schema) {
foreach ($table_schema as $schema_key => $schema_data) {
if ($schema_key == 'fields') {
foreach ($schema_data as $field_name => $field_data) {
if (preg_match('/_target_id$/', $field_name) && $field_data['description'] == 'The ID of the webform entity.' && $schema[$item_name][$table_name]['fields'][$field_name]['length'] === 255) {
$schema[$item_name][$table_name]['fields'][$field_name]['length'] = 32;
if ($database_schema->tableExists($table_name)) {
$database_schema->changeField($table_name, $field_name, $field_name, $schema[$item_name][$table_name]['fields'][$field_name]);
}
}
}
}
}
}
}
\Drupal::keyValue('entity.storage_schema.sql')->setMultiple($schema);
}
/**
* Issue #2834572: Refactor and improve token management.
*/
function webform_update_8002() {
$config_factory = \Drupal::configFactory();
// Update 'webform.settings' configuration.
$settings_config = \Drupal::configFactory()->getEditable('webform.settings');
$yaml = Yaml::encode($settings_config->getRawData());
$yaml = str_replace('[webform_submission:', '[webform_submission:', $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());
$yaml = str_replace('[webform_submission:', '[webform_submission:', $yaml);
$webform_config->setData(Yaml::decode($yaml));
$webform_config->save();
}
}
/**
* Issue #2834654: Add close button to messages.
*/
function webform_update_8003() {
// Change webform.* to webform.* state.
$webforms = Webform::loadMultiple();
foreach ($webforms as $webform) {
$state = \Drupal::state()->get('webform.' . $webform->id(), NULL);
if ($state !== NULL) {
\Drupal::state()->set('webform.webform.' . $webform->id(), $state);
\Drupal::state()->delete('webform.' . $webform->id());
}
}
}
/**
* Issue #2836948: Problem with autocomplete field. Change '#autocomplete_options' to '#autocomplete_items'.
*/
function webform_update_8004() {
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$elements = $webform_config->get('elements');
if (strpos($elements, '#autocomplete_options') !== FALSE) {
$elements = str_replace('#autocomplete_options', '#autocomplete_items', $elements);
$webform_config->set('elements', $elements);
$webform_config->save(TRUE);
}
}
}
/**
* Issue #2837090: Undefined function call webform_schema.
*/
function webform_update_8005() {
// @see webform_update_8006() which fixes this broken hook.
}
/**
* Issue #2837090: Undefined function call webform_schema.
*/
function webform_update_8006() {
// Fix key_value.collection which was no updated during the migration.
$module_handler = \Drupal::moduleHandler();
$database_type = Database::getConnection('default')->databaseType();
if ($module_handler->moduleExists('webform') && !$module_handler->moduleExists('yamlform') && $database_type == 'mysql') {
$database = \Drupal::database();
$select = $database->select('key_value', 'kv');
$select->fields('kv', ['collection', 'name', 'value']);
$select->condition('collection', '%yamlform%', 'LIKE');
$result = $select->execute();
while ($record = $result->fetchAssoc()) {
$old_collection = $record['collection'];
$new_collection = str_replace('yamlform', 'webform', $record['collection']);
$collection_select = $database->select('key_value', 'kv');
$collection_select->fields('kv', ['collection', 'name', 'value']);
$collection_select->condition('collection', $new_collection);
$collection_result = $collection_select->execute();
// Only insert the new record if there the collection does not exist.
if (!$collection_result->fetchAll()) {
$record['collection'] = $new_collection;
$database->insert('key_value')
->fields(['collection', 'name', 'value'])
->values(array_values($record))
->execute();
}
// Delete the old record.
$database->delete('key_value')
->condition('collection', $old_collection)
->execute();
}
}
}
/**
* Issue #2840521: Add support for global CSS and JS.
*/
function webform_update_8007() {
_webform_update_admin_settings();
}
/**
* Issue #2839615: Disabling message about viewing user's previous submissions.
*/
function webform_update_8008() {
_webform_update_form_settings();
}
/**
* Issue #2844020: Add admin and form specific setting to allow submit button to be clicked only once.
*/
function webform_update_8009() {
_webform_update_admin_settings();
_webform_update_form_settings();
}
/**
* Issue #2843400: Automated purging of submissions.
*/
function webform_update_8010() {
_webform_update_admin_settings();
_webform_update_form_settings();
}
/**
* Issue #2845028: Refactor and rework element formatting to better support multiple values.
*/
function webform_update_8011() {
// Update admin.settings format to support
// 'formats.{element_type}.item' and 'formats.{element_type}.items'.
$admin_config = \Drupal::configFactory()->getEditable('webform.settings');
$data = $admin_config->getRawData();
if (!empty($data['format'])) {
foreach ($data['format'] as $element_type => $element_format) {
if (is_string($element_format)) {
$data['format'][$element_type] = ['item' => $element_format];
}
}
$admin_config->setData($data)->save();
}
// Update webform element to support #format_items.
$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();
if (strpos($data['elements'], "'#format'") === FALSE) {
continue;
}
$elements = Yaml::decode($data['elements']);
_webform_update_8011($elements);
$data['elements'] = Yaml::encode($elements);
$webform_config->setData($data);
$webform_config->save();
}
}
/**
* Move $element['#format'] to $element['#format_items'].
*
* Applies to ol, ul, comma, and semicolon.
*
* @param array $element
* A form element.
*/
function _webform_update_8011(array &$element) {
if (isset($element['#format'])) {
/** @var \Drupal\webform\WebformElementManagerInterface $element_manager */
$element_manager = \Drupal::service('plugin.manager.webform.element');
$webform_element = $element_manager->getElementInstance($element);
$format = $element['#format'];
$item_formats = $webform_element->getItemFormats();
$items_formats = $webform_element->getItemsFormats();
if (!isset($item_formats[$format]) && isset($items_formats[$format])) {
unset($element['#format']);
$element['#format_items'] = $format;
}
}
foreach (Element::children($element) as $key) {
if (is_array($element[$key])) {
_webform_update_8011($element[$key]);
}
}
}
/**
* Issue #2845776: Improve #multiple handling.
*/
function webform_update_8012() {
_webform_update_admin_settings();
}
/**
* Issue #2840858: Create Webform and Webform Submission Action plugins.
*/
function webform_update_8013() {
_webform_update_actions();
}
/**
* Issue #2848042: Rework #type shorthand prefix handling.
*/
function webform_update_8014() {
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
// Get data, get elements, and update elements #type.
$data = $webform_config->getRawData();
$elements = Yaml::decode($data['elements']);
// Make sure $elements has been decoded into an array.
if (is_array($elements)) {
_webform_update_8014($elements);
// Set elements, set data, and save data.
$data['elements'] = Yaml::encode($elements);
$webform_config->setData($data);
$webform_config->save();
}
}
}
/**
* Add 'webform_' prefix to #type.
*
* @param array $element
* A form element.
*/
function _webform_update_8014(array &$element) {
/** @var \Drupal\webform\WebformElementManagerInterface $element_manager */
$element_manager = \Drupal::service('plugin.manager.webform.element');
// Add 'webform_' prefix to #type.
if (isset($element['#type']) && !$element_manager->hasDefinition($element['#type']) && $element_manager->hasDefinition('webform_' . $element['#type'])) {
$element['#type'] = 'webform_' . $element['#type'];
}
foreach (Element::children($element) as $key) {
if (is_array($element[$key])) {
_webform_update_8014($element[$key]);
}
}
}
/**
* Issue #2850247: Experiment with system tray integration.
*/
function webform_update_8015() {
_webform_update_admin_settings();
}
/**
* Issue #2850455: Add lookup_keys to webform config entity. Flush cache entity definitions.
*/
function webform_update_8016() {
drupal_flush_all_caches();
}
/**
* Issue #2850455: Add lookup_keys to webform config entity. Update Webform lookup keys.
*/
function webform_update_8017() {
// Must resave all Webform config lookup keys.
// @see \Drupal\Core\Config\Entity\Query\QueryFactory::updateConfigKeyStore
$webforms = Webform::loadMultiple();
foreach ($webforms as $webform) {
$webform->save();
}
}
/**
* Issue #2850885: Add ability to disable autocomplete for form and/or element.
*/
function webform_update_8018() {
_webform_update_admin_settings();
_webform_update_form_settings();
}
/**
* Issue #2853302: Allow confirmation page title to be customized.
*/
function webform_update_8019() {
_webform_update_form_settings();
}
/**
* Issue #2845724: Add webform opening and closing date/time.
*/
function webform_update_8020() {
// Resave all webforms to convert status boolean to string.
$webforms = Webform::loadMultiple();
foreach ($webforms as $webform) {
$webform->setStatus($webform->get('status'))->save();
}
_webform_update_form_settings();
}