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 settings.php. For more information see: DRUPAL-PSA-2016-003'), '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(); }