yandexdisk-8.x-1.x-dev/src/YandexDiskApiWebdav.php

src/YandexDiskApiWebdav.php
<?php

namespace Drupal\yandexdisk;

use Drupal\Component\Utility\UrlHelper;

/**
 * Yandex.Disk API WebDAV class.
 *
 * Here are only methods described in API docs. You probably want to use
 * YandexDiskApiWebdavHelper for extended functionality.
 *
 * @link http://api.yandex.com/disk/doc/dg/concepts/about.xml
 */
class YandexDiskApiWebdav {

  /**
   * Base path of a URI of the service api callback.
   */
  const SCHEMA_HOST = 'https://webdav.yandex.com';

  /**
   * Indicates that overwriting is allowed in copy/move methods.
   */
  const OVERWRITE_ALLOW = 'T';

  /**
   * Indicates that overwriting is not allowed in copy/move methods.
   */
  const OVERWRITE_DENY = 'F';

  /**
   * Disk path to work with.
   *
   * The $path must start with a slash.
   *
   * @var string
   */
  protected $path = '/';

  /**
   * Optional query parameters of the path to use with certain requests.
   *
   * @var array
   */
  protected $pathQuery;

  /**
   * Request method.
   *
   * @var string
   */
  protected $method;

  /**
   * Options that will be used in http request.
   *
   * @var array
   */
  protected $options;

  /**
   * Authorization header value.
   *
   * @var string
   */
  protected $authHeader;

  /**
   * Static field containing a result of last http request.
   *
   * @var \Psr\Http\Message\ResponseInterface
   */
  public static $lastResponse;

  /**
   * Class constructor.
   *
   * @param string $auth_string
   *   Authentication type and token in string of form 'Type token'. For
   *   example: 'Basic abcdefghijklmnopqrstuvwxyz123456' or 'OAuth ...'.
   */
  public function __construct($auth_string) {
    $this->authHeader = $auth_string;
    $this->resetOptions();
  }

  /**
   * Resets options to initial state after request execution.
   */
  protected function resetOptions() {
    $this->options = [
      'timeout' => PHP_INT_MAX,
      'headers' => [
        'Accept' => '*/*',
        'Authorization' => $this->authHeader,
      ],
      'exceptions' => FALSE,
    ];
    $this->pathQuery = [];
  }

  /**
   * Sets the query parameters for the path.
   *
   * @param array $query
   *   The query parameter array to be set, e.g., $_GET.
   */
  public function setPathQuery(array $query) {
    $this->pathQuery = $query;
  }

  /**
   * Downloads a file.
   *
   * The start_byte and end_byte can be used for requesting a particular section
   * of the file. The response to this type of request contains the header
   * Content-Type: multipart/byteranges.
   *
   * @param string $path
   *   Path to the file.
   * @param int $start_byte
   *   (optional) An offset from the start of the file to get a file part.
   * @param int $end_byte
   *   (optional) An end byte is included in a file part that will be returned.
   *
   * @return $this
   *   Same object.
   */
  public function get($path, $start_byte = NULL, $end_byte = NULL) {
    $this->method = 'GET';
    $this->path = $path;

    if (isset($start_byte)) {
      $range = 'bytes=' . $start_byte;
      if (isset($end_byte)) {
        $range .= '-' . $end_byte;
      }

      $this->options['headers']['Range'] = $range;
    }

    return $this;
  }

  /**
   * Uploads a file.
   *
   * At the beginning and end of uploading the file, the service checks whether
   * the file exceeds the space available to the user on Disk. If there is not
   * enough space, the service returns a response with the code 507 Insufficient
   * Storage.
   * Support is provided for transferring compressed files (Content-Encoding:
   * gzip header) and chunked files (Transfer-Encoding: chunked).
   *
   * @param string $path
   *   Path to the file.
   * @param string $data
   *   Data to be saved to the file.
   * @param string $content_type
   *   (optional) Data type.
   *
   * @return $this
   *   Same object.
   */
  public function put($path, $data, $content_type = 'application/binary') {
    $this->method = 'PUT';
    $this->path = $path;

    $this->options['headers']['Content-Type'] = $content_type;

    if ($data !== '') {
      // Check for duplicate files.
      $this->options['headers']['Etag'] = md5($data);
      $this->options['headers']['Sha256'] = strtoupper(hash('sha256', $data));
      $this->options['headers']['Expect'] = '100-continue';

      // Compress data.
      if (extension_loaded('zlib') && strpos($content_type, 'text/') === 0) {
        $data_compressed = gzencode($data, 9, FORCE_GZIP);

        // Check if compressing worked.
        if (strlen($data_compressed) < strlen($data)) {
          $data = $data_compressed;
          $this->options['headers']['Content-Encoding'] = 'gzip';
        }
      }
    }

    $this->options['body'] = $data;

    return $this;
  }

