File Coverage

blib/lib/GitLab/API/v4/Paginator.pm
Criterion Covered Total %
statement 18 52 34.6
branch 0 14 0.0
condition 0 2 0.0
subroutine 6 10 60.0
pod 4 4 100.0
total 28 82 34.1


line stmt bran cond sub pod time code
1             package GitLab::API::v4::Paginator;
2             our $VERSION = '0.25';
3              
4             =encoding utf8
5              
6             =head1 NAME
7              
8             GitLab::API::v4::Paginator - Iterate through paginated GitLab v4 API records.
9              
10             =head1 DESCRIPTION
11              
12             There should be no need to create objects of this type
13             directly, instead use L which
14             simplifies things a bit.
15              
16             =cut
17              
18 1     1   7 use Carp qw( croak );
  1         2  
  1         57  
19 1     1   7 use Types::Common::String -types;
  1         3  
  1         12  
20 1     1   1645 use Types::Standard -types;
  1         3  
  1         7  
21              
22 1     1   4537 use Moo;
  1         2  
  1         6  
23 1     1   382 use strictures 2;
  1         5  
  1         37  
24 1     1   166 use namespace::clean;
  1         3  
  1         8  
25              
26             =head1 REQUIRED ARGUMENTS
27              
28             =head2 method
29              
30             The name of the method subroutine to call on the L object
31             to get records from.
32              
33             This method must accept a hash ref of parameters as the last
34             argument, adhere to the C and C parameters, and
35             return an array ref.
36              
37             =cut
38              
39             has method => (
40             is => 'ro',
41             isa => NonEmptySimpleStr,
42             required => 1,
43             );
44              
45             =head2 api
46              
47             The L object.
48              
49             =cut
50              
51             has api => (
52             is => 'ro',
53             isa => InstanceOf[ 'GitLab::API::v4' ],
54             required => 1,
55             );
56              
57             =head1 OPTIONAL ARGUMENTS
58              
59             =head2 args
60              
61             The arguments to use when calling the L, the same arguments
62             you would use when you call the method yourself on the L
63             object, minus the C<\%params> hash ref.
64              
65             =cut
66              
67             has args => (
68             is => 'ro',
69             isa => ArrayRef,
70             default => sub{ [] },
71             );
72              
73             =head2 params
74              
75             The C<\%params> hash ref argument.
76              
77             =cut
78              
79             has params => (
80             is => 'ro',
81             isa => HashRef,
82             default => sub{ {} },
83             );
84              
85             =head1 METHODS
86              
87             =cut
88              
89             has _records => (
90             is => 'rw',
91             init_arg => undef,
92             default => sub{ [] },
93             );
94              
95             has _page => (
96             is => 'rw',
97             init_arg => undef,
98             default => 0,
99             );
100              
101             has _last_page => (
102             is => 'rw',
103             init_arg => undef,
104             default => 0,
105             );
106              
107             =head2 next_page
108              
109             while (my $records = $paginator->next_page()) { ... }
110              
111             Returns an array ref of records for the next page.
112              
113             =cut
114              
115             sub next_page {
116 0     0 1   my ($self) = @_;
117              
118 0 0         return if $self->_last_page();
119              
120 0           my $page = $self->_page() + 1;
121 0           my $params = $self->params();
122 0   0       my $per_page = $params->{per_page} || 20;
123              
124 0           $params = {
125             %$params,
126             page => $page,
127             per_page => $per_page,
128             };
129              
130 0           my $method = $self->method();
131             my $records = $self->api->$method(
132 0           @{ $self->args() },
  0            
133             $params,
134             );
135              
136 0 0         croak("The $method method returned a non array ref value")
137             if ref($records) ne 'ARRAY';
138              
139 0           $self->_page( $page );
140 0 0         $self->_last_page( 1 ) if @$records < $per_page;
141 0           $self->_records( [ @$records ] );
142              
143 0 0         return if !@$records;
144              
145 0           return $records;
146             }
147              
148             =head2 next
149              
150             while (my $record = $paginator->next()) { ... }
151              
152             Returns the next record in the current page. If all records have
153             been exhausted then L will automatically be called.
154             This way if you want to ignore pagination you can just call C
155             over and over again to walk through all the records.
156              
157             =cut
158              
159             sub next {
160 0     0 1   my ($self) = @_;
161              
162 0           my $records = $self->_records();
163 0 0         return shift(@$records) if @$records;
164              
165 0 0         return if $self->_last_page();
166              
167 0           $self->next_page();
168              
169 0           $records = $self->_records();
170 0 0         return shift(@$records) if @$records;
171              
172 0           return;
173             }
174              
175             =head2 all
176              
177             my $records = $paginator->all();
178              
179             This is just an alias for calling L over and over
180             again to build an array ref of all records.
181              
182             =cut
183              
184             sub all {
185 0     0 1   my ($self) = @_;
186              
187 0           $self->reset();
188              
189 0           my @records;
190 0           while (my $page = $self->next_page()) {
191 0           push @records, @$page;
192             }
193              
194 0           return \@records;
195             }
196              
197             =head2 reset
198              
199             $paginator->reset();
200              
201             Reset the paginator back to its original state on the first page
202             with no records retrieved yet.
203              
204             =cut
205              
206             sub reset {
207 0     0 1   my ($self) = @_;
208 0           $self->_records( [] );
209 0           $self->_page( 0 );
210 0           $self->_last_page( 0 );
211 0           return;
212             }
213              
214             1;
215             __END__