root/lang/perl/Catalyst-Controller-Atompub/tags/0.3.3/lib/Catalyst/Controller/Atompub/Base.pm @ 6742

Revision 6742, 6.7 kB (checked in by takemaru, 5 years ago)

lang/perl/Catalyst-Controller-Atompub: 0.3.3 released. fix many bugs, see Changes in details

Line 
1package Catalyst::Controller::Atompub::Base;
2
3use strict;
4use warnings;
5
6use Atompub::DateTime qw( datetime );
7use Atompub::MediaType qw( media_type );
8use Catalyst::Controller::Atompub;
9use HTTP::Status;
10use NEXT;
11
12use base qw( Catalyst::Controller );
13
14__PACKAGE__->mk_accessors( qw( info ) );
15
16sub new {
17    my $class = shift;
18    my $self = $class->NEXT::new(@_);
19    $self->info( Catalyst::Controller::Atompub::Info->instance( $self ) );
20    $self;
21}
22
23sub error {
24    my ( $self, $c, @args ) = @_;
25
26    return if ! is_success $c->res->status && $c->res->body;
27
28    my ( $status, $message )
29        = @args  > 1                                      ?  @args
30        : @args == 1 && $args[0] =~ /^([1-5]\d\d)\s*(.*)/ ? ( $1, $2 )
31        : @args == 1 && $args[0] =~ /^(.*)/               ? ( $2 )
32        :                                                   ();
33
34    $status ||= RC_INTERNAL_SERVER_ERROR;
35    $c->res->status( $status );
36
37    $message ||= status_message( $status );
38    my $report = "$status $message";
39
40    my $entry = XML::Atom::Entry->new;
41
42    my $link = XML::Atom::Link->new;
43    $link->rel('related'); # XXX via?
44    $link->href( $c->req->uri );
45    $entry->add_link( $link );
46
47    $entry->updated( datetime->w3c );
48    $entry->title( $report );
49    $entry->content( $report ); # XXX @type=text is better
50
51    $c->res->body( $entry->as_xml );
52    $c->res->content_type( media_type('entry') );
53
54    $c->log->error( $report );
55
56    return;
57}
58
59package Catalyst::Controller::Atompub::Info;
60
61use strict;
62use warnings;
63
64use Catalyst::Utils;
65use XML::Atom::Service;
66use base qw( Class::Accessor::Lvalue::Fast );
67
68__PACKAGE__->mk_accessors( qw( appclass ) );
69
70my $Info;
71
72sub instance {
73    my $class = shift;
74    $Info ||= bless { appclass => Catalyst::Utils::class2appclass( shift ) }, $class;
75    $Info;
76}
77
78sub get {
79    my ( $self, $c, $class ) = @_;
80    return unless $class = $self->_fullclass( $c, $class );
81    return unless $self->_is_collection( $c, $class );
82    $self->{info}{$class} ||= $self->_make_collection( $c, $class );
83}
84
85sub _fullclass {
86    my ( $self, $c, $class ) = @_;
87    $class = ref $class || $class || return;
88    my $appclass = $self->appclass;
89    return $class =~ /^$appclass\::/ ? $class : join( '::', $appclass, $class  );
90}
91
92sub _is_collection {
93    my ( $self, $c, $class ) = @_;
94    return UNIVERSAL::isa $class, 'Catalyst::Controller::Atompub::Collection';
95}
96
97sub _make_collection {
98    my ( $self, $c, $class ) = @_;
99
100    my $suffix = Catalyst::Utils::class2classsuffix( $class );
101
102    my $config = $c->config->{$suffix}{collection};
103
104    my $coll = XML::Atom::Collection->new;
105    $coll->href( $self->_make_href( $c, $class ) );
106    $coll->title( $config->{title} || $class =~ /Controller::(.+)/ );
107    $coll->accept( @{ $config->{accept} } ) if $config->{accept};
108
109    $coll->add_categories( $self->_make_categories( $c, $_ ) )
110        for @{ $config->{categories} };
111
112    return $coll;
113}
114
115sub _make_href {
116    my ( $self, $c, $class ) = @_;
117    return unless $class = $self->_fullclass( $c, $class );
118    return $c->req->base . $class->action_namespace( $c );
119}
120
121sub _make_categories {
122    my ( $self, $c, $config ) = @_;
123
124    my $cats = XML::Atom::Categories->new;
125    $cats->href( $config->{href} ) if $config->{href};
126    $cats->fixed( $config->{fixed} ) if $config->{fixed};
127    $cats->scheme( $config->{scheme} ) if $config->{scheme};
128
129    my @cat = map { my $cat = XML::Atom::Category->new;
130                    $cat->term( $_->{term} );
131                    $cat->scheme( $_->{scheme} ) if $_->{scheme};
132                    $cat->label( $_->{label} ) if $_->{label};
133                    $cat }
134                 @{ $config->{category} };
135    $cats->category( @cat );
136
137    return $cats;
138}
139
1401;
141__END__
142
143=head1 NAME
144
145Catalyst::Controller::Atompub::Base
146- A Catalyst controller for the Publishing Protocol
147
148
149=head1 DESCRIPTION
150
151L<Catalyst::Controller::Atompub::Base> is a base class of
152L<Catalyst::Controller::Atompub::Service> and
153L<Catalyst::Controller::Atompub::Collection>.
154
155
156=head1 METHODS
157
158=head2 $controller->new
159
160
161=head2 $controller->info
162
163An accessor for Collection information object.
164
165
166=head2 $controller->error( $c, [ $status, $message ] )
167
168Sets an Entry Document containing error message in $c->response->body,
169and returns C<undef>.
170
171See L<ERROR HANDLING>.
172
173
174=head1 ERROR HANDLING
175
176When something wrong happens, return with calling $controller->error method like:
177
178    sub foo {
179        my ( $controller ,$c ) = @_;
180
181        return $controller->error( $c, 404, "Entry does not exist" )
182            if is_something_wrong;
183    }
184
185Then, Atompub server responds with an Entry Document including error message:
186
187    HTTP/1.1 404 Not Found
188    Content-Type: application/atom+xml;type=entry
189
190    <?xml version="1.0" encoding="UTF-8"?>
191    <entry xmlns="http://www.w3.org/2005/Atom">
192     <updated>2007-01-01T00:00:00Z</updated>
193     <link rel="related"
194           href="http://localhost:3000/mycollection/entry_1.atom"/>
195     <title>404 Entry does not exist</title>
196     <content type="xhtml">
197      <div xmlns="http://www.w3.org/1999/xhtml">
198       404 Entry does not exist
199      </div>
200     </content>
201    </entry>
202
203This default behavior can be changed by overriding the C<error> method.
204
205
206=head1 SEE ALSO
207
208L<XML::Atom>
209L<XML::Atom::Service>
210L<Atompub>
211L<Catalyst::Controller::Atompub>
212
213
214=head1 AUTHOR
215
216Takeru INOUE  C<< <takeru.inoue _ gmail.com> >>
217
218
219=head1 LICENCE AND COPYRIGHT
220
221Copyright (c) 2007, Takeru INOUE C<< <takeru.inoue _ gmail.com> >>. All rights reserved.
222
223This module is free software; you can redistribute it and/or
224modify it under the same terms as Perl itself. See L<perlartistic>.
225
226
227=head1 DISCLAIMER OF WARRANTY
228
229BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
230FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
231OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
232PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
233EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
234WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
235ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
236YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
237NECESSARY SERVICING, REPAIR, OR CORRECTION.
238
239IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
240WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
241REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
242LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
243OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
244THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
245RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
246FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
247SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
248SUCH DAMAGES.
Note: See TracBrowser for help on using the browser.