File Coverage

blib/lib/Autodia/Handler/PHP.pm
Criterion Covered Total %
statement 15 176 8.5
branch 0 88 0.0
condition 0 6 0.0
subroutine 5 8 62.5
pod n/a
total 20 278 7.1


line stmt bran cond sub pod time code
1             ################################################################
2             # AutoDIA - Automatic Dia XML. (C)Copyright 2001 A Trevena #
3             # #
4             # AutoDIA comes with ABSOLUTELY NO WARRANTY; see COPYING file #
5             # This is free software, and you are welcome to redistribute #
6             # it under certain conditions; see COPYING file for details #
7             ################################################################
8             package Autodia::Handler::PHP;
9              
10             require Exporter;
11              
12 1     1   1635 use strict;
  1         2  
  1         44  
13              
14 1     1   4 use vars qw($VERSION @ISA @EXPORT);
  1         2  
  1         69  
15 1     1   6 use Autodia::Handler;
  1         2  
  1         42  
16 1     1   4 use Data::Dumper;
  1         2  
  1         57  
17              
18             @ISA = qw(Autodia::Handler Exporter);
19              
20 1     1   6 use Autodia::Diagram;
  1         1  
  1         2542  
21              
22             #---------------------------------------------------------------
23              
24             #####################
25             # Constructor Methods
26              
27             # new inherited from Handler
28              
29             #------------------------------------------------------------------------
30             # Access Methods
31              
32             # parse_file inherited from Handler
33              
34             #-----------------------------------------------------------------------------
35             # Internal Methods
36              
37             # _initialise inherited from Handler
38              
39             sub _parse
40             {
41 0     0     my $self = shift;
42 0           my $fh = shift;
43 0           my $filename = shift;
44 0           my $Diagram = $self->{Diagram};
45 0           my $incode = 0;
46 0           my $inclass = 0;
47 0           my $infunc = 0;
48 0           my $inclassparen = 0;
49 0           my $infuncparen = 0;
50 0           my $incommentcount = 0;
51 0           my $incomment = 0;
52              
53 0           my $Class;
54              
55 0           $self->{pod} = 0;
56              
57             # parse through file looking for stuff
58 0           foreach my $line (<$fh>)
59             {
60 0           chomp $line;
61 0 0         if ($self->_discard_line($line)) { next; }
  0            
62              
63 0           my $commentup = $line =~ tr/\/\*/\/\*/;
64 0           my $commentdown = $line =~ tr/\*\//\*\//;
65 0           $incommentcount = $commentup - $commentdown;
66 0 0         if ($incommentcount > 0) {
67 0           $incomment = 1;
68             } else {
69 0           $incomment = 0;
70             }
71 0 0         next if $incomment;
72 0           $line =~ s|\/\/.*$||;
73              
74 0           my $up = $line =~ tr/\{/\{/;
75 0           my $down = $line =~ tr/\}/\}/;
76 0 0         $inclassparen = $inclassparen + $up - $down if ($inclass > 0);
77 0 0         $infuncparen = $infuncparen + $up - $down if ($infunc > 0);
78 0 0         $inclass = 0 if ($inclassparen < 1);
79 0 0         $infunc = 0 if ($infuncparen < 1);
80              
81             # print "$inclassparen : $inclass $infuncparen : $infunc \n";
82 0 0         if ($line =~ /.*class\s+([^\s\(\)\{\}]+)/) {
83 0           my $className = $1;
84 0           $inclass = 1;
85 0           $inclassparen = $up - $down;
86             # print "Classname: $className matched on:\n$line\n";
87 0 0         last if ($self->skip($className));
88 0           $Class = Autodia::Diagram::Class->new($className);
89             # add to diagram
90 0           my $exists = $Diagram->add_class($Class);
91 0 0         $Class = $exists if ($exists);
92 0 0         if ($line =~ /.*extends\s+(\S+)/) {
93 0           my $superclass = $1;
94 0           $self->_is_package(\$Class, $filename);
95 0           my @superclasses = split(" ", $superclass);
96              
97 0           foreach my $super (@superclasses) # WHILE_SUPERCLASSES
98             {
99             # discard if stopword
100 0 0         next if ($super =~ /(?:exporter|autoloader)/i);
101             # create superclass
102 0           my $Superclass = Autodia::Diagram::Superclass->new($super);
103             # add superclass to diagram
104 0           my $exists_already = $Diagram->add_superclass($Superclass);
105 0 0         if (ref $exists_already)
106             {
107 0           $Superclass = $exists_already;
108             }
109             # create new inheritance
110 0           my $Inheritance = Autodia::Diagram::Inheritance->new($Class, $Superclass);
111             # add inheritance to superclass
112 0           $Superclass->add_inheritance($Inheritance);
113             # add inheritance to class
114 0           $Class->add_inheritance($Inheritance);
115             # add inheritance to diagram
116 0           $Diagram->add_inheritance($Inheritance);
117             }
118             }
119              
120             }
121              
122 0 0         if ($line =~ /^\s*(include|require|include_once|require_once)\s+\(*["']?([^\"\'\)]+)["']?\)*/) {
123 0           my $componentName = $2;
124              
125             # print "componentname: $componentName matched on:\n$line\n";
126             # discard if stopword
127 0 0         next if ($componentName =~ /(strict|vars|exporter|autoloader|data::dumper)/i);
128              
129             # check package exists before doing stuff
130 0           $self->_is_package(\$Class, $filename);
131              
132             # create component
133 0           my $Component = Autodia::Diagram::Component->new($componentName);
134             # add component to diagram
135 0           my $exists = $Diagram->add_component($Component);
136              
137             # replace component if redundant
138 0 0         if (ref $exists)
139             {
140 0           $Component = $exists;
141             }
142             # create new dependancy
143 0           my $Dependancy = Autodia::Diagram::Dependancy->new($Class, $Component);
144             # add dependancy to diagram
145 0           $Diagram->add_dependancy($Dependancy);
146             # add dependancy to class
147 0           $Class->add_dependancy($Dependancy);
148             # add dependancy to component
149 0           $Component->add_dependancy($Dependancy);
150             }
151              
152 0 0 0       if ($line =~ /^.*=\s*new\s+([^\s\(\)\{\}\;]+)/ || $line =~ /(\w+)::/) {
153 0           my $componentName = $1;
154              
155             # print "componentname: $componentName matched on:\n$line\n";
156             # discard if stopword
157 0 0         next if ($componentName =~ /(self|parent|strict|vars|exporter|autoloader|data::dumper)/i);
158              
159             # check package exists before doing stuff
160 0           $self->_is_package(\$Class, $filename);
161              
162             # create component
163 0           my $Component = Autodia::Diagram::Component->new($componentName);
164             # add component to diagram
165 0           my $exists = $Diagram->add_component($Component);
166              
167             # replace component if redundant
168 0 0         if (ref $exists)
169             {
170 0           $Component = $exists;
171             }
172             # create new dependancy
173 0           my $Dependancy = Autodia::Diagram::Dependancy->new($Class, $Component);
174             # add dependancy to diagram
175 0           $Diagram->add_dependancy($Dependancy);
176             # add dependancy to class
177 0           $Class->add_dependancy($Dependancy);
178             # add dependancy to component
179 0           $Component->add_dependancy($Dependancy);
180             }
181              
182 0 0         if ($line =~ /^\s*((((static|var|public|private|protected)\s+)+)\$|const\s+)([^\s=\{\}\(\)]+)/) {
183 0 0         last unless $inclass;
184 0           my $default;
185 0           my $attribute_name = $5;
186 0           my $class_modifier = $1;
187 0 0         my $comment = ($class_modifier =~ m/static/) ? "static ": "";
188 0 0         $comment .= ($class_modifier =~ m/const/) ? "const": "";
189              
190 0 0         my $attribute_visibility = ($class_modifier =~ m/(var|public|const)/) ? 0 : ($class_modifier =~ m/(protected)/) ? 2 : 1;
    0          
191              
192              
193 0           $attribute_name =~ s/(.*);/$1/;
194 0 0 0       if($attribute_name =~ m/^\_/ && $class_modifier =~ m/var/) {
195 0           $attribute_visibility = 1;
196             }
197              
198 0 0         if ($line =~ /^\s*((((static|var|public|private|protected)\s+)+)\$|const\s+)(\S+)\s*=\s*(.*)/) {
199 0           $default = $6;
200 0           $default =~ s/(.*);/$1/;
201 0           $default =~ s/(.*)\/\/.*/$1/;
202 0           $default =~ s/(.*)\/\*.*/$1/;
203             }
204             # print "Attr found: $attribute_name = $default\n$line\n";
205             $Class->add_attribute({
206 0           name => $attribute_name,
207             visibility => $attribute_visibility,
208             value => $default,
209             });
210              
211             }
212              
213              
214             # if line contains sub then parse for method data
215 0 0         if ($line =~ /([^\s]*)\s*function\s+&?(\w+)/) {
216 0 0         unless ($inclass) {
217 0           my @newclass = reverse split (/\//, $filename);
218 0           $Class = Autodia::Diagram::Class->new($newclass[0]);
219             # add to diagram
220 0           my $exists = $Diagram->add_class($Class);
221 0 0         $Class = $exists if ($exists);
222 0           $inclass = 1;
223 0           $inclassparen = $up - $down;
224             }
225 0           my $subname = $2;
226 0           my $method_modifier = $1;
227              
228 0           $infunc = 1;
229 0           $infuncparen = $up - $down;
230 0           print "Function found: $subname\n$line\n";
231 0           my %subroutine = ( "name" => $subname, );
232 0 0         $subroutine{"visibility"} = ($method_modifier =~ m/private/) ? 1 : ($method_modifier =~ m/protected/) ? 2 : ($subroutine{"name"} =~ m/^\_/) ? 1 : 0;
    0          
    0          
233 0 0         $subroutine{"inheritance_type"} = ($method_modifier =~ m/abstract/) ? 0 : ($method_modifier =~ m/final/) ? 2 : 1;
    0          
234              
235             # check for explicit parameters
236 0 0         if ($line =~ /function\s+(\S+)\s*\((.+?)\)/)
237             {
238 0           my $parameter_string = $2;
239              
240 0           $parameter_string =~ s/\s*//g;
241 0           $parameter_string =~ s/\$//g;
242             # print "Params: $parameter_string\n";
243 0           my @parameters1 = split(",",$parameter_string);
244 0           my @parameters;
245 0           foreach my $par (@parameters1) {
246 0           my ($name, $val) = split (/=/, $par);
247 0 0         $val =~ s/["']//g if (defined $val);
248 0           $name =~ s/^\s+|\s+$//g;
249 0           my $kind;
250 0 0         if($name =~ m/&/) {
251 0           $name =~ s/&//g;
252 0           $kind = 3;
253             } else {
254 0           $kind = 1;
255             }
256              
257 0           my %temphash = (
258             Name => $name,
259             Val => $val,
260             Kind => $kind,
261             );
262 0           push @parameters, \%temphash;
263              
264             }
265 0           $subroutine{"Params"} = \@parameters;
266             }
267             # print Dumper(\%subroutine);
268 0           $Class->add_operation(\%subroutine);
269             }
270              
271             }
272              
273 0           $self->{Diagram} = $Diagram;
274              
275 0           return;
276             }
277              
278             sub _discard_line
279             {
280 0     0     my $self = shift;
281 0           my $line = shift;
282 0           my $discard = 0;
283              
284             SWITCH:
285             {
286 0 0         if ($line =~ m/^\s*$/) # if line is blank or white space discard
  0            
287             {
288 0           $discard = 1;
289 0           last SWITCH;
290             }
291              
292 0 0         if ($line =~ /^\s*\/\//) # if line is a comment discard
293             {
294 0           $discard = 1;
295 0           last SWITCH;
296             }
297              
298 0 0         if ($line =~ /^\s*\=head/) # if line starts with pod syntax discard and flag with $pod
299             {
300 0           $self->{pod} = 1;
301 0           $discard = 1;
302 0           last SWITCH;
303             }
304              
305 0 0         if ($line =~ /^\s*\=cut/) # if line starts with pod end syntax then unflag and discard
306             {
307 0           $self->{pod} = 0;
308 0           $discard = 1;
309 0           last SWITCH;
310             }
311              
312 0 0         if ($self->{pod} == 1) # if line is part of pod then discard
313             {
314 0           $discard = 1;
315 0           last SWITCH;
316             }
317             }
318 0           return $discard;
319             }
320              
321             ####-----
322              
323             sub _is_package
324             {
325 0     0     my $self = shift;
326 0           my $package = shift;
327 0           my $Diagram = $self->{Diagram};
328              
329 0 0         unless(ref $$package)
330             {
331 0           my $filename = shift;
332              
333             # create new class with name
334 0           $$package = Autodia::Diagram::Class->new($filename);
335             # add class to diagram
336 0           $Diagram->add_class($$package);
337             }
338              
339 0           return;
340             }
341              
342             ####-----
343              
344             1;
345              
346             ###############################################################################
347              
348             =head1 NAME
349              
350             Autodia::Handler::PHP - AutoDia handler for PHP
351              
352             =head1 INTRODUCTION
353              
354             Autodia::Handler::PHP is registered in the Autodia.pm module, which contains a hash of language names and the name of their respective language - in this case:
355              
356             %language_handlers = ( .. ,
357             php => "Autodia::Handler::PHP",
358             .. );
359              
360             %patterns = ( .. ,
361             php => \%php,
362             .. );
363              
364             my %php = (
365             regex => '\w+\.php$',
366             wildcards => [
367             "php","php3","php4"
368             ],
369             );
370              
371              
372             =head1 CONSTRUCTION METHOD
373              
374             use Autodia::Handler::PHP;
375              
376             my $handler = Autodia::Handler::PHP->New(\%Config);
377              
378             This creates a new handler using the Configuration hash to provide rules selected at the command line.
379              
380             =head1 ACCESS METHODS
381              
382             $handler->Parse(filename); # where filename includes full or relative path.
383              
384             This parses the named file and returns 1 if successful or 0 if the file could not be opened.
385              
386             $handler->output(); # any arguments are ignored.
387              
388             This outputs the output file according to the rules in the %Config hash passed at initialisation of the object and the template.
389              
390             =cut
391