link_orcid-1.0.0-rc1/src/OrcidClient.php

src/OrcidClient.php
<?php

declare(strict_types=1);

namespace Drupal\link_orcid;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\key\KeyRepositoryInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;

/**
 * ORCID API client.
 */
final class OrcidClient {

  public function __construct(
    private readonly ConfigFactoryInterface $configFactory,
    private readonly KeyRepositoryInterface $keyRepository,
    private readonly ClientInterface $httpClient,
    private readonly EntityTypeManagerInterface $entityTypeManager,
    private readonly AccountProxyInterface $currentUser,
  ) {}

  /**
   * The base URL for ORCID API.
   */
  private function baseUrl(): string {
    $sandbox = (bool) $this->config()->get('sandbox');
    return $sandbox ? 'https://sandbox.orcid.org' : 'https://orcid.org';
  }

  /**
   * The token URL for ORCID API.
   */
  private function tokenUrl(): string {
    return $this->baseUrl() . '/oauth/token';
  }

  /**
   * The authorize URL for ORCID API.
   */
  private function authorizeUrl(): string {
    return $this->baseUrl() . '/oauth/authorize';
  }

  /**
   * Module configuration.
   */
  private function config() {
    return $this->configFactory->get('link_orcid.settings');
  }

  /**
   * Get the URL to redirect user to ORCID authorize endpoint.
   */
  public function getAuthorizeRedirect(string $state, string $redirect_uri): string {
    $client_id = (string) $this->config()->get('client_id');
    $query = http_build_query([
      'client_id' => $client_id,
      'response_type' => 'code',
      'scope' => '/authenticate',
      'redirect_uri' => $redirect_uri,
      'state' => $state,
    ], '', '&', PHP_QUERY_RFC3986);
    return $this->authorizeUrl() . '?' . $query;
  }

  /**
   * Exchange the received code for an access token and ORCID iD.
   *
   * @return array{orcid:string}|null
   *   Array with 'orcid' key on success, NULL on failure.
   */
  public function exchangeCodeForToken(string $code, string $state, string $redirect_uri): ?array {
    $client_id = (string) $this->config()->get('client_id');
    $secret_key_id = (string) $this->config()->get('secret_key');
    $secret = $this->keyRepository->getKey($secret_key_id)?->getKeyValue();
    if (!$client_id || !$secret) {
      throw new \RuntimeException('ORCID client credentials are not configured.');
    }

    try {
      $response = $this->httpClient->request('POST', $this->tokenUrl(), [
        'form_params' => [
          'client_id' => $client_id,
          'client_secret' => $secret,
          'grant_type' => 'authorization_code',
          'code' => $code,
          'redirect_uri' => $redirect_uri,
        ],
        'headers' => [
          'Accept' => 'application/json',
        ],
      ]);

      $data = json_decode((string) $response->getBody(), TRUE) ?: [];
      if (!empty($data['orcid'])) {
        return ['orcid' => (string) $data['orcid']];
      }
      return NULL;
    }
    catch (GuzzleException $e) {
      throw new \RuntimeException('ORCID token exchange failed: ' . $e->getMessage(), 0, $e);
    }
  }

  /**
   * Save ORCID to current user selected field.
   */
  public function saveCurrentUserOrcid(string $orcid): void {
    $user = $this->entityTypeManager->getStorage('user')->load($this->currentUser->id());
    if (!$user) {
      throw new \RuntimeException('User not found.');
    }

    $field = (string) $this->config()->get('user_field');

    /** @var \Drupal\user\UserInterface $user */
    if (!$field || !$user->hasField($field)) {
      throw new \RuntimeException('Configured ORCID field not found on user entity.');
    }

    $user->set($field, $orcid);
    $user->save();
  }

}

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

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