From 2c51074d59aee9ae21ee4c8dce41b1453580485e Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 7 Mar 2014 11:18:08 +0000
Subject: [PATCH] Issue #2210197 by sun, longwave: Remove public access to
 Extension::$type, ::$name, ::$filename.

---
 core/includes/install.core.inc                | 18 ++++++------
 core/includes/install.inc                     |  6 ++--
 core/includes/module.inc                      |  2 +-
 core/includes/theme.inc                       | 12 ++++----
 core/lib/Drupal/Core/DrupalKernel.php         |  6 ++--
 core/lib/Drupal/Core/Extension/Extension.php  | 29 ++-----------------
 .../Core/Extension/ExtensionDiscovery.php     | 14 ++++-----
 .../Drupal/Core/Extension/ModuleHandler.php   |  6 ++--
 .../Drupal/Core/Extension/ThemeHandler.php    |  5 ++--
 .../Drupal/Core/Template/TwigEnvironment.php  | 13 +++++----
 core/lib/Drupal/Core/Theme/Registry.php       | 18 ++++++------
 core/lib/Drupal/Core/Utility/ProjectInfo.php  | 15 +++++-----
 .../ConfigMapperManager.php                   |  2 +-
 core/modules/field/field.module               |  5 ++--
 .../modules/locale_test/locale_test.module    |  6 ++--
 .../locale_test_translate.module              |  6 ++--
 .../system/Controller/SystemController.php    | 22 +++++++-------
 .../Drupal/system/Form/ModulesListForm.php    | 15 +++++-----
 .../system/Form/ModulesUninstallForm.php      | 16 +++++-----
 .../Drupal/system/Form/ThemeSettingsForm.php  |  2 +-
 .../Tests/Bootstrap/GetFilenameUnitTest.php   |  8 ++---
 .../system/Tests/Common/SystemListingTest.php |  8 ++---
 core/modules/system/system.admin.inc          |  9 +++---
 core/modules/system/system.api.php            | 17 +++++------
 core/modules/system/system.module             |  9 ++----
 .../modules/module_test/module_test.module    | 22 +++++++-------
 .../modules/system_test/system_test.module    | 13 +++++----
 .../theme_page_test/theme_page_test.module    |  4 ++-
 .../modules/update_test/update_test.module    |  5 ++--
 .../views/lib/Drupal/views/ViewExecutable.php |  4 +--
 .../Tests/Core/Extension/ThemeHandlerTest.php | 22 +++++++-------
 .../Drupal/Tests/Core/Theme/RegistryTest.php  |  8 ++---
 .../engines/phptemplate/phptemplate.engine    |  9 +++---
 core/themes/engines/twig/twig.engine          |  9 +++---
 34 files changed, 172 insertions(+), 193 deletions(-)

diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 8d08d94528a5..f0e74e310dd9 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -835,7 +835,7 @@ function install_tasks($install_state) {
     // Load the profile install file, because it is not always loaded when
     // hook_install_tasks() is invoked (e.g. batch processing).
     $profile = $install_state['parameters']['profile'];
-    $profile_install_file = dirname($install_state['profiles'][$profile]->uri) . '/' . $profile . '.install';
+    $profile_install_file = $install_state['profiles'][$profile]->getPath() . '/' . $profile . '.install';
     if (file_exists($profile_install_file)) {
       include_once DRUPAL_ROOT . '/' . $profile_install_file;
     }
@@ -1351,19 +1351,19 @@ function _install_select_profile($profiles) {
   $request_params = \Drupal::request()->request;
   if (count($profiles) == 1) {
     $profile = array_pop($profiles);
-    return $profile->name;
+    return $profile->getName();
   }
   elseif ($request_params->has('profile') && ($profile = $request_params->get('profile')) && isset($profiles[$profile])) {
-    return $profiles[$profile]->name;
+    return $profiles[$profile]->getName();
   }
   // Check for a profile marked as "exclusive" and ensure that only one
   // profile is marked as such.
   $exclusive_profile = NULL;
   foreach ($profiles as $profile) {
-    $profile_info = install_profile_info($profile->name);
+    $profile_info = install_profile_info($profile->getName());
     if (!empty($profile_info['exclusive'])) {
       if (empty($exclusive_profile)) {
-        $exclusive_profile = $profile->name;
+        $exclusive_profile = $profile->getName();
       }
       else {
         // We found a second "exclusive" profile. There's no way to choose
@@ -1388,7 +1388,7 @@ function install_select_profile_form($form, &$form_state, $install_state) {
   $names = array();
 
   foreach ($install_state['profiles'] as $profile) {
-    $details = install_profile_info($profile->name);
+    $details = install_profile_info($profile->getName());
     // Skip this extension if its type is not profile.
     if (!isset($details['type']) || $details['type'] != 'profile') {
       continue;
@@ -1398,12 +1398,12 @@ function install_select_profile_form($form, &$form_state, $install_state) {
     if ($details['hidden'] === TRUE) {
       continue;
     }
-    $profiles[$profile->name] = $details;
+    $profiles[$profile->getName()] = $details;
 
     // Determine the name of the profile; default to file name if defined name
     // is unspecified.
-    $name = isset($details['name']) ? $details['name'] : $profile->name;
-    $names[$profile->name] = $name;
+    $name = isset($details['name']) ? $details['name'] : $profile->getName();
+    $names[$profile->getName()] = $name;
   }
 
   // Display radio buttons alphabetically by human-readable name, but always
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 74d8e3928a05..3630e07906e5 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -573,9 +573,7 @@ function drupal_verify_profile($install_state) {
   include_once __DIR__ . '/common.inc';
 
   $profile = $install_state['parameters']['profile'];
-  $profile_file = $install_state['profiles'][$profile]->uri;
-
-  if (!isset($profile) || !file_exists($profile_file)) {
+  if (!isset($profile) || !isset($install_state['profiles'][$profile])) {
     throw new Exception(install_no_profile_error());
   }
   $info = $install_state['profile_info'];
@@ -584,7 +582,7 @@ function drupal_verify_profile($install_state) {
   $listing = new ExtensionDiscovery();
   $present_modules = array();
   foreach ($listing->scan('module') as $present_module) {
-    $present_modules[] = $present_module->name;
+    $present_modules[] = $present_module->getName();
   }
 
   // The installation profile is also a module, which needs to be installed
diff --git a/core/includes/module.inc b/core/includes/module.inc
index e412598d4097..7bb0e3e0e280 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -63,7 +63,7 @@ function system_list($type) {
         $lists['filepaths'][] = array(
           'type' => 'theme',
           'name' => $name,
-          'filepath' => $theme->filename,
+          'filepath' => $theme->getPathname(),
         );
       }
     }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 1526113eafbf..213cd6ac0535 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -79,7 +79,7 @@
  */
 function drupal_theme_access($theme) {
   if ($theme instanceof Extension) {
-    $theme = $theme->name;
+    $theme = $theme->getName();
   }
   return \Drupal::service('access_check.theme')->checkAccess($theme);
 }
@@ -135,7 +135,7 @@ function _drupal_theme_initialize($theme, $base_theme = array()) {
   $theme_info = $theme;
   $base_theme_info = $base_theme;
 
-  $theme_path = dirname($theme->filename);
+  $theme_path = $theme->getPath();
 
   // Prepare stylesheets from this theme as well as all ancestor themes.
   // We work it this way so that we can have child themes override parent
@@ -155,7 +155,7 @@ function _drupal_theme_initialize($theme, $base_theme = array()) {
         }
       }
     }
-    $base_theme_path = dirname($base->filename);
+    $base_theme_path = $base->getPath();
     if (!empty($base->info['stylesheets-remove'])) {
       foreach ($base->info['stylesheets-remove'] as $basename) {
         $theme->stylesheets_remove[$basename] = $base_theme_path . '/' . $basename;
@@ -793,7 +793,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
   $theme_paths = array();
   foreach (list_themes() as $theme_info) {
     if (!empty($theme_info->base_theme)) {
-      $theme_paths[$theme_info->base_theme][$theme_info->name] = dirname($theme_info->filename);
+      $theme_paths[$theme_info->base_theme][$theme_info->getName()] = $theme_info->getPath();
     }
   }
   foreach ($theme_paths as $basetheme => $subthemes) {
@@ -955,7 +955,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
       if ($cache[$theme]->get('features.logo')) {
         $logo_path = $cache[$theme]->get('logo.path');
         if ($cache[$theme]->get('logo.use_default')) {
-          $cache[$theme]->set('logo.url', file_create_url(dirname($theme_object->filename) . '/logo.png'));
+          $cache[$theme]->set('logo.url', file_create_url($theme_object->getPath() . '/logo.png'));
         }
         elseif ($logo_path) {
           $cache[$theme]->set('logo.url', file_create_url($logo_path));
@@ -966,7 +966,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
       if ($cache[$theme]->get('features.favicon')) {
         $favicon_path = $cache[$theme]->get('favicon.path');
         if ($cache[$theme]->get('favicon.use_default')) {
-          if (file_exists($favicon = dirname($theme_object->filename) . '/favicon.ico')) {
+          if (file_exists($favicon = $theme_object->getPath() . '/favicon.ico')) {
             $cache[$theme]->set('favicon.url', file_create_url($favicon));
           }
           else {
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index a7631642e4a9..218e7da9434e 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -290,10 +290,8 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
    * @param $module
    *   The name of the module.
    *
-   * @return \stdClass|bool
-   *   Returns a stdClass object if the module data is found containing at
-   *   least an uri property with the module path, for example
-   *   core/modules/user/user.module.
+   * @return \Drupal\Core\Extension\Extension|bool
+   *   Returns an Extension object if the module is found, FALSE otherwise.
    */
   protected function moduleData($module) {
     if (!$this->moduleData) {
diff --git a/core/lib/Drupal/Core/Extension/Extension.php b/core/lib/Drupal/Core/Extension/Extension.php
index 188350c72b6e..97f3fa303f4d 100644
--- a/core/lib/Drupal/Core/Extension/Extension.php
+++ b/core/lib/Drupal/Core/Extension/Extension.php
@@ -15,11 +15,9 @@ class Extension implements \Serializable {
   /**
    * The type of the extension (e.g., 'module').
    *
-   * @todo Replace all uses of $type with getType() method.
-   *
    * @var string
    */
-  public $type;
+  protected $type;
 
   /**
    * The relative pathname of the extension (e.g., 'core/modules/node/node.info.yml').
@@ -28,15 +26,6 @@ class Extension implements \Serializable {
    */
   protected $pathname;
 
-  /**
-   * The internal name of the extension (e.g., 'node').
-   *
-   * @todo Replace all uses of $name with getName() method.
-   *
-   * @var string
-   */
-  public $name;
-
   /**
    * The relative pathname of the main extension file (e.g., 'core/modules/node/node.module').
    *
@@ -50,21 +39,9 @@ class Extension implements \Serializable {
   /**
    * The filename of the main extension file (e.g., 'node.module').
    *
-   * Note that this is not necessarily a filename but a pathname and also not
-   * necessarily the filename of the info file. Due to legacy code and property
-   * value overloading, it is either the filename of the main extension file or
-   * the relative pathname of the main extension file (== $uri), depending on
-   * whether the object has been post-processed or not.
-   *
-   * @see _system_rebuild_module_data()
-   * @see \Drupal\Core\Extension\ThemeHandler::rebuildThemeData()
-   *
-   * @todo Remove this property and do not require .module/.profile files.
-   * @see https://drupal.org/node/340723
-   *
    * @var string
    */
-  public $filename;
+  protected $filename;
 
   /**
    * An SplFileInfo instance for the extension's info file.
@@ -90,7 +67,6 @@ public function __construct($type, $pathname, $filename) {
     $this->type = $type;
     $this->pathname = $pathname;
     // Set legacy public properties.
-    $this->name = basename($pathname, '.info.yml');
     $this->filename = $filename;
     $this->uri = dirname($pathname) . '/' . $filename;
   }
@@ -207,7 +183,6 @@ public function unserialize($data) {
     // @todo Remove these properties and do not require .module/.profile files.
     // @see https://drupal.org/node/340723
     // @see Extension::$filename
-    $this->name = basename($data['pathname'], '.info.yml');
     $this->uri = dirname($data['pathname']) . '/' . $data['filename'];
     $this->filename = $data['filename'];
 
diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
index 2d35d00c2644..aba0c2fbb9e1 100644
--- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
+++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
@@ -278,14 +278,14 @@ protected function process(array $all_files) {
     // e.g. new modules were introduced in core while older contrib modules with
     // the same name still exist in a later search path.
     foreach ($all_files as $file) {
-      if (isset($files[$file->name])) {
+      if (isset($files[$file->getName()])) {
         // Skip the extension if it is incompatible with Drupal core.
         $info = $this->getInfoParser()->parse($file->getPathname());
         if (!isset($info['core']) || $info['core'] != \Drupal::CORE_COMPATIBILITY) {
           continue;
         }
       }
-      $files[$file->name] = $file;
+      $files[$file->getName()] = $file;
     }
     return $files;
   }
@@ -366,16 +366,12 @@ protected function scanDirectory($dir, $include_tests) {
       $name = $fileinfo->getBasename('.info.yml');
       $pathname = $dir_prefix . $fileinfo->getSubPathname();
 
-      // Supply main extension filename being used throughout Drupal.
-      // For themes, the filename is the info file itself.
-      if ($type == 'theme') {
-        $filename = $fileinfo->getFilename();
-      }
+      // Determine whether the extension has a main extension file.
       // For theme engines, the file extension is .engine.
-      elseif ($type == 'theme_engine') {
+      if ($type == 'theme_engine') {
         $filename = $name . '.engine';
       }
-      // Otherwise, it is .module/.profile; i.e., the extension type.
+      // For profiles/modules/themes, it is the extension type.
       else {
         $filename = $name . '.' . $type;
       }
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 1dd6f21ea104..89cd73e014ab 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -145,11 +145,11 @@ public function setModuleList(array $module_list = array()) {
    */
   public function buildModuleDependencies(array $modules) {
     foreach ($modules as $module) {
-      $graph[$module->name]['edges'] = array();
+      $graph[$module->getName()]['edges'] = array();
       if (isset($module->info['dependencies']) && is_array($module->info['dependencies'])) {
         foreach ($module->info['dependencies'] as $dependency) {
           $dependency_data = static::parseDependency($dependency);
-          $graph[$module->name]['edges'][$dependency_data['name']] = $dependency_data;
+          $graph[$module->getName()]['edges'][$dependency_data['name']] = $dependency_data;
         }
       }
     }
@@ -382,7 +382,7 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
       if (isset($theme)) {
         $theme_keys = array();
         foreach ($base_theme_info as $base) {
-          $theme_keys[] = $base->name;
+          $theme_keys[] = $base->getName();
         }
         $theme_keys[] = $theme;
         foreach ($theme_keys as $theme_key) {
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index e2bf62e93c36..060d796b29fd 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -220,7 +220,7 @@ public function listInfo() {
         if (!isset($theme->status)) {
           $theme->status = 0;
         }
-        $this->list[$theme->name] = $theme;
+        $this->list[$theme->getName()] = $theme;
       }
     }
     return $this->list;
@@ -271,7 +271,6 @@ public function rebuildThemeData() {
     $sub_themes = array();
     // Read info files for each theme.
     foreach ($themes as $key => $theme) {
-      $theme->filename = $theme->uri;
       $theme->info = $this->infoParser->parse($theme->getPathname()) + $defaults;
 
       // Add the info file modification time, so it becomes available for
@@ -292,7 +291,7 @@ public function rebuildThemeData() {
       $engine = $theme->info['engine'];
       if (isset($engines[$engine])) {
         $theme->owner = $engines[$engine]->uri;
-        $theme->prefix = $engines[$engine]->name;
+        $theme->prefix = $engines[$engine]->getName();
       }
 
       // Prefix stylesheets, scripts, and screenshot with theme path.
diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php
index 2bbf3c9a811b..06a8dcc1bb56 100644
--- a/core/lib/Drupal/Core/Template/TwigEnvironment.php
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -39,13 +39,16 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, $options = arr
     $this->cache_object = \Drupal::cache();
 
     // Set twig path namespace for themes and modules.
-    $namespaces = $module_handler->getModuleList();
-    foreach ($theme_handler->listInfo() as $theme => $info) {
-      $namespaces[$theme] = $info->filename;
+    $namespaces = array();
+    foreach ($module_handler->getModuleList() as $name => $filename) {
+      $namespaces[$name] = dirname($filename);
+    }
+    foreach ($theme_handler->listInfo() as $name => $extension) {
+      $namespaces[$name] = $extension->getPath();
     }
 
-    foreach ($namespaces as $name => $filename) {
-      $templatesDirectory = dirname($filename) . '/templates';
+    foreach ($namespaces as $name => $path) {
+      $templatesDirectory = $path . '/templates';
       if (file_exists($templatesDirectory)) {
         $loader->addPath($templatesDirectory, $name);
       }
diff --git a/core/lib/Drupal/Core/Theme/Registry.php b/core/lib/Drupal/Core/Theme/Registry.php
index 1d3cb22960a2..e84b33b9b4d4 100644
--- a/core/lib/Drupal/Core/Theme/Registry.php
+++ b/core/lib/Drupal/Core/Theme/Registry.php
@@ -154,7 +154,7 @@ protected function init($theme_name = NULL) {
       }
       // #2: The testing framework only cares for the global $theme variable at
       // this point. Cope with that.
-      if ($GLOBALS['theme'] != $GLOBALS['theme_info']->name) {
+      if ($GLOBALS['theme'] != $GLOBALS['theme_info']->getName()) {
         unset($this->runtimeRegistry);
         unset($this->registry);
         $this->initializeTheme();
@@ -207,7 +207,7 @@ public function get() {
     if (isset($this->registry)) {
       return $this->registry;
     }
-    if ($cache = $this->cache->get('theme_registry:' . $this->theme->name)) {
+    if ($cache = $this->cache->get('theme_registry:' . $this->theme->getName())) {
       $this->registry = $cache->data;
     }
     else {
@@ -230,7 +230,7 @@ public function get() {
    */
   public function getRuntime() {
     if (!isset($this->runtimeRegistry)) {
-      $this->runtimeRegistry = new ThemeRegistry('theme_registry:runtime:' . $this->theme->name, $this->cache, $this->lock, array('theme_registry' => TRUE), $this->moduleHandler->isLoaded());
+      $this->runtimeRegistry = new ThemeRegistry('theme_registry:runtime:' . $this->theme->getName(), $this->cache, $this->lock, array('theme_registry' => TRUE), $this->moduleHandler->isLoaded());
     }
     return $this->runtimeRegistry;
   }
@@ -239,7 +239,7 @@ public function getRuntime() {
    * Persists the theme registry in the cache backend.
    */
   protected function setCache() {
-    $this->cache->set('theme_registry:' . $this->theme->name, $this->registry, Cache::PERMANENT, array('theme_registry' => TRUE));
+    $this->cache->set('theme_registry:' . $this->theme->getName(), $this->registry, Cache::PERMANENT, array('theme_registry' => TRUE));
   }
 
   /**
@@ -319,20 +319,20 @@ protected function build() {
     // Process each base theme.
     foreach ($this->baseThemes as $base) {
       // If the base theme uses a theme engine, process its hooks.
-      $base_path = dirname($base->filename);
+      $base_path = $base->getPath();
       if ($this->engine) {
-        $this->processExtension($cache, $this->engine, 'base_theme_engine', $base->name, $base_path);
+        $this->processExtension($cache, $this->engine, 'base_theme_engine', $base->getName(), $base_path);
       }
-      $this->processExtension($cache, $base->name, 'base_theme', $base->name, $base_path);
+      $this->processExtension($cache, $base->getName(), 'base_theme', $base->getName(), $base_path);
     }
 
     // And then the same thing, but for the theme.
     if ($this->engine) {
-      $this->processExtension($cache, $this->engine, 'theme_engine', $this->theme->name, dirname($this->theme->filename));
+      $this->processExtension($cache, $this->engine, 'theme_engine', $this->theme->getName(), $this->theme->getPath());
     }
 
     // Finally, hooks provided by the theme itself.
-    $this->processExtension($cache, $this->theme->name, 'theme', $this->theme->name, dirname($this->theme->filename));
+    $this->processExtension($cache, $this->theme->getName(), 'theme', $this->theme->getName(), $this->theme->getPath());
 
     // Let modules alter the registry.
     $this->moduleHandler->alter('theme_registry', $cache);
diff --git a/core/lib/Drupal/Core/Utility/ProjectInfo.php b/core/lib/Drupal/Core/Utility/ProjectInfo.php
index e109c784d5bc..2a49c8c37551 100644
--- a/core/lib/Drupal/Core/Utility/ProjectInfo.php
+++ b/core/lib/Drupal/Core/Utility/ProjectInfo.php
@@ -9,6 +9,8 @@
 
 namespace Drupal\Core\Utility;
 
+use Drupal\Core\Extension\Extension;
+
 /**
  * Performs operations on drupal.org project data.
  */
@@ -94,8 +96,7 @@ function processInfoList(array &$projects, array $list, $project_type, $status,
       // which is left alone by tar and correctly set to the time the .info.yml
       // file was unpacked.
       if (!isset($file->info['_info_file_ctime'])) {
-        $info_filename = dirname($file->uri) . '/' . $file->name . '.info.yml';
-        $file->info['_info_file_ctime'] = filectime($info_filename);
+        $file->info['_info_file_ctime'] = $file->getCTime();
       }
 
       if (!isset($file->info['datestamp'])) {
@@ -142,7 +143,7 @@ function processInfoList(array &$projects, array $list, $project_type, $status,
           // not bloat our RAM usage needlessly.
           'info' => $this->filterProjectInfo($file->info, $additional_whitelist),
           'datestamp' => $file->info['datestamp'],
-          'includes' => array($file->name => $file->info['name']),
+          'includes' => array($file->getName() => $file->info['name']),
           'project_type' => $project_display_type,
           'project_status' => $status,
           'sub_themes' => $sub_themes,
@@ -155,7 +156,7 @@ function processInfoList(array &$projects, array $list, $project_type, $status,
         // $project_display_type). This prevents listing all the disabled
         // modules included with an enabled project if we happen to be checking
         // for disabled modules, too.
-        $projects[$project_name]['includes'][$file->name] = $file->info['name'];
+        $projects[$project_name]['includes'][$file->getName()] = $file->info['name'];
         $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
         $projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']);
         if (!empty($sub_themes)) {
@@ -170,7 +171,7 @@ function processInfoList(array &$projects, array $list, $project_type, $status,
         // does not, it means we're processing a disabled module or theme that
         // belongs to a project that has some enabled code. In this case, we add
         // the disabled thing into a separate array for separate display.
-        $projects[$project_name]['disabled'][$file->name] = $file->info['name'];
+        $projects[$project_name]['disabled'][$file->getName()] = $file->info['name'];
       }
     }
   }
@@ -184,12 +185,12 @@ function processInfoList(array &$projects, array $list, $project_type, $status,
    * @return string
    *   The canonical project short name.
    */
-  function getProjectName($file) {
+  function getProjectName(Extension $file) {
     $project_name = '';
     if (isset($file->info['project'])) {
       $project_name = $file->info['project'];
     }
-    elseif (isset($file->filename) && (strpos($file->filename, 'core/modules') === 0)) {
+    elseif (strpos($file->getPath(), 'core/modules') === 0) {
       $project_name = 'drupal';
     }
     return $project_name;
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php b/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
index 0cbcba42176d..122738207b10 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
@@ -72,7 +72,7 @@ public function __construct(CacheBackendInterface $cache_backend, LanguageManage
       $directories[$module] = dirname($filename);
     }
     foreach ($theme_handler->listInfo() as $theme) {
-      $directories[$theme->name] = dirname($theme->filename);
+      $directories[$theme->getName()] = $theme->getPath();
     }
 
     // Check for files named MODULE.config_translation.yml and
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 734eb7c11286..f0e280c6912e 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -8,6 +8,7 @@
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Template\Attribute;
 use Drupal\entity\Entity\EntityViewDisplay;
 use Drupal\field\Field;
@@ -157,11 +158,11 @@ function field_cron() {
  * Goes through a list of all modules that provide a field type and makes them
  * required if there are any active fields of that type.
  */
-function field_system_info_alter(&$info, $file, $type) {
+function field_system_info_alter(&$info, Extension $file, $type) {
   // It is not safe to call entity_load_multiple_by_properties() during
   // maintenance mode.
   if ($type == 'module' && !defined('MAINTENANCE_MODE')) {
-    $fields = entity_load_multiple_by_properties('field_config', array('module' => $file->name, 'include_deleted' => TRUE));
+    $fields = entity_load_multiple_by_properties('field_config', array('module' => $file->getName(), 'include_deleted' => TRUE));
     if ($fields) {
       $info['required'] = TRUE;
 
diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.module b/core/modules/locale/tests/modules/locale_test/locale_test.module
index 89616a5eee49..4db96b83efd3 100644
--- a/core/modules/locale/tests/modules/locale_test/locale_test.module
+++ b/core/modules/locale/tests/modules/locale_test/locale_test.module
@@ -4,6 +4,8 @@
  * @file
  * Simulate a custom module with a local po file.
  */
+
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\StreamWrapper\PublicStream;
 
 /**
@@ -12,13 +14,13 @@
  * Make the test scripts to be believe this is not a hidden test module, but
  * a regular custom module.
  */
-function locale_test_system_info_alter(&$info, $file, $type) {
+function locale_test_system_info_alter(&$info, Extension $file, $type) {
   // Only modify the system info if required.
   // By default the locale_test modules are hidden and have a project specified.
   // To test the module detection process by locale_project_list() the
   // test modules should mimic a custom module. I.e. be non-hidden.
   if (\Drupal::state()->get('locale.test_system_info_alter')) {
-    if ($file->name == 'locale_test' || $file->name == 'locale_test_translate') {
+    if ($file->getName() == 'locale_test' || $file->getName() == 'locale_test_translate') {
       // Don't hide the module.
       $info['hidden'] = FALSE;
     }
diff --git a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
index 498099fc1f5a..e55d4dc486eb 100644
--- a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
+++ b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
@@ -5,6 +5,8 @@
  * Simulates a custom module with a local po file.
  */
 
+use Drupal\Core\Extension\Extension;
+
 /**
  * Implements hook_system_info_alter().
  *
@@ -12,8 +14,8 @@
  * (not hidden) module. This hook implementation changes the .info.yml data by
  * setting the hidden status to FALSE.
  */
-function locale_test_translate_system_info_alter(&$info, $file, $type) {
-  if ($file->name == 'locale_test_translate') {
+function locale_test_translate_system_info_alter(&$info, Extension $file, $type) {
+  if ($file->getName() == 'locale_test_translate') {
     // Don't hide the module.
     $info['hidden'] = FALSE;
   }
diff --git a/core/modules/system/lib/Drupal/system/Controller/SystemController.php b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
index 5f55d6e885f5..5635b1e37e17 100644
--- a/core/modules/system/lib/Drupal/system/Controller/SystemController.php
+++ b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
@@ -200,17 +200,17 @@ public function themesPage() {
       if (!empty($theme->info['hidden'])) {
         continue;
       }
-      $theme->is_default = ($theme->name == $theme_default);
+      $theme->is_default = ($theme->getName() == $theme_default);
 
       // Identify theme screenshot.
       $theme->screenshot = NULL;
       // Create a list which includes the current theme and all its base themes.
-      if (isset($themes[$theme->name]->base_themes)) {
-        $theme_keys = array_keys($themes[$theme->name]->base_themes);
-        $theme_keys[] = $theme->name;
+      if (isset($themes[$theme->getName()]->base_themes)) {
+        $theme_keys = array_keys($themes[$theme->getName()]->base_themes);
+        $theme_keys[] = $theme->getName();
       }
       else {
-        $theme_keys = array($theme->name);
+        $theme_keys = array($theme->getName());
       }
       // Look for a screenshot in the current theme or in its closest ancestor.
       foreach (array_reverse($theme_keys) as $theme_key) {
@@ -239,18 +239,18 @@ public function themesPage() {
       $theme->operations = array();
       if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
         // Create the operations links.
-        $query['theme'] = $theme->name;
-        if ($this->themeAccess->checkAccess($theme->name)) {
+        $query['theme'] = $theme->getName();
+        if ($this->themeAccess->checkAccess($theme->getName())) {
           $theme->operations[] = array(
             'title' => $this->t('Settings'),
             'route_name' => 'system.theme_settings_theme',
-            'route_parameters' => array('theme' => $theme->name),
+            'route_parameters' => array('theme' => $theme->getName()),
             'attributes' => array('title' => $this->t('Settings for !theme theme', array('!theme' => $theme->info['name']))),
           );
         }
         if (!empty($theme->status)) {
           if (!$theme->is_default) {
-            if ($theme->name != $admin_theme) {
+            if ($theme->getName() != $admin_theme) {
               $theme->operations[] = array(
                 'title' => $this->t('Disable'),
                 'route_name' => 'system.theme_disable',
@@ -265,7 +265,7 @@ public function themesPage() {
               'attributes' => array('title' => $this->t('Set !theme as default theme', array('!theme' => $theme->info['name']))),
             );
           }
-          $admin_theme_options[$theme->name] = $theme->info['name'];
+          $admin_theme_options[$theme->getName()] = $theme->info['name'];
         }
         else {
           $theme->operations[] = array(
@@ -290,7 +290,7 @@ public function themesPage() {
         $theme->classes[] = 'theme-default';
         $theme->notes[] = $this->t('default theme');
       }
-      if ($theme->name == $admin_theme || ($theme->is_default && $admin_theme == '0')) {
+      if ($theme->getName() == $admin_theme || ($theme->is_default && $admin_theme == '0')) {
         $theme->classes[] = 'theme-admin';
         $theme->notes[] = $this->t('admin theme');
       }
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
index 15d5eafedda1..efc36a5ca0a3 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
 use Drupal\Core\Entity\Query\QueryFactoryInterface;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
@@ -176,14 +177,14 @@ public function buildForm(array $form, array &$form_state) {
    *
    * @param array $modules
    *   The list existing modules.
-   * @param object $module
+   * @param \Drupal\Core\Extension\Extension $module
    *   The module for which to build the form row.
    * @param $distribution
    *
    * @return array
    *   The form row for the given module.
    */
-  protected function buildRow(array $modules, $module, $distribution) {
+  protected function buildRow(array $modules, Extension $module, $distribution) {
     // Set the basic properties.
     $row['#required'] = array();
     $row['#requires'] = array();
@@ -199,12 +200,12 @@ protected function buildRow(array $modules, $module, $distribution) {
 
     // Generate link for module's help page, if there is one.
     $row['links']['help'] = array();
-    if ($help && $module->status && in_array($module->name, $this->moduleHandler->getImplementations('help'))) {
-      if ($this->moduleHandler->invoke($module->name, 'help', array("admin/help#$module->name", $help))) {
+    if ($help && $module->status && in_array($module->getName(), $this->moduleHandler->getImplementations('help'))) {
+      if ($this->moduleHandler->invoke($module->getName(), 'help', array('admin/help#' . $module->getName(), $help))) {
         $row['links']['help'] = array(
           '#type' => 'link',
           '#title' => $this->t('Help'),
-          '#href' => "admin/help/$module->name",
+          '#href' => 'admin/help/' . $module->getName(),
           '#options' => array('attributes' => array('class' =>  array('module-link', 'module-link-help'), 'title' => $this->t('Help'))),
         );
       }
@@ -212,12 +213,12 @@ protected function buildRow(array $modules, $module, $distribution) {
 
     // Generate link for module's permission, if the user has access to it.
     $row['links']['permissions'] = array();
-    if ($module->status && user_access('administer permissions') && in_array($module->name, $this->moduleHandler->getImplementations('permission'))) {
+    if ($module->status && user_access('administer permissions') && in_array($module->getName(), $this->moduleHandler->getImplementations('permission'))) {
       $row['links']['permissions'] = array(
         '#type' => 'link',
         '#title' => $this->t('Permissions'),
         '#href' => 'admin/people/permissions',
-        '#options' => array('fragment' => 'module-' . $module->name, 'attributes' => array('class' => array('module-link', 'module-link-permissions'), 'title' => $this->t('Configure permissions'))),
+        '#options' => array('fragment' => 'module-' . $module->getName(), 'attributes' => array('class' => array('module-link', 'module-link-permissions'), 'title' => $this->t('Configure permissions'))),
       );
     }
 
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
index 93bf906006d1..219653f531ef 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
@@ -71,7 +71,7 @@ public function buildForm(array $form, array &$form_state) {
     // Get a list of disabled, installed modules.
     $modules = system_rebuild_module_data();
     $uninstallable = array_filter($modules, function ($module) use ($modules) {
-      return empty($modules[$module->name]->info['required']) && drupal_get_installed_schema_version($module->name) > SCHEMA_UNINSTALLED;
+      return empty($modules[$module->getName()]->info['required']) && drupal_get_installed_schema_version($module->getName()) > SCHEMA_UNINSTALLED;
     });
 
     $form['modules'] = array();
@@ -89,12 +89,12 @@ public function buildForm(array $form, array &$form_state) {
 
     $form['uninstall'] = array('#tree' => TRUE);
     foreach ($uninstallable as $module) {
-      $name = $module->info['name'] ?: $module->name;
-      $form['modules'][$module->name]['#module_name'] = $name;
-      $form['modules'][$module->name]['name']['#markup'] = $name;
-      $form['modules'][$module->name]['description']['#markup'] = $this->t($module->info['description']);
+      $name = $module->info['name'] ?: $module->getName();
+      $form['modules'][$module->getName()]['#module_name'] = $name;
+      $form['modules'][$module->getName()]['name']['#markup'] = $name;
+      $form['modules'][$module->getName()]['description']['#markup'] = $this->t($module->info['description']);
 
-      $form['uninstall'][$module->name] = array(
+      $form['uninstall'][$module->getName()] = array(
         '#type' => 'checkbox',
         '#title' => $this->t('Uninstall @module module', array('@module' => $name)),
         '#title_display' => 'invisible',
@@ -106,8 +106,8 @@ public function buildForm(array $form, array &$form_state) {
       foreach (array_keys($module->required_by) as $dependent) {
         if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {
           $name = isset($modules[$dependent]->info['name']) ? $modules[$dependent]->info['name'] : $dependent;
-          $form['modules'][$module->name]['#required_by'][] = $name;
-          $form['uninstall'][$module->name]['#disabled'] = TRUE;
+          $form['modules'][$module->getName()]['#required_by'][] = $name;
+          $form['uninstall'][$module->getName()]['#disabled'] = TRUE;
         }
       }
     }
diff --git a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
index 2f910ae02be6..9459aad954a0 100644
--- a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php
@@ -288,7 +288,7 @@ public function buildForm(array $form, array &$form_state, $theme = '') {
       // Process the theme and all its base themes.
       foreach ($theme_keys as $theme) {
         // Include the theme-settings.php file.
-        $filename = DRUPAL_ROOT . '/' . str_replace("/$theme.info.yml", '', $themes[$theme]->filename) . '/theme-settings.php';
+        $filename = DRUPAL_ROOT . '/' . $themes[$theme]->getPath() . '/theme-settings.php';
         if (file_exists($filename)) {
           require_once $filename;
         }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/GetFilenameUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/GetFilenameUnitTest.php
index a471b0953a98..e412ee0415df 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/GetFilenameUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/GetFilenameUnitTest.php
@@ -35,17 +35,17 @@ function testDrupalGetFilename() {
     // does not exist.
     $this->assertFalse(\Drupal::hasService('keyvalue'), 'The container has no keyvalue service.');
     // Retrieving the location of a module.
-    $this->assertIdentical(drupal_get_filename('module', 'xmlrpc'), 'core/modules/xmlrpc/xmlrpc.module', 'Retrieve module location.');
+    $this->assertIdentical(drupal_get_filename('module', 'xmlrpc'), 'core/modules/xmlrpc/xmlrpc.module');
 
     // Retrieving the location of a theme.
-    $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'core/themes/stark/stark.info.yml', 'Retrieve theme location.');
+    $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'core/themes/stark/stark.theme');
 
     // Retrieving the location of a theme engine.
-    $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'core/themes/engines/phptemplate/phptemplate.engine', 'Retrieve theme engine location.');
+    $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'core/themes/engines/phptemplate/phptemplate.engine');
 
     // Retrieving the location of a profile. Profiles are a special case with
     // a fixed location and naming.
-    $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'core/profiles/standard/standard.profile', 'Retrieve installation profile location.');
+    $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'core/profiles/standard/standard.profile');
 
     // Searching for an item that does not exist returns NULL.
     $this->assertNull(drupal_get_filename('module', uniqid("", TRUE)), 'Searching for an item that does not exist returns NULL.');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
index d37fd4b48030..7962e497e8f3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/SystemListingTest.php
@@ -49,7 +49,7 @@ function testDirectoryPrecedence() {
     // meaning, so assert their presence first.
     foreach ($expected_directories as $module => $directories) {
       foreach ($directories as $directory) {
-        $filename = "$directory/$module/$module.module";
+        $filename = "$directory/$module/$module.info.yml";
         $this->assertTrue(file_exists(DRUPAL_ROOT . '/' . $filename), format_string('@filename exists.', array('@filename' => $filename)));
       }
     }
@@ -61,9 +61,9 @@ function testDirectoryPrecedence() {
     $files = $listing->scan('module');
     foreach ($expected_directories as $module => $directories) {
       $expected_directory = array_shift($directories);
-      $expected_uri = "$expected_directory/$module/$module.module";
-      $this->assertEqual($files[$module]->uri, $expected_uri, format_string('Module @actual was found at @expected.', array(
-        '@actual' => $files[$module]->uri,
+      $expected_uri = "$expected_directory/$module/$module.info.yml";
+      $this->assertEqual($files[$module]->getPathname(), $expected_uri, format_string('Module @actual was found at @expected.', array(
+        '@actual' => $files[$module]->getPathname(),
         '@expected' => $expected_uri,
       )));
     }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 37a30e4c71d7..79452c821bec 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Extension\Extension;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
@@ -61,20 +62,20 @@ function system_theme_default() {
  *   incompatible files as the keys, their values being TRUE.
  * @param $files
  *   The set of files that will be tested.
- * @param $file
+ * @param \Drupal\Core\Extension\Extension $file
  *   The file at which the check starts.
  * @return
  *   Returns TRUE if an incompatible file is found, NULL (no return value)
  *   otherwise.
  */
-function _system_is_incompatible(&$incompatible, $files, $file) {
-  if (isset($incompatible[$file->name])) {
+function _system_is_incompatible(&$incompatible, $files, Extension $file) {
+  if (isset($incompatible[$file->getName()])) {
     return TRUE;
   }
   // Recursively traverse required modules, looking for incompatible modules.
   foreach ($file->requires as $requires) {
     if (isset($files[$requires]) && _system_is_incompatible($incompatible, $files, $files[$requires])) {
-      $incompatible[$file->name] = TRUE;
+      $incompatible[$file->getName()] = TRUE;
       return TRUE;
     }
   }
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 3ded508dc4e3..3fe37c66ba16 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -993,19 +993,18 @@ function hook_system_breadcrumb_alter(array &$breadcrumb, array $attributes, arr
  * add to or alter the data generated by reading the .info.yml file with
  * \Drupal\Core\Extension\InfoParser.
  *
- * @param $info
+ * @param array $info
  *   The .info.yml file contents, passed by reference so that it can be altered.
- * @param $file
- *   Full information about the module or theme, including $file->name, and
- *   $file->filename
- * @param $type
+ * @param \Drupal\Core\Extension\Extension $file
+ *   Full information about the module or theme.
+ * @param string $type
  *   Either 'module' or 'theme', depending on the type of .info.yml file that
  *   was passed.
  */
-function hook_system_info_alter(&$info, $file, $type) {
+function hook_system_info_alter(array &$info, \Drupal\Core\Extension\Extension $file, $type) {
   // Only fill this in if the .info.yml file does not define a 'datestamp'.
   if (empty($info['datestamp'])) {
-    $info['datestamp'] = filemtime($file->filename);
+    $info['datestamp'] = $file->getMTime();
   }
 }
 
@@ -1463,7 +1462,7 @@ function hook_cache_flush() {
 function hook_rebuild() {
   $themes = list_themes();
   foreach ($themes as $theme) {
-    _block_rehash($theme->name);
+    _block_rehash($theme->getName());
   }
 }
 
@@ -2496,7 +2495,7 @@ function hook_system_themes_page_alter(&$theme_groups) {
       $theme->operations[] = array(
         'title' => t('Foo'),
         'href' => 'admin/appearance/foo',
-        'query' => array('theme' => $theme->name)
+        'query' => array('theme' => $theme->getName())
       );
     }
   }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 67b25fec06bc..60c7c4e5b5df 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -8,6 +8,7 @@
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Utility\ModuleInfo;
 use Drupal\block\BlockPluginInterface;
@@ -1377,10 +1378,6 @@ function _system_rebuild_module_data() {
 
   // Read info files for each module.
   foreach ($modules as $key => $module) {
-    // The module system uses the key 'filename' instead of 'uri' so copy the
-    // value so it will be used by the modules system.
-    $modules[$key]->filename = $module->uri;
-
     // Look for the info file.
     $module->info = \Drupal::service('info_parser')->parse($module->getPathname());
 
@@ -1437,7 +1434,7 @@ function _system_rebuild_module_data_ensure_required($module, &$modules) {
     foreach ($module->info['dependencies'] as $dependant) {
       if (!isset($modules[$dependant]->info['required'])) {
         $modules[$dependant]->info['required'] = TRUE;
-        $modules[$dependant]->info['explanation'] = t('Dependency of required module @module', array('@module' => $module->name));
+        $modules[$dependant]->info['explanation'] = t('Dependency of required module @module', array('@module' => $module->info['name']));
         // Ensure any dependencies it has are required.
         _system_rebuild_module_data_ensure_required($modules[$dependant], $modules);
       }
@@ -1595,7 +1592,7 @@ function system_sort_themes($a, $b) {
 /**
  * Implements hook_system_info_alter().
  */
-function system_system_info_alter(&$info, $file, $type) {
+function system_system_info_alter(&$info, Extension $file, $type) {
   // Remove page-top and page-bottom from the blocks UI since they are reserved for
   // modules to populate from outside the blocks system.
   if ($type == 'theme') {
diff --git a/core/modules/system/tests/modules/module_test/module_test.module b/core/modules/system/tests/modules/module_test/module_test.module
index b1372c0f8d2b..0968c6870989 100644
--- a/core/modules/system/tests/modules/module_test/module_test.module
+++ b/core/modules/system/tests/modules/module_test/module_test.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Extension\Extension;
+
 /**
  * Implements hook_permission().
  */
@@ -14,45 +16,45 @@ function module_test_permission() {
  *
  * Manipulate module dependencies to test dependency chains.
  */
-function module_test_system_info_alter(&$info, $file, $type) {
+function module_test_system_info_alter(&$info, Extension $file, $type) {
   if (\Drupal::state()->get('module_test.dependency') == 'missing dependency') {
-    if ($file->name == 'forum') {
+    if ($file->getName() == 'forum') {
       // Make forum module depend on ban.
       $info['dependencies'][] = 'ban';
     }
-    elseif ($file->name == 'ban') {
+    elseif ($file->getName() == 'ban') {
       // Make ban depend on a made-up module.
       $info['dependencies'][] = 'foo';
     }
   }
   elseif (\Drupal::state()->get('module_test.dependency') == 'dependency') {
-    if ($file->name == 'forum') {
+    if ($file->getName() == 'forum') {
       // Make the forum module depend on ban.
       $info['dependencies'][] = 'ban';
     }
-    elseif ($file->name == 'ban') {
+    elseif ($file->getName() == 'ban') {
       // Make ban depend on xmlrpc module.
       $info['dependencies'][] = 'xmlrpc';
     }
   }
   elseif (\Drupal::state()->get('module_test.dependency') == 'version dependency') {
-    if ($file->name == 'forum') {
+    if ($file->getName() == 'forum') {
       // Make the forum module depend on ban.
       $info['dependencies'][] = 'ban';
     }
-    elseif ($file->name == 'ban') {
+    elseif ($file->getName() == 'ban') {
       // Make ban depend on a specific version of xmlrpc module.
       $info['dependencies'][] = 'xmlrpc (1.x)';
     }
-    elseif ($file->name == 'xmlrpc') {
+    elseif ($file->getName() == 'xmlrpc') {
       // Set xmlrpc module to a version compatible with the above.
       $info['version'] = '8.x-1.0';
     }
   }
-  if ($file->name == 'seven' && $type == 'theme') {
+  if ($file->getName() == 'seven' && $type == 'theme') {
     $info['regions']['test_region'] = t('Test region');
   }
-  if ($file->name == 'module_test' && \Drupal::state()->get('module_test.hook_system_info_alter')) {
+  if ($file->getName() == 'module_test' && \Drupal::state()->get('module_test.hook_system_info_alter')) {
     $info['required'] = TRUE;
     $info['explanation'] = 'Testing hook_system_info_alter()';
   }
diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module
index b10934150f0e..4d3601b869aa 100644
--- a/core/modules/system/tests/modules/system_test/system_test.module
+++ b/core/modules/system/tests/modules/system_test/system_test.module
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Core\Extension\Extension;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
@@ -38,27 +39,27 @@ function system_test_modules_uninstalled($modules) {
 /**
  * Implements hook_system_info_alter().
  */
-function system_test_system_info_alter(&$info, $file, $type) {
+function system_test_system_info_alter(&$info, Extension $file, $type) {
   // We need a static otherwise the last test will fail to alter common_test.
   static $test;
   if (($dependencies = \Drupal::state()->get('system_test.dependencies')) || $test) {
-    if ($file->name == 'module_test') {
+    if ($file->getName() == 'module_test') {
       $info['hidden'] = FALSE;
       $info['dependencies'][] = array_shift($dependencies);
       \Drupal::state()->set('system_test.dependencies', $dependencies);
       $test = TRUE;
     }
-    if ($file->name == 'common_test') {
+    if ($file->getName() == 'common_test') {
       $info['hidden'] = FALSE;
       $info['version'] = '8.x-2.4-beta3';
     }
   }
 
   // Make the system_dependencies_test visible by default.
-  if ($file->name == 'system_dependencies_test') {
+  if ($file->getName() == 'system_dependencies_test') {
     $info['hidden'] = FALSE;
   }
-  if (in_array($file->name, array(
+  if (in_array($file->getName(), array(
     'system_incompatible_module_version_dependencies_test',
     'system_incompatible_core_version_dependencies_test',
     'system_incompatible_module_version_test',
@@ -66,7 +67,7 @@ function system_test_system_info_alter(&$info, $file, $type) {
   ))) {
     $info['hidden'] = FALSE;
   }
-  if ($file->name == 'requirements1_test' || $file->name == 'requirements2_test') {
+  if ($file->getName() == 'requirements1_test' || $file->getName() == 'requirements2_test') {
     $info['hidden'] = FALSE;
   }
 }
diff --git a/core/modules/system/tests/modules/theme_page_test/theme_page_test.module b/core/modules/system/tests/modules/theme_page_test/theme_page_test.module
index 1180d64fa855..7373fabde823 100644
--- a/core/modules/system/tests/modules/theme_page_test/theme_page_test.module
+++ b/core/modules/system/tests/modules/theme_page_test/theme_page_test.module
@@ -1,9 +1,11 @@
 <?php
 
+use Drupal\Core\Extension\Extension;
+
 /**
  * Implements hook_system_info_alter().
  */
-function theme_page_test_system_info_alter(&$info, $file, $type) {
+function theme_page_test_system_info_alter(&$info, Extension $file, $type) {
   // Make sure that all themes are visible on the Appearance form.
   if ($type == 'theme') {
     unset($info['hidden']);
diff --git a/core/modules/update/tests/modules/update_test/update_test.module b/core/modules/update/tests/modules/update_test/update_test.module
index ed5e008ec564..536d3303230c 100644
--- a/core/modules/update/tests/modules/update_test/update_test.module
+++ b/core/modules/update/tests/modules/update_test/update_test.module
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Core\Extension\Extension;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\BinaryFileResponse;
 
@@ -19,9 +20,9 @@
  * module or theme short name ($file->name) and the subarrays contain settings
  * just for that module or theme.
  */
-function update_test_system_info_alter(&$info, $file) {
+function update_test_system_info_alter(&$info, Extension $file) {
   $setting = \Drupal::config('update_test.settings')->get('system_info');
-  foreach (array('#all', $file->name) as $id) {
+  foreach (array('#all', $file->getName()) as $id) {
     if (!empty($setting[$id])) {
       foreach ($setting[$id] as $key => $value) {
         $info[$key] = $value;
diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php
index 17131c4568b2..f1b42fd14134 100644
--- a/core/modules/views/lib/Drupal/views/ViewExecutable.php
+++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php
@@ -1361,7 +1361,7 @@ public function render($display_id = NULL) {
       // Let the themes play too, because pre render is a very themey thing.
       if (isset($GLOBALS['base_theme_info']) && isset($GLOBALS['theme'])) {
         foreach ($GLOBALS['base_theme_info'] as $base) {
-          $module_handler->invoke($base->name, 'views_pre_render', array($this));
+          $module_handler->invoke($base->getName(), 'views_pre_render', array($this));
         }
 
         $module_handler->invoke($GLOBALS['theme'], 'views_pre_render', array($this));
@@ -1385,7 +1385,7 @@ public function render($display_id = NULL) {
     // Let the themes play too, because post render is a very themey thing.
     if (isset($GLOBALS['base_theme_info']) && isset($GLOBALS['theme'])) {
       foreach ($GLOBALS['base_theme_info'] as $base) {
-        $module_handler->invoke($base->name, 'views_post_render', array($this));
+        $module_handler->invoke($base->getName(), 'views_post_render', array($this));
       }
 
       $module_handler->invoke($GLOBALS['theme'], 'views_post_render', array($this));
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 9c45fd3d0508..bae3c9a33aad 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -242,13 +242,13 @@ public function testRebuildThemeData() {
       ->method('scan')
       ->with('theme')
       ->will($this->returnValue(array(
-        'seven' => new Extension('theme', DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', 'seven.info.yml'),
+        'seven' => new Extension('theme', DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', 'seven.theme'),
       )));
     $this->extensionDiscovery->expects($this->at(1))
       ->method('scan')
       ->with('theme_engine')
       ->will($this->returnValue(array(
-        'twig' => new Extension('theme_engine', DRUPAL_ROOT . '/core/themes/engines/twig.info.yml', 'twig.info.yml'),
+        'twig' => new Extension('theme_engine', DRUPAL_ROOT . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
       )));
     $this->infoParser->expects($this->once())
       ->method('parse')
@@ -267,10 +267,10 @@ public function testRebuildThemeData() {
 
     // Ensure some basic properties.
     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info);
-    $this->assertEquals('seven', $info->name);
-    $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', $info->uri);
-    $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', $info->filename);
-    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig.info.yml', $info->owner);
+    $this->assertEquals('seven', $info->getName());
+    $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', $info->getPathname());
+    $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.theme', $info->uri);
+    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine', $info->owner);
     $this->assertEquals('twig', $info->prefix);
 
     $this->assertEquals('twig', $info->info['engine']);
@@ -303,7 +303,7 @@ public function testRebuildThemeDataWithThemeParents() {
       ->method('scan')
       ->with('theme_engine')
       ->will($this->returnValue(array(
-        'twig' => new Extension('theme_engine', DRUPAL_ROOT . '/core/themes/engines/twig.info.yml', 'twig.info.yml'),
+        'twig' => new Extension('theme_engine', DRUPAL_ROOT . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
       )));
     $this->infoParser->expects($this->at(0))
       ->method('parse')
@@ -328,17 +328,17 @@ public function testRebuildThemeDataWithThemeParents() {
 
     // Ensure some basic properties.
     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_basetheme);
-    $this->assertEquals('test_basetheme', $info_basetheme->name);
+    $this->assertEquals('test_basetheme', $info_basetheme->getName());
     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_subtheme);
-    $this->assertEquals('test_subtheme', $info_subtheme->name);
+    $this->assertEquals('test_subtheme', $info_subtheme->getName());
 
     // Test the parent/child-theme properties.
     $info_subtheme->info['base theme'] = 'test_basetheme';
     $info_basetheme->sub_themes = array('test_subtheme');
 
-    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig.info.yml', $info_basetheme->owner);
+    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine', $info_basetheme->owner);
     $this->assertEquals('twig', $info_basetheme->prefix);
-    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig.info.yml', $info_subtheme->owner);
+    $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine', $info_subtheme->owner);
     $this->assertEquals('twig', $info_subtheme->prefix);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
index 399f22312626..892743363f6e 100644
--- a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Theme;
 
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Theme\Registry;
 use Drupal\Tests\UnitTestCase;
 
@@ -75,10 +76,7 @@ protected function setUp() {
    */
   public function testGetRegistryForModule() {
     $this->setupTheme('test_theme');
-    $this->registry->setTheme((object) array(
-      'name' => 'test_theme',
-      'filename' => 'core/modules/system/tests/themes/test_theme/test_theme.theme',
-    ));
+    $this->registry->setTheme(new Extension('theme', 'core/modules/system/tests/themes/test_theme/test_theme.info.yml', 'test_theme.theme'));
     $this->registry->setBaseThemes(array());
 
     // Include the module so that hook_theme can be called.
@@ -120,7 +118,7 @@ protected function setupTheme($theme_name = NULL) {
 
 class TestRegistry extends Registry {
 
-  public function setTheme(\stdClass $theme) {
+  public function setTheme(Extension $theme) {
     $this->theme = $theme;
   }
 
diff --git a/core/themes/engines/phptemplate/phptemplate.engine b/core/themes/engines/phptemplate/phptemplate.engine
index 718d4600a863..cab86fd67739 100644
--- a/core/themes/engines/phptemplate/phptemplate.engine
+++ b/core/themes/engines/phptemplate/phptemplate.engine
@@ -5,13 +5,14 @@
  * Handles integration of PHP templates with the Drupal theme system.
  */
 
+use Drupal\Core\Extension\Extension;
+
 /**
  * Implements hook_init().
  */
-function phptemplate_init($template) {
-  $file = dirname($template->filename) . '/' . $template->name . '.theme';
-  if (file_exists($file)) {
-    include_once DRUPAL_ROOT . '/' . $file;
+function phptemplate_init(Extension $theme) {
+  if (file_exists($theme->uri)) {
+    include_once DRUPAL_ROOT . '/' . $theme->uri;
   }
 }
 
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
index dd8442e163de..2985ddcb9b6c 100644
--- a/core/themes/engines/twig/twig.engine
+++ b/core/themes/engines/twig/twig.engine
@@ -4,6 +4,8 @@
  * @file
  * Handles integration of Twig templates with the Drupal theme system.
  */
+
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Template\TwigReference;
 
 /**
@@ -25,10 +27,9 @@ function twig_extension() {
 /**
  * Implements hook_init().
  */
-function twig_init($template) {
-  $file = dirname($template->filename) . '/' . $template->name . '.theme';
-  if (file_exists($file)) {
-    include_once DRUPAL_ROOT . '/' . $file;
+function twig_init(Extension $theme) {
+  if (file_exists($theme->uri)) {
+    include_once DRUPAL_ROOT . '/' . $theme->uri;
   }
 }
 
-- 
GitLab