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

Reply via email to