Skip to content

Instantly share code, notes, and snippets.

@opdavies
Last active May 11, 2020 16:20
Show Gist options
  • Save opdavies/4e75e1753d8603113f07f8264bb783d6 to your computer and use it in GitHub Desktop.
Save opdavies/4e75e1753d8603113f07f8264bb783d6 to your computer and use it in GitHub Desktop.
Automatically updating the created date for talk nodes, to match the date of the latest event for that talk.
<?php
/**
* @file
* Custom module.
*/
declare(strict_types=1);
use Drupal\custom\Entity\Node;
/**
* Implements hook_entity_type_build().
*/
function custom_entity_type_build(array &$entityTypes): void {
if (isset($entityTypes['node'])) {
$entityTypes['node']->setClass(Node::class);
}
}
services:
Drupal\custom\EventSubscriber\UpdateTalkCreatedDateOnSave:
tags:
- { name: event_subscriber }
<?php
declare(strict_types=1);
namespace Drupal\custom\Entity;
use Drupal\node\Entity\Node as CoreNode;
use Drupal\paragraphs\ParagraphInterface;
use Illuminate\Support\Collection;
final class Node extends CoreNode {
/**
* Find the date for the latest event.
*
* @return string|null
*/
public function findLatestEventDate(): ?string {
if (!$this->hasField('field_events')) {
return NULL;
}
return Collection::make($this->get('field_events')->referencedEntities())
->map(fn(ParagraphInterface $event) => $event->get('field_date')
->getString())
->max();
}
}
<?php
declare(strict_types=1);
namespace Drupal\Tests\custom\Kernel;
use Carbon\Carbon;
use Drupal\Core\Entity\EntityInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\paragraphs\ParagraphInterface;
final class UpdatesTalkCreatedDateTest extends EntityKernelTestBase {
/**
* {@inheritDoc}
*/
public static $modules = [
// Core.
'node',
'file',
'datetime',
// Contrib.
'entity_reference_revisions',
'paragraphs',
'hook_event_dispatcher',
// Custom.
'custom',
'custom_test',
];
public function testCreatingNode() {
$eventDate = Carbon::today()->addWeek();
$eventDateToFormat = $eventDate->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
$eventDateToTimestamp = $eventDate->getTimestamp();
$talk = $this->createTalk($eventDateToFormat);
$this->assertEqual($eventDateToTimestamp, $talk->get('created')
->getString());
}
public function testUpdatingNode() {
$talk = $this->createTalk();
$eventDate = Carbon::today()->addWeek();
$eventDateToFormat = $eventDate->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
$eventDateToTimestamp = $eventDate->getTimestamp();
$event = $this->createEvent($eventDateToFormat);
$talk->set('field_events', [$event]);
$talk->save();
$this->assertEqual($eventDateToTimestamp, $talk->get('created')
->getString());
}
protected function setUp() {
parent::setUp();
$this->installEntitySchema('paragraph');
$this->installSchema('node', ['node_access']);
$this->installConfig(['custom_test']);
}
private function createTalk(?string $eventDateToFormat = NULL): EntityInterface {
if ($eventDateToFormat) {
$event = $this->createEvent($eventDateToFormat);
}
$talk = Node::create([
'title' => 'TDD - Test Driven Drupal',
'type' => 'talk',
]);
if (isset($event)) {
$talk->set('field_events', [$event]);
}
$talk->save();
return $talk;
}
private function createEvent(string $eventDateToFormat): ParagraphInterface {
$event = Paragraph::create([
'field_date' => $eventDateToFormat,
'type' => 'event',
]);
$event->save();
return $event;
}
}
<?php
declare(strict_types=1);
namespace Drupal\custom\EventSubscriber;
use Carbon\Carbon;
use Drupal\Core\Entity\EntityInterface;
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Drupal\paragraphs\ParagraphInterface;
use Illuminate\Support\Collection;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Set the created date for a talk to be the last date that the talk is given.
*/
final class UpdateTalkCreatedDateOnSave implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
HookEventDispatcherInterface::ENTITY_INSERT => 'entityInsertOrUpdate',
HookEventDispatcherInterface::ENTITY_UPDATE => 'entityInsertOrUpdate',
];
}
public function entityInsertOrUpdate(BaseEntityEvent $event): void {
if ($event->getEntity()->getEntityTypeId() != 'node') {
return;
}
if ($event->getEntity()->bundle() != 'talk') {
return;
}
$this->updateCreatedDate($event->getEntity());
}
private function updateCreatedDate(EntityInterface $talk): void {
/** @var \Drupal\custom\Entity\Node $talk */
if (!$eventDate = $talk->findLatestEventDate()) {
return;
}
$talkDate = Carbon::parse($eventDate)->getTimestamp();
if ($talkDate == $talk->get('created')->getString()) {
return;
}
$talk->set('created', $talkDate);
}
/**
* Find the date for the latest event.
*
* @return string|null
*/
private function findLatestEventDate(EntityInterface $talk) {
return Collection::make($talk->get('field_events')->referencedEntities())
->map(fn(ParagraphInterface $event) => $event->get('field_date')
->getString())
->max();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment