Lucas Werkmeister (WMDE) has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/358935 )
Change subject: Add QueryTemplate class, helper function, and test
......................................................................
Add QueryTemplate class, helper function, and test
QueryTemplate will eventually wrap most query template-related
functionality which currently lives inside VisualEditor itself; to start
with, it just contains one helper function to split up a query template.
A test for the helper function is also added.
This was originally part of Ic362ea1087.
Change-Id: I36c75009fdead4603d4e41e9aefb739bd342d315
---
M embed.html
M index.html
A wikibase/queryService/ui/visualEditor/QueryTemplate.js
M wikibase/tests/VisualEditor.html
A wikibase/tests/queryService/ui/visualEditor/QueryTemplate.test.js
5 files changed, 121 insertions(+), 1 deletion(-)
git pull ssh://gerrit.wikimedia.org:29418/wikidata/query/gui
refs/changes/35/358935/1
diff --git a/embed.html b/embed.html
index 4dbbc62..869e135 100644
--- a/embed.html
+++ b/embed.html
@@ -149,6 +149,7 @@
<script
src="wikibase/queryService/ui/visualEditor/VisualEditor.js"></script>
<script
src="wikibase/queryService/ui/visualEditor/SparqlQuery.js"></script>
<script
src="wikibase/queryService/ui/visualEditor/SelectorBox.js"></script>
+ <script
src="wikibase/queryService/ui/visualEditor/QueryTemplate.js"></script>
<!-- endbuild -->
<script type="text/javascript">
diff --git a/index.html b/index.html
index 630ca01..9c0a255 100644
--- a/index.html
+++ b/index.html
@@ -275,6 +275,7 @@
<script
src="wikibase/queryService/ui/visualEditor/VisualEditor.js"></script>
<script
src="wikibase/queryService/ui/visualEditor/SparqlQuery.js"></script>
<script
src="wikibase/queryService/ui/visualEditor/SelectorBox.js"></script>
+ <script
src="wikibase/queryService/ui/visualEditor/QueryTemplate.js"></script>
<script src="wikibase/queryService/ui/QueryExampleDialog.js"></script>
<script
src="wikibase/queryService/ui/resultBrowser/helper/FormatterHelper.js"></script>
<script
src="wikibase/queryService/ui/resultBrowser/AbstractResultBrowser.js"></script>
diff --git a/wikibase/queryService/ui/visualEditor/QueryTemplate.js
b/wikibase/queryService/ui/visualEditor/QueryTemplate.js
new file mode 100644
index 0000000..2fe402c
--- /dev/null
+++ b/wikibase/queryService/ui/visualEditor/QueryTemplate.js
@@ -0,0 +1,65 @@
+var wikibase = wikibase || {};
+wikibase.queryService = wikibase.queryService || {};
+wikibase.queryService.ui = wikibase.queryService.ui || {};
+wikibase.queryService.ui.visualEditor = wikibase.queryService.ui.visualEditor
|| {};
+
+wikibase.queryService.ui.visualEditor.QueryTemplate = ( function( $, wikibase
) {
+ 'use strict';
+
+ /**
+ * A template for a SPARQL query
+ *
+ * @class wikibase.queryService.ui.visualEditor.QueryTemplate
+ * @license GNU GPL v2+
+ *
+ * @author Lucas Werkmeister
+ * @constructor
+ */
+ function SELF() {
+ }
+
+ /**
+ * Splits the template 'a ?b c ?d e' into
+ * [ 'a ', '?b', ' c ', '?d', ' e' ].
+ * Text and variable fragments always alternate,
+ * and the first and last fragment are always text fragments
+ * ('' if the template begins or ends in a variable).
+ *
+ * @param {{template: string, variables: string[]}} definition
+ * @return {string[]}
+ */
+ SELF._getQueryTemplateFragments = function( definition ) {
+ if ( definition.template.match( /\0/ ) ) {
+ throw new Error( 'query template must not contain null
bytes' );
+ }
+ var fragments = [ definition.template ],
+ variable,
+ newFragments;
+
+ function splitFragment( fragment ) {
+ var textFragments = fragment
+ .replace( new RegExp( '\\' + variable, 'g' ),
'\0' )
+ .split( '\0' );
+ newFragments.push( textFragments[0] );
+ for ( var i = 1; i < textFragments.length; i++ ) {
+ newFragments.push( variable );
+ newFragments.push( textFragments[ i ] );
+ }
+ }
+
+ for ( variable in definition.variables ) {
+ if ( !variable.match( /\?[a-z][a-z0-9]*/i ) ) {
+ // TODO this is more restrictive than SPARQL;
+ // see
https://www.w3.org/TR/sparql11-query/#rVARNAME
+ throw new Error( 'invalid variable name in
query template' );
+ }
+ newFragments = [];
+ fragments.forEach( splitFragment );
+ fragments = newFragments;
+ }
+
+ return fragments;
+ };
+
+ return SELF;
+}( jQuery, wikibase ) );
diff --git a/wikibase/tests/VisualEditor.html b/wikibase/tests/VisualEditor.html
index 28aad32..ad9e966 100644
--- a/wikibase/tests/VisualEditor.html
+++ b/wikibase/tests/VisualEditor.html
@@ -27,9 +27,11 @@
<script src="../queryService/ui/visualEditor/VisualEditor.js"></script>
<script src="../queryService/ui/visualEditor/SelectorBox.js"></script>
<script src="../queryService/ui/visualEditor/SparqlQuery.js"></script>
+ <script src="../queryService/ui/visualEditor/QueryTemplate.js"></script>
<!-- Tests -->
<script
src="queryService/ui/visualEditor/VisualEditor.test.js"></script>
<script src="queryService/ui/visualEditor/SparqlQuery.test.js"></script>
+ <script
src="queryService/ui/visualEditor/QueryTemplate.test.js"></script>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/wikibase/tests/queryService/ui/visualEditor/QueryTemplate.test.js
b/wikibase/tests/queryService/ui/visualEditor/QueryTemplate.test.js
new file mode 100644
index 0000000..f3ff237
--- /dev/null
+++ b/wikibase/tests/queryService/ui/visualEditor/QueryTemplate.test.js
@@ -0,0 +1,51 @@
+( function ( $, QUnit, sinon, wb ) {
+ 'use strict';
+
+ QUnit.module( 'wikibase.queryService.ui.visualEditor' );
+
+ var QueryTemplate = wb.queryService.ui.visualEditor.QueryTemplate;
+
+ QUnit.test( '_getQueryTemplateFragments internal function', function(
assert ) {
+ assert.expect( 7 );
+
+ assert.deepEqual(
+ QueryTemplate._getQueryTemplateFragments( { template:
'a ?b c ?d e', variables: { '?b': {}, '?d': {} } } ),
+ [ 'a ', '?b', ' c ', '?d', ' e' ],
+ "fragments should be split correctly"
+ );
+ assert.deepEqual(
+ QueryTemplate._getQueryTemplateFragments( { template:
'a ?b c ?d e ?f g', variables: { '?b': {}, '?d': {} } } ),
+ [ 'a ', '?b', ' c ', '?d', ' e ?f g' ],
+ "only variables mentioned in template should be
replaced"
+ );
+ assert.deepEqual(
+ QueryTemplate._getQueryTemplateFragments( { template:
'a ?b c ?b a', variables: { '?b': {} } } ),
+ [ 'a ', '?b', ' c ', '?b', ' a' ],
+ "variables occurring multiple times should work"
+ );
+ assert.deepEqual(
+ QueryTemplate._getQueryTemplateFragments( { template:
'?b a ?b', variables: { '?b': {} } } ),
+ [ '', '?b', ' a ', '?b', '' ],
+ "fragments should always begin and end with text
fragment"
+ );
+ assert.deepEqual(
+ QueryTemplate._getQueryTemplateFragments( { template:
'', variables: { '?b': {} } } ),
+ [ '' ],
+ "empty template should convert to single empty fragment"
+ );
+ assert.throws(
+ function() {
+ QueryTemplate._getQueryTemplateFragments( {
template: 'a \0 c', variables: { '?b': {} } } );
+ },
+ Error,
+ "should not be possible to manipulate the fragment list
via null bytes in template"
+ );
+ assert.throws(
+ function() {
+ QueryTemplate._getQueryTemplateFragments( {
template: 'a b c', variables: { '.*': {} } } );
+ },
+ Error,
+ "should not be possible to manipulate the fragment list
via regex characters in variables"
+ );
+ } );
+}( jQuery, QUnit, sinon, wikibase ) );
--
To view, visit https://gerrit.wikimedia.org/r/358935
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I36c75009fdead4603d4e41e9aefb739bd342d315
Gerrit-PatchSet: 1
Gerrit-Project: wikidata/query/gui
Gerrit-Branch: master
Gerrit-Owner: Lucas Werkmeister (WMDE) <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits