class abstract class ApiProviderBase

CDN Provider base that uses an API to populate its assets.

Hierarchy

Expanded class hierarchy of ApiProviderBase

Related topics

Namespace

Drupal\bootstrap\Plugin\Provider
Source
abstract class ApiProviderBase extends ProviderBase {

  /**
   * {@inheritdoc}
   */
  protected function discoverCdnAssets($version, $theme = NULL) {
    if ($this->supportsThemes()) {
      $themes = $this->getCdnThemes($version);
      return isset($themes[$theme]) ? $themes[$theme] : new CdnAssets();
    }
    return $this->requestApiAssets('bootstrap', $version, $this->getCacheTtl(static::CACHE_ASSETS));
  }

  /**
   * {@inheritdoc}
   */
  protected function discoverCdnThemes($version) {
    $assets = new CdnAssets();
    foreach (['bootstrap', 'bootswatch'] as $library) {
      $assets = $this->requestApiAssets($library, $version, $this->getCacheTtl(static::CACHE_THEMES), $assets);
    }
    return $assets->getThemes();
  }

  /**
   * {@inheritdoc}
   */
  protected function discoverCdnVersions() {
    return $this->requestApiVersions('bootstrap', $this->getCacheTtl(static::CACHE_VERSIONS));
  }

  /**
   * Retrieves the URL to use for determining available versions from the API.
   *
   * @param string $library
   *   The library to request.
   * @param string $version
   *   The version to request.
   *
   * @return string
   *   The API URL to use.
   */
  protected function getApiAssetsUrl($library, $version) {
    return (string) new FormattableMarkup($this->getApiAssetsUrlTemplate(), [
      '@library' => Markup::create($this->mapLibrary($library)),
      '@version' => Markup::create($this->mapVersion($version, $library)),
    ]);
  }

  /**
   * Retrieves the API URL template to use when requesting a specific asset.
   *
   * Available placeholders (must be prepended with an at symbol, @):
   * - library - The library to request.
   * - version - The version to request.
   *
   * @return string
   *   The CDN URL template.
   */
  abstract protected function getApiAssetsUrlTemplate();

  /**
   * Retrieves the URL to use for determining available versions from the API.
   *
   * @param string $library
   *   The library to request.
   *
   * @return string
   *   The API URL to use.
   */
  protected function getApiVersionsUrl($library) {
    return (string) new FormattableMarkup($this->getApiVersionsUrlTemplate(), [
      '@library' => Markup::create($this->mapLibrary($library)),
    ]);
  }

  /**
   * Retrieves the API URL template to use for determining available versions.
   *
   * Available placeholders (must be prepended with an at symbol, @):
   * - library - The specific library being requested.
   *
   * @return string
   *   The CDN URL template.
   */
  abstract protected function getApiVersionsUrlTemplate();

  /**
   * Retrieves a CDN URL based on provided variables.
   *
   * @param string $library
   *   The library to request.
   * @param string $version
   *   The version to request.
   * @param string $file
   *   The file to request.
   * @param array $info
   *   Additional information about the file, if any.
   *
   * @return \Drupal\bootstrap\Plugin\Provider\CdnAsset
   *   A CDN URL.
   */
  protected function getCdnUrl($library, $version, $file, array $info = []) {
    $library = $this->mapLibrary($library);
    $version = $this->mapVersion($version, $library);

    // Check if the "file" is really a fully qualified URL.
    if (UrlHelper::isExternal($file)) {
      $url = $file;
    }
    // Otherwise, use the template.
    else {
      $url = (string) new FormattableMarkup($this->getCdnUrlTemplate(), [
        '@library' => Markup::create($library),
        '@version' => Markup::create($version),
        '@file' => Markup::create(ltrim($file, '/')),
      ]);
    }

    return new CdnAsset($url, $library, $version, $info);
  }

  /**
   * Retrieves the CDN URL template to use.
   *
   * Available placeholders (must be prepended with an at symbol, @):
   * - library - The library to request.
   * - version - The version to request.
   * - file - The file to request.
   * - theme - The theme to request.
   *
   * @return string
   *   The CDN URL template.
   */
  abstract protected function getCdnUrlTemplate();

  /**
   * Checks whether a version is valid.
   *
   * @param string $version
   *   The version to check.
   *
   * @return bool
   *   TRUE or FALSE
   *
   * @todo Move regular expression to a constant once PHP 5.5 is no longer
   *   supported.
   */
  public static function isValidVersion($version) {
    return !!is_string($version) && preg_match('/^' . Bootstrap::FRAMEWORK_VERSION [0] . '\.\d+\.\d+$/', $version);
  }

