| Net-Google-DataAPI documentation | Contained in the Net-Google-DataAPI distribution. |
Net::Google::DataAPI - Base implementations for modules to negotiate with Google Data APIs
package MyService;
use Any::Moose;
use Net::Google::DataAPI;
with 'Net::Google::DataAPI::Role::Service';
# registering xmlns
has '+namespaces' => (
default => {
foobar => 'http://example.com/schema#foobar',
},
);
# registering feed url
feedurl myentry => (
entry_class => 'MyEntry',
# class name for the entry
default => 'http://example.com/myfeed',
);
sub _build_auth {
my ($self) = @_;
# .. authsub login things, this is optional.
# see Net::Google::Spreadsheets for typical implementation
my $authsub = Net::Google::DataAPI::Auth::AuthSub->new(
service => 'wise',
account_type => 'HOSTED_OR_GOOGLE',
);
$authsub->login('foo.bar@gmail.com', 'p4ssw0rd');
return $authsub;
}
1;
package MyEntry;
use Any::Moose;
use Net::Google::DataAPI;
with 'Net::Google::DataAPI::Role::Entry';
entry_has some_value => (
is => 'rw',
isa => 'Str',
# tagname
tagname => 'some_value',
# namespace
namespace => 'gd',
);
1;
Net::Google::DataAPI is base implementations for modules to negotiate with Google Data APIs.
define a feed url.
define a entry attribute.
You can set environment variable GOOGLE_DATAAPI_DEBUG=1 to see the raw requests and responses Net::Google::DataAPI sends and receives.
Nobuo Danjou <nobuo.danjou@gmail.com>
more pods.
Net::Google::DataAPI::Auth::AuthSub
Net::Google::DataAPI::Auth::ClientLogin::Multiple
Net::Google::DataAPI::Auth::OAuth
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Net-Google-DataAPI documentation | Contained in the Net-Google-DataAPI distribution. |
package Net::Google::DataAPI; use 5.008001; use Any::Moose; use Any::Moose '::Exporter'; use Carp; use Lingua::EN::Inflect::Number qw(to_PL); use XML::Atom; our $VERSION = '0.24'; any_moose('::Exporter')->setup_import_methods( as_is => ['feedurl', 'entry_has'], ); sub feedurl { my ($name, %args) = @_; my $class = caller; my $entry_class = delete $args{entry_class} or confess 'entry_class not specified'; my $can_add = delete $args{can_add}; $can_add = 1 unless defined $can_add; my $arg_builder = delete $args{arg_builder} || sub { my ($self, $args) = @_; return $args || {}; }; my $query_builder = delete $args{query_builder} || sub { my ($self, $args) = @_; return $args || {}; }; my $from_atom = delete $args{from_atom}; my $rel = delete $args{rel}; my $as_content_src = delete $args{as_content_src}; my $default = delete $args{default} || ''; my $attr_name = "${name}_feedurl"; my $class_meta = any_moose('::Meta::Class')->initialize($class); $class_meta->add_attribute( $attr_name => ( isa => 'Str', is => 'ro', lazy_build => 1, %args, ) ); $class_meta->add_method( "${name}_entryclass" => sub { $entry_class } ); $class_meta->add_method( "_build_$attr_name" => sub { my $self = shift; return $rel ? [ map { $_->href } grep { $_->rel eq $rel } $self->atom->link ]->[0] : $as_content_src ? $self->atom->content->elem->getAttribute('src') : $from_atom ? $from_atom->($self, $self->atom) : $default; } ); my $pl_name = to_PL($name); if ($can_add) { $class_meta->add_method( "add_$name" => sub { my ($self, $args) = @_; $self->$attr_name or confess "$attr_name is not set"; Any::Moose::load_class($entry_class); $args = $arg_builder->($self, $args); my %parent = $self->can('sync') ? ( container => $self ) : ( service => $self ); my $entry = $entry_class->new( { %parent, %$args } )->to_atom; my $atom = $self->service->post($self->$attr_name, $entry); $self->sync if $self->can('sync'); my $e = $entry_class->new( %parent, atom => $atom, ); return $e; } ); } $class_meta->add_method( $pl_name => sub { my ($self, $cond) = @_; $self->$attr_name or confess "$attr_name is not set"; Any::Moose::load_class($entry_class); $cond = $query_builder->($self, $cond); my $feed = $self->service->get_feed($self->$attr_name, $cond); return map { $entry_class->new( $self->can('sync') ? ( container => $self ) : ( service => $self ), atom => $_, ) } $feed->entries; } ); $class_meta->add_method( $name => sub { my ($self, $cond) = @_; return [ $self->$pl_name($cond) ]->[0]; } ); } sub entry_has { my ($name, %args) = @_; my $class = caller; my $class_meta = any_moose('::Meta::Class')->initialize($class); $class_meta->does_role('Net::Google::DataAPI::Role::Entry') or confess 'Net::Google::DataAPI::Role::Entry required to use entry_has'; my $tagname = delete $args{tagname}; my $ns = delete $args{ns}; my $from_atom = delete $args{from_atom}; my $to_atom = delete $args{to_atom}; my $default = delete $args{default} || ''; $default = $default->() if ref $default eq 'CODE'; $class_meta->add_attribute( $name => ( isa => 'Str', is => 'ro', $to_atom || $tagname ? ( trigger => sub {$_[0]->update } ) : (), $tagname || $from_atom ? ( lazy_build => 1, ) : (), %args, ) ); if ($tagname) { $class_meta->add_around_method_modifier( to_atom => sub { my ($next, $self) = @_; my $entry = $next->($self); my $ns_obj = $ns ? $self->ns($ns) : $entry->ns; $entry->set($ns_obj, $tagname, $self->$name) if $self->$name; return $entry; } ); $class_meta->add_method( "_build_$name" => sub { my $self = shift; $self->atom or return $default; my $ns_obj = $ns ? $self->ns($ns) : $self->atom->ns; return $self->atom->get($ns_obj, $tagname) || $default; } ); } if ($to_atom) { $class_meta->add_around_method_modifier( to_atom => sub { my ($next, $self) = @_; my $entry = $next->($self); $to_atom->($self, $entry) if $self->$name; return $entry; } ); } if ($from_atom) { $class_meta->add_method( "_build_$name" => sub { my $self = shift; $self->atom or return $default; return $from_atom->($self, $self->atom) || $default; } ); } } __PACKAGE__->meta->make_immutable; no Any::Moose; no Any::Moose '::Exporter'; 1; __END__