countdown-8.x-1.8/src/Utility/CdnUrlBuilder.php

src/Utility/CdnUrlBuilder.php
<?php

declare(strict_types=1);

namespace Drupal\countdown\Utility;

/**
 * Builds CDN URLs for countdown libraries.
 *
 * This utility centralizes CDN URL construction logic previously scattered
 * across plugins and the library manager.
 */
class CdnUrlBuilder {

  /**
   * CDN URL templates by provider.
   *
   * @var array
   */
  protected const CDN_TEMPLATES = [
    'jsdelivr' => [
      'npm' => '//cdn.jsdelivr.net/npm/@package@version/dist/@file',
      'github' => '//cdn.jsdelivr.net/gh/@owner/@repo@tag/@file',
    ],
    'unpkg' => [
      'npm' => '//unpkg.com/@package@version/dist/@file',
    ],
    'cdnjs' => [
      'library' => '//cdnjs.cloudflare.com/ajax/libs/@library/@version/@file',
    ],
  ];

  /**
   * Builds a CDN URL for a library asset.
   *
   * @param string $provider
   *   The CDN provider (jsdelivr, unpkg, cdnjs).
   * @param string $package
   *   The package identifier (npm package or library name).
   * @param string $version
   *   The version string.
   * @param string $file
   *   The file path within the package.
   * @param bool $minified
   *   Whether to use minified version.
   *
   * @return string
   *   The complete CDN URL.
   */
  public function buildUrl(string $provider, string $package, string $version, string $file, bool $minified = TRUE): string {
    // Apply minification to file name if needed.
    if ($minified && !str_contains($file, '.min.')) {
      $file = $this->minifyFileName($file);
    }

    // Handle special cases for each provider.
    switch ($provider) {
      case 'jsdelivr':
        return $this->buildJsdelivrUrl($package, $version, $file);

      case 'unpkg':
        return $this->buildUnpkgUrl($package, $version, $file);

      case 'cdnjs':
        return $this->buildCdnjsUrl($package, $version, $file);

      default:
        // For custom or unknown providers, return as-is.
        return "//{$provider}/{$package}@{$version}/{$file}";
    }
  }

  /**
   * Builds a jsDelivr URL.
   *
   * @param string $package
   *   The npm package name.
   * @param string $version
   *   The version string.
   * @param string $file
   *   The file path.
   *
   * @return string
   *   The jsDelivr URL.
   */
  protected function buildJsdelivrUrl(string $package, string $version, string $file): string {
    // Clean version (remove 'v' prefix if present).
    $version = ltrim($version, 'v');

    // Handle scoped packages.
    if (str_starts_with($package, '@')) {
      return "//cdn.jsdelivr.net/npm/{$package}@{$version}/{$file}";
    }

    return "//cdn.jsdelivr.net/npm/{$package}@{$version}/{$file}";
  }

  /**
   * Builds an unpkg URL.
   *
   * @param string $package
   *   The npm package name.
   * @param string $version
   *   The version string.
   * @param string $file
   *   The file path.
   *
   * @return string
   *   The unpkg URL.
   */
  protected function buildUnpkgUrl(string $package, string $version, string $file): string {
    // Clean version.
    $version = ltrim($version, 'v');

    return "//unpkg.com/{$package}@{$version}/{$file}";
  }

  /**
   * Builds a cdnjs URL.
   *
   * @param string $library
   *   The library name (without scope).
   * @param string $version
   *   The version string.
   * @param string $file
   *   The file path.
   *
   * @return string
   *   The cdnjs URL.
   */
  protected function buildCdnjsUrl(string $library, string $version, string $file): string {
    // Remove scope from package name if present.
    if (str_contains($library, '/')) {
      $parts = explode('/', $library);
      $library = end($parts);
    }

    // Clean version.
    $version = ltrim($version, 'v');

    return "//cdnjs.cloudflare.com/ajax/libs/{$library}/{$version}/{$file}";
  }

  /**
   * Converts a file name to its minified version.
   *
   * @param string $file
   *   The original file name.
   *
   * @return string
   *   The minified file name.
   */
  protected function minifyFileName(string $file): string {
    // Handle .js files.
    if (str_ends_with($file, '.js')) {
      return substr($file, 0, -3) . '.min.js';
    }

    // Handle .css files.
    if (str_ends_with($file, '.css')) {
      return substr($file, 0, -4) . '.min.css';
    }

    // Return as-is for other file types.
    return $file;
  }

  /**
   * Extracts CDN parameters from a URL template.
   *
   * @param string $url
   *   The CDN URL to parse.
   *
   * @return array|null
   *   Array with 'provider', 'package', 'version', 'file' keys, or NULL.
   */
  public function parseUrl(string $url): ?array {
    // Pattern for jsdelivr.
    if (preg_match('#//cdn\.jsdelivr\.net/npm/([^@]+)@([^/]+)/(.+)#', $url, $matches)) {
      return [
        'provider' => 'jsdelivr',
        'package' => $matches[1],
        'version' => $matches[2],
        'file' => $matches[3],
      ];
    }

    // Pattern for unpkg.
    if (preg_match('#//unpkg\.com/([^@]+)@([^/]+)/(.+)#', $url, $matches)) {
      return [
        'provider' => 'unpkg',
        'package' => $matches[1],
        'version' => $matches[2],
        'file' => $matches[3],
      ];
    }

    // Pattern for cdnjs.
    if (preg_match('#//cdnjs\.cloudflare\.com/ajax/libs/([^/]+)/([^/]+)/(.+)#', $url, $matches)) {
      return [
        'provider' => 'cdnjs',
        'package' => $matches[1],
        'version' => $matches[2],
        'file' => $matches[3],
      ];
    }

    return NULL;
  }

}

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

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