File Coverage

blib/lib/Twitter/API/Trait/NormalizeBooleans.pm
Criterion Covered Total %
statement 15 15 100.0
branch 6 6 100.0
condition 3 3 100.0
subroutine 6 6 100.0
pod 0 3 0.0
total 30 33 90.9


line stmt bran cond sub pod time code
1             package Twitter::API::Trait::NormalizeBooleans;
2             # ABSTRACT: Normalize Booleans
3             $Twitter::API::Trait::NormalizeBooleans::VERSION = '1.0006';
4 1     1   8341 use 5.14.1;
  1         4  
5 1     1   6 use Moo::Role;
  1         1  
  1         6  
6 1     1   790 use namespace::clean;
  1         9735  
  1         5  
7              
8             requires 'preprocess_args';
9              
10             around preprocess_args => sub {
11             my ( $next, $self, $c ) = @_;
12              
13             $self->$next($c);
14             $self->normalize_bools($c->args);
15             };
16              
17             # Twitter usually accepts 1, 't', 'true', or false for booleans, but they
18             # prefer 'true' or 'false'. In some cases, like include_email, they only accept
19             # 'true'. So, we normalize these options.
20             my @normal_bools = qw/
21             contributor_details display_coordinates exclude_replies hide_media
22             hide_thread hide_tweet include_email include_entities include_my_tweet
23             include_rts include_user_entities map omit_script possibly_sensitive
24             reverse trim_user
25             /;
26              
27             # Workaround Twitter bug: any value passed for these options are treated as
28             # true. The only way to get 'false' is to not pass the skip_user at all. So,
29             # we strip these boolean args if their values are false.
30             my @true_only_bools = qw/skip_status skip_user/;
31              
32             my %is_bool = map { $_ => undef } @normal_bools, @true_only_bools;
33             my %is_true_only_bool = map { $_ => undef } @true_only_bools;
34              
35 5     5 0 14 sub is_bool { exists $is_bool{$_[1]} }
36              
37 3     3 0 14 sub is_true_only_bool { exists $is_true_only_bool{$_[1]} }
38              
39             sub normalize_bools {
40 1     1 0 14566 my ( $self, $args ) = @_;
41              
42             # Twitter prefers 'true' or 'false' (requires it in some cases).
43 1         5 for my $k ( keys %$args ) {
44 5 100       11 next unless $self->is_bool($k);
45 3 100       8 $args->{$k} = $args->{$k} ? 'true' : 'false';
46             delete $args->{$k} if $self->is_true_only_bool($k)
47 3 100 100     7 && $args->{$k} eq 'false';
48             }
49             }
50              
51             1;
52              
53             __END__
54              
55             =pod
56              
57             =encoding UTF-8
58              
59             =head1 NAME
60              
61             Twitter::API::Trait::NormalizeBooleans - Normalize Booleans
62              
63             =head1 VERSION
64              
65             version 1.0006
66              
67             =head1 SYNOPSIS
68              
69             use Twitter::API;
70              
71             my $client = Twitter::API->new_with_traits(
72             traits => [ qw/ApiMethods NormalizeBooleans/ ],
73             %other_new_options
74             );
75              
76             my ( $r, $c ) = $client->home_timeline({ trim_user => 1 });
77              
78             say $c->http_request->uri;
79              
80             # output:
81             https://api.twitter.com/1.1/statuses/home_timeline.json?trim_user=true
82              
83             =head1 DESCRIPTION
84              
85             Twitter has a strange concept of boolean values. Usually, the API accepts C<t>,
86             C<true>, or C<1> for true. Sometimes it accepts C<f>, C<false>, or C<0> for
87             false. But then you have strange cases like the C<include_email> parameter used
88             for authorized applications by the C<verify_credentials> endpoint. It only
89             accepts C<true>. Worse, for some boolean values, passing C<f>, C<false>, or
90             C<0> all work as if you passed C<true>. For those values, false means not
91             including the parameter at all.
92              
93             So, this trait attempts to normalize booleans by transforming any perl truthy
94             value to the Twitter API's preference, C<true>. It transforms falsey values to
95             C<false>. And then it removes false parameters that the API always treats as
96             true.
97              
98             You're welcome.
99              
100             =head1 AUTHOR
101              
102             Marc Mims <marc@questright.com>
103              
104             =head1 COPYRIGHT AND LICENSE
105              
106             This software is copyright (c) 2015-2021 by Marc Mims.
107              
108             This is free software; you can redistribute it and/or modify it under
109             the same terms as the Perl 5 programming language system itself.
110              
111             =cut