File Coverage

blib/lib/WWW/LinkChecker/Internal/API/Worker.pm
Criterion Covered Total %
statement 29 92 31.5
branch 0 28 0.0
condition 0 17 0.0
subroutine 10 14 71.4
pod 1 1 100.0
total 40 152 26.3


line stmt bran cond sub pod time code
1             package WWW::LinkChecker::Internal::API::Worker;
2             $WWW::LinkChecker::Internal::API::Worker::VERSION = '0.14.0';
3 2     2   333852 use strict;
  2         3  
  2         64  
4 2     2   7 use warnings;
  2         3  
  2         96  
5 2     2   33 use 5.014;
  2         5  
6              
7 2     2   1124 use Moo;
  2         18073  
  2         10  
8              
9 2     2   4564 use Heap::Elem::Str qw( StrElem );
  2         2184  
  2         127  
10 2     2   1046 use Heap::Fibonacci ();
  2         5521  
  2         103  
11 2     2   1143 use JSON::MaybeXS qw( decode_json encode_json );
  2         19238  
  2         205  
12 2     2   16 use List::Util 1.34 qw/ any none /;
  2         45  
  2         284  
13              
14 2     2   1937 use Path::Tiny qw/ path /;
  2         31545  
  2         174  
15              
16 2     2   3688 use WWW::Mechanize ();
  2         394541  
  2         1656  
17              
18             has 'base_url' => ( is => 'ro', required => 1 );
19             has 'before_insert_skip' => ( is => 'ro', required => 1 );
20             has 'pre_skip' => ( is => 'ro', required => 1 );
21             has 'only_check_site_flow' => ( is => 'ro', );
22             has 'start_url' => ( is => 'ro', );
23             has 'state_filename' => ( is => 'ro', );
24              
25             sub run
26             {
27 0     0 1   my ( $self, $args ) = @_;
28              
29             my $check_url_inform_cb =
30 0   0 0     ( $args->{check_url_inform_cb} // sub { return; } );
  0            
31 0           my $base_url = $self->base_url;
32 0 0         if ( !defined($base_url) )
33             {
34 0           die "--base must be specified";
35             }
36 0           my @before_insert_skips_regexes = @{ $self->before_insert_skip() };
  0            
37              
38 0           my @pre_skip_regexes = @{ $self->pre_skip() };
  0            
39 0           my $alternative_start_url = $self->start_url();
40 0           my $only_check_site_flow = $self->only_check_site_flow();
41 0           my $state_fn = $self->state_filename();
42 0   0       my $start_url = ( $alternative_start_url || $base_url );
43              
44 0 0 0       my $state =
45             +( $state_fn && ( -e $state_fn ) )
46             ? decode_json( path($state_fn)->slurp_utf8 )
47             : {
48             stack => scalar( Heap::Fibonacci->new() ),
49             encountered_urls => { $start_url => undef(), },
50             };
51 0           my $stack = $state->{stack};
52             {
53 0           my $el = StrElem($start_url);
  0            
54 0           $stack->add($el);
55             }
56 0           my $encountered_urls = $state->{encountered_urls};
57 0           my $prev;
58             my $dest_url;
59 0           my $url;
60             STACK:
61              
62 0           while ( defined( my $url_rec = $stack->extract_top() ) )
63             {
64 0           $dest_url = undef;
65 0           $url = $url_rec->val();
66 0           $check_url_inform_cb->( { url => $url, } );
67              
68 0           my $mech = WWW::Mechanize->new();
69 0           eval { $mech->get($url); };
  0            
70              
71 0 0         if ($@)
72             {
73 0           $stack->add($url_rec);
74 0 0         if ($state_fn)
75             {
76 0           path($state_fn)->spew_utf8( encode_json($state) );
77             }
78 0   0       my $from = ( $encountered_urls->{$dest_url} // "START" );
79 0           die "SRC URL $from points to '$url'.";
80             }
81              
82 0 0   0     if ( any { $url =~ $_ } @pre_skip_regexes )
  0            
83             {
84 0           next STACK;
85             }
86             my $process = sub {
87 0     0     my ($link) = @_;
88 0           $dest_url = $link->url_abs() . "";
89 0           $dest_url =~ s{#[^#]+\z}{}ms;
90 0 0 0       if ( ( !exists( $encountered_urls->{$dest_url} ) )
      0        
91             and $dest_url =~ m{\A\Q$base_url\E}ms
92 0           and ( none { $dest_url =~ $_ } @before_insert_skips_regexes ) )
93             {
94 0           $encountered_urls->{$dest_url} = $url;
95 0           my $el = StrElem($dest_url);
96 0           $stack->add($el);
97             }
98 0           };
99 0           foreach my $link ( $mech->links() )
100             {
101 0 0         if ($only_check_site_flow)
102             {
103 0 0         if ( $link->tag() eq 'link' )
104             {
105 0           my $rel = $link->attrs()->{'rel'};
106 0 0         if ( $rel eq 'prev' )
    0          
107             {
108 0 0         if ( defined $prev )
109             {
110 0 0         if ( $link->url_abs ne $prev )
111             {
112 0           die "prev";
113             }
114             else
115             {
116 0           say "prev = $prev ;";
117             }
118             }
119             }
120             elsif ( $rel eq 'next' )
121             {
122 0           $process->($link);
123             }
124             }
125             }
126             else
127             {
128 0           $process->($link);
129             }
130             }
131             }
132             continue
133             {
134 0 0         if ($only_check_site_flow)
135             {
136 0 0         if ( !defined($dest_url) )
137             {
138 0           die "no next at SRC = $url";
139             }
140 0           $prev = $url;
141             }
142             }
143              
144 0           return +{ success => 1, };
145             }
146              
147             1;
148              
149             __END__