Move all files to old/drupal/

This commit is contained in:
Oliver Davies 2025-10-02 07:57:25 +01:00
parent 8203e983d5
commit 7d76bf2968
468 changed files with 0 additions and 0 deletions

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_has_tweet
- node.type.post
id: node.post.field_has_tweet
field_name: field_has_tweet
entity_type: node
bundle: post
label: 'Has tweet'
description: 'Check to include Twitter''s widget.js script for this page.'
required: false
translatable: false
default_value:
-
value: 0
default_value_callback: ''
settings:
on_label: 'Yes'
off_label: 'No'
field_type: boolean

View file

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

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_has_tweet
field_name: field_has_tweet
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,17 @@
langcode: en
status: true
dependencies:
module:
- node
id: node.field_send_to_social_media
field_name: field_send_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,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,11 @@
langcode: en
status: true
dependencies: { }
third_party_settings: { }
name: 'Blog post'
type: post
description: 'A single blog post.'
help: ''
new_revision: true
preview_mode: 1
display_submitted: true

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,4 @@
name: Oliver Davies Posts Test
type: module
core_version_requirement: ^8 || ^9
hidden: true

View file

@ -0,0 +1,9 @@
parameters:
container.autowiring.strict_mode: true
services:
Drupal\Core\Entity\EntityTypeManagerInterface:
alias: entity_type.manager
Drupal\opdavies_blog\Service\PostPusher\PostPusher:
class: Drupal\opdavies_blog\Service\PostPusher\NullPostPusher

View file

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Drupal\opdavies_blog_test\Factory;
use Assert\Assert;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\node\Entity\Node;
use Drupal\opdavies_blog\Entity\Node\Post;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\TermInterface;
use Illuminate\Support\Collection;
final class PostFactory {
private EntityStorageInterface $termStorage;
private Collection $tags;
private string $title = 'This is a test blog post';
public function __construct(
EntityTypeManagerInterface $entityTypeManager
) {
$this->termStorage = $entityTypeManager->getStorage('taxonomy_term');
$this->tags = new Collection();
}
public function create(array $overrides = []): Post {
$this->tags->each(function (TermInterface $tag): void {
Assert::that($tag->bundle())->same('tags');
});
$values = [
'title' => $this->title,
'type' => 'post',
Post::FIELD_TAGS => $this->tags->toArray(),
];
$post = Node::create($values + $overrides);
return Post::createFromNode($post);
}
public function setTitle(string $title): self {
Assert::that($title)->notEmpty();
$this->title = $title;
return $this;
}
public function withTags(array $tags): self {
$this->tags = new Collection();
foreach ($tags as $tag) {
Assert::that($tag)->notEmpty()->string();
$this->tags->push($this->createOrReferenceTag($tag));
}
return $this;
}
private function createOrReferenceTag(string $tag): EntityInterface {
$existingTags = $this->termStorage->loadByProperties(['name' => $tag]);
if ($existingTags) {
return reset($existingTags);
}
return Term::create(['vid' => 'tags', 'name' => $tag]);
}
}

View file

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Drupal\opdavies_blog_test;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Finder\Finder;
final class OpdaviesBlogTestServiceProvider implements ServiceProviderInterface {
public function register(ContainerBuilder $container): void {
foreach (['Factory'] as $directory) {
$files = Finder::create()
->in(__DIR__ . '/' . $directory)
->files()
->name('*.php');
foreach ($files as $file) {
$class = 'Drupal\opdavies_blog_test\\' . $directory . '\\' .
str_replace('/', '\\', substr($file->getRelativePathname(), 0, -4));
if ($container->hasDefinition($class)) {
continue;
}
$definition = new Definition($class);
$definition->setAutowired(TRUE);
$container->setDefinition($class, $definition);
}
}
}
}

View file

