Something went wrong on our end
-
Eric Bremner authoredEric Bremner authored
UwNodeFieldValue.php 18.52 KiB
<?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
*/
class UwNodeFieldValue {
// Date format: "Thursday, December 2, 2021".
const DATE_FORMAT_DATE_ONLY = 'l, F j, Y';
// Time format: "10:00 AM".
const DATE_FORMAT_TIME_ONLY = 'g:i A';
// Date and time format: "Thursday, December 2, 2021 10:00 AM".
const DATE_FORMAT_DATE_TIME = 'l, F j, Y g:i A';
/**
* 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
*/
protected $uwService;
/**
* 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->requestStack = $requestStack;
$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') {
$hours = $node->$field_name->view();
if (isset($hours['#title'])) {
return $hours;
}
else {
return [];
}
}
// Date field type (smart dates).
if ($type == 'date') {
return $this->getDates($node, $field_name, $view_mode);
}
// Select list field.
if ($type == 'select') {
return $node->$field_name->value;
}
// Taxonomy terms field type.
if ($type == 'terms') {
return $this->getTermsField($node, $field_name);
}
// Image field type.
if ($type == 'image') {
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' || $type == 'multiple_plain_text') {
if ($type == 'multiple_plain_text') {
return $this->getPlainText($node, $field_name, TRUE);
}
else {
return $this->getPlainText($node, $field_name);
}
}
// 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 {
// Get the value of the field.
$value = $node->$field_name->value;
// If the value is not null, then return the
// formatted text render array.
if ($value !== NULL) {
return [
'#type' => 'processed_text',
'#text' => $value,
'#format' => $node->$field_name->format,
];
}
// If we get here there is no value, so
// return an empty array and our clean
// node data function will handle it.
return [];
}
/**
* Function to get catalog tags.
*
* @param \Drupal\node\Entity\Node $node
* The node.
* @param array $field_name
* 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');
}
}
}
}
return $tags;
}
/**
* Gets a plain text field or fields.
*
* @param \Drupal\node\Entity\Node $node
* The node.
* @param string $field_name
* The field name.
* @param bool $multiple
* Flag if multiple plain text.
*
* @return mixed
* Plain text values.
*/
public function getPlainText(Node $node, string $field_name, bool $multiple = FALSE) {
$plain_text = [];
// If there are no multiple plain text, just return value.
// If there are multiple plain text, step through and
// get the values.
if (!$multiple) {
return $node->$field_name->value;
}
else {
// Get the values of the plain text field.
$values = $node->$field_name->getValue();
// Step through each and get the actual value.
foreach ($values as $value) {
$plain_text[] = $value['value'];
}
// Return array of plain text.
return $plain_text;
}
}
/**
* Prepares image for theme.
*
* @param \Drupal\node\Entity\Node $node
* Node entity.
* @param string $field_name
* Field name.
*
* @return array
* Array of data such as url, alt.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
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.
/** @var \Drupal\media\Entity\Media $media */
$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 array|null
* 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 array|null
* 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 taxonomy 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];
}
return NULL;
}
/**
* 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(),
];
}
// 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();
$author['name'] = $author_name;
if (!empty($link)) {
$author['link'] = $link[0]['uri'];
}
}
return $author;
}
/**
* Gets dates from node.
*
* @param \Drupal\node\Entity\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 {
$return_date = '';
if ($type == 'event') {
// If this is the same day, get the date and the start and end times.
if ($date['duration'] < '1439') {
$start_date = date(self::DATE_FORMAT_DATE_TIME, $date['value']);
$end_date = date(self::DATE_FORMAT_TIME_ONLY, $date['end_value']);
$return_date = $start_date . ' - ' . $end_date . ' ' . date('T', $date['end_value']);
}
// This is not the day, get the start and end date with time.
elseif ($date['duration'] > '1439') {
$start_date = date(self::DATE_FORMAT_DATE_TIME, $date['value']);
$end_date = date(self::DATE_FORMAT_DATE_TIME, $date['end_value']);
$return_date = $start_date . ' - ' . $end_date . ' ' . date('T', $date['end_value']);
}
// The all date case, duration is always 1439.
else {
$return_date = date(self::DATE_FORMAT_DATE_ONLY, $date['value']) . ' (all day)';
}
}
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;
}
}