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:
|
services:
|
||||||
Drupal\custom\EventSubscriber\UpdateTalkCreatedDateOnSave:
|
Drupal\custom\EventSubscriber\UpdateTalkNodeBeforeSave:
|
||||||
tags:
|
tags:
|
||||||
- { name: event_subscriber }
|
- { name: event_subscriber }
|
||||||
|
|
|
@ -18,13 +18,25 @@ use Illuminate\Support\Collection;
|
||||||
*/
|
*/
|
||||||
class Talk extends Node implements ContentEntityBundleInterface {
|
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.
|
* Find the date for the latest event.
|
||||||
*
|
*
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function findLatestEventDate(): ?string {
|
public function findLatestEventDate(): ?string {
|
||||||
return Collection::make($this->get('field_events')->referencedEntities())
|
return $this->getEvents()
|
||||||
->map(fn(ParagraphInterface $event) => $event->get('field_date')
|
->map(fn(ParagraphInterface $event) => $event->get('field_date')
|
||||||
->getString())
|
->getString())
|
||||||
->max();
|
->max();
|
||||||
|
|
|
@ -5,16 +5,17 @@ declare(strict_types=1);
|
||||||
namespace Drupal\custom\EventSubscriber;
|
namespace Drupal\custom\EventSubscriber;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Drupal\Core\Entity\EntityInterface;
|
use Drupal\custom\Entity\Node\Talk;
|
||||||
use Drupal\custom\Entity\Node;
|
use Drupal\custom\Entity\Paragraph\Event;
|
||||||
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
|
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
|
||||||
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
|
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
|
||||||
|
use Drupal\paragraphs\ParagraphInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
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() {
|
public static function getSubscribedEvents() {
|
||||||
return [
|
return [
|
||||||
|
@ -31,11 +32,26 @@ final class UpdateTalkCreatedDateOnSave implements EventSubscriberInterface {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->reorderEvents($event->getEntity());
|
||||||
$this->updateCreatedDate($event->getEntity());
|
$this->updateCreatedDate($event->getEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateCreatedDate(EntityInterface $talk): void {
|
private function reorderEvents(Talk $talk): void {
|
||||||
/** @var \Drupal\custom\Entity\Node $talk */
|
$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()) {
|
if (!$eventDate = $talk->findLatestEventDate()) {
|
||||||
return;
|
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;
|
namespace Drupal\Tests\custom\Kernel;
|
||||||
|
|
||||||
use Drupal\Core\Entity\EntityInterface;
|
use Drupal\custom\Entity\Node\Talk;
|
||||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||||
use Drupal\node\Entity\Node;
|
use Drupal\node\Entity\Node;
|
||||||
use Drupal\paragraphs\Entity\Paragraph;
|
use Drupal\paragraphs\Entity\Paragraph;
|
||||||
|
@ -33,6 +33,7 @@ abstract class TalksTestBase extends EntityKernelTestBase {
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function createEvent(array $overrides = []): ParagraphInterface {
|
protected function createEvent(array $overrides = []): ParagraphInterface {
|
||||||
|
/** @var \Drupal\paragraphs\ParagraphInterface $event */
|
||||||
$event = Paragraph::create(array_merge([
|
$event = Paragraph::create(array_merge([
|
||||||
'type' => 'event',
|
'type' => 'event',
|
||||||
], $overrides));
|
], $overrides));
|
||||||
|
@ -40,7 +41,7 @@ abstract class TalksTestBase extends EntityKernelTestBase {
|
||||||
return tap($event)->save();
|
return tap($event)->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createTalk(array $overrides = []): EntityInterface {
|
protected function createTalk(array $overrides = []): Talk {
|
||||||
$talk = Node::create(array_merge([
|
$talk = Node::create(array_merge([
|
||||||
'title' => 'Test Driven Drupal',
|
'title' => 'Test Driven Drupal',
|
||||||
'type' => 'talk',
|
'type' => 'talk',
|
||||||
|
|
Loading…
Reference in a new issue