Skip to content

Instantly share code, notes, and snippets.

@opdavies
Last active May 11, 2020
Embed
What would you like to do?
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