rdf_sync-1.x-dev/src/Plugin/rdf_sync/Connector/Virtuoso.php

src/Plugin/rdf_sync/Connector/Virtuoso.php
<?php

declare(strict_types=1);

namespace Drupal\rdf_sync\Plugin\rdf_sync\Connector;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\rdf_sync\Attribute\RdfSyncConnector;
use Drupal\rdf_sync\Model\VirtuosoEndpoint;
use Drupal\rdf_sync\RdfSyncConnectorPluginPluginBase;
use EasyRdf\GraphStore;
use EasyRdf\Http\Exception as EasyRdfException;
use EasyRdf\Sparql\Client;
use EasyRdf\Sparql\Result;

/**
 * Defines the Virtuoso connector plugin.
 */
#[RdfSyncConnector(
  id: 'virtuoso',
  label: new TranslatableMarkup('Virtuoso'),
  description: new TranslatableMarkup('Virtuoso OpenSource'),
  website: 'https://github.com/openlink/virtuoso-opensource',
)]
class Virtuoso extends RdfSyncConnectorPluginPluginBase implements PluginFormInterface {

  /**
   * The EasyRdf client.
   */
  protected Client $client;

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration(): array {
    return [
      'endpoint' => VirtuosoEndpoint::Basic->value,
      'scheme' => 'http',
      'host' => 'localhost',
      'port' => 8890,
      'paths' => [
        'query' => 'sparql',
        'update' => 'sparql',
        'graph_store' => 'sparql-graph-crud',
      ],
      'credentials' => [
        'user' => NULL,
        'password' => NULL,
      ],
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function query(string $query): Result {
    return $this->performOperation($query, 'query');
  }

  /**
   * {@inheritdoc}
   */
  public function update(string $query): Result {
    return $this->performOperation($query, 'update');
  }

  /**
   * {@inheritdoc}
   */
  public function clearGraph(string $uri): void {
    $this->update("CLEAR GRAPH <$uri>");
  }

  /**
   * {@inheritdoc}
   */
  public function createGraphStore(): GraphStore {
    $connectionString = $this->getEndpointUrl('graph_store');
    return new GraphStore($connectionString);
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    $form['endpoint'] = [
      '#type' => 'radios',
      '#title' => $this->t('SPARQL endpoint type'),
      '#description' => $this->t('See <a href=":url">Securing SPARQL endpoints</a>. Digest authentication and OAuth are not supported yet.', [
        ':url' => 'https://vos.openlinksw.com/owiki/wiki/VOS/VirtTipsAndTricksGuideSPARQLEndpoints',
      ]),
      '#options' => VirtuosoEndpoint::casesAsOptions(),
      '#config_target' => "rdf_sync.settings:connector.config.endpoint",
    ];

    // Not implemented yet.
    $form['endpoint'][VirtuosoEndpoint::Digest->value]['#disabled'] = TRUE;
    $form['endpoint'][VirtuosoEndpoint::OAuth->value]['#disabled'] = TRUE;

    $form['scheme'] = [
      '#type' => 'select',
      '#title' => $this->t('HTTP protocol'),
      '#options' => [
        'http' => $this->t('http'),
        'https' => $this->t('https'),
      ],
      '#config_target' => "rdf_sync.settings:connector.config.scheme",
    ];

    $form['host'] = [
      '#type' => 'textfield',
      '#title' => $this->t('RDF host'),
      '#required' => TRUE,
      '#config_target' => 'rdf_sync.settings:connector.config.host',
    ];

    $form['port'] = [
      '#type' => 'number',
      '#title' => $this->t('RDF port'),
      '#required' => TRUE,
      '#min' => 1,
      '#config_target' => 'rdf_sync.settings:connector.config.port',
    ];

    $form['paths'] = [
      '#type' => 'details',
      '#title' => $this->t('Paths'),
      '#open' => TRUE,
    ];

    $form['paths']['query'] = [
      '#type' => 'textfield',
      '#title' => $this->t('SPARQL query path'),
      '#required' => TRUE,
      '#config_target' => 'rdf_sync.settings:connector.config.paths.query',
    ];

    $form['paths']['update'] = [
      '#type' => 'textfield',
      '#title' => $this->t('SPARQL update path'),
      '#required' => TRUE,
      '#config_target' => 'rdf_sync.settings:connector.config.paths.update',
    ];

    $form['paths']['graph_store'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Graph store path'),
      '#required' => TRUE,
      '#config_target' => 'rdf_sync.settings:connector.config.paths.graph_store',
    ];

    $condition = [
      ':input[name="config[endpoint]"]' => [
        'value' => VirtuosoEndpoint::Basic->value,
      ],
    ];
    $states = ['invisible' => $condition, 'optional' => $condition];

    $form['credentials'] = [
      '#type' => 'details',
      '#title' => $this->t('Credentials'),
      '#open' => TRUE,
      '#states' => $states,
    ];
    $form['credentials']['user'] = [
      '#type' => 'textfield',
      '#title' => $this->t('User'),
      '#config_target' => 'rdf_sync.settings:connector.config.credentials.user',
      '#states' => $states,
    ];

    $form['credentials']['password'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Password'),
      '#config_target' => 'rdf_sync.settings:connector.config.credentials.password',
      '#states' => $states,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $needCredentials = [VirtuosoEndpoint::Digest, VirtuosoEndpoint::OAuth];
    $endpointType = VirtuosoEndpoint::from($form_state->getValue('endpoint'));
    if (in_array($endpointType, $needCredentials, TRUE)) {
      $user = trim($form_state->getValue(['credentials', 'user']));
      $password = $form_state->getValue(['credentials', 'password']);
      if (!$user) {
        $form_state->setErrorByName('credentials][user', $this->t('The user name is mandatory'));
      }
      // User might have been trimmed.
      $form_state->setValue(['credentials', 'user'], $user);

      if (!$password) {
        $form_state->setErrorByName('credentials][password', $this->t('The password is mandatory'));
      }
    }
    else {
      $form_state->unsetValue(['credentials', 'user']);
      $form_state->unsetValue(['credentials', 'password']);
    }
  }

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

  /**
   * Provides a helper to run a query or an update.
   *
   * @param string $query
   *   The SPARQL query.
   * @param string $method
   *   The method: 'query' or 'update'.
   *
   * @return \EasyRdf\Sparql\Result
   *   The result object.
   */
  protected function performOperation(string $query, string $method): Result {
    assert(in_array($method, ['query', 'update'], TRUE));

    try {
      return $this->getClient()->$method($query);
    }
    catch (EasyRdfException $exception) {
      // Re-throw the exception, but with the query as message.
      throw new \Exception("Execution of $method failed with message '{$exception->getBody()}'. Query: " . $query, $exception->getCode(), $exception);
    }
    catch (\Throwable $exception) {
      throw new \Exception("Execution of $method failed with message '{$exception->getMessage()}'. Query: " . $query, $exception->getCode(), $exception);
    }
  }

  /**
   * Returns the Easy RDF SPARQL client.
   *
   * @return \EasyRdf\Sparql\Client
   *   The Easy RDF SPARQL client.
   */
  protected function getClient(): Client {
    if (!isset($this->client)) {
      $this->client = new Client($this->getEndpointUrl('query'), $this->getEndpointUrl('update'));
    }
    return $this->client;
  }

  /**
   * {@inheritdoc}
   */
  public function getEndpointUrl(string $type): string {
    assert(in_array($type, ['query', 'update', 'graph_store'], TRUE));

    $config = $this->getConfiguration();
    $path = trim($config['paths'][$type], '/');
    $endpoint = VirtuosoEndpoint::from($config['endpoint']);

    return match($endpoint) {
      VirtuosoEndpoint::Basic => "{$config['scheme']}://{$config['host']}:{$config['port']}/$path",
      default => throw new \InvalidArgumentException("The '$endpoint->value' endpoint type is not supported yet"),
    };
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc