Automatically order events when a talk is saved
To ensure that the event dates for a talk are always in the correct order, and to make the editing experience easier, this change automatically re-orders the events on a talk node to be based on the event date. Fixes #74
This commit is contained in:
parent
45fda0fed1
commit
56f3434c4a
|
@ -1,4 +1,4 @@
|
|||
services:
|
||||
Drupal\custom\EventSubscriber\UpdateTalkCreatedDateOnSave:
|
||||
Drupal\custom\EventSubscriber\UpdateTalkNodeBeforeSave:
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
|
|
@ -18,13 +18,25 @@ use Illuminate\Support\Collection;
|
|||
*/
|
||||
class Talk extends Node implements ContentEntityBundleInterface {
|
||||
|
||||
public function addEvent(ParagraphInterface $event): void {
|
||||
$this->set(
|
||||
'field_events',
|
||||
$this->getEvents()->push($event)->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
public function getEvents(): Collection {
|
||||
return Collection::make($this->get('field_events')
|
||||
->referencedEntities());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the date for the latest event.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function findLatestEventDate(): ?string {
|
||||
return Collection::make($this->get('field_events')->referencedEntities())
|
||||
return $this->getEvents()
|
||||
->map(fn(ParagraphInterface $event) => $event->get('field_date')
|
||||
->getString())
|
||||
->max();
|
||||
|
|
|
@ -5,16 +5,17 @@ declare(strict_types=1);
|
|||
namespace Drupal\custom\EventSubscriber;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\custom\Entity\Node;
|
||||
use Drupal\custom\Entity\Node\Talk;
|
||||
use Drupal\custom\Entity\Paragraph\Event;
|
||||
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
|
||||
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
|
||||
use Drupal\paragraphs\ParagraphInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Set the created date for a talk to be the last date that the talk is given.
|
||||
* Update a talk node before it's saved.
|
||||
*/
|
||||
final class UpdateTalkCreatedDateOnSave implements EventSubscriberInterface {
|
||||
final class UpdateTalkNodeBeforeSave implements EventSubscriberInterface {
|
||||
|
||||
public static function getSubscribedEvents() {
|
||||
return [
|
||||
|
@ -31,11 +32,26 @@ final class UpdateTalkCreatedDateOnSave implements EventSubscriberInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
$this->reorderEvents($event->getEntity());
|
||||
$this->updateCreatedDate($event->getEntity());
|
||||
}
|
||||
|
||||
private function updateCreatedDate(EntityInterface $talk): void {
|
||||
/** @var \Drupal\custom\Entity\Node $talk */
|
||||
private function reorderEvents(Talk $talk): void {
|
||||
$events = $talk->getEvents();
|
||||
|
||||
$eventsByDate = $events
|
||||
->sortBy(fn(ParagraphInterface $event) => $event->get('field_date')
|
||||
->getString())
|
||||
->values();
|
||||
|
||||
// If the original event IDs don't match the sorted event IDs, update the
|
||||
// event field to use the sorted ones.
|
||||
if ($events->map->id() != $eventsByDate->map->id()) {
|
||||
$talk->set('field_events', $eventsByDate->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function updateCreatedDate(Talk $talk): void {
|
||||
if (!$eventDate = $talk->findLatestEventDate()) {
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.paragraph.field_name
|
||||
- paragraphs.paragraphs_type.event
|
||||
id: paragraph.event.field_name
|
||||
field_name: field_name
|
||||
entity_type: paragraph
|
||||
bundle: event
|
||||
label: 'Event name'
|
||||
description: ''
|
||||
required: true
|
||||
translatable: false
|
||||
default_value: { }
|
||||
default_value_callback: ''
|
||||
settings: { }
|
||||
field_type: string
|
|
@ -0,0 +1,20 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- paragraphs
|
||||
id: paragraph.field_name
|
||||
field_name: field_name
|
||||
entity_type: paragraph
|
||||
type: string
|
||||
settings:
|
||||
max_length: 255
|
||||
is_ascii: false
|
||||
case_sensitive: false
|
||||
module: core
|
||||
locked: false
|
||||
cardinality: 1
|
||||
translatable: true
|
||||
indexes: { }
|
||||
persist_with_no_fields: false
|
||||
custom_storage: false
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\custom\Kernel;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Drupal\paragraphs\ParagraphInterface;
|
||||
|
||||
final class EventsAreReorderedByDateTest extends TalksTestBase {
|
||||
|
||||
public function testCreatingNode() {
|
||||
$events = [
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->addWeeks(2),
|
||||
'field_name' => 'Drupal Bristol',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::yesterday(),
|
||||
'field_name' => 'DrupalCamp London',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::tomorrow(),
|
||||
'field_name' => 'PHP UK conference',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->addMonths(3),
|
||||
'field_name' => 'CMS Philly',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->subYear(),
|
||||
'field_name' => 'PHP South Wales',
|
||||
]),
|
||||
];
|
||||
|
||||
$talk = $this->createTalk([
|
||||
'field_events' => $events,
|
||||
]);
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'PHP South Wales',
|
||||
'DrupalCamp London',
|
||||
'PHP UK conference',
|
||||
'Drupal Bristol',
|
||||
'CMS Philly',
|
||||
],
|
||||
$talk->getEvents()
|
||||
->map(fn(ParagraphInterface $event) => $event->get('field_name')
|
||||
->getString())
|
||||
->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUpdatingNode() {
|
||||
$events = [
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->addWeeks(2),
|
||||
'field_name' => 'Drupal Bristol',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::yesterday(),
|
||||
'field_name' => 'DrupalCamp London',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->addMonths(3),
|
||||
'field_name' => 'CMS Philly',
|
||||
]),
|
||||
$this->createEvent([
|
||||
'field_date' => Carbon::today()->subYear(),
|
||||
'field_name' => 'PHP South Wales',
|
||||
]),
|
||||
];
|
||||
|
||||
$talk = $this->createTalk([
|
||||
'field_events' => $events,
|
||||
]);
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'PHP South Wales',
|
||||
'DrupalCamp London',
|
||||
'Drupal Bristol',
|
||||
'CMS Philly',
|
||||
],
|
||||
$talk->getEvents()
|
||||
->map(fn(ParagraphInterface $event) => $event->get('field_name')
|
||||
->getString())
|
||||
->toArray()
|
||||
);
|
||||
|
||||
$talk->addEvent($this->createEvent([
|
||||
'field_date' => Carbon::tomorrow(),
|
||||
'field_name' => 'PHP UK conference',
|
||||
]));
|
||||
$talk->save();
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'PHP South Wales',
|
||||
'DrupalCamp London',
|
||||
'PHP UK conference',
|
||||
'Drupal Bristol',
|
||||
'CMS Philly',
|
||||
],
|
||||
$talk->getEvents()
|
||||
->map(fn(ParagraphInterface $event) => $event->get('field_name')
|
||||
->getString())
|
||||
->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Drupal\Tests\custom\Kernel;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\custom\Entity\Node\Talk;
|
||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\paragraphs\Entity\Paragraph;
|
||||
|
@ -33,6 +33,7 @@ abstract class TalksTestBase extends EntityKernelTestBase {
|
|||
];
|
||||
|
||||
protected function createEvent(array $overrides = []): ParagraphInterface {
|
||||
/** @var \Drupal\paragraphs\ParagraphInterface $event */
|
||||
$event = Paragraph::create(array_merge([
|
||||
'type' => 'event',
|
||||
], $overrides));
|
||||
|
@ -40,7 +41,7 @@ abstract class TalksTestBase extends EntityKernelTestBase {
|
|||
return tap($event)->save();
|
||||
}
|
||||
|
||||
protected function createTalk(array $overrides = []): EntityInterface {
|
||||
protected function createTalk(array $overrides = []): Talk {
|
||||
$talk = Node::create(array_merge([
|
||||
'title' => 'Test Driven Drupal',
|
||||
'type' => 'talk',
|
||||
|
|
Loading…
Reference in a new issue