as-cornell / as_webhook_entities
Manage Drupal entities like people records and articles via webhook notifications.
Package info
github.com/as-cornell/as_webhook_entities
Type:drupal-custom-module
pkg:composer/as-cornell/as_webhook_entities
README
AS WEBHOOK ENTITIES (as_webhook_entities)
INTRODUCTION
Receives webhook notifications from remote systems and creates, updates, or deletes local Drupal entities (people, articles, taxonomy terms) accordingly. Uses a Strategy pattern with per-type handler classes for maintainability and extensibility.
REQUIREMENTS
System Requirements
- Drupal 9.5+ or Drupal 10+
- PHP 8.0+
INSTALLATION
New Installation
-
Enable the module:
drush en as_webhook_entities -y
-
Configure the module settings:
- Navigate to
/admin/config/as_webhook_entities/settings - Configure the authorization token and cron trigger settings
- Navigate to
-
Verify the queue worker is registered:
drush queue:list
You should see
webhook_entities_processorin the list.
Upgrading from 1.x to 2.0
-
Pull the updated code and clear cache:
drush cr
-
Verify the module is functioning:
drush watchdog:show --type=as_webhook_entities --count=10
CONFIGURATION
- Settings UI:
/admin/config/as_webhook_entities/settings - Runs on cron (
webhook_entities_processorqueue, 30 seconds per cron run) - Cron can be triggered on receipt via the
crontriggersetting - Logs create/update/delete operations as
as_webhook_entities
ARCHITECTURE
Strategy Pattern (v2.0+)
Per-type field logic is handled by dedicated handler classes. WebhookCrudManager is a thin dispatcher that handles shared logic (title, status, departments/domain access, save) and delegates to the appropriate handler.
as_webhook_entities/
├── src/
│ ├── WebhookCrudManager.php - Thin dispatcher, shared CRUD logic
│ ├── WebhookUuidLookup.php - Looks up existing entities by UUID
│ ├── WebhookHandler/
│ │ ├── WebhookHandlerInterface.php - applyCreateFields / applyUpdateFields
│ │ ├── WebhookHandlerBase.php - Shared lookup helpers
│ │ ├── PersonWebhookHandler.php
│ │ ├── ArticleWebhookHandler.php
│ │ ├── MediaReportEntryWebhookHandler.php
│ │ ├── MediaReportPersonWebhookHandler.php
│ │ └── TermWebhookHandler.php
│ └── Plugin/QueueWorker/
│ └── WebhookEntitiesQueue.php - Queue processor, event dispatcher
Supported Entity Types
| Payload type | Drupal entity | Handler |
|---|---|---|
person |
node:person |
PersonWebhookHandler |
article |
node:article |
ArticleWebhookHandler |
media_report_entry |
node:media_report_entry |
MediaReportEntryWebhookHandler |
media_report_person |
node:person |
MediaReportPersonWebhookHandler |
term |
taxonomy_term |
TermWebhookHandler |
Adding a New Entity Type
- Create a class in
src/WebhookHandler/extendingWebhookHandlerBase - Implement
getType(),applyCreateFields(), andapplyUpdateFields() - Register it in
WebhookCrudManager::__construct():'my_type' => new MyTypeWebhookHandler($entity_type_manager),
MAINTAINERS
Current maintainers for Drupal 10:
- Mark Wilson (markewilson)
TROUBLESHOOTING
Queue items not processing
-
Check the queue size:
drush queue:list
-
Run the queue manually:
drush queue:run webhook_entities_processor
-
Check recent logs:
drush watchdog:show --type=as_webhook_entities --count=20
Entity not created or updated
-
Verify the UUID lookup is finding the entity:
lando drush php-eval " \$lookup = \Drupal::service('as_webhook_entities.uuid_lookup'); \$entity = \$lookup->findEntity('YOUR-UUID-HERE', 'person'); echo \$entity ? 'Found: ' . \$entity->id() : 'Not found'; "
-
Push a test payload directly into the queue:
lando drush php-eval " \$payload = json_encode([ 'event' => 'create', 'type' => 'person', 'uuid' => 'test-uuid-001', 'status' => '1', 'uid' => '1', 'title' => 'Test Person', 'field_departments_programs' => [], 'field_overview_research' => [], 'field_links' => [], ]); \Drupal::queue('webhook_entities_processor')->createItem(\$payload); echo 'Queued.' . PHP_EOL; " lando drush queue:run webhook_entities_processor
-
Check for field errors — if a field in the payload doesn't exist on the destination bundle, the update will fail. Verify field existence:
lando drush php-eval " \$fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('node', 'article'); echo implode(', ', array_keys(\$fields)); "
CHANGELOG
2.0
- Refactored
WebhookCrudManagerusing the Strategy pattern — per-type field logic extracted into dedicated handler classes undersrc/WebhookHandler/ - Added
WebhookHandlerInterfaceandWebhookHandlerBasewith shared entity lookup helpers (lookupTermTidsByName,lookupTermTidsByProperty,lookupNodeNidsByRemoteUuid) - Added handler classes:
PersonWebhookHandler,ArticleWebhookHandler,MediaReportEntryWebhookHandler,MediaReportPersonWebhookHandler,TermWebhookHandler WebhookCrudManageris now a thin dispatcher; shared logic (departments/domain access, node creation, save) remains centralised- Simplified
WebhookUuidLookup::findEntity()to a type-keyed lookup map, eliminating duplicate if blocks - Cleaned up
WebhookEntitiesQueue: removed redundant UUID ternary, extracteddispatchCreate()helper, removed dead code - Fixed two bugs in
MediaReportEntryWebhookHandler:field_news_datewas incorrectly read fromfield_outlet_name, andfield_media_report_public_cathad a variable typo - Moved
field_portrait_image_altout of shared update logic intoArticleWebhookHandlerwhere it belongs