File Coverage

blib/lib/Net/Backpack.pm
Criterion Covered Total %
statement 24 396 6.0
branch 0 124 0.0
condition 1 36 2.7
subroutine 8 49 16.3
pod 40 40 100.0
total 73 645 11.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Net::Backpack - Perl extension for interfacing with Backpack.
4              
5             =head1 SYNOPSIS
6              
7             use strict; use warnings;
8             use Net::Backpack;
9              
10             my $bp = Net::Backpack(
11             user => $your_backpack_username,
12             token => $your_backpack_api_token,
13             ssl => $use_ssl
14             );
15              
16             # Fill out a Perl data structure with information about your Backspace pages.
17             my $std_pages = $bp->list_all_pages;
18              
19             # Alternatively get the same information in XML format
20             my $xml_pages = $bp->list_all_pages(xml => 1);
21              
22             # Create a new page
23             my $page = $bp->create_page(
24             title => 'A test page',
25             description => 'Created with the Backpack API'
26             );
27              
28             # Get the id of the new page
29             my $page_id = $page->{page}{id};
30              
31             # Get details of the new page (in XML format)
32             my $page_xml = $bp->show_page(id => $page->{page}{id});
33              
34             # Rename the page
35             $bp->update_title(
36             id => $page_id,
37             title => 'A new title'
38             );
39              
40             # Change the body
41             $bp->update_description(
42             id => $page_id,
43             description => 'Something new'
44             );
45              
46             # Remove the page
47             $bp->destroy_page(id => $page_id);
48              
49             =head1 DESCRIPTION
50              
51             Net::Backpack provides a thin Perl wrapper around the L.
52             Currently it only implements the parts of the API that manipulate Backpack pages.
53             Future releases will increase the coverage.
54              
55             =head2 Getting Started
56              
57             In order to use the Backpack API, you'll need to have a Backpack API token.And in
58             order to get one of those, you'll need a Backpack account.But then again, the API
59             will be pretty useless to you if you don't have a Backpack account to manipulate
60             with it.
61              
62             You can get a Backpack account from L.
63              
64             =head2 Backback API
65              
66             The Backpack API is based on XML over HTTP. You send an XML message over HTTP to
67             the Backpack server and the server sends a response to you which is also in XML.
68             The format of the various XML requests and responses are defined L.
69              
70             This module removes the need to deal with any XML.You create an object to talk to
71             the Backpack server and call methods on that object to manipulate your Backpage
72             pages. The values returned from Backpack are converted to Perl data structures
73             before being handed back to you (although it is also possible to get back the raw
74             XML).
75              
76             =head1 IMPORTANT NOTE
77              
78             C uses L to parse the data that is returned from
79             Backpack.From version 1.10 of C has changed.By default we now pass
80             the parameter C 1> to L. This will change the Perl
81             data structure returned by most calls.
82              
83             To get the old behaviour back, you can pass the parameter C 0>
84             to the C function.
85              
86             =cut
87              
88             package Net::Backpack;
89              
90 2     2   26408 use 5.006;
  2         4  
91 2     2   9 use strict;
  2         3  
  2         43  
92 2     2   7 use warnings;
  2         8  
  2         47  
93              
94 2     2   5 use Carp;
  2         2  
  2         119  
95 2     2   1083 use LWP::UserAgent;
  2         62288  
  2         50  
96 2     2   11 use HTTP::Request;
  2         3  
  2         35  
97 2     2   1371 use XML::Simple;
  2         11691  
  2         13  
