Newer
Older
Eric Bremner
committed
<?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;
Eric Bremner
committed
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 {
Eric Bremner
committed
// 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';
Eric Bremner
committed
/**
* Entity type manager from core.
Eric Bremner
committed
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
Eric Bremner
committed
*/
protected $entityTypeManager;
Eric Bremner
committed
/**
* The current request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* The UW Service.
*
* @var UWServiceInterface
*/
protected $uwService;
Eric Bremner
committed
/**
* Default constructor.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The current request stack.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
Eric Bremner
committed
* @param \Drupal\uw_cfg_common\Service\UWServiceInterface $uwService
* The UW Service.
*/
public function __construct(RequestStack $requestStack, EntityTypeManagerInterface $entityTypeManager, UWServiceInterface $uwService) {
Eric Bremner
committed
$this->requestStack = $requestStack;
$this->entityTypeManager = $entityTypeManager;
Eric Bremner
committed
$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.
* @param array|null $extra_options
* Some extra options if requried.
Eric Bremner
committed
*
* @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, array $extra_options = NULL) {
Eric Bremner
committed
// Address field type.
if ($type == 'address') {
return $this->getAddressField($node, $field_name);
Eric Bremner
committed
}
// 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);
Eric Bremner
committed
}
// Only content, either layout builder or summary.
if ($type == 'content') {
return $this->getContentField($node, $view_mode, $field_name);
Eric Bremner
committed
}
// Office hours field type.
if ($type == 'hours') {
wodby
committed
$hours = $node->$field_name->view();
if (isset($hours['#title'])) {
return $hours;
}
else {
return [];
}
Eric Bremner
committed
}
// 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;
}
Eric Bremner
committed
// Taxonomy terms field type.
if ($type == 'terms') {
return $this->getTermsField($node, $field_name);
Eric Bremner
committed
}
// Image field type.
if ($type == 'image') {
return $this->getImage($node, $field_name, $extra_options);
Eric Bremner
committed
}
// 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);
Eric Bremner
committed
}
// 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);
}
Eric Bremner
committed
}
// 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);
}
Eric Bremner
committed
// Title of the node.
if ($type == 'title') {
return $node->getTitle();
}
Eric Bremner
committed
// URL of the node.
if ($type == 'url') {
return $node->toUrl()->toString();
}
}
Eric Bremner
committed
/**
* Function to get the formatted text.
*
* @param \Drupal\node\Entity\Node $node
* The node.
* The name of the field to get.
*
* @return array
* Render array for formatted text.
*/
public function getFormattedText(Node $node, string $field_name = NULL): array {
// Ensure that we have a field to check.
if ($field_name !== NULL) {
// 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'];
}
Eric Bremner
committed
// 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');
Eric Bremner
committed
if (!empty($tags_to_add)) {
$tags[$key] = $this->getTermsFromEntityField($node->$field, 'tags');
Eric Bremner
committed
}
}
}
}
return $tags;
}
Eric Bremner
committed
/**
* Gets a plain text field or fields.
*
* 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 = [];
Eric Bremner
committed
// 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.
* @param string|null $extra_options
* An array of extra options for the image.
*
* @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 $extra_options = NULL): array {
$image = [];
if (isset($extra_options['is_responsive']) && $extra_options['is_responsive']) {
$image = $this->getSources($node, $field_name);
}
else {
// 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 (isset($extra_options['image_style'])) {
$file = $this->entityTypeManager->getStorage('file')->load($fid);
$image['uri'] = $this->entityTypeManager->getStorage('image_style')->load($extra_options['image_style'])->buildUrl($file->getFileUri());
$image['alt'] = $media->field_media_image->alt;
$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;
}
}
}
// If there is a type for the image, add it to the array.
if (isset($extra_options['type'])) {
$image['type'] = $extra_options['type'];
}
return $image;
}
/**
* Get the value of a map field.
*
* @param \Drupal\node\Entity\Node $node
* The node.
* @param string $field_name
* The field name.
*
* 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);
Eric Bremner
committed
}
return $map;
}
/**
* Get the value of an content field.
*
* @param \Drupal\node\Entity\Node $node
* The node.
* @param string $view_mode
* The view mode.
* The field name.
*
* Array of field value or NULL.
*/
public function getContentField(Node $node, string $view_mode, string $field_name = NULL): ?array {
// If on the teaser, return the summary field values.
if ($view_mode == 'teaser') {
return $this->getFormattedText($node, $field_name);
Eric Bremner
committed
}
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
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
*
* @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];
Eric Bremner
committed
}
Eric Bremner
committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
}
/**
* 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'];
}
Eric Bremner
committed
}
return $author;
}
/**
* Gets dates from node.
*
* @param \Drupal\node\Entity\Node $node
Eric Bremner
committed
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
* 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 {
Eric Bremner
committed
if ($type == 'event') {
// If this is the same day, get the date and the start and end times.
Eric Bremner
committed
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']);
Eric Bremner
committed
}
// 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.
Eric Bremner
committed
else {
$return_date = date(self::DATE_FORMAT_DATE_ONLY, $date['value']) . ' (all day)';
Eric Bremner
committed
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
}
}
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;
}
}