]> git.decadent.org.uk Git - maypole.git/blobdiff - doc/Request.pod
Introduction to Flox, beginnings of request chapter.
[maypole.git] / doc / Request.pod
index 815ea1d439d71a535b33edf68eff5a1e81a43405..6af82784ba5263dc2e78a07a681251bf63e1bbd2 100644 (file)
@@ -1,9 +1,127 @@
 =head1 Maypole Request Hacking Cookbook
 
-=head2 Changing how params are parsed
+=head2 Frontend hacks
 
-=head2 Authentication
+=head3 Changing how params are parsed
 
-=head2 REST
+=head3 REST
 
-=head2 Filling Content Yourself
+=head2 Authentication hacks
+
+=head2 Creating and editing hacks
+
+=head3 Getting data from external sources
+
+You want to supplement the data received from a form with additional
+data from another source.
+
+B<Solution>: Munge the contents of C< $r-E<gt>params > before jumping
+to the original C<do_edit> routine. For instance, in this method,
+we use a C<Net::Amazon> object to fill in some fields of a database row based
+on an ISBN:
+
+    sub create_from_isbn :Exported {
+       my ($self, $r) = @_;
+       my $response = $ua->search(asin => $r->{params}{isbn});
+       my ($prop) = $response->properties;
+       # Rewrite the CGI parameters with the ones from Amazon
+       @{$r->{params}{qw(title publisher author year)} =            
+           ($prop->title,
+           $prop->publisher,
+           (join "/", $prop->authors()),
+           $prop->year());
+       # And jump to the usual edit/create routine
+       $self->do_edit($r);
+    }
+
+The request will carry on as though it were a normal C<do_edit> POST, but
+with the additional fields we have provided.
+
+=head2 Content display hacks
+
+=head3 XSLT
+
+Here's a hack I've used a number of times. You want to store structured
+data in a database and to abstract out its display.
+
+B<Solution>: You have your data as XML, because handling big chunks of
+XML is a solved problem. Build your database schema as usual around the
+important elements that you want to be able to search and browse on. For
+instance, I have an XML format for songs which has a header section of
+the key, title and so on, plus another section for the lyrics and
+chords:
+
+    <song>
+        <header>
+            <title>Layla</title>
+            <artist>Derek and the Dominos</artist>
+            <key>Dm</key>
+        </header>
+        <lyrics>
+          <verse>...</verse>
+          <chorus>
+            <line> <sup>A</sup>Lay<sup>Dm</sup>la <sup>Bb</sup> </line> 
+            <line> <sup>C</sup>Got me on my <sup>Dm</sup>knees </line> 
+            ...
+I store the title, artist and key in the database, as well as an "xml"
+field which contains the whole song as XML.
+
+To load the songs into the database, I can C<use> the driver class for
+my application, since that's a handy way of setting up the database classes
+we're going to need to use. Then the handy C<XML::TreeBuilder> will handle
+the XML parsing for us:
+
+    use Songbook;
+    use XML::TreeBuilder;
+    my $t = XML::TreeBuilder->new;
+    $t->parse_file("songs.xml");
+
+    for my $song ($t->find("song")) {
+        my ($key) = $song->find("key"); $key &&= $key->as_text;
+        my ($title) = $song->find("title"); $title = $title->as_text;
+        my ($artist) = $song->find("artist"); $artist = $artist->as_text;
+        my ($first_line) = $song->find("line");
+        $first_line = join "", grep { !ref } $first_line->content_list;
+        $first_line =~ s/[,\.\?!]\s*$//;
+        Songbook::Song->find_or_create({
+            title => $title,
+            first_line => $first_line,
+            song_key => Songbook::SongKey->find_or_create({name => $key}),
+            artist => Songbook::Artist->find_or_create({name => $artist}),
+            xml => $song->as_XML
+        });
+    }
+
+Now we need to set up the custom display for each song; thankfully, with
+the C<Template::Plugin::XSLT> module, this is as simple as putting the
+following into F<templates/song/view>:
+
+    [%
+        USE transform = XSLT("song.xsl");
+        song.xml | $transform
+    %]
+
+We essentially pipe the XML for the selected song through to an XSL
+transformation, and this will fill out all the HTML we need. Job done.
+
+=head3 Displaying pictures
+
+You want to serve a picture, or something else which doesn't have a
+content type of C<text/html>, out of your database.
+
+B<Solution>: Fill the content and content-type yourself.
+
+Here's a subroutine which displays the C<photo> for either a specified
+user or the currently logged in user. We set the C<output> slot of the
+Maypole request object: if this is done then the view class is not called
+upon to process a template, since we already have some output to display.
+We also set the C<content_type> using one from the database.
+
+    sub view_picture :Exported {
+        my ($self, $r) = @_;
+        my $user = $r->{objects}->[0] || $r->{user};
+        if ($r->{content_type} = $user->photo_type) {
+           $r->{output} = $user->photo;
+        }
+    }