Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrated Context Reaction with Triplestore Actions #12

Merged
merged 8 commits into from
Sep 9, 2024
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
18 changes: 18 additions & 0 deletions config/install/context.context.index_content_blazegraph.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
module:
- triplestore_indexer
label: Content
name: index_content_blazegraph
group: Indexing
description: 'Index all content to Blazegraph.'
requireAllConditions: false
disabled: false
conditions: { }
reactions:
triplestore_index_reaction:
id: triplestore_index_reaction
actions: index_node_to_triplestore_advancedqueue
saved: false
weight: 0
18 changes: 18 additions & 0 deletions config/install/context.context.index_media_blazegraph.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
module:
- triplestore_indexer
label: Media
name: index_media_blazegraph
group: Indexing
description: 'Index all media bundles Blazegraph'
requireAllConditions: false
disabled: false
conditions: { }
reactions:
triplestore_index_reaction:
id: triplestore_index_reaction
actions: index_media_to_triplestore_advancedqueue
saved: false
weight: 0
18 changes: 18 additions & 0 deletions config/install/context.context.index_taxonomy_terms_blazegraph.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
module:
- triplestore_indexer
label: 'Taxonomy Terms'
name: index_taxonomy_terms_blazegraph
group: Indexing
description: 'Index taxonomy terms to Blazegraph.'
requireAllConditions: false
disabled: false
conditions: { }
reactions:
triplestore_index_reaction:
id: triplestore_index_reaction
actions: index_taxonomy_term_to_triplestore_advancedqueue
saved: false
weight: 0
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];
}

}
Loading
Loading