<?php namespace Drupal\uw_cfg_common\Service; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\EntityReferenceFieldItemListInterface; use Drupal\Core\Url; use Drupal\node\Entity\Node; use Drupal\simplify_menu\MenuItems; use Drupal\path_alias\AliasManager; use Symfony\Component\HttpFoundation\RequestStack; /** * Class UWService. * * UW Service that holds common functionality used by uw blocks. * * @package Drupal\uw_cfg_common\Service */ class UWService implements UWServiceInterface { /** * Entity type manager from core. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ private $entityTypeManager; /** * Database connection. * * @var \Drupal\Core\Database\Connection */ private $database; /** * Simplify_menu menu items. * * @var \Drupal\simplify_menu\MenuItems */ private $simplifyMenu; /** * Simplify_menu menu items. * * @var \Drupal\simplify_menu\MenuItems */ private $pathAliasManager; /** * The request stack. * * @var \Drupal\simplify_menu\MenuItems */ private $requestStack; /** * Default constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * Entity Type Manager from core. * @param \Drupal\Core\Database\Connection $database * The database entity. * @param \Drupal\simplify_menu\MenuItems $simplifyMenu * The simplify_menu menu items. * @param \Drupal\path_alias\AliasManager $pathAliasManager * The Drupal path alias manager. */ public function __construct(EntityTypeManagerInterface $entityTypeManager, Connection $database, MenuItems $simplifyMenu, AliasManager $pathAliasManager, RequestStack $requestStack) { $this->entityTypeManager = $entityTypeManager; $this->database = $database; $this->simplifyMenu = $simplifyMenu; $this->pathAliasManager = $pathAliasManager; $this->requestStack = $requestStack; } /** * {@inheritDoc} */ public function prepareResponsiveImage(EntityInterface $entity, string $image_style): array { // Load in the file object if we have one. if ($file = $entity->field_media_image->entity) { // Need to set these variables so that responsive image function, // has all the necessary info to process the image style. $variables['uri'] = $file->getFileUri(); $variables['responsive_image_style_id'] = $image_style; // Set the alt for the image. $variables['alt'] = $entity->field_media_image->alt; // These is a function from the responsive image module that sets all // the variables for the sources of the responsive image. template_preprocess_responsive_image($variables); // Step through each of the sources and setup our own sources array. foreach ($variables['sources'] as $source) { $variables['responsive_sources'][] = [ 'srcset' => $source->storage()['srcset']->value(), 'media' => $source->storage()['media']->value(), 'type' => $source->storage()['type']->value(), ]; } return $variables; } return []; } /** * {@inheritDoc} */ public function uwGetNodeContent(Node $node, string $view_mode, string $content = 'all'): array { // Flags for getting teaser content. $get_header = FALSE; $get_footer = FALSE; $get_image = FALSE; $get_content = FALSE; $get_title = TRUE; $featured_image = $this->uwGetNodePreprocessing('featured_image'); // Setup flags based on teaser content argument. if ($content == 'all') { $get_header = TRUE; $get_footer = TRUE; $get_content = TRUE; if ($view_mode == 'teaser') { $get_image = TRUE; } if ($view_mode == 'full') { $get_title = FALSE; if (in_array($node->getType(), array_keys($featured_image))) { $get_image = TRUE; $get_title = TRUE; } } } else { if ($content == 'header') { $get_header = TRUE; $get_image = TRUE; } if ($content == 'footer') { $get_footer = TRUE; $get_title = FALSE; } } // Setup the teaser data array, based on flags. switch ($node->getType()) { case 'uw_ct_blog': // The list of tags for blogs. $tag_list = [ 'field_uw_blog_tags', 'field_uw_audience', ]; $content_data = [ 'title' => $get_title ? TRUE : NULL, 'url' => TRUE, 'date' => $get_header ? 'field_uw_blog_date' : NULL, 'author' => $get_header ? TRUE : NULL, 'sources' => $get_image ? 'field_uw_blog_listing_page_image' : NULL, 'hero' => $get_image ? 'field_uw_hero_image' : NULL, 'content' => $get_content ? 'field_uw_blog_summary' : NULL, 'tags' => $get_footer ? $tag_list : NULL, ]; break; case 'uw_ct_event': // The list of tags for events. $tag_list = [ 'field_uw_event_tags', 'field_uw_audience', 'field_uw_event_type', ]; $content_data = [ 'title' => $get_title ? TRUE : NULL, 'url' => TRUE, 'date' => $get_header ? 'field_uw_event_date' : NULL, 'sources' => $get_image ? 'field_uw_event_listing_page_img' : NULL, 'content' => $get_content ? 'field_uw_event_summary' : NULL, 'hero' => $get_image ? 'field_uw_hero_image' : NULL, 'tags' => $get_footer ? $tag_list : NULL, 'host' => $get_footer ? 'field_uw_event_host' : NULL, 'event_website' => $get_footer ? 'field_uw_event_website' : NULL, 'cost' => $get_footer ? 'field_uw_event_cost' : NULL, 'map' => $get_footer ? 'field_uw_event_location_coord' : NULL, 'address' => $get_footer ? 'field_uw_event_location_address' : NULL, 'map_link' => $get_footer ? 'field_uw_event_map' : NULL, ]; break; case 'uw_ct_news_item': // The list of tags for news. $tag_list = [ 'field_uw_news_tags', 'field_uw_audience', ]; $content_data = [ 'title' => $get_title ? TRUE : NULL, 'url' => TRUE, 'date' => $get_header ? 'field_uw_news_date' : NULL, 'sources' => $get_image ? 'field_uw_news_listing_page_image' : NULL, 'hero' => $get_image ? 'field_uw_hero_image' : NULL, 'content' => $get_content ? 'field_uw_news_summary' : NULL, 'tags' => $get_footer ? $tag_list : NULL, ]; break; case 'uw_ct_web_page': $content_data = [ 'title' => $get_title ? TRUE : NULL, 'content' => $get_content ? 'layout_builder__layout' : NULL, ]; break; case 'uw_ct_catalog_item': $tags = [ 'Category' => 'field_uw_catalog_category', 'Faculty' => 'field_uw_catalog_faculty', 'Audience' => 'field_uw_audience', ]; $content_data = [ 'title' => $get_title ? TRUE : NULL, 'content' => $get_content ? 'layout_builder__layout' : NULL, 'catalog_tags' => $get_footer ? $tags : NULL, ]; break; case 'uw_ct_contact': $content_data = [ 'title' => $get_title ? TRUE : NULL, 'sub_title' => $get_header ? 'field_uw_ct_contact_title' : NULL, 'affiliation' => $get_header ? 'field_uw_ct_contact_affiliation' : NULL, 'image' => $get_image ? 'field_uw_ct_contact_image' : NULL, 'content' => $get_content ? 'layout_builder__layout' : NULL, 'email' => $get_footer ? 'field_uw_ct_contact_email' : NULL, 'location' => $get_footer ? 'field_uw_ct_contact_location' : NULL, 'phone' => $get_footer ? 'field_uw_ct_contact_phone' : NULL, 'additional_info' => $get_footer ? 'field_uw_ct_contact_info' : NULL, 'link_profile' => $get_footer ? 'field_uw_ct_contact_link_profile' : NULL, 'personal_webpage' => $get_footer ? 'field_uw_ct_contact_link_persona' : NULL, 'contact_for' => $get_footer ? 'field_uw_ct_contact_contact_for' : NULL, 'groups' => $get_footer ? 'field_uw_ct_contact_group' : NULL, 'url' => TRUE, ]; break; case 'uw_ct_profile': $tag_list = [ 'field_uw_ct_profile_type', ]; $content_data = [ 'title' => $get_title ? TRUE : NULL, 'sub_title' => $get_header ? 'field_uw_ct_profile_title' : NULL, 'affiliation' => $get_header ? 'field_uw_ct_profile_affiliation' : NULL, 'content' => $get_content ? 'field_uw_profile_summary' : NULL, 'image' => $get_header ? 'field_uw_ct_profile_image' : NULL, 'tags' => $get_footer ? $tag_list : NULL, 'link_profile' => $get_footer ? 'field_uw_ct_profile_info_link' : NULL, 'personal_webpage' => $get_footer ? 'field_uw_ct_profile_link_persona' : NULL, 'url' => TRUE, ]; break; } return $this->uwGetNodeData($node, $view_mode, $content_data); } /** * {@inheritDoc} */ public function uwGetNodeData(Node $node, string $view_mode, array $content_data): array { // Array to store the teaser data, need blank // array in case there is no data to return. $node_data = []; // Step through each of the teaser data, and if // we are to get the data then set the variable // inside the teaser array. foreach ($content_data as $index => $data) { // If there is data to get, then get it. if ($data) { // Switch on the index to get the proper value. // The index will either be true (like title) or // a field name. switch ($index) { case 'additional_info': $additional_info = $node->field_uw_ct_contact_info->getValue(); if ($additional_info) { $node_data['additional_info'] = [ '#type' => 'processed_text', '#text' => $additional_info[0]['value'], '#format' => $additional_info[0]['format'], ]; } break; case 'address': $node_data['address'] = NULL; $address = $node->$data->getValue(); if (isset($address[0])) { $node_data['address'] = $address[0]; } break; case 'author': $node_data['author'] = $this->uwGetAuthor($node); break; case 'content': if ($view_mode == 'teaser') { $node_data['content'] = [ '#type' => 'processed_text', '#text' => $node->$data->value, '#format' => $node->$data->format, ]; } break; case 'date': $node_data['date'] = $this->uwGetDates($node, $data); break; case 'audience': case 'category': case 'faculty': case 'groups': $node_data[$index] = $this->uwGetTermsFromEntityField($node->$data, 'tags'); break; case 'image': $node_data['image'] = $this->uwGetImage($node, $data); break; case 'event_website': case 'host': case 'link_profile': case 'map_link'; case 'personal_webpage': $node_data[$index] = $this->uwGetLinkInfo($node, $data); break; case 'map': // Set the map initially to null, if there are // coordinates, then will be replaced. $node_data['map'] = NULL; // If there are coordinates, set the map. if ($node->$data->getValue()) { $display = [ 'type' => 'leaflet_formatter_default', 'label' => 'visually_hidden', ]; $node_data['map'] = $node->$data->view($display); } break; case 'sources': $node_data['image'] = $this->uwGetSources($node, $data); break; case 'hero': $node_data['hero'] = $this->uwGetSources($node, $data); break; case 'catalog_tags': // Empty arrays so that we don't get undefined // index errors. $tabs = []; $tags = []; // Get the entity and values for the catalog, // which is the taxonomy term catalog. $catalog_entity = $node->field_uw_catalog_catalog->entity; $tabs_values = $catalog_entity->field_uw_catalog_tabs_display->getValue(); // Setup the array that we can use for in_array, // which is the tabs to be displayed. foreach ($tabs_values as $tab_value) { $tabs[] = $tab_value['value']; } // If there are tabs, then get them. if (!empty($tabs)) { foreach ($data as $key => $field) { if (in_array($key, $tabs)) { $tags[$key] = $this->uwGetTermsFromEntityField($node->$field, 'tags'); } } } $node_data[$index] = $tags; break; case 'tags': $tags = []; foreach ($data as $field) { $tags = array_merge($tags, $this->uwGetTermsFromEntityField($node->$field, 'tags')); } $node_data[$index] = [$tags]; break; case 'title': $node_data['title'] = $node->getTitle(); break; case 'url': $node_data['url'] = $node->toUrl()->toString(); break; default: $node_data[$index] = $node->$data->value; break; } } } return $node_data; } /** * {@inheritDoc} */ public function uwGetNodePreprocessing(string $type): array { // Ensure that we return at least empty array. $preprocess = []; // Get the array of things to be proprocessed based // on the type. switch ($type) { case 'full': $preprocess = [ 'uw_ct_blog', 'uw_ct_catalog_item', 'uw_ct_contact', 'uw_ct_event', 'uw_ct_news_item', 'uw_ct_profile', 'uw_ct_web_page', ]; break; case 'layout_container': $preprocess = [ 'uw_ct_blog', 'uw_ct_contact', 'uw_ct_event', 'uw_ct_news_item', 'uw_ct_profile', 'uw_ct_catalog_item', ]; break; case 'teaser': $preprocess = [ 'uw_ct_blog', 'uw_ct_catalog_item', 'uw_ct_contact', 'uw_ct_event', 'uw_ct_news_item', 'uw_ct_profile', 'uw_ct_web_page', ]; break; case 'featured_image': $preprocess = [ 'uw_ct_blog' => 'field_uw_hero_image', 'uw_ct_event' => 'field_uw_hero_image', 'uw_ct_news_item' => 'field_uw_hero_image', ]; break; } return $preprocess; } /** * {@inheritDoc} */ public function uwCheckNodeForFeaturedImage(Node $node): string { // Set the node type. $node_type = $node->getType(); // Get the list of content types that are allowed to have // feature images from our service. $featured_image = $this->uwGetNodePreprocessing('featured_image'); // If node is allowed to have a featured image, make sure that // node actually has an image. if (in_array($node_type, array_keys($featured_image))) { // Get the field name. $field_name = $featured_image[$node_type]; // Get the image object values from the node. $image = $node->$field_name->getValue(); // If there is an image present, set the variable so that // the page title will not be displayed. if ($image) { return 'yes'; } else { return 'no'; } } return 'no'; } /** * {@inheritDoc} */ public function uwGetLinkInfo(Node $node, string $field_name): array { $return_link_data = []; // Get the link from the node. $link_data = $node->$field_name->getValue(); // If there is data in the link, get the variables. if ($link_data) { // Get correct uri, if external just use uri from node // value, if not, then generate url from uri. if (UrlHelper::isExternal($link_data[0]['uri'])) { $return_link_data['uri'] = $link_data[0]['uri']; } else { $return_link_data['uri'] = URL::fromUri($link_data[0]['uri'])->toString(); } $return_link_data['title'] = $link_data[0]['title']; } return $return_link_data; } /** * {@inheritDoc} */ public function uwGetImage(Node $node, string $field_name): array { $image = []; // Get the media id. $mid = $node->$field_name->getValue(); // If there is an image, process it. if ($mid) { // Load in the media item. $media = $this->entityTypeManager->getStorage('media')->load($mid[0]['target_id']); // Get the file id from the media object. $fid = $media->getSource()->getSourceFieldValue($media); // If there is a file id, then get the uri, // using the thumbnail image style. if ($fid) { $file = $this->entityTypeManager->getStorage('file')->load($fid); $image['uri'] = $this->entityTypeManager->getStorage('image_style')->load('thumbnail')->buildUrl($file->getFileUri()); $image['alt'] = $media->field_media_image->alt; } } return $image; } /** * {@inheritDoc} */ public function uwGetDates(Node $node, string $field_name): array { $return_dates = []; // If this is not and event, just get the date. if ($node->getType() !== 'uw_ct_event') { $return_dates[] = date('l, F j, Y', strtotime($node->$field_name->value)); } else { // Get all the dates. $dates = $node->$field_name->getValue(); // Get the date query parameter. $date_parameter = $this->requestStack->getCurrentRequest()->query->get('date'); // If there is a date query parameter, convert // to timestamp so we can compare against dates // in the event. If there is no parameter, set // the timestamp todays date. if ($date_parameter) { $check_date = strtotime($date_parameter['value']); } else { $check_date = strtotime("now"); } // Step through each of the dates and get // out correct values. foreach ($dates as $date) { // Ensure that the dates are greater than timestamp // that we generated above. if ($date['end_value'] > $check_date) { // The all day case, duration is always 1439. if ($date['duration'] == '1439') { $return_dates[] = date('l, F j, Y', $date['value']) . ' (all day)'; } else { // If this is the same day, get the date and the start // and end times. if ($date['duration'] < '1439') { $start_date = date('l, F j, Y g:i A', $date['value']); $end_date = date('g:i A', $date['end_value']); } // This is not the day, get the start and end date with time. else { $start_date = date('l, F j, Y g:i A', $date['value']); $end_date = date('l, F j, Y g:i A', $date['end_value']); } // Add the start and end date with timezone. $return_dates[] = $start_date . ' - ' . $end_date . ' ' . date('T', $date['end_value']); } } } } return $return_dates; } /** * {@inheritDoc} */ public function uwGetSources(Node $node, string $field_name): array { $return_sources = []; if ($node->$field_name) { // Get the image entity. $image = $node->$field_name->entity; // If there is an image, get the responsive image sources. if ($image) { $sources = $this->prepareResponsiveImage($image, 'uw_ris_media'); } else { $sources = NULL; } if (isset($sources['responsive_sources'])) { $return_sources['sources'] = $sources['sources']; $return_sources['img_element'] = $sources['img_element']['#uri']; $return_sources['alt'] = $sources['alt']; } } return $return_sources; } /** * {@inheritDoc} */ public function getOrCheckAttachedSidebar(int $attached_page_nid, int $sidebar_nid = NULL, string $type = NULL): int { // A database called to get the field with the condition of the // attached_page_nid. $result = $this->database ->select('node__field_uw_attach_page', 'nfuap') ->fields('nfuap', ['entity_id', 'field_uw_attach_page_target_id']) ->condition('field_uw_attach_page_target_id', $attached_page_nid); // If we are doing a a check for sidebar, then add the condition // that it is not equal to the current sidebar_nid that we are on. // Meaning that we are checking for any other sidebars that this // attached_page_nid is attached to. if ($type == 'check') { // Add the not equals to condition. $result->condition('entity_id', $sidebar_nid, '<>'); } // Get the results of query, we only need to fetch, because we are // only every expecting one sidebar only has one other node page // attached. $results = $result->execute()->fetch(); // If we have results, then return the entity_id, which is the // sidebar_nid that the attached_page_nid is attached to. if (isset($results->entity_id)) { // Return the entity_id. return $results->entity_id; } // If we made it here, there are no other sidebars that the // attached_page_nid is attached to, so we can simply return 0. else { return 0; } } /** * {@inheritDoc} */ public function getUwContentTypes($with_sidebar = FALSE): array { $return_content_types = []; // This is the list of all UW content types, with a TRUE/FALSE, indicating // whether or not a sidebar can be attached to this content type. $content_types = [ 'uw_ct_blog' => TRUE, 'uw_ct_catalog_item' => FALSE, 'uw_ct_event' => TRUE, 'uw_ct_news_item' => TRUE, 'uw_ct_sidebar' => FALSE, 'uw_ct_site_footer' => FALSE, 'uw_ct_web_page' => TRUE, ]; foreach ($content_types as $key => $value) { if ($with_sidebar && $value) { $return_content_types[] = $key; } elseif (!$with_sidebar) { $return_content_types[] = $key; } } return $return_content_types; } /** * {@inheritDoc} */ public function uwGetMenu(string $menu_name = 'main', bool $count_menu_items = FALSE, bool $include_parent_in_count = FALSE): array { // Get the main menu from the simplify menu module. $menu = $this->simplifyMenu->getMenuTree($menu_name); // Set it to the menu_tree which is done by simplify menu. $menu = $menu['menu_tree']; // Check that menu links are published and accessible. $this->uwCheckMenuItems($menu); // If we want to have the count of menu items, then count them. if ($count_menu_items) { // Add the count of the menu items. $menu = $this->uwSetMenuItems($menu, $include_parent_in_count); } return $menu; } /** * {@inheritDoc} */ public function uwCheckMenuItems(&$menu): void { // The base path, need this for removing when on subfoldered sites, // for example d8/fdsu5/, we need to remove the fdsu5 from the path // alias. global $base_path; // Step through each menu and ensure that it is published. foreach ($menu as $key => $m) { // If there is a submenu (i.e. children), process it first. if (isset($m['submenu'])) { $this->uwCheckMenuItems($menu[$key]['submenu']); } // If its inaccessible, remove the menu link. if ($m['text'] == 'Inaccessible') { unset($menu[$key]); } else { // Remove the base path from the url so that we can get // the actual content from the path alias. $alias = str_replace($base_path, '', $m['url']); // Get the path from the URL of the menu link. $path = $this->pathAliasManager->getPathByAlias('/' . $alias); // Check if it is a node path and if so check if published. if (preg_match('/^node\/(\d+)$/', $path, $matches)) { // Load in the node based on the path. $node = $this->entityTypeManager->getStorage('node')->load($matches[1]); // If the node is unpublished, remove it from the menus. if ($node->status->value == 0) { unset($menu[$key]); } } } } } /** * {@inheritDoc} */ public function uwSetMenuItems(array $menus, bool $include_parent_in_count = FALSE): array { // Step through the menu and do a few things: // (a) Remove the Home link (this will be a house icon) // (b) Add the number of menu items per menu link. foreach ($menus as $index => $menu) { // If this is the Home link, then remove it. if ($menu['text'] == "Home") { // Remove the home link. unset($menus[$index]); } // If we are not on the home link, then add the number // of menu items in this menu link. else { // Set the menu_item_count, initially to 0. $menu_items_count = 0; // If there is a submenu, recursivley call the count function. if (isset($menu['submenu']) && count($menu['submenu']) > 0) { // Call the count function recursively till we have the number of // menu items. $this->uwCountMenuItems($menu['submenu'], $menu_items_count); // Set the menu items count. // If we need to include the parent in the count, for example the // main menu will print the parent inside the tray, then we increment // the menu items count by 1. if ($include_parent_in_count) { $menu_items_count++; } // Set the menu items count in the menu. $menus[$index]['menu_items_count'] = $menu_items_count; } // If there are no submenus, the count is 0, there will be no tray. else { // Set the number of items count, which is 0. $menus[$index]['menu_items_count'] = $menu_items_count; } } } return $menus; } /** * {@inheritDoc} */ public function uwCountMenuItems($menus, &$menu_items_count): void { // Step through the menus and check for submenus and count. foreach ($menus as $menu) { // Increment the menu items counter. $menu_items_count++; // If there is a submenu, recursivley call the count function. if (isset($menu['submenu']) && count($menu['submenu']) > 0) { // Recursively check the submenu. $this->uwCountMenuItems($menu['submenu'], $menu_items_count); } } } /** * Determine whether a node is the home page. * * @param int $nid * A node ID. * * @return bool * TRUE when the node is the home page, FALSE otherwise. */ public static function nodeIsHomePage(int $nid): bool { $front_page_path = \Drupal::configFactory()->get('system.site')->get('page.front'); $node_alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $nid); return $front_page_path === $node_alias; } /** * {@inheritDoc} */ public function uwMonthNameShort(int $month = NULL) { static $months = [ 1 => 'Jan.', 2 => 'Feb.', 3 => 'Mar.', 4 => 'Apr.', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'Aug.', 9 => 'Sep.', 10 => 'Oct.', 11 => 'Nov.', 12 => 'Dec.', ]; if ($month) { return $months[$month]; } else { return $months; } } /** * {@inheritDoc} */ public function uwGetAuthor(Node $node): array { // Get the author field from the node, if there is // no author specified the value will be NULL. $author_name = $node->field_author->value; // If there is no author in the field, get the owner // of the blog post. if (!$author_name) { // Set the author to the person who made blog. $author = [ 'name' => $node->getOwner()->getDisplayName(), 'link' => NULL, ]; } // If there is an author, get the author name and link. else { // Get the link field from the node. $link = $node->field_uw_author_link->getValue(); // Set the author name and link (if any). $author = [ 'name' => $author_name, 'link' => empty($link) ? NULL : $link[0]['uri'], ]; } return $author; } /** * {@inheritDoc} */ public function uwGetTerms(array $tids, string $type = NULL): array { // Array to hold the terms, need to set to // null in case there are no terms to be // returned. $terms = []; // Step through each of the tids and get the term name. foreach ($tids as $tid) { // Load the term. $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid['target_id']); // If this is a tags term type, we have to include // url and title. If not just the tag name. if ($type == 'tags') { $terms[] = [ 'title' => $term->getName(), 'url' => Url::fromRoute( 'entity.taxonomy_term.canonical', ['taxonomy_term' => $tid['target_id']] )->toString(), ]; } else { $terms[] = $term->getName(); } } // Return an array of term names. return $terms; } /** * {@inheritDoc} */ public function uwGetTermsFromEntityField(EntityReferenceFieldItemListInterface $values, string $type = NULL): array { // Array to hold the terms, need to set to // null in case there are no terms to be // returned. $terms = []; // Step through each of the values which is a // list of referenced taxonomy terms. foreach ($values as $term_ref) { // Get the term entity, which is the same as // loading the term. $term_entity = $term_ref->entity; // If there is an entity, set the variable. if ($term_entity) { // If this is a tags term type, we have to include // url and title. If not just the tag name. if ($type === 'tags') { // Set the variables. By default function // toUrl on entity uses canonical url. $terms[] = [ 'title' => $term_entity->getName(), 'url' => $term_entity->toUrl()->toString(), ]; } else { $terms[] = $term_entity->getName(); } } } // Return an array of term names. return $terms; } }