Something went wrong on our end
-
Eric Bremner authoredEric Bremner authored
uw_fdsu_theme_resp.theme 25.61 KiB
<?php
/**
* @file
* Theme file for uw_fdsu_theme_resp.
*/
use Drupal\Core\Url;
use Drupal\file\Plugin\Field\FieldType\FileFieldItemList;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
/**
* @file
* Functions to support theming.
*/
require_once dirname(__FILE__) . '/includes/views.inc';
/**
* Implements hook_preprocess_HOOK().
*
* Setting the faculty class colour and favicon information.
*/
function uw_fdsu_theme_resp_preprocess_html(&$variables) {
// Adding the faculty colour class to the body.
$variables['attributes']['class'][] = theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') ? theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') : 'org-default';
$variables['uw_admin_page'] = \Drupal::service('uw_cfg_common.uw_analytics')->administrationPage();
// Add the fav icons.
_uw_fdsu_theme_resp_add_favicons($variables);
// Get the route name.
$route_name = \Drupal::routeMatch()->getRouteName();
// Perform actions based on the route.
switch ($route_name) {
// Add Javascript only on the user login page.
case 'user.login':
$variables['#attached']['library'][] = 'uw_fdsu_theme_resp/user.login';
break;
// The header/page title on contributors listing page browser
// tab shows "Reference author: " in front of the author's name.
case 'entity.bibcite_contributor.canonical':
$variables['head_title']['title'] = t('Reference author:') . ' ' . $variables['head_title']['title'];
break;
// The header/page title on keywords listing page browser
// tab shows "Reference keyword: " in front of the keyword.
case 'entity.bibcite_keyword.canonical':
$variables['head_title']['title'] = t('Reference keyword:') . ' ' . $variables['head_title']['title'];
break;
// Adding the alternate link to listing pages.
case 'view.uw_view_blogs.blog_page':
case 'view.uw_view_events.event_page':
case 'view.uw_view_news_items.news_page':
// Get the alternate link based on the route.
switch ($route_name) {
case 'view.uw_view_blogs.blog_page':
$link = _uw_fdsu_theme_resp_get_alternate_link(
'uw_view_blogs',
'uw_public_blog_feed',
'Blogs feed'
);
break;
case 'view.uw_view_events.event_page':
$link = _uw_fdsu_theme_resp_get_alternate_link(
'uw_view_events',
'uw_public_event_feed',
'Events feed'
);
break;
case 'view.uw_view_news_items.news_page':
$link = _uw_fdsu_theme_resp_get_alternate_link(
'uw_view_news_items',
'uw_public_news_feed',
'News feed'
);
break;
}
// Add the alternate link to the page.
$variables['#attached']['html_head_link'][] = $link;
break;
}
// Get the current path.
$parts = explode('/', \Drupal::service('path.current')->getPath());
// If the last in the array parts is not layout,
// add a class so that we traget anything but
// the layout pages.
if (end($parts) !== 'layout') {
$variables['attributes']['class'][] = 'not-layout-page';
}
else {
$variables['attributes']['class'][] = 'layout-page';
}
// Add UW to page title, if not already there.
_uw_add_page_title($variables);
}
/**
* Function to get the alternate link.
*
* @param string $view_machine_name
* The machine name of the view.
* @param string $view_display_name
* The display name of the view.
* @param string $title
* The title of the alternate link.
*/
function _uw_fdsu_theme_resp_get_alternate_link(
string $view_machine_name,
string $view_display_name,
string $title
) {
// Get the URL to RSS feed.
$url = Url::fromRoute('view.' . $view_machine_name . '.' . $view_display_name);
$url->setOptions(['query' => \Drupal::request()->query->all()]);
// Return the link for the alternate.
return [
[
'rel' => 'alternate',
'href' => $url->toString(),
'title' => $title,
'type' => 'application/rss+xml',
],
];
}
/**
* Implements hook_preprocess_responsive_image().
*/
function uw_fdsu_theme_resp_preprocess_responsive_image(&$variables) {
// Step through each of the responsive image objects and get out source info.
foreach ($variables['sources'] as $source) {
// Set the a variable with the actual source info that we need.
$new_sources[] = [
'srcset' => $source['srcset']->value(),
'media' => $source['media']->value(),
'type' => $source['type']->value(),
];
}
// Set the sources variable to the new sources.
$variables['sources'] = $new_sources;
}
/**
* Implements hook_preprocess_region().
*/
function uw_fdsu_theme_resp_preprocess_region(&$variables) {
// Get the region from variables.
$region = $variables['elements']['#region'];
// Set 'search_local' variable if not set.
if (!isset($variables['search_local'])) {
$variables['search_show_local'] = theme_get_setting('wcms_search_show_local', 'uw_fdsu_theme_resp');
}
// Variables that we want to have access to regardless of region.
$variables['branding_level'] = theme_get_setting('wcms_branding_level', 'uw_fdsu_theme_resp') ? theme_get_setting('wcms_branding_level', 'uw_fdsu_theme_resp') : 'full';
// The menu style is set based on selection if the level is 'full'.
if ($variables['branding_level'] == 'full') {
$variables['branding_menu_style'] = theme_get_setting('wcms_branding_menu_style', 'uw_fdsu_theme_resp') ? theme_get_setting('wcms_branding_menu_style', 'uw_fdsu_theme_resp') : 'compressed';
}
// The menu style is set to 'compressed' if the level is not 'full'.
else {
$variables['branding_menu_style'] = 'compressed';
}
// If we are on the header, add the correct header classes
// TO DO: Store the colour scheme used for the theme
// (i.e. faculty colour and get the correct class here).
if ($region == "header") {
// Get the home page link.
$variables['home_link'] = Url::fromRoute('<front>')->setAbsolute()->toString();
// Set the main menu variable.
$variables['main_menu'] = \Drupal::service('uw_cfg_common.uw_menu_items')->getMenuTree('main', TRUE, TRUE);
// Set the secondary menu variable.
$variables['secondary_menu'] = \Drupal::service('uw_cfg_common.uw_menu_items')->getMenuTree('uw-menu-audience-menu', TRUE, TRUE);
// The class that is used for the header.
$variables['classes'][] = 'uw-header';
// Get the site name for placing inside the menu.
$config = \Drupal::config('system.site');
$variables['site_name'] = $config->get('name');
$variables['subtitle'] = $config->get('slogan');
$variables['faculty'] = theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') ? theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') : 'org-default';
// Create the stream context to use with file_get_contents
// so it times out after a certain period instead of
// waiting indefinitely. Timeout is in seconds.
$context = stream_context_create([
'http' => [
'timeout' => 3,
],
]);
// Global message content.
$global_message = file_get_contents('https://uwaterloo.ca/global-message.html', 0, $context);
// If there is something to display, make sure to include css file, and
// pass message as render array, then use render twig filter to avoid using
// raw twig filter. Trimming message before sending to template, this
// will remove any empty lines/spaces that message may have.
if (!empty($global_message)) {
$variables['global_message'] = ['#markup' => trim($global_message)];
}
}
// ISTWCMS-4847.
// If we are on the main content section, the check if not a node and add
// appropriate classes to display proper width.
if ($region == 'content') {
// Get the route name.
$route_match = \Drupal::routeMatch();
// If we are on not on a node, add appropriate classes to show
// proper width.
$route_name = $route_match->getRouteName();
$exemptions = [
'entity.node.canonical',
'entity.node.latest_version',
'layout_builder.overrides.node.view',
];
if (!in_array($route_name, $exemptions)) {
$variables['classes'][] = 'layout';
$variables['classes'][] = 'uw-contained-width';
}
}
if ($region == 'footer') {
$variables['social_media'] = \Drupal::service('uw_cfg_common.uw_menu_items')
->getMenuTree(
'uw-menu-global-social-media',
FALSE
);
$variables['footer_menu'] = \Drupal::service('uw_cfg_common.uw_menu_items')
->getMenuTree(
'uw-menu-global-footer',
FALSE
);
}
$variables['language'] = \Drupal::languageManager()->getCurrentLanguage();
}
/**
* Implements hook_FORM_ID_alter().
*
* Add settings for colour scheme.
*/
function uw_fdsu_theme_resp_form_system_theme_settings_alter(&$form, FormStateInterface &$form_state, $form_id = NULL) {
// Work-around for a core bug affecting admin themes. See issue #943212.
if (isset($form_id)) {
return;
}
// Fieldset for search options.
$form['search_options'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => t('Search options'),
];
// Search options checkbox field.
$form['search_options']['wcms_search_show_local'] = [
'#type' => 'checkbox',
'#title' => t("Show the 'on this site' search option"),
'#default_value' => theme_get_setting('wcms_search_show_local', 'uw_fdsu_theme_resp') ?? TRUE,
];
// Fieldset for colour scheme.
$form['colour_scheme'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => t('Colour scheme'),
];
// Colour scheme select list.
$form['colour_scheme']['wcms_colour_scheme'] = [
'#type' => 'select',
'#default_value' => theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') ? theme_get_setting('wcms_colour_scheme', 'uw_fdsu_theme_resp') : 'default',
'#description' => t("Select a color scheme to use"),
'#options' => _uw_cfg_common_get_faculty_color_options(),
];
// Fieldset for branding options.
$form['branding_options'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => t('Branding options'),
];
// Branding select option.
$form['branding_options']['wcms_branding_level'] = [
'#type' => 'select',
'#options' => [
'full' => t('Full University branding'),
'generic' => t('Generic with University wordmark'),
'generic_barebones' => t('Fully generic'),
],
'#default_value' => theme_get_setting('wcms_branding_level', 'uw_fdsu_theme_resp') ?: 'full',
];
$form['branding_options']['wcms_branding_menu_style'] = [
'#type' => 'select',
'#options' => [
'compressed' => t('Compressed ("jump to") global menu'),
'full' => t('Fully visible global menu'),
],
"#states" => [
'visible' => [
'select[name="wcms_branding_level"]' => ['value' => 'full'],
],
],
'#default_value' => theme_get_setting('wcms_branding_menu_style', 'uw_fdsu_theme_resp') ?: 'compressed',
];
}
/**
* Add favicons to the page when called from hook_preprocess_html().
*
* @param array $variables
* The variables array.
*/
function _uw_fdsu_theme_resp_add_favicons(array &$variables) {
// Remove Drupal's favicon.
foreach ($variables['page']['#attached']['html_head_link'] as $id => $html_head_link) {
if (isset($html_head_link[0]['rel']) && $html_head_link[0]['rel'] == 'shortcut icon') {
unset($variables['page']['#attached']['html_head_link'][$id]);
break;
}
}
// Specify new favicon locations.
// Based on https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs.
$favicon_base_path = base_path() . \Drupal::service('extension.list.theme')->getPath('uw_fdsu_theme_resp');
$favicon = [
'rel' => 'icon',
'href' => $favicon_base_path . '/favicon.ico',
];
$variables['page']['#attached']['html_head_link'][] = [$favicon];
$favicon_svg = [
'rel' => 'icon',
'href' => $favicon_base_path . '/icon.svg',
'type' => 'image/svg+xml',
];
$variables['page']['#attached']['html_head_link'][] = [$favicon_svg];
$favicon_apple = [
'rel' => 'apple-touch-icon',
'href' => $favicon_base_path . '/apple-touch-icon.png',
];
$variables['page']['#attached']['html_head_link'][] = [$favicon_apple];
// Manifest needs a full URL.
$favicon_base_path = \Drupal::request()->getSchemeAndHttpHost() . $favicon_base_path;
$manifest = [
'icons' => [
[
'src' => $favicon_base_path . '/icon-192.png',
'type' => 'image/png',
'sizes' => '192x192',
],
[
'src' => $favicon_base_path . '/icon-512.png',
'type' => 'image/png',
'sizes' => '512x512',
],
],
];
$manifest = urlencode(json_encode($manifest));
$favicon_manifest = [
'rel' => 'manifest',
'href' => 'data:application/manifest+json,' . $manifest,
];
$variables['page']['#attached']['html_head_link'][] = [$favicon_manifest];
}
/**
* Get the specified field value from a paragraph.
*
* @param object $paragraph
* The paragraph object.
* @param string $field
* The name of the field.
*
* @return mixed
* The field value.
*/
function _uw_fdsu_theme_resp_get_field_value_from_paragraph($paragraph, $field) {
// Get the field value.
$field_value = $paragraph->get($field)->first();
return $field_value->getValue()['value'];
}
/**
* Set the variables required for a responsive image.
*
* @param array $variables
* The variables array.
* @param \Drupal\image\Plugin\Field\FieldType\ImageItem $field
* The field object.
* @param string $responsive_image_style
* The ID of the responsive image style.
*
* @return array|null
* An array with keys:
* - sources: An array of image sources.
* - alt: The alternative text.
*/
function _uw_fdsu_theme_resp_add_responsive_image_variables(array &$variables, ImageItem $field, string $responsive_image_style) : ?array {
// If there is a file present, set responsive image variables.
if ($file = $field->entity) {
// Set uri and image style id.
$variables['uri'] = $file->getFileUri();
$variables['responsive_image_style_id'] = $responsive_image_style;
// Call template function from responsive image core module.
// It sets variables for srcset, media, type and img_element
// for the responsive image style.
template_preprocess_responsive_image($variables);
// Step through each source and get string values.
$sources = [];
foreach ($variables['sources'] as $source) {
$sources[] = [
'srcset' => $source['srcset']->value(),
'media' => $source['media']->value(),
'type' => $source['type']->value(),
];
}
return [
'sources' => $sources,
'alt' => $field->get('alt')->getValue(),
];
}
return NULL;
}
/**
* Get image properties from an image field.
*
* @param \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $field
* The image field.
*
* @return array|null
* An array of image properties or NULL if $field does not contain the
* required information.
*/
function _uw_fdsu_theme_resp_get_image_info(FileFieldItemList $field) {
// If there is an image, process it.
if ($img_entity = $field->first()) {
// If we can load a file, grab the info about the file.
if ($file_entity = $img_entity->get('entity')->getTarget()) {
return [
'src' => \Drupal::service('file_url_generator')->generateAbsoluteString($file_entity->get('uri')->getString()),
'alt' => $img_entity->get('alt')->getString(),
];
}
}
}
/**
* Implements hook_preprocess_node().
*
* Set variables for node and teaser.
*/
function uw_fdsu_theme_resp_preprocess_node(&$variables) {
// The UW service object.
$uwService = \Drupal::service('uw_cfg_common.uw_service');
$nodeContent = \Drupal::service('uw_cfg_common.uw_node_content');
// The types of nodes the need preprocessing.
$nodes_to_preprocess = $uwService->uwGetNodePreprocessing('full');
// Teaser to be preprocessed.
$teasers_to_preprocess = $uwService->uwGetNodePreprocessing('teaser');
// If there is a node that needs preprocessing,
// set the appropriate variables.
if (in_array($variables['node']->getType(), $nodes_to_preprocess) ||
in_array($variables['node']->getType(), $teasers_to_preprocess)) {
// If on a teaser page get the variables for teaser.
if ($variables['view_mode'] == 'teaser' &&
in_array($variables['node']->getType(), $teasers_to_preprocess)) {
$variables['teaser'] = $nodeContent->getNodeContent($variables['node'], 'teaser', 'all');
}
// If on a node page get the variables for now.
if ($variables['view_mode'] == 'full' &&
in_array($variables['node']->getType(), $nodes_to_preprocess
)) {
$variables['node_data'] = $nodeContent->getNodeContent($variables['node'], 'full', 'all');
$variables['node_data']['content'] = $variables['content'];
}
// Unset the content variable, so that we do not get
// a second print of all the content.
unset($variables['content']);
}
}
/**
* Implements hook_preprocess_block().
*
* Add the admin_label and css classes if we are in layout builder.
*/
function uw_fdsu_theme_resp_preprocess_block(&$variables) {
// Look at page title block to see if we have a featured image.
// If we do then, set variable to not show page title.
if ($variables['plugin_id'] == 'page_title_block') {
// Set the media variable to no, we will only
// change if there is a media.
$variables['media'] = 'no';
// Load the node.
$node = \Drupal::routeMatch()->getParameter('node');
// If this is a node, check for contact and set if we
// have to hide the title.
if ($node = \Drupal::routeMatch()->getParameter('node')) {
// Get the media flags.
$media_flags = \Drupal::service('uw_cfg_common.uw_service')->uwGetMediaFlags($node);
// Set the show title flag.
$variables['show_title'] = $media_flags['has_media'] || $media_flags['has_portrait'] ? FALSE : TRUE;
}
// ISTWCMS-4943: ensure that we get a node object.
// If node is not object by this point, probably on
// a revision page where node is an integer, so load
// the node.
if ($node && !is_object($node)) {
$node = Node::load($node);
}
// If there is a node, check that it has a media.
if ($node) {
// The UW service object.
$uwService = \Drupal::service('uw_cfg_common.uw_service');
$variables['media'] = $uwService->uwCheckNodeForMedia($node);
}
}
// If we are in layout builder (this is set much earlier in
// the page load process), then continue to look if we need
// to add the admin_label and css classes.
if (isset($variables['in_layout_builder']) && $variables['in_layout_builder'] == TRUE) {
// Get the block manager object.
$blockManager = \Drupal::service('plugin.manager.block');
// Get the plugin definitions for the block, using the
// plugin_id of the block.
$plugin_definitions = $blockManager->getDefinition($variables['plugin_id']);
// The admin labels to exclude, these are ones that we do not
// want the admin label to appear on the layout builder page.
$admin_labels_to_exclude = [
'Messages',
'Tabs',
'Page title',
'Global header',
'Main navigation',
'Site Footer block',
];
// Check if the admin_label is an object, we need to do this
// because some admin labels are translatable and are therefore
// translatable markup objects (usually through code way of
// building blocks. Others are not, if translations are not turned
// on for this block (usually through the GUI way of creating a block,
// where the translation option is not set).
if (is_object($plugin_definitions['admin_label'])) {
// The admin label is a translatable markup, so just render
// the object to set the admin label variable..
$admin_label = $plugin_definitions['admin_label']->render();
}
else {
// The admin label is not an object so just set the
// admin label variable.
$admin_label = $plugin_definitions['admin_label'];
}
// If the admin label is not in the ones to exclude add it
// to the template variables and set the class to be used
// to display the admin label.
if (!in_array($admin_label, $admin_labels_to_exclude)) {
// ISTWCMS-6062, add publication to reference block admin
// labels when in layout builder.
if ($admin_label == 'Reference search') {
$admin_label = 'Publication reference search';
}
if ($admin_label == 'Reference teaser') {
$admin_label = 'Publication reference teaser';
}
$variables['admin_label'] = $admin_label;
$variables['attributes']['class'][] = 'in-layout-builder';
}
}
}
/**
* Implements template_preprocess_container().
*/
function uw_fdsu_theme_resp_preprocess_container(&$variables) {
// Ensure that we are on a layout page.
if (\Drupal::routeMatch()->getRouteName() == 'layout_builder.overrides.node.view') {
// Ensure that we are on the first layout builder container.
if (
isset($variables['attributes']['class']) &&
$variables['attributes']['class'][0] == 'layout-builder'
) {
// The UW service object.
$uwService = \Drupal::service('uw_cfg_common.uw_service');
// The UW node content service.
$uwNodeContent = \Drupal::service('uw_cfg_common.uw_node_content');
// The list of content types that will have header
// and footer in layout builder pages.
$content_types = $uwService->uwGetNodePreprocessing('layout_container');
// Get the node object.
$node = \Drupal::routeMatch()->getParameter('node');
// If there is a node object, and it is a content
// type that has header and footer for layout pages,
// get the header and footer.
if ($node && in_array($node->getType(), $content_types)) {
// Get the node object.
$node = \Drupal::routeMatch()->getParameter('node');
// Set variables for featured image.
$variables['node_type'] = str_replace('_', '-', $node->getType());
$variables['media'] = $uwService->uwCheckNodeForMedia($node);
$variables['media_flags'] = $uwService->uwGetMediaFlags($node);
// If there is a node object, get the header and footer data.
if ($node) {
$variables['header_data'] = $uwNodeContent->getNodeContent($node, 'full', 'header');
$variables['footer_data'] = $uwNodeContent->getNodeContent($node, 'full', 'footer');
// If this is an event, add the ical url so that it displays
// inside of layout builder.
if ($node->getType() == 'uw_ct_event') {
$variables['header_data']['ical'] = _uw_ct_event_get_ical_link($node->id());
}
}
}
}
}
}
/**
* Implements template_preprocess_details().
*/
function uw_fdsu_theme_resp_preprocess_details(&$variables) {
// ISTWCMS-6711: this comes from the label not having the
// correct for in it. So we are going to check if this is
// a better exposed filter and if so then add the correct
// based on the type of exposed filter it is. The date
// filter needs special treatment, since it is using the
// wrapper as the data drupal selector, and we need it to
// use the -value. If it is not a bef, then check if there
// is a data drupal selector and use it as the form field id.
if (
isset($variables['element'][0]['#context']['#plugin_type']) &&
$variables['element'][0]['#context']['#plugin_type'] == 'bef'
) {
// If this is a date picker, then change the form field id
// to use -value instead of -wrapper. If not then just use
// the straight data drupal selector.
if ($variables['element'][0]['#context']['#plugin_id'] == 'bef_datepicker') {
$variables['form_field_id'] = str_replace(
'-wrapper',
'-value',
$variables['element'][0]['#attributes']['data-drupal-selector']
);
}
else {
$variables['form_field_id'] = $variables['element'][0]['#attributes']['data-drupal-selector'];
}
}
else {
// Search input needs a special form id, so setting that, if not
// We continue the old fix.
if (isset($variables['element']['search'])) {
$variables['form_field_id'] = $variables['element']['search']['#attributes']['id'];
}
else {
// If there is an element, process it.
if (isset($variables['element'])) {
// Step through each of the indexes and ensure that we
// have an actual element, which means it will be an array.
foreach ($variables['element'] as $index => $value) {
// If this is an array, then we have an element to look at.
if (is_array($value)) {
// One more check to ensure that we have an element.
if (isset($variables['element'][$index]['#type'])) {
// Get the id based on where the id is stored, either it
// is by itself or within the attributes.
if (isset($variables['element'][$index]['#id'])) {
$variables['form_field_id'] = $variables['element'][$index]['#id'];
}
elseif (isset($variables['element'][$index]['#attributes']['id'])) {
$variables['form_field_id'] = $variables['element'][$index]['#attributes']['id'];
}
// Break out of the loop to save computational time.
break;
}
}
}
}
// If there is a data drupal selector use it for form field id.
elseif (isset($variables['element'][0]['#attributes']['data-drupal-selector'])) {
$variables['form_field_id'] = $variables['element'][0]['#attributes']['data-drupal-selector'];
}
}
}
}