registration: Always specify version number in extension.schema.json file
authorKunal Mehta <legoktm@member.fsf.org>
Fri, 16 Dec 2016 19:32:26 +0000 (11:32 -0800)
committerKunal Mehta <legoktm@member.fsf.org>
Fri, 16 Dec 2016 19:47:15 +0000 (11:47 -0800)
Instead of having the current version of the schema live at
extension.schema.json, always include a version number in it. This
simplifies both the code, and makes merging, cherry-picks, rebasing,
etc. easier when the current schema version changes.

Change-Id: I1b5ef4ced1eb34b8bdda7ba9b3f086b1997b704c

docs/extension.schema.json [deleted file]
docs/extension.schema.v2.json [new file with mode: 0644]
includes/registration/ExtensionJsonValidator.php
tests/phpunit/includes/registration/ExtensionProcessorTest.php

diff --git a/docs/extension.schema.json b/docs/extension.schema.json
deleted file mode 100644 (file)
index a5543d1..0000000
+++ /dev/null
@@ -1,727 +0,0 @@
-{
-       "$schema": "http://json-schema.org/schema#",
-       "description": "MediaWiki extension.json schema",
-       "type": "object",
-       "properties": {
-               "manifest_version": {
-                       "type": "integer",
-                       "description": "Version of the extension.json schema the extension.json file is in.",
-                       "required": true
-               },
-               "name": {
-                       "type": "string",
-                       "description": "The extension's canonical name.",
-                       "required": true
-               },
-               "namemsg": {
-                       "type": "string",
-                       "description": "i18n message key of the extension's name."
-               },
-               "type": {
-                       "type": "string",
-                       "description": "The extension's type, as an index to $wgExtensionCredits.",
-                       "default": "other"
-               },
-               "author": {
-                       "type": [
-                               "string",
-                               "array"
-                       ],
-                       "description": "Extension's authors.",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "version": {
-                       "type": "string",
-                       "description": "The version of this release of the extension."
-               },
-               "url": {
-                       "type": "string",
-                       "description": "URL to the homepage for the extension.",
-                       "format": "uri"
-               },
-               "description": {
-                       "type": "string",
-                       "description": "Raw description of the extension."
-               },
-               "descriptionmsg": {
-                       "type": "string",
-                       "description": "Message key for a i18n message describing the extension."
-               },
-               "license-name": {
-                       "type": "string",
-                       "description": "SPDX identifier for the license under which the extension is released."
-               },
-               "requires": {
-                       "type": "object",
-                       "description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
-                       "properties": {
-                               "MediaWiki": {
-                                       "type": "string",
-                                       "description": "Version constraint string against MediaWiki core."
-                               },
-                               "extensions": {
-                                       "type": "object",
-                                       "description": "Set of version constraint strings against specific extensions."
-                               },
-                               "skins": {
-                                       "type": "object",
-                                       "description": "Set of version constraint strings against specific skins."
-                               }
-                       }
-               },
-               "ResourceFileModulePaths": {
-                       "type": "object",
-                       "description": "Default paths to use for all ResourceLoader file modules",
-                       "additionalProperties": false,
-                       "properties": {
-                               "localBasePath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all local paths, relative to current directory"
-                               },
-                               "remoteExtPath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath"
-                               },
-                               "remoteSkinPath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all remote paths, relative to $wgStylePath"
-                               }
-                       }
-               },
-               "ResourceModules": {
-                       "type": "object",
-                       "description": "ResourceLoader modules to register",
-                       "patternProperties": {
-                               "^[a-zA-Z0-9-\\.]+$": {
-                                       "type": "object",
-                                       "anyOf": [
-                                               {
-                                                       "description": "A ResourceLoaderFileModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "localBasePath": {
-                                                                       "type": "string",
-                                                                       "description": "Base path to prepend to all local paths in $options. Defaults to $IP"
-                                                               },
-                                                               "remoteBasePath": {
-                                                                       "type": "string",
-                                                                       "description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
-                                                               },
-                                                               "remoteExtPath": {
-                                                                       "type": "string",
-                                                                       "description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
-                                                               },
-                                                               "skipFunction": {
-                                                                       "type": "string",
-                                                                       "description": "Path to a file containing a JavaScript \"skip function\", if desired."
-                                                               },
-                                                               "scripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to always include (array of file paths)",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "languageScripts": {
-                                                                       "type": "object",
-                                                                       "description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
-                                                                       "patternProperties": {
-                                                                               "^[a-zA-Z0-9-]{2,}$": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "skinScripts": {
-                                                                       "type": "object",
-                                                                       "description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
-                                                                       "patternProperties": {
-                                                                               ".+": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "debugScripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to include in debug contexts",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "loaderScripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to include in the startup module",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "dependencies": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Modules which must be loaded before this module",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "styles": {
-                                                                       "type": ["string", "array", "object"],
-                                                                       "description": "Styles to always load",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "skinStyles": {
-                                                                       "type": "object",
-                                                                       "description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
-                                                                       "patternProperties": {
-                                                                               ".+": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "messages": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Messages to always load",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "group": {
-                                                                       "type": "string",
-                                                                       "description": "Group with which this module should be loaded"
-                                                               },
-                                                               "deprecated": {
-                                                                       "type": ["object", "boolean"],
-                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
-                                                               },
-                                                               "position": {
-                                                                       "type": "string",
-                                                                       "description": "Position on the page to load this module at",
-                                                                       "enum": [
-                                                                               "bottom",
-                                                                               "top"
-                                                                       ]
-                                                               },
-                                                               "templates": {
-                                                                       "type": ["object", "array"],
-                                                                       "description": "Templates to be loaded for client-side usage"
-                                                               },
-                                                               "targets": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "ResourceLoader target the module can run on",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "noflip": {
-                                                                       "type": "boolean",
-                                                                       "description": "Whether to skip CSSJanus LTR-to-RTL flipping for this module. Recommended for styles imported from libraries that already properly handle their RTL styles. Default is false, meaning CSSJanus will be applied on RTL-mode output."
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "A ResourceLoaderWikiModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "class": {
-                                                                       "enum": ["ResourceLoaderWikiModule"]
-                                                               },
-                                                               "group": {
-                                                                       "type": "string",
-                                                                       "description": "Group with which this module should be loaded"
-                                                               },
-                                                               "position": {
-                                                                       "type": "string",
-                                                                       "description": "Position on the page to load this module at",
-                                                                       "enum": [
-                                                                               "bottom",
-                                                                               "top"
-                                                                       ]
-                                                               },
-                                                               "targets": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "ResourceLoader target the module can run on",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "scripts": {
-                                                                       "type": "array",
-                                                                       "description": "A list of on-wiki pages containing JavaScript that should be loaded",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "styles": {
-                                                                       "type": "array",
-                                                                       "description": "A list of on-wiki pages containing CSS that should be loaded",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "A ResourceLoaderImageModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "class": {
-                                                                       "enum": ["ResourceLoaderImageModule"]
-                                                               },
-                                                               "data": {
-                                                                       "type": "string"
-                                                               },
-                                                               "prefix": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selector": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selectorWithoutVariant": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selectorWithVariant": {
-                                                                       "type": "string"
-                                                               },
-                                                               "variants": {
-                                                                       "type": "object"
-                                                               },
-                                                               "images": {
-                                                                       "type": "object"
-                                                               },
-                                                               "position": {
-                                                                       "enum": [
-                                                                               "top",
-                                                                               "bottom"
-                                                                       ]
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "An arbitrary ResourceLoaderModule definition",
-                                                       "properties": {
-                                                               "class": {
-                                                                       "type": "string",
-                                                                       "pattern": "^((?!ResourceLoader(File|Image)Module).)*$"
-                                                               }
-                                                       },
-                                                       "required": ["class"]
-                                               }
-                                       ]
-                               }
-                       }
-               },
-               "ResourceModuleSkinStyles": {
-                       "type": "object",
-                       "description": "ResourceLoader modules for custom skin styles"
-               },
-               "ResourceLoaderSources": {
-                       "type": "object",
-                       "description": "ResourceLoader sources to register"
-               },
-               "ResourceLoaderLESSVars": {
-                       "type": "object",
-                       "description": "ResourceLoader LESS variables"
-               },
-               "ConfigRegistry": {
-                       "type": "object",
-                       "description": "Registry of factory functions to create Config objects"
-               },
-               "SessionProviders": {
-                       "type": "object",
-                       "description": "Session providers"
-               },
-               "AuthManagerAutoConfig": {
-                       "type": "object",
-                       "description": "AuthManager auto-configuration",
-                       "additionalProperties": false,
-                       "properties": {
-                               "preauth": {
-                                       "type": "object",
-                                       "description": "Pre-authentication providers"
-                               },
-                               "primaryauth": {
-                                       "type": "object",
-                                       "description": "Primary authentication providers"
-                               },
-                               "secondaryauth": {
-                                       "type": "object",
-                                       "description": "Secondary authentication providers"
-                               }
-                       }
-               },
-               "CentralIdLookupProviders": {
-                       "type": "object",
-                       "description": "Central ID lookup providers"
-               },
-               "ChangeCredentialsBlacklist": {
-                       "type": "object",
-                       "description": "AuthenticationRequest classes which can only be used internally for credentials change"
-               },
-               "RemoveCredentialsBlacklist": {
-                       "type": "object",
-                       "description": "AuthenticationRequest classes which can only be used internally for credentials removal"
-               },
-               "namespaces": {
-                       "type": "array",
-                       "description": "Method to add extra namespaces",
-                       "items": {
-                               "type": "object",
-                               "properties": {
-                                       "id": {
-                                               "type": "integer"
-                                       },
-                                       "constant": {
-                                               "type": "string"
-                                       },
-                                       "name": {
-                                               "type": "string"
-                                       },
-                                       "gender": {
-                                               "type": "object",
-                                               "properties": {
-                                                       "male": {
-                                                               "type": "string"
-                                                       },
-                                                       "female": {
-                                                               "type": "string"
-                                                       }
-                                               }
-                                       },
-                                       "subpages": {
-                                               "type": "boolean",
-                                               "default": false
-                                       },
-                                       "content": {
-                                               "type": "boolean",
-                                               "default": false
-                                       },
-                                       "defaultcontentmodel": {
-                                               "type": "string"
-                                       },
-                                       "protection": {
-                                               "type": ["string", "array"],
-                                               "description": "Userright(s) required to edit in this namespace"
-                                       },
-                                       "capitallinkoverride": {
-                                               "type": "boolean",
-                                               "description": "Set $wgCapitalLinks on a per-namespace basis"
-                                       },
-                                       "conditional": {
-                                               "type": "boolean",
-                                               "description": "Whether the namespace is conditional upon configuration and should not be registered (requires separate registration via a hook)",
-                                               "default": false
-                                       }
-                               },
-                               "required": ["id", "constant", "name"]
-                       }
-               },
-               "TrackingCategories": {
-                       "type": "array",
-                       "description": "Tracking category message keys",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "DefaultUserOptions": {
-                       "type": "object",
-                       "description": "Default values of user options"
-               },
-               "HiddenPrefs": {
-                       "type": "array",
-                       "description": "Preferences users cannot set",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "GroupPermissions": {
-                       "type": "object",
-                       "description": "Default permissions to give to user groups",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "RevokePermissions": {
-                       "type": "object",
-                       "description": "Default permissions to revoke from user groups",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "GrantPermissions": {
-                       "type": "object",
-                       "description": "Map of permissions granted to authorized consumers to their bundles, called 'grants'",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "GrantPermissionGroups": {
-                       "type": "object",
-                       "description": "Map of grants to their UI grouping",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "string"
-                               }
-                       }
-               },
-               "ImplicitGroups": {
-                       "type": "array",
-                       "description": "Implicit groups"
-               },
-               "GroupsAddToSelf": {
-                       "type": "object",
-                       "description": "Groups a user can add to themselves"
-               },
-               "GroupsRemoveFromSelf": {
-                       "type": "object",
-                       "description": "Groups a user can remove from themselves"
-               },
-               "AddGroups": {
-                       "type": "object",
-                       "description": "Groups a user can add to users"
-               },
-               "RemoveGroups": {
-                       "type": "object",
-                       "description": "Groups a user can remove from users"
-               },
-               "AvailableRights": {
-                       "type": "array",
-                       "description": "User rights added by the extension",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "ContentHandlers": {
-                       "type": "object",
-                       "description": "Mapping of model ID to class name",
-                       "patternProperties": {
-                               "^[A-Za-z]+$": {
-                                       "type": "string"
-                               }
-                       }
-               },
-               "RateLimits": {
-                       "type": "object",
-                       "description": "Rate limits"
-               },
-               "RecentChangesFlags": {
-                       "type": "object",
-                       "description": "Flags (letter symbols) shown on RecentChanges pages"
-               },
-               "MediaHandlers": {
-                       "type": "object",
-                       "description": "Plugins for media file type handling. Each entry in the array maps a MIME type to a PHP class name."
-               },
-               "ExtensionFunctions": {
-                       "type": [
-                               "array",
-                               "string"
-                       ],
-                       "description": "Function to call after setup has finished",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "ExtensionMessagesFiles": {
-                       "type": "object",
-                       "description": "File paths containing PHP internationalization data"
-               },
-               "MessagesDirs": {
-                       "type": "object",
-                       "description": "Directory paths containing JSON internationalization data"
-               },
-               "ExtensionEntryPointListFiles": {
-                       "type": "object"
-               },
-               "SpecialPages": {
-                       "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
-               },
-               "AutoloadClasses": {
-                       "type": "object"
-               },
-               "Hooks": {
-                       "type": [ "string", "object" ],
-                       "description": "Hooks this extension uses (mapping of hook name to callback)"
-               },
-               "JobClasses": {
-                       "type": "object",
-                       "description": "Job types this extension implements (mapping of job type to class name)"
-               },
-               "LogTypes": {
-                       "type": "array",
-                       "description": "List of new log types this extension uses"
-               },
-               "LogRestrictions": {
-                       "type": "object"
-               },
-               "FilterLogTypes": {
-                       "type": "object"
-               },
-               "ActionFilteredLogs": {
-                       "type": "object",
-                       "description": "List of log types which can be filtered by log actions",
-                       "patternProperties": {
-                               "^[a-z-]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z-]+$": {
-                                                       "type": "array",
-                                                       "items": {
-                                                               "type": "string"
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "LogNames": {
-                       "type": "object"
-               },
-               "LogHeaders": {
-                       "type": "object"
-               },
-               "LogActions": {
-                       "type": "object"
-               },
-               "LogActionsHandlers": {
-                       "type": "object"
-               },
-               "Actions": {
-                       "type": "object"
-               },
-               "APIModules": {
-                       "type": "object"
-               },
-               "APIFormatModules": {
-                       "type": "object"
-               },
-               "APIMetaModules": {
-                       "type": "object"
-               },
-               "APIPropModules": {
-                       "type": "object"
-               },
-               "APIListModules": {
-                       "type": "object"
-               },
-               "ValidSkinNames": {
-                       "type": "object"
-               },
-               "FeedClasses": {
-                       "type": "object",
-                       "description": "Available feeds objects"
-               },
-               "SkinOOUIThemes": {
-                       "type": "object"
-               },
-               "PasswordPolicy": {
-                       "type": "object",
-                       "description": "Password policies"
-               },
-               "FileExtensions": {
-                       "type": "array",
-                       "description": "Preferred file extensions for uploading",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "callback": {
-                       "type": [
-                               "array",
-                               "string"
-                       ],
-                       "description": "A function to be called right after MediaWiki processes this file"
-               },
-               "config_prefix": {
-                       "type": "string",
-                       "default": "wg",
-                       "description": "Prefix to put in front of configuration settings when exporting them to $GLOBALS"
-               },
-               "config": {
-                       "type": "object",
-                       "description": "Configuration options for this extension",
-                       "patternProperties": {
-                               "^[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*$": {
-                                       "type": "object",
-                                       "properties": {
-                                               "value": {
-                                                       "required": true
-                                               },
-                                               "merge_strategy": {
-                                                       "type": "string",
-                                                       "enum": [
-                                                               "array_merge_recursive",
-                                                               "array_replace_recursive",
-                                                               "array_plus_2d",
-                                                               "array_plus",
-                                                               "array_merge"
-                                                       ],
-                                                       "default": "array_merge"
-                                               },
-                                               "path": {
-                                                       "description": "Whether this should be interpreted as a filesystem path, relative to extension directory root",
-                                                       "type": "boolean",
-                                                       "default": false
-                                               },
-                                               "description": {
-                                                       "type": ["string", "array"],
-                                                       "description": "A description of the config setting, mostly for documentation/developers"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "ParserTestFiles": {
-                       "type": "array",
-                       "description": "Parser test suite files to be run by parserTests.php when no specific filename is passed to it"
-               },
-               "ServiceWiringFiles": {
-                       "type": "array",
-                       "description": "List of service wiring files to be loaded by the default instance of MediaWikiServices"
-               },
-               "load_composer_autoloader": {
-                       "type": "boolean",
-                       "description": "Load the composer autoloader for this extension, if one is present"
-               }
-       }
-}
diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json
new file mode 100644 (file)
index 0000000..a5543d1
--- /dev/null
@@ -0,0 +1,727 @@
+{
+       "$schema": "http://json-schema.org/schema#",
+       "description": "MediaWiki extension.json schema",
+       "type": "object",
+       "properties": {
+               "manifest_version": {
+                       "type": "integer",
+                       "description": "Version of the extension.json schema the extension.json file is in.",
+                       "required": true
+               },
+               "name": {
+                       "type": "string",
+                       "description": "The extension's canonical name.",
+                       "required": true
+               },
+               "namemsg": {
+                       "type": "string",
+                       "description": "i18n message key of the extension's name."
+               },
+               "type": {
+                       "type": "string",
+                       "description": "The extension's type, as an index to $wgExtensionCredits.",
+                       "default": "other"
+               },
+               "author": {
+                       "type": [
+                               "string",
+                               "array"
+                       ],
+                       "description": "Extension's authors.",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "version": {
+                       "type": "string",
+                       "description": "The version of this release of the extension."
+               },
+               "url": {
+                       "type": "string",
+                       "description": "URL to the homepage for the extension.",
+                       "format": "uri"
+               },
+               "description": {
+                       "type": "string",
+                       "description": "Raw description of the extension."
+               },
+               "descriptionmsg": {
+                       "type": "string",
+                       "description": "Message key for a i18n message describing the extension."
+               },
+               "license-name": {
+                       "type": "string",
+                       "description": "SPDX identifier for the license under which the extension is released."
+               },
+               "requires": {
+                       "type": "object",
+                       "description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
+                       "properties": {
+                               "MediaWiki": {
+                                       "type": "string",
+                                       "description": "Version constraint string against MediaWiki core."
+                               },
+                               "extensions": {
+                                       "type": "object",
+                                       "description": "Set of version constraint strings against specific extensions."
+                               },
+                               "skins": {
+                                       "type": "object",
+                                       "description": "Set of version constraint strings against specific skins."
+                               }
+                       }
+               },
+               "ResourceFileModulePaths": {
+                       "type": "object",
+                       "description": "Default paths to use for all ResourceLoader file modules",
+                       "additionalProperties": false,
+                       "properties": {
+                               "localBasePath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all local paths, relative to current directory"
+                               },
+                               "remoteExtPath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath"
+                               },
+                               "remoteSkinPath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all remote paths, relative to $wgStylePath"
+                               }
+                       }
+               },
+               "ResourceModules": {
+                       "type": "object",
+                       "description": "ResourceLoader modules to register",
+                       "patternProperties": {
+                               "^[a-zA-Z0-9-\\.]+$": {
+                                       "type": "object",
+                                       "anyOf": [
+                                               {
+                                                       "description": "A ResourceLoaderFileModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "localBasePath": {
+                                                                       "type": "string",
+                                                                       "description": "Base path to prepend to all local paths in $options. Defaults to $IP"
+                                                               },
+                                                               "remoteBasePath": {
+                                                                       "type": "string",
+                                                                       "description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
+                                                               },
+                                                               "remoteExtPath": {
+                                                                       "type": "string",
+                                                                       "description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
+                                                               },
+                                                               "skipFunction": {
+                                                                       "type": "string",
+                                                                       "description": "Path to a file containing a JavaScript \"skip function\", if desired."
+                                                               },
+                                                               "scripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to always include (array of file paths)",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "languageScripts": {
+                                                                       "type": "object",
+                                                                       "description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
+                                                                       "patternProperties": {
+                                                                               "^[a-zA-Z0-9-]{2,}$": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "skinScripts": {
+                                                                       "type": "object",
+                                                                       "description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
+                                                                       "patternProperties": {
+                                                                               ".+": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "debugScripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to include in debug contexts",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "loaderScripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to include in the startup module",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "dependencies": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Modules which must be loaded before this module",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "styles": {
+                                                                       "type": ["string", "array", "object"],
+                                                                       "description": "Styles to always load",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "skinStyles": {
+                                                                       "type": "object",
+                                                                       "description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
+                                                                       "patternProperties": {
+                                                                               ".+": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "messages": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Messages to always load",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "group": {
+                                                                       "type": "string",
+                                                                       "description": "Group with which this module should be loaded"
+                                                               },
+                                                               "deprecated": {
+                                                                       "type": ["object", "boolean"],
+                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
+                                                               },
+                                                               "position": {
+                                                                       "type": "string",
+                                                                       "description": "Position on the page to load this module at",
+                                                                       "enum": [
+                                                                               "bottom",
+                                                                               "top"
+                                                                       ]
+                                                               },
+                                                               "templates": {
+                                                                       "type": ["object", "array"],
+                                                                       "description": "Templates to be loaded for client-side usage"
+                                                               },
+                                                               "targets": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "ResourceLoader target the module can run on",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "noflip": {
+                                                                       "type": "boolean",
+                                                                       "description": "Whether to skip CSSJanus LTR-to-RTL flipping for this module. Recommended for styles imported from libraries that already properly handle their RTL styles. Default is false, meaning CSSJanus will be applied on RTL-mode output."
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "A ResourceLoaderWikiModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "class": {
+                                                                       "enum": ["ResourceLoaderWikiModule"]
+                                                               },
+                                                               "group": {
+                                                                       "type": "string",
+                                                                       "description": "Group with which this module should be loaded"
+                                                               },
+                                                               "position": {
+                                                                       "type": "string",
+                                                                       "description": "Position on the page to load this module at",
+                                                                       "enum": [
+                                                                               "bottom",
+                                                                               "top"
+                                                                       ]
+                                                               },
+                                                               "targets": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "ResourceLoader target the module can run on",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "scripts": {
+                                                                       "type": "array",
+                                                                       "description": "A list of on-wiki pages containing JavaScript that should be loaded",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "styles": {
+                                                                       "type": "array",
+                                                                       "description": "A list of on-wiki pages containing CSS that should be loaded",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "A ResourceLoaderImageModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "class": {
+                                                                       "enum": ["ResourceLoaderImageModule"]
+                                                               },
+                                                               "data": {
+                                                                       "type": "string"
+                                                               },
+                                                               "prefix": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selector": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selectorWithoutVariant": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selectorWithVariant": {
+                                                                       "type": "string"
+                                                               },
+                                                               "variants": {
+                                                                       "type": "object"
+                                                               },
+                                                               "images": {
+                                                                       "type": "object"
+                                                               },
+                                                               "position": {
+                                                                       "enum": [
+                                                                               "top",
+                                                                               "bottom"
+                                                                       ]
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "An arbitrary ResourceLoaderModule definition",
+                                                       "properties": {
+                                                               "class": {
+                                                                       "type": "string",
+                                                                       "pattern": "^((?!ResourceLoader(File|Image)Module).)*$"
+                                                               }
+                                                       },
+                                                       "required": ["class"]
+                                               }
+                                       ]
+                               }
+                       }
+               },
+               "ResourceModuleSkinStyles": {
+                       "type": "object",
+                       "description": "ResourceLoader modules for custom skin styles"
+               },
+               "ResourceLoaderSources": {
+                       "type": "object",
+                       "description": "ResourceLoader sources to register"
+               },
+               "ResourceLoaderLESSVars": {
+                       "type": "object",
+                       "description": "ResourceLoader LESS variables"
+               },
+               "ConfigRegistry": {
+                       "type": "object",
+                       "description": "Registry of factory functions to create Config objects"
+               },
+               "SessionProviders": {
+                       "type": "object",
+                       "description": "Session providers"
+               },
+               "AuthManagerAutoConfig": {
+                       "type": "object",
+                       "description": "AuthManager auto-configuration",
+                       "additionalProperties": false,
+                       "properties": {
+                               "preauth": {
+                                       "type": "object",
+                                       "description": "Pre-authentication providers"
+                               },
+                               "primaryauth": {
+                                       "type": "object",
+                                       "description": "Primary authentication providers"
+                               },
+                               "secondaryauth": {
+                                       "type": "object",
+                                       "description": "Secondary authentication providers"
+                               }
+                       }
+               },
+               "CentralIdLookupProviders": {
+                       "type": "object",
+                       "description": "Central ID lookup providers"
+               },
+               "ChangeCredentialsBlacklist": {
+                       "type": "object",
+                       "description": "AuthenticationRequest classes which can only be used internally for credentials change"
+               },
+               "RemoveCredentialsBlacklist": {
+                       "type": "object",
+                       "description": "AuthenticationRequest classes which can only be used internally for credentials removal"
+               },
+               "namespaces": {
+                       "type": "array",
+                       "description": "Method to add extra namespaces",
+                       "items": {
+                               "type": "object",
+                               "properties": {
+                                       "id": {
+                                               "type": "integer"
+                                       },
+                                       "constant": {
+                                               "type": "string"
+                                       },
+                                       "name": {
+                                               "type": "string"
+                                       },
+                                       "gender": {
+                                               "type": "object",
+                                               "properties": {
+                                                       "male": {
+                                                               "type": "string"
+                                                       },
+                                                       "female": {
+                                                               "type": "string"
+                                                       }
+                                               }
+                                       },
+                                       "subpages": {
+                                               "type": "boolean",
+                                               "default": false
+                                       },
+                                       "content": {
+                                               "type": "boolean",
+                                               "default": false
+                                       },
+                                       "defaultcontentmodel": {
+                                               "type": "string"
+                                       },
+                                       "protection": {
+                                               "type": ["string", "array"],
+                                               "description": "Userright(s) required to edit in this namespace"
+                                       },
+                                       "capitallinkoverride": {
+                                               "type": "boolean",
+                                               "description": "Set $wgCapitalLinks on a per-namespace basis"
+                                       },
+                                       "conditional": {
+                                               "type": "boolean",
+                                               "description": "Whether the namespace is conditional upon configuration and should not be registered (requires separate registration via a hook)",
+                                               "default": false
+                                       }
+                               },
+                               "required": ["id", "constant", "name"]
+                       }
+               },
+               "TrackingCategories": {
+                       "type": "array",
+                       "description": "Tracking category message keys",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "DefaultUserOptions": {
+                       "type": "object",
+                       "description": "Default values of user options"
+               },
+               "HiddenPrefs": {
+                       "type": "array",
+                       "description": "Preferences users cannot set",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "GroupPermissions": {
+                       "type": "object",
+                       "description": "Default permissions to give to user groups",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "RevokePermissions": {
+                       "type": "object",
+                       "description": "Default permissions to revoke from user groups",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "GrantPermissions": {
+                       "type": "object",
+                       "description": "Map of permissions granted to authorized consumers to their bundles, called 'grants'",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "GrantPermissionGroups": {
+                       "type": "object",
+                       "description": "Map of grants to their UI grouping",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "string"
+                               }
+                       }
+               },
+               "ImplicitGroups": {
+                       "type": "array",
+                       "description": "Implicit groups"
+               },
+               "GroupsAddToSelf": {
+                       "type": "object",
+                       "description": "Groups a user can add to themselves"
+               },
+               "GroupsRemoveFromSelf": {
+                       "type": "object",
+                       "description": "Groups a user can remove from themselves"
+               },
+               "AddGroups": {
+                       "type": "object",
+                       "description": "Groups a user can add to users"
+               },
+               "RemoveGroups": {
+                       "type": "object",
+                       "description": "Groups a user can remove from users"
+               },
+               "AvailableRights": {
+                       "type": "array",
+                       "description": "User rights added by the extension",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "ContentHandlers": {
+                       "type": "object",
+                       "description": "Mapping of model ID to class name",
+                       "patternProperties": {
+                               "^[A-Za-z]+$": {
+                                       "type": "string"
+                               }
+                       }
+               },
+               "RateLimits": {
+                       "type": "object",
+                       "description": "Rate limits"
+               },
+               "RecentChangesFlags": {
+                       "type": "object",
+                       "description": "Flags (letter symbols) shown on RecentChanges pages"
+               },
+               "MediaHandlers": {
+                       "type": "object",
+                       "description": "Plugins for media file type handling. Each entry in the array maps a MIME type to a PHP class name."
+               },
+               "ExtensionFunctions": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "Function to call after setup has finished",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "ExtensionMessagesFiles": {
+                       "type": "object",
+                       "description": "File paths containing PHP internationalization data"
+               },
+               "MessagesDirs": {
+                       "type": "object",
+                       "description": "Directory paths containing JSON internationalization data"
+               },
+               "ExtensionEntryPointListFiles": {
+                       "type": "object"
+               },
+               "SpecialPages": {
+                       "type": "object",
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+               },
+               "AutoloadClasses": {
+                       "type": "object"
+               },
+               "Hooks": {
+                       "type": [ "string", "object" ],
+                       "description": "Hooks this extension uses (mapping of hook name to callback)"
+               },
+               "JobClasses": {
+                       "type": "object",
+                       "description": "Job types this extension implements (mapping of job type to class name)"
+               },
+               "LogTypes": {
+                       "type": "array",
+                       "description": "List of new log types this extension uses"
+               },
+               "LogRestrictions": {
+                       "type": "object"
+               },
+               "FilterLogTypes": {
+                       "type": "object"
+               },
+               "ActionFilteredLogs": {
+                       "type": "object",
+                       "description": "List of log types which can be filtered by log actions",
+                       "patternProperties": {
+                               "^[a-z-]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z-]+$": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "LogNames": {
+                       "type": "object"
+               },
+               "LogHeaders": {
+                       "type": "object"
+               },
+               "LogActions": {
+                       "type": "object"
+               },
+               "LogActionsHandlers": {
+                       "type": "object"
+               },
+               "Actions": {
+                       "type": "object"
+               },
+               "APIModules": {
+                       "type": "object"
+               },
+               "APIFormatModules": {
+                       "type": "object"
+               },
+               "APIMetaModules": {
+                       "type": "object"
+               },
+               "APIPropModules": {
+                       "type": "object"
+               },
+               "APIListModules": {
+                       "type": "object"
+               },
+               "ValidSkinNames": {
+                       "type": "object"
+               },
+               "FeedClasses": {
+                       "type": "object",
+                       "description": "Available feeds objects"
+               },
+               "SkinOOUIThemes": {
+                       "type": "object"
+               },
+               "PasswordPolicy": {
+                       "type": "object",
+                       "description": "Password policies"
+               },
+               "FileExtensions": {
+                       "type": "array",
+                       "description": "Preferred file extensions for uploading",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "callback": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "A function to be called right after MediaWiki processes this file"
+               },
+               "config_prefix": {
+                       "type": "string",
+                       "default": "wg",
+                       "description": "Prefix to put in front of configuration settings when exporting them to $GLOBALS"
+               },
+               "config": {
+                       "type": "object",
+                       "description": "Configuration options for this extension",
+                       "patternProperties": {
+                               "^[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*$": {
+                                       "type": "object",
+                                       "properties": {
+                                               "value": {
+                                                       "required": true
+                                               },
+                                               "merge_strategy": {
+                                                       "type": "string",
+                                                       "enum": [
+                                                               "array_merge_recursive",
+                                                               "array_replace_recursive",
+                                                               "array_plus_2d",
+                                                               "array_plus",
+                                                               "array_merge"
+                                                       ],
+                                                       "default": "array_merge"
+                                               },
+                                               "path": {
+                                                       "description": "Whether this should be interpreted as a filesystem path, relative to extension directory root",
+                                                       "type": "boolean",
+                                                       "default": false
+                                               },
+                                               "description": {
+                                                       "type": ["string", "array"],
+                                                       "description": "A description of the config setting, mostly for documentation/developers"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "ParserTestFiles": {
+                       "type": "array",
+                       "description": "Parser test suite files to be run by parserTests.php when no specific filename is passed to it"
+               },
+               "ServiceWiringFiles": {
+                       "type": "array",
+                       "description": "List of service wiring files to be loaded by the default instance of MediaWikiServices"
+               },
+               "load_composer_autoloader": {
+                       "type": "boolean",
+                       "description": "Load the composer autoloader for this extension, if one is present"
+               }
+       }
+}
index f6e76af..8142111 100644 (file)
@@ -75,11 +75,7 @@ class ExtensionJsonValidator {
                }
 
                $version = $data->manifest_version;
-               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
-                       $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
-               } else {
-                       $schemaPath = __DIR__ . '/../../docs/extension.schema.json';
-               }
+               $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
 
                // Not too old
                if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION ) {
index 11995de..71f760d 100644 (file)
@@ -450,8 +450,9 @@ class ExtensionProcessorTest extends MediaWikiTestCase {
                $globalSettings = TestingAccessWrapper::newFromClass(
                        ExtensionProcessor::class )->globalSettings;
 
+               $version = ExtensionRegistry::MANIFEST_VERSION;
                $schema = FormatJson::decode(
-                       file_get_contents( "$IP/docs/extension.schema.json" ),
+                       file_get_contents( "$IP/docs/extension.schema.v$version.json" ),
                        true
                );
                $missing = [];