  /**
   * Allows providers a way to map a library to a different library.
   *
   * @param string $library
   *   The library to map.
   *
   * @return string
   *   The mapped library.
   */
  protected function mapLibrary($library) {
    return $library;
  }

  /**
   * {@inheritdoc}
   */
  protected function mapVersion($version, $library = NULL) {
    $mapped = [];

    // While the Bootswatch project attempts to maintain version parity with
    // Bootstrap, it doesn't always happen. This causes issues when the system
    // expects a 1:1 version match between Bootstrap and Bootswatch.
    // @see https://github.com/thomaspark/bootswatch/issues/892#ref-issue-410070082
    if ($library === 'bootswatch') {
      // This version is "broken" because of jsDelivr's API limit.
      $mapped['3.4.1'] = '3.4.0';
      // This version doesn't exist.
      $mapped['3.1.1'] = '3.2.0';
    }

    return isset($mapped[$version]) ? $mapped[$version] : $version;
  }

  /**
   * Parses assets provided by the API data.
   *
   * @param array $data
   *   The data to parse.
   * @param string $library
   *   The base URL each one of the $files are relative to, this usually
   *   should also include the version path prefix as well.
   * @param string $version
   *   A specific version to use.
   * @param \Drupal\bootstrap\Plugin\Provider\CdnAssets $assets
   *   An existing CdnAssets object, if chaining multiple requests together.
   *
   * @return \Drupal\bootstrap\Plugin\Provider\CdnAssets
   *   A CdnAssets object containing the necessary assets.
   */
  protected function parseAssets(array $data, $library, $version, CdnAssets $assets = NULL) {
    if (!isset($assets)) {
      $assets = new CdnAssets();
    }

    $files = [];
    // Support APIs that have a dedicated "files" property.
    if (isset($data['files'])) {
      $files = $data['files'];
    }
    elseif (isset($data['assets'])) {
      foreach ($data['assets'] as $asset) {
        // Support APIs that clump all the assets together, regardless of their
        // versions. Skip assets that don't match this version.
        if (isset($asset['version']) && $asset['version'] !== $version) {
          continue;
        }
        // Found the necessary files for the specified version.
        if (!empty($asset['files'])) {
          $files = $asset['files'];
          break;
        }
      }
    }
    foreach ($files as $file) {
      // Support APIs that simply use simple strings as files.
      if (is_string($file) && CdnAsset::isFileValid($file)) {
        $assets->append($this->getCdnUrl($library, $version, $file));
      }
      // Support APIs that put each file into its own array (metadata).
      elseif (is_array($file)) {
        // Support APIs that clump all the files together, regardless of their
        // versions. Skip assets that don't match this version.
        if (isset($file['version']) && $file['version'] !== $version) {
          continue;
        }
        // Support multiple keys for the "file".
        foreach (['filename', 'name', 'url', 'uri', 'path'] as $key) {
          if (!empty($file[$key]) && CdnAsset::isFileValid($file[$key])) {
            $assets->append($this->getCdnUrl($library, $version, $file[$key], $file));
            break;
          }
        }
      }
    }

    return $assets;
  }

  /**
   * Parses available versions provided by the API data.
   *
   * @param array $data
   *   The data to parse.
   *
   * @return array
   *   An associative array of versions, keyed by version.
   */
  protected function parseVersions(array $data = []) {
    $versions = [];

    // Support APIs that have a dedicated "versions" property.
    if (!empty($data['versions'])) {
      foreach ($data['versions'] as $version) {
        // Only extract valid versions.
        if ($this->isValidVersion($version)) {
          $versions[$version] = $version;
        }
      }
    }
    // Support APIs that have the version nested under individual assets.
    elseif (!empty($data['assets'])) {
      foreach ($data['assets'] as $asset) {
        if (isset($asset['version']) && $this->isValidVersion($asset['version'])) {
          $versions[$asset['version']] = $asset['version'];
        }
      }
    }

    return $versions;
  }

