Skip to content
Snippets Groups Projects
uw_cfg_common.module 84.8 KiB
Newer Older
Liam Morland's avatar
Liam Morland committed
<?php

/**
 * @file
 * Module file.
 */

use Drupal\Component\Utility\Html;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
Igor Biki's avatar
Igor Biki committed
use Drupal\Core\Entity\EntityInterface;
Liam Morland's avatar
Liam Morland committed
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\fillpdf\Controller\HandlePdfController;
use Drupal\fillpdf\Form\FillPdfFormForm;
use Drupal\media_library\MediaLibraryState;
use Drupal\uw_cfg_common\Service\UWService;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformSubmissionStorageInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
Liam Morland's avatar
Liam Morland committed

include_once 'includes/helper_functions.php';

 * Implements hook_preprocess_form_element().
 *
 * Allows for use of label_class in form elements and will add
 * any class in label_classes to the label.
 */
function uw_cfg_common_preprocess_form_element(&$variables) {
  if (isset($variables['element']['#label_classes'])) {
    $variables['label']['#attributes']['class'] = $variables['element']['#label_classes'];
  }
}

/**
 * Implements template_preprocess_form_element_label().
 */
function uw_cfg_common_preprocess_form_element_label(&$variables) {

  // Check if we need to add the form required to the label.
  // Conditions are not the blank summary checkbox,
  // the id of the label contains edit-field-uw and has
  // either summary or position in the id.
  if (
    isset($variables['element']['#id']) &&
    $variables['element']['#id'] !== 'edit-field-uw-blank-summary-value' &&
    str_contains($variables['element']['#id'], 'edit-field-uw-') &&
    (
      str_contains($variables['element']['#id'], 'summary') ||
      str_contains($variables['element']['#id'], 'position')
    )
  ) {

    // Try and get the node type, by replacing the id of the label.
    $node_type = $variables['element']['#id'];
    $node_type = str_replace('edit-field-uw-', '', $node_type);
    $node_type = str_replace('-summary-0-value', '', $node_type);
    $node_type = str_replace('-position-0-value', '', $node_type);

    // The node types to place the form required on the label.
    $blank_summary_node_types = [
      'blog',
      'event',
      'news',
      'opportunity',
      'profile',
      'project',
    ];

    // If we are on a node that needs a form required
    // on the label add the class.
    if (in_array($node_type, $blank_summary_node_types)) {
      $variables['attributes']['class'][] = 'form-required';
    }
  }
}

/**
 * Implements hook_sendgrid_integration_categories_alter().
 *
 * Set the category for all sendmail as WCMS.
 */
function uw_cfg_common_sendgrid_integration_categories_alter($message, $categories) {
  $categories = ['WCMS'];

  return $categories;
}

 * Implements hook_metatags_attachments_alter().
