moodle_rest-1.0.1/src/Services/MoodleRest.php

src/Services/MoodleRest.php
<?php

namespace Drupal\moodle_rest\Services;

use GuzzleHttp\ClientInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use GuzzleHttp\Exception\TransferException;

/**
 * MoodleRest basic communication with Guzzle.
 */
class MoodleRest {

  /**
   * The HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The Base URL of the Moodle site.
   *
   * @var string
   */
  protected $baseUrl;

  /**
   * The token for the Rest Webservice.
   *
   * @var string
   */
  protected $token;

  /**
   * Constructs a MoodleRest object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \GuzzleHttp\ClientInterface $http_client
   *   The HTTP client.
   */
  public function __construct(ConfigFactoryInterface $config_factory, ClientInterface $http_client) {
    $this->configFactory = $config_factory;
    $this->httpClient = $http_client;
  }

  /**
   * Set Moodle Site Base URL.
   *
   * The default URL is set in configuration.
   */
  public function setBaseUrl(string $url) {
    $this->baseUrl = $url;
  }

  /**
   * Sets token for Moodle Webservice.
   *
   * The default token is set in the cofiguration.
   */
  public function setToken(string $token) {
    $this->token = $token;
  }

  /**
   * Get Moodle Site Base URL.
   */
  public function getBaseUrl() {
    if (empty($this->baseUrl)) {
      $config = $this->configFactory->get('moodle_rest.settings');
      $this->baseUrl = $config->get('url');
    }

    return $this->baseUrl;
  }

  /**
   * Get Moodle Webservice token.
   */
  public function getToken() {
    if (empty($this->token)) {
      $config = $this->configFactory->get('moodle_rest.settings');
      $this->token = $config->get('wstoken');
    }

    return $this->token;
  }

  /**
   * Call a Moodle WS API function.
   *
   * @param string $name
   *   API function name.
   *   https://docs.moodle.org/dev/Web_service_API_functions
   * @param array $params
   *   Parameters for the function.
   *
   * @return mixed
   *   NULL, string or array as defined by the Webservice Function.
   *
   * @throws \Drupal\moodle_rest\Services\MoodleRestException
   */
  public function requestFunction($name, array $params = []) {
    $host = $this->getBaseUrl();
    $wstoken = $this->getToken();
    if (empty($host) || empty($wstoken)) {
      throw new MoodleRestException('Moodle host or wstoken not configured.', 1);
    }

    $options = [];
    $options['query']['wsfunction'] = $name;

    try {
      // Moodle merges $_GET and $_POST. So we can safely put all $params into a
      // POST so it will work no matter length.
      if (empty($params)) {
        $response = $this->request($options);
      }
      else {
        $options['form_params'] = $params;
        $response = $this->request($options, 'POST');
      }
    }
    catch (TransferException $e) {
      // Chances are it'll be 500. But really this can be any
      // https://docs.guzzlephp.org/en/stable/quickstart.html#exceptions
      throw new MoodleRestException('Guzzle Exception', 500, $e);
    }

    // Moodle will also reply with HTTP 200. Examples:
    // @code
    // {
    //   "exception":"invalid_parameter_exception",
    //   "errorcode":"invalidparameter",
    //   "message":"Invalid parameter value detected"
    // }
    // @endcode
    // @code
    // {
    //   "exception":"webservice_access_exception",
    //   "errorcode":"accessexception",
    //   "message":"Access control exception"
    // }
    // @endcode
    $content = json_decode($response->getBody(), TRUE);
    if (isset($content['exception'])) {
      if ($content['errorcode'] == 'accessexception') {
        throw new MoodleRestException('Moodle access exception', 403, NULL, $content);
      }
      else {
        throw new MoodleRestException($content['message'], 400, NULL, $content);
      }
    }

    return $content;
  }

  /**
   * Basic request to Moodle WS.
   *
   * Wrapper around Guzzle. Accepts the same options. Will add the wstoken if
   * not present, will call the configured host url WS endpoint. Handles missing
   * configuration. For use if more complicated direct guzzle interaction is
   * needed that can't be achieved with the user, course service classes, or
   * even self::requestFunction().
   *
   * @param array $options
   *   Requires at least the Moodle 'wsfunction' to be set.
   *   Format and Token do not need to be set as they are added if not in the
   *   query.
   *   \GuzzleHttp\ClientInterface::request()
   * @param string $type
   *   Optional request type.
   *
   * @return \GuzzleHttp\Psr7\Response
   *   Guzzle response object.
   *
   * @throws \Drupal\moodle_rest\Services\MoodleRestException
   * @throws \GuzzleHttp\Exception\TransferException
   */
  public function request(array $options, $type = 'GET') {
    $host = $this->getBaseUrl();
    $wstoken = $this->getToken();
    if (empty($host) || empty($wstoken)) {
      throw new MoodleRestException('Host or Token not configured', 1, NULL);
    }
    if (empty($options['query']['wsfunction']) && empty($options['form_params']['wsfunction'])) {
      throw new MoodleRestException('No WS Function specified', 404, NULL);
    }
    $options['query'] = $options['query'] ?? [];
    $options['query'] += ['moodlewsrestformat' => 'json'];
    $options['query'] += ['wstoken' => $wstoken];

    $response = $this->httpClient->request($type, $host . '/webservice/rest/server.php', $options);
    return $response;
  }

  /**
   * Request a file.
   *
   * The file webservice isn't a direct part of the Moodle REST service, but
   * logs the user in with the service token, admittedly with a different option
   * key.
   *
   * @param string $url
   *   The path, or full url (host and webservice/pluginfile.php), for the file
   *   to retrieve.
   * @param string $preview
   *   Optional Use preview in order to display the preview of the file
   *   (e.g. "thumb" for a thumbnail).
   * @param bool $offline
   *   Optional means download the file from the repository and serve it, even
   *   if it was an external link. The repository may have to export the file
   *   to an offline format.
   *
   * @return \GuzzleHttp\Psr7\Response
   *   Guzzle response object.
   *
   * @throws \Drupal\moodle_rest\Services\MoodleRestException
   * @throws \GuzzleHttp\Exception\TransferException
   */
  public function requestFile($url, $preview = '', $offline = NULL) {
    $host = $this->getBaseUrl();
    $wstoken = $this->getToken();
    if (empty($host) || empty($wstoken)) {
      throw new MoodleRestException('Host or Token not configured', 1, NULL);
    }

    // URL is often given with the full path, if it has just passthrough, if
    // not add it. Maintain our schema for contacting service.
    $url_parts = parse_url($url);
    $host_parts = parse_url($host);
    if ($url_parts['host'] != $host_parts['host'] ||
      strpos($url_parts['path'], '/webservice/pluginfile.php') !== 0) {
      if (substr($url, 0, 1) != '/') {
        $url = '/' . $url;
      }
      $url = $host . '/webservice/pluginfile.php' . $url;
    }

    $options['query'] = ['token' => $wstoken];
    if ($preview != '') {
      $options['query']['preview'] = $preview;
    }
    if (!is_null($offline)) {
      $options['query']['offline'] = $offline;
    }

    $response = $this->httpClient->request('GET', $url, $options);
    return $response;
  }

}

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

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