  /**
   * Requests available assets from the CDN Provider API.
   *
   * @param string $library
   *   The library to request.
   * @param string $version
   *   The version to request.
   * @param int $ttl
   *   Optional. A specific TTL value to use for caching the HTTP request. If
   *   not set, it will default to whatever is returned by the HTTP request.
   * @param \Drupal\bootstrap\Plugin\Provider\CdnAssets $assets
   *   An existing CdnAssets object, if chaining multiple requests together.
   *
   * @return \Drupal\bootstrap\Plugin\Provider\CdnAssets
   *   The CdnAssets provided by the API.
   */
  protected function requestApiAssets($library, $version, $ttl = NULL, CdnAssets $assets = NULL) {
    $url = $this->getApiAssetsUrl($library, $version);
    $data = $this->request($url, ['ttl' => $ttl])->getData();

    // If bootstrap data could not be returned, provide defaults.
    if (!$data && $this->cdnExceptions && $library === 'bootstrap') {
      $data = [
        'files' => [
          '/dist/css/bootstrap.css',
          '/dist/js/bootstrap.js',
          '/dist/css/bootstrap.min.css',
          '/dist/js/bootstrap.min.js',
        ],
      ];
    }

    // Parse the files from data.
    return $this->parseAssets($data, $library, $version, $assets);
  }

  /**
   * Requests available versions from the CDN Provider API.
   *
   * @param string $library
   *   The library to request versions for.
   * @param int $ttl
   *   Optional. A specific TTL value to use for caching the HTTP request. If
   *   not set, it will default to whatever is returned by the HTTP request.
   *
   * @return array
   *   An associative array of versions, keyed by version.
   */
  public function requestApiVersions($library, $ttl = NULL) {
    $url = $this->getApiVersionsUrl($library);
    $data = $this->request($url, ['ttl' => $ttl])->getData();

    // If bootstrap data could not be returned, provide defaults.
    if (!$data && $this->cdnExceptions && $library === 'bootstrap') {
      $data = ['versions' => [Bootstrap::FRAMEWORK_VERSION]];
    }

    return $this->parseVersions($data);
  }

  /**
   * {@inheritdoc}
   *
   * @deprecated in 8.x-3.18, will be removed in a future release.
   */
  public function processDefinition(array &$definition, $plugin_id) {
    // Intentionally left blank so it doesn't trigger a deprecation warning.
  }

}

Members

