Issue #3225812 by larowlan, Gábor Hojtsy, catch, andypost: Add lifecycle_link key to info.yml files

merge-requests/1069/head
catch 2021-07-30 09:31:26 +01:00
parent 16edf0a2a9
commit 3726333893
6 changed files with 102 additions and 2 deletions

View File

@ -19,6 +19,11 @@ final class ExtensionLifecycle {
*/
const LIFECYCLE_IDENTIFIER = 'lifecycle';
/**
* The string used to identify the lifecycle link in an .info.yml file.
*/
const LIFECYCLE_LINK_IDENTIFIER = 'lifecycle_link';
/**
* Extension is experimental. Warnings will be shown if installed.
*/

View File

@ -108,14 +108,23 @@ class InfoParserDynamic implements InfoParserInterface {
$parsed_info['version'] = \Drupal::VERSION;
}
$parsed_info += [ExtensionLifecycle::LIFECYCLE_IDENTIFIER => ExtensionLifecycle::STABLE];
if (!ExtensionLifecycle::isValid($parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER])) {
$lifecycle = $parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER];
if (!ExtensionLifecycle::isValid($lifecycle)) {
$valid_values = [
ExtensionLifecycle::EXPERIMENTAL,
ExtensionLifecycle::STABLE,
ExtensionLifecycle::DEPRECATED,
ExtensionLifecycle::OBSOLETE,
];
throw new InfoParserException("'lifecycle: {$parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER]}' is not valid in $filename. Valid values are: '" . implode("', '", $valid_values) . "'.");
throw new InfoParserException("'lifecycle: {$lifecycle}' is not valid in $filename. Valid values are: '" . implode("', '", $valid_values) . "'.");
}
if (in_array($lifecycle, [ExtensionLifecycle::DEPRECATED, ExtensionLifecycle::OBSOLETE], TRUE)) {
if (empty($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER])) {
throw new InfoParserException(sprintf("Extension %s (%s) has 'lifecycle: %s' but is missing a '%s' entry.", $parsed_info['name'], $filename, $lifecycle, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
}
if (!filter_var($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER], FILTER_VALIDATE_URL)) {
throw new InfoParserException(sprintf("Extension %s (%s) has a '%s' entry that is not a valid URL.", $parsed_info['name'], $filename, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
}
}
}
return $parsed_info;

View File

@ -2,6 +2,7 @@ name: 'Entity Reference'
type: module
description: 'Obsolete. All the functionality has been moved to Core.'
lifecycle: obsolete
lifecycle_link: 'https://www.drupal.org/about/core/policies/core-change-policies/deprecated-and-obsolete-modules-and-themes#s-entity-reference'
package: Field types
version: VERSION
hidden: true

View File

@ -2,6 +2,7 @@ name: Testing
type: module
description: 'Obsolete. SimpleTest has been removed from core.'
lifecycle: obsolete
lifecycle_link: 'https://www.drupal.org/about/core/policies/core-change-policies/deprecated-and-obsolete-modules-and-themes#s-simpletest'
package: Core
version: VERSION
hidden: true

View File

@ -4,3 +4,4 @@ description: 'Support module for testing an obsolete module extension.'
package: Testing
version: VERSION
lifecycle: obsolete
lifecycle_link: 'https://i.giphy.com/media/100JPq1ylYXEti/giphy.webp'

View File

@ -710,6 +710,9 @@ INFO;
if (!empty($lifecycle)) {
$info .= "\nlifecycle: $lifecycle\n";
}
if (in_array($lifecycle, [ExtensionLifecycle::DEPRECATED, ExtensionLifecycle::OBSOLETE], TRUE)) {
$info .= "\nlifecycle_link: http://example.com\n";
}
vfsStream::setup('modules');
$filename = "lifecycle-$lifecycle.info.yml";
vfsStream::create([
@ -798,4 +801,84 @@ INFO;
];
}
/**
* Tests an info file's lifecycle_link values.
*
* @covers ::parse
*
* @dataProvider providerLifecycleLink
*/
public function testLifecycleLink($lifecycle, $lifecycle_link = NULL, $exception_message = NULL) {
$info = <<<INFO
package: Core
core: 8.x
version: VERSION
type: module
name: Module for That
lifecycle: $lifecycle
INFO;
if (($lifecycle_link)) {
$info .= "\nlifecycle_link: $lifecycle_link\n";
}
vfsStream::setup('modules');
// Use a random file name to bypass the static caching in
// \Drupal\Core\Extension\InfoParser.
$random = mb_strtolower($this->randomMachineName());
$filename = "lifecycle-$random.info.yml";
vfsStream::create([
'fixtures' => [
$filename => $info,
],
]);
$path = vfsStream::url("modules/fixtures/$filename");
if ($exception_message) {
$this->expectException(InfoParserException::class);
$this->expectExceptionMessage(sprintf($exception_message, $path));
}
$info_values = $this->infoParser->parse($path);
$this->assertSame($lifecycle, $info_values[ExtensionLifecycle::LIFECYCLE_IDENTIFIER]);
}
/**
* Data provider for testLifecycleLink().
*/
public function providerLifecycleLink() {
return [
'valid deprecated' => [
ExtensionLifecycle::DEPRECATED,
'http://example.com',
],
'valid obsolete' => [
ExtensionLifecycle::OBSOLETE,
'http://example.com',
],
'valid stable' => [
ExtensionLifecycle::STABLE,
],
'valid experimental' => [
ExtensionLifecycle::EXPERIMENTAL,
],
'missing deprecated' => [
ExtensionLifecycle::DEPRECATED,
NULL,
"Extension Module for That (%s) has 'lifecycle: deprecated' but is missing a 'lifecycle_link' entry.",
],
'missing obsolete' => [
ExtensionLifecycle::OBSOLETE,
NULL,
"Extension Module for That (%s) has 'lifecycle: obsolete' but is missing a 'lifecycle_link' entry.",
],
'invalid deprecated' => [
ExtensionLifecycle::DEPRECATED,
'look ma, not a url',
"Extension Module for That (%s) has a 'lifecycle_link' entry that is not a valid URL.",
],
'invalid obsolete' => [
ExtensionLifecycle::OBSOLETE,
'I think you may find that this is also not a url',
"Extension Module for That (%s) has a 'lifecycle_link' entry that is not a valid URL.",
],
];
}
}