Commit 6bf13bd8 authored by Dries's avatar Dries

Issue #1793074 by cweagans, sun, chx: Convert .info files to YAML.

parent 13bd2b25
......@@ -918,7 +918,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
$extension = 'engine';
}
elseif ($type == 'theme') {
$extension = 'info';
$extension = 'info.yml';
}
// Profiles are converted into modules in system_rebuild_module_data().
// @todo Remove false-exposure of profiles as modules.
......
......@@ -3,6 +3,7 @@
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Yaml\Parser;
use Drupal\Component\PhpStorage\PhpStorageFactory;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface;
......@@ -2507,7 +2508,7 @@ function drupal_add_html_head_link($attributes, $header = FALSE) {
* enabled, this should be set to TRUE if the stylesheet is present on every
* page of the website for users for whom it is present at all. This
* defaults to FALSE. It is set to TRUE for stylesheets added via module and
* theme .info files. Modules that add stylesheets within hook_init()
* theme .info.yml files. Modules that add stylesheets within hook_init()
* implementations, or from other code that ensures that the stylesheet is
* added to all website pages, should also set this flag to TRUE. All
* stylesheets within the same group that have the 'every_page' flag set to
......@@ -3252,7 +3253,7 @@ function drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE)
$basepath = dirname($file);
// Load the CSS stylesheet. We suppress errors because themes may specify
// stylesheets in their .info file that don't exist in the theme's path,
// stylesheets in their .info.yml file that don't exist in the theme's path,
// but are merely there to disable certain module CSS files.
if ($contents = @file_get_contents($file)) {
// Return the processed stylesheet.
......@@ -3631,7 +3632,7 @@ function drupal_region_class($region) {
* enabled, this should be set to TRUE if the JavaScript is present on every
* page of the website for users for whom it is present at all. This
* defaults to FALSE. It is set to TRUE for JavaScript files that are added
* via module and theme .info files. Modules that add JavaScript within
* via module and theme .info.yml files. Modules that add JavaScript within
* hook_init() implementations, or from other code that ensures that the
* JavaScript is added to all website pages, should also set this flag to
* TRUE. All JavaScript files within the same group and that have the
......@@ -6185,39 +6186,39 @@ function element_set_attributes(array &$element, array $map) {
}
/**
* Parses Drupal module and theme .info files.
* Parses Drupal module and theme .info.yml files.
*
* Info files are NOT for placing arbitrary theme and module-specific settings.
* Use variable_get() and variable_set() for that.
* Use variable_get() and variable_set() for that. Info files are formatted as
* YAML. If the 'version' key is set to 'VERSION' in any info file, then the
* value will be substituted with the current version of Drupal core.
*
* Information stored in a module .info file:
* Information stored in a module .info.yml file:
* - name: The real name of the module for display purposes.
* - description: A brief description of the module.
* - dependencies: An array of shortnames of other modules this module requires.
* - package: The name of the package of modules this module belongs to.
*
* See forum.info for an example of a module .info file.
* See forum.info.yml for an example of a module .info.yml file.
*
* Information stored in a theme .info file:
* Information stored in a theme .info.yml file:
* - name: The real name of the theme for display purposes.
* - description: Brief description.
* - screenshot: Path to screenshot relative to the theme's .info file.
* - screenshot: Path to screenshot relative to the theme's .info.yml file.
* - engine: Theme engine; typically phptemplate.
* - base: Name of a base theme, if applicable; e.g., base = zen.
* - regions: Listed regions; e.g., region[left] = Left sidebar.
* - features: Features available; e.g., features[] = logo.
* - stylesheets: Theme stylesheets; e.g., stylesheets[all][] = my-style.css.
* - scripts: Theme scripts; e.g., scripts[] = my-script.js.
* - base theme: Name of a base theme, if applicable.
* - regions: Listed regions.
* - features: Features available.
* - stylesheets: Theme stylesheets.
* - scripts: Theme scripts.
*
* See bartik.info for an example of a theme .info file.
* See bartik.info.yml for an example of a theme .info.yml file.
*
* @param $filename
* @param string $filename
* The file we are parsing. Accepts file with relative or absolute path.
*
* @return
* @return array
* The info array.
*
* @see drupal_parse_info_format()
*/
function drupal_parse_info_file($filename) {
$info = &drupal_static(__FUNCTION__, array());
......@@ -6227,105 +6228,14 @@ function drupal_parse_info_file($filename) {
$info[$filename] = array();
}
else {
$data = file_get_contents($filename);
$info[$filename] = drupal_parse_info_format($data);
}
}
return $info[$filename];
}
/**
* Parses data in Drupal's .info format.
*
* Data should be in an .ini-like format to specify values. White-space
* generally doesn't matter, except inside values:
* @code
* key = value
* key = "value"
* key = 'value'
* key = "multi-line
* value"
* key = 'multi-line
* value'
* key
* =
* 'value'
* @endcode
*
* Arrays are created using a HTTP GET alike syntax:
* @code
* key[] = "numeric array"
* key[index] = "associative array"
* key[index][] = "nested numeric array"
* key[index][index] = "nested associative array"
* @endcode
*
* PHP constants are substituted in, but only when used as the entire value.
* Comments should start with a semi-colon at the beginning of a line.
*
* @param $data
* A string to parse.
*
* @return
* The info array.
*
* @see drupal_parse_info_file()
*/
function drupal_parse_info_format($data) {
$info = array();
$constants = get_defined_constants();
if (preg_match_all('
@^\s* # Start at the beginning of a line, ignoring leading whitespace
((?:
[^=;\[\]]| # Key names cannot contain equal signs, semi-colons or square brackets,
\[[^\[\]]*\] # unless they are balanced and not nested
)+?)
\s*=\s* # Key/value pairs are separated by equal signs (ignoring white-space)
(?:
("(?:[^"]|(?<=\\\\)")*")| # Double-quoted string, which may contain slash-escaped quotes/slashes
(\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
([^\r\n]*?) # Non-quoted string
)\s*$ # Stop at the next end of a line, ignoring trailing whitespace
@msx', $data, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
// Fetch the key and value string.
$i = 0;
foreach (array('key', 'value1', 'value2', 'value3') as $var) {
$$var = isset($match[++$i]) ? $match[$i] : '';
$parser = new Parser();
$info[$filename] = $parser->parse(file_get_contents($filename));
if (isset($info[$filename]['version']) && $info[$filename]['version'] === 'VERSION') {
$info[$filename]['version'] = VERSION;
}
$value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
// Parse array syntax.
$keys = preg_split('/\]?\[/', rtrim($key, ']'));
$last = array_pop($keys);
$parent = &$info;
// Create nested arrays.
foreach ($keys as $key) {
if ($key == '') {
$key = count($parent);
}
if (!isset($parent[$key]) || !is_array($parent[$key])) {
$parent[$key] = array();
}
$parent = &$parent[$key];
}
// Handle PHP constants.
if (isset($constants[$value])) {
$value = $constants[$value];
}
// Insert actual value.
if ($last == '') {
$last = count($parent);
}
$parent[$last] = $value;
}
}
return $info;
return $info[$filename];
}
/**
......
......@@ -24,7 +24,7 @@
*
* Image toolkits are discovered based on the associated module's
* hook_image_toolkits. Additionally the image toolkit include file
* must be identified in the files array in the module.info file. The
* must be identified in the files array in the module.info.yml file. The
* toolkit must then be enabled using the admin/config/media/image-toolkit
* form.
*
......
......@@ -187,7 +187,7 @@ function install_state_defaults() {
// redirect.
'parameters_changed' => FALSE,
// An array of information about the chosen installation profile. This will
// be filled in based on the profile's .info file.
// be filled in based on the profile's .info.yml file.
'profile_info' => array(),
// An array of available installation profiles.
'profiles' => array(),
......
......@@ -84,7 +84,7 @@ function drupal_load_updates() {
* Loads the installation profile, extracting its defined distribution name.
*
* @return
* The distribution name defined in the profile's .info file. Defaults to
* The distribution name defined in the profile's .info.yml file. Defaults to
* "Drupal" if none is explicitly provided by the installation profile.
*
* @see install_profile_info()
......@@ -864,17 +864,18 @@ function drupal_check_module($module) {
}
/**
* Retrieves information about an installation profile from its .info file.
* Retrieves information about an installation profile from its .info.yml file.
*
* The information stored in a profile .info file is similar to that stored in
* a normal Drupal module .info file. For example:
* The information stored in a profile .info.yml file is similar to that stored
* in a normal Drupal module .info.yml file. For example:
* - name: The real name of the installation profile for display purposes.
* - description: A brief description of the profile.
* - dependencies: An array of shortnames of other modules that this install
* profile requires.
*
* Additional, less commonly-used information that can appear in a profile.info
* file but not in a normal Drupal module .info file includes:
* Additional, less commonly-used information that can appear in a
* profile.info.yml file but not in a normal Drupal module .info.yml file
* includes:
* - distribution_name: The name of the Drupal distribution that is being
* installed, to be shown throughout the installation process. Defaults to
* 'Drupal'.
......@@ -889,7 +890,7 @@ function drupal_check_module($module) {
* information for dependencies. If you only need information from the info
* file itself, use system_get_info().
*
* Example of .info file:
* Example of .info.yml file:
* @code
* name = Minimal
* description = Start fresh, with only a few modules enabled.
......@@ -918,7 +919,7 @@ function install_profile_info($profile, $langcode = 'en') {
'hidden' => FALSE,
'php' => DRUPAL_MINIMUM_PHP,
);
$profile_file = drupal_get_path('profile', $profile) . "/$profile.info";
$profile_file = drupal_get_path('profile', $profile) . "/$profile.info.yml";
$info = drupal_parse_info_file($profile_file);
$info += $defaults;
$info['dependencies'] = array_unique(array_merge(
......
......@@ -626,7 +626,7 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
* Returns an array of modules required by core.
*/
function drupal_required_modules() {
$files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'modules');
$files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info.yml$/', 'modules');
$required = array();
// An installation profile is required and one must always be loaded.
......
......@@ -121,7 +121,7 @@ function drupal_theme_initialize() {
* @param $theme
* An object with the following information:
* filename
* The .info file for this theme. The 'path' to
* The .info.yml file for this theme. The 'path' to
* the theme will be in this file's directory. (Required)
* owner
* The path to the .theme file or the .engine file to load for
......@@ -693,22 +693,22 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
* An associative array of the currently available themes. The keys are the
* themes' machine names and the values are objects having the following
* properties:
* - filename: The filepath and name of the .info file.
* - filename: The filepath and name of the .info.yml file.
* - name: The machine name of the theme.
* - status: 1 for enabled, 0 for disabled themes.
* - info: The contents of the .info file.
* - info: The contents of the .info.yml file.
* - stylesheets: A two dimensional array, using the first key for the
* media attribute (e.g. 'all'), the second for the name of the file
* (e.g. style.css). The value is a complete filepath (e.g.
* themes/bartik/style.css). Not set if no stylesheets are defined in the
* .info file.
* .info.yml file.
* - scripts: An associative array of JavaScripts, using the filename as key
* and the complete filepath as value. Not set if no scripts are defined in
* the .info file.
* the .info.yml file.
* - prefix: The base theme engine prefix.
* - engine: The machine name of the theme engine.
* - base_theme: If this is a sub-theme, the machine name of the base theme
* defined in the .info file. Otherwise, the element is not set.
* defined in the .info.yml file. Otherwise, the element is not set.
* - base_themes: If this is a sub-theme, an associative array of the
* base-theme ancestors of this theme, starting with this theme's base
* theme, then the base theme's own base theme, etc. Each entry has an
......@@ -1357,8 +1357,9 @@ function drupal_find_theme_templates($cache, $extension, $path) {
* The final setting is obtained from the last value found in the following
* sources:
* - the default global settings specified in this function
* - the default theme-specific settings defined in any base theme's .info file
* - the default theme-specific settings defined in the theme's .info file
* - the default theme-specific settings defined in any base theme's .info.yml
* file
* - the default theme-specific settings defined in the theme's .info.yml file
* - the saved values from the global theme settings form
* - the saved values from the theme's settings form
* To only retrieve the default global theme setting, an empty string should be
......@@ -1398,8 +1399,8 @@ function theme_get_setting($setting_name, $theme = NULL) {
$cache[$theme]['toggle_' . $feature] = 1;
}
// Get the values for the theme-specific settings from the .info files of
// the theme and all its base themes.
// Get the values for the theme-specific settings from the .info.yml files
// of the theme and all its base themes.
if ($theme) {
$themes = list_themes();
$theme_object = $themes[$theme];
......
......@@ -64,7 +64,7 @@ function _drupal_maintenance_theme() {
$themes = list_themes();
// list_themes() triggers a drupal_alter() in maintenance mode, but we can't
// let themes alter the .info data until we know a theme's base themes. So
// let themes alter the .info.yml data until we know a theme's base themes. So
// don't set global $theme until after list_themes() builds its cache.
$theme = $custom_theme;
......
......@@ -186,6 +186,7 @@ protected function scanDirectory($dir, $key, $mask, $nomask) {
$file->uri = $uri;
$file->filename = $filename;
$file->name = pathinfo($filename, PATHINFO_FILENAME);
$this->processFile($file);
$files[$file->$key] = $file;
}
}
......@@ -195,4 +196,14 @@ protected function scanDirectory($dir, $key, $mask, $nomask) {
}
return $files;
}
/**
* Process each file object as it is found by scanDirectory().
*
* @param $file
* A file object.
*/
protected function processFile($file) {
}
}
......@@ -54,8 +54,8 @@ protected function process(array $files, array $files_to_add) {
foreach (array_intersect_key($files_to_add, $files) as $file_key => $file) {
// If it has no info file, then we just behave liberally and accept the
// new resource on the list for merging.
if (file_exists($info_file = dirname($file->uri) . '/' . $file->name . '.info')) {
// Get the .info file for the module or theme this file belongs to.
if (file_exists($info_file = dirname($file->uri) . '/' . $file->name . '.info.yml')) {
// Get the .info.yml file for the module or theme this file belongs to.
$info = drupal_parse_info_file($info_file);
// If the module or theme is incompatible with Drupal core, remove it
......@@ -69,4 +69,11 @@ protected function process(array $files, array $files_to_add) {
return $files_to_add;
}
/**
* Overrides Drupal\Core\SystemListing::processFile().
*/
protected function processFile($file) {
$file->name = basename($file->name, '.info');
}
}
......@@ -94,7 +94,7 @@ public static function getUpdaterFromDirectory($directory) {
* Path to the info file.
*/
public static function findInfoFile($directory) {
$info_files = file_scan_directory($directory, '/.*\.info$/');
$info_files = file_scan_directory($directory, '/.*\.info.yml$/');
if (!$info_files) {
return FALSE;
}
......
......@@ -10,7 +10,7 @@
use Drupal\Core\Utility\CacheArray;
/**
* Extends CacheArray to lazy load .info properties for modules.
* Extends CacheArray to lazy load .info.yml properties for modules.
*
* Use system_get_module_info() rather than instantiating this class directly.
*/
......
name = Actions
description = Perform tasks on specific events triggered within the system.
package = Core
version = VERSION
core = 8.x
configure = admin/config/system/actions
name: Actions
description: 'Perform tasks on specific events triggered within the system.'
package: Core
version: VERSION
core: 8.x
configure: admin/config/system/actions
name = Action bulk form test
description = Support module for action bulk form testing.
package = Testing
version = VERSION
core = 8.x
hidden = TRUE
dependencies[] = action
dependencies[] = views
name: 'Action bulk form test'
description: 'Support module for action bulk form testing.'
package: Testing
version: VERSION
core: 8.x
hidden: true
dependencies:
- action
- views
name = Action loop test
description = Support module for action loop testing.
package = Testing
version = VERSION
core = 8.x
hidden = TRUE
dependencies[] = action
name: 'Action loop test'
description: 'Support module for action loop testing.'
package: Testing
version: VERSION
core: 8.x
hidden: true
dependencies:
- action
name = Aggregator
description = "Aggregates syndicated content (RSS, RDF, and Atom feeds) from external sources."
package = Core
version = VERSION
core = 8.x
configure = admin/config/services/aggregator/settings
dependencies[] = file
name: Aggregator
description: 'Aggregates syndicated content (RSS, RDF, and Atom feeds) from external sources.'
package: Core
version: VERSION
core: 8.x
configure: admin/config/services/aggregator/settings
dependencies:
- file
name = "Aggregator module tests"
description = "Support module for aggregator related testing."
package = Testing
version = VERSION
core = 8.x
hidden = TRUE
name: 'Aggregator module tests'
description: 'Support module for aggregator related testing.'
package: Testing
version: VERSION
core: 8.x
hidden: true
name = Ban
description = Enables banning of IP addresses.
package = Core
version = VERSION
core = 8.x
configure = admin/config/people/ban
name: Ban
description: 'Enables banning of IP addresses.'
package: Core
version: VERSION
core: 8.x
configure: admin/config/people/ban
name = Block
description = Controls the visual building blocks a page is constructed with. Blocks are boxes of content rendered into an area, or region, of a web page.
package = Core
version = VERSION
core = 8.x
configure = admin/structure/block