ExtensionDiscovery example



  /** * Scans all module, theme, and profile extensions and load the update files. * * @param string|null $extension * (optional) Limits the extension update files loaded to the provided * extension. */
  protected function scanExtensionsAndLoadUpdateFiles(string $extension = NULL) {
    // Scan for extensions.     $extension_discovery = new ExtensionDiscovery($this->root, TRUE, []$this->sitePath);
    $module_extensions = $extension_discovery->scan('module');
    $theme_extensions = $this->includeThemes() ? $extension_discovery->scan('theme') : [];
    $profile_extensions = $extension_discovery->scan('profile');
    $extensions = array_merge($module_extensions$theme_extensions$profile_extensions);

    // Limit to a single extension.     if ($extension) {
      $extensions = array_intersect_key($extensions[$extension => TRUE]);
    }

    $this->loadUpdateFiles($extensions);
  }

  protected function getProfiles($include_hidden = FALSE, $auto_select_distributions = TRUE) {
    // Build a list of all available profiles.     $listing = new ExtensionDiscovery(getcwd(), FALSE);
    $listing->setProfileDirectories([]);
    $profiles = [];
    $info_parser = new InfoParserDynamic(getcwd());
    foreach ($listing->scan('profile') as $profile) {
      $details = $info_parser->parse($profile->getPathname());
      // Don't show hidden profiles.       if (!$include_hidden && !empty($details['hidden'])) {
        continue;
      }
      // Determine the name of the profile; default to the internal name if none       // is specified.

    return FALSE;
  }

  /** * Returns all available extensions. * * @return \Drupal\Core\Extension\Extension[] * An array of Extension objects, keyed by extension name. */
  protected function getExtensions() {
    $listing = new ExtensionDiscovery($this->root);
    // Ensure that tests in all profiles are discovered.     $listing->setProfileDirectories([]);
    $extensions = $listing->scan('module', TRUE);
    $extensions += $listing->scan('profile', TRUE);
    $extensions += $listing->scan('theme', TRUE);
    return $extensions;
  }

}

  protected function getAllFolders() {
    if (!isset($this->folders)) {
      $this->folders = [];
      $this->folders += $this->getCoreNames();
      // Perform an ExtensionDiscovery scan as we cannot use       // \Drupal\Core\Extension\ExtensionList::getPath() yet because the system       // module may not yet be enabled during install.       // @todo Remove as part of https://www.drupal.org/node/2186491       $listing = new ExtensionDiscovery(\Drupal::root());
      if ($profile = \Drupal::installProfile()) {
        $profile_list = $listing->scan('profile');
        if (isset($profile_list[$profile])) {
          // Prime the \Drupal\Core\Extension\ExtensionList::getPathname static           // cache with the profile info file location so we can use           // \Drupal\Core\Extension\ExtensionList::getPath() on the active           // profile during the module scan.           // @todo Remove as part of https://www.drupal.org/node/2186491           /** @var \Drupal\Core\Extension\ProfileExtensionList $profile_extension_list */
          $profile_extension_list = \Drupal::service('extension.list.profile');
          $profile_extension_list->setPathname($profile$profile_list[$profile]->getPathname());
          
'test_missing_base_theme.theme' => file_get_contents(DRUPAL_ROOT . '/core/tests/fixtures/test_missing_base_theme/test_missing_base_theme.theme'),
        ],
      ],
    ]$vfs_root);
  }

  /** * Tests exception is thrown. */
  public function testMissingBaseThemeException() {
    $this->container->get('extension.list.theme')
      ->setExtensionDiscovery(new ExtensionDiscovery('vfs://core'));

    $this->expectException(InfoParserException::class);
    $this->expectExceptionMessage('Missing required key ("base theme") in themes/test_missing_base_theme/test_missing_base_theme.info.yml, see https://www.drupal.org/node/3066038');
    $this->themeInstaller->install(['test_missing_base_theme']);
  }

}

/** * Test theme extension list class. */
    // different places in the filesystem. Without that, the test has no     // meaning, so assert their presence first.     foreach ($expected_directories as $module => $directories) {
      foreach ($directories as $directory) {
        $filename = "$directory/$module/$module.info.yml";
        $this->assertFileExists($this->root . '/' . $filename);
      }
    }

    // Now scan the directories and check that the files take precedence as     // expected.     $listing = new ExtensionDiscovery($this->root);
    $listing->setProfileDirectories(['core/profiles/testing']);
    $files = $listing->scan('module');
    foreach ($expected_directories as $module => $directories) {
      $expected_directory = array_shift($directories);
      $expected_uri = "$expected_directory/$module/$module.info.yml";
      $this->assertEquals($expected_uri$files[$module]->getPathname()new FormattableMarkup('Module @actual was found at @expected.', ['@actual' => $files[$module]->getPathname(), '@expected' => $expected_uri]));
    }
  }

  /** * Tests that directories matching file_scan_ignore_directories are ignored. */
protected $availableThemes;

  /** * {@inheritdoc} */
  protected function setUp(): void {
    parent::setUp();
    // Theme settings rely on System module's system.theme.global configuration.     $this->installConfig(['system']);

    if (!isset($this->availableThemes)) {
      $discovery = new ExtensionDiscovery($this->root);
      $this->availableThemes = $discovery->scan('theme');
    }
  }

  /** * Tests that $theme.settings are imported and used as default theme settings. */
  public function testDefaultConfig() {
    $name = 'test_basetheme';
    $path = $this->availableThemes[$name]->getPath();
    $this->assertFileExists("$path/" . InstallStorage::CONFIG_INSTALL_DIRECTORY . "/$name.settings.yml");
    

  protected $xssLabel = "string with <em>HTML</em> and <script>alert('JS');</script>";

  /** * {@inheritdoc} */
  protected function setUp(): void {
    parent::setUp();

    // Install all available non-testing themes.     $listing = new ExtensionDiscovery(\Drupal::root());
    $this->themes = $listing->scan('theme', FALSE);
    /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
    $theme_data = \Drupal::service('theme_handler')->rebuildThemeData();
    foreach (array_keys($this->themes) as $theme) {
      // Skip obsolete and deprecated themes.       $info = $theme_data[$theme]->info;
      if ($info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER] === ExtensionLifecycle::OBSOLETE || $info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER] === ExtensionLifecycle::DEPRECATED) {
        unset($this->themes[$theme]);
      }
    }
    \Drupal::service('theme_installer')->install(array_keys($this->themes));

    
