File Coverage

blib/lib/Twitter/API/Trait/DecodeHtmlEntities.pm
Criterion Covered Total %
statement 22 22 100.0
branch 7 10 70.0
condition 2 2 100.0
subroutine 6 6 100.0
pod n/a
total 37 40 92.5


line stmt bran cond sub pod time code
1             package Twitter::API::Trait::DecodeHtmlEntities;
2             # ABSTRACT: Decode HTML entities in strings
3             $Twitter::API::Trait::DecodeHtmlEntities::VERSION = '1.0006';
4 1     1   7733 use Moo::Role;
  1         2  
  1         5  
5 1     1   710 use HTML::Entities qw/decode_entities/;
  1         4525  
  1         59  
6 1     1   6 use Scalar::Util qw/refaddr/;
  1         1  
  1         38  
7 1     1   382 use Ref::Util qw/is_arrayref is_hashref is_ref/;
  1         1231  
  1         60  
8 1     1   387 use namespace::clean;
  1         8788  
  1         20  
9              
10             sub _decode_html_entities {
11 7     7   15187 my ( $self, $ref, $seen ) = @_;
12 7   100     29 $seen //= {};
13              
14             # Recursively walk data structure; decode entities is place on strings
15 7 50       20 for ( is_arrayref($ref) ? @$ref : is_hashref($ref) ? values %$ref : () ) {
    100          
16 23 50       35 next unless defined;
17              
18             # There shouldn't be any circular references in Twitter results, but
19             # guard against it, anyway.
20 23 100       38 if ( my $id = refaddr($_) ) {
21 6 50       36 $self->_decode_html_entities($_, $seen) unless $$seen{$id}++;
22             }
23             else {
24             # decode in place; happily, numbers remain untouched, no PV created
25 17         50 decode_entities($_);
26             }
27             }
28             }
29              
30             around inflate_response => sub {
31             my ( $orig, $self, $c ) = @_;
32              
33             $self->$orig($c);
34             $self->_decode_html_entities($c->result);
35             };
36              
37             1;
38              
39             __END__
40              
41             =pod
42              
43             =encoding UTF-8
44              
45             =head1 NAME
46              
47             Twitter::API::Trait::DecodeHtmlEntities - Decode HTML entities in strings
48              
49             =head1 VERSION
50              
51             version 1.0006
52              
53             =head1 SYNOPSIS
54              
55             use Twitter::API;
56             use open qw/:std :utf8/;
57              
58             my $client = Twitter::API->new_with_traits(
59             traits => [ qw/ApiMethods DecodeHtmlEntites/ ],
60             %other_options
61             );
62              
63             my $status = $client->show_status(801814387723935744);
64             say $status->{text};
65              
66             # output:
67             # Test DecodeHtmlEntities trait. < & > ⚠️ 🏉 'single' "double"
68             #
69             # output without the DecodeHtmlEntities trait:
70             # Test DecodeHtmlEntities trait. &lt; &amp; &gt; ⚠️ 🏉 'single' "double"
71              
72             =head1 DESCRIPTION
73              
74             Twitter has trust issues. They assume you're going to push the text you receive
75             in API responses to a web page without HTML encoding it. But you HTML encode
76             all of your output right? And Twitter's lack of trust has you double encoding
77             entities.
78              
79             So, include this trait and Twitter::API will decode HTML entities in all of the
80             text returned by the API.
81              
82             You're welcome.
83              
84             =head1 AUTHOR
85              
86             Marc Mims <marc@questright.com>
87              
88             =head1 COPYRIGHT AND LICENSE
89              
90             This software is copyright (c) 2015-2021 by Marc Mims.
91              
92             This is free software; you can redistribute it and/or modify it under
93             the same terms as the Perl 5 programming language system itself.
94              
95             =cut