From: Simon Cozens Date: Mon, 5 Apr 2004 22:16:18 +0000 (+0000) Subject: Introduction to Flox, beginnings of request chapter. X-Git-Tag: 2.10~247 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=d6437cf11ffb95f80143ea9af87e3bc972b0807e;p=maypole.git Introduction to Flox, beginnings of request chapter. git-svn-id: http://svn.maypole.perl.org/Maypole/trunk@115 48953598-375a-da11-a14b-00016c27c3ee --- diff --git a/doc/Flox.pod b/doc/Flox.pod index ee0a96a..b8d3d7a 100644 --- a/doc/Flox.pod +++ b/doc/Flox.pod @@ -1 +1,21 @@ -=head1 FlOx: A Social Networking Site +=head1 Flox: A Free Social Networking Site + +Friendster, Tribe, and now Google's Orkut - it seems like in early 2004, +everyone wanted to be a social networking site. At the time, I was too +busy to be a social networking site, as I was working on my own project +at the time, a web application server called Maypole. However, I +realised that if I could implement a social networking system using +Maypole, then Maypole could probably do anything. + +I'd already decided there was room for a free, open-source networking +site, and then Peter Sergeant came up with the hook - localizing it to +universities and societies, and tying in meet-ups with restaurant +bookings. I called it Flox, partially because it flocks people together +and partially because it's localised for my home town of Oxford and its +university. + +Flox is still in, uh, flux, but it does the essentials. In this chapter, +we're going to see how it was put together, and how the techniques shown +in the L chapter can help to create a sophisticated web +application. Of course, I didn't have this manual available at the time, +so it took a bit longer than it should have done... diff --git a/doc/Request.pod b/doc/Request.pod index 815ea1d..6af8278 100644 --- a/doc/Request.pod +++ b/doc/Request.pod @@ -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: Munge the contents of C< $r-Eparams > before jumping +to the original C routine. For instance, in this method, +we use a C 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 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: 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: + + +
+ Layla + Derek and the Dominos + Dm +
+ + ... + + ALayDmla Bb + CGot me on my Dmknees + ... + +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 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 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 module, this is as simple as putting the +following into F: + + [% + 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, out of your database. + +B: Fill the content and content-type yourself. + +Here's a subroutine which displays the C for either a specified +user or the currently logged in user. We set the C 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 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; + } + }