Skip to content

Commit

Permalink
Merge pull request #1884 from danskernesdigitalebibliotek/bnf-import-ui
Browse files Browse the repository at this point in the history
BNF: Library import forms. DDFHER-166
  • Loading branch information
rasben authored Jan 2, 2025
2 parents c2be9ec + 850df4b commit 3901d76
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ x-environment:
WEBROOT: web
GRAPHQL_USER_NAME: graphql_consumer
GRAPHQL_USER_PASSWORD: test
BNF_SERVER_GRAPHQL_ENDPOINT: "https://dpl-cms.local/graphql"
BNF_SERVER_BASE_ENDPOINT: "https://dpl-cms.local"
# Uncomment if you like to have the system behave like in production
#LAGOON_ENVIRONMENT_TYPE: production

Expand Down
26 changes: 26 additions & 0 deletions web/modules/custom/bnf/bnf.module
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Drupal\bnf\BnfStateEnum;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\node\NodeInterface;

/**
* Implements hook_entity_base_field_info().
Expand Down Expand Up @@ -41,3 +42,28 @@ function bnf_get_bnf_state_allowed_values(): array {
}
return $values;
}

/**
* Implements theme_preprocess_html().
*
* Adding the node UUID as a metatag, that we can use when the user submits
* a URL to the BNF import form.
*/
function bnf_preprocess_html(array &$variables): void {
$route = \Drupal::routeMatch();
$node = $route->getParameter('node');

if ($route->getRouteName() !== 'entity.node.canonical' || !($node instanceof NodeInterface)) {
return;
}

$uuid_metatag = [
'#tag' => 'meta',
'#attributes' => [
'name' => 'uuid',
'content' => $node->uuid(),
],
];

$variables['page']['#attached']['html_head'][] = [$uuid_metatag, 'node-uuid'];
}
6 changes: 6 additions & 0 deletions web/modules/custom/bnf/bnf_client/bnf_client.links.menu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
bnf_client.import_content:
title: 'Import BNF content'
parent: system.admin_content
route_name: bnf_client.import_form
weight: 10
4 changes: 2 additions & 2 deletions web/modules/custom/bnf/bnf_client/bnf_client.module
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use Drupal\drupal_typed\DrupalTyped;
/**
* Implements hook_form_FORM_ID_alter().
*
* Altering the node form, and adding an option to export the node to BNF.
* Altering the article form, and adding an option to export the node to BNF.
* If checked, a custom form submit handler will take care of the rest.
*
* @see bnf_client_form_node_form_submit()
*/
function bnf_client_form_node_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
function bnf_client_form_node_article_edit_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
$current_user = \Drupal::currentUser();