Contains filters are case sensitive
Name Modifiers Type Description
ApiProviderBase::discoverCdnAssets protected function Discovers the assets supported by the CDN Provider. Overrides ProviderBase::discoverCdnAssets
ApiProviderBase::discoverCdnThemes protected function Discovers the themes supported by the CDN Provider. Overrides ProviderBase::discoverCdnThemes
ApiProviderBase::discoverCdnVersions protected function Discovers the versions supported by the CDN Provider. Overrides ProviderBase::discoverCdnVersions
ApiProviderBase::getApiAssetsUrl protected function Retrieves the URL to use for determining available versions from the API.
ApiProviderBase::getApiAssetsUrlTemplate abstract protected function Retrieves the API URL template to use when requesting a specific asset.
ApiProviderBase::getApiVersionsUrl protected function Retrieves the URL to use for determining available versions from the API.
ApiProviderBase::getApiVersionsUrlTemplate abstract protected function Retrieves the API URL template to use for determining available versions.
ApiProviderBase::getCdnUrl protected function Retrieves a CDN URL based on provided variables.
ApiProviderBase::getCdnUrlTemplate abstract protected function Retrieves the CDN URL template to use.
ApiProviderBase::isValidVersion public static function Checks whether a version is valid.
ApiProviderBase::mapLibrary protected function Allows providers a way to map a library to a different library.
ApiProviderBase::mapVersion protected function Allows providers a way to map a version to a different version. Overrides ProviderBase::mapVersion
ApiProviderBase::parseAssets protected function Parses assets provided by the API data.
ApiProviderBase::parseVersions protected function Parses available versions provided by the API data.
ApiProviderBase::processDefinition Deprecated public function Overrides ProviderBase::processDefinition
ApiProviderBase::requestApiAssets protected function Requests available assets from the CDN Provider API.
ApiProviderBase::requestApiVersions public function Requests available versions from the CDN Provider API.
PluginBase::$theme protected property The currently set theme object.
PluginBase::__construct public function
ProviderBase::$assets Deprecated protected property The currently set assets.
ProviderBase::$cacheTtl protected property The cache TTL values, in seconds, keyed by type.
ProviderBase::$cdnAssets protected property The currently set CDN assets, keyed by a hash identifier.
ProviderBase::$cdnExceptions protected property A list of currently set Exception objects.
ProviderBase::$keyValue protected property The cache backend used for storing various permanent CDN Provider data.
ProviderBase::$keyValueExpirable protected property The cache backend used for storing various expirable CDN Provider data.
ProviderBase::$themes protected property The themes supplied by the CDN Provider, keyed by version.
ProviderBase::$versions protected property The versions supplied by the CDN Provider.
ProviderBase::addCdnException protected function Adds a new CDN Provider exception.
ProviderBase::alterFrameworkLibrary public function Overrides ProviderInterface::alterFrameworkLibrary
ProviderBase::cacheGet protected function Retrieves a value from the CDN Provider cache.
ProviderBase::getApi Deprecated public function Overrides ProviderInterface::getApi
ProviderBase::getAssets Deprecated public function Overrides ProviderInterface::getAssets
ProviderBase::getCacheId protected function Retrieves the unique cache identifier for the CDN Provider.
ProviderBase::getCacheTtl public function Retrieves the cache time-to-live (TTL) value. Overrides ProviderInterface::getCacheTtl
ProviderBase::getCdnAssets public function Retrieves the assets from the CDN, if any. Overrides ProviderInterface::getCdnAssets
ProviderBase::getCdnAssetsCacheData protected function Retrieves the data used to create a hash for CDN Assets.
ProviderBase::getCdnExceptions public function Retrieves any CDN ProviderException objects triggered during discovery. Overrides ProviderInterface::getCdnExceptions
ProviderBase::getCdnTheme public function Retrieves the currently set CDN Provider theme. Overrides ProviderInterface::getCdnTheme
ProviderBase::getCdnThemes public function Retrieves the themes supported by the CDN Provider. Overrides ProviderInterface::getCdnThemes
ProviderBase::getCdnThemesCacheData protected function Retrieves the data used to create a hash for CDN Themes.
ProviderBase::getCdnVersion public function Retrieves the currently set CDN Provider version. Overrides ProviderInterface::getCdnVersion
ProviderBase::getCdnVersions public function Retrieves the versions supported by the CDN Provider. Overrides ProviderInterface::getCdnVersions
ProviderBase::getCdnVersionsCacheData protected function Retrieves the data used to create a hash for CDN Versions.
ProviderBase::getDescription public function Retrieves the provider description. Overrides ProviderInterface::getDescription
ProviderBase::getKeyValue protected function Retrieves a permanent key/value storage instance.
ProviderBase::getKeyValueExpirable protected function Retrieves a expirable key/value storage instance.
ProviderBase::getLabel public function Retrieves the provider human-readable label. Overrides ProviderInterface::getLabel
ProviderBase::getOverrides protected function Retrieves the Drupal overrides CSS file.
ProviderBase::getThemes public function Retrieves the themes supported by the CDN Provider. Overrides ProviderInterface::getThemes
ProviderBase::getVersions public function Retrieves the versions supported by the CDN Provider. Overrides ProviderInterface::getVersions
ProviderBase::hasError Deprecated public function Overrides ProviderInterface::hasError
ProviderBase::isImported Deprecated public function Overrides ProviderInterface::isImported
ProviderBase::processApi Deprecated public function Overrides ProviderInterface::processApi
ProviderBase::request protected function Initiates an HTTP request.
ProviderBase::resetCache public function Removes any cached data the CDN Provider may have. Overrides ProviderInterface::resetCache
ProviderBase::setCdnExceptions protected function Sets CDN Provider exceptions, replacing any existing exceptions.
ProviderBase::supportsThemes public function Indicates whether the CDN Provider supports themes. Overrides ProviderInterface::supportsThemes
ProviderBase::supportsVersions public function Indicates whether the CDN Provider supports versions. Overrides ProviderInterface::supportsVersions
ProviderBase::trackCdnExceptions public function Tracks any newly generated CDN exceptions generated during a callable. Overrides ProviderInterface::trackCdnExceptions
ProviderInterface::CACHE_ASSETS constant Defines the "assets" cache type.
ProviderInterface::CACHE_LIBRARY constant Defines the "library" cache type.
ProviderInterface::CACHE_THEMES constant Defines the "themes" cache type.
ProviderInterface::CACHE_VERSIONS constant Defines the "versions" cache type.
ProviderInterface::TTL_FOREVER constant Defines the "forever" time-to-live (TTL) value.
ProviderInterface::TTL_NEVER constant Defines the "never" time-to-live (TTL) value.
ProviderInterface::TTL_ONE_DAY constant Defines the "one day" time-to-live (TTL) value.
ProviderInterface::TTL_ONE_MONTH constant Defines the "one month" time-to-live (TTL) value.
ProviderInterface::TTL_ONE_WEEK constant Defines the "one week" time-to-live (TTL) value.
ProviderInterface::TTL_ONE_YEAR constant Defines the "one year" time-to-live (TTL) value.
ProviderInterface::TTL_SIX_MONTHS constant Defines the "six months" time-to-live (TTL) value.
ProviderInterface::TTL_THREE_MONTHS constant Defines the "three months" time-to-live (TTL) value.