$this->moduleHandler = $module_handler;
    $this->state = $state;
    $this->installProfile = $install_profile;
  }

  /** * Returns the extension discovery. * * @return \Drupal\Core\Extension\ExtensionDiscovery */
  protected function getExtensionDiscovery() {
    return new ExtensionDiscovery($this->root);
  }

  /** * Resets the stored extension list. * * We don't reset statically added filenames, as it is a static cache which * logically can't change. This is done for performance reasons of the * installer. * * @return $this */
  
// Make a list of required modules.     $required_modules = [];
    foreach ($annotations as $requirement) {
      if (str_starts_with($requirement, 'module ')) {
        $required_modules[] = trim(str_replace('module ', '', $requirement));
      }
    }

    // If there are required modules, check if they're available.     if (!empty($required_modules)) {
      // Scan for modules.       $discovery = new ExtensionDiscovery($root, FALSE);
      $discovery->setProfileDirectories([]);
      $list = array_keys($discovery->scan('module'));
      $not_available = array_diff($required_modules$list);
      if (!empty($not_available)) {
        throw new SkippedTestError('Required modules: ' . implode(', ', $not_available));
      }
    }
  }

}

  protected function moduleData($module) {
    if (!$this->moduleData) {
      // First, find profiles.       $listing = new ExtensionDiscovery($this->root);
      $listing->setProfileDirectories([]);
      $all_profiles = $listing->scan('profile');
      $profiles = array_intersect_key($all_profiles$this->moduleList);

      $profile_directories = array_map(function DExtension $profile) {
        return $profile->getPath();
      }$profiles);
      $listing->setProfileDirectories($profile_directories);

      // Now find modules.       $this->moduleData = $profiles + $listing->scan('module');
    }
if (!empty($property_definitions)) {
        $message = sprintf("%s property %s found in %s", $plugin_id$property$properties);
        $this->assertArrayHasKey($property$class::propertyDefinitions($storage_definition)$message);
      }
    }
  }

  /** * Enable all core modules. */
  protected function enableAllCoreModules() {
    $listing = new ExtensionDiscovery($this->root);
    $module_list = $listing->scan('module', FALSE);
    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
    $module_handler = $this->container->get('module_handler');
    $module_list = array_filter(array_keys($module_list)function D$module) use ($module_handler$module_list) {
      return !$module_handler->moduleExists($module) && substr($module_list[$module]->getPath(), 0, 4) === 'core';
    });
    $this->enableModules($module_list);
  }

}

  protected function getAllFolders() {
    if (!isset($this->folders)) {
      $this->folders = [];
      $this->folders += $this->getCoreNames();

      $extensions = $this->configStorage->read('core.extension');
      // @todo Remove this scan as part of https://www.drupal.org/node/2186491       $listing = new ExtensionDiscovery(\Drupal::root());
      if (!empty($extensions['module'])) {
        $modules = $extensions['module'];
        // Remove the install profile as this is handled later.         unset($modules[$this->installProfile]);
        $profile_list = $listing->scan('profile');
        if ($this->installProfile && isset($profile_list[$this->installProfile])) {
          // Prime the \Drupal\Core\Extension\ExtensionList::getPathname()           // static cache with the profile info file location so we can use           // ExtensionList::getPath() on the active profile during the module           // scan.           // @todo Remove as part of https://www.drupal.org/node/2186491


  /** * Gets theme info using the theme name. * * @param string $theme * The machine name of the theme. * * @return \Drupal\Core\Extension\Extension|null */
  private function getThemeInfo(string $theme): ? Extension {
    $extension_discovery = new ExtensionDiscovery($this->root, FALSE, []);
    $themes = $extension_discovery->scan('theme');

    if (!isset($themes[$theme])) {
      return NULL;
    }

    return $themes[$theme];
  }

  /** * Checks if the theme is a starterkit theme. * * @param \Drupal\Core\Extension\Extension $theme * The theme extension. * * @return bool */
// Set up the file system.     $filesystem = [];
    $files_by_type_and_name_expected = $this->populateFilesystemStructure($filesystem);

    $vfs = vfsStream::setup('root', NULL, $filesystem);
    $root = $vfs->url();

    $this->assertFileExists($root . '/core/modules/system/system.module');
    $this->assertFileExists($root . '/core/modules/system/system.info.yml');

    // Create an ExtensionDiscovery with $root.     $extension_discovery = new ExtensionDiscovery($root, FALSE, NULL, 'sites/default');

    /** @var \Drupal\Core\Extension\Extension[][] $extensions_by_type */
    $extensions_by_type = [];
    $files_by_type_and_name = [];
    foreach (['profile', 'module', 'theme', 'theme_engine'] as $type) {
      $extensions_by_type[$type] = $extension_discovery->scan($type, FALSE);
      foreach ($extensions_by_type[$type] as $name => $extension) {
        $files_by_type_and_name[$type][$name] = $extension->getPathname();
      }
      if ($type === 'profile') {
        // Set profile directories for discovery of the other extension types.
Home | Imprint | This part of the site doesn't use cookies.