if (!$current_user->hasPermission('bnf client export nodes')) {
Expand Down
2 changes: 2 additions & 0 deletions web/modules/custom/bnf/bnf_client/bnf_client.permissions.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
bnf client export nodes:
title: 'Can export nodes to BNF'
bnf client import nodes:
title: 'Can import nodes from BNF'
16 changes: 16 additions & 0 deletions web/modules/custom/bnf/bnf_client/bnf_client.routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
bnf_client.import_form:
path: '/admin/bnf/import'
defaults:
_form: '\Drupal\bnf_client\Form\BnfImportForm'
_title: 'Import'
requirements:
_permission: 'bnf client import nodes'

bnf_client.import_confirm_form:
path: '/admin/bnf/import/{uuid}'
defaults:
_form: '\Drupal\bnf_client\Form\BnfImportConfirmForm'
_title: 'Confirm import'
requirements:
_permission: 'bnf client import nodes'
134 changes: 134 additions & 0 deletions web/modules/custom/bnf/bnf_client/src/Form/BnfImportConfirmForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php

namespace Drupal\bnf_client\Form;

use Drupal\bnf\Exception\AlreadyExistsException;
use Drupal\bnf\Services\BnfImporter;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Displaying an import preview, and allowing editor to import.
*/
class BnfImportConfirmForm implements FormInterface, ContainerInjectionInterface {
use StringTranslationTrait;

use AutowireTrait;

/**
* {@inheritDoc}
*/
public function __construct(
protected RouteMatchInterface $routeMatch,
protected MessengerInterface $messenger,
protected BnfImporter $bnfImporter,
protected LoggerInterface $logger,
) {}

/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container): static {
return new static(
$container->get('current_route_match'),
$container->get('messenger'),
$container->get('bnf.importer'),
$container->get('logger.channel.bnf'),
);
}

/**
* {@inheritDoc}
*/
public function getFormId(): string {
return 'bnf_import_form_form';
}

/**
* {@inheritDoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$form['#title'] = $this->t('Confirm import of BNF content', [], ['context' => 'BNF']);

$uuid = $this->routeMatch->getParameter('uuid');
$bnfServer = (string) getenv('BNF_SERVER_BASE_ENDPOINT') . '/graphql';

$form_state->set('uuid', $uuid);
$form_state->set('bnfServer', $bnfServer);

$importable = TRUE;

try {
$nodeData = $this->bnfImporter->loadNodeData($uuid, $bnfServer);
}
catch (\Exception $e) {
$importable = FALSE;

$this->messenger->addError($this->t('Cannot import this node from BNF.', [], ['context' => 'BNF']));

if ($e instanceof AlreadyExistsException) {
$this->messenger->addError($this->t('Node has previously been imported from BNF.', [], ['context' => 'BNF']));
}
}

$form['uuid'] = [
'#title' => 'UUID',
'#type' => 'textfield',
'#default_value' => $uuid,
'#disabled' => TRUE,
];

$form['label'] = [
'#title' => $this->t('Content label', [], ['context' => 'BNF']),
'#type' => 'textfield',
'#default_value' => $nodeData['title'] ?? NULL,
'#disabled' => TRUE,
];

$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Import content'),
'#disabled' => !$importable,
];

return $form;
}

/**
* {@inheritDoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {

}

/**
* {@inheritDoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$uuid = $form_state->get('uuid');
$bnfServer = $form_state->get('bnfServer');

try {
$node = $this->bnfImporter->importNode($uuid, $bnfServer);
$form_state->setRedirect('entity.node.edit_form', ['node' => $node->id()]);
}
catch (\Exception $e) {
$this->logger->error('Could not import node from BNF. @message', ['@message' => $e->getMessage()]);

$this->messenger->addError($this->t('Could not import node from BNF.', [], ['context' => 'BNF']));

if ($e instanceof AlreadyExistsException) {
$this->messenger->addError($this->t('Node has previously been imported from BNF.', [], ['context' => 'BNF']));
}
}

}

}
94 changes: 94 additions & 0 deletions web/modules/custom/bnf/bnf_client/src/Form/BnfImportForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Drupal\bnf_client\Form;

use Drupal\Component\Uuid\Uuid;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use function Safe\get_meta_tags;

/**
* An import form, letting editors input URL or UUID from BNF.
*/
class BnfImportForm implements FormInterface, ContainerInjectionInterface {
use StringTranslationTrait;

use AutowireTrait;

/**
* {@inheritDoc}
*/
public function getFormId(): string {
return 'bnf_initial_form';
}

/**
* {@inheritDoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$form['#title'] = $this->t('Import nodes from BNF', [], ['context' => 'BNF']);
$form['reference'] = [
'#type' => 'textfield',
'#title' => $this->t('URL or UUID of content'),
];

$form['actions'] = [
'#type' => 'actions',
];

$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Preview content'),
];

return $form;
}

/**
* {@inheritDoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
$reference = $form_state->getValue('reference');
$uuid = $this->parseAndValidateUuid($reference);

if (empty($uuid)) {
$form_state->setErrorByName(
'reference',
$this->t('Invalid URL or UUID.', [], ['context' => 'BNF'])
);
}

$form_state->set('uuid', $uuid);
}

/**
* {@inheritDoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$uuid = $form_state->get('uuid');
$form_state->setRedirect('bnf_client.import_confirm_form', ['uuid' => $uuid]);
}

/**
* Getting and validate a UUID from string or URL.
*/
protected function parseAndValidateUuid(string $reference): string|false {
try {
// Detect if reference is a URL.
if (filter_var($reference, FILTER_VALIDATE_URL)) {
// Finding the metatag that contains the UUID.
$meta_tags = get_meta_tags($reference);
$reference = $meta_tags['uuid'] ?? NULL;
}

return Uuid::isValid((string) $reference) ? $reference : FALSE;
}
catch (\Exception) {
return FALSE;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function exportNode(NodeInterface $node): void {
GRAPHQL;

try {
$bnfServer = (string) getenv('BNF_SERVER_GRAPHQL_ENDPOINT');
$bnfServer = (string) getenv('BNF_SERVER_BASE_ENDPOINT') . '/graphql';

if (!filter_var($bnfServer, FILTER_VALIDATE_URL)) {
throw new \InvalidArgumentException('The provided BNF server URL is not valid.');
Expand Down

0 comments on commit 3901d76

Please sign in to comment.