function uw_cfg_common_metatags_attachments_alter(array &$metatag_attachments) {
  // Check if the image and og:image fields are empty.
  // We do this here instead of in hook_metatags_alter() because we want to
  // check if they're empty after tokens have been applied.
  // We also want to support the use case where they don't upload an image,
  // but do manually specify an image.
  // Because of where the information is stored, we have to loop to find it.
  $found_image_src = FALSE;
  $found_og_image = FALSE;
  foreach ($metatag_attachments['#attached']['html_head'] as $attachment) {
    if ($attachment[1] == 'image_src') {
      $found_image_src = TRUE;
    }
    elseif ($attachment[1] == 'og_image_0') {
      $found_og_image = TRUE;
    }
  }
  // Define what the fallback image is, so we only need to change it once.
  $fallback_image = 'https://uwaterloo.ca/university-of-waterloo-logo-152.png';
  // If the image_src field is missing, create one with the UWaterloo logo.
  if (!$found_image_src) {
    $metatag_attachments['#attached']['html_head'][] = [
      0 => [
        '#tag' => 'link',
        '#attributes' => [
          'rel' => "image_src",
          'href' => $fallback_image,
  // If the og:image field is missing, create one with the UWaterloo logo.
  if (!$found_og_image) {
    $metatag_attachments['#attached']['html_head'][] = [
      0 => [
        '#tag' => 'meta',
        '#attributes' => [
          'property' => "og:image",
          'content' => $fallback_image,
      ],
      1 => 'og_image_0',
    ];
Igor Biki's avatar
Igor Biki committed
function uw_cfg_common_entity_presave(EntityInterface $entity) {

  // Check if we are on a menu link.
  if ($entity->getEntityTypeId() == 'menu_link_content') {

    // Check that we are on a Information For (audience) link.
    if ($entity->menu_name->value == 'uw-menu-audience-menu') {

      // Invalid all the menu caching.
      \Drupal::cache('menu')->invalidateAll();

      // Rebuild all the menus.
      \Drupal::service('plugin.manager.menu.link')->rebuild();
    }
  }

  // On a node entity save, check if the responsive
  // image has created the derivatives so that things
  // like hero images will load when no image has yet
  // been rendered.  If we do not do this, most hero
  // images will not work.
  if ($entity->getEntityTypeId() == 'node') {

    // ISTWCMS-5846: if the leave summary blank is checked
    // on the node add/edit page, set the summary to NULL.
    // Check that the node has the field leave summary blank.
    if ($entity->hasField('field_uw_blank_summary')) {

      // If the leave summary blank is checked, set summary to NULL.
      if ($entity->field_uw_blank_summary->value) {

        // Get the node type from the entity.
        $node_type = $entity->getType();

        // Since all the summary fields are field_uw_ct_<node_type>_summary,
        // we need to get the node_type from the getType.  We need this
        // because the node_type has uw_ct_ in the name, so simply replacing
        // the uw_ct_ with nothing will give us the node_type.
        // the uw_ct_ with nothing will give us the node_type.
        $node_type = str_replace('uw_ct_', '', $node_type);

        // Since news has the content type with news_item, we need
        // to remove the _item to get the correct field name.
        $node_type = str_replace('_item', '', $node_type);

        // Set the field name using the notation from above.
        $field_name = 'field_uw_' . $node_type . '_summary';

        // Now set the summary to NULL using the field_name.
        $entity->$field_name = NULL;
      }
    }

    // If there is a hero image (media), continue to process.
    if (
      $entity->hasField('field_uw_hero_image') &&
      $media = $entity->field_uw_hero_image->entity
    ) {
      // Hero media exists, get file entity from media.
      if ($file = $media->field_media_image->entity) {

        // Load the image styles that are needed for the hero.
        $uw_styles = \Drupal::service('uw_cfg_common.uw_service')->uwGetResponsiveImageStyles();

        // Step through each of the image styles and ensure that
        // the derivative is created.
        foreach ($uw_styles as $uw_style) {

          // Load the image style.
          $style = \Drupal::entityTypeManager()
            ->getStorage('image_style')
            ->load($uw_style);

          // Get the styled image derivative.
          $destination = $style->buildUri($file->getFileUri());

          // If the derivative doesn't exist yet (as the image style may
          // have been added post launch), create it.
          if (!file_exists($destination)) {
            $style->createDerivative($file->getFileUri(), $destination);
          }
Liam Morland's avatar
Liam Morland committed
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Remove the None option from layout builder styles.
 */
function uw_cfg_common_form_layout_builder_configure_section_alter(array &$form, FormStateInterface $form_state, string $form_id): void {

  // Column separator group should not appear one column.
  if (isset($form['layout_builder_style_column_separator'])) {
    // Ensuring that none is selected for column separator by default.
    if (!isset($form['layout_builder_style_column_separator']['#default_value'])) {
      $form['layout_builder_style_column_separator']['#default_value'] = 'uw_lbs_column_separator_none';
    }
  }

  // Ensuring that none is selected for section separator by default.
  if (!isset($form['layout_builder_style_section_separator']['#default_value'])) {
    $form['layout_builder_style_section_separator']['#default_value'] = 'uw_lbs_section_separator_none';
  }

  // Ensuring that default is selected for section spacing by default.
  if (!isset($form['layout_builder_style_section_spacing']['#default_value'])) {
    $form['layout_builder_style_section_spacing']['#default_value'] = 'uw_lbs_section_spacing_default';
  }
Liam Morland's avatar
Liam Morland committed
  // Ensuring that the contained width is selected by default.
  if (!isset($form['layout_builder_style_default']['#default_value'])) {
    $form['layout_builder_style_default']['#default_value'] = 'uw_lbs_contained_width';
  }

  // Layout builder style - background style default and removing
  // empty(none) option.
  if ($form['layout_builder_style_section_background']['#default_value'] === NULL) {
    $form['layout_builder_style_section_background']['#default_value'] = 'uw_lbs_section_background_full_width';
  }
  unset($form['layout_builder_style_section_background']['#empty_option']);

  $config = $form_state->getFormObject()->getLayout()->getConfiguration();

  $form['layout_builder_background_type'] = [
    '#type' => 'select',
    '#title' => t('Background'),
    '#options' => [
      'none' => t('None'),
      'solid_color' => t('Solid colour'),
      'image' => t('Image'),
    ],
    '#weight' => 80,
    '#default_value' => $config['layout_builder_background_type'] ?? 'none',
  ];

  $form['layout_builder_background_color'] = [
    '#type' => 'select',
    '#title' => t('Background colour'),
    '#options' => [
      'neutral' => t('Light grey'),
      'org-default' => t('UW Gold'),
      'org-default-b' => t('UW Black'),
      'org-art' => t('Orange (Arts)'),
      'org-eng' => t('Purple (Engineering)'),
      'org-env' => t('Green (Environment)'),
      'org-ahs' => t('Teal (Health)'),
      'org-mat' => t('Pink (Mathematics)'),
      'org-sci' => t('Blue (Science)'),
      'org-school' => t('Red (school)'),
      'org-cgc' => t('Red (Conrad Grebel University College)'),
      'org-ren' => t('Green (Renison University College)'),
      'org-stj' => t('Green (St. Jerome’s University)'),
      'org-stp' => t('Blue (United College)'),
    ],
    '#weight' => 81,
    '#default_value' => $config['layout_builder_background_color'] ?? 'neutral',
    '#states' => [
      'visible' => [
        ':input[name="layout_builder_background_type"]' => ['value' => 'solid_color'],
      ],
    ],
  ];

  $form['layout_builder_background_image'] = [
    '#type' => 'media_library',
    '#allowed_bundles' => ['uw_mt_image'],
    '#title' => t('Background image'),
    '#default_value' => $config['layout_builder_background_image'] ?? NULL,
    '#description' => t('This image should be at least 1000x400 pixels, and will be proportionally scaled as needed to ensure it covers the entire section. This may mean that the top and bottom or left and right of the image get cut off. Images should not contain text or any other content that would require a description, and must be selected so that text over top can maintain sufficient colour contrast.'),
    '#weight' => 82,
    '#states' => [
      'visible' => [
        ':input[name="layout_builder_background_type"]' => ['value' => 'image'],
      ],
    ],
  ];

  $form['layout_builder_background_image_image_tint'] = [
    '#type' => 'select',
    '#title' => t('Image tint'),
    '#options' => [
      'none' => t('None'),
      'black' => t('Black (darken)'),
      'white' => t('White (lighten)'),
    ],
    '#weight' => 83,
    '#default_value' => $config['layout_builder_background_image_image_tint'] ?? 'none',
    '#description' => t('For some images, tinting the image darker or lighter can improve the accessibility and readability of the overlaid content.'),
    '#states' => [
      'visible' => [
        ':input[name="layout_builder_background_type"]' => ['value' => 'image'],
      ],
    ],
  ];

  $form['layout_builder_background_image_text_color'] = [
    '#type' => 'select',
    '#title' => t('Text colour'),
    '#options' => [
      'white' => t('White'),
      'white-black-shadow' => t('White with black shadow'),
      'black' => t('Black'),
      'black-white-shadow' => t('Black with white shadow'),
    ],
    '#default_value' => $config['layout_builder_background_image_text_color'] ?? 'white',
    '#description' => t('Make sure to select the option that provides the best contrast from the image underneath.'),
    '#states' => [
      'visible' => [
        ':input[name="layout_builder_background_type"]' => ['value' => 'image'],
      ],
    ],
  ];
Martin Leblanc's avatar
Martin Leblanc committed
  // Adding #states to layout builder styles created using UI.
  $form['layout_builder_style_section_background']['#states'] = [
    'visible' => [
      ':input[name="layout_builder_background_type"]' => ['value' => 'image'],
      ':input[name="layout_builder_style_default"]' => ['!value' => 'uw_lbs_full_width'],
    ],
  ];

  $form['#validate'][] = 'uw_cfg_common_validate_section_configuration_validate';

  array_unshift($form['#submit'], 'uw_cfg_common_submit_section_configuration_submit');

}

/**
 * Validation for section background.
 *
 * @param array $form
 *   Form render array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form state.
 */
function uw_cfg_common_validate_section_configuration_validate(array &$form, FormStateInterface $form_state) {
  $type = $form_state->getValue('layout_builder_background_type');

  if ($type === 'image' && empty($form_state->getValue('layout_builder_background_image'))) {

    // Get the values from the form state.
    $values = $form_state->getValues();

    // If this is image, ensure one is selected.
    if (
      $values['layout_builder_background_type'] === 'image' &&
      empty($values['layout_builder_background_image'])
    ) {
      $form_state->setErrorByName(
        'layout_builder_background_type',
        t('Background image is required!')
      );
    }
  }
}
Martin Leblanc's avatar
Martin Leblanc committed

/**
 * Submit handler for section background.
 *
 * @param array $form
 *   Form render array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form state object.
 */
function uw_cfg_common_submit_section_configuration_submit(array &$form, FormStateInterface $form_state) {
  $layout_builder_background = $form_state->getValues();
  $type = $layout_builder_background['layout_builder_background_type'] ?? 'none';

  /** @var \Drupal\Core\Layout\LayoutDefault $layout */
  $layout = $form_state->getFormObject()->getLayout();
  $config = $layout->getConfiguration();

  // Reset all previously stored values.
  $config['layout_builder_background_type'] = $type;
  $config['layout_builder_background_color'] = NULL;
  $config['layout_builder_background_image'] = NULL;
  $config['layout_builder_background_image_image_tint'] = $layout_builder_background['layout_builder_background_image_image_tint'] ?? 'none';
  $config['layout_builder_background_image_text_color'] = $layout_builder_background['layout_builder_background_image_text_color'] ?? 'white';

  if ($type !== 'none') {
    if ($type === 'solid_color') {
      $config['layout_builder_background_color'] = $layout_builder_background['layout_builder_background_color'] ?? 'neutral';
    }
    elseif ($type === 'image') {
      $config['layout_builder_background_image'] = $layout_builder_background['layout_builder_background_image'];
    }
  }
  else {
    $config['layout_builder_background_color'] = NULL;
    $config['layout_builder_background_image_image_tint'] = NULL;
    $config['layout_builder_background_image_text_color'] = NULL;
  }

  $layout->setConfiguration($config);
Liam Morland's avatar
Liam Morland committed
}
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/config/submissions.
 */
function uw_cfg_common_form_webform_admin_config_submissions_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Remove undesired features.
  $form['views_settings']['#access'] = FALSE;
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Remove all ability to set CSS classes, CSS styles and custom attributes
 * in admin/structure/webform/manage/{webform_id}.
 */
function uw_cfg_common_form_webform_ui_element_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  $form['properties']['wrapper_attributes']['#access'] = FALSE;
  // Advanced -> Element Attributes.
  $form['properties']['element_attributes']['#access'] = FALSE;
  // Advanced -> Label Attributes.
  $form['properties']['label_attributes']['#access'] = FALSE;
  // Advanced -> Submission Display -> Display Wrapper Attributes.
  $form['properties']['display']['format_attributes']['#access'] = FALSE;
  // Advanced -> Summary Attributes.
  $form['properties']['summary_attributes']['#access'] = FALSE;
  // Advanced -> Title Attributes.
  $form['properties']['title_attributes']['#access'] = FALSE;
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/access.
 */
function uw_cfg_common_form_webform_settings_access_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  /** @var \Drupal\webform\WebformInterface $webform */
  $webform = $form_state->getFormObject()->getEntity();

  // Choose access control method.
  $form['access']['create']['uw_access_control_method'] = [
    '#type' => 'radios',
    '#title' => t('Choose who can view and submit the form'),
    '#options' => [
      'all' => t('Everyone'),
      'auth' => t('Users who are logged in'),
      'group' => t('Users specified by Active Directory groups'),
      'user' => t('Users specified below'),
      'anon' => t('Users who are logged out (for anonymous submission)'),
    ],
    '#default_value' => $webform->getThirdPartySetting('uw_cfg_common', 'access_control_method') ?: 'all',
    '#required' => TRUE,
    '#weight' => -50,
  ];

  // Access by Active Directory group.
  $form['access']['create']['uw_ad_access'] = [
    '#type' => 'details',
    '#title' => t('Access control by Active Directory group'),
    '#required' => TRUE,
    '#open' => TRUE,
    '#states' => [
      'visible' => [
        'input[name="access[create][uw_access_control_method]"]' => ['value' => 'group'],
      ],
    ],
  ];
  $form['access']['create']['uw_ad_access']['ad_require_groups'] = [
    '#type' => 'textarea',
    '#title' => t('Limit form submission to these Active Directory groups'),
    '#description' => t('Put one Active Directory group per line. To complete the form, the user must be in at least one of these groups. Leave blank to allow everyone.'),
    '#default_value' => implode("\r\n", $webform->getThirdPartySetting('uw_cfg_common', 'ad_require_groups') ?: []),
  ];
  $form['access']['create']['uw_ad_access']['ad_deny_groups'] = [
    '#type' => 'textarea',
    '#title' => t('Prevent form submission for these Active Directory groups'),
    '#description' => t('Put one Active Directory group per line. To complete the form, the user must not be in any of these groups. Leave blank to allow everyone.'),
    '#default_value' => implode("\r\n", $webform->getThirdPartySetting('uw_cfg_common', 'ad_deny_groups') ?: []),
  ];

  // Validate and submit handler to save UW settings.
  $form['actions']['submit']['#validate'][] = '_uw_cfg_common_form_webform_settings_access_form_validate';
  $form['actions']['submit']['#submit'][] = '_uw_cfg_common_form_webform_settings_access_form_submit';

  // Users control is hidden or required, the latter when authz by user.
  $access_rule = [
    'input[name="access[create][uw_access_control_method]"]' => ['value' => 'user'],
  ];
  $form['access']['create']['users']['#states']['required'][] = $access_rule;
  $form['access']['create']['users']['#states']['visible'][] = $access_rule;

  // Remove sections for access control that should not be available.
  $sections_to_remove = [
    'update_any',
    'update_own',
    'delete_own',
    'administer',
    'configuration',
  ];
  foreach ($sections_to_remove as $section) {
    $form['access'][$section]['#access'] = FALSE;
  }

  // Remove all but user-based access for submissions and test.
  $permissions_to_edit = [
    'create',
    'view_any',
    'delete_any',
    'purge_any',
    'view_own',
    'test',
  ];
  $access_types_to_remove = [
    'roles',
    'permissions',
  ];
  foreach ($permissions_to_edit as $permission) {
    foreach ($access_types_to_remove as $type) {
      $form['access'][$permission][$type]['#access'] = FALSE;
/**
 * Form validate handler.
 */
function _uw_cfg_common_form_webform_settings_access_form_validate(array $form, FormStateInterface $form_state): void {
  // Validate UW settings.
  $access_control_method = [
    'access',
    'create',
    'uw_access_control_method',
  ];
  $access_control_method = $form_state->getValue($access_control_method);
  switch ($access_control_method) {
    // Validate AD groups.
    case 'group':
      $fields = [
        'ad_require_groups' => NULL,
        'ad_deny_groups' => NULL,
      ];
      foreach (array_keys($fields) as $field) {
        // Get groups.
        $setting = [
          'access',
          'create',
          'uw_ad_access',
          $field,
        ];
        $fields[$field] = uw_cfg_common_array_split_clean($form_state->getValue($setting));
        $form_state->setValue($setting, $fields[$field]);

        // Raise error for invalid groups.
        foreach ($fields[$field] as $group) {
          if (!preg_match('/^[A-Za-z0-9_& -]+$/', $group)) {
            $form_state->setError(
              $form['access']['create']['uw_ad_access'][$field],
              t(
                'Invalid group: %group.',
                ['%group' => substr($group, 0, 100)]
              )
            );
            break;
          }
        }
      }

      // Raise error if no groups are entered.
      if (!array_filter($fields)) {
        $form_state->setError(
          $form['access']['create']['uw_ad_access'],
          t('Provide at least one group to use for access control.')
        );
      }
      // Fall-through.
    case 'all':
    case 'auth':
    case 'anon':
      // Except for case 'user', ensure no user access constraint is set.
      $form_state->setValue(['access', 'create', 'users'], NULL);
      break;
  }
}

/**
 * Form submit handler.
 */
function _uw_cfg_common_form_webform_settings_access_form_submit(array $form, FormStateInterface $form_state): void {
  // Save UW settings.
  if ($webform = $form_state->getFormObject()->getEntity()) {
    // Access control method.
    $access_control_method = [
      'access',
      'create',
      'uw_access_control_method',
    ];
    $access_control_method = $form_state->getValue($access_control_method);
    $webform->setThirdPartySetting('uw_cfg_common', 'access_control_method', $access_control_method);

    // Only save groups if that is the access method. Otherwise, they would be
    // saved without having been validated.
    if ($access_control_method === 'group') {
      // AD group access.
      foreach (['ad_require_groups', 'ad_deny_groups'] as $field) {
        $setting = [
          'access',
          'create',
          'uw_ad_access',
          $field,
        ];
        $setting = $form_state->getValue($setting);
        $webform->setThirdPartySetting('uw_cfg_common', $field, $setting);
      }
    }

    $webform->save();
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/settings/confirmation.
 */
function uw_cfg_common_form_webform_settings_confirmation_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Remove undesirable Webform submission confirmation types.
  // The 'modal' type is just a different way to display the message. Disable
  // for consistency.
  unset($form['confirmation_type']['confirmation_type']['#options']['modal']);
  // The 'none' type is only useful along with a custom handler which provides
  // the confirmation message.
  unset($form['confirmation_type']['confirmation_type']['#options']['none']);

  // Remove undesired features.
  $form['confirmation_attributes_container']['#access'] = FALSE;
  $form['back']['back_container']['confirmation_back_attributes_container']['#access'] = FALSE;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/settings.
 */
function uw_cfg_common_form_webform_settings_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Remove undesired features.
  $form['ajax_settings']['#access'] = FALSE;
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/handlers.
 */
function uw_cfg_common_form_webform_handler_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Add help text to 'SEND FROM (WEBSITE/DOMAIN)' in webform email handler.
  if ($form['#webform_handler_plugin_id'] === 'email') {
    $form['settings']['from']['#description'] = t('This must be an <strong>@uwaterloo.ca</strong> email address for sending to succeed. Please consider using the reply-to email option instead when emails are not limited to campus accounts.');

    // To email: remove 'Site email address' option under Other.
    array_shift($form['settings']['to']['to_mail']['to_mail']['#options']['Other']);

    // From email: remove 'Site email address' option under Other.
    array_shift($form['settings']['from']['from_mail']['from_mail']['#options']['Other']);

    // CC email: remove 'Site email address' option under Other.
    array_shift($form['settings']['to']['cc_mail']['cc_mail']['#options']['Other']);

    // CC email: Set 'Webform author email address' as default.
    $form['settings']['to']['cc_mail']['cc_mail']['#default_value'] = "[webform:author:mail]";

    // BCC email: remove 'Site email address' option under Other.
    array_shift($form['settings']['to']['bcc_mail']['bcc_mail']['#options']['Other']);

    // BCC email: Set 'Webform author email address' as default.
    $form['settings']['to']['bcc_mail']['bcc_mail']['#default_value'] = "[webform:author:mail]";

    // Reply-to email: remove 'Site email address' option under Other.
    array_shift($form['settings']['reply_to']['reply_to']['reply_to']['#options']['Other']);

    // Reply-to email: Set 'Webform author email address' as default.
    $form['settings']['reply_to']['reply_to']['reply_to']['#default_value'] = "[webform:author:mail]";
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/settings/form.
 */
function uw_cfg_common_form_webform_settings_form_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Unset the source entity settings in webforms.
  $form['form_behaviors']['form_prepopulate_source_entity']['#access'] = FALSE;
  $form['form_behaviors']['form_prepopulate_source_entity_required']['#access'] = FALSE;
  $form['form_behaviors']['form_prepopulate_source_entity_type']['#access'] = FALSE;

  // Remove undesired features.
  $form['access_denied']['#access'] = FALSE;
  $form['custom_settings']['#access'] = FALSE;
  $form['form_behaviors']['form_autofocus']['#access'] = FALSE;
  $form['form_behaviors']['form_disable_back']['#access'] = FALSE;
  $form['form_behaviors']['form_novalidate']['#access'] = FALSE;
  $form['form_behaviors']['form_required']['#access'] = FALSE;
  $form['form_behaviors']['form_reset']['#access'] = FALSE;
  $form['form_behaviors']['form_submit_back']['#access'] = FALSE;
  $form['form_settings']['form_attributes']['#access'] = FALSE;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Configure admin/structure/webform/manage/WEBFORM_ID/settings/submissions.
 */
function uw_cfg_common_form_webform_settings_submissions_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  // Remove undesired features.
  $form['access_denied']['#access'] = FALSE;
  $form['submission_behaviors']['form_convert_anonymous']['#access'] = FALSE;
  $form['submission_behaviors']['submission_log']['#access'] = FALSE;
  $form['submission_behaviors']['token_update']['#access'] = FALSE;
  $form['views_settings']['#access'] = FALSE;
/**
 * Implements hook_ENTITY_TYPE_create().
 */
function uw_cfg_common_webform_create(WebformInterface $webform) {
  // Submission purge settings. Set the default to purge drafts after 28 days.
  $webform->setSetting('purge', WebformSubmissionStorageInterface::PURGE_DRAFT);
  $webform->setSetting('purge_days', 28);
  // On admin/structure/webform/manage/FORM/settings/confirmation, default
  // "Confirmation type" to "inline".
  $webform->setSetting('confirmation_type', WebformInterface::CONFIRMATION_INLINE);
  // Set so that uw_cfg_common_webform_build_access_denied_alter() will run.
  // This value is tested for in Webform::preRenderWebformElement().
Liam Morland's avatar
Liam Morland committed
  // This value appears on
  // admin/structure/webform/manage/WEBFORM_ID/settings/form.
  $webform->setSetting('form_access_denied', WebformInterface::ACCESS_DENIED_PAGE);
/**
 * Implements hook_toolbar_alter().
 *
 * Remove the Manage link from the toolbar for authenticated users.
 */
function uw_cfg_common_toolbar_alter(&$items) {
  // Get the current user.
  $current_user = \Drupal::currentUser();

  // Remove the "manage" people for non-admin users.
  if (!$current_user->hasPermission('access manage toolbar item')) {
    // Remove "Manage" toolbar item.
    unset($items['administration']);
  }

  // Add "people" and "reports" links to "Workbench".
  // Note: 'dashboards' is renamed in
  // uw_dashboard_toolbar_alter().
  $links = [
    'entity.user.collection' => t('People'),
    'system.admin_reports' => t('Reports'),
  ];
  foreach ($links as $route => $title) {
    $url = Url::fromRoute($route);
    if ($url->access()) {
      $items['dashboards']['tray']['dashboards']['#items'][] = [
        '#type' => 'link',
        '#title' => $title,
        '#url' => $url,
      ];
Liam Morland's avatar
Liam Morland committed
 * Implements hook_preprocess_HOOK().
 */
function uw_cfg_common_preprocess_node(&$variables) {

  // Get the current path.
  $path = explode('/', \Drupal::service('path.current')->getPath());

  // The paths to place the content moderation block on.  Made this
  // an array to future proof, if there are more pages later.
  $paths_for_content_moderation = ['latest'];

  // ISTWCMS-4493: adding class if section has full width.
  // If there is a sidebar on the node, check all sections for full width.
  if (isset($variables['sidebar'])) {

    // Get the layouts from the node.
    $layouts = $variables['node']->layout_builder__layout->getValue();

    // Step through each of the layouts and check for full width.
    foreach ($layouts as $layout) {

      // Get the layout settings from the section.
      $settings = $layout['section']->getLayoutSettings();

      // If the layout builder style is set to full width, then set
      // the classes variable for the node and exit the loop.
      if (isset($settings['layout_builder_styles_style']) &&
        $settings['layout_builder_styles_style'] == "uw_lbs_full_width"
      ) {

        // Add a class to the node for full width on a section.
        $variables['attributes']['class'][] = 'uw-section-has-full-width';

        // Break out of the loop to save computational time.
        break;
      }
    }
  }

  // Check if we are to add the content moderation place.
  if (in_array(end($path), $paths_for_content_moderation)) {

    // Add the content moderation block.
    $variables['uw_content_moderation_form'] = \Drupal::formBuilder()->getForm('Drupal\content_moderation\Form\EntityModerationForm', $variables['node']);
  }
  else {

    $block_manager = \Drupal::service('plugin.manager.block');

    $plugin_block = $block_manager->createInstance('uw_cbl_content_moderation', []);

    $access_result = $plugin_block->access(\Drupal::currentUser());

    // Return empty render array if user doesn't have access.
    // $access_result can be boolean or an AccessResult class.
    if (
      is_object($access_result) &&
      $access_result->isForbidden() ||
      is_bool($access_result)
      && $access_result
    ) {
      $variables['uw_content_moderation_form'] = $plugin_block->build();
    }
  // Set the media flags for the node.
  $variables['media_flags'] = \Drupal::service('uw_cfg_common.uw_service')->uwGetMediaFlags($variables['node'], $variables['view_mode']);
/**
 * Get the layout builder styles as options.
 *
 * @param \Drupal\field\Entity\FieldStorageConfig $definition
 *   The field definition.
 * @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
 *   The entity being created if applicable.
 * @param bool $cacheable
 *   Boolean indicating if the results are cacheable.
 *
 * @return array
 *   An array of possible key and value options.
 *
 * @see options_allowed_values()
 */
function _uw_cfg_common_get_layout_builder_styles(
  FieldStorageConfig $definition,
  ContentEntityInterface $entity = NULL,
  $cacheable
) {

  // Get all the styles for sections.
  $all_styles = _layout_builder_styles_retrieve_by_type('section');
  // Array of options.
  $options = [];

  // Step through each style and get the info.
  foreach ($all_styles as $style) {
    // Only load styles from the "default" group,
    // which contains the section widths.
    // Needed for when other section styles ship.
    if ($style->getGroup() == 'default') {
      $options[$style->id()] = $style->label();
    }
/**
 * Implements hook_page_attachments().
 */
function uw_cfg_common_page_attachments(array &$page) {
  $page['#attached']['library'][] = 'uw_cfg_common/uw_mathjax';

  // Load uw_cfg_common module analytics configuration.
  $config = \Drupal::config('uw_cfg_common.google_settings');

  if ($config && $gso = $config->get('uw_cfg_common_google_site_ownership')) {
    $data = [
      '#tag' => 'meta',
      '#attributes' => [
        'name' => 'google-site-verification',
    // Attach tag to HEAD section.
    $page['#attached']['html_head'][] = [$data, 'uw-google-site-verification'];
  $admin_page = \Drupal::service('uw_cfg_common.uw_analytics')->administrationPage();
  // Get the code from config and inject to the page.
  if (!$admin_page && !empty($config->get('uw_cfg_common_ga_account'))) {
    $code = Html::escape($config->get('uw_cfg_common_ga_account'));

    $firstLetter = strtolower(substr($code, 0, 1));
    $snippet = _uw_cfg_common_google_analytics_snippet($firstLetter, $code);

    if ($firstLetter === 'g') {
      $external_script_data = [
        '#tag' => 'script',
        '#attributes' => [
          'async' => TRUE,
          'src' => 'https://www.googletagmanager.com/gtag/js?id=' . $code,
        ],
      ];
      $page['#attached']['html_head'][] = [
        $external_script_data,
        'uw-google-tag-manager',
      ];
    }

    $analytics = [
      '#type' => 'html_tag',
      '#tag' => 'script',
      '#value' => $snippet,
    ];

    $page['#attached']['html_head'][] = [
      $analytics,
 * Returns Google Analytics snippet code.