patchinfo-8.x-2.x-dev/modules/patchinfo_source_composer/src/Plugin/PatchInfo/Source/ComposerJsonSource.php

modules/patchinfo_source_composer/src/Plugin/PatchInfo/Source/ComposerJsonSource.php
<?php

namespace Drupal\patchinfo_source_composer\Plugin\patchinfo\source;

use Drupal\Core\Extension\Extension;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\patchinfo\PatchInfoSourceBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Gathers patch information from composer.json files.
 *
 * This patch source will read patches from your composer.json files and any
 * external patch files specified in your composer.json files. For Drupal Core,
 * it will check for a composer.json in your Drupal root directory or in the
 * core folder.
 *
 * It is assumed, that 'cweagans/composer-patches' is used for patch management
 * with Composer.
 *
 * Presently, the source plugin will skip any patches for modules outside the
 * 'drupal/' namespace.
 *
 * @see https://github.com/cweagans/composer-patches
 *
 * @PatchInfoSource(
 *   id = "patchinfo_composer",
 *   label = @Translation("composer.json", context = "PatchInfoSource"),
 * )
 */
class ComposerJsonSource extends PatchInfoSourceBase {

  /**
   * The file system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * Constructs a PatchInfoSourceBase object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The logger factory.
   * @param \Drupal\Core\File\FileSystemInterface $file_system
   *   The file system service.
   */
  public function __construct(array $configuration, string $plugin_id, $plugin_definition, LoggerChannelFactoryInterface $logger_factory, FileSystemInterface $file_system) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $logger_factory);
    $this->fileSystem = $file_system;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.factory'),
      $container->get('file_system')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getPatches(array $info, Extension $file, string $type) {
    $return = [];

    if (!in_array($type, ['module', 'theme'])) {
      return $return;
    }

    $patches = $this->parseComposerFile($file->getPath());
    $return = array_merge_recursive($return, $patches);

    if ($file->getName() == 'system') {
      // Check for patches in /composer.json, ../composer.json and
      // /core/composer.json.
      $core_base_path = str_replace('/modules/system', '', $file->getPath());

      $patches = $this->parseComposerFile($core_base_path);
      $return = array_merge_recursive($return, $patches);

      $patches = $this->parseComposerFile('.');
      $return = array_merge_recursive($return, $patches);

      $patches = $this->parseComposerFile('..');
      $return = array_merge_recursive($return, $patches);
    }

    return $return;
  }

  /**
   * Parses composer.json within a given path for patches.
   *
   * @param string $path
   *   A path from the local filesystem from where to fetch composer.json.
   *
   * @return array
   *   An array of patch information keyed by composer project name. The patch
   *   information is an array with an info key and a source key. The info key
   *   is a string with the url of the patch file followed by a space and the
   *   patch description. The source key is the path to the composer.json file
   *   that contained the patch information or link to the external patch file.
   */
  protected function parseComposerFile(string $path) {
    $return = [];

    // Try to prevent triggering open basedir restrictions.
    if (stream_resolve_include_path($path . DIRECTORY_SEPARATOR . 'composer.json') === FALSE) {
      return $return;
    }

    $path = $this->fileSystem->realpath($path);

    $config = $this->getDecodedJson($path, 'composer.json');

    $patches = [];
    if (!empty($config['extra']['patches'])) {
      $patches = $config['extra']['patches'];
    }
    elseif (!empty($config['extra']['patches-file'])) {
      $patch_file = $this->getDecodedJson($path, $config['extra']['patches-file']);
      if (!empty($patch_file['patches'])) {
        $patches = $patch_file['patches'];
      }
    }

    foreach ($patches as $project => $project_patches) {
      if (strpos($project, 'drupal/') !== 0) {
        // Only handle Drupal projects.
        continue;
      }

      // Generate Drupal project name from composer project name.
      $project = str_replace('drupal/', '', $project);
      if ($project == 'core' || $project == 'drupal') {
        $project = 'system';
      }

      foreach ($project_patches as $description => $url) {
        $info = $url . ' ' . $description;
        $return[$project][] = [
          'info' => trim($info),
          'source' => $path . '/composer.json',
        ];
      }
    }

    return $return;
  }

  /**
   * Gets decoded JSON from a JSON file.
   *
   * @param string $path
   *   Path to JSON file.
   * @param string $file
   *   JSON file name.
   *
   * @return mixed
   *   Parsed JSON.
   */
  protected function getDecodedJson(string $path, string $file) {
    $return = [];

    if (!file_exists($path . '/' . $file)) {
      return $return;
    }

    if (!is_readable($path . '/' . $file)) {
      $this->loggerFactory->get('patchinfo_source_composer')->warning($this->t('Can not read @path/@file. Check your file permissions.', [
        '@path' => $path,
        '@file' => $file,
      ]));
      return $return;
    }

    $content = file_get_contents($path . '/' . $file);
    if ($content === FALSE) {
      $this->loggerFactory->get('patchinfo_source_composer')->warning($this->t('Can not get contents from @path/@file.', [
        '@path' => $path,
        '@file' => $file,
      ]));
      return $return;
    }

    $config = json_decode($content, TRUE);
    if ($config === NULL) {
      $this->loggerFactory->get('patchinfo_source_composer')->warning($this->t('Unable to parse @path/@file. Check your JSON syntax.', [
        '@path' => $path,
        '@file' => $file,
      ]));
      return $return;
    }

    return $config;
  }

}

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

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