Rename custom module directories
- Rename `opdavies_blog` to `blog`. - Rename `opdavies_blog_test` to `blog_test`. - Rename `opdavies_talks` to `talks`. - Rename `opdavies_talks_test` to `talks_test`. The files within the directories haven't changed, so there is no breaking change caused by renaming the directories. Please enter the commit message for your changes. Lines starting
This commit is contained in:
parent
d7d5a6c8a3
commit
cbe60209e6
59 changed files with 0 additions and 0 deletions
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opdavies_blog\Command;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
final class ExportBodyValuesForThemePurgingCommand {
|
||||
|
||||
private static array $tableNames = [
|
||||
'block_content__body',
|
||||
'node__body',
|
||||
];
|
||||
|
||||
private string $filename = 'body-field-values.txt';
|
||||
|
||||
private Connection $database;
|
||||
|
||||
public function __construct(Connection $database) {
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drush command to export body field values into a file.
|
||||
*
|
||||
* @command opdavies:export-body-values-for-theme-purging
|
||||
*/
|
||||
public function handle(): void {
|
||||
$values = Collection::make(self::$tableNames)
|
||||
->flatMap(fn(string $tableName) => $this->getValuesFromTable($tableName))
|
||||
->implode(PHP_EOL);
|
||||
|
||||
file_put_contents($this->getFilePath(), $values);
|
||||
}
|
||||
|
||||
private function getFilePath(): string {
|
||||
return drupal_get_path('theme', 'opdavies') . DIRECTORY_SEPARATOR . $this->filename;
|
||||
}
|
||||
|
||||
private function getValuesFromTable(string $tableName): array {
|
||||
return $this->database->select($tableName)
|
||||
->fields($tableName, ['body_value'])
|
||||
->execute()
|
||||
->fetchCol();
|
||||
}
|
||||
|
||||
}
|
138
web/modules/custom/blog/src/Command/FormatTagNamesCommand.php
Normal file
138
web/modules/custom/blog/src/Command/FormatTagNamesCommand.php
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opdavies_blog\Command;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drush\Commands\DrushCommands;
|
||||
|
||||
final class FormatTagNamesCommand extends DrushCommands {
|
||||
|
||||
/**
|
||||
* A lookup table for new name overrides.
|
||||
*
|
||||
* @var array
|
||||
* An associative array, keyed by the original tag name. The value is either
|
||||
* an overridden tag name or FALSE if the tag name is not to be changed.
|
||||
*/
|
||||
private static $tagNames = [
|
||||
'accessible-bristol' => 'Accessible Bristol',
|
||||
'admin:hover' => FALSE,
|
||||
'aria' => 'ARIA',
|
||||
'cck' => 'CCK',
|
||||
'centos' => 'CentOS',
|
||||
'css' => 'CSS',
|
||||
'dcbristol' => FALSE,
|
||||
'ddev' => 'DDEV',
|
||||
'drupal-association' => 'Drupal Association',
|
||||
'drupal-bristol' => 'Drupal Bristol',
|
||||
'drupal-commerce' => 'Drupal Commerce',
|
||||
'drupal-planet' => 'Drupal Planet',
|
||||
'drupal-vm' => 'Drupal VM',
|
||||
'drupal-vm-generator' => 'Drupal VM Generator',
|
||||
'drupalcamp' => 'DrupalCamp',
|
||||
'drupalcamp-bristol' => 'DrupalCamp Bristol',
|
||||
'drupalcamp-london' => 'DrupalCamp London',
|
||||
'drupalcamp-north' => 'DrupalCamp North',
|
||||
'drupalcon' => 'DrupalCon',
|
||||
'entity-api' => 'Entity API',
|
||||
'fancy-slide' => 'Fancy Slide',
|
||||
'field-collection' => 'Field Collection',
|
||||
'filefield' => 'FileField',
|
||||
'form-api' => 'Form API',
|
||||
'git-flow' => 'Git Flow',
|
||||
'github' => 'GitHub',
|
||||
'github-actions' => 'GitHub Actions',
|
||||
'illuminate-collections' => 'Illuminate Collections',
|
||||
'image-caption' => 'Image Caption',
|
||||
'imagecache' => 'ImageCache',
|
||||
'imagefield' => 'ImageField',
|
||||
'imagefield-import' => 'ImageField Import',
|
||||
'javascript' => 'JavaScript',
|
||||
'laravel-collections' => 'Laravel Collections',
|
||||
'laravel-mix' => 'Laravel Mix',
|
||||
'linux-journal' => 'Linux Journal',
|
||||
'mac-os-x' => 'macOS',
|
||||
'mamp' => 'MAMP',
|
||||
'mod_rewrite' => FALSE,
|
||||
'npm' => FALSE,
|
||||
'oliverdavies.co.uk' => FALSE,
|
||||
'php' => 'PHP',
|
||||
'php-south-wales' => 'PHP South Wales',
|
||||
'phpstorm' => 'PhpStorm',
|
||||
'phpsw' => 'PHPSW',
|
||||
'phpunit' => 'PHPUnit',
|
||||
'postcss' => 'PostCSS',
|
||||
'psr' => 'PSR',
|
||||
'regular-expression' => 'Regular expressions',
|
||||
'sequel-pro' => 'Sequel Pro',
|
||||
'settings.php' => FALSE,
|
||||
'sql' => 'SQL',
|
||||
'ssh' => 'SSH',
|
||||
'sublime-text' => 'Sublime Text',
|
||||
'svn' => 'SVN',
|
||||
'swdug' => 'SWDUG',
|
||||
'symfonylive' => 'SymfonyLive',
|
||||
'tailwind-css' => 'Tailwind CSS',
|
||||
'tdd' => 'TDD',
|
||||
'test-driven-drupal' => 'Test Driven Drupal',
|
||||
'views-attach' => 'Views Attach',
|
||||
'virtualbox' => 'VirtualBox',
|
||||
'vuejs' => 'VueJS',
|
||||
'virtualhostx' => 'VirtualHostX',
|
||||
];
|
||||
|
||||
/**
|
||||
* The taxonomy term storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
private $termStorage;
|
||||
|
||||
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
|
||||
parent::__construct();
|
||||
|
||||
$this->termStorage = $entityTypeManager->getStorage('taxonomy_term');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drush command for updating legacy tag names.
|
||||
*
|
||||
* @command opdavies:update-tag-names
|
||||
*/
|
||||
public function updateTagNames(): void {
|
||||
foreach ($this->getTags() as $tag) {
|
||||
$name = $tag->label();
|
||||
$newName = $this->getNewTagName($name);
|
||||
|
||||
if ($newName === NULL) {
|
||||
$this->writeln(sprintf('Skipping %s.', $name));
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->writeln(sprintf('Updating %s to %s.', $name, $newName));
|
||||
$tag->name = $newName;
|
||||
$tag->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function getTags(): array {
|
||||
return $this->termStorage->loadByProperties([
|
||||
'vid' => 'tags',
|
||||
]);
|
||||
}
|
||||
|
||||
private function getNewTagName(string $tagName): ?string {
|
||||
if (!array_key_exists($tagName, static::$tagNames)) {
|
||||
return str_replace('-', ' ', ucfirst($tagName));
|
||||
}
|
||||
|
||||
if (static::$tagNames[$tagName] === FALSE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return static::$tagNames[$tagName];
|
||||
}
|
||||
|
||||
}
|
83
web/modules/custom/blog/src/Entity/Node/Post.php
Normal file
83
web/modules/custom/blog/src/Entity/Node/Post.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opdavies_blog\Entity\Node;
|
||||
|
||||
use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Defines an blog post node class.
|
||||
*
|
||||
* @ContentEntityBundleClass(
|
||||
* label = @Translation("Blog post"),
|
||||
* entity_type = "node",
|
||||
* bundle = "post"
|
||||
* );
|
||||
*/
|
||||
class Post extends Node implements ContentEntityBundleInterface {
|
||||
|
||||
public function getExternalLink(): ?array {
|
||||
return ($link = $this->get('field_external_link')->get(0))
|
||||
? $link->getValue()
|
||||
: NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Term[]
|
||||
*/
|
||||
public function getTags(): Collection {
|
||||
return new Collection($this->get('field_tags')->referencedEntities());
|
||||
}
|
||||
|
||||
public function hasBeenSentToSocialMedia(): bool {
|
||||
return (bool) $this->get('field_sent_to_social_media')->getString();
|
||||
}
|
||||
|
||||
public function hasTweet(): bool {
|
||||
return (bool) $this->get('field_has_tweet')->getString();
|
||||
}
|
||||
|
||||
public function isExternalPost(): bool {
|
||||
return (bool) $this->getExternalLink();
|
||||
}
|
||||
|
||||
public function setTags(array $tags): void {
|
||||
$this->set('field_tags', $tags);
|
||||
}
|
||||
|
||||
public function toTweet(): string {
|
||||
$parts = [
|
||||
$this->label(),
|
||||
$this->url('canonical', ['absolute' => TRUE]),
|
||||
$this->convertTermsToHashtags(),
|
||||
];
|
||||
|
||||
return implode(PHP_EOL . PHP_EOL, $parts);
|
||||
}
|
||||
|
||||
private function convertTermsToHashtags(): string {
|
||||
return $this->getTags()
|
||||
->filter(fn(Term $term) => !$this->tagsToRemove()
|
||||
->contains($term->label()))
|
||||
->map(fn(Term $term) => $this->convertTermToHashtag($term))
|
||||
->implode(' ');
|
||||
}
|
||||
|
||||
private function tagsToRemove(): Collection {
|
||||
// TODO: Move these values into configuration/settings.php.
|
||||
return new Collection([
|
||||
'Drupal Planet',
|
||||
]);
|
||||
}
|
||||
|
||||
private function convertTermToHashtag(Term $tag): string {
|
||||
return '#' . (new Collection(explode(' ', $tag->label())))
|
||||
->map(fn(string $word): string => ucfirst($word))
|
||||
->implode('');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opdavies_blog\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\ImmutableConfig;
|
||||
use Drupal\hook_event_dispatcher\Event\Entity\BaseEntityEvent;
|
||||
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
|
||||
use Drupal\opdavies_blog\Entity\Node\Post;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
final class PushBlogPostToSocialMedia implements EventSubscriberInterface {
|
||||
|
||||
private ClientInterface $client;
|
||||
|
||||
private ImmutableConfig $config;
|
||||
|
||||
public function __construct(
|
||||
ConfigFactoryInterface $configFactory,
|
||||
Client $client
|
||||
) {
|
||||
$this->client = $client;
|
||||
$this->config = $configFactory->get('opdavies_blog.settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
return [
|
||||
HookEventDispatcherInterface::ENTITY_INSERT => 'onEntityUpdate',
|
||||
HookEventDispatcherInterface::ENTITY_UPDATE => 'onEntityUpdate',
|
||||
];
|
||||
}
|
||||
|
||||
public function onEntityUpdate(BaseEntityEvent $event): void {
|
||||
$entity = $event->getEntity();
|
||||
|
||||
if ($entity->getEntityTypeId() != 'node') {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Post $entity */
|
||||
if ($entity->bundle() != 'post') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity->isPublished()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this post has already been sent to social media, do not send it again.
|
||||
if ($entity->hasBeenSentToSocialMedia()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->isExternalPost()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$url = $this->config->get('zapier_post_tweet_url')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->client->post($url, [
|
||||
'form_params' => [
|
||||
'message' => $entity->toTweet(),
|
||||
],
|
||||
]);
|
||||
|
||||
$entity->set('field_sent_to_social_media', TRUE);
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
27
web/modules/custom/blog/src/Repository/PostRepository.php
Normal file
27
web/modules/custom/blog/src/Repository/PostRepository.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opdavies_blog\Repository;
|
||||
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
final class PostRepository {
|
||||
|
||||
private EntityStorageInterface $nodeStorage;
|
||||
|
||||
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
|
||||
$this->nodeStorage = $entityTypeManager->getStorage('node');
|
||||
}
|
||||
|
||||
public function getAll(): Collection {
|
||||
return new Collection(
|
||||
$this->nodeStorage->loadByProperties([
|
||||
'type' => 'post',
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue