You are here

class AcquiaDAMStreamWrapper in Media: Acquia DAM 7

Provides a remote stream wrapper for Acquia DAM assets.

Create an instance like this: ```php $dam = new AcquiaDAMStreamWrapper('acquiadam://[asset_id].[filetype]'); ```

Hierarchy

Expanded class hierarchy of AcquiaDAMStreamWrapper

1 string reference to 'AcquiaDAMStreamWrapper'
media_acquiadam_stream_wrappers in ./media_acquiadam.module
Implements hook_stream_wrappers().

File

includes/AcquiaDAMStreamWrapper.inc, line 16
Create an Acquia DAM Stream Wrapper class for the Media/Resource module.

View source
class AcquiaDAMStreamWrapper extends DrupalRemoteStreamWrapper {

  /**
   * Fetch the content of the file using drupal_http_request().
   */
  protected function getStreamContent() {
    if (!isset($this->stream_content)) {
      $this->stream_content = NULL;

      // Translate our acquiadam:// uri into a remote URL before we make the
      // request.
      $uri = file_create_url($this->uri);
      $request = drupal_http_request($uri);
      if (empty($request->error) && !empty($request->data)) {
        $this->stream_content = $request->data;
      }
      elseif (!empty($request->error)) {
        watchdog('media_acquiadam', '(@code) Error fetching asset content: @error', [
          '@code' => $request->code,
          '@error' => $request->error,
        ], WATCHDOG_NOTICE, l(t('View'), $uri));
      }
    }
    return $this->stream_content;
  }

  /**
   * Support for fstat().
   *
   * {@inheritDoc}
   */
  public function stream_stat() {
    $stat = [];

    // Skip looking up the size if we already have it stored locally.
    // If we don't do this then file listing pages can issue several requests
    // and have a delay in loading.
    $files = entity_load('file', FALSE, [
      'uri' => $this->uri,
    ]);
    $file = !empty($files) ? reset($files) : FALSE;
    if (!empty($file->filesize)) {
      $stat = [
        'size' => $file->filesize,
      ];
    }
    else {

      // If the asset has an overall large size then we skip trying to get the
      // accurate size of the specific URL we're referencing. This comes into
      // play when the source image or video might be 15MB but we're trying to
      // render a thumbnail.
      $asset = $this
        ->getAssetByUri($this->uri);

      // Filesize can be '0.00' which will count as not empty, so we have to
      // check the size is greater than 0 as well.
      if (!empty($asset['filesize']) && 0 < $asset['filesize']) {
        $stat['size'] = $asset['filesize'] * 1024 * 1024;
      }
      else {

        // Translate our acquiadam:// uri into a remote URL before we make the
        // request.
        $uri = file_create_url($this->uri);
        $scheme = file_uri_scheme($uri);
        if (empty($scheme)) {
          $uri = url($uri, [
            'absolute' => TRUE,
          ]);
        }

        // We have to use a GET request here instead of HEAD because the
        // download links we receive are not valid for a HEAD-type request and
        // will return a 403.
        $request = drupal_http_request($uri, [
          'method' => 'GET',
        ]);
        if (empty($request->error) && isset($request->headers['content-length'])) {
          $stat['size'] = $request->headers['content-length'];
        }
        elseif (!empty($request->error)) {
          watchdog('media_acquiadam', '(@code) Error fetching asset size: @error', [
            '@code' => $request->code,
            '@error' => $request->error,
          ], WATCHDOG_NOTICE, l(t('View'), $uri));
        }
      }
    }
    return !empty($stat) ? $this
      ->getStat($stat) : FALSE;
  }

  /**
   * Get the mimetype of the file.
   *
   * Overridden to work with the Acquia DAM uri structure.
   *
   * {@inheritDoc}
   */
  public static function getMimeType($uri, $mapping = NULL) {
    if (!isset($mapping)) {

      // The default file map, defined in file.mimetypes.inc is quite big.
      // We only load it when necessary.
      include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
      $mapping = file_mimetype_mapping();
    }
    if ($target = file_uri_target($uri)) {
      $extension = '';
      $file_parts = explode('.', drupal_basename($target));
      $extensions = $mapping['extensions'];
      $mimetypes = $mapping['mimetypes'];
      $parsed_overrides = static::getMimetypeOverrides();

      // Remove the first part: a full filename should not match an extension.
      array_shift($file_parts);

      // Iterate over the file parts, trying to find a match.
      // For my.awesome.image.jpeg, we try:
      // - jpeg
      // - image.jpeg, and
      // - awesome.image.jpeg
      while ($additional_part = array_pop($file_parts)) {
        $extension = strtolower($additional_part . ($extension ? '.' . $extension : ''));
        if (!empty($parsed_overrides[$extension])) {
          $extension = $parsed_overrides[$extension];
        }
        if (!empty($mimetypes[$extensions[$extension]])) {
          return $mimetypes[$extensions[$extension]];
        }
      }
    }
    return 'application/octet-stream';
  }

  /**
   * Get a list of extensions mapped to other filetypes.
   *
   * @return array
   *   An array keyed by original extensions and the file types they shuld be
   *   treated as.
   */
  protected static function getMimetypeOverrides() {
    $parsed_overrides =& drupal_static(__CLASS__ . ':' . __METHOD__);
    if (is_null($parsed_overrides)) {
      $parsed_overrides = [];
      $extension_overrides = drupal_strtolower(variable_get('media_acquiadam_extension_overrides', 'eps png'));
      if (!empty($extension_overrides)) {

        // We need to convert a multiline "key value" pairing into a key value
        // array for ease of checking in extension/mimetype lists.
        $extension_overrides = explode("\n", $extension_overrides);
        foreach ($extension_overrides as $pairing) {
          if (!empty($pairing)) {
            list($source, $target) = explode(' ', $pairing, 2);
            $parsed_overrides[trim($source)] = trim($target);
          }
        }
      }
    }
    return $parsed_overrides;
  }

  /**
   * Return the external Url.
   *
   * {@inheritDoc}
   */
  public function getExternalUrl() {
    if ('acquiadam' !== file_uri_scheme($this->uri)) {
      return $this->uri;
    }
    $asset = static::getAssetByUri($this->uri);
    if (empty($asset)) {
      return FALSE;
    }
    $preview = $asset
      ->getPreviewUrl();
    if (empty($preview)) {

      // All other files (txt, docx, html, etc.).
      return url('acquiadam/asset/' . $asset['id'], [
        'absolute' => TRUE,
      ]);
    }
    return $preview;
  }

  /**
   * Get an asset ID from an Acquia DAM Uri.
   *
   * @param string $uri
   *   The URI to parse for an asset ID.
   *
   * @return int|false
   *   The asset ID or FALSE on failure.
   */
  protected static function getAssetIdFromUri($uri) {
    $target = file_uri_target($uri);
    list($asset_id) = explode('.', drupal_basename($target), 2);
    $asset_id = intval($asset_id);
    return empty($asset_id) ? FALSE : $asset_id;
  }

  /**
   * Load an asset by the Uri.
   *
   * @param string $uri
   *   The Uri to use to look up an asset.
   *
   * @return AcquiaDAM_Assets_Asset|false
   *   The asset or FALSE on failure.
   */
  protected static function getAssetByUri($uri) {
    $asset_id = static::getAssetIdFromUri($uri);
    return static::getAssetById($asset_id);
  }

  /**
   * Get an asset by ID.
   *
   * This requires the file already exist in Drupal and has valid JSON saved
   * to the database. We cannot directly look up assets using the API because
   * there is no promise that the user has API access.
   *
   * @param int $id
   *   The asset ID.
   *
   * @return AcquiaDAM_Assets_Asset|false
   *   The asset or FALSE on failure.
   */
  protected static function getAssetById($id) {
    module_load_include('inc', 'media_acquiadam', 'includes/media_acquiadam.helpers');
    try {
      $asset = media_acquiadam_get_asset($id);
    } catch (Exception $x) {
      watchdog_exception('acquiadam_stream_wrapper', $x);
      drupal_set_message(t('@class: Unable to load remote asset: @id.', [
        '@class' => __CLASS__,
        '@id' => $id,
      ]), 'warning');
    }
    return $asset;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AcquiaDAMStreamWrapper::getAssetById protected static function Get an asset by ID.
AcquiaDAMStreamWrapper::getAssetByUri protected static function Load an asset by the Uri.
AcquiaDAMStreamWrapper::getAssetIdFromUri protected static function Get an asset ID from an Acquia DAM Uri.
AcquiaDAMStreamWrapper::getExternalUrl public function Return the external Url. Overrides DrupalRemoteStreamWrapper::getExternalUrl
AcquiaDAMStreamWrapper::getMimeType public static function Get the mimetype of the file. Overrides DrupalRemoteStreamWrapper::getMimeType
AcquiaDAMStreamWrapper::getMimetypeOverrides protected static function Get a list of extensions mapped to other filetypes.
AcquiaDAMStreamWrapper::getStreamContent protected function Fetch the content of the file using drupal_http_request(). Overrides DrupalRemoteStreamWrapper::getStreamContent
AcquiaDAMStreamWrapper::stream_stat public function Support for fstat(). Overrides DrupalRemoteStreamWrapper::stream_stat
DrupalRemoteStreamWrapper::$context public property Stream context resource.
DrupalRemoteStreamWrapper::$stream_content protected property The content of the file.
DrupalRemoteStreamWrapper::$stream_pointer protected property The pointer to the next read or write within the content variable.
DrupalRemoteStreamWrapper::$uri protected property Instance URI (stream).
DrupalRemoteStreamWrapper::chmod function Implements chmod(). Overrides DrupalStreamWrapperInterface::chmod
DrupalRemoteStreamWrapper::dirname public function Gets the name of the directory from a given path. Overrides DrupalStreamWrapperInterface::dirname
DrupalRemoteStreamWrapper::dir_closedir public function Support for closedir(). Overrides StreamWrapperInterface::dir_closedir
DrupalRemoteStreamWrapper::dir_opendir public function Support for opendir(). Overrides StreamWrapperInterface::dir_opendir
DrupalRemoteStreamWrapper::dir_readdir public function Support for readdir(). Overrides StreamWrapperInterface::dir_readdir
DrupalRemoteStreamWrapper::dir_rewinddir public function Support for rewinddir(). Overrides StreamWrapperInterface::dir_rewinddir
DrupalRemoteStreamWrapper::getDirectoryPath public function Implements abstract public function getDirectoryPath()
DrupalRemoteStreamWrapper::getLocalPath function Return the local filesystem path.
DrupalRemoteStreamWrapper::getStat protected function Helper function to return a full array for stat functions.
DrupalRemoteStreamWrapper::getUri function Base implementation of getUri(). Overrides DrupalStreamWrapperInterface::getUri
DrupalRemoteStreamWrapper::mkdir public function Support for mkdir(). Overrides StreamWrapperInterface::mkdir
DrupalRemoteStreamWrapper::realpath function Implements realpath(). Overrides DrupalStreamWrapperInterface::realpath
DrupalRemoteStreamWrapper::rename public function Support for rename(). Overrides StreamWrapperInterface::rename
DrupalRemoteStreamWrapper::rmdir public function Support for rmdir(). Overrides StreamWrapperInterface::rmdir
DrupalRemoteStreamWrapper::setUri function Base implementation of setUri(). Overrides DrupalStreamWrapperInterface::setUri
DrupalRemoteStreamWrapper::stream_close public function Support for fclose(). Overrides StreamWrapperInterface::stream_close
DrupalRemoteStreamWrapper::stream_eof public function Support for feof(). Overrides StreamWrapperInterface::stream_eof
DrupalRemoteStreamWrapper::stream_flush public function Support for fflush(). Overrides StreamWrapperInterface::stream_flush
DrupalRemoteStreamWrapper::stream_lock public function Support for flock(). Overrides StreamWrapperInterface::stream_lock
DrupalRemoteStreamWrapper::stream_open public function Support for fopen(), file_get_contents(), file_put_contents() etc. Overrides StreamWrapperInterface::stream_open
DrupalRemoteStreamWrapper::stream_read public function Support for fread(), file_get_contents() etc. Overrides StreamWrapperInterface::stream_read
DrupalRemoteStreamWrapper::stream_seek public function Support for fseek(). Overrides StreamWrapperInterface::stream_seek
DrupalRemoteStreamWrapper::stream_tell public function Support for ftell(). Overrides StreamWrapperInterface::stream_tell
DrupalRemoteStreamWrapper::stream_write public function Support for fwrite(), file_put_contents() etc. Overrides StreamWrapperInterface::stream_write
DrupalRemoteStreamWrapper::unlink public function Support for unlink(). Overrides StreamWrapperInterface::unlink
DrupalRemoteStreamWrapper::url_stat public function Support for stat(). Overrides StreamWrapperInterface::url_stat