[Catalyst-commits] r8711 -
trunk/examples/CatalystAdvent/root/2008/pen
dhoss at dev.catalyst.perl.org
dhoss at dev.catalyst.perl.org
Thu Dec 4 11:50:24 GMT 2008
Author: dhoss
Date: 2008-12-04 11:50:24 +0000 (Thu, 04 Dec 2008)
New Revision: 8711
Added:
trunk/examples/CatalystAdvent/root/2008/pen/AdventPhotoGallery.pod
Log:
added PhotoGallery advent calendar
Added: trunk/examples/CatalystAdvent/root/2008/pen/AdventPhotoGallery.pod
===================================================================
--- trunk/examples/CatalystAdvent/root/2008/pen/AdventPhotoGallery.pod (rev 0)
+++ trunk/examples/CatalystAdvent/root/2008/pen/AdventPhotoGallery.pod 2008-12-04 11:50:24 UTC (rev 8711)
@@ -0,0 +1,448 @@
+=head1 Super Simple Photo Gallery
+
+Let's create an extremely simple (but fun!) photogallery.
+First things first, we need to make sure we have everything.
+
+=head2 Our packing list:
+
+=over 12
+
+=item C<DBIx::Class::InflateColumn::FS>
+
+This will be used to store our file pointer in the database, write the image to the file system, and later, give us a
+Path::Class::File object to manipulate our images later on.
+
+=item C<Imager>
+
+The all and the everything for our image manipulation needs. If not installed already, make sure you install libjpeg so that
+JPEG files can be manipulated by Imager.
+
+
+=item C<MIME::Types>
+
+=item C<File::Mimeinfo>
+
+=item C<DateTime>
+
+=back
+
+Once you have installed these two things with great success, move on to the next step.
+
+=head1 Let's get started already!
+
+Ok. So here comes the fun stuff. We're going to assume you know how to create a Catalyst application skeleton, controllers, and models
+at the very least. If not, you have some documentation to read first :-)
+
+Create a controller in your application called Photos. Something like this:
+
+ perl script/*create.pl controller Photos
+
+Next, you'll want to set up a table called Photos in your RDBMS of choice. Here, we use MySQL because I've yet to learn Postgres.
+The necessary columns you will need are as follows:
+
+=over 12
+
+=item photoid
+
+type: INT
+size: 11
+null: no
+other: PRIMARY KEY auto_increment
+
+=item name
+
+type: VARCHAR
+size: 255
+null: no
+other:
+
+=item uploaded
+
+type: DATETIME
+size:
+null: no
+other:
+(If you so desire, include the InflateColumn::DateTime component to be able to manipulate this column as if it were
+a DateTime object)
+
+=item path
+
+type: TEXT
+size:
+null: no
+other:
+
+
+=item caption
+
+type: TEXT
+size:
+null: no
+other:
+
+
+=back
+
+So now you have your basic tables set up. Next, we need to generate our Schema files so DBIx::Class can interact with our
+database objects. I use this script to update/create my schema definition from the database.
+Copy/paste this script into a file called myapp_update_schema.pl (replace "myapp" with whatever you named this application) and stick it
+in the script/ directory of your application:
+
+ #!/usr/bin/perl
+
+
+ use FindBin;
+ use DBIx::Class::Schema::Loader qw| make_schema_at |;
+ make_schema_at(
+ "MyApp::Schema",
+ {
+ debug => 1,
+ use_namespaces => 0,
+ components => [qw/ InflateColumn::DateTime InflateColumn::FS PK::Auto/],
+ dump_directory => "$FindBin::Bin/../lib"
+ },
+ [ "dbi:mysql:myapp", "narf", "blarf" ]
+ );
+
+now run perl script/*update*. If there are no errors, proceed!
+
+=head2 Adding the InflateColumn::FS magic
+
+Open up Schema/Photos.pm. Since we used ::Loader, there will be a good portion of the file that you're not supposed to manually
+edit. This is marked by these lines:
+
+ # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-12-01 02:57:02
+ # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:A/YrsvGDAWKpDaGlJ3Dwqg
+
+You can safely modify anything below this though. Add these lines to the file:
+
+ use MyApp;
+ __PACKAGE__->add_columns(
+ "path",
+ {
+ data_type => 'TEXT',
+ is_fs_column => 1,
+ fs_column_path => MyApp->path_to( 'root', 'static', 'photos' ) . ""
+ }
+ );
+
+This tells DBIx::Class that the column "path" is now a Path::Class::File object and we can call Path::Class::File methods on it upon retrieval.
+
+Great! Now let's edit our controller.
+
+=head1 The Photos Controller
+
+Edit Controller/Photos.pm to match this file:
+
+ package MyApp::Controller::Photos;
+
+ use strict;
+ use warnings;
+ use parent 'Catalyst::Controller::HTML::FormFu';
+ use DateTime;
+ use Imager;
+ use MIME::Types;
+ use File::MimeInfo ();
+ use BoyosPlace;
+
+ __PACKAGE__->mk_accessors(qw(thumbnail_size));
+
+ =head1 NAME
+
+ MyApp::Controller::Photos - Catalyst Controller
+
+ =head1 DESCRIPTION
+
+ Catalyst Controller.
+
+ =head1 METHODS
+
+ =cut
+
+ =head2 index
+
+ display the photos
+
+ =cut
+
+ sub index : Path : Args(0) {
+ my ( $self, $c ) = @_;
+
+ my @photos = $c->model('DB::Photos')->all;
+
+ $c->stash->{photos} = \@photos;
+ $c->stash->{template} = "photos/index.tt2";
+
+ }
+
+ =head2 get_photos
+
+ set up photo stash
+
+ =cut
+
+ sub get_photos : Chained('/') PathPart('photo') CaptureArgs(1) {
+ my ( $self, $c, $photoid ) = @_;
+
+ my $photo = $c->model('DB::Photos')->find($photoid);
+
+ if ( $photo == undef ) {
+
+ $c->stash->{error_msg} = "No such photo.";
+
+ }
+ else {
+
+ $c->stash->{photo} = $photo;
+
+ }
+
+ }
+
+ =head2 add_photo
+
+ Add a photo to the database
+
+ =cut
+
+ sub add_photo : Path('/photo/add') FormConfig('photos/add.yml') {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{template} = "photos/add.tt2";
+ my $form = $c->stash->{form};
+ my $mime = MIME::Types->new;
+
+ ## comment out this block if you're not using the Authorization plugin
+ unless ( $c->check_user_roles('admin') ) {
+
+ $c->flash->{error_msg} =
+ "You don't have the proper permissions to add photos here";
+ $c->res->redirect( $c->uri_for('/photos') );
+
+ }
+
+ if ( $form->submitted_and_valid ) {
+
+ my $photo = $c->model('DB::Photos')->create(
+ {
+ name => $form->param('photo_name'),
+ path => $c->req->upload('photo')->fh,
+ caption => $form->param('caption'),
+ uploaded => DateTime->now,
+ mime => $mime->mimeTypeOf( $c->req->upload('photo')->basename ),
+ }
+ );
+
+ $c->stash->{status_msg} = "Successfully uploaded!";
+ $c->stash->{photo} = $photo;
+ $c->detach;
+
+ }
+
+ }
+
+ =head2 generate_thumbnail
+
+ this method generates a thumbnail of a
+ given image
+
+ =cut
+
+ sub generate_thumbnail : Chained('get_photos') PathPart('thumbnail') Args(0) {
+ my ( $self, $c ) = @_;
+
+
+ my $photo = $c->stash->{photo};
+ my $size = $self->thumbnail_size;
+
+ my $mimeinfo = File::MimeInfo->new;
+
+ my $data = $photo->path->open('r') or die "Error: $!";
+ my $img = Imager->new;
+ $img->read( fh => $data ) or die $img->errstr;
+ my $scaled = $img->scale( xheight => $size );
+ my $out;
+ $scaled->write(
+ type => $mimeinfo->extensions( $photo->mime ),
+ data => \$out
+ )
+ or die $scaled->errstr;
+ $c->res->content_type( $photo->mime );
+ $c->res->content_length( -s $out );
+ $c->res->header( "Content-Disposition" => "inline; filename="
+ . $mimeinfo->extensions( $photo->mime ) );
+
+ binmode $out;
+ $c->res->body($out);
+
+ }
+
+ =head2 view_image
+
+ hackish method to view
+ an image full-size
+
+ =cut
+
+ sub view_image : Chained('get_photos') PathPart('generate') Args(0) {
+ my ( $self, $c ) = @_;
+
+ my $photo = $c->stash->{photo};
+
+ my $mimeinfo = File::MimeInfo->new;
+
+ my $data = $photo->path->open('r') or die "Error: $!";
+ my $img = Imager->new;
+ $img->read( fh => $data ) or die $img->errstr;
+
+ my $out;
+ $img->write(
+ type => $mimeinfo->extensions( $photo->mime ),
+ data => \$out
+ )
+ or die $img->errstr;
+ $c->res->content_type( $photo->mime );
+ $c->res->content_length( -s $out );
+ $c->res->header( "Content-Disposition" => "inline; filename="
+ . $mimeinfo->extensions( $photo->mime ) );
+
+ binmode $out;
+ $c->res->body($out);
+
+ }
+
+ =head2 view_photo
+
+ view an individual photo
+
+ =cut
+
+ sub view_photo : Chained("get_photos") PathPart('view') Args(0) {
+ my ( $self, $c ) = @_;
+
+ my $photo = $c->stash->{photo};
+
+ $c->stash->{template} = "photos/view.tt2";
+
+ }
+
+ =head2 delete_photo
+
+ delete a photo or photos
+
+ =cut
+
+ sub delete_photo : Chained("get_photos") PathPart('delete') Args(0) {
+ my ( $self, $c ) = @_;
+
+ my $photo = $c->stash->{photo};
+ $c->stash->{template} = 'photos/delete.tt2';
+
+ if ( $c->check_user_roles("admin") ) {
+
+ if ( $c->req->param('delete') eq 'yes' ) {
+
+ $photo->delete;
+ $c->stash->{status_msg} = "Photo " . $photo->photoid . " deleted!";
+ $c->detach;
+
+ }
+
+ }
+ else {
+
+ $c->flash->{error_msg} =
+ "You don't have proper permissions to delete images.";
+ $c->res->redirect("/");
+
+ }
+
+ }
+
+The view:
+
+=over 12
+
+=item add.tt2
+
+ <h2>Upload your photos</h2>
+ [% UNLESS form.submitted_and_valid %]
+ [% form %]
+
+ [% ELSE %]
+
+ <p>Success!</p>
+ <p>Here's your image: <img src="[% c.uri_for("/photo/$photo.photoid/thumbnail") %]" />
+
+ [% END %]
+
+=item delete.tt2
+
+ [% UNLESS c.req.param('delete') %]
+ <h2>Deleting [% photo.name %]</h2>
+ <div id="photo">
+ <img src="[% c.uri_for("/photo/$photo.photoid/generate") %]" alt="[% photo.name %]" />
+ </div>
+ <p>ARE YOU SURE YOU WANT TO DELETE THIS PHOTO?</p>
+ <p><a href="[% c.uri_for("/photo/$photo.photoid/delete", { delete=> 'yes' } ) %]">yes</a> I do</p>
+ <p><a href="[% c.uri_for("/photos") %]">no</a> I don't</p>
+ <div>«<a href="[% c.uri_for("/photos") %]">back</a>
+ [% ELSE %]
+ <p>Deleted!</p>
+ [% END %]
+
+=item index.tt2
+
+ [% USE table (photos, rows=3) %]
+ <h2>Puppy Photos</h2>
+
+ <div id="puppy-list">
+ <table>
+ [% FOREACH column = table.cols %]
+ <tr>
+ [% FOREACH photo = column %]
+ <td>
+ [% IF photo %]
+ <a href="[% c.uri_for("/photo/$photo.photoid/view") %]">
+ <img src="[% c.uri_for("/photo/$photo.photoid/thumbnail")%]" />
+ </a>
+ [% ELSE %]
+ <img src="[% c.uri_for("/static/photos/blank.gif")%]" width="150" height="100"/>
+ [% END %]
+ </td>
+ [% END %]
+ </tr>
+ [% END %]
+ <table>
+ </div>
+
+
+=item view.tt2
+
+ <h2>[% photo.name %]</h2>
+ <div id="photo">
+ <img src="[% c.uri_for("/photo/$photo.photoid/generate") %]" alt="[% photo.name %]" />
+ </div>
+ <p>[% photo.caption %]</p>
+ <div>«<a href="[% c.uri_for("/photos") %]">back</a>
+
+
+Voila! There you have it. Go nuts.
+
+=head1 AUTHOR
+
+Devin Austin
+devin.austin at gmail.com
+http://www.codedright.net
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
+
+
+
More information about the Catalyst-commits
mailing list