X-Git-Url: http://erislabs.net/gitweb/?p=libwww-opensearch-perl.git;a=blobdiff_plain;f=lib%2FWWW%2FOpenSearch%2FDescription.pm;h=0075e355ca2fbf6c99da6a534aa01037f717a11f;hp=6ed1e9a3d326b5ec6f78e50b6eb0b8d576b6fe31;hb=1fc70f0d6badbef9bb483990d761d1446d52cbb2;hpb=ec50391b25e981b1b9bae8e42e03c0fc9c218845 diff --git a/lib/WWW/OpenSearch/Description.pm b/lib/WWW/OpenSearch/Description.pm index 6ed1e9a..0075e35 100644 --- a/lib/WWW/OpenSearch/Description.pm +++ b/lib/WWW/OpenSearch/Description.pm @@ -1,245 +1,264 @@ -package WWW::OpenSearch::Description; - -use strict; -use warnings; - -use base qw( Class::Accessor::Fast ); - -use Carp; -use XML::LibXML; -use WWW::OpenSearch::Url; - -my @columns = qw( - AdultContent Contact Description Developer - Format Image LongName Query - SampleSearch ShortName SyndicationRight Tags +package WWW::OpenSearch::Description; + +use strict; +use warnings; + +use base qw( Class::Accessor::Fast ); + +use Carp; +use XML::LibXML; +use WWW::OpenSearch::Url; +use WWW::OpenSearch::Query; +use WWW::OpenSearch::Image; + +my @columns = qw( + AdultContent Contact Description Developer + Format Image LongName Query + SampleSearch ShortName SyndicationRight Tags Url Attribution InputEncoding OutputEncoding - Language -); - -__PACKAGE__->mk_accessors( qw( version ns ), map { lc } @columns ); - -=head1 NAME - -WWW::OpenSearch::Description - Encapsulate an OpenSearch Description -provided by an A9 OpenSearch compatible engine - -=head1 SYNOPSIS - - use WWW::OpenSearch; - - my $url = "http://bulkfeeds.net/opensearch.xml"; - my $engine = WWW::OpenSearch->new($url); - my $description = $engine->description; - - my $format = $description->Format; # or $description->format - my $longname = $description->LongName; # or $description->longname - -=head1 DESCRIPTION - -WWW::OpenSearch::Description is a module designed to encapsulate an -OpenSearch Description provided by an A9 OpenSearch compatible engine. -See http://opensearch.a9.com/spec/1.1/description/ for details. - -=head1 CONSTRUCTOR - -=head2 new( [ $xml ] ) - -Constructs a new instance of WWW::OpenSearch::Description. If scalar -parameter $xml is provided, data will be automatically loaded from it -using load( $xml ). - -=head1 METHODS - -=head2 load( $xml ) - + Language +); + +__PACKAGE__->mk_accessors( qw( version ns ), map { lc } @columns ); + +=head1 NAME + +WWW::OpenSearch::Description - Encapsulate an OpenSearch Description +provided by an A9 OpenSearch compatible engine + +=head1 SYNOPSIS + + use WWW::OpenSearch; + + my $url = "http://bulkfeeds.net/opensearch.xml"; + my $engine = WWW::OpenSearch->new($url); + my $description = $engine->description; + + my $format = $description->Format; # or $description->format + my $longname = $description->LongName; # or $description->longname + +=head1 DESCRIPTION + +WWW::OpenSearch::Description is a module designed to encapsulate an +OpenSearch Description provided by an A9 OpenSearch compatible engine. +See http://opensearch.a9.com/spec/1.1/description/ for details. + +=head1 CONSTRUCTOR + +=head2 new( [ $xml ] ) + +Constructs a new instance of WWW::OpenSearch::Description. If scalar +parameter $xml is provided, data will be automatically loaded from it +using load( $xml ). + +=head1 METHODS + +=head2 load( $xml ) + Loads description data by parsing provided argument using XML::LibXML. =head2 urls( ) -Return all of the urls associated with this description in an array. - -=head2 get_best_url( ) - -Attempts to retrieve the best URL associated with this description, based -on the following content types (from most preferred to least preferred): - -=over 4 - -=item * application/atom+xml - -=item * application/rss+xml - -=item * text/xml - -=back - -=head2 get_url_by_type( $type ) - -Retrieves the first WWW::OpenSearch::URL associated with this description -whose type is equal to $type. - -=head1 ACCESSORS - -=head2 version( ) - -=head2 ns( ) - -=head2 AdultContent( ) - -=head2 Contact( ) - -=head2 Description( ) - -=head2 Developer( ) - -=head2 Format( ) - -=head2 Image( ) - -=head2 LongName( ) - -=head2 Query( ) - -=head2 SampleSearch( ) - -=head2 ShortName( ) - -=head2 SyndicationRight( ) - -=head2 Tags( ) - -=head2 Url( ) - -=head1 AUTHOR - -=over 4 - -=item * Tatsuhiko Miyagawa Emiyagawa@bulknews.netE - -=item * Brian Cassidy Ebricas@cpan.orgE - -=back - -=head1 COPYRIGHT AND LICENSE - -Copyright 2006 by Tatsuhiko Miyagawa and Brian Cassidy - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut - -for( @columns ) { - no strict 'refs'; - my $col = lc; - *$_ = \&$col; -} - -sub new { - my $class = shift; - my $xml = shift; - - my $self = $class->SUPER::new; - - eval{ $self->load( $xml ); } if $xml; - if( $@ ) { - croak "Error while parsing Description XML: $@"; - } - - return $self; -} - -sub load { - my $self = shift; - my $xml = shift; - - my $parser = XML::LibXML->new; - my $doc = $parser->parse_string( $xml ); - my $element = $doc->documentElement; - my $nodename = $element->nodeName; - - croak "Node should be OpenSearchDescription: $nodename" if $nodename ne 'OpenSearchDescription'; - - my $ns = $element->getNamespace->value; - my $version; - if( $ns eq 'http://a9.com/-/spec/opensearch/1.1/' ) { - $self->ns( $ns ); - $version = '1.1'; - } - else { - $version = '1.0'; - } - $self->version( $version ); - - for my $column ( @columns ) { - my $node = $doc->documentElement->getChildrenByTagName( $column ) or next; - if( $column eq 'Url' ) { - if( $version eq '1.0' ) { - $self->Url( [ WWW::OpenSearch::Url->new( template => $node->string_value, type => 'application/rss+xml' ) ] ); - next; - } - - my @url; - for my $urlnode ( $node->get_nodelist ) { - my $type = $urlnode->getAttributeNode( 'type' )->value; - my $url = $urlnode->getAttributeNode( 'template' )->value; - $url =~ s/\?}/}/g; # optional - my $method = $urlnode->getAttributeNode( 'method' ); - $method = $method->value if $method; - - my %params; - for( $urlnode->getChildrenByTagName( 'Param' ) ) { - my $param = $_->getAttributeNode( 'name' )->value; +Return all of the urls associated with this description in an array. + +=head2 get_best_url( ) + +Attempts to retrieve the best URL associated with this description, based +on the following content types (from most preferred to least preferred): + +=over 4 + +=item * application/atom+xml + +=item * application/rss+xml + +=item * text/xml + +=back + +=head2 get_url_by_type( $type ) + +Retrieves the first WWW::OpenSearch::URL associated with this description +whose type is equal to $type. + +=head1 ACCESSORS + +=head2 version( ) + +=head2 ns( ) + +=head2 AdultContent( ) + +=head2 Contact( ) + +=head2 Description( ) + +=head2 Developer( ) + +=head2 Format( ) + +=head2 Image( ) + +=head2 LongName( ) + +=head2 Query( ) + +=head2 SampleSearch( ) + +=head2 ShortName( ) + +=head2 SyndicationRight( ) + +=head2 Tags( ) + +=head2 Url( ) + +=head1 AUTHOR + +=over 4 + +=item * Tatsuhiko Miyagawa Emiyagawa@bulknews.netE + +=item * Brian Cassidy Ebricas@cpan.orgE + +=back + +=head1 COPYRIGHT AND LICENSE + +Copyright 2007 by Tatsuhiko Miyagawa and Brian Cassidy + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +for( @columns ) { + no strict 'refs'; + my $col = lc; + *$_ = \&$col; +} + +sub new { + my $class = shift; + my $xml = shift; + + my $self = $class->SUPER::new; + + eval{ $self->load( $xml ); } if $xml; + if( $@ ) { + croak "Error while parsing Description XML: $@"; + } + + return $self; +} + +sub load { + my $self = shift; + my $xml = shift; + + my $parser = XML::LibXML->new; + my $doc = $parser->parse_string( $xml ); + my $element = $doc->documentElement; + my $nodename = $element->nodeName; + + croak "Node should be OpenSearchDescription: $nodename" if $nodename ne 'OpenSearchDescription'; + + my $ns = $element->getNamespace->value; + my $version; + if( $ns eq 'http://a9.com/-/spec/opensearchdescription/1.0/' ) { + $self->ns( 'http://a9.com/-/spec/opensearchrss/1.0/' ); + $version = '1.0'; + } + else { + $self->ns( $ns ); + ( $version ) = $ns =~ m{([^/]+)/?$}; + } + $self->version( $version ); + + for my $column ( @columns ) { + my $node = $doc->documentElement->getChildrenByTagName( $column ) or next; + if( $column eq 'Url' ) { + if( $version eq '1.0' ) { + $self->Url( [ WWW::OpenSearch::Url->new( template => $node->string_value, type => 'application/rss+xml', ns => $self->ns ) ] ); + next; + } + + my @url; + for my $urlnode ( $node->get_nodelist ) { + my $type = $urlnode->getAttributeNode( 'type' )->value; + my $url = $urlnode->getAttributeNode( 'template' )->value; + $url =~ s/\?}/}/g; # optional + my $method = $urlnode->getAttributeNode( 'method' ); + $method = $method->value if $method; + + my %params; + for( $urlnode->getChildrenByTagName( 'Param' ) ) { + my $param = $_->getAttributeNode( 'name' )->value; my $value = $_->getAttributeNode( 'value' )->value; - $value =~ s/\?}/}/g; # optional - $params{ $param } = $value; - } - - push @url, WWW::OpenSearch::Url->new( template => $url, type => $type, method => $method, params => \%params ); - } - $self->Url( \@url ); - } - elsif( $version eq '1.1' and $column eq 'Query' ) { - my $query = ( $node->get_nodelist )[ 0 ]; - next if $query->getAttributeNode( 'role' )->value eq 'example'; - $self->SampleSearch( $query->getAttributeNode( 'searchTerms' )->value ); - } - elsif( $version eq '1.0' and $column eq 'Format' ) { - $self->Format( $node->string_value ); - $self->ns( $self->Format ); - } - else { - $self->$column( $node->string_value ); - } - } -} - -sub get_best_url { - my $self = shift; - - return $self->get_url_by_type( 'application/atom+xml' ) - || $self->get_url_by_type( 'application/rss+xml' ) - || $self->get_url_by_type( 'text/xml' ) - || $self->url->[ 0 ]; -} - -sub get_url_by_type { - my $self = shift; - my $type = shift; - - my $template; - for( $self->urls ) { - $template = $_ if $_->type eq $type; - last; - }; - - return $template; -} + $value =~ s/\?}/}/g; # optional + $params{ $param } = $value; + } + + push @url, WWW::OpenSearch::Url->new( template => $url, type => $type, method => $method, params => \%params, ns => $self->ns ); + } + $self->Url( \@url ); + } + elsif( $version eq '1.1' and $column eq 'Query' ) { + my $queries = $self->query || []; + + for my $node ( $node->get_nodelist ) { + my $query = WWW::OpenSearch::Query->new( { + map { $_ => $node->getAttributeNode( $_ )->value } qw( role searchTerms ) + } ); + + push @$queries, $query; + } + + $self->query( $queries ); + } + elsif( $version eq '1.1' and $column eq 'Image' ) { + my $images = $self->image || []; + + for my $node ( $node->get_nodelist ) { + my $image = WWW::OpenSearch::Image->new( { + ( map { my $attr = $node->getAttributeNode( $_ ); $attr ? ($_ => $attr->value) : () } qw( height width type ) ), + url => $node->string_value + } ); + + push @$images, $image; + } + + $self->image( $images ); + } + else { + $self->$column( $node->string_value ); + } + } +} + +sub get_best_url { + my $self = shift; + + return $self->get_url_by_type( 'application/atom+xml' ) + || $self->get_url_by_type( 'application/rss+xml' ) + || $self->get_url_by_type( 'text/xml' ) + || $self->url->[ 0 ]; +} + +sub get_url_by_type { + my $self = shift; + my $type = shift; + + for( $self->urls ) { + return $_ if $_->type eq $type; + }; + + return; +} sub urls { my $self = shift; return @{ $self->url }; } - -1; + +1;