Catalyst::Plugin::Sitemap

September 26th, 2010
PerlCatalystCatalyst::Plugin::SitemapSearch::Sitemap

Catalyst::Plugin::Sitemap

I hadn’t planned on writing this. In fact, I positively don’t have the time to write this. But, sometimes, the only mistake a man has to make is to pause one second and wonders hey, wouldn’t be cool to have something that auto-generates the sitemap of a Catalyst app? And then BAM! The yak jumps out of nowhere, hangs to the poor sod’s t-shirt with all hooves and forcefully moos “shave me, shaaaave me” until the silly git succumbs to the pressure.

Oh well. On the sunny side, I’ve now written my very first Catalyst plugin, and that’s going to be something useful for Galuga.

As I don’t have a lot of time, I’ll be succint. As you’ve doubtlessly gathered by now, the name of the game is Catalyst::Plugin::Sitemap. It’s on Github, but it’s not CPANized yet.

To use it, add the plugin to your Catalyst app main module:

use Catalyst qw/ 
    Sitemap 
/;

Then, use the sub attribute :Sitemap to tag actions for which you want an entry in the sitemap. The attribute can be called different ways:

    # bare attribute, add the uri for the action

sub alone :Local :Sitemap { 
    ...
}

    # with the priority of the sitemap entry

sub with_priority :Local :Sitemap(0.75) { 
}

    # with desired sitemap attributes
    # see Search::Sitemap for the full list

sub with_args :Local 
        :Sitemap( lastmod => 2010-09-27, changefreq => daily ) {
}

    # with '*', calls the function '<action>_sitemap'
    # with the arguments ( $controller, $c, $sitemap ) 

sub with_function :Local :Sitemap(*) { }

sub with_function_sitemap {
    $_[2]->add( 'http://localhost/with_function' );
}

And that’s it. Your catalyst application now has a sitemap() method that harvest all those entries and returns a Search::Sitemap object.

sub sitemap : Path('/sitemap') {
    my ( $self, $c ) = @_;

    $c->res->body( $c->sitemap->xml );
}

That action, coupled with the ones defined above, would give this sitemap:

 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
 <url>
 <loc>http://localhost/root/with_priority</loc>
 <priority>0.75</priority>
 </url>
 <url>
 <loc>http://localhost/root/alone</loc>
 </url>
 <url>
 <loc>http://localhost/root/with_function</loc>
 </url>
 <url>
 <loc>http://localhost/root/with_args</loc>
 <lastmod>2010-09-27</lastmod>
 <changefreq>daily</changefreq>
 </url>
 </urlset>

Right now, the Search::Sitemap object is re-created each time the method is called. The next time I have some rount tuit, I plan to provide the option to also just create it once.