<?php namespace Drupal\uw_cfg_common\Service; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; 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 \Symfony\Component\HttpFoundation\RequestStack */ 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. * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack * The request stack. */ 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 getCropImageStyles(string $type, bool $get_all = FALSE): array { // Image styles for portrait. $image_styles['portrait'] = [ 'uw_is_portrait', ]; // Image styles for responsive. $image_styles['responsive'] = [ 'uw_is_media_x_large', 'uw_is_media_x_small', 'uw_is_media_medium', 'uw_is_media_large', 'uw_is_media_small', ]; // If the flag to get all the image styles is set, // return all of them. If not return the // specific image style. if ($get_all) { return $image_styles; } else { return $image_styles[$type]; } } /** * {@inheritDoc} */ public function prepareResponsiveImage(?EntityInterface $entity, string $image_style): array { // Ensure that we can load an entity on the media. if ($entity && isset($entity->field_media_image->entity)) { // 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; // This 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) { $srcset = $source->storage()['srcset']->value(); $srcset_parts = explode('/', $srcset); foreach ($srcset_parts as $srcset_part) { if (strpos($srcset_part, 'uw_is') !== FALSE) { $style = $srcset_part; break; } } $variables['responsive_sources'][] = [ 'srcset' => $srcset, 'media' => $source->storage()['media']->value(), 'type' => $source->storage()['type']->value(), 'style' => $style, ]; } return $variables; } } return []; } /** * {@inheritDoc} */ public function uwGetResponsiveImageStyles(): array { return [ 'uw_is_media_x_large', 'uw_is_media_large', 'uw_is_media_medium', 'uw_is_media_small', 'uw_is_media_x_small', 'uw_is_portrait', ]; } /** * {@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_expand_collapse_group', 'uw_ct_news_item', 'uw_ct_opportunity', 'uw_ct_profile', 'uw_ct_project', 'uw_ct_web_page', 'uw_ct_service', ]; break; case 'layout_container': $preprocess = [ 'uw_ct_blog', 'uw_ct_contact', 'uw_ct_event', 'uw_ct_news_item', 'uw_ct_opportunity', 'uw_ct_profile', 'uw_ct_project', 'uw_ct_catalog_item', 'uw_ct_service', ]; break; case 'teaser': $preprocess = [ 'uw_ct_blog', 'uw_ct_catalog_item', 'uw_ct_contact', 'uw_ct_event', 'uw_ct_news_item', 'uw_ct_opportunity', 'uw_ct_profile', 'uw_ct_project', 'uw_ct_web_page', ]; break; case 'media': $preprocess = [ 'uw_ct_blog', 'uw_ct_event', 'uw_ct_news_item', ]; break; } return $preprocess; } /** * {@inheritDoc} */ public function uwCheckNodeForMedia(Node $node): string { // Set the node type. $node_type = $node->getType(); // Get the list of content types that are allowed to have // hero from our service. $media = $this->uwGetNodePreprocessing('media'); // If node is allowed to have a media, make sure that // node actually has a media. if (in_array($node_type, $media)) { // Ensure that the node has the type of media field. if ($node->hasField('field_uw_type_of_media')) { // Get the type of media value from the node. $value = $node->field_uw_type_of_media->value; // If there is a media present, set the variable so that // the page title will not be displayed. if ($value) { return 'yes'; } } } // Return a no by default. return 'no'; } /** * {@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_contact' => FALSE, 'uw_ct_event' => TRUE, 'uw_ct_news_item' => TRUE, 'uw_ct_opportunity' => FALSE, 'uw_ct_profile' => FALSE, 'uw_ct_project' => FALSE, 'uw_ct_service' => 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'); $front_page_alias = \Drupal::service('path_alias.manager')->getAliasByPath($front_page_path); $node_alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $nid); return $front_page_alias === $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 getContentTypeUsage( array $content_types, bool $show_null_content_types = FALSE ): array { // Node content types array. $list = []; // Step through the content types and get info. foreach ($content_types as $ct) { // Query to get all nodes of the content type. $query = $this->entityTypeManager->getStorage('node')->getQuery(); $query->condition('type', $ct); // Get the total number of nodes. $total = $query->count()->execute(); // If there are no nodes of the content type, // break out of this iteration, as we do not // want to display no nodes, however if flag // is set to show null nodes we will show them. if ($total == 0 && !$show_null_content_types) { continue; } // Load the content type, we need to use current as this // will load multiple, current will load the first entry. $content_type = current( $this->entityTypeManager->getStorage('node_type') ->loadByProperties(['type' => $ct]) ); // Add the condition of published to query. $query->condition('status', 1); // Set the number of published nodes. $published = $query->count()->execute(); // Set up the list to be used as rows in the table. $list[$ct] = [ 'name' => $content_type->get('name'), 'total' => $total, 'published' => $published, 'unpublished' => $total - $published, ]; } return $list; } }