From: <pau...@us...> - 2007-05-22 23:12:25
|
Revision: 957 http://svn.sourceforge.net/everydevel/?rev=957&view=rev Author: paul_the_nomad Date: 2007-05-22 16:12:13 -0700 (Tue, 22 May 2007) Log Message: ----------- Move node title search into NodeBase.pm to move SQL out of Everything.pm and allow DB independent and flexible title search. Modified Paths: -------------- trunk/ebase/lib/Everything/NodeBase.pm trunk/ebase/lib/Everything/Test/NodeBase.pm trunk/ebase/lib/Everything/Test.pm trunk/ebase/lib/Everything.pm Property Changed: ---------------- trunk/ebase/ Property changes on: trunk/ebase ___________________________________________________________________ Name: svk:merge - 16c2b9cb-492b-4d64-9535-64d4e875048d:/wip/ebase:982 a6810612-c0f9-0310-9d3e-a9e4af8c5745:/ebase/offline:17930 + 16c2b9cb-492b-4d64-9535-64d4e875048d:/wip/ebase:983 a6810612-c0f9-0310-9d3e-a9e4af8c5745:/ebase/offline:17930 Modified: trunk/ebase/lib/Everything/NodeBase.pm =================================================================== --- trunk/ebase/lib/Everything/NodeBase.pm 2007-05-22 23:11:44 UTC (rev 956) +++ trunk/ebase/lib/Everything/NodeBase.pm 2007-05-22 23:12:13 UTC (rev 957) @@ -680,4 +680,61 @@ return Everything::Security::checkPermissions( $perms, $modes ); } + +=head2 C<search_node_title> + +Applies a search algorithm to words passed as arguments + +=over 4 + +=item * + +Takes an array ref of words to search on + + +=item * + +And an array ref of nodetypes to search on + + +=back + +Returns an array of hash refs. + +=cut + +sub search_node_name { + + my ( $self, $words, $types ) = @_; + my $match = ''; + + $types = [$types] if defined $types and $types and ref($types) eq "SCALAR"; + + my $typestr = ''; + if ( ref($types) eq 'ARRAY' and @$types ) { + my $t = shift @$types; + $typestr .= "AND (type_nodetype = " . $self->getId($t); + foreach (@$types) { + $typestr .= " OR type_nodetype = " . $self->getId($_); + } + + $typestr .= ')'; + } + + $match = '%' . join( '%', @$words ) . '%'; + my $cursor = + $self->{storage} + ->sqlSelectMany( "*", "node", "title like ? $typestr", undef, [$match] ); + + return unless $cursor; + + my @ret; + while ( my $m = $cursor->fetchrow_hashref ) { + push @ret, $m; + } + + return \@ret; + +} + 1; Modified: trunk/ebase/lib/Everything/Test/NodeBase.pm =================================================================== --- trunk/ebase/lib/Everything/Test/NodeBase.pm 2007-05-22 23:11:44 UTC (rev 956) +++ trunk/ebase/lib/Everything/Test/NodeBase.pm 2007-05-22 23:12:13 UTC (rev 957) @@ -504,4 +504,67 @@ is( $result, 'cp', '... and returning results' ); } +sub test_search_node_name : Test(10) { + my $self = shift; + + my $nb = $self->{nb}; + + my $mock = Test::MockObject->new; + + my $id = []; + + my $fake_nodes = { foo => 1, bar => 2 }; + $nb->mock( + 'getId', + sub { + push @$id, $fake_nodes->{ $_[1] }; + return $fake_nodes->{ $_[1] }; + } + )->set_always( 'getNode', $mock ); + + $mock->set_series( 'fetchrow_hashref', 1, 2, 3 ); + + $nb->{storage}->set_always( sqlSelectMany => undef ); + + is( $nb->search_node_name(['']), + undef, + 'searchNodeName() should return without workable words to find' ); + + $nb->{storage}->set_always( sqlSelectMany => $mock ); + $mock->set_always( fetchfow_hashref => undef ); + $nb->{storage}->clear; + $mock->clear; + $nb->search_node_name( [''], [ 'foo', 'bar' ] ); + is( $id->[0], 1, '... should call getId() for first type' ); + is( $id->[1], 2, + '... should call getId() for subsequent types (if passed)' ); + + my ( $method, $args ) = $nb->{storage}->next_call; + is ($method, 'sqlSelectMany', '...calls execute against the db cursor.'); + is ($$args[3], 'title like ? AND (type_nodetype = 1 OR type_nodetype = 2)', '... creates sql for types.'); + $nb->{storage}->clear; + $mock->clear; + + $nb->search_node_name(['quote']); + ( $method, $args ) = $nb->{storage}->next_call; + is_deeply( $$args[5], [q{%quote%}], + '... should process searchable words' ); + + # reset series + $mock->set_series( 'fetchrow_hashref', 1, 2, 3 ); + + $nb->{storage}->clear; + $mock->clear; + + my $found = + $nb->search_node_name( ['ab', 'aBc!', 'abcd', 'a', 'ee'], [ 'foo', 'bar' ] ); + ( $method, $args ) = $nb->{storage}->next_call; + is_deeply( $$args[5], ['%ab%aBc!%abcd%a%ee%'], '... processes all search word arguments.' ); + + is( ref $found, 'ARRAY', '... should return an arrayref on success' ); + + is( @$found, 3, '... should find all proper results' ); + is( join( '', @$found ), '123', '... and should return results' ); +} + 1; Modified: trunk/ebase/lib/Everything/Test.pm =================================================================== --- trunk/ebase/lib/Everything/Test.pm 2007-05-22 23:11:44 UTC (rev 956) +++ trunk/ebase/lib/Everything/Test.pm 2007-05-22 23:12:13 UTC (rev 957) @@ -375,13 +375,12 @@ 'getBacksideErrors() should return reference to @bsErrors' ); } -sub test_searchNodeName : Test(12) { +sub test_searchNodeName : Test(8) { my $self = shift; local $Everything::DB = Test::MockObject->new; my $mock = Test::MockObject->new; my $quotes; my $id = []; - my @calls; my $fake_nodes = { foo => 1, bar => 2 }; $Everything::DB->mock( 'getId', @@ -389,11 +388,7 @@ push @$id, $fake_nodes->{ $_[1] }; return $fake_nodes->{ $_[1] }; } - )->set_always( 'getNode', $mock ) - ->set_always( 'getDatabaseHandle', $mock )->mock( - 'sqlSelectMany', - sub { push @calls, [ 'sqlSelectMany', @_ ]; $mock } - ); + )->set_always( 'getNode', $mock ); $mock->mock( 'quote', sub { my $r = qq{'$_[1]'}; $quotes .= $r; $r; } ); $mock->set_series( 'fetchrow_hashref', 1, 2, 3 ); @@ -401,46 +396,28 @@ ## to test skipped words $mock->set_always( getVars => { ab => 1, abcd => 1, } ); + $Everything::DB->set_always( search_node_name => [ 1, 2, 3 ] ); + is( Everything::searchNodeName(''), undef, 'searchNodeName() should return without workable words to find' ); - Everything::searchNodeName( '', [ 'foo', 'bar' ] ); - is( $id->[0], 1, '... should call getId() for first type' ); - is( $id->[1], 2, - '... should call getId() for subsequent types (if passed)' ); - + $Everything::DB->clear; Everything::searchNodeName('quote'); - is( $quotes, q{'[[:<:]]quote[[:>:]]'}, - '... should quote() searchable words' ); - # reset series - $mock->set_series( 'fetchrow_hashref', 1, 2, 3 ); + my ($method, $args) = $Everything::DB->next_call(2); + is ($method, 'search_node_name'); + is_deeply( $args->[1], [q{quote}], + '... passes searchable words to search function' ); + $Everything::DB->clear; my $found = Everything::searchNodeName( 'ab aBc! abcd a ee', [ 'foo', 'bar' ] ); - like( $quotes, qr/abc\\!/, '... should escape nonword chars too' ); + ($method, $args) = $Everything::DB->next_call(2); + is ($method, 'search_node_name', '...calls search node name.'); + is_deeply( $args->[1], ['aBc!'], '... strips out unwanted strings.' ); - is( $calls[-1]->[0], 'sqlSelectMany', - '... should sqlSelectMany() matching titles' ); - like( - $calls[-1]->[2], - qr/\*.+?lower.title.+?rlike.+abc.+/, - '... selecting by title with regexes' - ); - - like( - $calls[-1]->[4], - qr/AND .type_nodetype = 1 OR type_nodetype = 2/, - '... should constrain by type, if provided' - ); - is( - $calls[-1]->[5], - 'ORDER BY matchval DESC', - '... and should order results properly' - ); - is( ref $found, 'ARRAY', '... should return an arrayref on success' ); is( @$found, 3, '... should find all proper results' ); Modified: trunk/ebase/lib/Everything.pm =================================================================== --- trunk/ebase/lib/Everything.pm 2007-05-22 23:11:44 UTC (rev 956) +++ trunk/ebase/lib/Everything.pm 2007-05-22 23:12:13 UTC (rev 957) @@ -486,20 +486,6 @@ my ( $searchWords, $TYPE ) = @_; my $typestr = ''; - $TYPE = [$TYPE] if defined $TYPE and $TYPE and ref($TYPE) eq "SCALAR"; - - if ( ref($TYPE) eq 'ARRAY' and @$TYPE ) - { - my $t = shift @$TYPE; - $typestr .= "AND (type_nodetype = " . getId($t); - foreach (@$TYPE) - { - $typestr .= " OR type_nodetype = " . getId($_); - } - - $typestr .= ')'; - } - my $NOSEARCH = getNode( 'stopwords', 'setting' ); my $NOWORDS = $NOSEARCH ? $NOSEARCH->getVars() : {}; @@ -507,35 +493,7 @@ split ' ', $searchWords; return unless @words; - - my $match = ''; - foreach my $word (@words) - { - $word = lc($word); - $word =~ s/(\W)/\\$1/gs; - $word = '[[:<:]]' . $word . '[[:>:]]'; - $word = - "(lower(title) rlike " - . $DB->getDatabaseHandle()->quote($word) . ")"; - } - - $match = '(' . join( ' + ', @words ) . ')'; - my $cursor = $DB->sqlSelectMany( - "*, $match AS matchval", - "node", - "$match >= 1 $typestr", - "ORDER BY matchval DESC" - ); - - return unless $cursor; - - my @ret; - while ( my $m = $cursor->fetchrow_hashref ) - { - push @ret, $m; - } - - return \@ret; + return $DB->search_node_name(\@words, $TYPE); } =cut This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |