Implement new 'autovalue' parameter property

Add an 'autovalue' parameter property to the TemplateData spec. And
implement it in the validation for the API and in the editor.

Also added tests to make sure all parameter attributes preserve
their values before and after parsing, including the 'autovalue'
parameter.

Bug: 51428
Change-Id: Iffb376a804d39388d2b5b6ea3583ef2a292eea41
This commit is contained in:
Moriel Schottlender 2014-09-02 11:29:33 -04:00 committed by Timo Tijhof
parent 949401fa10
commit 4f3e647758
8 changed files with 168 additions and 19 deletions

View file

@ -95,6 +95,7 @@ $wgResourceModules['ext.templateDataGenerator.core'] = array(
'templatedata-modal-notice-import-numparams',
'templatedata-modal-table-param-actions',
'templatedata-modal-table-param-aliases',
'templatedata-modal-table-param-autovalue',
'templatedata-modal-table-param-default',
'templatedata-modal-table-param-desc',
'templatedata-modal-table-param-label',

View file

@ -88,6 +88,7 @@ class TemplateDataBlob {
'description',
'deprecated',
'aliases',
'autovalue',
'default',
'inherits',
'type',
@ -254,6 +255,20 @@ class TemplateDataBlob {
$paramObj->aliases = array();
}
// Param.autovalue
if ( isset( $paramObj->autovalue ) ) {
if ( !is_string( $paramObj->autovalue ) ) {
// TODO: Validate the autovalue values.
return Status::newFatal(
'templatedata-invalid-type',
"params.{$paramName}.autovalue",
'string'
);
}
} else {
$paramObj->autovalue = null;
}
// Param.default
if ( isset( $paramObj->default ) ) {
if ( !is_string( $paramObj->default ) ) {
@ -586,6 +601,11 @@ class TemplateDataBlob {
array(),
wfMessage( 'templatedata-doc-param-default' )->inLanguage( $lang )->text()
)
. Html::element(
'th',
array(),
wfMessage( 'templatedata-doc-param-autovalue' )->inLanguage( $lang )->text()
)
. Html::element(
'th',
array(),
@ -659,6 +679,16 @@ class TemplateDataBlob {
$paramObj->default :
wfMessage( 'templatedata-doc-param-default-empty' )->inLanguage( $lang )->text()
)
// Auto value
. Html::rawElement( 'td', array(
'class' => array(
'mw-templatedata-doc-muted' => $paramObj->autovalue === null
)
),
$paramObj->autovalue !== null ?
Html::element( 'code', array(), $paramObj->autovalue ) :
wfMessage( 'templatedata-doc-param-autovalue-empty' )->inLanguage( $lang )->escaped()
)
// Status
. Html::element( 'td', array(), wfMessage( $status )->inLanguage( $lang )->text() )
. '</tr>';

View file

@ -7,6 +7,8 @@
},
"templatedata-desc": "Implement data storage for template parameters (using JSON)",
"templatedata-doc-desc-empty": "No description.",
"templatedata-doc-param-autovalue": "Auto value",
"templatedata-doc-param-autovalue-empty": "empty",
"templatedata-doc-param-default": "Default",
"templatedata-doc-param-default-empty": "empty",
"templatedata-doc-param-desc": "Description",
@ -41,6 +43,7 @@
"templatedata-modal-notice-import-numparams": "$1 new {{PLURAL:$1|parameter was|parameters were}} imported.",
"templatedata-modal-table-param-actions": "Actions",
"templatedata-modal-table-param-aliases": "Aliases (comma separated)",
"templatedata-modal-table-param-autovalue": "Auto value",
"templatedata-modal-table-param-default": "Default",
"templatedata-modal-table-param-desc": "Description",
"templatedata-modal-table-param-label": "Label",

View file

@ -13,6 +13,8 @@
},
"templatedata-desc": "{{desc|name=Template Data|url=http://www.mediawiki.org/wiki/Extension:TemplateData}}",
"templatedata-doc-desc-empty": "Displayed when a template has no description (should be a valid sentence).\n{{Identical|No description}}",
"templatedata-doc-param-autovalue": "Used as column heading in the table for auto fill value.\n{{Related|Templatedata-doc-param}}\n",
"templatedata-doc-param-autovalue-empty": "Displayed when a template parameter has no auto filled value (should not be a full sentence, used in a table).\n{{Identical|Empty}}",
"templatedata-doc-param-default": "Used as column heading in the table.\n{{Related|Templatedata-doc-param}}\n{{Identical|Default}}",
"templatedata-doc-param-default-empty": "Displayed when a template parameter has no default value (should not be a full sentence, used in a table).\n{{Identical|Empty}}",
"templatedata-doc-param-desc": "Used as column heading in the table.\n{{Related|Templatedata-doc-param}}\n{{Identical|Description}}",
@ -47,6 +49,7 @@
"templatedata-modal-notice-import-numparams": "Message that appears in the TemplateData generator GUI showing how many new parameters were imported into the GUI from an existing template.\n\nParameters:\n* $1 - number of parameters",
"templatedata-modal-table-param-actions": "Label for a table heading: Parameter actions in the table",
"templatedata-modal-table-param-aliases": "Label for a table heading: Aliases of the parameter, instruct the user to separate aliases with commas.",
"templatedata-modal-table-param-autovalue": "Label for a table heading: Parameter auto value in the table",
"templatedata-modal-table-param-default": "Label for a table heading: Default value of the parameter.\n{{Identical|Default}}",
"templatedata-modal-table-param-desc": "Label for a table heading: Description of the parameter.\n{{Identical|Description}}",
"templatedata-modal-table-param-label": "Label for a table heading: Label of the parameter.\n\nSee https://en.wikipedia.org/w/index.php?title=Template:Infobox_treaty/TemplateData&action=edit for example.\n{{Identical|Label}}",

View file

@ -1262,6 +1262,12 @@
label: 'templatedata-modal-table-param-default',
$element: $( '<input>' )
},
autovalue: {
selector: 'input',
type: 'wikitext',
label: 'templatedata-modal-table-param-autovalue',
$element: $( '<input>' )
},
required: {
selector: 'input[type="checkbox"]',
type: 'checkbox',

View file

@ -62,6 +62,9 @@
@property {string} [inherits] Key to another object in `Root.params`.
The current Param object will inherit from that one, with local properties
overriding the inherited ones.
@property {Type} [autovalue] A dynamically generated default value such as today's
date or the editing user's name. Should generally involve substitution,
such as {{subst:CURRENTMONTHNAME}}.
@structure {Object} Set
@property {InterfaceText} label Label of this set.
@ -130,7 +133,8 @@
"description": {
"en": "Timestamp of when the comment was posted, in YYYY-MM-DD format."
},
"aliases": ["2"]
"aliases": ["2"],
"autovalue": '{{subst:#time:Y-m-d}}'
},
"year": {
"label": "Year",

View file

@ -95,7 +95,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"suggested": false,
"deprecated": false,
"aliases": [],
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo"],
@ -120,6 +121,7 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"label": null,
"description": null,
"default": "",
"autovalue": null,
"required": false,
"suggested": false,
"deprecated": false,
@ -167,7 +169,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"aliases": [
"1"
],
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["nickname"],
@ -207,7 +210,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"default": "example",
"deprecated": false,
"aliases": [],
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"2d": {
"label": null,
@ -219,7 +223,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"default": "overridden",
"deprecated": false,
"aliases": [],
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["1d", "2d"],
@ -303,7 +308,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"bar": {
"label": null,
@ -313,7 +319,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"quux": {
"label": null,
@ -323,7 +330,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo", "bar", "quux"],
@ -344,6 +352,51 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
}',
'status' => true
),
array(
'input' => '{
"description": "Testing some template description.",
"params": {
"bar": {
"label": "Bar label",
"description": "Bar description",
"default": "Baz",
"autovalue": "{{SomeTemplate}}",
"required": true,
"suggested": false,
"deprecated": false,
"aliases": [ "foo", "baz" ],
"type": "line"
}
}
}
',
'output' => '{
"description": {
"en": "Testing some template description."
},
"params": {
"bar": {
"label": {
"en": "Bar label"
},
"description": {
"en": "Bar description"
},
"default": "Baz",
"autovalue": "{{SomeTemplate}}",
"required": true,
"suggested": false,
"deprecated": false,
"aliases": [ "foo", "baz" ],
"type": "line"
}
},
"paramOrder": ["bar"],
"sets": []
}
',
'msg' => 'Parameter attributes preserve information.'
),
array(
// Should be long enough to trigger this condition after gzipping.
'input' => '{
@ -370,6 +423,42 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
return $str;
}
private static function ksort( Array &$input ) {
ksort( $input );
foreach ( $input as $key => &$value ) {
if ( is_array( $value ) ) {
self::ksort( $value );
}
}
}
/**
* PHPUnit'a assertEquals does weak comparison, use strict instead.
*
* There is a built-in assertSame, but that only strictly compares
* the top level structure, not the invidual array values.
*
* so "array( 'a' => '' )" still equals "array( 'a' => null )"
* because empty string equals null in PHP's weak comparison.
*
* @param mixed $expected
* @param mixed $actual
*/
protected function assertStrictJsonEquals( $expected, $actual, $message = null ) {
// Lazy recursive strict comparison: Serialise to JSON and compare that
// Sort first to ensure key-order
$expected = json_decode( $expected, /* assoc = */ true );
$actual = json_decode( $actual, /* assoc = */ true );
self::ksort( $expected );
self::ksort( $actual );
$this->assertEquals(
FormatJson::encode( $expected, true ),
FormatJson::encode( $actual, true ),
$message
);
}
protected function assertTemplateData( Array $case ) {
// Expand defaults
if ( !isset( $case['status'] ) ) {
@ -402,7 +491,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
'Status: ' . $case['msg']
);
}
$this->assertJsonStringEqualsJsonString(
$this->assertStrictJsonEquals(
$case['output'],
$actual,
$case['msg']
@ -421,7 +511,7 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
);
}
$this->assertJsonStringEqualsJsonString(
$this->assertStrictJsonEquals(
$case['output'],
$t->getJSON(),
'Roundtrip: ' . $case['msg']
@ -568,7 +658,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo"],
@ -601,7 +692,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo"],
@ -638,7 +730,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo"],
@ -715,7 +808,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"bar": {
"label": null,
@ -725,7 +819,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"baz": {
"label": null,
@ -735,7 +830,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["foo", "bar", "baz"],
@ -765,7 +861,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"bar": {
"label": null,
@ -775,7 +872,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
},
"baz": {
"label": null,
@ -785,7 +883,8 @@ class TemplateDataBlobTest extends MediaWikiTestCase {
"deprecated": false,
"aliases": [],
"default": "",
"type": "unknown"
"type": "unknown",
"autovalue": null
}
},
"paramOrder": ["baz", "foo", "bar"],

View file

@ -25,6 +25,7 @@
' "en": "Timestamp of when the comment was posted, in YYYY-MM-DD format."' +
' },' +
' "aliases": ["2"],' +
' "autovalue": "{{subst:CURRENTMONTHNAME}}",' +
' "suggested": true' +
' },' +
' "year": {' +
@ -71,6 +72,7 @@
' "aliases": [\n' +
' "2"\n' +
' ],\n' +
' "autovalue": "{{subst:CURRENTMONTHNAME}}",\n' +
' "suggested": true\n' +
' },\n' +
' "year": {\n' +
@ -115,6 +117,7 @@
'description': {
'en': 'Timestamp of when the comment was posted, in YYYY-MM-DD format.'
},
'autovalue': '{{subst:CURRENTMONTHNAME}}',
'aliases': ['2'],
'suggested': true
},