
jesse at bestpractical
Nov 5, 2009, 4:31 PM
Post #1 of 1
(133 views)
Permalink
|
|
rt branch, librarize-search-logic, created. 20fdc5f179a20f0adc1530f2675a216d9afbcf6a
|
|
The branch, librarize-search-logic has been created at 20fdc5f179a20f0adc1530f2675a216d9afbcf6a (commit) - Log ----------------------------------------------------------------- commit 1346a0281f28db61a7cd795a4221298431a75730 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 11:20:06 2009 -0500 First round of moving Search/Build logic to lib/ Conflicts: share/html/Search/Build.html diff --git a/lib/RT/Interface/Web/QueryBuilder.pm b/lib/RT/Interface/Web/QueryBuilder.pm new file mode 100644 index 0000000..788a9de --- /dev/null +++ b/lib/RT/Interface/Web/QueryBuilder.pm @@ -0,0 +1,175 @@ +package RT::Interface::Web::QueryBuilder; +use warnings; +use strict; + +sub process_query { + my $self = shift; + my $ARGS = shift; + my $tree = shift; + my $selected = shift; + my $new = shift || []; + +my @NewSelection = (); + +my @results; +if ( $ARGS->{'up'} || $ARGS->{'down'} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + my $index = $value->getIndex; + my $newindex = $index; + $newindex++ if $ARGS->{'down'}; + $newindex-- if $ARGS->{'up'}; + if ( $newindex < 0 || $newindex >= $parent->getChildCount ) { + push( @results, [ _("error: can't move up"), -1 ] ) if $ARGS->{'up'}; + push( @results, [ _("error: can't move down"), -1 ] ) if $ARGS->{'down'}; + next; + } + + $parent->removeChild( $index ); + $parent->insertChild( $newindex, $value ); + } + } + else { + push( @results, [ _("error: nothing to move"), -1 ] ); + } +} +elsif ( $ARGS->{"left"} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + if( $value->isRoot || $parent->isRoot ) { + push( @results, [ _("error: can't move left"), -1 ] ); + next; + } + + my $grandparent = $parent->getParent; + if( $grandparent->isRoot ) { + push( @results, [ _("error: can't move left"), -1 ] ); + next; + } + + my $index = $parent->getIndex; + $parent->removeChild($value); + $grandparent->insertChild( $index, $value ); + if ( $parent->isLeaf ) { + $grandparent->removeChild($parent); + } + } + } + else { + push( @results, [ _("error: nothing to move"), -1 ] ); + } +} +elsif ( $ARGS->{"right"} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + my $index = $value->getIndex; + + my $newparent; + if ( $index > 0 ) { + my $sibling = $parent->getChild( $index - 1 ); + $newparent = $sibling unless $sibling->isLeaf; + } + $newparent ||= RT::Interface::Web::QueryBuilder::Tree->new( $ARGS->{'and_or'} || 'AND', $parent ); + + $parent->removeChild($value); + $newparent->addChild($value); + } + } + else { + push( @results, [ _("error: nothing to move"), -1 ] ); + } +} +elsif ( $ARGS->{"delete_clause"} ) { + if (@$selected) { + my (@top); + my %Selected = map { $_ => 1 } @$selected; + foreach my $node ( @$selected ) { + my $tmp = $node->getParent; + while ( !$Selected{ $tmp } && !$tmp->isRoot ) { + $tmp = $tmp->getParent; + } + next if $Selected{ $tmp }; + push @top, $node; + } + + my %seen; + my @non_siblings_top = grep !$seen{ $_->getParent }++, @top; + + foreach ( @$new ) { + my $add = $_->clone; + foreach my $sel( @non_siblings_top ) { + my $newindex = $sel->getIndex + 1; + $sel->insertSibling( $newindex, $add ); + } + $add->getParent->setNodeValue( $ARGS->{'and_or'} ); + push @NewSelection, $add; + } + @$new = (); + + while( my $node = shift @top ) { + my $parent = $node->getParent; + $parent->removeChild($node); + $node->DESTROY; + } + @$selected = (); + } + else { + push( @results, [ _("error: nothing to delete"), -1 ] ); + } +} +elsif ( $ARGS->{"toggle"} ) { + if (@$selected) { + my %seen; + my @unique_nodes = grep !$seen{ $_ + 0 }++, + map ref $_->getNodeValue? $_->getParent: $_, + @$selected; + + foreach my $node ( @unique_nodes ) { + if ( $node->getNodeValue eq 'AND' ) { + $node->setNodeValue('OR'); + } + else { + $node->setNodeValue('AND'); + } + } + } + else { + push( @results, [ _("error: nothing to toggle"), -1 ] ); + } +} + +if ( @$new && @$selected ) { + my %seen; + my @non_siblings_selected = grep !$seen{ $_->getParent }++, @$selected; + + foreach ( @$new ) { + my $add = $_->clone; + foreach my $sel( @non_siblings_selected ) { + my $newindex = $sel->getIndex + 1; + $sel->insertSibling( $newindex, $add ); + } + $add->getParent->setNodeValue( $ARGS->{'and_or'} ); + push @NewSelection, $add; + } + @$selected = (); +} +elsif ( @$new ) { + foreach ( @$new ) { + my $add = $_->clone; + $tree->addChild( $add ); + push @NewSelection, $add; + } + $tree->setNodeValue( $ARGS->{'and_or'} ); +} +$_->DESTROY foreach @$new; + +push @$selected, @NewSelection; + +$tree->prune_childless_aggregators; + +return @results; +} +1; diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index fa10b35..915d5b5 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -225,7 +225,7 @@ foreach my $arg ( keys %ARGS ) { $op = "IS NOT"; } - # This isn't "right", but... + # This is not "right", but... # It has to be this way until #5182 is fixed $value = "'NULL'"; } @@ -245,12 +245,12 @@ foreach my $arg ( keys %ARGS ) { } # }}} - -push @actions, $m->comp('Elements/EditQuery:Process', - %ARGS, - tree => $tree, - selected => \@current_values, - new => \@new_values, +use RT::Interface::Web::QueryBuilder; +push @actions, RT::Interface::Web::QueryBuilder->process_query( + \%ARGS, + $tree, + \@current_values, + \@new_values, ); # {{{ Rebuild $Query based on the additions / movements @@ -307,7 +307,7 @@ if ($new_query) { $query_string = 'new_query=1'; } elsif ( $query{'query'} ) { - $query_string = $m->comp('/Elements/QueryString', %query ); +$query_string = URI->new->query_form( %query ); } # }}} diff --git a/share/html/Search/Elements/EditQuery b/share/html/Search/Elements/EditQuery index c3f0d12..19f9cc8 100644 --- a/share/html/Search/Elements/EditQuery +++ b/share/html/Search/Elements/EditQuery @@ -68,176 +68,3 @@ $description => undef $optionlist => '' $actions => [] </%ARGS> - -<%METHOD Process> -<%ARGS> -$tree -$selected - [at] ne => () -</%ARGS> -<%INIT> - -my @NewSelection = (); - -my @results; -if ( $ARGS{'up'} || $ARGS{'down'} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - my $index = $value->getIndex; - my $newindex = $index; - $newindex++ if $ARGS{'down'}; - $newindex-- if $ARGS{'up'}; - if ( $newindex < 0 || $newindex >= $parent->getChildCount ) { - push( @results, [ _("error: can't move up"), -1 ] ) if $ARGS{'up'}; - push( @results, [ _("error: can't move down"), -1 ] ) if $ARGS{'down'}; - next; - } - - $parent->removeChild( $index ); - $parent->insertChild( $newindex, $value ); - } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"left"} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - if( $value->isRoot || $parent->isRoot ) { - push( @results, [ _("error: can't move left"), -1 ] ); - next; - } - - my $grandparent = $parent->getParent; - if( $grandparent->isRoot ) { - push( @results, [ _("error: can't move left"), -1 ] ); - next; - } - - my $index = $parent->getIndex; - $parent->removeChild($value); - $grandparent->insertChild( $index, $value ); - if ( $parent->isLeaf ) { - $grandparent->removeChild($parent); - } - } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"right"} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - my $index = $value->getIndex; - - my $newparent; - if ( $index > 0 ) { - my $sibling = $parent->getChild( $index - 1 ); - $newparent = $sibling unless $sibling->isLeaf; - } - $newparent ||= RT::Interface::Web::QueryBuilder::Tree->new( $ARGS{'and_or'} || 'AND', $parent ); - - $parent->removeChild($value); - $newparent->addChild($value); - } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"delete_clause"} ) { - if (@$selected) { - my (@top); - my %Selected = map { $_ => 1 } @$selected; - foreach my $node ( @$selected ) { - my $tmp = $node->getParent; - while ( !$Selected{ $tmp } && !$tmp->isRoot ) { - $tmp = $tmp->getParent; - } - next if $Selected{ $tmp }; - push @top, $node; - } - - my %seen; - my @non_siblings_top = grep !$seen{ $_->getParent }++, @top; - - foreach ( @new ) { - my $add = $_->clone; - foreach my $sel( @non_siblings_top ) { - my $newindex = $sel->getIndex + 1; - $sel->insertSibling( $newindex, $add ); - } - $add->getParent->setNodeValue( $ARGS{'and_or'} ); - push @NewSelection, $add; - } - @new = (); - - while( my $node = shift @top ) { - my $parent = $node->getParent; - $parent->removeChild($node); - $node->DESTROY; - } - @$selected = (); - } - else { - push( @results, [ _("error: nothing to delete"), -1 ] ); - } -} -elsif ( $ARGS{"toggle"} ) { - if (@$selected) { - my %seen; - my @unique_nodes = grep !$seen{ $_ + 0 }++, - map ref $_->getNodeValue? $_->getParent: $_, - @$selected; - - foreach my $node ( @unique_nodes ) { - if ( $node->getNodeValue eq 'AND' ) { - $node->setNodeValue('OR'); - } - else { - $node->setNodeValue('AND'); - } - } - } - else { - push( @results, [ _("error: nothing to toggle"), -1 ] ); - } -} - -if ( @new && @$selected ) { - my %seen; - my @non_siblings_selected = grep !$seen{ $_->getParent }++, @$selected; - - foreach ( @new ) { - my $add = $_->clone; - foreach my $sel( @non_siblings_selected ) { - my $newindex = $sel->getIndex + 1; - $sel->insertSibling( $newindex, $add ); - } - $add->getParent->setNodeValue( $ARGS{'and_or'} ); - push @NewSelection, $add; - } - @$selected = (); -} -elsif ( @new ) { - foreach ( @new ) { - my $add = $_->clone; - $tree->addChild( $add ); - push @NewSelection, $add; - } - $tree->setNodeValue( $ARGS{'and_or'} ); -} -$_->DESTROY foreach @new; - -push @$selected, @NewSelection; - -$tree->prune_childless_aggregators; - -return @results; -</%INIT> -</%METHOD> commit b2bbf538585fbb95e27693eb7b0f3115e1b294c1 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 14:28:39 2009 -0500 tiny change to how we use base in RT/I18N.pm diff --git a/lib/RT/I18N.pm b/lib/RT/I18N.pm index f4c45df..a8d1b11 100755 --- a/lib/RT/I18N.pm +++ b/lib/RT/I18N.pm @@ -59,7 +59,7 @@ use warnings; use Locale::Maketext 1.04; use Locale::Maketext::Lexicon 0.25; -use base ('Locale::Maketext::Fuzzy'); +use base 'Locale::Maketext::Fuzzy'; use Encode; use MIME::Entity; commit 7dc91a5149e5743f6ac946bd23593184f0e24d60 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 14:29:47 2009 -0500 Added a new format_query_params method to RT::Interface::Web to replace /Elements/QueryString diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm index c948e83..a3a8119 100755 --- a/lib/RT/Interface/Web.pm +++ b/lib/RT/Interface/Web.pm @@ -64,6 +64,8 @@ package RT::Interface::Web; use RT::Report::Tickets; use RT::System; use RT::SavedSearches; +use RT::Interface::Web::QueryBuilder; + use URI qw(); use Digest::MD5 (); use Encode qw(); @@ -289,6 +291,18 @@ sub strip_content { return $content; } + + +sub format_query_params { + my $self = shift; + my %params = @_; + + my $uri = URI->new; + $uri->query_form(%params); + return $uri->query; +} + + package HTML::Mason::Commands; use vars qw/$r $m/; @@ -1493,4 +1507,5 @@ sub _detailed_messages { } + 1; commit c82f2934a4621d3cde7bb2a591739d437ce77f53 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 14:30:36 2009 -0500 extract saved search related display logic from mason components into a library. diff --git a/lib/RT/Interface/Web/QueryBuilder.pm b/lib/RT/Interface/Web/QueryBuilder.pm index 788a9de..a699d67 100644 --- a/lib/RT/Interface/Web/QueryBuilder.pm +++ b/lib/RT/Interface/Web/QueryBuilder.pm @@ -3,173 +3,314 @@ use warnings; use strict; sub process_query { - my $self = shift; - my $ARGS = shift; - my $tree = shift; - my $selected = shift; - my $new = shift || []; - -my @NewSelection = (); - -my @results; -if ( $ARGS->{'up'} || $ARGS->{'down'} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - my $index = $value->getIndex; - my $newindex = $index; - $newindex++ if $ARGS->{'down'}; - $newindex-- if $ARGS->{'up'}; - if ( $newindex < 0 || $newindex >= $parent->getChildCount ) { - push( @results, [ _("error: can't move up"), -1 ] ) if $ARGS->{'up'}; - push( @results, [ _("error: can't move down"), -1 ] ) if $ARGS->{'down'}; - next; - } + my $self = shift; + my $ARGS = shift; + my $tree = shift; + my $selected = shift; + my $new = shift || []; - $parent->removeChild( $index ); - $parent->insertChild( $newindex, $value ); - } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS->{"left"} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - if( $value->isRoot || $parent->isRoot ) { - push( @results, [ _("error: can't move left"), -1 ] ); - next; + my @NewSelection = (); + + my @results; + if ( $ARGS->{'up'} || $ARGS->{'down'} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + my $index = $value->getIndex; + my $newindex = $index; + $newindex++ if $ARGS->{'down'}; + $newindex-- if $ARGS->{'up'}; + if ( $newindex < 0 || $newindex >= $parent->getChildCount ) { + push( @results, [ _("error: can't move up"), -1 ] ) if $ARGS->{'up'}; + push( @results, [ _("error: can't move down"), -1 ] ) if $ARGS->{'down'}; + next; + } + + $parent->removeChild($index); + $parent->insertChild( $newindex, $value ); } + } else { + push( @results, [ _("error: nothing to move"), -1 ] ); + } + } elsif ( $ARGS->{"left"} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + if ( $value->isRoot || $parent->isRoot ) { + push( @results, [ _("error: can't move left"), -1 ] ); + next; + } + + my $grandparent = $parent->getParent; + if ( $grandparent->isRoot ) { + push( @results, [ _("error: can't move left"), -1 ] ); + next; + } - my $grandparent = $parent->getParent; - if( $grandparent->isRoot ) { - push( @results, [ _("error: can't move left"), -1 ] ); - next; + my $index = $parent->getIndex; + $parent->removeChild($value); + $grandparent->insertChild( $index, $value ); + if ( $parent->isLeaf ) { + $grandparent->removeChild($parent); + } } - - my $index = $parent->getIndex; - $parent->removeChild($value); - $grandparent->insertChild( $index, $value ); - if ( $parent->isLeaf ) { - $grandparent->removeChild($parent); + } else { + push( @results, [ _("error: nothing to move"), -1 ] ); + } + } elsif ( $ARGS->{"right"} ) { + if (@$selected) { + foreach my $value (@$selected) { + my $parent = $value->getParent; + my $index = $value->getIndex; + + my $newparent; + if ( $index > 0 ) { + my $sibling = $parent->getChild( $index - 1 ); + $newparent = $sibling unless $sibling->isLeaf; + } + $newparent ||= RT::Interface::Web::QueryBuilder::Tree->new( $ARGS->{'and_or'} || 'AND', $parent ); + + $parent->removeChild($value); + $newparent->addChild($value); } + } else { + push( @results, [ _("error: nothing to move"), -1 ] ); } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS->{"right"} ) { - if (@$selected) { - foreach my $value (@$selected) { - my $parent = $value->getParent; - my $index = $value->getIndex; - - my $newparent; - if ( $index > 0 ) { - my $sibling = $parent->getChild( $index - 1 ); - $newparent = $sibling unless $sibling->isLeaf; + } elsif ( $ARGS->{"delete_clause"} ) { + if (@$selected) { + my (@top); + my %Selected = map { $_ => 1 } @$selected; + foreach my $node (@$selected) { + my $tmp = $node->getParent; + while ( !$Selected{$tmp} && !$tmp->isRoot ) { + $tmp = $tmp->getParent; + } + next if $Selected{$tmp}; + push @top, $node; + } + + my %seen; + my @non_siblings_top = grep !$seen{ $_->getParent }++, @top; + + foreach (@$new) { + my $add = $_->clone; + foreach my $sel (@non_siblings_top) { + my $newindex = $sel->getIndex + 1; + $sel->insertSibling( $newindex, $add ); + } + $add->getParent->setNodeValue( $ARGS->{'and_or'} ); + push @NewSelection, $add; } - $newparent ||= RT::Interface::Web::QueryBuilder::Tree->new( $ARGS->{'and_or'} || 'AND', $parent ); + @$new = (); - $parent->removeChild($value); - $newparent->addChild($value); + while ( my $node = shift @top ) { + my $parent = $node->getParent; + $parent->removeChild($node); + $node->DESTROY; + } + @$selected = (); + } else { + push( @results, [ _("error: nothing to delete"), -1 ] ); } - } - else { - push( @results, [ _("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS->{"delete_clause"} ) { - if (@$selected) { - my (@top); - my %Selected = map { $_ => 1 } @$selected; - foreach my $node ( @$selected ) { - my $tmp = $node->getParent; - while ( !$Selected{ $tmp } && !$tmp->isRoot ) { - $tmp = $tmp->getParent; + } elsif ( $ARGS->{"toggle"} ) { + if (@$selected) { + my %seen; + my @unique_nodes = grep !$seen{ $_ + 0 }++, map ref $_->getNodeValue ? $_->getParent : $_, @$selected; + + foreach my $node (@unique_nodes) { + if ( $node->getNodeValue eq 'AND' ) { + $node->setNodeValue('OR'); + } else { + $node->setNodeValue('AND'); + } } - next if $Selected{ $tmp }; - push @top, $node; + } else { + push( @results, [ _("error: nothing to toggle"), -1 ] ); } + } + if ( @$new && @$selected ) { my %seen; - my @non_siblings_top = grep !$seen{ $_->getParent }++, @top; + my @non_siblings_selected = grep !$seen{ $_->getParent }++, @$selected; - foreach ( @$new ) { + foreach (@$new) { my $add = $_->clone; - foreach my $sel( @non_siblings_top ) { + foreach my $sel (@non_siblings_selected) { my $newindex = $sel->getIndex + 1; $sel->insertSibling( $newindex, $add ); } $add->getParent->setNodeValue( $ARGS->{'and_or'} ); push @NewSelection, $add; } - @$new = (); - - while( my $node = shift @top ) { - my $parent = $node->getParent; - $parent->removeChild($node); - $node->DESTROY; - } @$selected = (); + } elsif (@$new) { + foreach (@$new) { + my $add = $_->clone; + $tree->addChild($add); + push @NewSelection, $add; + } + $tree->setNodeValue( $ARGS->{'and_or'} ); } - else { - push( @results, [ _("error: nothing to delete"), -1 ] ); - } + $_->DESTROY foreach @$new; + + push @$selected, @NewSelection; + + $tree->prune_childless_aggregators; + + return @results; } -elsif ( $ARGS->{"toggle"} ) { - if (@$selected) { - my %seen; - my @unique_nodes = grep !$seen{ $_ + 0 }++, - map ref $_->getNodeValue? $_->getParent: $_, - @$selected; - foreach my $node ( @unique_nodes ) { - if ( $node->getNodeValue eq 'AND' ) { - $node->setNodeValue('OR'); - } - else { - $node->setNodeValue('AND'); - } - } - } - else { - push( @results, [ _("error: nothing to toggle"), -1 ] ); + +sub load_saved_search { + my $self = shift; + my $ARGS = shift; + my $query = shift; + my $saved_search = shift; + my $search_fields = shift || [qw( query format order_by order rows_per_page)]; + + $saved_search->{'id'} = $ARGS->{'saved_search_id'} || 'new'; + $saved_search->{'description'} = $ARGS->{'saved_search_description'} || undef; + $saved_search->{'Privacy'} = $ARGS->{'saved_search_owner'} || undef; + + my @results; + + if ( $ARGS->{'saved_search_revert'} ) { + $ARGS->{'saved_search_load'} = $saved_search->{'id'}; } -} -if ( @$new && @$selected ) { - my %seen; - my @non_siblings_selected = grep !$seen{ $_->getParent }++, @$selected; + if ( $ARGS->{'saved_search_load'} ) { + my ( $container, $id ) = _parse_saved_search( $ARGS->{'saved_search_load'} ); + my $search = $container->attributes->with_id($id); + + $saved_search->{'id'} = $ARGS->{'saved_search_load'}; + $saved_search->{'object'} = $search; + $saved_search->{'description'} = $search->description; + $query->{$_} = $search->sub_value($_) foreach @$search_fields; + + if ( $ARGS->{'saved_search_revert'} ) { + push @results, _( 'Loaded original "%1" saved search', $saved_search->{'description'} ); + } else { + push @results, _( 'Loaded saved search "%1"', $saved_search->{'description'} ); + } + } elsif ( $ARGS->{'saved_search_delete'} ) { + + # We set $SearchId to 'new' above already, so peek into the %ARGS + my ( $container, $id ) = _parse_saved_search( $saved_search->{'id'} ); + if ( $container && $container->id ) { - foreach ( @$new ) { - my $add = $_->clone; - foreach my $sel( @non_siblings_selected ) { - my $newindex = $sel->getIndex + 1; - $sel->insertSibling( $newindex, $add ); + # We have the object the entry is an attribute on; delete the entry... + $container->attributes->delete_entry( name => 'saved_search', id => $id ); + } + $saved_search->{'id'} = 'new'; + $saved_search->{'object'} = undef; + $saved_search->{'description'} = undef; + push @results, _("Deleted saved search"); + } elsif ( $ARGS->{'saved_search_copy'} ) { + my ( $container, $id ) = _parse_saved_search( $ARGS->{'saved_search_id'} ); + $saved_search->{'object'} = $container->attributes->withid($id); + if ( $ARGS->{'saved_search_description'} + && $ARGS->{'saved_search_description'} ne $saved_search->{'object'}->description ) + { + $saved_search->{'description'} = $ARGS->{'saved_search_description'}; + } else { + $saved_search->{'description'} = _( "%1 copy", $saved_search->{'object'}->description ); } - $add->getParent->setNodeValue( $ARGS->{'and_or'} ); - push @NewSelection, $add; + $saved_search->{'id'} = 'new'; + $saved_search->{'object'} = undef; } - @$selected = (); -} -elsif ( @$new ) { - foreach ( @$new ) { - my $add = $_->clone; - $tree->addChild( $add ); - push @NewSelection, $add; + + if ( $saved_search->{'id'} + && $saved_search->{'id'} ne 'new' + && !$saved_search->{'object'} ) + { + my ( $container, $id ) = _parse_saved_search( $ARGS->{'saved_search_id'} ); + $saved_search->{'object'} = $container->attributes->with_id($id); + $saved_search->{'description'} ||= $saved_search->{'object'}->description; } - $tree->setNodeValue( $ARGS->{'and_or'} ); + + return @results; } -$_->DESTROY foreach @$new; -push @$selected, @NewSelection; -$tree->prune_childless_aggregators; +sub save_search { + my $self = shift; + my $ARGS = shift; + my $query = shift; + my $saved_search = shift; + my $search_fields = shift || [qw( query format order_by order rows_per_page)]; + + return unless $ARGS->{'saved_search_save'} || $ARGS->{'saved_search_copy'}; + + my @results; + my $obj = $saved_search->{'object'}; + my $id = $saved_search->{'id'}; + my $desc = $saved_search->{'description'}; + + my $privacy = $saved_search->{'Privacy'}; + + my %params = map { $_ => $query->{$_} } @$search_fields; + my ( $new_obj_type, $new_obj_id ) = split( /\-/, ( $privacy || '' ) ); -return @results; + if ( $obj && $obj->id ) { + + # permission check + if ( $obj->object->isa('RT::System') ) { + unless ( Jifty->web->current_user->has_right( object => RT->system, right => 'SuperUser' ) ) { + push @results, _("No permission to save system-wide searches"); + return @results; + } + } + + $obj->set_sub_values(%params); + $obj->set_description($desc); + + my $obj_type = ref( $obj->object ); + + # We need to get current obj_id now, because when we change obj_type to + # RT::System, $obj->object->id returns 1, not the old one :( + my $obj_id = $obj->object->id; + + if ( $new_obj_type && $new_obj_id ) { + my ( $val, $msg ); + if ( $new_obj_type ne $obj_type ) { + ( $val, $msg ) = $obj->set_objectType($new_obj_type); + push @results, _( 'Unable to set privacy object: %1', $msg ) unless ($val); + } + if ( $new_obj_id != $obj_id ) { + ( $val, $msg ) = $obj->set_objectid($new_obj_id); + push @results, _( 'Unable to set privacy id: %1', $msg ) unless ($val); + } + } else { + push @results, _('Unable to determine object type or id'); + } + push @results, _( 'Updated saved search "%1"', $desc ); + } elsif ( $id eq 'new' ) { + my $saved_search = RT::SavedSearch->new(); + my ( $status, $msg ) = $saved_search->save( + privacy => $privacy, + name => $desc, + type => $saved_search->{'type'}, + search_params => \%params, + ); + + if ($status) { + $saved_search->{'object'} = Jifty->web->current_user->user_object->attributes->with_id( $saved_search->id ); + + # Build new SearchId + $saved_search->{'id'} + = ref( Jifty->web->current_user->user_object ) . '-' + . Jifty->web->current_user->user_object->id + . '-SavedSearch-' + . $saved_search->{'object'}->id; + } else { + push @results, _("Can't find a saved search to work with") . ': ' . _($msg); + } + } else { + push @results, _("Can't save this search"); + } + + return @results; } + + 1; diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 915d5b5..93b69ed 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -125,7 +125,7 @@ for( qw(query format order_by order rows_per_page) ) { } my %saved_search; -my @actions = $m->comp( 'Elements/EditSearches:Init', %ARGS, query => \%query, saved_search => \%saved_search); +my @actions = RT::Interface::Web::QueryBuilder->load_saved_search(\%ARGS, \%query, \%saved_search); if ( $new_query ) { @@ -278,7 +278,8 @@ my ( $AvailableColumns, $current_format ); # }}} # if we're asked to save the current search, save it -push @actions, $m->comp( 'Elements/EditSearches:Save', %ARGS, query => \%query, saved_search => \%saved_search); +push @actions, RT::Interface::Web::QueryBuilder->save_search(\%ARGS, \%query, \%saved_search); + # {{{ Push the updates into the session so we don't loose 'em @@ -307,7 +308,7 @@ if ($new_query) { $query_string = 'new_query=1'; } elsif ( $query{'query'} ) { -$query_string = URI->new->query_form( %query ); +$query_string = RT::Interface::Web->format_query_params( %query ); } # }}} diff --git a/share/html/Search/Elements/EditSearches b/share/html/Search/Elements/EditSearches index fa0be1a..5bed321 100644 --- a/share/html/Search/Elements/EditSearches +++ b/share/html/Search/Elements/EditSearches @@ -135,157 +135,3 @@ $allow_copy => 1 $title => _('Saved searches') </%ARGS> -<%METHOD Init> -<%ARGS> -$query => {} -$saved_search => {} - [at] search_field => qw(Query format order_by order rows_per_page) -</%ARGS> -<%INIT> - - -$saved_search->{'id'} = $ARGS{'saved_search_id'} || 'new'; -$saved_search->{'description'} = $ARGS{'saved_search_description'} || undef; -$saved_search->{'Privacy'} = $ARGS{'saved_search_owner'} || undef; - -my @results; - -if ( $ARGS{'saved_search_revert'} ) { - $ARGS{'saved_search_load'} = $saved_search->{'id'}; -} - -if ( $ARGS{'saved_search_load'} ) { - my ($container, $id ) = _parse_saved_search ($ARGS{'saved_search_load'}); - my $search = $container->attributes->with_id( $id ); - - $saved_search->{'id'} = $ARGS{'saved_search_load'}; - $saved_search->{'object'} = $search; - $saved_search->{'description'} = $search->description; - $query->{$_} = $search->sub_value($_) foreach @search_fields; - - if ( $ARGS{'saved_search_revert'} ) { - push @results, _('Loaded original "%1" saved search', $saved_search->{'description'} ); - } else { - push @results, _('Loaded saved search "%1"', $saved_search->{'description'} ); - } -} -elsif ( $ARGS{'saved_search_delete'} ) { - # We set $SearchId to 'new' above already, so peek into the %ARGS - my ($container, $id) = _parse_saved_search( $saved_search->{'id'} ); - if ( $container && $container->id ) { - # We have the object the entry is an attribute on; delete the entry... - $container->attributes->delete_entry( name => 'saved_search', id => $id ); - } - $saved_search->{'id'} = 'new'; - $saved_search->{'object'} = undef; - $saved_search->{'description'} = undef; - push @results, _("Deleted saved search"); -} -elsif ( $ARGS{'saved_search_copy'} ) { - my ($container, $id ) = _parse_saved_search( $ARGS{'saved_search_id'} ); - $saved_search->{'object'} = $container->attributes->withid( $id ); - if ( $ARGS{'saved_search_description'} && $ARGS{'saved_search_description'} ne $saved_search->{'object'}->description ) { - $saved_search->{'description'} = $ARGS{'saved_search_description'}; - } else { - $saved_search->{'description'} = _( "%1 copy", $saved_search->{'object'}->description ); - } - $saved_search->{'id'} = 'new'; - $saved_search->{'object'} = undef; -} - -if ( $saved_search->{'id'} && $saved_search->{'id'} ne 'new' - && !$saved_search->{'object'} ) -{ - my ($container, $id ) = _parse_saved_search( $ARGS{'saved_search_id'} ); - $saved_search->{'object'} = $container->attributes->with_id( $id ); - $saved_search->{'description'} ||= $saved_search->{'object'}->description; -} - -return @results; - -</%INIT> -</%METHOD> - -<%METHOD Save> -<%ARGS> -$query => {} -$saved_search => {} - [at] search_field => qw(query format order_by order rows_per_page) -</%ARGS> -<%INIT> - -return unless $ARGS{'saved_search_save'} || $ARGS{'saved_search_copy'}; - -my @results; -my $obj = $saved_search->{'object'}; -my $id = $saved_search->{'id'}; -my $desc = $saved_search->{'description'}; - -my $privacy = $saved_search->{'Privacy'}; - -my %params = map { $_ => $query->{$_} } @search_fields; -my ($new_obj_type, $new_obj_id) = split(/\-/, ($privacy || '')); - -if ( $obj && $obj->id ) { - # permission check - if ($obj->object->isa('RT::System')) { - unless (Jifty->web->current_user->has_right( object=> RT->system, right => 'SuperUser')) { - push @results, _("No permission to save system-wide searches"); - return @results; - } - } - - $obj->set_sub_values( %params ); - $obj->set_description( $desc ); - - my $obj_type = ref($obj->object); - # We need to get current obj_id now, because when we change obj_type to - # RT::System, $obj->object->id returns 1, not the old one :( - my $obj_id = $obj->object->id; - - if ( $new_obj_type && $new_obj_id ) { - my ($val, $msg); - if ( $new_obj_type ne $obj_type ) { - ($val, $msg ) = $obj->set_objectType($new_obj_type); - push @results, _('Unable to set privacy object: %1', $msg) unless ( $val ); - } - if ( $new_obj_id != $obj_id ) { - ($val, $msg) = $obj->set_objectid($new_obj_id); - push @results, _('Unable to set privacy id: %1', $msg) unless ( $val ); - } - } else { - push @results, _('Unable to determine object type or id'); - } - push @results, _('Updated saved search "%1"', $desc); -} -elsif ( $id eq 'new' ) { - my $saved_search = RT::SavedSearch->new(); - my ($status, $msg) = $saved_search->save( - privacy => $privacy, - name => $desc, - type => $saved_search->{'type'}, - search_params => \%params, - ); - - if ( $status ) { - $saved_search->{'object'} = - Jifty->web->current_user->user_object->attributes->with_id( $saved_search->id ); - # Build new SearchId - $saved_search->{'id'} = - ref( Jifty->web->current_user->user_object ) . '-' - . Jifty->web->current_user->user_object->id - . '-SavedSearch-' - . $saved_search->{'object'}->id; - } - else { - push @results, _("Can't find a saved search to work with").': '._($msg); - } -} -else { - push @results, _("Can't save this search"); -} - -return @results; - -</%INIT> -</%METHOD> diff --git a/share/html/Ticket/Graphs/index.html b/share/html/Ticket/Graphs/index.html index 40ba94f..52ab0aa 100644 --- a/share/html/Ticket/Graphs/index.html +++ b/share/html/Ticket/Graphs/index.html @@ -84,12 +84,7 @@ foreach my $level ( 0 .. 6 ) { push @save_arguments, "Level-". $level ."-Properties"; } my $saved_search = { type => 'Graph' }; -push @results, $m->comp( '/Search/Elements/EditSearches:Init', - %ARGS, - query => \%ARGS, - saved_search => $saved_search, - search_fields => \@save_arguments, -); +push @results, RT::Interface::Web::QueryBuilder->load_saved_search(\%ARGS, \%ARGS, $saved_search, \@save_arguments); my $id = $ARGS{'id'}; my $ticket = load_ticket( $id ); @@ -104,12 +99,7 @@ if ( $ARGS{'show_links'} && !ref $ARGS{'show_links'} ) { $ARGS{'show_links'} = [ grep $_ ne $ARGS{'leading_link'}, @{ $ARGS{'show_links'} } ]; $ARGS{'max_depth'} = 3 unless defined $ARGS{'max_depth'} && length $ARGS{'max_depth'}; -push @results, $m->comp( '/Search/Elements/EditSearches:Save', - %ARGS, - query => \%ARGS, - saved_search => $saved_search, - search_fields => \@save_arguments, -); +push @results, RT::Interface::Web::QueryBuilder->save_search(\%ARGS, \%ARGS, $saved_search, \@save_arguments); my $title = _( "Ticket #%1 relationships graph", $id ); </%INIT> commit a76a42f2ab98429c6b4b952249210d96b11c0f2b Merge: c82f293 d70f744 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 14:34:59 2009 -0500 Merge commit 'origin/3.999-trunk' into librarize-search-logic * commit 'origin/3.999-trunk': ShowLinks was made aware of autovivification of queue objects commit 048c9f30b546c1856f6163808c45c5357b638e22 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 14:45:26 2009 -0500 remove {{{ }}} and tidy Build.html diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 93b69ed..060801d 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -1,4 +1,4 @@ -%# BEGIN BPS TAGGED BLOCK {{{ +%# BEGIN BPS TAGGED BLOCK @@ -44,7 +44,7 @@ -%# END BPS TAGGED BLOCK }}} +%# END BPS TAGGED BLOCK @@ -120,14 +120,14 @@ use RT::Interface::Web::QueryBuilder::Tree; my %query; -for( qw(query format order_by order rows_per_page) ) { +for (qw(query format order_by order rows_per_page)) { $query{$_} = $ARGS{$_}; } my %saved_search; -my @actions = RT::Interface::Web::QueryBuilder->load_saved_search(\%ARGS, \%query, \%saved_search); +my @actions = RT::Interface::Web::QueryBuilder->load_saved_search( \%ARGS, \%query, \%saved_search ); -if ( $new_query ) { +if ($new_query) { # Wipe all data-carrying variables clear if we want a new # search, or we're deleting an old one.. @@ -141,31 +141,32 @@ if ( $new_query ) { Jifty->web->session->get('tickets')->clean_slate if defined Jifty->web->session->get('tickets'); } -{ # Attempt to load what we can from the session and preferences, set defaults +{ # Attempt to load what we can from the session and preferences, set defaults my $current = Jifty->web->session->get('CurrentSearchHash'); - my $prefs = Jifty->web->current_user->user_object->preferences("SearchDisplay") || {}; - my $default = {query => '', format => '', order_by => 'id', order => 'ASC', rows_per_page => 50 }; + my $prefs = Jifty->web->current_user->user_object->preferences("SearchDisplay") || {}; + my $default = { query => '', format => '', order_by => 'id', order => 'ASC', rows_per_page => 50 }; - for( qw(query format order_by order rows_per_page) ) { + for (qw(query format order_by order rows_per_page)) { $query{$_} = $current->{$_} unless defined $query{$_}; - $query{$_} = $prefs->{$_} unless defined $query{$_}; + $query{$_} = $prefs->{$_} unless defined $query{$_}; $query{$_} = $default->{$_} unless defined $query{$_}; } - for( qw(order order_by) ) { - if (ref $query{$_} eq "ARRAY") { + for (qw(order order_by)) { + if ( ref $query{$_} eq "ARRAY" ) { $query{$_} = join( '|', @{ $query{$_} } ); } } if ( $query{'format'} ) { + # Clean unwanted junk from the format $query{'format'} = $m->comp( '/Elements/ScrubHTML', content => $query{'format'} ); } } -my $parse_query = sub { - my ($string, $results) = @_; +my $parse_query = sub { + my ( $string, $results ) = @_; my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); @$results = $tree->parse_sql( query => $string ); @@ -180,33 +181,35 @@ if ( $actions[0] ) { return $m->comp( "Edit.html", query => $query{'query'}, actions => \@actions ); } -my @options = $tree->get_displayed_nodes; +my @options = $tree->get_displayed_nodes; my @current_values = grep defined, @options[@clauses]; -my @new_values = (); +my @new_values = (); -# {{{ Try to find if we're adding a clause +# Try to find if we're adding a clause foreach my $arg ( keys %ARGS ) { - next unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ - && ( ref $ARGS{$arg} eq "ARRAY" - ? grep $_ ne '', @{ $ARGS{$arg} } - : $ARGS{$arg} ne '' ); + next + unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ + && (ref $ARGS{$arg} eq "ARRAY" + ? grep $_ ne '', @{ $ARGS{$arg} } + : $ARGS{$arg} ne '' + ); # We're adding a $1 clause my $field = $1; - my ($op, $value); + my ( $op, $value ); #figure out if it's a grouping my $keyword = $ARGS{ $field . "_field" } || $field; my ( @ops, @values ); if ( ref $ARGS{ 'value_of_' . $field } eq "ARRAY" ) { + # we have many keys/values to iterate over, because there is # more than one CF with the same name. @ops = @{ $ARGS{ $field . '_op' } }; @values = @{ $ARGS{ 'value_of_' . $field } }; - } - else { + } else { @ops = ( $ARGS{ $field . '_op' } ); @values = ( $ARGS{ 'value_of_' . $field } ); } @@ -220,16 +223,14 @@ foreach my $arg ( keys %ARGS ) { if ( $value eq 'NULL' && $op =~ /=/ ) { if ( $op eq '=' ) { $op = "IS"; - } - elsif ( $op eq '!=' ) { + } elsif ( $op eq '!=' ) { $op = "IS NOT"; } # This is not "right", but... # It has to be this way until #5182 is fixed $value = "'NULL'"; - } - else { + } else { $value =~ s/'/\\'/g; $value = "'$value'" unless $value =~ /^\d+$/; } @@ -244,74 +245,61 @@ foreach my $arg ( keys %ARGS ) { } } -# }}} use RT::Interface::Web::QueryBuilder; -push @actions, RT::Interface::Web::QueryBuilder->process_query( - \%ARGS, - $tree, - \@current_values, - \@new_values, -); +push @actions, RT::Interface::Web::QueryBuilder->process_query( \%ARGS, $tree, \@current_values, \@new_values, ); -# {{{ Rebuild $Query based on the additions / movements +# Rebuild $Query based on the additions / movements my $optionlist_arrayref; -($query{'query'}, $optionlist_arrayref) = $tree->get_query_and_option_list(\@current_values); +( $query{'query'}, $optionlist_arrayref ) = $tree->get_query_and_option_list( \@current_values ); -my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) - . (" " x (5 * $_->{DEPTH})) - . $m->interp->apply_escapes($_->{TEXT}, 'h') . qq(</option>) } @$optionlist_arrayref; - -# }}} +my $optionlist = join "\n", map { + qq(<option value="$_->{INDEX}" $_->{SELECTED}>) + . ( " " x ( 5 * $_->{DEPTH} ) ) + . $m->interp->apply_escapes( $_->{TEXT}, 'h' ) + . qq(</option>) +} @$optionlist_arrayref; my $queues = $tree->get_referenced_queues; -# {{{ Deal with format changes +# Deal with format changes my ( $AvailableColumns, $current_format ); ( $query{'format'}, $AvailableColumns, $current_format ) = $m->comp( 'Elements/BuildFormatString', %ARGS, cfqueues => $queues, - format => $query{'format'}, + format => $query{'format'}, ); -# }}} - # if we're asked to save the current search, save it -push @actions, RT::Interface::Web::QueryBuilder->save_search(\%ARGS, \%query, \%saved_search); +push @actions, RT::Interface::Web::QueryBuilder->save_search( \%ARGS, \%query, \%saved_search ); +# Push the updates into the session so we don't loose 'em -# {{{ Push the updates into the session so we don't loose 'em - -Jifty->web->session->set('CurrentSearchHash', { - %query, - search_id => $saved_search{'id'}, - object => $saved_search{'object'}, - description => $saved_search{'description'}, -} ); - -# }}} +Jifty->web->session->set( + 'CurrentSearchHash', + { %query, + search_id => $saved_search{'id'}, + object => $saved_search{'object'}, + description => $saved_search{'description'}, + } +); -# {{{ Show the results, if we were asked. +# Show the results, if we were asked. if ( $ARGS{'do_search'} ) { $m->comp( 'Results.html', %query ); $m->abort; } -# }}} - -# {{{ Build a query_string for the tabs +# Build a query_string for the tabs my $query_string = ''; if ($new_query) { $query_string = 'new_query=1'; +} elsif ( $query{'query'} ) { + $query_string = RT::Interface::Web->format_query_params(%query); } -elsif ( $query{'query'} ) { -$query_string = RT::Interface::Web->format_query_params( %query ); -} - -# }}} </%INIT> commit cf15d14559267c7f4f4849193a3f9dfae487f442 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 15:22:09 2009 -0500 Replace Elements/ScrubHTML with a library routine diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm index a3a8119..ea1842f 100755 --- a/lib/RT/Interface/Web.pm +++ b/lib/RT/Interface/Web.pm @@ -66,9 +66,12 @@ use RT::System; use RT::SavedSearches; use RT::Interface::Web::QueryBuilder; + use URI qw(); use Digest::MD5 (); use Encode qw(); +use HTML::Scrubber; + =head2 web_canonicalize_info(); @@ -302,6 +305,33 @@ sub format_query_params { return $uri->query; } +my $scrubber = HTML::Scrubber->new(); +$scrubber->default( + 0, + { + '*' => 0, + id => 1, + class => 1, + # Match http, ftp and relative urls + # XXX: we also scrub format strings with this module then allow simple config options + href => qr{^(?:http:|ftp:|https:|/|__Web(?:Path|baseURL|URL)__)}i, + face => 1, + size => 1, + target => 1, + style => qr{^(?:(?:color:\s*rgb\(\d+,\s*\d+,\s*\d+\))| + (?:text-align:\s*))}ix, + } +); +$scrubber->deny(qw[*]); +$scrubber->allow( qw[.A B U P BR I HR BR SMALL EM FONT SPAN STRONG SUB SUP STRIKE H1 H2 H3 H4 H5 H6 DIV UL OL LI DL DT DD PRE]); +$scrubber->comment(0); + +sub scrub_html { + my $self = shift; + my $content = shift; + return $scrubber->scrub($content); +} + package HTML::Mason::Commands; diff --git a/share/html/Elements/CollectionAsTable/Header b/share/html/Elements/CollectionAsTable/Header index 6bd146d..283cde1 100644 --- a/share/html/Elements/CollectionAsTable/Header +++ b/share/html/Elements/CollectionAsTable/Header @@ -102,7 +102,7 @@ foreach my $col ( @format ) { ); unless( $tmp ) { - $title = $m->comp('/Elements/ScrubHTML', content => $title); + $title = RT::Interface::Web->scrub_html( $title); } else { if ( UNIVERSAL::isa( $tmp, 'CODE' ) ) { my @tmp = $tmp->( $title ); diff --git a/share/html/Elements/CollectionList b/share/html/Elements/CollectionList index 015a424..89329b5 100644 --- a/share/html/Elements/CollectionList +++ b/share/html/Elements/CollectionList @@ -84,8 +84,8 @@ $collection->set_page_info( $display_format ||= $format; # Scrub the html of the format string to remove any potential nasties. -$format = $m->comp('/Elements/ScrubHTML', content => $format); -$display_format = $m->comp('/Elements/ScrubHTML', content => $display_format); +$format = RT::Interface::Web->scrub_html( $format); +$display_format = RT::Interface::Web->scrub_html( $display_format); my @format = $m->comp('/Elements/CollectionAsTable/ParseFormat', format => $display_format); diff --git a/share/html/Elements/ScrubHTML b/share/html/Elements/ScrubHTML deleted file mode 100644 index 912cc80..0000000 --- a/share/html/Elements/ScrubHTML +++ /dev/null @@ -1,77 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC -%# <jesse [at] bestpractical> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -<%ONCE> -my $scrubber = new HTML::Scrubber; -$scrubber->default( - 0, - { - '*' => 0, - id => 1, - class => 1, - # Match http, ftp and relative urls - # XXX: we also scrub format strings with this module then allow simple config options - href => qr{^(?:http:|ftp:|https:|/|__Web(?:Path|baseURL|URL)__)}i, - face => 1, - size => 1, - target => 1, - style => qr{^(?:(?:color:\s*rgb\(\d+,\s*\d+,\s*\d+\))| - (?:text-align:\s*))}ix, - } -); -$scrubber->deny(qw[*]); -$scrubber->allow( - qw[.A B U P BR I HR BR SMALL EM FONT SPAN STRONG SUB SUP STRIKE H1 H2 H3 H4 H5 H6 DIV UL OL LI DL DT DD PRE] -); -$scrubber->comment(0); -</%ONCE> -<%init> -return $scrubber->scrub($content); -</%init> -<%args> -$content => undef -</%args> diff --git a/share/html/Elements/ShowCustomFieldText b/share/html/Elements/ShowCustomFieldText index 6955f4a..c0b0d23 100644 --- a/share/html/Elements/ShowCustomFieldText +++ b/share/html/Elements/ShowCustomFieldText @@ -47,7 +47,7 @@ %# END BPS TAGGED BLOCK }}} <%init> my $content = $object->large_content || $object->content; - $content = $m->comp('/Elements/ScrubHTML', content => $content); + $content = RT::Interface::Web->scrub_html( $content); $content =~ s|\n|<br />|g; </%init> <%$content|n%> diff --git a/share/html/Elements/ShowCustomFieldWikitext b/share/html/Elements/ShowCustomFieldWikitext index 7be0d7d..4567fec 100644 --- a/share/html/Elements/ShowCustomFieldWikitext +++ b/share/html/Elements/ShowCustomFieldWikitext @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} % my $content = $object->large_content || $object->content; -% $content = $m->comp('/Elements/ScrubHTML', content => $content); +% $content = RT::Interface::Web->scrub_html( $content); % my $base = $object->object->wiki_base; % my $wiki_content = Text::WikiFormat::format( $content."\n" , {}, { extended => 1, absolute_links => 1, implicit_links => RT->config->get('wiki_implicit_links'), prefix => $base} ); <%$wiki_content|n%> diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 060801d..a0332f3 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -161,7 +161,7 @@ if ($new_query) { if ( $query{'format'} ) { # Clean unwanted junk from the format - $query{'format'} = $m->comp( '/Elements/ScrubHTML', content => $query{'format'} ); + $query{'format'} = RT::Interface::Web->scrub_html( $query{'format'} ); } } diff --git a/share/html/Search/Edit.html b/share/html/Search/Edit.html index 4c7c467..9e86374 100755 --- a/share/html/Search/Edit.html +++ b/share/html/Search/Edit.html @@ -73,7 +73,7 @@ </&> <%INIT> my $title = _("Edit Query"); -$format = $m->comp('/Elements/ScrubHTML', content => $format); +$format = RT::Interface::Web->scrub_html( $format); my $query_string = $m->comp('/Elements/QueryString', query => $query, format => $format, diff --git a/share/html/Ticket/Elements/ShowTransactionAttachments b/share/html/Ticket/Elements/ShowTransactionAttachments index ae63080..28652f0 100644 --- a/share/html/Ticket/Elements/ShowTransactionAttachments +++ b/share/html/Ticket/Elements/ShowTransactionAttachments @@ -117,7 +117,7 @@ unless ( ($message->get_header('Content-Disposition')||"") =~ /attachment/i ) { # if it's a text/html clean the body and show it if ( $message->content_type =~ m{^text/(?:html|enriched)$}i ) { - $content = $m->comp( '/Elements/ScrubHTML', content => $content ); + $content = RT::Interface::Web->scrub_html( $content ); if ( $message->content_type eq 'text/html' ) { $m->comp('/Elements/MakeClicky', content => \$content, html => 1 ); commit 5dec3e324f0d46891b4cc0c7a13cfc2a6a879a83 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:27:53 2009 -0500 librarize BuildFormatString diff --git a/lib/RT/Interface/Web/QueryBuilder.pm b/lib/RT/Interface/Web/QueryBuilder.pm index a699d67..6eff61f 100644 --- a/lib/RT/Interface/Web/QueryBuilder.pm +++ b/lib/RT/Interface/Web/QueryBuilder.pm @@ -312,5 +312,179 @@ sub save_search { return @results; } +sub build_format_string { + my $self = shift; + my %args = ( + format => RT->config->get('default_search_result_format'), + cfqueues => undef, + face => undef, + size => undef, + link => undef, + title => undef, + add_col => undef, + remove_col => undef, + col_up => undef, + col_down => undef, + select_display_columns => undef, + current_display_columns => undef, + @_ + ); + + # All the things we can display in the format string by default + my @fields = qw( + id queue_name subject + status extended_status update_status + type owner_name requestors cc admin_cc created_by last_updated_by + priority initial_priority final_priority + time_worked time_left time_estimated + starts starts_relative + started started_relative + created created_relative + last_updated last_updated_relative + told told_relative + due due_relative + resolved resolved_relative + refers_to referred_to_by + depends_on depended_on_by + member_of members + parents children + Bookmark + NEWLINE Bookmark + ); # loc_qw + + my $CustomFields = RT::Model::CustomFieldCollection->new(); + foreach my $id ( keys %{$args{cfqueues}} ) { + + # Gotta load up the $queue object, since queues get stored by name now. my $id + my $queue = RT::Model::Queue->new(); + $queue->load($id); + unless ( $queue->id ) { + + # XXX TODO: This ancient code dates from a former developer + # we have no idea what it means or why cfqueues are so encoded. + $id =~ s/^.'*(.*).'*$/$1/; + $queue->load($id); + } + $CustomFields->limit_to_queue( $queue->id ); + } + $CustomFields->limit_to_global; + + while ( my $CustomField = $CustomFields->next ) { + push @fields, "custom_field.{" . $CustomField->name . "}"; + } + + my (@seen); + + my @format = split( /,\s*/, $args{format} ); + foreach my $field (@format) { + my %column = (); + $field =~ s/'(.*)'/$1/; + my ( $prefix, $suffix ); + if ( $field =~ m/(.*)__(.*)__(.*)/ ) { + $prefix = $1; + $suffix = $3; + $field = $2; + } + $field = "<blank>" if !$field; + $column{Prefix} = $prefix; + $column{Suffix} = $suffix; + $field =~ s/\s*(.*)\s*/$1/; + $column{Column} = $field; + push @seen, \%column; + } + + if ( $args{remove_col} ) { + + # we do this regex match to avoid a non-numeric warning + my ($index) = $args{current_display_columns} =~ /^(\d+)/; + + my $column = $seen[$index]; + if ($index) { + delete $seen[$index]; + my @temp = @seen; + @seen = (); + foreach my $element (@temp) { + next unless $element; + push @seen, $element; + } + } + } elsif ( $args{add_col} ) { + if ( defined $args{select_display_columns} ) { + my $selected = $args{select_display_columns}; + my @columns; + if ( ref($selected) eq 'ARRAY' ) { + @columns = @$selected; + } else { + push @columns, $selected; + } + foreach my $col (@columns) { + my %column = (); + $column{Column} = $col; + + if ( $args{face} eq "Bold" ) { + $column{Prefix} .= "<b>"; + $column{Suffix} .= "</b>"; + } + if ( $args{face} eq "Italic" ) { + $column{Prefix} .= "<i>"; + $column{Suffix} .= "</i>"; + } + if ($args{size}) { + $column{Prefix} .= "<" . Jifty->web->escape($args{size}) . ">"; + $column{Suffix} .= "</" . Jifty->web->escape($args{size}) . ">"; + } + if ( $args{link} eq "Display" ) { + $column{Prefix} .= q{<a HREF="__WebPath__/Ticket/Display.html?id=__id__">}; + $column{Suffix} .= "</a>"; + } elsif ( $args{link} eq "Take" ) { + $column{Prefix} .= q{<a HREF="__WebPath__/Ticket/Display.html?Action=Take&id=__id__">}; + $column{Suffix} .= "</a>"; + } + + if ( $args{title} ) { + $column{Suffix} .= "/TITLE:" . Jifty->web->escape( $args{title} ); + } + push @seen, \%column; + } + } + } elsif ( $args{col_up} ) { + my $index = $args{current_display_columns}; + if ( defined $index && ( $index - 1 ) >= 0 ) { + my $column = $seen[$index]; + $seen[$index] = $seen[ $index - 1 ]; + $seen[ $index - 1 ] = $column; + $args{current_display_columns} = $index - 1; + } + } elsif ( $args{col_down} ) { + my $index = $args{current_display_columns}; + if ( defined $index && ( $index + 1 ) < scalar @seen ) { + my $column = $seen[$index]; + $seen[$index] = $seen[ $index + 1 ]; + $seen[ $index + 1 ] = $column; + $args{current_display_columns} = $index + 1; + } + } + + my @format_string; + foreach my $field (@seen) { + next unless $field; + my $row = "'"; + $row .= $field->{'Prefix'} if defined $field->{'Prefix'}; + $row .= "__" . ( + $field->{'Column'} =~ m/\(/ + ? $field->{'Column'} # func, don't escape + : Jifty->web->escape( $field->{'Column'} ) + ) + . "__" + unless ( $field->{'Column'} eq "<blank>" ); + $row .= $field->{'Suffix'} if defined $field->{'Suffix'}; + $row .= "'"; + push( @format_string, $row ); + } + + return ( join( ",\n", @format_string ), \@fields, \@seen ); + +} + 1; diff --git a/share/html/Prefs/Search.html b/share/html/Prefs/Search.html index 8712afa..6e62506 100644 --- a/share/html/Prefs/Search.html +++ b/share/html/Prefs/Search.html @@ -98,8 +98,7 @@ $ARGS{'order'} = join '|', grep defined && /\S/, (ref $ARGS{'order'})? @{$ARGS{' $ARGS{'order_by'} = join '|', grep defined && /\S/, (ref $ARGS{'order_by'})? @{$ARGS{'order_by'}}: $ARGS{'order_by'}; my ( $AvailableColumns, $current_format ); -( $ARGS{format}, $AvailableColumns, $current_format ) = $m->comp( - '/Search/Elements/BuildFormatString', +( $ARGS{format}, $AvailableColumns, $current_format ) = RT::Interface::Web::QueryBuilder->build_format_string( cfqueues => {}, %ARGS ); diff --git a/share/html/Prefs/SearchOptions.html b/share/html/Prefs/SearchOptions.html index c92ee4d..2136df7 100644 --- a/share/html/Prefs/SearchOptions.html +++ b/share/html/Prefs/SearchOptions.html @@ -96,8 +96,7 @@ $order_by ||= ($prefs->{'order_by'} || 'id'); ($rows_per_page = defined( $prefs->{'rows_per_page'} ) ? $prefs->{'rows_per_page'} : 50) unless defined ($rows_per_page); my ( $AvailableColumns, $current_format ); -( $format, $AvailableColumns, $current_format ) = $m->comp( - '/Search/Elements/BuildFormatString', +( $format, $AvailableColumns, $current_format ) = RT::Interface::Web::QueryBuilder->build_format_string( %ARGS, format => $format ); </%INIT> diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index a0332f3..bb49c89 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -264,8 +264,8 @@ my $queues = $tree->get_referenced_queues; # Deal with format changes my ( $AvailableColumns, $current_format ); -( $query{'format'}, $AvailableColumns, $current_format ) = $m->comp( - 'Elements/BuildFormatString', + +( $query{'format'}, $AvailableColumns, $current_format ) = RT::Interface::Web::QueryBuilder->build_format_string( %ARGS, cfqueues => $queues, format => $query{'format'}, diff --git a/share/html/Search/Elements/BuildFormatString b/share/html/Search/Elements/BuildFormatString deleted file mode 100644 index eca3fd9..0000000 --- a/share/html/Search/Elements/BuildFormatString +++ /dev/null @@ -1,230 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC -%# <jesse [at] bestpractical> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/copyleft/gpl.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -<%ARGS> -$format => RT->config->get('default_search_result_format') -%cfqueues => () -$face => undef -$size => undef -$link => undef -$title => undef - -$add_col => undef -$remove_col => undef -$col_up => undef -$col_down => undef - -$select_display_columns => undef -$current_display_columns => undef -</%ARGS> - -<%init> -# This can't be in a <once> block, because otherwise we return the -# same \@fields every request, and keep tacking more CustomFields onto -# it -- and it grows per request. - -# All the things we can display in the format string by default -my @fields = qw( - id queue_name subject - status extended_status update_status - type owner_name requestors cc admin_cc created_by last_updated_by - priority initial_priority final_priority - time_worked time_left time_estimated - starts starts_relative - started started_relative - created created_relative - last_updated last_updated_relative - told told_relative - due due_relative - resolved resolved_relative - refers_to referred_to_by - depends_on depended_on_by - member_of members - parents children - Bookmark - NEWLINE Bookmark -); # loc_qw - -$m->callback( callback_once => 1, callback_name => 'SetFieldsOnce', Fields => \@fields ); - -my $CustomFields = RT::Model::CustomFieldCollection->new( current_user => Jifty->web->current_user); -foreach my $id (keys %cfqueues) { - # Gotta load up the $queue object, since queues get stored by name now. my $id - my $queue = RT::Model::Queue->new( current_user => Jifty->web->current_user ); - $queue->load($id); - unless ($queue->id) { - # XXX TODO: This ancient code dates from a former developer - # we have no idea what it means or why cfqueues are so encoded. - $id =~ s/^.'*(.*).'*$/$1/; - $queue->load($id); - } - $CustomFields->limit_to_queue($queue->id); -} -$CustomFields->limit_to_global; - -while ( my $CustomField = $CustomFields->next ) { - push @fields, "custom_field.{" . $CustomField->name . "}"; -} - -$m->callback( Fields => \@fields, args_ref => \%ARGS ); - -my ( @seen); - -$format ||= RT->config->get('default_search_result_format'); -my @format = split( /,\s*/, $format ); -foreach my $field (@format) { - my %column = (); - $field =~ s/'(.*)'/$1/; - my ( $prefix, $suffix ); - if ( $field =~ m/(.*)__(.*)__(.*)/ ) { - $prefix = $1; - $suffix = $3; - $field = $2; - } - $field = "<blank>" if !$field; - $column{Prefix} = $prefix; - $column{Suffix} = $suffix; - $field =~ s/\s*(.*)\s*/$1/; - $column{Column} = $field; - push @seen, \%column; -} - -if ( $remove_col ) { - # we do this regex match to avoid a non-numeric warning - my ($index) = $current_display_columns =~ /^(\d+)/; - - my $column = $seen[$index]; - if ($index) { - delete $seen[$index]; - my @temp = @seen; - @seen = (); - foreach my $element (@temp) { - next unless $element; - push @seen, $element; - } - } -} -elsif ( $add_col ) { - if ( defined $select_display_columns ) { - my $selected = $select_display_columns; - my @columns; - if (ref($selected) eq 'ARRAY') { - @columns = @$selected; - } else { - push @columns, $selected; - } - foreach my $col (@columns) { - my %column = (); - $column{Column} = $col; - - if ( $face eq "Bold" ) { - $column{Prefix} .= "<b>"; - $column{Suffix} .= "</b>"; - } - if ( $face eq "Italic" ) { - $column{Prefix} .= "<i>"; - $column{Suffix} .= "</i>"; - } - if ($size) { - $column{Prefix} .= "<" . $m->interp->apply_escapes( $size, 'h' ) . ">"; - $column{Suffix} .= "</" . $m->interp->apply_escapes( $size, 'h' ) . ">"; - } - if ( $link eq "Display" ) { - $column{Prefix} .= q{<a HREF="__WebPath__/Ticket/Display.html?id=__id__">}; - $column{Suffix} .= "</a>"; - } - elsif ( $link eq "Take" ) { - $column{Prefix} .= q{<a HREF="__WebPath__/Ticket/Display.html?Action=Take&id=__id__">}; - $column{Suffix} .= "</a>"; - } - - if ($title) { - $column{Suffix} .= "/TITLE:" . $m->interp->apply_escapes( $title, 'h' ); - } - push @seen, \%column; - } - } -} -elsif ( $col_up ) { - my $index = $current_display_columns; - if ( defined $index && ( $index - 1 ) >= 0 ) { - my $column = $seen[$index]; - $seen[$index] = $seen[ $index - 1 ]; - $seen[ $index - 1 ] = $column; - $current_display_columns = $index - 1; - } -} -elsif ( $col_down ) { - my $index = $current_display_columns; - if ( defined $index && ( $index + 1 ) < scalar @seen ) { - my $column = $seen[$index]; - $seen[$index] = $seen[ $index + 1 ]; - $seen[ $index + 1 ] = $column; - $current_display_columns = $index + 1; - } -} - - -my @format_string; -foreach my $field (@seen) { - next unless $field; - my $row = "'"; - $row .= $field->{'Prefix'} if defined $field->{'Prefix'}; - $row .= "__" . ($field->{'Column'} =~ m/\(/ ? $field->{'Column'} # func, don't escape - : $m->interp->apply_escapes( $field->{'Column'}, 'h' )) . "__" - unless ( $field->{'Column'} eq "<blank>" ); - $row .= $field->{'Suffix'} if defined $field->{'Suffix'}; - $row .= "'"; - push( @format_string, $row ); -} - -$format = join(",\n", @format_string); - - -return($format, \@fields, \@seen); - -</%init> commit bdb999258e08f19d6c5f2b61beb47565d7dd3c47 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:29:23 2009 -0500 remove a mason escaping call diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index bb49c89..5770448 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -256,7 +256,7 @@ my $optionlist_arrayref; my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) . ( " " x ( 5 * $_->{DEPTH} ) ) - . $m->interp->apply_escapes( $_->{TEXT}, 'h' ) + . Jifty->web->escape( $_->{TEXT}) . qq(</option>) } @$optionlist_arrayref; commit 6b08e74a1c449cf301154e87bd17ce0c0157d0ca Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:48:59 2009 -0500 incremental refactoring diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 5770448..7929b74 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -106,7 +106,7 @@ <& Elements/DisplayOptions, %ARGS, %query, - available_columns => $AvailableColumns, + available_columns => $available_columns, current_format => $current_format, &> @@ -119,12 +119,8 @@ <%INIT> use RT::Interface::Web::QueryBuilder::Tree; -my %query; -for (qw(query format order_by order rows_per_page)) { - $query{$_} = $ARGS{$_}; -} - my %saved_search; +my %query = map { $_ => $ARGS{$_} } qw(query format order_by order rows_per_page); my @actions = RT::Interface::Web::QueryBuilder->load_saved_search( \%ARGS, \%query, \%saved_search ); if ($new_query) { @@ -157,24 +153,13 @@ if ($new_query) { if ( ref $query{$_} eq "ARRAY" ) { $query{$_} = join( '|', @{ $query{$_} } ); } - } - if ( $query{'format'} ) { + } - # Clean unwanted junk from the format - $query{'format'} = RT::Interface::Web->scrub_html( $query{'format'} ); - } + $query{'format'} = RT::Interface::Web->scrub_html( $query{'format'} ) if ( $query{'format'} ); } -my $parse_query = sub { - my ( $string, $results ) = @_; - - my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); - @$results = $tree->parse_sql( query => $string ); - - return $tree; -}; - -my $tree = $parse_query->( $query{'query'}, \@actions ); +my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); +push @actions, = $tree->parse_sql( query => $query{query} ); # if parsing went poorly, send them to the edit page to fix it if ( $actions[0] ) { @@ -185,36 +170,35 @@ my @options = $tree->get_displayed_nodes; my @current_values = grep defined, @options[@clauses]; my @new_values = (); -# Try to find if we're adding a clause foreach my $arg ( keys %ARGS ) { - next - unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ - && (ref $ARGS{$arg} eq "ARRAY" - ? grep $_ ne '', @{ $ARGS{$arg} } - : $ARGS{$arg} ne '' - ); - - # We're adding a $1 clause - my $field = $1; + # Try to find if we're adding a clause + next unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ && (ref $ARGS{$arg} eq "ARRAY" ? grep $_ ne '', @{ $ARGS{$arg} } : $ARGS{$arg} ne ''); + my $field = $1; my ( $op, $value ); #figure out if it's a grouping my $keyword = $ARGS{ $field . "_field" } || $field; - my ( @ops, @values ); - if ( ref $ARGS{ 'value_of_' . $field } eq "ARRAY" ) { + my ( @ops, @values ); + + my $op_name = $field. "_op"; + my $op_value = 'value_of_'.$field; + + if ( ref $ARGS{$op_value} eq "ARRAY" ) { # we have many keys/values to iterate over, because there is # more than one CF with the same name. - @ops = @{ $ARGS{ $field . '_op' } }; - @values = @{ $ARGS{ 'value_of_' . $field } }; + @ops = @{ $ARGS{ $op_name } }; + @values = @{ $ARGS{ $op_value } }; } else { - @ops = ( $ARGS{ $field . '_op' } ); - @values = ( $ARGS{ 'value_of_' . $field } ); - } - Jifty->log->error("Bad Parameters passed into Query Builder") - unless @ops == @values; + @ops = ( $ARGS{ $op_name } ); + @values = ( $ARGS{ $op_value } ); + } + + + + Jifty->log->error("Bad Parameters passed into Query Builder") unless @ops == @values; for ( my $i = 0; $i < @ops; $i++ ) { my ( $op, $value ) = ( $ops[$i], $values[$i] ); @@ -257,15 +241,14 @@ my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) . ( " " x ( 5 * $_->{DEPTH} ) ) . Jifty->web->escape( $_->{TEXT}) - . qq(</option>) -} @$optionlist_arrayref; + . qq(</option>) } @$optionlist_arrayref; my $queues = $tree->get_referenced_queues; # Deal with format changes -my ( $AvailableColumns, $current_format ); +my ( $available_columns, $current_format ); -( $query{'format'}, $AvailableColumns, $current_format ) = RT::Interface::Web::QueryBuilder->build_format_string( +( $query{'format'}, $available_columns, $current_format ) = RT::Interface::Web::QueryBuilder->build_format_string( %ARGS, cfqueues => $queues, format => $query{'format'}, @@ -276,8 +259,7 @@ push @actions, RT::Interface::Web::QueryBuilder->save_search( \%ARGS, \%query, \ # Push the updates into the session so we don't loose 'em -Jifty->web->session->set( - 'CurrentSearchHash', +Jifty->web->session->set( 'CurrentSearchHash', { %query, search_id => $saved_search{'id'}, object => $saved_search{'object'}, commit 2fad999bd772e8e4cf7a113c7a96e8124486874a Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:50:24 2009 -0500 incremental refactoring diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 7929b74..6a77a0c 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -186,15 +186,10 @@ foreach my $arg ( keys %ARGS ) { my $op_name = $field. "_op"; my $op_value = 'value_of_'.$field; - if ( ref $ARGS{$op_value} eq "ARRAY" ) { - # we have many keys/values to iterate over, because there is - # more than one CF with the same name. - @ops = @{ $ARGS{ $op_name } }; - @values = @{ $ARGS{ $op_value } }; - } else { - @ops = ( $ARGS{ $op_name } ); - @values = ( $ARGS{ $op_value } ); - } + # we may have many keys/values to iterate over, because there + # may be more than one CF with the same name. + @ops = ref $ARGS{$op_value} ? @{ $ARGS{ $op_name } } : $ARGS{$op_name}; + @values = ref $ARGS{$op_value} ? @{ $ARGS{ $op_value } } : $ARGS{$op_value}; commit d85893c906619d110c6f71a2ad70144b89fb120a Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:50:42 2009 -0500 perltidy diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 6a77a0c..4ca110e 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -171,8 +171,11 @@ my @current_values = grep defined, @options[@clauses]; my @new_values = (); foreach my $arg ( keys %ARGS ) { - # Try to find if we're adding a clause - next unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ && (ref $ARGS{$arg} eq "ARRAY" ? grep $_ ne '', @{ $ARGS{$arg} } : $ARGS{$arg} ne ''); + + # Try to find if we're adding a clause + next + unless $arg =~ m/^value_of_(\w+|'CF.{.*?}')$/ + && ( ref $ARGS{$arg} eq "ARRAY" ? grep $_ ne '', @{ $ARGS{$arg} } : $ARGS{$arg} ne '' ); my $field = $1; my ( $op, $value ); @@ -180,18 +183,15 @@ foreach my $arg ( keys %ARGS ) { #figure out if it's a grouping my $keyword = $ARGS{ $field . "_field" } || $field; - my ( @ops, @values ); - - - my $op_name = $field. "_op"; - my $op_value = 'value_of_'.$field; - - # we may have many keys/values to iterate over, because there - # may be more than one CF with the same name. - @ops = ref $ARGS{$op_value} ? @{ $ARGS{ $op_name } } : $ARGS{$op_name}; - @values = ref $ARGS{$op_value} ? @{ $ARGS{ $op_value } } : $ARGS{$op_value}; + my ( @ops, @values ); + my $op_name = $field . "_op"; + my $op_value = 'value_of_' . $field; + # we may have many keys/values to iterate over, because there + # may be more than one CF with the same name. + @ops = ref $ARGS{$op_value} ? @{ $ARGS{$op_name} } : $ARGS{$op_name}; + @values = ref $ARGS{$op_value} ? @{ $ARGS{$op_value} } : $ARGS{$op_value}; Jifty->log->error("Bad Parameters passed into Query Builder") unless @ops == @values; commit 8da265dd6181ffc9f22a42ee14fcf0fb6adb3df1 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 16:52:01 2009 -0500 typo fix diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 4ca110e..df6b6c3 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -159,7 +159,7 @@ if ($new_query) { } my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); -push @actions, = $tree->parse_sql( query => $query{query} ); +push @actions, $tree->parse_sql( query => $query{query} ); # if parsing went poorly, send them to the edit page to fix it if ( $actions[0] ) { commit e08153afd1ace3939b1cf17b36a2c91b9b10209d Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 17:38:26 2009 -0500 remove a temp variable diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index df6b6c3..d2660b1 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -214,13 +214,13 @@ foreach my $arg ( keys %ARGS ) { $value = "'$value'" unless $value =~ /^\d+$/; } - my $clause = { - Key => $keyword, - Op => $op, - Value => $value - }; + push @new_values, RT::Interface::Web::QueryBuilder::Tree->new( + { Key => $keyword, + Op => $op, + Value => $value + } - push @new_values, RT::Interface::Web::QueryBuilder::Tree->new($clause); + ); } } commit d3229b63b34c22e0561a12606da939a5dd4f7f3e Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:00:10 2009 -0500 remove a workaround for a bug 4 years ago diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index d2660b1..059f5a6 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -205,10 +205,6 @@ foreach my $arg ( keys %ARGS ) { } elsif ( $op eq '!=' ) { $op = "IS NOT"; } - - # This is not "right", but... - # It has to be this way until #5182 is fixed - $value = "'NULL'"; } else { $value =~ s/'/\\'/g; $value = "'$value'" unless $value =~ /^\d+$/; commit ebcaa03b0845f2dd435b97ec642504cd6e225bc1 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:01:11 2009 -0500 one more line down diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 059f5a6..1e7ba36 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -183,15 +183,13 @@ foreach my $arg ( keys %ARGS ) { #figure out if it's a grouping my $keyword = $ARGS{ $field . "_field" } || $field; - my ( @ops, @values ); - my $op_name = $field . "_op"; my $op_value = 'value_of_' . $field; # we may have many keys/values to iterate over, because there # may be more than one CF with the same name. - @ops = ref $ARGS{$op_value} ? @{ $ARGS{$op_name} } : $ARGS{$op_name}; - @values = ref $ARGS{$op_value} ? @{ $ARGS{$op_value} } : $ARGS{$op_value}; + my @ops = ref $ARGS{$op_value} ? @{ $ARGS{$op_name} } : $ARGS{$op_name}; + my @values = ref $ARGS{$op_value} ? @{ $ARGS{$op_value} } : $ARGS{$op_value}; Jifty->log->error("Bad Parameters passed into Query Builder") unless @ops == @values; commit 306d05b930d472069e5b0b9e848976f91a8985e2 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:01:25 2009 -0500 runtime bad web params don't merit logged errors diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 1e7ba36..4f31560 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -191,7 +191,7 @@ foreach my $arg ( keys %ARGS ) { my @ops = ref $ARGS{$op_value} ? @{ $ARGS{$op_name} } : $ARGS{$op_name}; my @values = ref $ARGS{$op_value} ? @{ $ARGS{$op_value} } : $ARGS{$op_value}; - Jifty->log->error("Bad Parameters passed into Query Builder") unless @ops == @values; + Jifty->log->debug("Bad Parameters passed into Query Builder") unless @ops == @values; for ( my $i = 0; $i < @ops; $i++ ) { my ( $op, $value ) = ( $ops[$i], $values[$i] ); commit 2df7ebc690749164e85d6b7b8be9dca3f6c0c21a Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:02:52 2009 -0500 declared and then not used diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 4f31560..0c9b3fa 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -178,7 +178,6 @@ foreach my $arg ( keys %ARGS ) { && ( ref $ARGS{$arg} eq "ARRAY" ? grep $_ ne '', @{ $ARGS{$arg} } : $ARGS{$arg} ne '' ); my $field = $1; - my ( $op, $value ); #figure out if it's a grouping my $keyword = $ARGS{ $field . "_field" } || $field; commit 0ee30e6a7ea5de1d39c2787730942df03ab92c0a Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:05:29 2009 -0500 removed unneeded lines diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm index ea1842f..06af369 100755 --- a/lib/RT/Interface/Web.pm +++ b/lib/RT/Interface/Web.pm @@ -66,7 +66,6 @@ use RT::System; use RT::SavedSearches; use RT::Interface::Web::QueryBuilder; - use URI qw(); use Digest::MD5 (); use Encode qw(); diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 0c9b3fa..24af53b 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -217,7 +217,6 @@ foreach my $arg ( keys %ARGS ) { } } -use RT::Interface::Web::QueryBuilder; push @actions, RT::Interface::Web::QueryBuilder->process_query( \%ARGS, $tree, \@current_values, \@new_values, ); # Rebuild $Query based on the additions / movements commit 8c36128ee57e7e9d525a63d1e42a0a8177ec165f Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:32:08 2009 -0500 redirect rather than fall through for results display diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 24af53b..fb5a638 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -153,9 +153,9 @@ if ($new_query) { if ( ref $query{$_} eq "ARRAY" ) { $query{$_} = join( '|', @{ $query{$_} } ); } - } + } - $query{'format'} = RT::Interface::Web->scrub_html( $query{'format'} ) if ( $query{'format'} ); + $query{'format'} = RT::Interface::Web->scrub_html( $query{'format'} ) if ( $query{'format'} ); } my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); @@ -227,7 +227,7 @@ my $optionlist_arrayref; my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) . ( " " x ( 5 * $_->{DEPTH} ) ) - . Jifty->web->escape( $_->{TEXT}) + . Jifty->web->escape( $_->{TEXT}) . qq(</option>) } @$optionlist_arrayref; my $queues = $tree->get_referenced_queues; @@ -257,8 +257,9 @@ Jifty->web->session->set( 'CurrentSearchHash', # Show the results, if we were asked. if ( $ARGS{'do_search'} ) { - $m->comp( 'Results.html', %query ); - $m->abort; + Jifty->web->redirect( Jifty->web->url . "Search/Results.html?" . + RT::Interface::Web->format_query_params(%query) ); + } # Build a query_string for the tabs commit e75caec4ea20db7b5f229bb40c8a6f8d9a5b8f53 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:33:03 2009 -0500 kill a bandaid we haven't needed in a looong time. diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index fb5a638..63acca5 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -161,10 +161,6 @@ if ($new_query) { my $tree = RT::Interface::Web::QueryBuilder::Tree->new('AND'); push @actions, $tree->parse_sql( query => $query{query} ); -# if parsing went poorly, send them to the edit page to fix it -if ( $actions[0] ) { - return $m->comp( "Edit.html", query => $query{'query'}, actions => \@actions ); -} my @options = $tree->get_displayed_nodes; my @current_values = grep defined, @options[@clauses]; commit 69ef54528958856f7f5727d9f1bf2b86e1e2d38b Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:43:25 2009 -0500 saved_search is now a ref diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 63acca5..fd9ea3e 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -70,11 +70,11 @@ current_tab => "Search/Build.html?".$query_string, title => _("Query Builder"), %query, - saved_search_id => $saved_search{'id'}, + saved_search_id => $saved_search->{'id'}, &> <form method="post" action="Build.html" name="build_query"> -<input type="hidden" class="hidden" name="saved_search_id" value="<% $saved_search{'id'} %>" /> + <input type="hidden" class="hidden" name="saved_search_id" value="<% $saved_search->{'id'} %>" /> <input type="hidden" class="hidden" name="query" value="<% $query{'query'} %>" /> <input type="hidden" class="hidden" name="format" value="<% $query{'format'} %>" /> @@ -93,11 +93,11 @@ %ARGS, actions => \@actions, optionlist => $optionlist, - description => $saved_search{'description'}, + description => $saved_search->{'description'}, &> </div> <div id="editsearches"> - <& Elements/EditSearches, %saved_search, current_search => \%query &> + <& Elements/EditSearches, %$saved_search, current_search => \%query &> </div> @@ -119,21 +119,19 @@ <%INIT> use RT::Interface::Web::QueryBuilder::Tree; -my %saved_search; +my $saved_search; my %query = map { $_ => $ARGS{$_} } qw(query format order_by order rows_per_page); -my @actions = RT::Interface::Web::QueryBuilder->load_saved_search( \%ARGS, \%query, \%saved_search ); +my @actions = RT::Interface::Web::QueryBuilder->load_saved_search( \%ARGS, \%query, $saved_search ); if ($new_query) { # Wipe all data-carrying variables clear if we want a new # search, or we're deleting an old one.. %query = (); - %saved_search = ( id => 'new' ); + $saved_search = { id => 'new'}; - # ..then wipe the session out.. + # ..then wipe the sessionand the search results. Jifty->web->session->remove('CurrentSearchHash'); - - # ..and the search results. Jifty->web->session->get('tickets')->clean_slate if defined Jifty->web->session->get('tickets'); } @@ -238,15 +236,15 @@ my ( $available_columns, $current_format ); ); # if we're asked to save the current search, save it -push @actions, RT::Interface::Web::QueryBuilder->save_search( \%ARGS, \%query, \%saved_search ); +push @actions, RT::Interface::Web::QueryBuilder->save_search( \%ARGS, \%query, $saved_search ); # Push the updates into the session so we don't loose 'em Jifty->web->session->set( 'CurrentSearchHash', { %query, - search_id => $saved_search{'id'}, - object => $saved_search{'object'}, - description => $saved_search{'description'}, + search_id => $saved_search->{'id'}, + object => $saved_search->{'object'}, + description => $saved_search->{'description'}, } ); commit 54dcf157b1c57a3b629df808a769ac3784cfa1b8 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 18:44:16 2009 -0500 factor out a "use" line diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm index 06af369..c06d800 100755 --- a/lib/RT/Interface/Web.pm +++ b/lib/RT/Interface/Web.pm @@ -65,6 +65,7 @@ use RT::Report::Tickets; use RT::System; use RT::SavedSearches; use RT::Interface::Web::QueryBuilder; +use RT::Interface::Web::QueryBuilder::Tree; use URI qw(); use Digest::MD5 (); diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index fd9ea3e..a81ce5d 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -117,8 +117,6 @@ </&> <%INIT> -use RT::Interface::Web::QueryBuilder::Tree; - my $saved_search; my %query = map { $_ => $ARGS{$_} } qw(query format order_by order rows_per_page); my @actions = RT::Interface::Web::QueryBuilder->load_saved_search( \%ARGS, \%query, $saved_search ); commit 40c61ed0e4c87ccf57b78dab641c3408e1c97bc2 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 19:06:40 2009 -0500 remove unneeded current_user diff --git a/share/html/Search/Elements/DisplayOptions b/share/html/Search/Elements/DisplayOptions index 36d8c47..797e3e6 100644 --- a/share/html/Search/Elements/DisplayOptions +++ b/share/html/Search/Elements/DisplayOptions @@ -101,7 +101,7 @@ selected="selected" </&> <%INIT> -my $tickets = RT::Model::TicketCollection->new( current_user => Jifty->web->current_user ); +my $tickets = RT::Model::TicketCollection->new( ); my %fields = %{$tickets->columns}; map { $fields{$_}->[0] =~ /^(?:ENUM|INT|DATE|STRING|ID)$/ || delete $fields{$_} } keys %fields; delete $fields{'effective_id'}; commit a16b6af4b3ab91a3ea42757dcc24d479b192e155 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 19:12:56 2009 -0500 don't stomp the default format diff --git a/lib/RT/Interface/Web/QueryBuilder.pm b/lib/RT/Interface/Web/QueryBuilder.pm index 6eff61f..87fe764 100644 --- a/lib/RT/Interface/Web/QueryBuilder.pm +++ b/lib/RT/Interface/Web/QueryBuilder.pm @@ -315,7 +315,7 @@ sub save_search { sub build_format_string { my $self = shift; my %args = ( - format => RT->config->get('default_search_result_format'), + format => undef, cfqueues => undef, face => undef, size => undef, @@ -329,6 +329,9 @@ sub build_format_string { current_display_columns => undef, @_ ); + + + $args{format} = RT->config->get('default_search_result_format') unless $args{format}; # All the things we can display in the format string by default my @fields = qw( commit 33ddbccf5e829b20cecbdd2333365c8627a0fe9b Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 19:13:32 2009 -0500 warning avoidance diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index a81ce5d..928fbbc 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -74,9 +74,9 @@ &> <form method="post" action="Build.html" name="build_query"> - <input type="hidden" class="hidden" name="saved_search_id" value="<% $saved_search->{'id'} %>" /> -<input type="hidden" class="hidden" name="query" value="<% $query{'query'} %>" /> -<input type="hidden" class="hidden" name="format" value="<% $query{'format'} %>" /> +<input type="hidden" class="hidden" name="saved_search_id" value="<% $saved_search->{'id'} || '' %>" /> +<input type="hidden" class="hidden" name="query" value="<% $query{'query'} || '' %>" /> +<input type="hidden" class="hidden" name="format" value="<% $query{'format'} || '' %>" /> commit f39e4e7ae94956e2928553aa0cc36b34164b8e26 Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 19:16:07 2009 -0500 capitalization fix diff --git a/share/html/Ticket/Elements/Tabs b/share/html/Ticket/Elements/Tabs index 0f21125..d12f63c 100755 --- a/share/html/Ticket/Elements/Tabs +++ b/share/html/Ticket/Elements/Tabs @@ -270,7 +270,7 @@ $has_query = 1 if ( $ARGS{'query'} or Jifty->web->session->get('CurrentSearchHas $args = "?" . $m->comp( '/Elements/QueryString', %query_args ); $tabs->{"f"} = { - path => "Search/Build.html?NewQuery=1", + path => "Search/Build.html?new_query=1", title => _('New Search') }; $tabs->{"g"} = { commit 20fdc5f179a20f0adc1530f2675a216d9afbcf6a Author: Jesse Vincent <jesse [at] bestpractical> Date: Thu Nov 5 19:19:57 2009 -0500 minor refactoring to reuse a compiled query string diff --git a/share/html/Search/Build.html b/share/html/Search/Build.html index 928fbbc..5e4537b 100644 --- a/share/html/Search/Build.html +++ b/share/html/Search/Build.html @@ -247,22 +247,19 @@ Jifty->web->session->set( 'CurrentSearchHash', ); # Show the results, if we were asked. - -if ( $ARGS{'do_search'} ) { - Jifty->web->redirect( Jifty->web->url . "Search/Results.html?" . - RT::Interface::Web->format_query_params(%query) ); - -} +my $query_string = ''; # Build a query_string for the tabs - -my $query_string = ''; if ($new_query) { $query_string = 'new_query=1'; } elsif ( $query{'query'} ) { $query_string = RT::Interface::Web->format_query_params(%query); } +if ( $ARGS{'do_search'} ) { + Jifty->web->redirect( Jifty->web->url . "Search/Results.html?" .$query_string; +} + </%INIT> <%ARGS> ----------------------------------------------------------------------- _______________________________________________ Rt-commit mailing list Rt-commit [at] lists http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-commit
|