Automatically re-order tags on save

Fixes #167
This commit is contained in:
Oliver Davies 2020-08-28 11:35:54 +01:00
parent 5e107b48d6
commit 59a98b8d78
13 changed files with 268 additions and 0 deletions

View file

@ -6,6 +6,7 @@
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/custom/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\custom" /> <sourceFolder url="file://$MODULE_DIR$/web/modules/custom/custom/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\custom" />
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\opd_talks" /> <sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\opd_talks" />
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/src" isTestSource="false" packagePrefix="Drupal\opd_talks" /> <sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/src" isTestSource="false" packagePrefix="Drupal\opd_talks" />
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opdavies_blog/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\opdavies_blog" />
<excludeFolder url="file://$MODULE_DIR$/vendor/asm89/stack-cors" /> <excludeFolder url="file://$MODULE_DIR$/vendor/asm89/stack-cors" />
<excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink" /> <excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink" />
<excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink-browserkit-driver" /> <excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink-browserkit-driver" />

View file

@ -3,5 +3,9 @@ services:
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
Drupal\opdavies_blog\EventSubscriber\ReorderBlogTags:
tags:
- { name: event_subscriber }
Drupal\opdavies_blog\Repository\PostRepository: Drupal\opdavies_blog\Repository\PostRepository:
autowire: true autowire: true

View file

@ -6,6 +6,8 @@ namespace Drupal\opdavies_blog\Entity\Node;
use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface; use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface;
use Drupal\node\Entity\Node; use Drupal\node\Entity\Node;
use Drupal\taxonomy\Entity\Term;
use Illuminate\Support\Collection;
/** /**
* Defines an blog post node class. * Defines an blog post node class.
@ -24,6 +26,13 @@ class Post extends Node implements ContentEntityBundleInterface {
: NULL; : NULL;
} }
/**
* @return Collection|Term[]
*/
public function getTags(): Collection {
return new Collection($this->get('field_tags')->referencedEntities());
}
public function hasBeenSentToSocialMedia(): bool { public function hasBeenSentToSocialMedia(): bool {
return (bool) $this->get('field_sent_to_social_media')->getString(); return (bool) $this->get('field_sent_to_social_media')->getString();
} }
@ -36,6 +45,10 @@ class Post extends Node implements ContentEntityBundleInterface {
return (bool) $this->getExternalLink(); return (bool) $this->getExternalLink();
} }
public function setTags(array $tags): void {
$this->set('field_tags', $tags);
}
public function toTweet(): string { public function toTweet(): string {
// TODO: Add tags. // TODO: Add tags.

View file

@ -48,6 +48,10 @@ final class PushBlogPostToSocialMedia implements EventSubscriberInterface {
$url = \Drupal::configFactory()->get('opdavies_talks.config') $url = \Drupal::configFactory()->get('opdavies_talks.config')
->get('zapier_post_tweet_url'); ->get('zapier_post_tweet_url');
if (!$url) {
return;
}
\Drupal::httpClient()->post($url, [ \Drupal::httpClient()->post($url, [
'form_params' => [ 'form_params' => [
'message' => $entity->toTweet(), 'message' => $entity->toTweet(),

View file

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Drupal\opdavies_blog\EventSubscriber;
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Drupal\opdavies_blog\Entity\Node\Post;
use Drupal\taxonomy\TermInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
final class ReorderBlogTags implements EventSubscriberInterface {
/**
* @inheritDoc
*/
public static function getSubscribedEvents() {
return [
HookEventDispatcherInterface::ENTITY_PRE_SAVE => 'onEntityPreSave',
];
}
public function onEntityPresave(BaseEntityEvent $event): void {
$entity = $event->getEntity();
if ($entity->getEntityTypeId() != 'node') {
return;
}
/** @var Post $entity */
if ($entity->bundle() != 'post') {
return;
}
$sortedTags = $entity->getTags()
->sortBy(fn(TermInterface $tag) => $tag->label());
$entity->setTags($sortedTags->toArray());
}
}

View file

@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_external_link
- node.type.post
module:
- link
id: node.post.field_external_link
field_name: field_external_link
entity_type: node
bundle: post
label: 'External link'
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
link_type: 16
title: 2
field_type: link

View file

@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_sent_to_social_media
- node.type.post
id: node.post.field_sent_to_social_media
field_name: field_sent_to_social_media
entity_type: node
bundle: post
label: 'Sent to social media'
description: ''
required: false
translatable: false
default_value:
-
value: 0
default_value_callback: ''
settings:
on_label: 'On'
off_label: 'Off'
field_type: boolean

View file

@ -0,0 +1,28 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_tags
- node.type.post
- taxonomy.vocabulary.tags
id: node.post.field_tags
field_name: field_tags
entity_type: node
bundle: post
label: Tags
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
handler: 'default:taxonomy_term'
handler_settings:
target_bundles:
tags: tags
sort:
field: name
direction: asc
auto_create: true
auto_create_bundle: ''
field_type: entity_reference

View file

@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
module:
- link
- node
id: node.field_external_link
field_name: field_external_link
entity_type: node
type: link
settings: { }
module: link
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View file

@ -0,0 +1,17 @@
langcode: en
status: true
dependencies:
module:
- node
id: node.field_sent_to_social_media
field_name: field_sent_to_social_media
entity_type: node
type: boolean
settings: { }
module: core
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:
- node
- taxonomy
id: node.field_tags
field_name: field_tags
entity_type: node
type: entity_reference
settings:
target_type: taxonomy_term
module: core
locked: false
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View file

@ -0,0 +1,7 @@
langcode: en
status: true
dependencies: { }
name: Tags
vid: tags
description: 'Tags for categorising blog posts.'
weight: 0

View file

@ -0,0 +1,71 @@
<?php
namespace Drupal\Tests\opdavies_blog\Kernel;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\opdavies_blog\Entity\Node\Post;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\TermInterface;
use Drupal\taxonomy\VocabularyInterface;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
final class ReorderBlogTagsTest extends EntityKernelTestBase {
use NodeCreationTrait;
use TaxonomyTestTrait;
public static $modules = [
// Core.
'node',
'taxonomy',
'link',
// Contrib.
'discoverable_entity_bundle_classes',
'hook_event_dispatcher',
// Custom.
'opdavies_blog_test',
'opdavies_blog',
];
/** @test */
public function it_reorders_tags_on_blog_posts_to_be_arranged_alphabetically(): void {
/** @var VocabularyInterface $vocabulary */
$vocabulary = Vocabulary::load('tags');
$this->createTerm($vocabulary, ['name' => 'Drupal']); // 1
$this->createTerm($vocabulary, ['name' => 'PHP']); // 2
$this->createTerm($vocabulary, ['name' => 'Symfony']); // 3
$post = $this->createNode([
'field_tags' => [3, 1, 2],
'type' => 'post',
]);
/** @var Post $post */
$post = Node::load($post->id());
$this->assertSame(
['Drupal', 'PHP', 'Symfony'],
$post->getTags()
->map(fn(TermInterface $tag) => $tag->label())
->toArray()
);
}
protected function setUp() {
parent::setUp();
$this->installConfig([
'filter',
'opdavies_blog_test',
]);
$this->installEntitySchema('taxonomy_vocabulary');
$this->installEntitySchema('taxonomy_term');
}
}