From e5b46f3cedbb6bebca871a4d94c28b1aae6854e1 Mon Sep 17 00:00:00 2001 From: SvenDowideit Date: Sun, 13 Mar 2011 12:23:49 +0000 Subject: [PATCH] Item10338: this aught to give us a much less crashy OP_ref, and may well fix the 'Something broke'-edness Paul found git-svn-id: http://svn.foswiki.org/trunk/MongoDBPlugin@11039 0b4bb1d4-4e5a-0410-9cc4-b2b747904278 --- data/System/MongoDBPlugin.txt | 4 ++ lib/Foswiki/Plugins/MongoDBPlugin.pm | 13 ++++++ .../Plugins/MongoDBPlugin/HoistMongoDB.pm | 33 +++++++-------- templates/mongodb_js.tmpl | 40 +++++++++++++++++++ test/unit/HoistMongoDBsTests.pm | 28 +++++++------ 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/data/System/MongoDBPlugin.txt b/data/System/MongoDBPlugin.txt index 7cd6b66..0683b00 100644 --- a/data/System/MongoDBPlugin.txt +++ b/data/System/MongoDBPlugin.txt @@ -17,6 +17,10 @@ This is an experimental attempt to utilise [[http://mongodb.org][MongoDB]] for a At this point the Plugin is used to populate the MongoDB. All user topic Saves are automatically copied into the MongoDB, and you can batch load using the restHandler: * %SCRIPTURL{rest}%/MongoDBPlugin/update?updateweb=Main +To update the javascript stored in MongoDB + * %SCRIPTURL{rest}%/MongoDBPlugin/updateDatabase + + ---++ Technical details This initial version serialises the internal Meta object directly into _one_ collection, using web.name as a unique index. diff --git a/lib/Foswiki/Plugins/MongoDBPlugin.pm b/lib/Foswiki/Plugins/MongoDBPlugin.pm index 84ee50f..2ebcc8c 100644 --- a/lib/Foswiki/Plugins/MongoDBPlugin.pm +++ b/lib/Foswiki/Plugins/MongoDBPlugin.pm @@ -319,6 +319,19 @@ sub _updateDatabase { my $foswiki_getRef_js = Foswiki::Func::expandTemplate('foswiki_getRef_js'); getMongoDB()->updateSystemJS('foswiki_getRef', $foswiki_getRef_js); + + my $foswiki_getField_js = Foswiki::Func::expandTemplate('foswiki_getField_js'); + getMongoDB()->updateSystemJS('foswiki_getField', $foswiki_getField_js); + + my $foswiki_toLowerCase_js = Foswiki::Func::expandTemplate('foswiki_toLowerCase_js'); + getMongoDB()->updateSystemJS('foswiki_toLowerCase', $foswiki_toLowerCase_js); + + my $foswiki_toUpperCase_js = Foswiki::Func::expandTemplate('foswiki_toUpperCase_js'); + getMongoDB()->updateSystemJS('foswiki_toUpperCase', $foswiki_toUpperCase_js); + + my $foswiki_length_js = Foswiki::Func::expandTemplate('foswiki_length_js'); + getMongoDB()->updateSystemJS('foswiki_length', $foswiki_length_js); + } diff --git a/lib/Foswiki/Plugins/MongoDBPlugin/HoistMongoDB.pm b/lib/Foswiki/Plugins/MongoDBPlugin/HoistMongoDB.pm index 72d6abc..e1d5892 100644 --- a/lib/Foswiki/Plugins/MongoDBPlugin/HoistMongoDB.pm +++ b/lib/Foswiki/Plugins/MongoDBPlugin/HoistMongoDB.pm @@ -384,9 +384,9 @@ my %js_op_map = ( ); my %js_func_map = ( - '#lc' => '.toLowerCase()', - '#uc' => '.toUpperCase()', - '#length' => '.length', + '#lc' => 'foswiki_toLowerCase', + '#uc' => 'foswiki_toUpperCase', + '#length' => 'foswiki_length', '#d2n' => 'foswiki_d2n', '#int' => 'parseInt', '#match' => 'MATCHBANG', @@ -402,10 +402,13 @@ my %js_func_map = ( sub convertFunction { my ( $value, $key ) = @_; - if ( $key eq '#d2n' ) { - return $js_func_map{$key} . '(' . convertStringToJS($value) . ')'; - } - if ( $key eq '#int' ) { + if ( + ( $key eq '#lc' ) or + ( $key eq '#uc' ) or + ( $key eq '#length' ) or + ( $key eq '#d2n' ) or + ( $key eq '#int' ) + ) { return $js_func_map{$key} . '(' . convertStringToJS($value) . ')'; } if ( $key eq '#match' ) { @@ -420,12 +423,10 @@ sub convertFunction { } if ($key eq '#ref') { #TODO: like all accessses, this needs alot of undef protection. - my $addr = convertStringToJS( $$value[1] ); - $addr =~ s/^this//; - return - '(foswiki_getRef(' - . convertStringToJS( $$value[0] ) . ')' - . $addr . ')'; + my $addr = '('.convertStringToJS( $$value[1] ).')'; + my $ref = 'foswiki_getRef(' . convertStringToJS( $$value[0] ) . ')'; + $addr =~ s/this/$ref/; + return $addr; } if ( ( $key eq '#div' ) or ( $key eq '#mult' ) @@ -466,10 +467,10 @@ sub convertStringToJS { #TODO: i _think_ the line below is ok, its needed to make ::test_hoistLengthLHSString work return $string if ( $string =~ /^\'.*/ ); - return $string if ( $string =~ /^this\./ ); - # all registered meta type prefixes use a this. in js - return 'this.' . $string if ( $string =~ /^$fields/ ); + return $string if ( $string =~ /^foswiki_/ ); + return 'foswiki_getField(this, \''.$string.'\')' if ( $string =~ /^$fields/ ); + return $string if ( $string =~ /^$ops$/ ); #for ops, we only want the entirety diff --git a/templates/mongodb_js.tmpl b/templates/mongodb_js.tmpl index 53dad26..deaca67 100644 --- a/templates/mongodb_js.tmpl +++ b/templates/mongodb_js.tmpl @@ -1,3 +1,39 @@ +%{ foswiki_getField attempts to avoid dereferenceing an undefined element. }% +%TMPL:DEF{foswiki_getField_js}%function(this, address) { + var ptr = this; +//address is of the form 'this.TOPICINFO.version' and needs to be separated into individual return undefined if this['TOPICINFO'] == undefined etc + + var addrs = address.split('.'); + for (var name in addrs) { + if (ptr == undefined) { + return ptr; + } + ptr = ptr[name]; + } + return ptr; +}%TMPL:END% +%TMPL:DEF{foswiki_toLowerCase_js}%function(value) { + if (value == undefined) { + return value; + } + return value.toLowerCase(); +}%TMPL:END% + +%TMPL:DEF{foswiki_toUpperCase_js}%function(value) { + if (value == undefined) { + return value; + } + return value.toUpperCase(); +}%TMPL:END% +%TMPL:DEF{foswiki_length_js}%function(value) { + if (value == undefined) { + return value; + } + return value.length; +}%TMPL:END% + + + %TMPL:DEF{foswiki_getRef_js}%function(host, collection, web, topic) { conn = new Mongo(host); current = conn.getCollection(collection); @@ -5,6 +41,10 @@ return current.findOne({_web:web, _topic: topic}); }%TMPL:END% %TMPL:DEF{foswiki_d2n_js}%function(dateString) { + if (dateString == undefined) { + return dateString; + } + var parseTime = function(date, defaultLocal) { // ala Time::Local::timegm() diff --git a/test/unit/HoistMongoDBsTests.pm b/test/unit/HoistMongoDBsTests.pm index f9a5ad8..4ca16d6 100644 --- a/test/unit/HoistMongoDBsTests.pm +++ b/test/unit/HoistMongoDBsTests.pm @@ -724,7 +724,7 @@ sub test_hoistLcRHSName { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'this._topic == \'WebHome\'.toLowerCase()' + '$where' => "this._topic == foswiki_toLowerCase('WebHome')" } ); } @@ -740,7 +740,7 @@ sub test_hoistLcLHSField { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'this.FIELD.Subject.value.toLowerCase() == \'WebHome\'' + '$where' => "foswiki_toLowerCase(foswiki_getField(this, 'FIELD.Subject.value')) == 'WebHome'" } ); } @@ -755,7 +755,7 @@ sub test_hoistLcLHSName { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'this._topic.toLowerCase() == \'WebHome\'' + '$where' => "foswiki_toLowerCase(this._topic) == 'WebHome'" } ); } @@ -784,7 +784,7 @@ sub test_hoistLcLHSLikeName { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => '( /^Web.*$/.test(this._topic.toLowerCase()) )' + '$where' => "( /^Web.*\$/.test(foswiki_toLowerCase(this._topic)) )" } ); } @@ -799,7 +799,7 @@ sub test_hoistLengthLHSName { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'this._topic.length == 12' + '$where' => "foswiki_length(this._topic) == 12" } ); } @@ -813,7 +813,7 @@ sub test_hoistLengthLHSString { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => '\'something\'.length == 9' + '$where' => "foswiki_length('something') == 9" } ); } @@ -828,7 +828,7 @@ sub test_hoistLengthLHSNameGT { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'this._topic.length < 12' + '$where' => "foswiki_length(this._topic) < 12" } ); } @@ -843,7 +843,7 @@ sub test_hoist_d2n_value { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => 'foswiki_d2n(this.FIELD.noatime.value)' + '$where' => "foswiki_d2n(foswiki_getField(this, 'FIELD.noatime.value'))" } ); } @@ -859,7 +859,7 @@ sub test_hoist_d2n_valueAND { $this->do_Assert( $query, $mongoDBQuery, { #TODO: need to figure out how to not make both into js - '$where' => ' ( (foswiki_d2n(this.FIELD.noatime.value)) ) && this.FIELD.topic.value == \'WebHome\'' + '$where' => " ( (foswiki_d2n(foswiki_getField(this, 'FIELD.noatime.value'))) ) && foswiki_getField(this, 'FIELD.topic.value') == 'WebHome'" # '$where' => 'foswiki_d2n(this.FIELD.noatime.value)', # 'FIELD.topic.value' => 'WebHome' } @@ -892,7 +892,7 @@ sub test_hoist_Item10323_1 { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => '( /bio/.test(this.FIELD.TermGroup.value.toLowerCase()) )' + '$where' => "( /bio/.test(foswiki_toLowerCase(foswiki_getField(this, 'FIELD.TermGroup.value'))) )" } ); } @@ -960,7 +960,7 @@ sub test_hoist_maths { $this->do_Assert( $query, $mongoDBQuery, { - '$where' => ' ((12)-(this.FIELD.Namespace.value) < (((24)*(60))*(60))-(5)) && ((this.FIELD.TermGroup.value)/(12) > (this.FIELD.WebScale.value)*(42.8)) ' + '$where' => " ((12)-(foswiki_getField(this, 'FIELD.Namespace.value')) < (((24)*(60))*(60))-(5)) && ((foswiki_getField(this, 'FIELD.TermGroup.value'))/(12) > (foswiki_getField(this, 'FIELD.WebScale.value'))*(42.8)) " } ); } @@ -1320,7 +1320,8 @@ sub test_hoist_dateAndRelationship { $mongoDBQuery, { 'FORM.name' => qr/(?-xism:^.*RelationshipForm$)/, - '$where' => '(this.FIELD.NOW.value)-(this.TOPICINFO.date) < (((60)*(60))*(24))*(7)' + '$where' => "(foswiki_getField(this, 'FIELD.NOW.value'))-(foswiki_getField(this, 'TOPICINFO.date')) < (((60)*(60))*(24))*(7)" + } } ); } @@ -1429,7 +1430,8 @@ sub test_hoist_ref { $query, $mongoDBQuery, { - '$where' => "(foswiki_getRef('AnotherTopic').FIELD.number.value) == 12", + '$where' => "(foswiki_getField(foswiki_getRef('AnotherTopic'), 'FIELD.number.value')) == 12" + #"(foswiki_getRef('AnotherTopic').FIELD.number.value) == 12", } ); }