Skip to content

Commit

Permalink
Integrated Context Reaction with Triplestore Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
HyphenHook committed Feb 29, 2024
1 parent 82a6a9d commit ea58f6c
Show file tree
Hide file tree
Showing 16 changed files with 756 additions and 82 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ This Drupal 8 or 9's module provide a system to get the Json-LD representation (
- **Method of operation**:
+ **[Drupal Entity Hooks](https://api.drupal.org/api/drupal/core%21core.api.php/group/hooks/9.0.x)**: By default this option selected, the indexing will be executed immediately after a node or a taxonomy term is [created](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_insert/9.0.x), [update](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_update/9.0.x), or [deleted](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_delete/9.0.x). (*WARNING: it may effect the performance of the site if many nodes/taxonomy terms are being ingested in bulk.*)
+ **[Advanced Queue](https://www.drupal.org/project/advancedqueue)**: Highly Recommended, when a node or a taxonomy term is created, updated, or deleted, the indexing operation will be added to a queue which can be configured to run with Cron job or Drupal Console commnad (eg. drupal advancedqueue:queue:process default). You can create a seperated queue if needed, then enter the new queue's machine name with default in the "Queue" text field below.
- **When to index**: During ONLY selected event(s), the indexing will be executed.
- **Content type**: For ONLY selected content type(s), the indexing will be executed.
- **Taxonomy**: For ONLY selected taxonomy term(s), the indexing will be executed.
# Enabling Indexing/Deleting
- To enable indexing/deleting of media, node, or taxonomy term, you must make use of the Context module
- Go to `Structure > Context`
- Create a Context and choose the Conditions that should be true for the indexing/deleting action to proceed
- Under `Reaction` add a Reaction and pick `Triplestore Index Reaction` or `Triplestore Delete Reaction`
- In the Action form that shows up for the Reaction, just pick the corresponding one that you would like
- Ensure the context is enabled and then save
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"require": {
"islandora/jsonld": "^3.0",
"drupal/advancedqueue": "^1.0@RC",
"drupal/restui": "^1.21"
"drupal/restui": "^1.21",
"drupal/context":"^5.0@RC"
},
"require-dev": {
"phpunit/phpunit": "^8",
Expand Down
6 changes: 0 additions & 6 deletions config/schema/triplestore_indexer.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,3 @@ triplestore_indexer.settings:
advancedqueue_id:
type: string
label: 'Advanced Queue ID'
content_type_to_index:
type: sequence
label: 'Content types to be indexed'
sequence:
type: string
label: 'Content type'
50 changes: 50 additions & 0 deletions src/ContextProvider/MediaContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Drupal\triplestore_indexer\ContextProvider;

use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\media\MediaInterface;

/**
* Sets the provided media as a context.
*/
class MediaContextProvider implements ContextProviderInterface {

use StringTranslationTrait;

/**
* Media to provide in a context.
*
* @var \Drupal\media\MediaInterface
*/
protected $media;

/**
* Constructs a new MediaRouteContext.
*
* @var \Drupal\media\MediaInterface $media
* The media to provide in a context.
*/
public function __construct(MediaInterface $media) {
$this->media = $media;
}

/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$context = EntityContext::fromEntity($this->media);
return ['@triplestore_indexer.media_route_context_provider:media' => $context];
}

/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = EntityContext::fromEntityType(\Drupal::entityTypeManager()->getDefinition('media'), $this->t('Media from URL'));
return ['@triplestore_indexer.media_route_context_provider:media' => $context];
}

}
76 changes: 76 additions & 0 deletions src/ContextProvider/MediaRouteContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Drupal\triplestore_indexer\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\media\Entity\Media;

/**
* Sets the current media as a context on media routes.
*/
class MediaRouteContextProvider implements ContextProviderInterface {

use StringTranslationTrait;

/**
* The route match object.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;

/**
* Constructs a new MediaRouteContextProvider.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object.
*/
public function __construct(RouteMatchInterface $route_match) {
$this->routeMatch = $route_match;
}

/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$context_definition = EntityContextDefinition::fromEntityTypeId('media')->setLabel(NULL)->setRequired(FALSE);
$value = NULL;

$route_object = $this->routeMatch->getRouteObject();
if ($route_object) {
$route_contexts = $route_object->getOption('parameters');
if ($route_contexts && isset($route_contexts['media'])) {
$media = $this->routeMatch->getParameter('media');
if ($media) {
$value = $media;
}
}
elseif ($this->routeMatch->getRouteName() == 'entity.media.add_form') {
$media_type = $this->routeMatch->getParameter('media_type');
$value = Media::create(['bundle' => $media_type->id()]);
}
}

$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['route']);

$context = new Context($context_definition, $value);
$context->addCacheableDependency($cacheability);
return ['media' => $context];
}

