class InfoParserDynamic
Parses dynamic .info.yml files that might change during the page request.
Hierarchy
- class \Drupal\Core\Extension\InfoParserDynamic implements \Drupal\Core\Extension\InfoParserInterface
 
Expanded class hierarchy of InfoParserDynamic
3 files declare their use of InfoParserDynamic
- InfoParserUnitTest.php in core/
tests/ Drupal/ Tests/ Core/ Extension/ InfoParserUnitTest.php  - InstallCommand.php in core/
lib/ Drupal/ Core/ Command/ InstallCommand.php  - UpdateUploadTest.php in core/
modules/ update/ tests/ src/ Functional/ UpdateUploadTest.php  
File
- 
              core/
lib/ Drupal/ Core/ Extension/ InfoParserDynamic.php, line 12  
Namespace
Drupal\Core\ExtensionView source
class InfoParserDynamic implements InfoParserInterface {
  
  /**
   * The root directory of the Drupal installation.
   *
   * @var string
   */
  protected $root;
  
  /**
   * InfoParserDynamic constructor.
   *
   * @param string|null $app_root
   *   The root directory of the Drupal installation.
   */
  public function __construct(?string $app_root = NULL) {
    if ($app_root === NULL) {
      @trigger_error('Calling InfoParserDynamic::__construct() without the $app_root argument is deprecated in drupal:10.1.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3293709', E_USER_DEPRECATED);
      $app_root = \Drupal::hasService('kernel') ? \Drupal::root() : DRUPAL_ROOT;
    }
    $this->root = $app_root;
  }
  
  /**
   * {@inheritdoc}
   */
  public function parse($filename) {
    if (!file_exists($filename)) {
      throw new InfoParserException("Unable to parse {$filename} as it does not exist");
    }
    try {
      $parsed_info = Yaml::decode(file_get_contents($filename));
    } catch (InvalidDataTypeException $e) {
      throw new InfoParserException("Unable to parse {$filename} " . $e->getMessage());
    }
    $missing_keys = array_diff($this->getRequiredKeys(), array_keys($parsed_info));
    if (!empty($missing_keys)) {
      throw new InfoParserException('Missing required keys (' . implode(', ', $missing_keys) . ') in ' . $filename);
    }
    if (!isset($parsed_info['core_version_requirement'])) {
      if (str_starts_with($filename, 'core/') || str_starts_with($filename, $this->root . '/core/')) {
        // Core extensions do not need to specify core compatibility: they are
        // by definition compatible so a sensible default is used. Core
        // modules are allowed to provide these for testing purposes.
        $parsed_info['core_version_requirement'] = \Drupal::VERSION;
      }
      elseif (isset($parsed_info['package']) && $parsed_info['package'] === 'Testing') {
        // Modules in the testing package are exempt as well. This makes it
        // easier for contrib to use test modules.
        $parsed_info['core_version_requirement'] = \Drupal::VERSION;
      }
      else {
        // Non-core extensions must specify core compatibility.
        throw new InfoParserException("The 'core_version_requirement' key must be present in " . $filename);
      }
    }
    // Determine if the extension is compatible with the current version of
    // Drupal core.
    try {
      $parsed_info['core_incompatible'] = !Semver::satisfies(\Drupal::VERSION, $parsed_info['core_version_requirement']);
    } catch (\UnexpectedValueException $exception) {
      throw new InfoParserException("The 'core_version_requirement' constraint ({$parsed_info['core_version_requirement']}) is not a valid value in {$filename}");
    }
    if (isset($parsed_info['version']) && $parsed_info['version'] === 'VERSION') {
      $parsed_info['version'] = \Drupal::VERSION;
    }
    $parsed_info += [
      ExtensionLifecycle::LIFECYCLE_IDENTIFIER => ExtensionLifecycle::STABLE,
    ];
    $lifecycle = $parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER];
    if (!ExtensionLifecycle::isValid($lifecycle)) {
      $valid_values = [
        ExtensionLifecycle::EXPERIMENTAL,
        ExtensionLifecycle::STABLE,
        ExtensionLifecycle::DEPRECATED,
        ExtensionLifecycle::OBSOLETE,
      ];
      throw new InfoParserException("'lifecycle: {$lifecycle}' is not valid in {$filename}. Valid values are: '" . implode("', '", $valid_values) . "'.");
    }
    if (in_array($lifecycle, [
      ExtensionLifecycle::DEPRECATED,
      ExtensionLifecycle::OBSOLETE,
    ], TRUE)) {
      if (empty($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER])) {
        throw new InfoParserException(sprintf("Extension %s (%s) has 'lifecycle: %s' but is missing a '%s' entry.", $parsed_info['name'], $filename, $lifecycle, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
      }
      if (!filter_var($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER], FILTER_VALIDATE_URL)) {
        throw new InfoParserException(sprintf("Extension %s (%s) has a '%s' entry that is not a valid URL.", $parsed_info['name'], $filename, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
      }
    }
    return $parsed_info;
  }
  
  /**
   * Returns an array of keys required to exist in .info.yml file.
   *
   * @return array
   *   An array of required keys.
   */
  protected function getRequiredKeys() {
    return [
      'type',
      'name',
    ];
  }
}
Members
| Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides | 
|---|---|---|---|---|---|
| InfoParserDynamic::$root | protected | property | The root directory of the Drupal installation. | ||
| InfoParserDynamic::getRequiredKeys | protected | function | Returns an array of keys required to exist in .info.yml file. | ||
| InfoParserDynamic::parse | public | function | Parses Drupal module, theme and profile .info.yml files. | Overrides InfoParserInterface::parse | 1 | 
| InfoParserDynamic::__construct | public | function | InfoParserDynamic constructor. | 1 | 
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.