98              
99             our $VERSION = '1.15';
100              
101             my %data = (
102             'list_all_pages' =>
103             {
104             url => '/ws/pages/all',
105             req => '
106             [S:token]
107             '
108             },
109             'create_page' =>
110             {
111             url => '/ws/pages/new',
112             req => '
113             [S:token]
114            
115             [P:title]
116             [P:description]
117            
118             '
119             },
120             'show_page' =>
121             {
122             url => '/ws/page/[P:id]',
123             req => '
124             [S:token]
125             '
126             },
127             'destroy_page' =>
128             {
129             url => '/ws/page/[P:id]/destroy',
130             req => '
131             [S:token]
132             '
133             },
134             'update_title' =>
135             {
136             url => '/ws/page/[P:id]/update_title',
137             req => '
138             [S:token]
139             [P:title]
140             '
141             },
142             update_body =>
143             {
144             url => '/ws/page/[P:id]/update_body',
145             req => '
146             [S:token]
147             [P:description]
148             '
149             },
150             'duplicate_page' =>
151             {
152             url => '/ws/page/[P:id]/duplicate',
153             req => '
154             [S:token]
155             '
156             },
157             'link_page' =>
158             {
159             url => '/ws/page/[P:to_page]/link',
160             req => '
161             [S:token]
162             [P:link_page]
163             '
164             },
165             'unlink_page' =>
166             {
167             url => '/ws/page/[P:from_page]/link',
168             req => '
169             [S:token]
170             [P:link_page]
171             '
172             },
173             'share_people' =>
174             {
175             url => '/ws/page/[P:id]/share',
176             req => '
177             [S:token]
178            
179             [P:people]
180            
181             '
182             },
183             'make_page_public' =>
184             {
185             url => '/ws/page/[P:id]/share',
186             req => '
187             [S:token]
188            
189             [P:public]
190            
191             '
192             },
193             'unshare_friend_page' =>
194             {
195             url => '/ws/page/[P:id]/unshare_friend_page',
196             req => '
197             [S:token]
198             '
199             },
200             'email_page' =>
201             {
202             url => '/ws/page/[P:id]/email',
203             req => '
204             [S:token]
205             '
206             },
207             'list_all_items' =>
208             {
209             url => '/ws/page/[P:page_id]/items/list',
210             req => '
211             [S:token]
212             '
213             },
214             'create_item' =>
215             {
216             url => '/ws/page/[P:page_id]/items/add',
217             req => '
218             [S:token]
219            
220             [P:item]
221            
222             '
223             },
224             'update_item' =>
225             {
226             url => '/ws/page/[P:page_id]/items/update/[P:id]',
227             req => '
228             [S:token]
229            
230             [P:item]
231            
232             '
233             },
234             'toggle_item' =>
235             {
236             url => '/ws/page/[P:page_id]/items/toggle/[P:id]',
237             req => '
238             [S:token]
239             '
240             },
241             'destroy_item' =>
242             {
243             url => '/ws/page/[P:page_id]/items/destroy/[P:id]',
244             req => '
245             [S:token]
246             '
247             },
248             'move_item' =>
249             {
250             url => '/ws/page/[P:page_id]/items/move/[P:id]',
251             req => '
252             [S:token]
253             [P:direction]
254             '
255             },
256             'list_all_notes' =>
257             {
258             url => '/ws/page/[P:page_id]/notes/list',
259             req => '
260             [S:token]
261             '
262             },
263             'create_note' =>
264             {
265             url => '/ws/page/[P:page_id]/notes/create',
266             req => '
267             [S:token]
268            
269             [P:title]
270             [P:body]
271            
272             '
273             },
274             'update_note' =>
275             {
276             url => '/ws/page/[P:page_id]/notes/update/[P:id]',
277             req => '
278             [S:token]
279            
280             [P:title]
281             [P:body]
282            
283             '
284             },
285             'destroy_note' =>
286             {
287             url => '/ws/page/[P:page_id]/notes/destroy/[P:id]',
288             req => '
289             [S:token]
290             '
291             },
292             'get_tag_pages' =>
293             {
294             url => '/ws/tags/[P:page_id]',
295             req => '
296             [S:token]
297             '
298             },
299             'set_page_tags' =>
300             {
301             url => '/ws/page/[P:page_id]/tags/tag',
302             req => '
303             [S:token]
304             [P:tags]
305             '
306             },
307             'upcoming_reminders' =>
308             {
309             url => '/ws/reminders',
310             req => '
311             [S:token]
312             '
313             },
314             'create_reminder' =>
315             {
316             url => '/ws/reminders/create',
317             req => '
318             [S:token]
319            
320             [P:content]
321             [P:remind_at]
322            
323             '
324             },
325             'update_reminder' =>
326             {
327             url => '/ws/reminders/update/[P:id]',
328             req => '
329             [S:token]
330            
331             [P:content]
332             [P:remind_at]
333            
334             '
335             },
336             'destroy_reminder' =>
337             {
338             url => '/ws/reminders/destroy/[P:id]',
339             req => '
340             [S:token]
341             '
342             },
343             'list_all_emails' =>
344             {
345             url => '/ws/page/[P:page_id]/emails/list',
346             req => '
347             [S:token]
348             '
349             },
350             'show_email' =>
351             {
352             url => '/ws/page/[P:page_id]/emails/show/[P:id]',
353             req => '
354             [S:token]
355             '
356             },
357             'destroy_email' =>
358             {
359             url => '/ws/page/[P:page_id]/emails/destroy/[P:id]',
360             req => '
361             [S:token]
362             '
363             },
364             'export' =>
365             {
366             url => '/ws/account/export',
367             req => '
368             [S:token]
369             '
370             },
371             'list_all_lists' =>
372             {
373             url => '/ws/page/[P:page_id]/lists/list',
374             req => '
375             [S:token]
376             '
377             },
378             'list_this_list' =>
379             {
380             url => '/ws/page/[P:page_id]/items/list?list_id=[P:list_id]',
381             req => '
382             [S:token]
383             '
384             },
385             'create_list' =>
386             {
387             url => '/ws/page/[P:page_id]/lists/add',
388             req => '
389             [S:token]
390             [P:title]
391             '
392             },
393             'update_list' =>
394             {
395             url => '/ws/page/[P:page_id]/lists/update/[P:list_id]',
396             req => '
397             [S:token]
398            
399             [P:title]
400            
401             '
402             },
403             'destroy_list' =>
404             {
405             url => '/ws/page/[P:page_id]/lists/destroy/[P:list_id]',
406             req => '
407             [S:token]
408             '
409             },
410             'create_list_item' =>
411             {
412             url => '/ws/page/[P:page_id]/items/add?list_id=[P:list_id]',
413             req => '
414             [S:token]
415            
416             [P:item]
417            
418             '
419             },
420             );
421              
422             =head1 METHODS
423              
424             =head2 new(%params)
425              
426             Creates a new Net::Backpack object. All communication with the Backpack server is
427             made through this object.
428              
429             Takes two mandatory arguments,your Backpack API token and your Backpack username.
430             Returns the new C object.
431              
432             There is also an optional parameter, forcearray. This controls the value of the
433             C parameter that is used by C. The default value is 1.
434              
435             If the C parameter is provided, then communication will take place over SSL.
436             This is required for Plus and Premium accounts.
437              
438             my $bp = Net::Backpack->new(
439             token => $token,
440             user => $user,
441             forcearray => 0,
442             ssl => 0
443             );
444              
445             =cut
446              
447             sub new {
448 3     3 1 732 my $class = shift;
449 3         11 my %params = @_;
450              
451 3         2 my $self;
452             $self->{token} = $params{token}
453 3   33     307 || croak "No Backpack API token passed Net::Backpack::new\n";
454             $self->{user} = $params{user}
455 0   0       || croak "No Backpack API user passed Net::Backpack::new\n";
456              
457 0 0         $self->{protocol} = $params{ssl} ? 'https' : 'http';
458 0   0       $self->{forcearray} = $params{forcearray} || 1;
459              
460 0           $self->{ua} = LWP::UserAgent->new;
461 0           $self->{ua}->env_proxy;
462 0           $self->{ua}->default_header('X-POST-DATA-FORMAT' => 'xml');
463              
464 0           $self->{base_url} = "$self->{protocol}://$self->{user}.backpackit.com";
465              
466 0           return bless $self, $class;
467             }
468              
469             =head2 list_all_pages(%params)
470              
471             Get a list of all of your Backpack pages.Returns a Perl data structure unless the
472             C parameter is true, in which case it returns the raw XML as returned by the
473             Backpack server.
474              
475             my $bp = Net::Backpack->new(
476             token => $token,
477             user => $user,
478             forcearray => 0,
479             ssl => 0
480             );
481              
482             $pages = $bp->list_all_pages(xml => 1);
483              
484             =cut
485              
486             sub list_all_pages {
487 0     0 1   my $self = shift;
488 0           my %params = @_;
489              
490 0           my $req_data = $data{list_all_pages};
491 0           my $url = $self->{base_url} . $req_data->{url};
492              
493 0           my $req = HTTP::Request->new('POST', $url);
494 0           $req->content($self->_expand($req_data->{req}, %params));
495              
496 0           return $self->_call(%params, req => $req);
497             }
498              
499             =head2 create_page(%param)
500              
501             Create a new Backpack page with the given title and (optional) description.Returns
502             a Perl data structure unless the C parameter is true,in which case it returns
503             the raw XML as returned by the Backpack server.
504              
505              
506             my $bp = Net::Backpack->new(
507             token => $token,
508             user => $user,
509             forcearray => 0,
510             ssl => 0
511             );
512              
513             my $page = $bp->create_page(
514             title => $title,
515             description => $desc,
516             xml => 1
517             );
518              
519             =cut
520              
521             sub create_page {
522 0     0 1   my $self = shift;
523 0           my %params = @_;
524              
525 0 0         croak 'No title for new page' unless $params{title};
526 0   0       $params{description} ||= '';
527              
528 0           my $req_data = $data{create_page};
529 0           my $url = $self->{base_url} . $req_data->{url};
530              
531 0           my $req = HTTP::Request->new(POST => $url);
532 0           $req->content($self->_expand($req_data->{req}, %params));
533              
534 0           return $self->_call(%params, req => $req);
535             }
536              
537             =head2 $rc = $bp->show_page(id => $id, [xml => 1]);
538              
539             Get details of the Backpack page with the given id. Returns a Perl data
540             structure unless the C parameter is true, in which case it returns the
541             raw XML as returned by the Backpack server.
542              
543             =cut
544              
545             sub show_page {
546 0     0 1   my $self = shift;
547 0           my %params = @_;
548              
549 0 0         croak 'No id' unless $params{id};
550              
551 0           my $req_data = $data{show_page};
552 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
553              
554 0           my $req = HTTP::Request->new(POST => $url);
555              
556 0           $req->content($self->_expand($req_data->{req}, %params));
557              
558 0           return $self->_call(%params, req => $req);
559             }
560              
561             =head2 $rc = $bp->destroy_page(id => $id, [xml => 1]);
562              
563             Delete the Backpack page with the given id. Returns a Perl data structure
564             unless the C parameter is true, in which case it returns the raw XML
565             as returned by the Backpack server.
566              
567             =cut
568              
569             sub destroy_page {
570 0     0 1   my $self = shift;
571 0           my %params = @_;
572              
573 0 0         croak 'No id' unless $params{id};
574              
575 0           my $req_data = $data{destroy_page};
576 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
577              
578 0           my $req = HTTP::Request->new(POST => $url);
579              
580 0           $req->content($self->_expand($req_data->{req}, %params));
581              
582 0           return $self->_call(%params, req => $req);
583             }
584              
585             =head2 $rc = $bp->update_title(id => $id, title => $title, [xml => 1]);
586              
587             Update the title of the given Backpack page. Returns a Perl data structure
588             unless the C parameter is true, in which case it returns the raw XML
589             as returned by the Backpack server.
590              
591             =cut
592              
593             sub update_title {
594 0     0 1   my $self = shift;
595 0           my %params = @_;
596              
597 0 0         croak 'No id' unless $params{id};
598 0 0         croak 'No title' unless $params{title};
599              
600 0           my $req_data = $data{update_title};
601 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
602              
603 0           my $req = HTTP::Request->new(POST => $url);
604              
605 0           $req->content($self->_expand($req_data->{req}, %params));
606              
607 0           return $self->_call(%params, req => $req);
608             }
609              
610             =head2 $rc = $bp->update_body(id => $id, description => $desc, [xml => 1]);
611              
612             Update the description of the given Backpack page. Returns a Perl data
613             structure unless the C parameter is true, in which case it returns the
614             raw XML as returned by the Backpack server.
615              
616             =cut
617              
618             sub update_body {
619 0     0 1   my $self = shift;
620 0           my %params = @_;
621              
622 0 0         croak 'No id' unless $params{id};
623 0 0         croak 'No description' unless defined $params{description};
624              
625 0           my $req_data = $data{update_body};
626 0           my $url = $self->{base_url} .$self->_expand($req_data->{url}, %params);
627 0           my $req = HTTP::Request->new(POST => $url);
628              
629 0           $req->content($self->_expand($req_data->{req}, %params));
630              
631 0           return $self->_call(%params, req => $req);
632             }
633              
634             =head2 $page = $bp->duplicate_page(id => $id, [xml => 1]);
635              
636             Create a duplicate of the given Backpack page. Returns a Perl data
637             structure unless the C parameter is true, in which case it returns the
638             raw XML as returned by the Backpack server.
639              
640             =cut
641              
642             sub duplicate_page {
643 0     0 1   my $self = shift;
644 0           my %params = @_;
645              
646 0 0         croak 'No id' unless $params{id};
647              
648 0           my $req_data = $data{duplicate_page};
649 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
650 0           my $req = HTTP::Request->new(POST => $url);
651              
652 0           $req->content($self->_expand($req_data->{req}, %params));
653              
654 0           return $self->_call(%params, req => $req);
655             }
656              
657             =head2 $rc = $bp->link_page(link_page => $id1, to_page => $id2, [xml => 1]);
658              
659             Link one Backpack page to another. Returns a Perl data structure unless the
660             C parameter is true, in which case it returns the raw XML as returned
661             by the Backpack server.
662              
663             =cut
664              
665             sub link_page {
666 0     0 1   my $self = shift;
667 0           my %params = @_;
668              
669 0 0 0       croak 'No id' unless $params{link_page} and $params{to_page};
670              
671 0           my $req_data = $data{link_page};
672 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
673 0           my $req = HTTP::Request->new(POST => $url);
674              
675 0           $req->content($self->_expand($req_data->{req}, %params));
676              
677 0           return $self->_call(%params, req => $req);
678             }
679              
680             =head2 $rc = $bp->unlink_page(link_page => $id1, from_page => $id2,
681             [xml => 1]);
682              
683             Unlink one Backpack page from another. Returns a Perl data structure unless
684             the C parameter is true, in which case it returns the raw XML as returned
685             by the Backpack server.
686              
687             =cut
688              
689             sub unlink_page {
690 0     0 1   my $self = shift;
691 0           my %params = @_;
692              
693 0 0 0       croak 'No id' unless $params{link_page} and $params{from_page};
694              
695 0           my $req_data = $data{unlink_page};
696 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
697 0           my $req = HTTP::Request->new(POST => $url);
698              
699 0           $req->content($self->_expand($req_data->{req}, %params));
700              
701 0           return $self->_call(%params, req => $req);
702             }
703              
704             =head2 $rc = $bp->share_page(id => $id, people => \@people,
705             [ xml => 1 ]);
706              
707             Share a given Backpack page with a list of other people. The parameter
708             'people' is a list of email addresses of the people you wish to share the
709             page with.
710              
711             =cut
712              
713             sub share_page {
714 0     0 1   my $self = shift;
715 0           my %params = @_;
716              
717 0 0         croak 'No id' unless $params{id};
718 0 0         croak 'No people' unless scalar @{$params{people}};
  0            
719              
720 0           $params{people} = join "\n", @{$params{people}};
  0            
721 0           my $req_data = $data{share_people};
722 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
723 0           my $req = HTTP::Request->new(POST => $url);
724              
725 0           $req->content($self->_expand($req_data->{req}, %params));
726              
727 0           return $self->_call(%params, req => $req);
728             }
729              
730             =head2 $rc = $bp->make_page_public(id => $id, public => $public,
731             [ xml => 1 ]);
732              
733             Make a given Backpage page public or private. The parameter 'public' is
734             a boolean flag indicating whether the page should be made public or
735             private
736              
737             =cut
738              
739             sub make_page_public {
740 0     0 1   my $self = shift;
741 0           my %params = @_;
742              
743 0 0         croak 'No id' unless $params{id};
744 0 0         croak 'No public flag' unless exists $params{public};
745              
746 0           $params{public} = !!$params{public};
747 0           my $req_data = $data{make_page_public};
748 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
749 0           my $req = HTTP::Request->new(POST => $url);
750              
751 0           $req->content($self->_expand($req_data->{req}, %params));
752              
753 0           return $self->_call(%params, req => $req);
754             }
755              
756             =head2 $rc = $bp->unshare_friend_page(id => $id, [ xml => 1 ]);
757              
758             Unshare yourself from a friend's page.
759              
760             =cut
761              
762             sub unshare_friend_page {
763 0     0 1   my $self = shift;
764 0           my %params = @_;
765              
766 0 0         croak 'No id' unless $params{id};
767              
768 0           my $req_data = $data{unshare_friend_page};
769 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
770 0           my $req = HTTP::Request->new(POST => $url);
771              
772 0           $req->content($self->_expand($req_data->{req}, %params));
773              
774 0           return $self->_call(%params, req => $req);
775             }
776              
777              
778             =head2 $rc = $bp->email_page(id => $id, [ xml => 1 ]);
779              
780             Email a page to yourself.
781              
782             =cut
783              
784             sub email_page {
785 0     0 1   my $self = shift;
786 0           my %params = @_;
787              
788 0 0         croak 'No id' unless $params{id};
789              
790 0           my $req_data = $data{email_page};
791 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
792 0           my $req = HTTP::Request->new(POST => $url);
793              
794 0           $req->content($self->_expand($req_data->{req}, %params));
795              
796 0           return $self->_call(%params, req => $req);
797             }
798              
799             =head2 $items = $bp->list_all_items(page_id => $page_id, [xml => 1]);
800              
801             Get a list of all of your Backpack checklist items. Returns a Perl data structure
802             unless the C parameter is true, in which case it returns the raw
803             XML as returned by the Backpack server.
804              
805             =cut
806              
807             sub list_all_items {
808 0     0 1   my $self = shift;
809 0           my %params = @_;
810              
811 0 0         croak 'No id' unless $params{page_id};
812              
813 0           my $req_data = $data{list_all_items};
814 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
815              
816 0           my $req = HTTP::Request->new('POST', $url);
817 0           $req->content($self->_expand($req_data->{req}, %params));
818              
819 0           return $self->_call(%params, req => $req);
820             }
821              
822             =head2 $item = $bp->create_item(page_id => $page_id, item => $item, [xml => 1]);
823              
824             Create a Backpack checklist item given a page id and some item content.
825             Returns a Perl data structure unless the C parameter is true, in which case
826             it returns the raw XML as returned by the Backpack server.
827              
828             =cut
829              
830             sub create_item {
831 0     0 1   my $self = shift;
832 0           my %params = @_;
833              
834 0 0         croak 'No page id' unless $params{page_id};
835 0 0         croak 'No item content' unless $params{item};
836              
837 0           my $req_data = $data{create_item};
838 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
839              
840 0           my $req = HTTP::Request->new('POST', $url);
841 0           $req->content($self->_expand($req_data->{req}, %params));
842              
843 0           return $self->_call(%params, req => $req);
844             }
845              
846             =head2 $item = $bp->update_item(page_id => $page_id, item => $item, [xml => 1]
847             id => $item_id);
848              
849             Updates a Backpack checklist item given a page id, item id, and new content.
850             Returns a Perl data structure unless the C parameter is true, in which
851             case it returns the raw XML as returned by the Backpack server.
852              
853             =cut
854              
855             sub update_item {
856 0     0 1   my $self = shift;
857 0           my %params = @_;
858              
859 0 0         croak 'No page id' unless $params{page_id};
860 0 0         croak 'No item id' unless $params{id};
861 0 0         croak 'No item content' unless $params{item};
862              
863 0           my $req_data = $data{update_item};
864 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
865              
866 0           my $req = HTTP::Request->new('POST', $url);
867 0           $req->content($self->_expand($req_data->{req}, %params));
868              
869 0           return $self->_call(%params, req => $req);
870             }
871              
872             =head2 $response = $bp->toggle_item(page_id => $page_id, id => $item_id,
873             [xml => 1]);
874              
875             Toggles a Backpack checklist item given a page id and an item id.
876             Returns a Perl data structure unless the C parameter is true, in which
877             case it returns the raw XML as returned by the Backpack server.
878              
879             =cut
880              
881             sub toggle_item {
882 0     0 1   my $self = shift;
883 0           my %params = @_;
884              
885 0 0         croak 'No page id' unless $params{page_id};
886 0 0         croak 'No item id' unless $params{id};
887              
888 0           my $req_data = $data{toggle_item};
889 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
890              
891 0           my $req = HTTP::Request->new('POST', $url);
892 0           $req->content($self->_expand($req_data->{req}, %params));
893              
894 0           return $self->_call(%params, req => $req);
895             }
896              
897             =head2 $response = $bp->destroy_item(page_id => $page_id, id => $item_id,
898             [xml => 1]);
899              
900             Destroys a Backpack checklist item given a page id and an item id.
901             Returns a Perl data structure unless the C parameter is true, in which
902             case it returns the raw XML as returned by the Backpack server.
903              
904             =cut
905              
906             sub destroy_item {
907 0     0 1   my $self = shift;
908 0           my %params = @_;
909              
910 0 0         croak 'No page id' unless $params{page_id};
911 0 0         croak 'No item id' unless $params{id};
912              
913 0           my $req_data = $data{destroy_item};
914 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
915              
916 0           my $req = HTTP::Request->new('POST', $url);
917 0           $req->content($self->_expand($req_data->{req}, %params));
918              
919 0           return $self->_call(%params, req => $req);
920             }
921              
922             =head2 $response = $bp->move_item(page_id => $page_id, id => $item_id,
923             direction => $direction, [xml => 1]);
924              
925             Modifies the location in the list of a Backpack checklist item. Requires a
926             page id, a direction and an item id. Valid values for direction are
927             "move_lower", "move_higher", "move_to_top", and "move_to_bottom". Returns a
928             Perl data structure unless the C parameter is true, in which case it
929             returns the raw XML as returned by the Backpack server.
930              
931             =cut
932              
933             sub move_item {
934 0     0 1   my $self = shift;
935 0           my %params = @_;
936              
937 0 0         croak 'No page id' unless $params{page_id};
938 0 0         croak 'No item id' unless $params{id};
939 0 0 0       unless (exists $params{direction} &&
940             $params{direction} =~ /move_(lower|higher|to_top|to_bottom)/) {
941 0           croak 'No direction specified';
942             }
943              
944 0           my $req_data = $data{move_item};
945 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
946             #print "url : $url\n";
947             #sleep 2;
948 0           my $req = HTTP::Request->new('POST', $url);
949 0           $req->content($self->_expand($req_data->{req}, %params));
950              
951 0           return $self->_call(%params, req => $req);
952             }
953              
954             =head2 $notes = $bp->list_all_notes(page_id => $page_id, [xml => 1]);
955              
956             Get a list of all of your Backpack notes. Returns a Perl data structure
957             unless the C parameter is true, in which case it returns the raw
958             XML as returned by the Backpack server.
959              
960             =cut
961              
962             sub list_all_notes {
963 0     0 1   my $self = shift;
964 0           my %params = @_;
965              
966 0 0         croak 'No id' unless $params{page_id};
967              
968 0           my $req_data = $data{list_all_notes};
969 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
970              
971 0           my $req = HTTP::Request->new('POST', $url);
972 0           $req->content($self->_expand($req_data->{req}, %params));
973              
974 0           return $self->_call(%params, req => $req);
975             }
976              
977             =head2 $note = $bp->create_note(page_id => $page_id, title => $title,
978             body => $body, [xml => 1]);
979              
980             Create a Backpack note given a page id and some content. Title is required,
981             body is optional. Returns a Perl data structure unless the C parameter
982             is true, in which case it returns the raw XML as returned by the Backpack
983             server.
984              
985             =cut
986              
987             sub create_note {
988 0     0 1   my $self = shift;
989 0           my %params = @_;
990              
991 0 0         croak 'No page id' unless $params{page_id};
992 0 0         croak 'No note title' unless $params{title};
993              
994 0   0       $params{body} ||= "";
995              
996 0           my $req_data = $data{create_note};
997 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
998              
999 0           print "url: $url\n";
1000              
1001 0           my $req = HTTP::Request->new('POST', $url);
1002 0           $req->content($self->_expand($req_data->{req}, %params));
1003              
1004 0           return $self->_call(%params, req => $req);
1005             }
1006              
1007             =head2 $note = $bp->update_note(page_id => $page_id, id => $note_id, [xml => 1]
1008             title => $title, body => $body);
1009              
1010             Updates a Backpack note given a page id, note id, and new content.
1011             Returns a Perl data structure unless the C parameter is true, in which
1012             case it returns the raw XML as returned by the Backpack server.
1013              
1014             =cut
1015              
1016             sub update_note {
1017 0     0 1   my $self = shift;
1018 0           my %params = @_;
1019              
1020 0 0         croak 'No page id' unless $params{page_id};
1021 0 0         croak 'No note id' unless $params{id};
1022              
1023 0   0       $params{title} ||= "";
1024 0   0       $params{body} ||= "";
1025              
1026 0           my $req_data = $data{update_note};
1027 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1028              
1029 0           my $req = HTTP::Request->new('POST', $url);
1030 0           $req->content($self->_expand($req_data->{req}, %params));
1031              
1032 0           return $self->_call(%params, req => $req);
1033             }
1034              
1035             =head2 $response = $bp->destroy_note(page_id => $page_id, id => $note_id,
1036             [xml => 1]);
1037              
1038             Destroys a Backpack note given a page id and an note id.
1039             Returns a Perl data structure unless the C parameter is true, in which
1040             case it returns the raw XML as returned by the Backpack server.
1041              
1042             =cut
1043              
1044             sub destroy_note {
1045 0     0 1   my $self = shift;
1046 0           my %params = @_;
1047              
1048 0 0         croak 'No page id' unless $params{page_id};
1049 0 0         croak 'No note id' unless $params{id};
1050              
1051 0           my $req_data = $data{destroy_note};
1052 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1053              
1054 0           my $req = HTTP::Request->new('POST', $url);
1055 0           $req->content($self->_expand($req_data->{req}, %params));
1056              
1057 0           return $self->_call(%params, req => $req);
1058             }
1059              
1060             =head2 $pages = $bp->get_tag_pages(page_id => $id, [ xml => 1 ]);
1061              
1062             Retrieve all the pages associated with a particular tag id. Returns a Perl
1063             data structure unless the C parameter is true, in which case it returns
1064             the raw XML as returned by the Backpack server.
1065              
1066             =cut
1067              
1068             sub get_tag_pages {
1069 0     0 1   my $self = shift;
1070 0           my %params = @_;
1071              
1072 0 0         croak 'No page id' unless $params{page_id};
1073              
1074 0           my $req_data = $data{get_tag_pages};
1075 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1076 0           my $req = HTTP::Request->new(POST => $url);
1077              
1078 0           $req->content($self->_expand($req_data->{req}, %params));
1079              
1080 0           return $self->_call(%params, req => $req);
1081             }
1082              
1083             =head2 $response = $bp->set_page_tags(page_id => $id, tags => \@tags,
1084             [ xml => 1 ]);
1085              
1086             Set the tags for a given Backpack page. This method overwrites all tags for
1087             the page. An empty set of tags serves to remove all the tags for the page.
1088             Returns a Perl data structure unless the C parameter is true, in which
1089             case it returns the raw XML as returned by the Backpack server.
1090              
1091             This is currently returning true, and though it seems to create and submit a
1092             valid request, the tags are not being updated.
1093              
1094             =cut
1095              
1096             sub set_page_tags {
1097 0     0 1   my $self = shift;
1098 0           my %params = @_;
1099              
1100 0 0         croak 'No page id' unless $params{page_id};
1101              
1102 0           $params{tags} = join "\n", map { '"'.$_.'"' } @{$params{tags}};
  0            
  0            
1103 0           my $req_data = $data{set_page_tags};
1104              
1105 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1106              
1107             # print $url.$self->_expand($req_data->{req}, %params);
1108              
1109 0           my $req = HTTP::Request->new(POST => $url);
1110              
1111 0           $req->content($self->_expand($req_data->{req}, %params));
1112              
1113 0           return $self->_call(%params, req => $req);
1114             }
1115              
1116             =head2 $reminders = $bp->upcoming_reminders([ xml => 1 ]);
1117              
1118             Gets the upcoming Backpack reminders for an account, in the time zone
1119             specified per the account's settings.
1120             Returns a Perl data structure unless the C parameter is true, in which
1121             case it returns the raw XML as returned by the Backpack server.
1122              
1123             =cut
1124              
1125             sub upcoming_reminders {
1126 0     0 1   my $self = shift;
1127 0           my %params = @_;
1128              
1129 0           my $req_data = $data{upcoming_reminders};
1130              
1131 0           my $url = $self->{base_url} . $self->_expand($req_data->{url});
1132 0           my $req = HTTP::Request->new(POST => $url);
1133              
1134 0           $req->content($self->_expand($req_data->{req}, %params));
1135              
1136 0           return $self->_call(%params, req => $req);
1137             }
1138              
1139             =head2 $reminder = $bp->create_reminder(content => $reminder, [xml => 1],
1140             [remind_at => $remind_at]);
1141              
1142             Create a Backpack reminder given some reminder content. The content
1143             takes fuzzy date/times like "+30 Do foo and bar" to set the reminder for 30
1144             minutes from now. Optionally, specify a date in a relatively parseable date
1145             format and use the remind_at parameter instead.
1146             Returns a Perl data structure unless the C parameter is true, in which
1147             case it returns the raw XML as returned by the Backpack server.
1148              
1149             =cut
1150              
1151             sub create_reminder {
1152 0     0 1   my $self = shift;
1153 0           my %params = @_;
1154              
1155 0 0         croak 'No reminder content' unless $params{content};
1156              
1157 0   0       $params{remind_at} ||= "";
1158              
1159 0           my $req_data = $data{create_reminder};
1160 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1161              
1162 0           my $req = HTTP::Request->new('POST', $url);
1163 0           $req->content($self->_expand($req_data->{req}, %params));
1164              
1165 0           return $self->_call(%params, req => $req);
1166             }
1167              
1168             =head2 $reminder = $bp->update_reminder(id => $reminder_id,
1169             [content => $reminder], [xml => 1],
1170             [remind_at => $remind_at);
1171              
1172             Update a Backpack reminder given a reminder id. The content takes fuzzy
1173             date/times like "+30 Do foo and bar" to set the reminder for 30 minutes
1174             from now. Optionally, specify a date in a relatively parseable date format
1175             and use the remind_at parameter instead.
1176             Returns a Perl data structure unless the C parameter is true, in which
1177             case it returns the raw XML as returned by the Backpack server.
1178              
1179             =cut
1180              
1181             sub update_reminder {
1182 0     0 1   my $self = shift;
1183 0           my %params = @_;
1184              
1185 0 0         croak 'No reminder id' unless $params{id};
1186 0 0 0       unless (exists $params{content} && exists $params{remind_at}) {
1187 0           my $reminders = $self->upcoming_reminders();
1188             $params{content} ||=
1189 0   0       $reminders->{reminders}{reminder}{$params{id}}{content};
1190             $params{remind_at} ||=
1191 0   0       $reminders->{reminders}{reminder}{$params{id}}{remind_at};
1192             }
1193              
1194 0           my $req_data = $data{update_reminder};
1195 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1196              
1197 0           my $req = HTTP::Request->new('POST', $url);
1198 0           $req->content($self->_expand($req_data->{req}, %params));
1199              
1200 0           return $self->_call(%params, req => $req);
1201             }
1202              
1203             =head2 $response = $bp->destroy_reminder( id => $reminder_id, [xml => 1]);
1204              
1205             Destroys a Backpack reminder given a reminder id.
1206             Returns a Perl data structure unless the C parameter is true, in which
1207             case it returns the raw XML as returned by the Backpack server.
1208              
1209             =cut
1210              
1211             sub destroy_reminder {
1212 0     0 1   my $self = shift;
1213 0           my %params = @_;
1214              
1215 0 0         croak 'No reminder id' unless $params{id};
1216              
1217 0           my $req_data = $data{destroy_reminder};
1218 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1219              
1220 0           my $req = HTTP::Request->new('POST', $url);
1221 0           $req->content($self->_expand($req_data->{req}, %params));
1222              
1223 0           return $self->_call(%params, req => $req);
1224             }
1225              
1226             =head2 $emails = $bp->list_all_emails(page_id => $page_id, [xml => 1]);
1227              
1228             Get a list of all of your Backpack email items for a page. Returns a Perl
1229             data structure unless the C parameter is true, in which case it returns
1230             the raw XML as returned by the Backpack server.
1231              
1232             =cut
1233              
1234             sub list_all_emails {
1235 0     0 1   my $self = shift;
1236 0           my %params = @_;
1237              
1238 0 0         croak 'No id' unless $params{page_id};
1239              
1240 0           my $req_data = $data{list_all_emails};
1241 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1242              
1243 0           my $req = HTTP::Request->new('POST', $url);
1244 0           $req->content($self->_expand($req_data->{req}, %params));
1245              
1246 0           return $self->_call(%params, req => $req);
1247             }
1248              
1249             =head2 $email = $bp->show_email(page_id => $page_id, id => $reminder_id,
1250             [xml => 1]);
1251              
1252             Returns a Backpack email item given a page id and an email id.
1253             Returns a Perl data structure unless the C parameter is true, in which
1254             case it returns the raw XML as returned by the Backpack server.
1255              
1256             =cut
1257              
1258             sub show_email {
1259 0     0 1   my $self = shift;
1260 0           my %params = @_;
1261              
1262 0 0         croak 'No page id' unless $params{page_id};
1263 0 0         croak 'No email id' unless $params{id};
1264              
1265 0           my $req_data = $data{show_email};
1266 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1267              
1268 0           my $req = HTTP::Request->new('POST', $url);
1269 0           $req->content($self->_expand($req_data->{req}, %params));
1270              
1271 0           return $self->_call(%params, req => $req);
1272             }
1273              
1274             =head2 $response = $bp->destroy_email(page_id => $page_id, id => $reminder_id,
1275             [xml => 1]);
1276              
1277             Destroys a Backpack email item for a page given a page id and an email id.
1278             Returns a Perl data structure unless the C parameter is true, in which
1279             case it returns the raw XML as returned by the Backpack server.
1280              
1281             =cut
1282              
1283             sub destroy_email {
1284 0     0 1   my $self = shift;
1285 0           my %params = @_;
1286              
1287 0 0         croak 'No page id' unless $params{page_id};
1288 0 0         croak 'No email id' unless $params{id};
1289              
1290 0           my $req_data = $data{destroy_email};
1291 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1292              
1293 0           my $req = HTTP::Request->new('POST', $url);
1294 0           $req->content($self->_expand($req_data->{req}, %params));
1295              
1296 0           return $self->_call(%params, req => $req);
1297             }
1298              
1299             =head2 $exported_bp = $bp->export([xml => 1]);
1300              
1301             Exports an account's entire Backpack. Returns a Perl data structure
1302             unless the C parameter is true, in which case it returns the raw
1303             XML as returned by the Backpack server.
1304              
1305             =cut
1306              
1307             sub export {
1308 0     0 1   my $self = shift;
1309 0           my %params = @_;
1310              
1311 0           my $req_data = $data{export};
1312 0           my $url = $self->{base_url} . $req_data->{url};
1313              
1314 0           my $req = HTTP::Request->new('POST', $url);
1315 0           $req->content($self->_expand($req_data->{req}, %params));
1316              
1317 0           return $self->_call(%params, req => $req);
1318             }
1319              
1320             =head2 $lists = $bp->list_all_lists(page_id => $page_id, [xml => 1]);
1321              
1322             Get a list of *all* of your Backpack checklists for a specific page.
1323             Returns a Perl data structure unless the C parameter is true,
1324             in which case it returns the raw XML as returned by the Backpack server.
1325              
1326             =cut
1327              
1328             sub list_all_lists {
1329 0     0 1   my $self = shift;
1330 0           my %params = @_;
1331              
1332 0 0         croak 'No id' unless $params{page_id};
1333              
1334 0           my $req_data = $data{list_all_lists};
1335 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1336              
1337 0           my $req = HTTP::Request->new('POST', $url);
1338 0           $req->content($self->_expand($req_data->{req}, %params));
1339              
1340 0           return $self->_call(%params, req => $req);
1341             }
1342              
1343             =head2 $list = $bp->list_this_list(page_id => $page_id, list_id => $list_id, [xml => 1]);
1344              
1345             Get details of a specific list with the given list_id on a specific Backpack
1346             page with the given page_id. Returns a Perl data structure unless the C
1347             parameter is true, in which case it returns the raw XML as returned by the
1348             Backpack server.
1349              
1350             =cut
1351              
1352             sub list_this_list {
1353 0     0 1   my $self = shift;
1354 0           my %params = @_;
1355              
1356 0 0         croak 'No page id' unless $params{page_id};
1357 0 0         croak 'No list id' unless $params{list_id};
1358              
1359 0           my $req_data = $data{list_this_list};
1360 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1361              
1362 0           my $req = HTTP::Request->new('POST', $url);
1363 0           $req->content($self->_expand($req_data->{req}, %params));
1364              
1365 0           return $self->_call(%params, req => $req);
1366             }
1367              
1368             =head2 $list = $bp->create_list(page_id => $page_id, title => $title, [xml => 1]);
1369              
1370             Create a new Backpack checklist given a page id and a list title.
1371             Returns a Perl data structure unless the C parameter is true, in which
1372             case it returns the raw XML as returned by the Backpack server.
1373              
1374             =cut
1375              
1376             sub create_list {
1377 0     0 1   my $self = shift;
1378 0           my %params = @_;
1379              
1380 0 0         croak 'No page id' unless $params{page_id};
1381 0 0         croak 'No list title' unless $params{title};
1382              
1383 0           my $req_data = $data{create_list};
1384 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1385              
1386 0           my $req = HTTP::Request->new('POST', $url);
1387 0           $req->content($self->_expand($req_data->{req}, %params));
1388              
1389 0           return $self->_call(%params, req => $req);
1390             }
1391              
1392             =head2 $list = $bp->update_list(page_id => $page_id, list_id => $list_id, title => $title, [xml => 1]);
1393              
1394             Update the title of a specific list with the given list_id on a specific
1395             Backpack page with the given page_id. Returns a Perl data structure unless
1396             the C parameter is true, in which case it returns the raw XML as
1397             returned by the Backpack server.
1398              
1399             =cut
1400              
1401             sub update_list {
1402 0     0 1   my $self = shift;
1403 0           my %params = @_;
1404              
1405 0 0         croak 'No page id' unless $params{page_id};
1406 0 0         croak 'No list id' unless $params{list_id};
1407 0 0         croak 'No title' unless $params{title};
1408              
1409 0           my $req_data = $data{update_list};
1410 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1411              
1412 0           my $req = HTTP::Request->new('POST', $url);
1413 0           $req->content($self->_expand($req_data->{req}, %params));
1414              
1415 0           return $self->_call(%params, req => $req);
1416             }
1417              
1418             =head2 $list = $bp->destroy_list(page_id => $page_id, list_id => $list_id, [xml => 1]);
1419              
1420             Destroy a specific list with the given list_id on a specific Backpack page
1421             with the given page_id. Returns a Perl data structure unless the C
1422             parameter is true, in which case it returns the raw XML as returned by the
1423             Backpack server.
1424              
1425             =cut
1426              
1427             sub destroy_list {
1428 0     0 1   my $self = shift;
1429 0           my %params = @_;
1430              
1431 0 0         croak 'No page id' unless $params{page_id};
1432 0 0         croak 'No list id' unless $params{list_id};
1433              
1434 0           my $req_data = $data{destroy_list};
1435 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1436              
1437 0           my $req = HTTP::Request->new('POST', $url);
1438 0           $req->content($self->_expand($req_data->{req}, %params));
1439              
1440 0           return $self->_call(%params, req => $req);
1441             }
1442              
1443             =head2 $list = $bp->create_list_item(page_id => $page_id, list_id => $list_id, item = $item, [xml => 1]);
1444              
1445             Create an item on a specific list with the given list_id on a specific
1446             Backpack page with the given page_id. This differs from the usual
1447             "create_item" function in that you can specify which list on a page you want
1448             to add the item to. Returns a Perl data structure unless the C parameter
1449             is true, in which case it returns the raw XML as returned by the Backpack
1450             server.
1451              
1452             =cut
1453              
1454             sub create_list_item {
1455 0     0 1   my $self = shift;
1456 0           my %params = @_;
1457              
1458 0 0         croak 'No page id' unless $params{page_id};
1459 0 0         croak 'No list id' unless $params{list_id};
1460 0 0         croak 'No item content' unless $params{item};
1461              
1462 0           my $req_data = $data{create_list_item};
1463 0           my $url = $self->{base_url} . $self->_expand($req_data->{url}, %params);
1464              
1465 0           my $req = HTTP::Request->new('POST', $url);
1466 0           $req->content($self->_expand($req_data->{req}, %params));
1467              
1468 0           return $self->_call(%params, req => $req);
1469             }
1470              
1471              
1472             sub _call {
1473 0     0     my $self = shift;
1474 0           my %params = @_;
1475              
1476 0           my $resp = $self->{ua}->request($params{req});
1477 0           my $xml = $resp->content;
1478              
1479 0 0         if ($params{xml}) {
1480 0           return $xml;
1481             } else {
1482 0           my $data = XMLin($xml, ForceArray => $self->{forcearray});
1483 0           return $data;
1484             }
1485             }
1486              
1487             sub _expand {
1488 0     0     my $self = shift;
1489 0           my $string = shift;
1490 0           my %params = @_;
1491              
1492 0           $string =~ s/\[S:(\w+)]/$self->{$1}/g;
1493 0           $string =~ s/\[P:(\w+)]/$params{$1}/g;
1494              
1495 0           return $string;
1496             }
1497              
1498             =head1 AUTHOR
1499              
1500             Dave Cross Edave@dave@mag-sol.comE
1501              
1502             Please feel free to email me to tell me how you are using the module.
1503              
1504             Lots of stuff implemented by neshura when I was being too tardy!
1505              
1506             Currently maintained by Mohammad S Anwar, C<< >>
1507              
1508             =head1 REPOSITORY
1509              
1510             L
1511              
1512             =head1 BUGS
1513              
1514             Please report bugs by email to Ebug-Net-Backpack@rt.cpan.orgE.
1515              
1516             =head1 LICENSE AND COPYRIGHT
1517              
1518             Copyright (c) 2005, Dave Cross. All Rights Reserved.
1519              
1520             This script is free software; you can redistribute it and/or modify it under the
1521             same terms as Perl itself.
1522              
1523             =head1 SEE ALSO
1524              
1525             L, L
1526              
1527             =cut
1528              
1529             1;
1530             __END__