PageRenderTime 48ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/entity_reference_timer/src/Service/EntityReferenceTimerVisibilityService.php

https://bitbucket.org/publicplan/degov
PHP | 166 lines | 106 code | 22 blank | 38 comment | 20 complexity | 781bd5adf5c3ee8bc0b83c904ce34cda MD5 | raw file
  1. <?php
  2. namespace Drupal\entity_reference_timer\Service;
  3. use Drupal\Core\Database\Connection;
  4. use Drupal\Core\Datetime\DrupalDateTime;
  5. use Drupal\Core\Field\FieldItemInterface;
  6. use Drupal\Core\Routing\RouteMatchInterface;
  7. use Drupal\entity_reference_timer\Plugin\Field\FieldType\EntityReferenceDate;
  8. use Drupal\node\NodeInterface;
  9. /**
  10. * Class EntityReferenceTimerVisibilityService.
  11. */
  12. class EntityReferenceTimerVisibilityService {
  13. /**
  14. * Database.
  15. *
  16. * @var \Drupal\Core\Database\Connection
  17. */
  18. private $database;
  19. /**
  20. * @var \Drupal\Core\Routing\RouteMatchInterface
  21. */
  22. private $currentRouteMatch;
  23. /**
  24. * EntityReferenceTimerVisibilityService constructor.
  25. */
  26. public function __construct(Connection $database, RouteMatchInterface $current_route_match) {
  27. $this->database = $database;
  28. $this->currentRouteMatch = $current_route_match;
  29. }
  30. /**
  31. * Get next expiration timestamp from item.
  32. */
  33. public function getNextExpirationTimestampFromItem(EntityReferenceDate $item): ?int {
  34. $now = \time();
  35. $closestTimestamp = NULL;
  36. foreach (['start_date', 'end_date'] as $fieldName) {
  37. $dateTime = $item->get($fieldName)->getValue();
  38. if (\is_string($dateTime)) {
  39. $dateTime = new DrupalDateTime($dateTime);
  40. }
  41. if ($dateTime instanceof DrupalDateTime && $dateTime->getTimestamp() > $now && ($closestTimestamp === NULL || $dateTime->getTimestamp() < $closestTimestamp)) {
  42. $closestTimestamp = $dateTime->getTimestamp();
  43. }
  44. }
  45. return $closestTimestamp;
  46. }
  47. /**
  48. * Add expiration date to parent node.
  49. */
  50. public function addExpirationDateToParentNode(FieldItemInterface $item): void {
  51. $node = $this->currentRouteMatch->getParameter('node');
  52. if ($node instanceof NodeInterface) {
  53. $cacheTagString = 'node:' . $node->id();
  54. $cacheTagResult = $this->database->select('cachetags', 'ct')
  55. ->fields('ct')
  56. ->range(0, 1)
  57. ->condition('tag', $cacheTagString)
  58. ->execute();
  59. $cacheTag = $cacheTagResult->fetchAll();
  60. $nextExpirationTime = $this->getNextExpirationTimestampFromItem($item);
  61. if ($nextExpirationTime !== NULL) {
  62. if (!empty($cacheTag[0]) && property_exists($cacheTag[0], 'expires')) {
  63. if ($cacheTag[0]->expires === NULL || $cacheTag[0]->expires > $nextExpirationTime) {
  64. $this->database->update('cachetags')
  65. ->condition('tag', $cacheTagString)
  66. ->fields(['expires' => $nextExpirationTime])
  67. ->execute();
  68. }
  69. }
  70. else {
  71. $this->database->insert('cachetags')
  72. ->fields([
  73. 'tag' => $cacheTagString,
  74. 'invalidations' => 0,
  75. 'expires' => $nextExpirationTime,
  76. ])
  77. ->execute();
  78. }
  79. }
  80. }
  81. }
  82. /**
  83. * Count visible items in array.
  84. */
  85. public function countVisibleItemsInArray(array $items): int {
  86. $visibleItems = 0;
  87. foreach ($items as $item) {
  88. if ($this->isVisibleArray($item)) {
  89. $visibleItems++;
  90. }
  91. }
  92. return $visibleItems;
  93. }
  94. /**
  95. * Check if item is visible.
  96. */
  97. public function isVisible(FieldItemInterface $item): bool {
  98. if ($this->referenceItemSupportsTimedDisplay($item)) {
  99. return $this->isDateInThe('past', $item->get('start_date')
  100. ->getValue()) && $this->isDateInThe('future', $item->get('end_date')
  101. ->getValue());
  102. }
  103. return TRUE;
  104. }
  105. /**
  106. * Check if items are visible.
  107. */
  108. public function isVisibleArray(array $item): bool {
  109. if ($this->timedDisplayFieldsPresent($item)) {
  110. return $this->isDateInThe('past', $item['start_date']) && $this->isDateInThe('future', $item['end_date']);
  111. }
  112. return TRUE;
  113. }
  114. /**
  115. * Check if date is in the past or future.
  116. */
  117. private function isDateInThe(string $era, $value): bool {
  118. if (empty($value)) {
  119. return TRUE;
  120. }
  121. $dtNow = new DrupalDateTime();
  122. $dtFromValue = new DrupalDateTime($value);
  123. switch ($era) {
  124. case 'future':
  125. return $dtNow < $dtFromValue;
  126. case 'past':
  127. return $dtNow >= $dtFromValue;
  128. }
  129. return TRUE;
  130. }
  131. /**
  132. * Reference item supports timed display.
  133. */
  134. public function referenceItemSupportsTimedDisplay(FieldItemInterface $item): bool {
  135. $properties = $item->getProperties(TRUE);
  136. return $this->timedDisplayFieldsPresent($properties);
  137. }
  138. /**
  139. * Timed display fields present.
  140. */
  141. private function timedDisplayFieldsPresent($fields): bool {
  142. return \array_key_exists('start_date', $fields) && \array_key_exists('end_date', $fields);
  143. }
  144. }