  /**
   * Creates a directory.
   *
   * According to the protocol, only one directory can be created as the result
   * of a single request. If the application sends a request to create the
   * /a/b/c/ directory, but the /a/ directory does not contain a /b/ directory,
   * the service will not create the /b/ directory, and will respond with the
   * code 409 Conflict.
   *
   * @param string $path
   *   Path to the directory to create.
   *
   * @return $this
   *   Same object.
   */
  public function mkcol($path) {
    $this->method = 'MKCOL';
    $this->path = $path;

    return $this;
  }

  /**
   * Copies a file/directory.
   *
   * If parent directory where the file/directory should be copied to does not
   * exist, the service will respond with the code 409 Conflict.
   * If overwriting is not allowed and target exists, the service will respond
   * with the code 412 Precondition Failed.
   *
   * @param string $source
   *   Path to the file/directory to copy.
   * @param string $destination
   *   Path where the copy should be created.
   * @param string $overwrite
   *   (optional) Constant indicating whether overwriting is allowed or denied
   *   if target already exists. Default is to allow.
   *
   * @return $this
   *   Same object.
   */
  public function copy($source, $destination, $overwrite = self::OVERWRITE_ALLOW) {
    $this->method = 'COPY';
    $this->path = $source;

    $this->options['headers']['Destination'] = $destination;
    $this->options['headers']['Overwrite'] = $overwrite;

    return $this;
  }

  /**
   * Moves/renames a file/directory.
   *
   * If parent directory where the file/directory should be moved to does not
   * exist, the service will respond with the code 409 Conflict.
   * If overwriting is not allowed and target exists, the service will respond
   * with the code 412 Precondition Failed.
   *
   * @param string $source
   *   Path to the source file/directory.
   * @param string $destination
   *   New path for the file/directory.
   * @param string $overwrite
   *   (optional) Constant indicating whether overwriting is allowed or denied
   *   if target already exists. Default is to allow.
   *
   * @return $this
   *   Same object.
   */
  public function move($source, $destination, $overwrite = self::OVERWRITE_ALLOW) {
    $this->method = 'MOVE';
    $this->path = $source;

    $this->options['headers']['Destination'] = $destination;
    $this->options['headers']['Overwrite'] = $overwrite;

    return $this;
  }

  /**
   * Removes a file/directory.
   *
   * As specified in the protocol, removing a directory always removes all of
   * the files and directories that are in it.
   *
   * @param string $path
   *   Path to the file/directory to delete.
   *
   * @return $this
   *   Same object.
   */
  public function delete($path) {
    $this->method = 'DELETE';
    $this->path = $path;

    return $this;
  }

  /**
   * Gets file/directory properties.
   *
   * @param string $path
   *   Path to the file/directory.
   * @param int $depth
   *   (optional) Use 1 for directory to get a list of its contents properties.
   * @param string $data
   *   (optional) Data to send with the request.
   *
   * @return $this
   *   Same object.
   */
  public function propfind($path, $depth = 0, $data = NULL) {
    $this->method = 'PROPFIND';
    $this->path = $path;

    $this->options['headers']['Depth'] = $depth;

    $this->options['body'] = $data;

    return $this;
  }

  /**
   * Changes the properties of a file/directory.
   *
   * @param string $path
   *   Path to the file/directory.
   * @param string $data
   *   (optional) Data to send with the request.
   *
   * @return $this
   *   Same object.
   */
  public function proppatch($path, $data = NULL) {
    $this->method = 'PROPPATCH';
    $this->path = $path;

    $this->options['body'] = $data;

    return $this;
  }

  /**
   * Executes a request.
   *
   * @return bool
   *   Whether the request was executed successfully.
   *
   * @throws YandexDiskException
   *   If service failed to response.
   */
  public function execute() {
    $url = self::SCHEMA_HOST . UrlHelper::encodePath($this->path);
    if ($this->pathQuery) {
      $url .= '?' . UrlHelper::buildQuery($this->pathQuery);
    }
    $response = \Drupal::httpClient()->request($this->method, $url, $this->options);

    self::$lastResponse = $response;
    $code = (string) $response->getStatusCode();

    if (!$code) {
      throw new YandexDiskException(t('No response from service.'));
    }

    // Check for success code.
    $return = ($code[0] == 2 || $this->method == 'PUT' && $code == 100);

    // Prepare instance for future requests.
    $this->resetOptions();

    return $return;
  }

}

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

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