--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use WWW::Mechanize;
+use Getopt::Std;
+use File::chdir;
+use URI;
+use File::Slurp qw(write_file);
+
+my %opt;
+getopts('d:h:u:p:', \%opt);
+die usage() unless ($opt{d} and $opt{u} and $opt{p});
+my $host = $opt{h} || 'http://localhost/freeside';
+
+my $mech = WWW::Mechanize->new( autocheck => 0 );
+$mech->get("$host/index.html");
+$mech->submit_form(
+ with_fields => {
+ credential_0 => $opt{u},
+ credential_1 => $opt{p}
+ }
+);
+
+my @tests = <>;
+
+mkdir($opt{d}) unless -d $opt{d};
+push @CWD, $opt{d};
+
+while (my $path = shift @tests) {
+ if ($path =~ /^#(.*)/) {
+ print "$1 - skipped\n";
+ next;
+ }
+ my $uri = URI->new("$host/$path");
+ print $uri->path;
+ my $response = $mech->get($uri);
+ print " - " . $response->code . "\n";
+ if ($response->is_success) {
+ local $CWD;
+ my @dirs = $uri->path_segments;
+ my $file = pop @dirs;
+ foreach my $dir (@dirs) {
+ mkdir $dir unless -d $dir;
+ push @CWD, $dir;
+ }
+ write_file($file, {binmode => ':utf8'}, $response->decoded_content);
+ }
+}
+
+sub usage {
+ "Usage: fetch_pages -d directory -u username -p password [ -h hostname ]\n\n";
+}
+
+=head1 NAME
+
+fetch_pages - a testing tool for UI changes
+
+=head1 USAGE
+
+fetch_pages -d before_change -u myuser -p mypass list_of_tests
+git checkout newbranch
+make install; apache2ctl restart
+fetch_pages -d after_change -u myuser -p mypass list_of_tests
+diff -ur before_change/ after_change/ |diffstat
+
+=head1 ARGUMENTS
+
+-d: the directory to put the files in. Required.
+
+-u: the username to use with the Freeside web interface. Required.
+
+-p: the password. Required.
+
+-h: the URL prefix for the Freeside server. Defaults to
+"http://localhost/freeside".
+
+The list of tests can be in a file specified after all arguments, or passed
+to stdin.
+
+=cut
+++ /dev/null
-/var/www/ng_selfservice-DIST/freeside.class.php
--- /dev/null
+/var/www/ng_selfservice-DIST/freeside.class.php
--- /dev/null
+/var/www/html/ng_selfservice-DIST/freeside.class.php
'Basics' => 'basics',
'Notes' => 'notes', #notes and files?
'Tickets' => 'tickets',
+ 'Appointments' => 'appointments',
+ 'Quotations' => 'quotations',
'Packages' => 'packages',
'Payment History' => 'payment_history',
;
$customer_views{'Change History'} = 'change_history'
if $curuser->access_right('View customer history');
-$customer_views{'Jumbo'} = 'jumbo';
# XSS via your own preferences? seems unlikely, but nice try anyway...
( $curuser->option('menu_position') || 'top' )
% }
% my $i = 0; # for row striping # XXX CSS - nth-child
+% my $id = 0;
% foreach my $row ( @$rows ) {
%
% my $rowstyle = '';
%
% $tooltip = &{$tooltip}($row)
% if ref($tooltip) eq 'CODE';
-% $tooltip = qq! title="<% $tooltip |h %>"!;
+% $tooltip = qq! id="a$id" !.
+% qq! onmouseover="return overlib(!.
+% $m->interp->apply_escapes($tooltip, 'h', 'js_string').
+% qq!, FGCLASS, 'tooltip', REF, 'a$id', !.
+% qq!REFC, 'LL', REFP, 'UL')"! if $tooltip;
%
% if ( $link ) {
% my( $url, $method ) = @{$link};
% elsif ( $tooltip ) {
% $a = qq(<A $tooltip>);
% }
+% $id++;
% }
%
'table' => $query->{'table'},
);
+ # this is ridiculous, but we do have searches where $query has constraints
+ # and $count_query doesn't, or vice versa.
if ( $query->{'extra_sql'} =~ /\bWHERE\b/i or keys %{$query->{hashref}} ) {
$query->{'extra_sql'} .= " AND $agentnums_sql";
- $count_query .= " AND $agentnums_sql";
} else {
$query->{'extra_sql'} .= " WHERE $agentnums_sql";
+ }
+
+ if ( $count_query =~ /\bWHERE\b/i ) {
+ $count_query .= " AND $agentnums_sql";
+ } else {
$count_query .= " WHERE $agentnums_sql";
}
my $header = [ map { ref($_) ? $_->{'label'} : $_ } @{$opt{header}} ];
my $rows;
-my @query;
-if (ref($query) eq 'HASH') {
- @query = $query;
-
- if ( $order_by ) {
- if ( $query->{'order_by'} ) {
- if ( $query->{'order_by'} =~ /^(\s*ORDER\s+BY\s+)?(\S.*)$/is ) {
- $query->{'order_by'} = "ORDER BY $order_by, $2";
+if ( ref $query ) {
+ my @query;
+ if (ref($query) eq 'HASH') {
+ @query = $query;
+
+ if ( $order_by ) {
+ if ( $query->{'order_by'} ) {
+ if ( $query->{'order_by'} =~ /^(\s*ORDER\s+BY\s+)?(\S.*)$/is ) {
+ $query->{'order_by'} = "ORDER BY $order_by, $2";
+ } else {
+ warn "unparsable query order_by: ". $query->{'order_by'};
+ die "unparsable query order_by: ". $query->{'order_by'};
+ }
} else {
- warn "unparsable query order_by: ". $query->{'order_by'};
- die "unparsable query order_by: ". $query->{'order_by'};
+ $query->{'order_by'} = "ORDER BY $order_by";
}
- } else {
- $query->{'order_by'} = "ORDER BY $order_by";
}
+
+ $query->{'order_by'} .= " $limit";
+
+ } elsif (ref($query) eq 'ARRAY') {
+ # do we still use this? it was for the old 477 report.
+ @query = @{ $query };
+ } else {
+ die "invalid query reference";
}
- $query->{'order_by'} .= " $limit";
+ #eval "use FS::$opt{'query'};";
+ my @param = qw( select table addl_from hashref extra_sql order_by debug );
+ $rows = [ qsearch( [ map { my $query = $_;
+ ({ map { $_ => $query->{$_} } @param });
+ }
+ @query
+ ],
+ #'order_by' => $opt{order_by}. " ". $limit,
+ )
+ ];
-} elsif (ref($query) eq 'ARRAY') {
- # do we still use this? it was for the old 477 report.
- @query = @{ $query };
-} else {
- die "invalid query reference";
-}
+} else { # not ref $query; plain SQL (still used as of 07/2015)
-if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
- #%search = ( 'disabled' => '' );
- $opt{'query'}->{'hashref'}->{'disabled'} = '';
- $opt{'query'}->{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
-}
+ $query .= " $limit";
+ my $sth = dbh->prepare($query)
+ or die "Error preparing $query: ". dbh->errstr;
+ $sth->execute
+ or die "Error executing $query: ". $sth->errstr;
-#eval "use FS::$opt{'query'};";
-my @param = qw( select table addl_from hashref extra_sql order_by debug );
-$rows = [ qsearch( [ map { my $query = $_;
- ({ map { $_ => $query->{$_} } @param });
- }
- @query
- ],
- #'order_by' => $opt{order_by}. " ". $limit,
- )
- ];
+ $rows = $sth->fetchall_arrayref;
+ $header ||= $sth->{NAME};
+}
# run the count query to get number of rows and other totals
my $count_sth = dbh->prepare($count_query);
'title' => 'Query Results',
'name' => 'rows',
'query' => "SELECT $sql",
-
+ 'count_query' => $count,
&>
<%init>
my $sql = $cgi->param('sql') or errorpage('Empty query');
$sql =~ s/;+\s*$//; #remove trailing ;
+my $count = $sql;
+$count =~ s/.* FROM /SELECT COUNT(*) FROM /i;
+
</%init>