@ -0,0 +1,49 @@
<?php
// phpcs:disable Drupal.Commenting.DocComment, Drupal.NamingConventions.ValidFunctionName
namespace Drupal\Tests\opdavies_blog\Kernel\Entity\Node;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\opdavies_blog\Entity\Node\Post;
use Drupal\opdavies_blog_test\Factory\PostFactory;
final class PostTest extends EntityKernelTestBase {
public static $modules = [
// Core.
'node',
'link',
'taxonomy',
// Custom.
'opdavies_blog',
'opdavies_blog_test',
];
private PostFactory $postFactory;
/** @test */
public function it_can_determine_if_a_post_contains_a_tweet(): void {
$post = $this->postFactory->create();
$post->save();
$this->assertFalse($post->hasTweet());
$post = $this->postFactory->create([Post::FIELD_HAS_TWEET => TRUE]);
$post->save();
$this->assertTrue($post->hasTweet());
}
protected function setUp() {
parent::setUp();
$this->postFactory = $this->container->get(PostFactory::class);
$this->installEntitySchema('taxonomy_term');
$this->installConfig(['opdavies_blog_test']);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\opdavies_blog\Kernel;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
abstract class PostTestBase extends EntityKernelTestBase {
use NodeCreationTrait;
use TaxonomyTestTrait;
public static $modules = [
// Core.
'node',
'taxonomy',
'link',
// Contrib.
'hook_event_dispatcher',
'core_event_dispatcher',
// Custom.
'opdavies_blog_test',
'opdavies_blog',
];
protected function setUp() {
parent::setUp();
$this->installConfig([
'filter',
'opdavies_blog_test',
]);
$this->installEntitySchema('taxonomy_vocabulary');
$this->installEntitySchema('taxonomy_term');
}
}

View file

@ -0,0 +1,77 @@
<?php
// phpcs:disable Drupal.Commenting.DocComment, Drupal.NamingConventions.ValidFunctionName
namespace Drupal\Tests\opdavies_blog\Kernel;
use Drupal\Core\Queue\QueueInterface;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\node\NodeInterface;
use Drupal\opdavies_blog\Entity\Node\Post;
final class PushToSocialMediaTest extends EntityKernelTestBase {
use NodeCreationTrait;
public static $modules = [
// Core.
'node',
'taxonomy',
'link',
// Contrib.
'hook_event_dispatcher',
'core_event_dispatcher',
// Custom.
'opdavies_blog',
'opdavies_blog_test',
];
private QueueInterface $queue;
/** @test */
public function it_queues_a_post_when_it_is_created(): void {
$this->assertSame(0, $this->queue->numberOfItems());
$this->createNode([
'title' => 'Ignoring PHPCS sniffs within PHPUnit tests',
'type' => 'post',
]);
$this->assertSame(1, $this->queue->numberOfItems());
$item = $this->queue->claimItem();
/** @var Post $post */
$post = $item->data['post'];
$this->assertNotNull($post);
$this->assertInstanceOf(NodeInterface::class, $post);
$this->assertSame('post', $post->bundle());
$this->assertSame('Ignoring PHPCS sniffs within PHPUnit tests', $post->getTitle());
}
/** @test */
public function it_queues_a_post_when_it_is_updated(): void {
$this->markTestSkipped();
}
/** @test */
public function it_pushes_a_post_when_the_queue_is_processed(): void {
$this->markTestSkipped();
}
protected function setUp() {
parent::setUp();
$this->installConfig(['filter', 'opdavies_blog_test']);
$this->installSchema('node', ['node_access']);
$this->queue = $this->container->get('queue')
->get('opdavies_blog.push_post_to_social_media');
}
}

View file

@ -0,0 +1,67 @@
<?php
// phpcs:disable Drupal.Commenting.DocComment, Drupal.NamingConventions.ValidFunctionName
namespace Drupal\Tests\opdavies_blog\Kernel;
use Drupal\opdavies_blog\Repository\RelatedPostsRepository;
use Drupal\opdavies_blog_test\Factory\PostFactory;
final class RelatedPostsTest extends PostTestBase {
private PostFactory $postFactory;
private RelatedPostsRepository $relatedPostsRepository;
/** @test */
public function it_returns_related_posts(): void {
$postA = $this->postFactory
->setTitle('Post A')
->withTags(['Drupal 8'])
->create();
$postA->save();
$postB = $this->postFactory
->setTitle('Post B')
->withTags(['Drupal 8'])
->create();
$postB->save();
$relatedPosts = $this->relatedPostsRepository->getFor($postA);
$this->assertCount(1, $relatedPosts);
$this->assertSame('Post B', $relatedPosts->first()->label());
}
/** @test */
public function unpublished_posts_are_not_returned(): void {
$this->markTestSkipped();
}
/** @test */
public function it_returns_an_empty_collection_if_there_are_no_related_posts(): void {
$postA = $this->postFactory
->setTitle('Drupal 8 post')
->withTags(['Drupal 8'])
->create();
$postA->save();
$postB = $this->postFactory
->setTitle('Drupal 9 post')
->withTags(['Drupal 9'])
->create();
$postB->save();
$relatedPosts = $this->relatedPostsRepository->getFor($postA);
$this->assertEmpty($relatedPosts);
}
protected function setUp() {
parent::setUp();
$this->postFactory = $this->container->get(PostFactory::class);
$this->relatedPostsRepository = $this->container->get(RelatedPostsRepository::class);
}
}

View file

@ -0,0 +1,41 @@
<?php
// phpcs:disable Drupal.Commenting.DocComment, Drupal.NamingConventions.ValidFunctionName
namespace Drupal\Tests\opdavies_blog\Kernel;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\opdavies_blog\Entity\Node\Post;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\TermInterface;
use Drupal\taxonomy\VocabularyInterface;
final class ReorderBlogTagsTest extends PostTestBase {
/** @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']);
$this->createTerm($vocabulary, ['name' => 'PHP']);
$this->createTerm($vocabulary, ['name' => 'Symfony']);
$post = $this->createNode([
'type' => 'post',
Post::FIELD_TAGS => [3, 1, 2],
]);
$node = Node::load($post->id());
$post = Post::createFromNode($node);
$this->assertSame(
['Drupal', 'PHP', 'Symfony'],
$post->getTags()
->map(fn(TermInterface $tag) => $tag->label())
->toArray()
);
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Drupal\Tests\opdavies_blog\Kernel\UseCase;
use Drupal\opdavies_blog\UseCase\ConvertPostToTweet;
use Drupal\opdavies_blog_test\Factory\PostFactory;
use Drupal\Tests\opdavies_blog\Kernel\PostTestBase;
final class ConvertPostToTweetTest extends PostTestBase {
private ConvertPostToTweet $convertPostToTweet;
public function testConvertPostToTweet(): void {
$post = $this->postFactory
->setTitle('Creating a custom PHPUnit command for DDEV')
->withTags(['Automated testing', 'DDEV', 'Drupal', 'Drupal 8', 'PHP'])
->create();
$post->save();
$expected = <<<EOF
Creating a custom PHPUnit command for DDEV
http://localhost/node/1
#AutomatedTesting #DDEV #Drupal #Drupal8 #PHP
EOF;
$this->assertSame($expected, ($this->convertPostToTweet)($post));
}
public function testCertainTermsAreNotAddedAsHashtags(): void {
$post = $this->postFactory
->setTitle('Drupal Planet should not be added as a hashtag')
->withTags(['Drupal', 'Drupal Planet', 'PHP'])
->create();
$post->save();
$expected = <<<EOF
Drupal Planet should not be added as a hashtag
http://localhost/node/1
#Drupal #PHP
EOF;
$this->assertSame($expected, ($this->convertPostToTweet)($post));
}
public function testSomeTagsAreNotAutomaticallyCapitalised(): void {
$this->markTestSkipped();
}
protected function setUp() {
parent::setUp();
$this->convertPostToTweet = $this->container->get(ConvertPostToTweet::class);
$this->postFactory = $this->container->get(PostFactory::class);
}
}