File Coverage

blib/lib/XML/GSA/Group.pm
Criterion Covered Total %
statement 21 99 21.2
branch 0 60 0.0
condition 0 70 0.0
subroutine 7 19 36.8
pod 7 7 100.0
total 35 255 13.7


line stmt bran cond sub pod time code
1             package XML::GSA::Group;
2              
3 1     1   5 use strict;
  1         2  
  1         38  
4 1     1   5 use warnings;
  1         3  
  1         34  
5              
6 1     1   6 use XML::Writer;
  1         2  
  1         18  
7 1     1   5 use Data::Dumper;
  1         2  
  1         57  
8 1     1   5 use Carp;
  1         2  
  1         56  
9 1     1   6 use DateTime ();
  1         1  
  1         22  
10 1     1   5 use Date::Parse ();
  1         2  
  1         2023  
11              
12             sub new {
13 0     0 1   my $class = shift;
14              
15 0   0       return bless { 'records' => [], 'action' => 'add', @_, },
16             ref $class || $class;
17             }
18              
19             #getters
20             sub writer {
21 0     0 1   my $self = shift;
22              
23 0           return $self->{'writer'};
24             }
25              
26             sub xml {
27 0     0 1   my $self = shift;
28              
29 0           return $self->{'xml'};
30             }
31              
32             sub to_string {
33 0     0 1   my $self = shift;
34              
35 0           return $self->{'xml'};
36             }
37              
38             sub records {
39 0     0 1   my $self = shift;
40              
41 0   0       return $self->{'records'} || [];
42             }
43              
44             #getters and setters
45             sub action {
46 0     0 1   my ( $self, $value ) = @_;
47              
48 0 0 0       $self->{'action'} = $value
49             if $value && $value =~ /(add|delete)/;
50              
51 0           return $self->{'action'};
52             }
53              
54             #other public methods
55             sub create {
56 0     0 1   my ( $self, $feed ) = @_;
57              
58 0 0 0       return unless $feed && ref $feed eq 'XML::GSA';
59              
60             #always
61 0           my $writer = XML::Writer->new( OUTPUT => 'self', );
62 0           $self->{'writer'} = $writer;
63              
64 0           my %attributes;
65 0 0         $attributes{'action'} = $self->action
66             if defined $self->action;
67              
68 0           $self->writer->startTag( 'group', %attributes );
69              
70 0 0         for my $record ( @{ $self->records || [] } ) {
  0            
71 0           $self->_add_record( $record, $feed );
72             }
73              
74 0           $self->writer->endTag('group');
75              
76 0           my $xml = $self->writer->to_string;
77 0           $self->{'xml'} = $xml;
78              
79 0           return $xml;
80             }
81              
82             #private methods
83              
84             #adds a record to a feed
85             sub _add_record {
86 0     0     my ( $self, $record, $feed ) = @_;
87              
88 0 0 0       return unless $self->writer && $record && ref $record eq 'HASH';
      0        
89              
90             #url and mimetype are mandatory parameters for the record
91 0 0 0       return unless $record->{'url'} && $record->{'mimetype'};
92              
93 0           my $attributes = $self->_record_attributes( $record, $feed );
94              
95 0 0         $self->writer->startTag( 'record', %{ $attributes || {} } );
  0            
96              
97 0 0 0       if ( $record->{'metadata'} && ref $record->{'metadata'} eq 'ARRAY' ) {
98 0           $self->_add_metadata( $record->{'metadata'} );
99             }
100              
101 0 0         $self->_record_content($record)
102             if $feed->type eq 'full';
103              
104 0           $self->writer->endTag('record');
105             }
106              
107             #adds record content part
108             sub _record_content {
109 0     0     my ( $self, $record ) = @_;
110              
111 0 0 0       return unless $self->writer && $record->{'content'};
112              
113 0 0         if ( $record->{'mimetype'} eq 'text/plain' ) {
    0          
114 0           $self->writer->dataElement( 'content', $record->{'content'} );
115             }
116             elsif ( $record->{'mimetype'} eq 'text/html' ) {
117 0           $self->writer->cdataElement( 'content', $record->{'content'} );
118             }
119              
120             #else {
121             #TODO support other mimetype with base64 encoding content
122             #}
123             }
124              
125             #creates record attributes
126             sub _record_attributes {
127 0     0     my ( $self, $record, $feed ) = @_;
128              
129             #must be a full record url
130             #that is: if no base url, the url in record must start with http
131             #base url and url in record can't include the domain at the same time
132 0 0 0       if (( !$feed->base_url && $record->{'url'} !~ /^http/ )
      0        
      0        
      0        
133             || ( $feed->base_url
134             && $feed->base_url =~ /^http/
135             && $record->{'url'} =~ /^http/ )
136             )
137             {
138 0           return {};
139             }
140              
141             #mandatory attributes
142 0 0         my %attributes = (
143             'url' => $feed->base_url
144             ? sprintf( '%s%s', $feed->base_url, $record->{'url'} )
145             : $record->{'url'},
146             'mimetype' => $record->{'mimetype'},
147             );
148              
149             ####optional attributes####
150              
151             #action is delete or add
152 0 0 0       $attributes{'action'} = $record->{'action'}
153             if $record->{'action'}
154             && $record->{'action'} =~ /^(delete|add)$/;
155              
156             #lock is true or false
157 0 0 0       $attributes{'lock'} = $record->{'lock'}
158             if $record->{'lock'}
159             && $record->{'lock'} =~ /^(true|false)$/;
160              
161 0 0         $attributes{'displayurl'} = $record->{'displayurl'}
162             if $record->{'displayurl'};
163              
164             #validate datetime format
165 0 0         if ( $record->{'last-modified'} ) {
166 0           my $date = $self->_to_RFC822_date( $record->{'last-modified'} );
167              
168 0 0         $attributes{'last-modified'} = $date
169             if $date;
170             }
171              
172             #allowed values for authmethod
173 0 0 0       $attributes{'authmethod'} = $record->{'authmethod'}
174             if $record->{'authmethod'}
175             && $record->{'authmethod'} =~ /^(none|httpbasic|ntlm|httpsso)$/;
176              
177 0 0 0       $attributes{'pagerank'} = $record->{'pagerank'}
178             if $feed->type ne 'metadata-and-url' && defined $record->{'pagerank'};
179              
180             #true or false and only for web feeds
181 0 0 0       $attributes{'crawl-immediately'} = $record->{'crawl-immediately'}
      0        
182             if $feed->datasource eq 'web'
183             && $record->{'crawl-immediately'}
184             && $record->{'crawl-immediately'} =~ /^(true|false)$/;
185              
186             #for web feeds
187 0 0 0       $attributes{'crawl-once'} = $record->{'crawl-once'}
      0        
      0        
188             if ( $feed->datasource eq 'web'
189             && $feed->type() eq 'metadata-and-url'
190             && $record->{'crawl-once'}
191             && $record->{'crawl-once'} =~ /^(true|false)$/ );
192              
193 0           return \%attributes;
194             }
195              
196             sub _add_metadata {
197 0     0     my ( $self, $metadata ) = @_;
198              
199 0 0 0       return unless $self->writer && scalar @{ $metadata || [] };
  0 0          
200              
201 0           $self->writer->startTag('metadata');
202 0 0         for my $meta ( @{ $metadata || [] } ) {
  0            
203 0 0 0       next unless $meta->{'name'} && $meta->{'content'};
204              
205 0           my $content = $meta->{'content'};
206              
207 0 0         if( ref $content eq 'ARRAY' ) {
208 0 0         $content = join ';', @{ $content || [] };
  0            
209             }
210              
211 0           my %attributes = (
212             'name' => $meta->{'name'},
213             'content' => $content,
214             );
215              
216 0           $self->writer->dataElement( 'meta', '', %attributes );
217             }
218              
219 0           $self->writer->endTag('metadata');
220             }
221              
222             #receives a string representing a datetime and returns its RFC822 representation
223             sub _to_RFC822_date {
224 0     0     my ( $self, $value ) = @_;
225              
226 0           my $epoch = Date::Parse::str2time($value);
227              
228 0 0         unless ($epoch) {
229 0           carp("Unknown date format received");
230 0           return;
231             }
232              
233 0           my $datetime = DateTime->from_epoch(
234             'epoch' => $epoch,
235             'time_zone' => 'local',
236             );
237              
238 0           return $datetime->strftime('%a, %d %b %Y %H:%M:%S %z');
239             }
240              
241             1;
242              
243              
244             =head1 NAME
245              
246             XML::GSA::Group - A class that represents a group in gsa xml
247              
248             =head1 VERSION
249              
250             Version 0.07
251              
252             =cut
253              
254             our $VERSION = '0.07';
255              
256             =head1 METHODS
257              
258             =head2 new( C<$params> )
259              
260             Create a new XML::GSA::Group object:
261              
262             my $gsa = XML::GSA->new('records' => [], 'action' => 'add');
263              
264             Arguments of this method are an anonymous hash of parameters:
265              
266             =head3 records
267              
268             An arrayref of hashrefs where each of the hashrefs represents a gsa xml record
269              
270             =head3 action
271              
272             A string that can be 'add' or 'delete' that defines what this group will do to the gsa indexer
273              
274             =cut
275              
276             =head2 create( C<$feed> )
277              
278             Receives an instance of XML::GSA so that when creating the group, one know to what feed will it belong. This is necessary because the type of feed influences the type of parameters acccepted by the group.
279              
280             =cut
281              
282             =head2 action
283              
284             Getter or the action attribute
285              
286              
287             =head2 xml
288              
289             Getter for the xml generated by the `create` method.
290              
291             =head2 to_string
292              
293             Getter for the xml generated by the `create` method.
294              
295             =head2 records
296              
297             Getter for the array of groups records added to this class
298              
299             =head2 writer
300              
301             Getter for the XML::Writer object used in this class to create the xml
302              
303             =cut
304              
305             =head1 AUTHOR
306              
307             Shemahmforash, C<< >>
308              
309             =head1 BUGS
310              
311             Please report any bugs or feature requests to C, or through
312             the web interface at L. I will be notified, and then you'll
313             automatically be notified of progress on your bug as I make changes.
314              
315              
316              
317              
318             =head1 SUPPORT
319              
320             You can find documentation for this module with the perldoc command.
321              
322             perldoc XML::GSA
323              
324              
325             You can also look for information at:
326              
327             =over 4
328              
329             =item * RT: CPAN's request tracker (report bugs here)
330              
331             L
332              
333             =item * AnnoCPAN: Annotated CPAN documentation
334              
335             L
336              
337             =item * CPAN Ratings
338              
339             L
340              
341             =item * Search CPAN
342              
343             L
344              
345             =item * Github Repository
346              
347             L
348              
349             =back
350              
351             =head1 LICENSE AND COPYRIGHT
352              
353             Copyright 2013-2014 Shemahmforash.
354              
355             This program is free software: you can redistribute it and/or modify
356             it under the terms of the GNU General Public License as published by
357             the Free Software Foundation, either version 3 of the License, or
358             (at your option) any later version.
359              
360             This program is distributed in the hope that it will be useful,
361             but WITHOUT ANY WARRANTY; without even the implied warranty of
362             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
363             GNU General Public License for more details.
364              
365             You should have received a copy of the GNU General Public License
366             along with this program. If not, see L.
367              
368              
369             =cut