ui_icons-1.0.x-dev/modules/ui_icons_font/src/Plugin/IconExtractor/FontExtractor.php

modules/ui_icons_font/src/Plugin/IconExtractor/FontExtractor.php
<?php

declare(strict_types=1);

namespace Drupal\ui_icons_font\Plugin\IconExtractor;

// cspell:ignore codepoints
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Theme\Icon\Attribute\IconExtractor;
use Drupal\Core\Theme\Icon\Exception\IconPackConfigErrorException;
use Drupal\Core\Theme\Icon\IconDefinition;
use Drupal\Core\Theme\Icon\IconDefinitionInterface;
use Drupal\Core\Theme\Icon\IconExtractorBase;
use Drupal\Core\Theme\Icon\IconPackExtractorForm;
use FontLib\Font;

/**
 * Plugin implementation of the icon_extractor.
 */
#[IconExtractor(
  id: 'font',
  label: new TranslatableMarkup('Web Font'),
  description: new TranslatableMarkup('Provide Icons from web fonts.'),
  forms: [
    'settings' => IconPackExtractorForm::class,
  ]
)]
class FontExtractor extends IconExtractorBase {

  /**
   * {@inheritdoc}
   */
  public function discoverIcons(): array {
    if (!isset($this->configuration['config']['sources'])) {
      throw new IconPackConfigErrorException(sprintf('Missing `config: sources` in your definition, extractor %s require this value.', $this->getPluginId()));
    }

    $icons = [];
    foreach ($this->configuration['config']['sources'] as $filename) {
      $filepath = sprintf('%s/%s', $this->configuration['absolute_path'], $filename);
      $fileinfo = pathinfo($filepath);

      if (!isset($fileinfo['extension'])) {
        continue;
      }

      switch ($fileinfo['extension']) {
        case 'codepoints':
          $icons = array_merge($icons, $this->getCodePoints($filepath));
          break;

        case 'ttf':
        case 'woff':
          $icons = array_merge($icons, $this->getFontIcons($filepath));
          break;

        case 'json':
          $icons = array_merge($icons, $this->getJsonIcons($filepath));
          break;

        case 'yml':
        case 'yaml':
          $icons = array_merge($icons, $this->getYamlIcons($filepath));
          break;

        default:
          break;
      }
    }

    if (isset($this->configuration['config']['offset'])) {
      $icons = array_slice($icons, (int) $this->configuration['config']['offset']);
    }

    return $icons;
  }

  /**
   * {@inheritdoc}
   */
  public function loadIcon(array $icon_data): ?IconDefinitionInterface {
    if (!isset($icon_data['icon_id']) || empty($icon_data['icon_id'])) {
      return NULL;
    }

    $data = [];
    if (isset($icon_data['content'])) {
      $data['content'] = $icon_data['content'];
    }

    return $this->createIcon(
      $icon_data['icon_id'],
      '',
      NULL,
      $data,
    );
  }

  /**
   * Wrapper to get a file content.
   *
   * @param string $filepath
   *   The absolute path to the file.
   *
   * @return string|bool
   *   File content or false.
   */
  private function getFileContents(string $filepath): string|bool {
    return file_get_contents($filepath);
  }

  /**
   * Extract Icon names from TTF or Woff file.
   *
   * @param string $filepath
   *   The Code points file absolute path.
   *
   * @return array
   *   List of icons indexed by ID.
   */
  private function getFontIcons(string $filepath): array {
    $icons = [];

    if (!class_exists('\FontLib\Font')) {
      // @todo log error?
      return [];
    }

    $font = Font::load($filepath);
    if (NULL === $font) {
      return [];
    }

    $font->parse();
    $icons_names = $font->getData('post')['names'] ?? [];
    $icons = [];
    foreach ($icons_names as $icon_id) {
      $id = IconDefinition::createIconId($this->configuration['id'], (string) $icon_id);
      $icons[$id] = [];
    }

    return $icons;
  }

  /**
   * Extract Icon names from Json file.
   *
   * @param string $filepath
   *   The Code points file absolute path.
   *
   * @return array
   *   List of icons indexed by ID.
   */
  private function getJsonIcons(string $filepath): array {
    if (!$data = $this->getFileContents($filepath)) {
      return [];
    }

    if (!json_validate((string) $data)) {
      // @todo log error?
      return [];
    }

    $icons = [];
    $icon_json_ids = array_keys(json_decode((string) $data, TRUE));
    foreach ($icon_json_ids as $icon_id) {
      $id = IconDefinition::createIconId($this->configuration['id'], (string) $icon_id);
      $icons[$id] = [];
    }

    return $icons;
  }

  /**
   * Extract Icon names from Yaml file.
   *
   * @param string $filepath
   *   The Code points file absolute path.
   *
   * @return array
   *   List of icons indexed by ID.
   */
  private function getYamlIcons(string $filepath): array {
    if (!$data = $this->getFileContents($filepath)) {
      return [];
    }

    try {
      $data = Yaml::decode((string) $data);
    }
    catch (InvalidDataTypeException $e) {
      // @todo log error?
      return [];
    }

    if (empty($data)) {
      // @todo log warning?
      return [];
    }

    $icons = [];
    foreach (array_keys($data) as $icon_id) {
      $id = IconDefinition::createIconId($this->configuration['id'], (string) $icon_id);
      $icons[$id] = [];
    }

    return $icons;
  }

  /**
   * Extract Icon codepoints from codepoints file.
   *
   * @param string $filepath
   *   The Code points file absolute path.
   *
   * @return array
   *   List of icons indexed by ID.
   */
  private function getCodePoints(string $filepath): array {
    if (!$data = $this->getFileContents($filepath)) {
      return [];
    }

    $data_lines = explode("\n", (string) $data);
    $icons = [];
    foreach ($data_lines as $line) {
      $values = explode(' ', $line);
      if (empty($values) || !isset($values[1])) {
        continue;
      }
      $icon_id = $values[0];
      if (0 === strlen($icon_id)) {
        continue;
      }
      $id = IconDefinition::createIconId($this->configuration['id'], (string) $icon_id);
      $icons[$id] = [
        'content' => $values[1],
      ];
    }

    return $icons;
  }

}

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

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