File Coverage

blib/lib/WWW/PTV.pm
Criterion Covered Total %
statement 27 168 16.0
branch 0 30 0.0
condition 0 12 0.0
subroutine 9 25 36.0
pod 13 13 100.0
total 49 248 19.7


line stmt bran cond sub pod time code
1             package WWW::PTV;
2              
3 1     1   14463 use warnings;
  1         2  
  1         27  
4 1     1   4 use strict;
  1         1  
  1         26  
5              
6 1     1   829 use LWP;
  1         62529  
  1         44  
7 1     1   806 use WWW::Mechanize;
  1         112120  
  1         33  
8 1     1   731 use HTML::TreeBuilder;
  1         16611  
  1         9  
9 1     1   36 use Carp qw(croak);
  1         2  
  1         58  
10 1     1   467 use WWW::PTV::Area;
  1         2  
  1         21  
11 1     1   318 use WWW::PTV::Stop;
  1         2  
  1         24  
12 1     1   277 use WWW::PTV::Route;
  1         2  
  1         1579  
13              
14             our $VERSION = '0.06';
15             our $CACHE;
16              
17             sub __request {
18 0     0     my($self,$uri) = @_;
19 0 0         my $res = ( $uri !~ /^http:/
20             ? $self->{ua}->get( $self->{uri} . $uri )
21             : $self->{ua}->get( $uri ) );
22 0 0         $res->is_success and return $res->content;
23 0           croak 'Unable to retrieve content: ' . $res->status_line
24             }
25              
26             sub __tl_request {
27 0     0     my ($self, $tag_id)= @_;
28 0   0       my $r = ( $self->{cache} and $CACHE->{timetables}->{master}
29             ? $CACHE->{timetables}->{master}
30             : $self->__request( 'http://ptv.vic.gov.au/timetables' ) );
31 0 0         $CACHE->{timetables}->{master} = $r if $self->{cache};
32 0           my $t = HTML::TreeBuilder->new_from_content( $r );
33 0           $t = $t->look_down( _tag => 'select', id => $tag_id );
34 0           my @routes = $t->look_down( _tag => 'option' );
35 0           return my %routes = map { $_->attr( 'value' ) => $_->as_text } grep { $_->attr( 'value' ) ne '' } @routes
  0            
  0            
36             }
37              
38             sub new {
39 0     0 1   my($class,%args)= @_;
40 0           my $self = bless {}, $class;
41 0 0         $self->{uri} = 'http://' . ( defined $args{uri} ? $args{uri} : 'ptv.vic.gov.au' ) . '/';
42 0           $self->{ua} = LWP::UserAgent->new;
43 0           $self->{tree} = HTML::TreeBuilder->new;
44 0 0         $self->{cache}++ if $args{cache};
45 0           return $self
46             }
47              
48 0     0 1   sub cache { $_[0]->{cache}++ }
49              
50 0     0 1   sub nocache { $_[0]->{cache} = 0 }
51              
52             sub get_metropolitan_bus_routes {
53 0     0 1   return $_[0]->__tl_request( 'RouteForm1_RouteUrl' );
54             }
55              
56             sub get_metropolitan_train_routes {
57 0     0 1   return $_[0]->__tl_request( 'RouteForm2_RouteUrl' )
58             }
59              
60             sub get_metropolitan_tram_routes {
61 0     0 1   return $_[0]->__tl_request( 'RouteForm3_RouteUrl' );
62             }
63              
64             sub get_vline_bus_routes {
65 0     0 1   return $_[0]->__tl_request( 'RouteForm4_RouteUrl' )
66             }
67              
68             sub get_vline_train_routes {
69 0     0 1   return $_[0]->__tl_request( 'RouteForm5_RouteUrl' )
70             }
71              
72             sub get_regional_bus_routes {
73 0     0 1   return $_[0]->__tl_request( 'RouteForm6_RouteUrl' )
74             }
75              
76             sub get_route_by_id {
77 0     0 1   my( $self, $id )= @_;
78 0 0         $id or return "Mandatory parameter id not given";
79              
80 0 0 0       return $CACHE->{ROUTE}->{$id} if ( $self->{cache} and $CACHE->{ROUTE}->{$id} );
81              
82 0           my $r = $self->__request( "/route/view/$id" );
83 0           my $t = HTML::TreeBuilder->new_from_content( $r );
84             #my $t = HTML::TreeBuilder->new_from_file( './metro_train_route_1' );
85             #my $t = HTML::TreeBuilder->new_from_file( './regional_bus_route_geelong_19' );
86 0           my %route = (id => $id);
87 0           my $r_link = $t->look_down( _tag => 'div', id => 'content' );
88 0           $route{name} = $t->look_down( _tag => 'h1' )->as_text;
89 0           ( $route{direction_in}, $route{direction_out} )
90             = $r_link->look_down( _tag => 'a' );
91              
92 0           ( $route{direction_in_link}, $route{direction_out_link} )
93 0           = map { $_->attr( 'href' ) } $r_link->look_down( _tag => 'a' );
94              
95 0           ( $route{direction_in}, $route{direction_out} )
96 0           = map { $_->as_text } ( $route{direction_in}, $route{direction_out} );
97              
98 0           ( $route{description_in}, $route{description_out} )
99 0           = map { $_->as_text } $r_link->look_down( _tag => 'p' );
100 0           my $operator = $t->look_down( _tag => 'div', class => 'operator' )->as_text;
101 0           $operator =~ s/(Contact|Website|:)/,/g;
102 0           $operator =~ s/\s//g;
103 0           ( $route{operator} ,$route{operator_ph} ) = ( split /,/, $operator )[0,2];
104 0           $route{ua} = $self->{ua};
105 0           $route{uri} = $self->{uri};
106 0           my $route = WWW::PTV::Route->new( %route );
107 0 0         $CACHE->{ROUTE}->{$id} = $route if ( $self->{cache} );
108 0           return $route
109             }
110              
111              
112              
113             sub get_stop_by_id {
114 0     0 1   my( $self, $id )= @_;
115 0 0         $id or return "Mandatory parameter id not given";
116 0 0 0       return $CACHE->{STOP}->{$id} if ( $self->{cache} and $CACHE->{STOP}->{$id} );
117 0           my $r = $self->__request( "/stop/view/$id" );
118 0           my $t = HTML::TreeBuilder->new_from_content( $r );
119             #my $t = HTML::TreeBuilder->new_from_file( './45470' );
120 0           my %stop = (id => $id );
121 0           my $s_type = $t->look_down( _tag => 'img', class => 'stopModeImage' );
122 0           $stop{address} = $t->look_down( _tag => 'div', id => 'container' )
123             ->look_down( _tag => 'p' )
124             ->as_text;
125              
126 0           $stop{transport_type} = $s_type->attr('src');
127 0           $stop{transport_type} =~ s|themes/transport-site/images/jp/icons/icon||;
128 0           $stop{transport_type} =~ s|\.png||;
129 0           ( $stop{street}, $stop{locality} ) = ( split /,/, $stop{address} );
130 0           ( $stop{postcode} ) = $stop{locality} =~ /\b(\d{4})\b/;
131 0           $stop{municipiality} = $t->look_down( _tag => 'table', class => 'stationSummary' )
132             ->look_down( _tag => 'a' )
133             ->as_text;
134              
135 0           ( $stop{municipiality_id} ) = $t->look_down( _tag => 'table', class => 'stationSummary' )
136             ->look_down( _tag => 'a' )
137             ->attr( 'href' );
138 0           ( $stop{municipiality_id} ) = $stop{municipiality_id} =~ /\/(\d.*)$/;
139              
140 0           $stop{zone} = ( $t->look_down( _tag => 'table', class => 'stationSummary' )
141             ->look_down( _tag => 'td' )
142             )[2]->as_text;
143              
144 0           $stop{map_ref} = $t->look_down( _tag => 'div', class => 'aside' )
145             ->look_down( _tag => 'a' )
146             ->attr( 'href' );
147              
148 0           ( $stop{latitude} ) = $stop{map_ref} =~ /=(-?\d.*),/;
149              
150 0           ( $stop{longitude} ) = $stop{map_ref} =~ /,(-?\d.*)$/;
151              
152 0           ( $stop{phone_feedback}, $stop{phone_station} )
153 0           = map { $_->as_text } $t->look_down( _tag => 'div', class => 'expander phone-numbers' )
154             ->look_down( _tag => 'dd' );
155              
156 0           $stop{staff_hours} = $t->look_down( _tag => 'div', 'data-cookie' => 'stop-staff' )
157             ->look_down( _tag => 'dd' )->as_text;
158              
159 0           ( $stop{myki_machines}, $stop{myki_checks}, $stop{vline_bookings} )
160 0           = map { $_->as_text } $t->look_down( _tag => 'div', 'data-cookie' => 'stop-ticketing' )
161             ->look_down( _tag => 'dd' );
162              
163 0           ( $stop{car_parking}, $stop{_bicycles}, $stop{taxi_rank} )
164 0           = map { $_->as_text } $t->look_down( _tag => 'div', 'data-cookie' => 'stop-other-transport-links' )
165             ->look_down( _tag => 'dd' );
166              
167 0           ( $stop{bicycle_racks}, $stop{bicycle_lockers}, $stop{bicycle_cage} )
168 0           = map { s/.*://; $_ } split /,/, $stop{_bicycles};
  0            
169              
170 0           ( $stop{wheelchair_accessible}, $stop{stairs}, $stop{escalator}, $stop{lift}, $stop{tactile_paths}, $stop{hearing_loop} )
171 0           = map { $_->as_text } $t->look_down( _tag => 'div', 'data-cookie' => 'stop-accessibility' )
172             ->look_down( _tag => 'dd' );
173              
174 0           ( $stop{seating}, $stop{lighting}, $stop{lockers}, $stop{public_phone}, $stop{public_toilet}, $stop{_waiting_area} )
175 0           = map { $_->as_text } $t->look_down( _tag => 'div', 'data-cookie' => 'stop-general-facilities' )
176             ->look_down( _tag => 'dd' );
177              
178 0           ( $stop{waiting_area_indoor}, $stop{waiting_area_sheltered} )
179 0           = map { s/.*://; $_ } split /,/, $stop{_waiting_area};
  0            
180              
181 0           foreach my $line ( $t->look_down( _tag => 'div', 'data-cookie' => 'stop-line-timetables' )
182             ->look_down( _tag => 'div', class => 'timetable-row' ) ) {
183 0           my $ref = { id => $line->look_down( _tag => 'a' )->attr( 'href' ) =~ /^.*\/(.*)/ };
184 0           $ref->{ name } = $line->look_down( _tag => 'a' )->as_text;
185 0           $ref->{ type } = _get_line_type( $line->look_down( _tag => 'img' )->attr( 'src' ) );
186 0           push @{ $stop{routes} }, $ref
  0            
187             }
188              
189 0           $stop{ua} = $self->{ua};
190              
191 0           my $stop = WWW::PTV::Stop->new( %stop );
192 0 0         $CACHE->{STOP}->{$id} = $stop if ( $self->{cache} );
193              
194 0           return $stop
195             }
196              
197             sub get_area_by_id {
198 0     0 1   my( $self, $id )= @_;
199 0 0         $id or return "Mandatory parameter id not given";
200 0 0 0       return $CACHE->{AREA}->{$id} if ( $self->{cache} and $CACHE->{AREA}->{$id} );
201 0           my $r = $self->__request( "/location/view/$id" );
202 0           my $t = HTML::TreeBuilder->new_from_content( $r );
203             #my $t = HTML::TreeBuilder->new_from_file( './local_area_19' );
204             #my $t = HTML::TreeBuilder->new_from_file( './area_30' );
205 0           my %area = ( id => $id );
206 0           $area{name} = $t->look_down( _tag => 'h1' )->as_text;
207 0           @{ $area{suburbs}} = split /, /, $t->look_down( _tag => 'p' )->as_text;
  0            
208 0           my $t_type;
209              
210 0           foreach my $service ( $t->look_down( _tag => 'div', id => 'content' )->look_down( _tag => 'div' ) ) {
211 0           my $type = $service->look_down( _tag => 'h3' );
212              
213 0 0         if ( $type->as_text ne '' ) { $t_type = $type->as_text }
  0            
214              
215 0           @{ $area{service}{names}{$t_type} }
  0            
216 0           = map { $_->as_text } $service->look_down( _tag => 'li' );
217              
218 0           @{ $area{service}{links}{$t_type} }
  0            
219 0           = map { $_->attr( 'href' ) } $service->look_down( _tag => 'a' );
220             }
221              
222 0           my $area = WWW::PTV::Area->new( %area );
223 0 0         $CACHE->{AREA}->{$id} = $area if ( $self->{cache} );
224              
225 0           return $area
226             }
227              
228             sub get_local_areas {
229 0     0 1   my $self = shift;
230 0           my $r = $self->__request( '/getting-around/local-areas/' );
231 0           my $t = HTML::TreeBuilder->new_from_content( $r );
232             #my $t = HTML::TreeBuilder->new_from_file( './local_areas_list' );
233 0           $t = $t->look_down( _tag => 'div', id => 'content' );
234              
235 0           @{ $self->{local_areas}{names} }
  0            
236 0           = map { $_->as_text } $t->look_down( _tag => 'li' );
237              
238 0           @{ $self->{local_areas}{links} }
  0            
239 0           = map { $_->attr( 'href' ) } $t->look_down( _tag => 'a' );
240              
241 0           my %res;
242 0           @res{ @{ $self->{local_areas}{names} } } = @{ $self->{local_areas}{links} };
  0            
  0            
243 0           return %res
244             }
245              
246             sub _get_line_type {
247 0     0     my $obj = shift;
248 0           $obj =~ s/^.*\/icon//;
249 0           $obj =~ s/\..*$//;
250 0           return lc $obj
251             }
252              
253             1;
254              
255             __END__