/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = EntityContext::fromEntityType(\Drupal::entityTypeManager()->getDefinition('media'), $this->t('Media from URL'));
return ['media' => $context];
}

}
50 changes: 50 additions & 0 deletions src/ContextProvider/NodeContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Drupal\triplestore_indexer\ContextProvider;

use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

/**
* Sets the provided media as a context.
*/
class NodeContextProvider implements ContextProviderInterface {

use StringTranslationTrait;

/**
* Node to provide in a context.
*
* @var \Drupal\node\NodeInterface
*/
protected $node;

/**
* Constructs a new NodeContextProvider.
*
* @var \Drupal\node\NodeInterface $node
* The node to provide in a context.
*/
public function __construct(NodeInterface $node) {
$this->node = $node;
}

/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$context = EntityContext::fromEntity($this->node);
return ['@node.node_route_context:node' => $context];
}

/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = EntityContext::fromEntityTypeId('node', $this->t('Node from entity hook'));
return ['@node.node_route_context:node' => $context];
}

}
50 changes: 50 additions & 0 deletions src/ContextProvider/TermContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Drupal\triplestore_indexer\ContextProvider;

use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\taxonomy\TermInterface;

/**
* Sets the provided media as a context.
*/
class TermContextProvider implements ContextProviderInterface {

use StringTranslationTrait;

/**
* Term to provide in a context.
*
* @var \Drupal\term\TermInterface
*/
protected $term;

/**
* Constructs a new TermContextProvider.
*
* @var \Drupal\term\TermInterface $term
* The term to provide in a context.
*/
public function __construct(TermInterface $term) {
$this->term = $term;
}

/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$context = EntityContext::fromEntity($this->term);
return ['@triplestore_indexer.taxonomy_term_route_context_provider:taxonomy_term' => $context];
}

/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = EntityContext::fromEntityTypeId('taxonomy_term', $this->t('Term from entity hook'));
return ['@triplestore_indexer.taxonomy_term_route_context_provider:taxonomy_term' => $context];
}

}
71 changes: 71 additions & 0 deletions src/ContextProvider/TermRouteContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Drupal\triplestore_indexer\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
* Sets the current file as a context on file routes.
*/
class TermRouteContextProvider implements ContextProviderInterface {

use StringTranslationTrait;

/**
* The route match object.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;

/**
* Constructs a new TermRouteContextProvider.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object.
*/
public function __construct(RouteMatchInterface $route_match) {
$this->routeMatch = $route_match;
}

/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$context_definition = EntityContextDefinition::fromEntityTypeId('taxonomy_term')->setLabel(NULL)->setRequired(FALSE);
$value = NULL;

$route_object = $this->routeMatch->getRouteObject();
if ($route_object) {
$route_contexts = $route_object->getOption('parameters');
if ($route_contexts && isset($route_contexts['taxonomy_term'])) {
$term = $this->routeMatch->getParameter('taxonomy_term');
if ($term) {
$value = $term;
}
}
}

$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['route']);

$context = new Context($context_definition, $value);
$context->addCacheableDependency($cacheability);
return ['taxonomy_term' => $context];
}

/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = EntityContext::fromEntityTypeId('taxonomy_term', $this->t('Term from URL'));
return ['taxonomy_term' => $context];
}

}
24 changes: 0 additions & 24 deletions src/Form/TripleStoreIndexerConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,29 +179,6 @@ public function buildForm(array $form, FormStateInterface $form_state) {
];
$form['configuration']['#tree'] = TRUE;

$form['content-type'] = [
'#type' => 'details',
'#title' => $this
->t('Condition: Node Bundle'),
'#group' => 'configuration',
];

// Pull list of exsiting content types of the site.
$content_types = \Drupal::entityTypeManager()
->getStorage('node_type')
->loadMultiple();
$options_contentypes = [];
foreach ($content_types as $ct) {
$options_contentypes[$ct->id()] = $ct->label();
}

$form['content-type']['select-content-types'] = [
'#type' => 'checkboxes',
'#title' => t('Select which content type(s) to be indexed:'),
'#options' => $options_contentypes,
'#default_value' => ($config->get("content_type_to_index") !== NULL) ? array_keys(array_filter($config->get('content_type_to_index'))) : [],
];

$form['submit-save-config'] = [
'#type' => 'submit',
'#name' => "submit-save-server-config",
Expand Down Expand Up @@ -290,7 +267,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
}

$configFactory->set('advancedqueue_id', $form_state->getValues()['advancedqueue_id']);
$configFactory->set('content_type_to_index', $form_state->getValues()['select-content-types']);
$configFactory->save();

parent::submitForm($form, $form_state);
Expand Down
Loading

0 comments on commit ea58f6c

Please sign in to comment.