=================================================================== RCS file: /cvs/todotxt/Text-Todo-REST-API/lib/Text/Todo/REST/API.pm,v retrieving revision 1.9 retrieving revision 1.20 diff -u -r1.9 -r1.20 --- todotxt/Text-Todo-REST-API/lib/Text/Todo/REST/API.pm 2010/01/23 07:15:40 1.9 +++ todotxt/Text-Todo-REST-API/lib/Text/Todo/REST/API.pm 2010/04/30 00:04:29 1.20 @@ -1,15 +1,20 @@ package Text::Todo::REST::API; -# $AFresh1: API.pm,v 1.8 2010/01/19 03:18:34 andrew Exp $ +# $AFresh1: API.pm,v 1.19 2010/02/16 06:12:26 andrew Exp $ use warnings; use strict; use Carp; use Text::Todo; +use Text::Todo::REST::API::Response; +use Module::Pluggable + instantiate => 'new', + search_path => 'Text::Todo::REST::API::Actions', + sub_name => 'actions'; + use Class::Std::Utils; -use Digest::MD5 qw/ md5_hex /; use version; our $VERSION = qv('0.0.1'); @@ -61,22 +66,26 @@ } sub _parse_options { - my ( $self, $method, @args ) = @_; + my ( $self, $method, @options) = @_; my %options = ( method => lc $method, list => '', action => 'files', - args => [], + args => {}, + + suffix => $self->_suffix, + file_regex => $self->_file_regex, + format => $self->_format, ); - if (@args) { - if ( !ref $args[0] ) { - $options{path} = shift @args; + if (@options) { + if ( !ref $options[0] ) { + $options{path} = shift @options; } - if ( ref $args[0] eq 'HASH' ) { - my $opts = shift @args; + if ( ref $options[0] eq 'HASH' ) { + my $opts = shift @options; foreach my $o ( keys %{$opts} ) { $options{$o} = $opts->{$o}; } @@ -94,17 +103,21 @@ } } - if ($options{action} eq 'entry' && @{ $options{args} }) { - $options{entry} = shift @{ $options{args} }; - if (@{ $options{args} }) { - $options{action} = lc shift @{ $options{args} }; - } + if ( $options{action} eq 'entry' && @{ $options{extra} } ) { + $options{action} .= q{_} . lc shift @{ $options{extra} }; } + + push @{ $options{extra} }, @options; - push @{ $options{args} }, @args; + my $list = $self->_todo->file( $options{list} ); - $options{list} = defined $options{list} ? $options{list} : 'todo_file'; + my $suffix = $self->_suffix || q{}; + if ( $list !~ / \Q$suffix\E $/ixms ) { + $list .= $suffix; + } + $options{list} = $list; + if ( $options{format} ) { $format_of{ ident $self } = $options{format}; delete $options{format}; @@ -124,14 +137,19 @@ sub _handle_action { my ( $self, @args ) = @_; - my ($method, %options) = $self->_parse_options(@args); + my ( $method, %options ) = $self->_parse_options(@args); my $todo = $self->_todo; $todo->load( $options{list} ); - foreach my $class ( $self ) { - if ($class->can($method) ) { - return $class->$method( $todo, \%options ); + foreach my $class ( $self->actions ) { + if ( $class->can($method) ) { + return Text::Todo::REST::API::Response->new( + { type => $options{action}, + format => $self->_format, + data => $class->$method( $todo, \%options ), + } + ); } } @@ -142,9 +160,10 @@ my ( $self, $path ) = @_; my %options = ( - list => undef, action => undef, - args => [], + list => undef, + entry => undef, + extra => [], ); $path = defined $path ? $path : q{}; @@ -154,129 +173,33 @@ $options{format} = $1; } - ( $options{list}, $options{action}, @{ $options{args} } ) = split '/', - $path; + ( $options{list}, $options{action}, + @{ $options{extra} } ) = split '/', $path; - if ( $options{list} ) { - $options{action} ||= 'list'; - - my $suffix = $self->_suffix; - - if (( lc $options{list} ) eq 'files') { - $options{action} = lc $options{list}; - $options{list} = q{}; + if (!defined $options{action}) { + if ( $options{list} ) { + $options{action} = 'list'; } - elsif ($self->_todo->file( $options{list} )) { - $options{list} = $self->_todo->file( $options{list} ); - } - } - - if ( @{ $options{args} } && ( lc $options{args}[0] ) eq 'entry' ) { - $options{action} = lc shift @{ $options{args} }; - } - - return %options; - } - - sub GET { - my ( $self, @args ) = @_; - return $self->_handle_action( 'GET', @args ); - } - - sub get_entry { - my ( $self, $todo, $key ) = @_; - - if ( !$key ) { - return $self->fail("get_entry requires arguments"); - } - elsif ( ref $key eq 'ARRAY' ) { - my @entries; - foreach ( @{$key} ) { - push @entries, $self->get_entry($_); - } - return @entries; - } - elsif ( ref $key eq 'HASH' ) { - if (exists $key->{entry}) { - $key = $key->{entry}; - } else { - return $self->fail('get_entry requires key [entry]'); + $options{action} = 'files'; } } - my @list = $self->get_list($todo); + $options{action} = lc( $options{action} ); - my $entry; - if ( $key =~ /^[[:xdigit:]]{32}$/xms ) { - my $search = lc $key; - - ENTRY: foreach my $e (@list) { - if ( $search eq $e->{md5} ) { - $entry = $e; - last ENTRY; - } - } + if ($options{action} eq 'entry' + || $options{action} eq 'tags' + ) { + $options{ $options{action} } = shift @{ $options{extra} }; } - elsif ( $key =~ /^\d+$/xms ) { - $entry = $list[ $key - 1 ]; - } - if ( !$entry ) { - return $self->fail("Unable to find entry!"); - } - - return $entry; + return %options; } - sub get_list { - my ($self, $todo) = @_; - - my $line = 1; - return map ( { - line => $line++, - md5 => md5_hex( $_->text ), - text => $_->text, - }, - $todo->list ); - } - - sub get_files { - my ($self, $todo) = @_; - my $dir = $todo->file('todo_dir'); - - if ( !$dir ) { - return $self->fail('Unable to find todo_dir'); - } - - my $file_regex = $self->_file_regex; - - opendir my $dh, $dir or croak "Couldn't opendir: $!"; - my @files = grep {m/$file_regex/xms} readdir $dh; - closedir $dh; - - return @files; - } - - sub get_tags { - my ( $self, $todo, $tag ) = @_; - return $todo->listtag($tag); - } - - sub POST { - my ( $self, @args ) = @_; - return $self->_handle_action( 'POST', @args ); - } - - sub PUT { - my ( $self, @args ) = @_; - return $self->_handle_action( 'PUT', @args ); - } - - sub DELETE { - my ( $self, @args ) = @_; - return $self->_handle_action( 'DELETE', @args ); - } + sub GET { return shift->_handle_action( 'GET', @_ ) } + sub POST { return shift->_handle_action( 'POST', @_ ) } + sub PUT { return shift->_handle_action( 'PUT', @_ ) } + sub DELETE { return shift->_handle_action( 'DELETE', @_ ) } sub fail { my ( $self, @message ) = @_;