From 8278fa36baba6451283bbbfc0e02af6cd343dc21 Mon Sep 17 00:00:00 2001 From: dannylamb Date: Thu, 26 Jan 2017 23:28:59 -0400 Subject: [PATCH] Resolves Islandora-CLAW/CLAW#468 (#31) * Broadcaster rules action. * Re-exporting rules * Tests * Updating travis environment for testing with activemq --- .gitignore | 1 + .scripts/travis_setup.sh | 13 +- .travis.yml | 10 +- composer.json | 3 +- ...lay.fedora_resource.rdf_source.default.yml | 7 + ...ntity_view_mode.fedora_resource.teaser.yml | 10 +- ...resource.rdf_source.field_ldp_contains.yml | 18 ++- ...ge.fedora_resource.field_ldp_contains.yml} | 10 +- ...ra.fedora_resource_type.non_rdf_source.yml | 10 +- ...andora.fedora_resource_type.rdf_source.yml | 8 ++ config/install/islandora.settings.yml | 8 +- ...ng.fedora_resource_type.non_rdf_source.yml | 11 +- ...apping.fedora_resource_type.rdf_source.yml | 11 +- .../rules.reaction.broadcast_create_event.yml | 15 ++- .../rules.reaction.broadcast_delete_event.yml | 15 ++- .../rules.reaction.broadcast_update_event.yml | 15 ++- .../views.view.fedora_entities_reference.yml | 7 + config/schema/islandora.schema.yml | 14 ++ islandora.services.yml | 4 + .../EventGeneratorActionBase.php | 2 +- src/Form/IslandoraSettingsForm.php | 51 +++++-- src/Plugin/RulesAction/Broadcaster.php | 125 +++++++++++++++++ src/StompFactory.php | 33 +++++ tests/src/Kernel/BroadcasterTest.php | 127 ++++++++++++++++++ tests/src/Kernel/EventGeneratorTestBase.php | 8 +- tests/src/Kernel/IslandoraKernelTestBase.php | 1 + tests/src/Kernel/VectorClockTest.php | 15 ++- 27 files changed, 475 insertions(+), 77 deletions(-) create mode 100644 .gitignore rename config/install/{field.storage.fedora_resource.rdf_source.field_ldp_contains.yml => field.storage.fedora_resource.field_ldp_contains.yml} (63%) create mode 100644 config/schema/islandora.schema.yml create mode 100644 src/Plugin/RulesAction/Broadcaster.php create mode 100644 src/StompFactory.php create mode 100644 tests/src/Kernel/BroadcasterTest.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..22d0d82f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/.scripts/travis_setup.sh b/.scripts/travis_setup.sh index ea2bfb78..93eb196f 100755 --- a/.scripts/travis_setup.sh +++ b/.scripts/travis_setup.sh @@ -65,11 +65,16 @@ drush en -y jsonld drush en -y islandora -drush -y dl bootstrap -drush -y en bootstrap -drush -y config-set system.theme default bootstrap - drush cr + +# ACTIVEMQ +cd $HOME +wget "http://archive.apache.org/dist/activemq/5.14.3/apache-activemq-5.14.3-bin.tar.gz" +tar -xzf apache-activemq-5.14.3-bin.tar.gz +sudo sed -i 's|ACTIVEMQ_USER="activemq"|ACTIVEMQ_USER="travis"|' /etc/default/activemq +apache-activemq-5.14.3/bin/activemq start + # The shebang in this file is a bogeyman that is haunting the web test cases. rm /home/travis/.phpenv/rbenv.d/exec/hhvm-switcher.bash + sleep 20 diff --git a/.travis.yml b/.travis.yml index cda9420c..4b06ff6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,27 +15,21 @@ branches: only: - /^8.x/ -addons: - apt: - packages: - - activemq - before_install: - export ISLANDORA_DIR=$TRAVIS_BUILD_DIR install: - - printf "no" | pecl install stomp - $TRAVIS_BUILD_DIR/.scripts/travis_setup.sh - composer install - php vendor/bin/phpcs --config-set installed_paths vendor/drupal/coder/coder_sniffer - + - cd $HOME/drupal; composer require stomp-php/stomp-php:4.* script: - $ISLANDORA_DIR/.scripts/line_endings.sh . - cd $HOME/drupal/modules/islandora - php vendor/bin/phpcs --standard=Drupal --extensions=module/php,php/php src tests - php vendor/bin/phpcpd --names *.module,*.inc,*.test,*.php --exclude=vendor . - - cd $HOME/drupal; php core/scripts/run-tests.sh --php `which php` islandora + - cd $HOME/drupal; php core/scripts/run-tests.sh --verbose --php `which php` islandora notifications: irc: diff --git a/composer.json b/composer.json index a51a1eae..19c5ef79 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "drupal/inline_entity_form": "^1.0@beta", "drupal/rules": "^3.0@alpha", "drupal/search_api": "^1.0@beta", - "islandora/claw-jsonld": "dev-8.x-1.x" + "islandora/claw-jsonld": "dev-8.x-1.x", + "stomp-php/stomp-php": "4.*" }, "require-dev": { "phpunit/phpunit": "^4.8", diff --git a/config/install/core.entity_form_display.fedora_resource.rdf_source.default.yml b/config/install/core.entity_form_display.fedora_resource.rdf_source.default.yml index 61353577..802d45ae 100644 --- a/config/install/core.entity_form_display.fedora_resource.rdf_source.default.yml +++ b/config/install/core.entity_form_display.fedora_resource.rdf_source.default.yml @@ -1,9 +1,15 @@ +uuid: ab918e50-21f9-42b3-b490-42fee6177162 langcode: en status: true dependencies: + enforced: + module: + - islandora config: - field.field.fedora_resource.rdf_source.field_ldp_contains - islandora.fedora_resource_type.rdf_source +_core: + default_config_hash: jDTpzFJD_PoXr0W008d5FvJV65oGCh89KANvALcy_O4 id: fedora_resource.rdf_source.default targetEntityType: fedora_resource bundle: rdf_source @@ -58,3 +64,4 @@ content: placeholder: '' third_party_settings: { } hidden: { } + diff --git a/config/install/core.entity_view_mode.fedora_resource.teaser.yml b/config/install/core.entity_view_mode.fedora_resource.teaser.yml index 36f1a934..d76f3f15 100644 --- a/config/install/core.entity_view_mode.fedora_resource.teaser.yml +++ b/config/install/core.entity_view_mode.fedora_resource.teaser.yml @@ -2,9 +2,13 @@ uuid: 0efc20d3-0bd6-4606-842f-b87548de1924 langcode: en status: true dependencies: - module: - - islandora + enforced: + module: + - islandora +_core: + default_config_hash: PnOwgzHIcT0m2y9dN2B5D7og29JXDCm4dCqb1pKUWek id: fedora_resource.teaser label: Teaser targetEntityType: fedora_resource -cache: true \ No newline at end of file +cache: true + diff --git a/config/install/field.field.fedora_resource.rdf_source.field_ldp_contains.yml b/config/install/field.field.fedora_resource.rdf_source.field_ldp_contains.yml index 452c1357..9810847c 100644 --- a/config/install/field.field.fedora_resource.rdf_source.field_ldp_contains.yml +++ b/config/install/field.field.fedora_resource.rdf_source.field_ldp_contains.yml @@ -1,25 +1,31 @@ +uuid: 29ea11d1-4267-4bc1-bdc0-550e58833c0b langcode: en status: true dependencies: + enforced: + module: + - islandora config: - - field.storage.fedora_resource.rdf_source.field_ldp_contains - - islandora.fedora_resource_type.non_rdf_source + - field.storage.fedora_resource.field_ldp_contains - islandora.fedora_resource_type.rdf_source +_core: + default_config_hash: y-E4uXZywn0AAVWULpj46kKRevLvEFQup5pLJ2J9jsk id: fedora_resource.rdf_source.field_ldp_contains field_name: field_ldp_contains entity_type: fedora_resource bundle: rdf_source -label: ldp:contains +label: 'ldp:contains' description: 'Contains Fedora Resource.' required: false translatable: false default_value: { } default_value_callback: '' settings: - handler: 'default:fedora_resource' + handler: views handler_settings: view: - view_name: bundles_of_fedora + view_name: fedora_entities_reference display_name: entity_reference_1 arguments: { } -field_type: entity_reference \ No newline at end of file +field_type: entity_reference + diff --git a/config/install/field.storage.fedora_resource.rdf_source.field_ldp_contains.yml b/config/install/field.storage.fedora_resource.field_ldp_contains.yml similarity index 63% rename from config/install/field.storage.fedora_resource.rdf_source.field_ldp_contains.yml rename to config/install/field.storage.fedora_resource.field_ldp_contains.yml index 21595e43..fdea66bc 100644 --- a/config/install/field.storage.fedora_resource.rdf_source.field_ldp_contains.yml +++ b/config/install/field.storage.fedora_resource.field_ldp_contains.yml @@ -1,8 +1,12 @@ +uuid: d40c0b76-1a6d-4dd2-8f0b-2945e30d2832 langcode: en status: true dependencies: - module: - - islandora + enforced: + module: + - islandora +_core: + default_config_hash: jkwDP8hekY3eWzIrEN4yinGftfXZlArUaz7PsiU6BcM id: fedora_resource.field_ldp_contains field_name: field_ldp_contains entity_type: fedora_resource @@ -15,4 +19,4 @@ cardinality: -1 translatable: true indexes: { } persist_with_no_fields: false -custom_storage: false \ No newline at end of file +custom_storage: false diff --git a/config/install/islandora.fedora_resource_type.non_rdf_source.yml b/config/install/islandora.fedora_resource_type.non_rdf_source.yml index 6a0cb707..84fd1c21 100644 --- a/config/install/islandora.fedora_resource_type.non_rdf_source.yml +++ b/config/install/islandora.fedora_resource_type.non_rdf_source.yml @@ -1,3 +1,11 @@ +uuid: 68d5a1cb-e493-4e9d-adad-21229a41ac68 langcode: en +status: true +dependencies: + enforced: + module: + - islandora +_core: + default_config_hash: KgkkNCMXV1urHhxyo7wuwYPWaEAnyLAXvwrRnZWDmtw id: non_rdf_source -label: 'Non RDF Source' \ No newline at end of file +label: 'Non RDF Source' diff --git a/config/install/islandora.fedora_resource_type.rdf_source.yml b/config/install/islandora.fedora_resource_type.rdf_source.yml index 64a9808e..17de2d9f 100644 --- a/config/install/islandora.fedora_resource_type.rdf_source.yml +++ b/config/install/islandora.fedora_resource_type.rdf_source.yml @@ -1,3 +1,11 @@ +uuid: af1cb3d8-2c1f-4ca1-a1c2-b1173704807f langcode: en +status: true +dependencies: + enforced: + module: + - islandora +_core: + default_config_hash: 61Pa7qgwWd8HBTCgoxF3RxTsvCBcmHNhfg5k8FPqEpQ id: rdf_source label: 'RDF Source' diff --git a/config/install/islandora.settings.yml b/config/install/islandora.settings.yml index efcdc773..7c052397 100644 --- a/config/install/islandora.settings.yml +++ b/config/install/islandora.settings.yml @@ -1,4 +1,6 @@ -broker_url: 'http://localhost:61613' -triplestore_index_queue: '/islandora/triplestore/index' +broker_url: 'tcp://localhost:61613' fedora_rest_endpoint: 'http://localhost:8080/fcrepo/rest' -fedora_indexing_queue: 'islandora/indexing/fedora' +_core: + default_config_hash: nDZDR2rrpXXQ-D_7BYrdDFAXYOsB5hgH6vCAMV5I3w8 +broadcast_queue: islandora-connector-broadcast + diff --git a/config/install/rdf.mapping.fedora_resource_type.non_rdf_source.yml b/config/install/rdf.mapping.fedora_resource_type.non_rdf_source.yml index 96e8d3b0..aa12b32a 100644 --- a/config/install/rdf.mapping.fedora_resource_type.non_rdf_source.yml +++ b/config/install/rdf.mapping.fedora_resource_type.non_rdf_source.yml @@ -1,11 +1,15 @@ +uuid: 58d7388f-c602-4a03-9c63-aed54b8d2b7e langcode: en status: true dependencies: + enforced: + module: + - islandora config: - islandora.fedora_resource_type.non_rdf_source - module: - - islandora -id: fedora_resource_type.non_rdf_source +_core: + default_config_hash: HoZxZHzZDjK45CfvxQaCJCn6eqr9Ve2FxcqtLlYf-RI +id: fedora_resource.non_rdf_source targetEntityType: fedora_resource bundle: non_rdf_source types: @@ -41,3 +45,4 @@ fieldMappings: properties: - 'ldp:contains' mapping_type: rel + diff --git a/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml b/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml index 6697ebc7..9169a752 100644 --- a/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml +++ b/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml @@ -1,11 +1,15 @@ +uuid: 77e9e71f-f67f-438f-80eb-bb5fa931a5ec langcode: en status: true dependencies: + enforced: + module: + - islandora config: - islandora.fedora_resource_type.rdf_source - module: - - islandora -id: fedora_resource_type.rdf_source +_core: + default_config_hash: SXB_6Qvx5WtM-zrkkgEOjok1YGMeyjn9Zsa7ymV2MbM +id: fedora_resource.rdf_source targetEntityType: fedora_resource bundle: rdf_source types: @@ -45,3 +49,4 @@ fieldMappings: properties: - 'ldp:contains' mapping_type: rel + diff --git a/config/install/rules.reaction.broadcast_create_event.yml b/config/install/rules.reaction.broadcast_create_event.yml index e740c0b5..95e35c54 100644 --- a/config/install/rules.reaction.broadcast_create_event.yml +++ b/config/install/rules.reaction.broadcast_create_event.yml @@ -8,6 +8,8 @@ dependencies: enforced: module: - islandora +_core: + default_config_hash: EKVRKXObBdrm-lGcG3RPpF8sg0tZSZbZx00lkzm42_E id: broadcast_create_event label: 'Broadcast Create Event' events: @@ -40,17 +42,16 @@ expression: action_id: islandora_create_event_generator - id: rules_action - uuid: bbcd7317-2879-4961-a79d-5827fab4e194 + uuid: 2afa7216-91bb-49a3-a567-e504ba8f95e1 context_values: - type: info - repeat: false + recipients: + - "activemq:queue:islandora-indexing-fcrepo\r" + - 'activemq:queue:islandora-indexing-triplestore' context_mapping: message: event_message context_processors: - type: - rules_tokens: { } - repeat: + recipients: rules_tokens: { } provides_mapping: { } - action_id: rules_system_message + action_id: islandora_broadcast diff --git a/config/install/rules.reaction.broadcast_delete_event.yml b/config/install/rules.reaction.broadcast_delete_event.yml index 96c6d411..cb470615 100644 --- a/config/install/rules.reaction.broadcast_delete_event.yml +++ b/config/install/rules.reaction.broadcast_delete_event.yml @@ -8,6 +8,8 @@ dependencies: enforced: module: - islandora +_core: + default_config_hash: 79mBUbR_0wDo3oT4vWjuFgGPic_hghVkQ0yiYMuxLns id: broadcast_delete_event label: 'Broadcast Delete Event' events: @@ -40,17 +42,16 @@ expression: action_id: islandora_delete_event_generator - id: rules_action - uuid: bacf7f09-1d54-46f2-a4b9-e345992a604d + uuid: 53942d65-7567-4b6b-9b43-4d67079651f6 context_values: - type: info - repeat: false + recipients: + - "activemq:queue:islandora-indexing-fcrepo\r" + - 'activemq:queue:islandora-indexing-triplestore' context_mapping: message: event_message context_processors: - type: - rules_tokens: { } - repeat: + recipients: rules_tokens: { } provides_mapping: { } - action_id: rules_system_message + action_id: islandora_broadcast diff --git a/config/install/rules.reaction.broadcast_update_event.yml b/config/install/rules.reaction.broadcast_update_event.yml index f0529981..deedc0cb 100644 --- a/config/install/rules.reaction.broadcast_update_event.yml +++ b/config/install/rules.reaction.broadcast_update_event.yml @@ -8,6 +8,8 @@ dependencies: enforced: module: - islandora +_core: + default_config_hash: XX87LaQzcIVbzZTzUR4HBgeZKCzKOMJzVCTJYgmg47k id: broadcast_update_event label: 'Broadcast Update Event' events: @@ -40,17 +42,16 @@ expression: action_id: islandora_update_event_generator - id: rules_action - uuid: f77c64ef-c737-4143-89b4-e1b6599232b5 + uuid: 40aa4a03-ad36-45bf-9584-ede3b9b3e5c9 context_values: - type: info - repeat: false + recipients: + - "activemq:queue:islandora-indexing-fcrepo\r" + - 'activemq:queue:islandora-indexing-triplestore' context_mapping: message: event_message context_processors: - type: - rules_tokens: { } - repeat: + recipients: rules_tokens: { } provides_mapping: { } - action_id: rules_system_message + action_id: islandora_broadcast diff --git a/config/install/views.view.fedora_entities_reference.yml b/config/install/views.view.fedora_entities_reference.yml index c23bb8c6..b3aa6a67 100644 --- a/config/install/views.view.fedora_entities_reference.yml +++ b/config/install/views.view.fedora_entities_reference.yml @@ -1,9 +1,15 @@ +uuid: ec053572-be63-4209-a49a-16c09c9a3e73 langcode: en status: true dependencies: module: - islandora - user + enforced: + module: + - islandora +_core: + default_config_hash: UU-ZHb4xUJIu4JMAIGXvy0c93Y_xq4CPibq1qrgp098 id: fedora_entities_reference label: 'Fedora Entities Reference' module: views @@ -161,3 +167,4 @@ display: - 'languages:language_interface' - user.permissions tags: { } + diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml new file mode 100644 index 00000000..8756286d --- /dev/null +++ b/config/schema/islandora.schema.yml @@ -0,0 +1,14 @@ +islandora.settings: + type: config_object + label: 'Islandora Core Settings' + mapping: + broker_url: + type: string + label: 'Url to connect to message broker' + fedora_rest_endpoint: + type: string + label: 'Url to Fedora instance' + broadcast_queue: + type: string + label: 'Queue that handles distributing messages amongst multiple recipients' + diff --git a/islandora.services.yml b/islandora.services.yml index d1a94b40..e17fb7c4 100644 --- a/islandora.services.yml +++ b/islandora.services.yml @@ -8,3 +8,7 @@ services: arguments: ['@entity.manager'] islandora.eventgenerator: class: Drupal\islandora\EventGenerator\EventGenerator + islandora.stomp: + class: Stomp\StatefulStomp + factory: ['Drupal\islandora\StompFactory', create] + arguments: ['@config.factory'] diff --git a/src/EventGenerator/EventGeneratorActionBase.php b/src/EventGenerator/EventGeneratorActionBase.php index 5e458adb..6c66fb06 100644 --- a/src/EventGenerator/EventGeneratorActionBase.php +++ b/src/EventGenerator/EventGeneratorActionBase.php @@ -19,7 +19,7 @@ abstract class EventGeneratorActionBase extends RulesActionBase implements Conta protected $eventGenerator; /** - * Constructs a MessageBroadcaster action. + * Constructs a EventGeneratorActionBase. * * @param array $configuration * A configuration array containing information about the plugin instance. diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index c01850d8..35606f82 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -4,6 +4,9 @@ namespace Drupal\islandora\Form; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; +use Stomp\Client; +use Stomp\Exception\StompException; +use Stomp\StatefulStomp; /** * Config form for Islandora settings. @@ -12,9 +15,8 @@ class IslandoraSettingsForm extends ConfigFormBase { const CONFIG_NAME = 'islandora.settings'; const BROKER_URL = 'broker_url'; - const TRIPLESTORE_INDEX_QUEUE = 'triplestore_index_queue'; const FEDORA_REST_ENDPOINT = 'fedora_rest_endpoint'; - const FEDORA_INDEXING_QUEUE = 'fedora_indexing_queue'; + const BROADCAST_QUEUE = 'broadcast_queue'; /** * {@inheritdoc} @@ -44,10 +46,10 @@ class IslandoraSettingsForm extends ConfigFormBase { '#default_value' => $config->get(self::BROKER_URL), ); - $form[self::TRIPLESTORE_INDEX_QUEUE] = array( + $form[self::BROADCAST_QUEUE] = array( '#type' => 'textfield', - '#title' => $this->t('Triplestore Index Queue'), - '#default_value' => $config->get(self::TRIPLESTORE_INDEX_QUEUE), + '#title' => $this->t('Broadcast Queue'), + '#default_value' => $config->get(self::BROADCAST_QUEUE), ); $form[self::FEDORA_REST_ENDPOINT] = array( @@ -57,16 +59,38 @@ class IslandoraSettingsForm extends ConfigFormBase { '#default_value' => $config->get(self::FEDORA_REST_ENDPOINT), ); - $form[self::FEDORA_INDEXING_QUEUE] = array( - '#type' => 'textfield', - '#title' => $this->t('Fedora Indexing Queue Name'), - '#description' => $this->t('Name of the queue where Drupal will publish updates to have "indexed" to Fedora'), - '#default_value' => $config->get(self::FEDORA_INDEXING_QUEUE), - ); - return parent::buildForm($form, $form_state); } + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + // Validate broker url by actually connecting with a stomp client. + $brokerUrl = $form_state->getValue(self::BROKER_URL); + + // Attempt to subscribe to a dummy queue. + try { + $stomp = new StatefulStomp( + new Client( + $brokerUrl + ) + ); + $stomp->subscribe('dummy-queue-for-validation'); + $stomp->unsubscribe(); + } + // Invalidate the form if there's an issue. + catch (StompException $e) { + $form_state->setErrorByName( + self::BROKER_URL, + $this->t( + 'Cannot connect to message broker at @broker_url', + ['@broker_url' => $brokerUrl] + ) + ); + } + } + /** * {@inheritdoc} */ @@ -75,9 +99,8 @@ class IslandoraSettingsForm extends ConfigFormBase { $config ->set(self::BROKER_URL, $form_state->getValue(self::BROKER_URL)) - ->set(self::TRIPLESTORE_INDEX_QUEUE, $form_state->getValue(self::TRIPLESTORE_INDEX_QUEUE)) + ->set(self::BROADCAST_QUEUE, $form_state->getValue(self::BROADCAST_QUEUE)) ->set(self::FEDORA_REST_ENDPOINT, $form_state->getValue(self::FEDORA_REST_ENDPOINT)) - ->set(self::FEDORA_INDEXING_QUEUE, $form_state->getValue(self::FEDORA_INDEXING_QUEUE)) ->save(); parent::submitForm($form, $form_state); diff --git a/src/Plugin/RulesAction/Broadcaster.php b/src/Plugin/RulesAction/Broadcaster.php new file mode 100644 index 00000000..05140f29 --- /dev/null +++ b/src/Plugin/RulesAction/Broadcaster.php @@ -0,0 +1,125 @@ +broadcastQueue = $broadcast_queue; + $this->stomp = $stomp; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $config = $container->get('config.factory'); + $settings = $config->get(IslandoraSettingsForm::CONFIG_NAME); + $broadcastQueue = $settings->get(IslandoraSettingsForm::BROADCAST_QUEUE); + + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $broadcastQueue, + $container->get('islandora.stomp') + ); + } + + /** + * Sends a message to a broadcaster to get distributed. + * + * @param string $message + * Message body to send. + * @param array $recipients + * List of queues/topics to broadcast message to. + */ + protected function doExecute($message, array $recipients) { + // Transform recipients array into comma searated list. + $recipients = array_map('trim', $recipients); + $recipients = implode(',', $recipients); + + // Transform message from string into a proper message object. + $message = new Message($message, ['IslandoraBroadcastRecipients' => $recipients]); + + // Send the message. + try { + $this->stomp->begin(); + $this->stomp->send($this->broadcastQueue, $message); + $this->stomp->commit(); + } + catch (StompException $e) { + // Log it. + \Drupal::logger('islandora')->error( + 'Error publishing message: @msg', + ['@msg' => $e->getMessage()] + ); + + // Notify user. + drupal_set_message( + t('Error publishing message: @msg', + ['@msg' => $e->getMessage()] + ), + 'error' + ); + } + } + +} diff --git a/src/StompFactory.php b/src/StompFactory.php new file mode 100644 index 00000000..53c01a60 --- /dev/null +++ b/src/StompFactory.php @@ -0,0 +1,33 @@ +get(IslandoraSettingsForm::CONFIG_NAME); + $brokerUrl = $settings->get(IslandoraSettingsForm::BROKER_URL); + + $client = new Client($brokerUrl); + return new StatefulStomp($client); + } + +} diff --git a/tests/src/Kernel/BroadcasterTest.php b/tests/src/Kernel/BroadcasterTest.php new file mode 100644 index 00000000..81bfd330 --- /dev/null +++ b/tests/src/Kernel/BroadcasterTest.php @@ -0,0 +1,127 @@ +prophesize(StatefulStomp::CLASS); + $prophecy->begin()->willThrow(new StompException('STOMP EXCEPTION')); + $stomp = $prophecy->reveal(); + + $action = $this->createBroadcaster($stomp); + + try { + // Execute the action. + $action->execute(); + $this->assertTrue(TRUE, "The execute() method must squash StompExceptions."); + } + catch (\Exception $e) { + $this->assertTrue(FALSE, "The execute() method must squash StompExceptions."); + } + + } + + /** + * Tests that the action DOES NOT squash any other Exception. + * + * @covers \Drupal\islandora\Plugin\RulesAction\Broadcaster::execute + * @expectedException \Exception + */ + public function testExecuteDoesNotSquashOtherExceptions() { + // Set up a fake Stomp client to throw a non-StompException when used. + $prophecy = $this->prophesize(StatefulStomp::CLASS); + $prophecy->begin()->willThrow(new \Exception('NOT A STOMP EXCEPTION')); + $stomp = $prophecy->reveal(); + + $action = $this->createBroadcaster($stomp); + + // This should throw an exception. + $action->execute(); + } + + /** + * Tests that the action publishes the message to be broadcast to a broker. + * + * @covers \Drupal\islandora\Plugin\RulesAction\Broadcaster::execute + */ + public function testBrokerIntegration() { + // Grab a legit stomp client, using values from config. + $this->installConfig('islandora'); + $stomp = $this->container->get('islandora.stomp'); + + // Create and execute the action. + $action = $this->createBroadcaster($stomp); + $action->execute(); + + // Verify the message actually got sent. + try { + $stomp->subscribe($this->testQueue); + $msg = $stomp->read(); + + $this->assertTrue( + strcmp($msg->getBody(), 'test') == 0, + "Message body is not 'test'" + ); + + $headers = $msg->getHeaders(); + $this->assertTrue( + strcmp($headers['IslandoraBroadcastRecipients'], 'activemq:queue:foo,activemq:queue:bar') == 0, + "IslandoraBroadcastRecipients header must be a comma separated list of endpoints" + ); + $stomp->unsubscribe(); + } + catch (StompException $e) { + $this->assertTrue(FALSE, "There was an error connecting to the stomp broker"); + } + } + + /** + * Utility function to create a broadcaster action from a Stomp prophecy. + * + * @param StatefulStomp $stomp + * Stomp instance or prophecy. + * + * @return \Drupal\islandora\Plugin\RulesAction\Broadcaster + * Broadcaster, ready to test. + */ + protected function createBroadcaster(StatefulStomp $stomp) { + // Pull the plugin definition out of the plugin system. + $actionManager = $this->container->get('plugin.manager.rules_action'); + $definitions = $actionManager->getDefinitions(); + $pluginDefinition = $definitions['islandora_broadcast']; + + $action = new Broadcaster( + [], + 'islandora_broadcast', + $pluginDefinition, + $this->testQueue, + $stomp + ); + + // Set the required contexts for the action to run. + $action->setContextValue('message', "test"); + $action->setContextValue('recipients', ['activemq:queue:foo', 'activemq:queue:bar']); + + return $action; + } + +} diff --git a/tests/src/Kernel/EventGeneratorTestBase.php b/tests/src/Kernel/EventGeneratorTestBase.php index 36dd8c51..228437e3 100644 --- a/tests/src/Kernel/EventGeneratorTestBase.php +++ b/tests/src/Kernel/EventGeneratorTestBase.php @@ -10,9 +10,7 @@ use Drupal\simpletest\UserCreationTrait; */ abstract class EventGeneratorTestBase extends IslandoraKernelTestBase { - use UserCreationTrait { - createUser as drupalCreateUser; - } + use UserCreationTrait; /** * User entity. @@ -35,12 +33,12 @@ abstract class EventGeneratorTestBase extends IslandoraKernelTestBase { parent::setUp(); // Create a test user. - $this->user = $this->drupalCreateUser(); + $this->user = $this->createUser(['add fedora resource entities']); // Create a test entity. $this->entity = FedoraResource::create([ "type" => "rdf_source", - "uid" => 1, + "uid" => $this->user->get('uid'), "name" => "Test Fixture", "langcode" => "und", "status" => 1, diff --git a/tests/src/Kernel/IslandoraKernelTestBase.php b/tests/src/Kernel/IslandoraKernelTestBase.php index 1a8e1671..bff7d6d9 100644 --- a/tests/src/Kernel/IslandoraKernelTestBase.php +++ b/tests/src/Kernel/IslandoraKernelTestBase.php @@ -29,6 +29,7 @@ abstract class IslandoraKernelTestBase extends KernelTestBase { 'typed_data', 'rules', 'jsonld', + 'views', 'islandora', ]; diff --git a/tests/src/Kernel/VectorClockTest.php b/tests/src/Kernel/VectorClockTest.php index e5ae3340..26f06996 100644 --- a/tests/src/Kernel/VectorClockTest.php +++ b/tests/src/Kernel/VectorClockTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\islandora\Kernel; use Drupal\islandora\Entity\FedoraResource; +use Drupal\simpletest\UserCreationTrait; /** * Tests the basic behavior of a vector clock. @@ -12,6 +13,8 @@ use Drupal\islandora\Entity\FedoraResource; */ class VectorClockTest extends IslandoraKernelTestBase { + use UserCreationTrait; + /** * Fedora resource entity. * @@ -19,16 +22,26 @@ class VectorClockTest extends IslandoraKernelTestBase { */ protected $entity; + /** + * User entity. + * + * @var \Drupal\user\UserInterface + */ + protected $user; + /** * {@inheritdoc} */ public function setUp() { parent::setUp(); + // Create a test user. + $this->user = $this->createUser(['add fedora resource entities', 'edit fedora resource entities']); + // Create a test entity. $this->entity = FedoraResource::create([ "type" => "rdf_source", - "uid" => 1, + "uid" => $this->user->get('uid'), "name" => "Test Fixture", "langcode" => "und", "status" => 1,