Automatically update the created date for talks

Automatically update the created dates for talk nodes so that they match
the most-future event. This means that the talks are ordered correctly
on the Talks page.
This commit is contained in:
Oliver Davies 2020-05-08 18:46:31 +01:00
parent fe5340d1c7
commit 7a9bf80a89
18 changed files with 412 additions and 6 deletions

View file

@ -3,3 +3,7 @@ type: module
core: 8.x
core_version_requirements: ^8 || ^9
package: Custom
dependencies:
- drupal:node
- hook_event_dispatcher:hook_event_dispatcher
- paragraphs:paragraphs

View file

@ -0,0 +1,4 @@
services:
Drupal\custom\EventSubscriber\UpdateTalkCreatedDateOnSave:
tags:
- { name: event_subscriber }

View file

@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace Drupal\custom\EventSubscriber;
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 {
if (!$eventDate = $this->findLatestEventDate($talk)) {
return;
}
$talkDate = (new \DateTime($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();
}
}

View file

@ -12,6 +12,8 @@ use Drupal\paragraphs\Entity\Paragraph;
use Illuminate\Support\Collection;
/**
* A migrate destination for a talk node.
*
* @MigrateDestination(
* id="opd_talk"
* )

View file

@ -0,0 +1,30 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_events
- node.type.talk
- paragraphs.paragraphs_type.event
module:
- entity_reference_revisions
id: node.talk.field_events
field_name: field_events
entity_type: node
bundle: talk
label: Events
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
handler: 'default:paragraph'
handler_settings:
negate: 0
target_bundles:
event: event
target_bundles_drag_drop:
event:
enabled: true
weight: 2
field_type: entity_reference_revisions

View file

@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
config:
- field.storage.paragraph.field_date
- paragraphs.paragraphs_type.event
module:
- datetime
id: paragraph.event.field_date
field_name: field_date
entity_type: paragraph
bundle: event
label: Date
description: ''
required: true
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: datetime

View file

@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
module:
- entity_reference_revisions
- node
- paragraphs
id: node.field_events
field_name: field_events
entity_type: node
type: entity_reference_revisions
settings:
target_type: paragraph
module: entity_reference_revisions
locked: false
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View file

@ -0,0 +1,19 @@
langcode: en
status: true
dependencies:
module:
- datetime
- paragraphs
id: paragraph.field_date
field_name: field_date
entity_type: paragraph
type: datetime
settings:
datetime_type: date
module: datetime
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View file

@ -0,0 +1,10 @@
langcode: en
status: true
dependencies: { }
name: Talk
type: talk
description: ''
help: ''
new_revision: true
preview_mode: 1
display_submitted: false

View file

@ -0,0 +1,9 @@
langcode: en
status: true
dependencies: { }
id: event
label: Event
icon_uuid: null
icon_default: null
description: ''
behavior_plugins: { }

View file

@ -0,0 +1,5 @@
name: Custom Test
type: module
core: 8.x
core_version_requirements: ^8 || ^9
hidden: true

View file

@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\custom\Kernel;
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 = (new \DateTime('today'))->modify('+1 week');
$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 = (new \DateTime('today'))->modify('+1 week');
$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;
}
}