]> git.donarmstrong.com Git - debbugs.git/commitdiff
allow arbitrarily complex boolean operations in usercategories selection statements
authorDon Armstrong <don@donarmstrong.com>
Sat, 21 Feb 2015 19:25:37 +0000 (11:25 -0800)
committerDon Armstrong <don@donarmstrong.com>
Sat, 21 Feb 2015 19:25:37 +0000 (11:25 -0800)
Debbugs/CGI/Pkgreport.pm

index 77b55165ae669916679d04c0e7bac69854383ff7..696a9e015c382c29555f772b7db61454e32ed5a9 100644 (file)
@@ -458,40 +458,55 @@ sub pkg_htmlizebugs {
      return $result;
 }
 
+sub parse_order_statement_into_boolean {
+    my ($statement,$status,$tags) = @_;
+
+    if (not defined $tags) {
+        $tags = {map { $_, 1 } split / /, $status->{"tags"}
+                }
+            if defined $status->{"tags"};
+
+    }
+    # replace all + with &&
+    $statement =~ s/\+/&&/g;
+    # replace all , with ||
+    $statement =~ s/,/||/g;
+    $statement =~ s{(?<field>[^\&\|\=]+)=(?<value>[^\&\|\=]+)}
+              {
+                  my $ok = 0;
+                  if ($+{field} eq 'tag') {
+                      $ok = 1 if defined $tags->{$+{value}};
+                  } else {
+                      $ok = 1 if defined $status->{$+{field}} and
+                          $status->{$+{field}} eq $+{value};
+                  }
+                  $ok;
+              }exg;
+    # check that the parsed statement is just valid boolean statements
+    if ($statement =~ /^([01\(\)\&\|]+)$/) {
+        return eval "$statement";
+    } else {
+        # this is an invalid boolean statement
+        return 0;
+    }
+}
+
 sub get_bug_order_index {
      my $order = shift;
      my $status = shift;
-     my $pos = -1;
-
-     my %tags = ();
-     %tags = map { $_, 1 } split / /, $status->{"tags"}
-         if defined $status->{"tags"};
-
+     my $pos = 0;
+     my $tags = {map { $_, 1 } split / /, $status->{"tags"}
+                }
+         if defined $status->{"tags"};
      for my $el (@${order}) {
-         $pos++;
-         my $match = 1;
-          my $first_field = 1; # true if no previous fields have been
-                               # checked
-          while ($el =~ /(?<joiner>^|\+|,)(?<field>[^=]+)=(?<value>[^=,\+]+)/g) {
-              my ($j,$f,$v) = @+{qw(joiner field value)};
-              my $isokay = 0;
-              $isokay = 1 if (defined $status->{$f} and $v eq $status->{$f});
-              $isokay = 1 if ($f eq "tag" && defined $tags{$v});
-              if (defined $j and $j eq ',') {
-                  $match ||= $isokay;
-              } else {
-                  $match &&= $isokay;
-              }
-              $first_field = 0;
-          }
-          # if there is a match, or if there were no fields to check,
-          # this usertag matched.
-         if ($match || $first_field) {
-              return $pos;
-              last;
-         }
+         if (not length $el or
+             parse_order_statement_into_boolean($el,$status,$tags)
+            ) {
+             return $pos;
+         }
+         $pos++;
      }
-     return $pos + 1;
+     return $pos;
 }
 
 # sets: my @names; my @prior; my @title; my @order;