package CPANXR::Apache::Symbol; use CPANXR::Apache::Util; use CPANXR::Database; use CPANXR::Parser qw(:constants); use File::Spec::Functions qw(catdir); use Data::Page; use strict; our %Types = ( t1 => [CONN_PACKAGE, 'packages'], t2 => [CONN_FUNCTION, 'function calls'], t3 => [CONN_METHOD, 'method calls'], t3 => [CONN_MACRO, 'macros'], t4 => [CONN_INCLUDE, 'uses'], t5 => [CONN_DECL, 'declarations'], t6 => [CONN_ISA, 'inheritence'], t7 => [CONN_REF, 'references'], t8 => [CONN_LINK, 'includes'], t9 => [CONN_FILE, 'files'], ); sub find { my ($self, $r, $q) = @_; my $symbol_id = $q->param('symbol'); my $pkg_id = $q->param('pkg'); my $current = $q->param('p') || 1; unless($symbol_id =~ /^\d+$/) { $r->print("Missing argument symbol"); return; } my $pkg = ""; if($pkg_id) { unless($pkg_id =~ /^\d+$/) { $r->print("Malformed argument pkg"); } $pkg = CPANXR::Database->select_symbol($pkg_id)->[0]->[0]; } my $symbol = CPANXR::Database->select_symbol($symbol_id)->[0]->[0]; $r->print("Looking for $symbol"); if($pkg) { $r->print(" in package $pkg"); } $r->print(" and found
\n"); $r->print("
\n"); my %args; # Extract limit { my @limit_types; while(my ($param, $value) = each %Types) { my $v = $q->param($param) ? 1 : 0; push @limit_types, $value->[0] if $v; } if(@limit_types) { $args{limit_types} = \@limit_types; } } # Select files matching symbol my $files = CPANXR::Database->select_files(symbol_id => $symbol_id); @$files = map { [ $symbol_id, $symbol, "", "", $_->[2], $_->[0], undef, CONN_FILE, undef, $_->[1]] } @$files; # Select connections matching symbol my $result = CPANXR::Database->select_connections(symbol_id => $symbol_id, %args); unshift @$result, @$files; $result = $self->transform($result); my $table = CPANXR::Apache::Util::Table->new($r, 4, [qw(15% 55% 15% 15%)]); $table->begin; $table->header("Type:", "File:", "Location:", "Show:"); my $page = Data::Page->new(scalar @$result, 10, $current); my ($pre_file, $pre_type) = ("",""); for($page->splice($result)) { if($pre_file ne $_->[1] || ($pre_type ne $_->[0])) { $pre_file = $_->[1]; } else { $_->[1] = ""; } if($pre_type eq $_->[0]) { $_->[0] = ""; } else { $pre_type = $_->[0]; } $table->print(@$_); } $table->end; # Write navigation my $base = "find?symbol=$symbol_id&pkg=$pkg_id"; my $base_type = ""; $base_type .= "&$_=" . ($q->param($_) ? 1 : 0) for(keys %Types); $base_type =~ s/=0/=1/g unless($base =~ /=1/); CPANXR::Apache::Util->navigator($r, $page, $base . $base_type); # Limit search $r->print(qq{
Show: }); for(sort { $Types{$a}->[1] cmp $Types{$b}->[1] } keys %Types) { my $checked = $q->param($_) ? "checked" : ""; $r->print(qq{@{[lcfirst($Types{$_}->[1])]} }); } $r->print(q{
}); $r->print("
"); } my @Types = ("uses", "calls", "calls", "functions", "macros", "packages", "inherits", "references", "includes", "files", ); sub transform { my ($self, $result) = @_; my $groups = {}; foreach my $item (@$result) { my $type = $Types[$item->[7]]; $groups->{$type} = {} unless(exists $groups->{$type}); if(exists $groups->{$type}->{$item->[4]}) { push @{$groups->{$type}->{$item->[4]}->{lines}}, [$item->[2], $item->[0], $item->[6], $item->[8]]; } else { $groups->{$type}->{$item->[4]} = { file_id => $item->[5], lines => [[$item->[2], $item->[0], $item->[6], $item->[8]]], }; } } my @result; foreach my $type (sort keys %$groups) { my $show_type = "$type"; while(my ($file, $entries) = each %{$groups->{$type}}) { my $show_file = $file; if(@{$entries->{lines}}) { foreach my $line (@{$entries->{lines}}) { my $show_line = ""; if($line->[0] ne "") { $show_line = qq{at line $line->[0]}; } else { $show_line = "n/a"; } my $func = ""; if($type eq 'functions') { my $pkg_id = $line->[2] || $line->[3]; my $sym_id = $line->[1]; $func = qq{Call graph}; } elsif($type eq 'packages') { $func = qq{IS-A graph}; } elsif($type eq 'files') { $func = qq{File graph}; } push @result, [$show_type, $show_file, $show_line, $func]; } } } } return \@result; } 1;