Skip to content
Snippets Groups Projects
UwNodeFieldValue.php 16.1 KiB
Newer Older
<?php

namespace Drupal\uw_cfg_common\Service;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Class UwFieldValue.
 *
 * Gets the data out from individual fields of a node.
 *
 * @package Drupal\uw_cfg_common\Service
 */
   * Entity type manager from core.
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
  protected $entityTypeManager;

  /**
   * The current request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The UW Service.
   *
   * @var UWServiceInterface
   */
  /**
   * Default constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   The current request stack.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\uw_cfg_common\Service\UWServiceInterface $uwService
   *   The UW Service.
   */
  public function __construct(RequestStack $requestStack, EntityTypeManagerInterface $entityTypeManager, UWServiceInterface $uwService) {
    $this->entityTypeManager = $entityTypeManager;
    $this->uwService = $uwService;
  }

  /**
   * Function to get the value of a node field.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param string $view_mode
   *   The view mode of the bnode.
   * @param string $type
   *   The type of field.
   * @param mixed $field_name
   *   The name of the field.
   *
   * @return array|\Drupal\Core\GeneratedUrl|mixed|string|void|null
   *   Array of the value of the field.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  public function getFieldValue(Node $node, string $view_mode, string $type, $field_name = NULL) {

    // Address field type.
    if ($type == 'address') {
      return $this->getAddressField($node, $field_name);
    }

    // Author field type.
    if ($type == 'author') {
      return $this->getAuthor($node);
    }

    // Long text field type with a text format.
    if ($type == 'formatted_text') {
      return $this->getFormattedText($node, $field_name);
    }

    // Only content, either layout builder or summary.
    if ($type == 'content') {
      return $this->getContentField($node, $view_mode, $field_name);
    }

    // Office hours field type.
    if ($type == 'hours') {
      return $node->$field_name->view();
    }

    // Date field type (smart dates).
    if ($type == 'date') {
      return $this->getDates($node, $field_name, $view_mode);
    }

    // Taxonomy terms field type.
    if ($type == 'terms') {
      return $this->getTermsField($node, $field_name);
      return $this->getImage($node, $field_name);
    }

    // Link field type.
    if ($type == 'link') {
      return $this->getLinkInfo($node, $field_name);
    }

    // Map (leaflet) field type.
    if ($type == 'map') {
      return $this->getMapField($node, $field_name);
    }

    // Plain text field type (textbox).
    if ($type == 'plain_text') {
      return $node->$field_name->value;
    }

    // Source or hero image field type.
    if ($type == 'sources' || $type == 'hero') {
      return $this->getSources($node, $field_name);
    }

    // Catalog tags, this is a special type of terms, since we
    // need to worry about the tabs that go along with them.
    if ($type == 'catalog_terms') {
      return $this->getCatalogTags($node, $field_name);
    }
    // Title of the node.
    if ($type == 'title') {
      return $node->getTitle();
    }
    // URL of the node.
    if ($type == 'url') {
      return $node->toUrl()->toString();
    }
  }
  /**
   * Function to get the formatted text.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param string $field_name
   *   The name of the field to get.
   *
   * @return array
   *   Render array for formatted text.
   */
  public function getFormattedText(Node $node, string $field_name): array {
    return [
      '#type' => 'processed_text',
      '#text' => $node->$field_name->value,
      '#format' => $node->$field_name->format,
    ];
  }

  /**
   * Function to get catalog tags.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   *   The field name.
   *
   * @return array
   *   Array of values for the field.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  public function getCatalogTags(Node $node, array $field_name): array {

    // 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 ($field_name as $key => $field) {
        if (in_array($key, $tabs)) {
          $tags_to_add = $this->getTermsFromEntityField($node->$field, 'tags');
          if (!empty($tags_to_add)) {
            $tags[$key] = $this->getTermsFromEntityField($node->$field, 'tags');
  /**
   * {@inheritDoc}
   */
  public function getImage(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;
  }

  /**
   * Get the value of a map field.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param string $field_name
   *   The field name.
   *
   * @return mixed
   *   Array of field value or NULL.
   */
  public function getMapField(Node $node, string $field_name) {

    // Set the map initially to null, if there are
    // coordinates, then will be replaced.
    $map = NULL;

    // If there are coordinates, set the map.
    if ($node->$field_name->getValue()) {
      $display = [
        'type' => 'leaflet_formatter_default',
        'label' => 'visually_hidden',
      ];
      $map = $node->$field_name->view($display);
    return $map;
  }

  /**
   * Get the value of an content field.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param string $view_mode
   *   The view mode.
   * @param string $field_name
   *   The field name.
   *
   * @return mixed
   *   Array of field value or NULL.
   */
  public function getContentField(Node $node, string $view_mode, string $field_name) {

    // If on the teaser, return the summary field values.
    if ($view_mode == 'teaser') {
      return $this->getFormattedText($node, $field_name);
    return NULL;
  }

  /**
   * Get the taxonomy terms field(s) value.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param array $field_name
   *   Array of field names.
   *
   * @return array
   *   Array of taxomoy term values.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  public function getTermsField(Node $node, array $field_name): array {

    // Need empty array in case there are no terms.
    $tags = [];

    // Step through each of the terms and add to array.
    foreach ($field_name as $field) {
      $tags = array_merge($tags, $this->getTermsFromEntityField($node->$field, 'tags'));
    }

    // Return array of terms.
    return $tags;
  }

  /**
   * Get the value of an address field.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   * @param string $field_name
   *   The field name.
   *
   * @return mixed
   *   Array of field value or NULL.
   */
  public function getAddressField(Node $node, string $field_name) {

    $address = $node->$field_name->getValue();
    if (isset($address[0])) {
      return $address[0];
  }

  /**
   * Get the author of the node.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node.
   *
   * @return array
   *   Array of the author info.
   */
  public function getAuthor(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;
  }

  /**
   * Gets dates from node.
   *
   * @param \Drupal\node\Node $node
   *   Node entity.
   * @param string $field_name
   *   The field name that has the date(s).
   * @param string $view_mode
   *   The view mode of the node.
   *
   * @return array
   *   Array of dates.
   */
  public function getDates(Node $node, string $field_name, string $view_mode): 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) {

        // ISTWCMS-5088: we need to ensure that at least
        // some dates show on the node page, so let's just
        // display them all.
        // If not node page, only get dates in the future.
        if ($view_mode == 'full') {

          $return_dates[] = $this->getDate($date, 'event');
        }
        else {

          // Ensure that the dates are greater than timestamp
          // that we generated above.
          if ($date['end_value'] > $check_date) {
            $return_dates[] = $this->getDate($date, 'event');
          }
        }
      }
    }

    return $return_dates;
  }

  /**
   * Function that parses terms and returns a list.
   *
   * @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $values
   *   List of values for the provided field.
   * @param string|null $type
   *   The type of terms to get, if none provided just term name returned.
   *
   * @return array
   *   List of terms with name and link.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  public function getTermsFromEntityField(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;
  }

  /**
   * Gets sources from node.
   *
   * @param \Drupal\node\Entity\Node $node
   *   Node entity.
   * @param string $field_name
   *   The field name that has the date(s).
   *
   * @return array
   *   Either array with responsive image.
   */
  public function getSources(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->uwService->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;
  }

  /**
   * Get a date in the proper format.
   *
   * @param array $date
   *   An array of date info.
   * @param string $type
   *   The type of date.
   *
   * @return string
   *   A converted date to a string.
   */
  public function getDate(array $date, string $type): string {

    // The all day case, duration is always 1439.
    if ($date['duration'] == '1439') {
      $return_date = 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_date = $start_date . ' - ' . $end_date . ' ' . date('T', $date['end_value']);
    }

    return $return_date;
  }

  /**
   * Gets link info from node.
   *
   * @param \Drupal\node\Entity\Node $node
   *   Node entity.
   * @param string $field_name
   *   The field name that has the date(s).
   *
   * @return array
   *   Array with link info.
   */
  public function getLinkInfo(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) {

      // Step through each link and get the info.
      foreach ($link_data as $ld) {

        // Get correct uri, if external just use uri from node
        // value, if not, then generate url from uri.
        if (UrlHelper::isExternal($ld['uri'])) {
          $link_info['uri'] = $ld['uri'];
        }
        else {
          $link_info['uri'] = URL::fromUri($ld['uri'])->toString();
        }
        $link_info['title'] = $ld['title'];

        $return_link_data[] = $link_info;
      }
    }

    return $return_link_data;
  }

}