File Coverage

lib/Google/RestApi/SheetsApi4/RangeGroup.pm
Criterion Covered Total %
statement 94 119 78.9
branch 12 18 66.6
condition 2 3 66.6
subroutine 21 28 75.0
pod 13 20 65.0
total 142 188 75.5


line stmt bran cond sub pod time code
1             package Google::RestApi::SheetsApi4::RangeGroup;
2              
3             # some private subroutines of Range are called from here,
4             # so think of RangeGroup as a friend of Range. the routines
5             # called are commented thusly:
6             # "private range routine called here!"
7              
8             our $VERSION = '1.0.4';
9              
10 1     1   563 use Google::RestApi::Setup;
  1         3  
  1         8  
11              
12 1     1   13633 use List::Util qw( first );
  1         3  
  1         73  
13 1     1   7 use Scalar::Util ();
  1         2  
  1         20  
14 1     1   5 use Storable qw( dclone );
  1         2  
  1         145  
15              
16 1     1   7 use aliased 'Google::RestApi::SheetsApi4::RangeGroup::Iterator';
  1         10  
  1         8  
17              
18             sub new {
19 26     26 1 73 my $class = shift;
20              
21 26         56 state $check = compile_named(
22             spreadsheet => HasApi,
23             ranges => ArrayRef[HasRange], { default => [] },
24             );
25              
26 26         3446 return bless $check->(@_), $class;
27             }
28              
29             sub push_ranges {
30 0     0 1 0 my $self = shift;
31 0         0 state $check = compile(slurpy ArrayRef[HasRange]);
32 0         0 my ($ranges) = $check->(@_);
33 0         0 push(@{ $self->{ranges} }, @$ranges);
  0         0  
34 0         0 return;
35             }
36              
37             sub clear {
38 0     0 1 0 my $self = shift;
39              
40 0         0 $self->clear_cached_values();
41              
42 0         0 my @ranges = map { $_->range(); } $self->ranges();
  0         0  
43 0         0 my %p = (
44             content => { ranges => \@ranges },
45             uri => "/values:batchClear",
46             method => "post",
47             );
48 0         0 return $self->api(%p);
49             }
50              
51             sub clear_cached_values {
52 0     0 0 0 my $self = shift;
53 0         0 $_->clear_cached_values() foreach $self->ranges();
54 0         0 return;
55             }
56              
57             sub refresh_values {
58 0     0 0 0 my $self = shift;
59 0         0 $self->clear_cached_values();
60 0         0 return $self->values();
61             }
62              
63             sub values {
64 19     19 1 496 my $self = shift;
65              
66 19         41 state $check = compile_named(
67             params => HashRef, { default => {} },
68             _extra_ => slurpy Any,
69             );
70 19         5204 my $p = named_extra($check->(@_));
71              
72 19         99 my @ranges = $self->ranges();
73 19         71 my @needs_values = grep { !$_->has_values(); } @ranges;
  54         148  
74             # for some reason google designed this so that you can set
75             # various ranges in the params, but only one majorDimension
76             # for the entire url. it's a bit strange since the return
77             # values have a majorDimension in each range. all other parts
78             # of their api treat range/majorDimension as a unit except for
79             # batchGet. so we have to potentially do two calls for a
80             # batch get, one for cols, and one for rows.
81 19         57 my (@cols, @rows);
82 19         55 foreach (@needs_values) {
83 23 100       68 if ($_->dimension() =~ /^col/i) { push(@cols, $_); }
  3         6  
84 20         45 else { push(@rows, $_); }
85             }
86 19         922 $self->_batch_get('col', dclone($p), \@cols);
87 19         289 $self->_batch_get('row', dclone($p), \@rows);
88              
89 19         74 my @values = map { $_->values(); } @ranges;
  54         172  
90 19         261 return \@values;
91             }
92              
93             sub _batch_get {
94 38     38   102 my $self = shift;
95              
96 38         102 my ($dim, $p, $ranges) = @_;
97 38 100 66     212 return if !$ranges || !@$ranges;
98              
99 9         28 my @ranges = map { $_->range(); } @$ranges;
  23         75  
100 9         35 $p->{params}->{ranges} = \@ranges;
101 9 100       40 $p->{params}->{majorDimension} = 'COLUMNS' if $dim =~ /^col/i;
102 9         33 $p->{uri} = "/values:batchGet";
103              
104 9         52 my $response = $self->api(%$p);
105              
106 9         37 my $value_ranges = $response->{valueRanges};
107             # private range routine called here!
108 9         29 my @ranges2 = map { $_->range(); } @$ranges;
  23         77  
109 23         150 $ranges->[$_]->_cache_range_values(%{ $value_ranges->[$_] })
110 9         58 foreach (0..$#$ranges);
111              
112 9         48 return;
113             }
114              
115             sub batch_values {
116 10     10 1 27 my $self = shift;
117              
118 10         22 state $check = compile_named(
119             values => ArrayRef, { optional => 1 },
120             );
121 10         2052 my $p = $check->(@_);
122              
123 10         264 my $values = $p->{values};
124 10 50       35 if (defined $values) {
125 0         0 my @ranges = $self->ranges();
126 0 0       0 LOGDIE "Too many values provided for range group" if scalar @$values > scalar @ranges;
127 0         0 $ranges[$_]->batch_values(values => $values->[$_]) foreach (0..$#$values);
128 0         0 return $self;
129             }
130              
131             my @batch_values = map {
132 10 50       33 $_->has_values() ? ($_->batch_values()) : ();
  31         92  
133             } $self->ranges();
134              
135 10         57 return \@batch_values;
136             }
137              
138             sub values_response_from_api {
139 10     10 0 30 my $self = shift;
140 10         27 state $check = compile(ArrayRef);
141 10         2229 my ($updates) = $check->(@_);
142             my @updates = map {
143 10 50       143 $_->has_values() ? ($_->values_response_from_api($updates)) : ();
  31         119  
144             } $self->ranges();
145 10         63 return \@updates;
146             }
147              
148             sub submit_values {
149 10     10 1 395 my $self = shift;
150 10         33 $self->spreadsheet()->submit_values(ranges => [ $self ], @_);
151 10         56 return $self->values();
152             }
153              
154             sub batch_requests {
155 2     2 1 6 my $self = shift;
156             my @batch_requests = map {
157 2         7 $_->batch_requests(@_);
  6         13  
158             } $self->ranges();
159 2         8 return @batch_requests;
160             }
161              
162             sub submit_requests {
163 1     1 1 44 my $self = shift;
164 1         5 return $self->spreadsheet()->submit_requests(ranges => [ $self ], @_);
165             # return $self;
166             }
167              
168             sub requests_response_from_api {
169 1     1 0 3 my $self = shift;
170 1         5 state $check = compile(ArrayRef);
171 1         2168 my ($requests) = $check->(@_);
172             my @requests = map {
173 1         16 $_->requests_response_from_api($requests);
  3         29  
174             } $self->ranges();
175 1         5 return \@requests;
176             }
177              
178             sub iterator {
179 1     1 1 51 my $self = shift;
180 1         14 return Iterator->new(@_, range_group => $self);
181             }
182              
183             sub has_values {
184 10     10 1 32 my $self = shift;
185 10     10   69 return first { $_->has_values(); } $self->ranges();
  10         46  
186             }
187              
188             # enables pass-throughs to the underlying ranges so you can go:
189             # $range_group->red()->bold() etc.
190             sub AUTOLOAD {
191 28     28   1262 our $AUTOLOAD;
192 28 100       511 return if $AUTOLOAD =~ /DESTROY$/;
193 2 50       7 return if $AUTOLOAD =~ /\0$/; # wtf is this???
194              
195 2         7 my $self = shift;
196 2         11 my $method = (split('::', $AUTOLOAD))[-1];
197 2         9 $_->$method(@_) for $self->ranges();
198 2         22 return $self;
199             }
200              
201 64     64 1 129 sub ranges { @{ shift->{ranges} }; }
  64         260  
202 26     26 1 142 sub spreadsheet { shift->{spreadsheet}; }
203 9     9 1 33 sub api { shift->spreadsheet()->api(@_); }
204 0     0 0   sub sheets_api { shift->spreadsheet()->sheets_api(); }
205 0     0 0   sub rest_api { shift->sheets_api()->rest_api(); }
206 0     0 0   sub transaction { shift->rest_api()->transaction(); }
207              
208             1;
209              
210             __END__
211              
212             =head1 NAME
213              
214             Google::RestApi::SheetsApi4::RangeGroup - Represents a group of ranges in a Worksheet.
215              
216             =head1 DESCRIPTION
217              
218             A RangeGroup is a lightweight object that represents a collection of ranges
219             on which you can operate as one unit (e.g. RangeGroup::submit_values
220             will submit all batch values for the underlying ranges).
221              
222             See the description and synopsis at Google::RestApi::SheetsApi4.
223              
224             =head1 NAVIGATION
225              
226             =over
227              
228             =item * L<Google::RestApi::SheetsApi4>
229              
230             =item * L<Google::RestApi::SheetsApi4::Spreadsheet>
231              
232             =item * L<Google::RestApi::SheetsApi4::Worksheet>
233              
234             =item * L<Google::RestApi::SheetsApi4::Range>
235              
236             =item * L<Google::RestApi::SheetsApi4::Range::All>
237              
238             =item * L<Google::RestApi::SheetsApi4::Range::Col>
239              
240             =item * L<Google::RestApi::SheetsApi4::Range::Row>
241              
242             =item * L<Google::RestApi::SheetsApi4::Range::Cell>
243              
244             =item * L<Google::RestApi::SheetsApi4::RangeGroup>
245              
246             =item * L<Google::RestApi::SheetsApi4::RangeGroup::Iterator>
247              
248             =item * L<Google::RestApi::SheetsApi4::RangeGroup::Tie>
249              
250             =item * L<Google::RestApi::SheetsApi4::RangeGroup::Tie::Iterator>
251              
252             =item * L<Google::RestApi::SheetsApi4::Request::Spreadsheet>
253              
254             =item * L<Google::RestApi::SheetsApi4::Request::Spreadsheet::Worksheet>
255              
256             =item * L<Google::RestApi::SheetsApi4::Request::Spreadsheet::Worksheet::Range>
257              
258             =back
259              
260             =head1 SUBROUTINES
261              
262             =over
263              
264             =item new(spreadsheet => <Spreadsheet>, ranges => <arrayref<Range>>);
265              
266             Creates a new range group object for the given spreadsheet.
267              
268             spreadsheet: The parent Spreadsheet object for this range group.
269             ranges: The array of ranges to be grouped into this range group.
270              
271             You would not normally call this directly, you'd use Spreadsheet::range_group
272             method to create the range group object for you.
273              
274             =item api(%args);
275              
276             Calls the parent spreadsheet's 'api' routine with the ranges added into
277             the URI or content appropriately.
278              
279             You would not normally call this directly unless you were
280             making a Google API call not currently supported by this API
281             framework.
282              
283             =item push_ranges(<arrayref<Range>>);
284              
285             Adds the extra ranges to this range group. No attempt is made to
286             check for duplicate range objects.
287              
288             =item clear();
289              
290             Clears each range in the range group in one call using batchClear
291             Google API call.
292              
293             =item values(%args);
294              
295             Fetches the values of the spreadsheet for each range in the group. Note
296             that there is no way to set values with this method as it is assumed
297             that setting will be done via routine batch_values.
298              
299             'args' are passed to the SheetsApi4's 'api' routine so you may add
300             extra arguments to the 'params' as necessary.
301              
302             =item batch_values(values => <arrayref>);
303              
304             Gets or sets the queued batch values for each range in the range group.
305             Batch values can be set on particular ranges individually, or can be
306             set with this routine all in one shot.
307              
308             =item submit_values(%args);
309              
310             Sends the previously queued batch values to Google API, if any.
311              
312             'args' are passed to the SheetsApi4's 'api' routine so you may add
313             extra arguments to the 'params' or 'content' as necessary.
314              
315             =item batch_requests();
316              
317             Gets the queued batch requests for each range in the group.
318              
319             =item submit_requests(%args);
320              
321             Sends the previously queued requests (formatting, sheet properties etc)
322             to Google API, if any.
323              
324             'args' are passed to the SheetsApi4's 'api' routine so you may add
325             extra arguments to the 'params' or 'content' as necessary.
326              
327             =item iterator(%args);
328              
329             Returns an iterator for this range group. Any 'args' are passed to the
330             'new' routine for the iterator.
331              
332             =item has_values();
333              
334             Returns a true value if any of the underlying ranges has values
335             associated with it.
336              
337             =item ranges();
338              
339             Returns the array of Range objects in this range group.
340              
341             =item spreadsheet();
342              
343             Returns the parent Spreadsheet object.
344              
345             =back
346              
347             =head1 AUTHORS
348              
349             =over
350              
351             =item
352              
353             Robin Murray mvsjes@cpan.org
354              
355             =back
356              
357             =head1 COPYRIGHT
358              
359             Copyright (c) 2021, Robin Murray. All rights reserved.
360              
361             This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.