Help - Search - Members - Calendar
Full Version: Trying To Create My Own Plugin
Movable Type Community Forum > Additional Resources > Plugin Development and Usage
Uriel Lizama
Hello,

I want to display some random page links, I was unable to find something that would help me with it so I decided to give it a go in creating my own plugin.

The idea is to add a <MTRandomPages> block that will allow me to display the random pages in my templates. The function I have is:

CODE
sub RandomPagesLoop{

    my ($ctx, $args, $cond) = @_;

    my $folder = $args->{folder} || $args->{folders};
    $args->{categories} = $folder if $folder;

    if($args->{no_folder}) {
        require MT::Folder;
        my $blog_id = $ctx->stash('blog_id');
        my @fols = MT::Folder->load({blog_id => $blog_id});
        my $not_folder;
        foreach my $folder (@fols) {
            if ($not_folder) {
                $not_folder .= " OR ".$folder->label;
            } else {
                $not_folder = $folder->label;
            }
        }
        if ($not_folder) {
            $args->{categories} = "NOT ($not_folder)";
        }
    }

    require MT::Page;
    $args->{class_type} = MT::Page->properties->{class_type};

    my $class = MT->model( $args->{class_type} );

    my $blog_id = $ctx->stash('blog_id');
    my $blog = $ctx->stash('blog');

    my (@filters, %blog_terms, %blog_args, %terms, %args);

    $ctx->set_blog_load_context($args, \%blog_terms, \%blog_args)
        or return $ctx->error($ctx->errstr);
    %terms = %blog_terms;
    %args = %blog_args;

    my @pages = $class->load(\%terms, \%args);

    srand;

    my $builder = $ctx->stash('builder');
    my $tok = $ctx->stash('tokens');

    my %usedPages;
    my $res;

    my $limit = $args->{limit} || 1;

    $limit = @pages if ($limit > @pages);


    while($limit > 0){
        my $randPage = $pages[ rand @pages ];

        while ($usedPages{$randPage->id}) {
            $randPage = $pages[ rand @pages ];
        }

        $usedPages{$randPage->id}++;

        local $ctx->{__stash}{blog} = $randPage->blog;
        local $ctx->{__stash}{blog_id} = $randPage->blog_id;
        local $ctx->{__stash}{entry} = $randPage;
        local $ctx->{current_timestamp} = $randPage->authored_on;
        local $ctx->{modification_timestamp} = $randPage->modified_on;

        my $out = $builder->build($ctx, $tok, { %$cond });

        return $ctx->error( $builder->errstr ) unless defined $out;

        $res .= $out;
        $limit--;
    }

    $res;

} #sub RandomPagesLoop


In my template I have:

CODE
<mt:RandomPages limit="5">
<li><h4><a href="<$mt:PagePermalink$>"><$mt:PageTitle$></a></h4> <$mt:PageExcerpt$></li>
</mt:RandomPages>


But it doesn't display anything and the plugin doesn't throw any errors when publishing.

Any help or advice will be greatly appreciated.

Thanks
Uriel Lizama
Hello,

I want to display some random page links, I was unable to find something that would help me with it so I decided to give it a go in creating my own plugin.

The idea is to add a <MTRandomPages> block that will allow me to display the random pages in my templates. The function I have is:

CODE
sub RandomPagesLoop{

    my ($ctx, $args, $cond) = @_;

    my $folder = $args->{folder} || $args->{folders};
    $args->{categories} = $folder if $folder;

    if($args->{no_folder}) {
        require MT::Folder;
        my $blog_id = $ctx->stash('blog_id');
        my @fols = MT::Folder->load({blog_id => $blog_id});
        my $not_folder;
        foreach my $folder (@fols) {
            if ($not_folder) {
                $not_folder .= " OR ".$folder->label;
            } else {
                $not_folder = $folder->label;
            }
        }
        if ($not_folder) {
            $args->{categories} = "NOT ($not_folder)";
        }
    }

    require MT::Page;
    $args->{class_type} = MT::Page->properties->{class_type};

    my $class = MT->model( $args->{class_type} );

    my $blog_id = $ctx->stash('blog_id');
    my $blog = $ctx->stash('blog');

    my (@filters, %blog_terms, %blog_args, %terms, %args);

    $ctx->set_blog_load_context($args, \%blog_terms, \%blog_args)
        or return $ctx->error($ctx->errstr);
    %terms = %blog_terms;
    %args = %blog_args;

    my @pages = $class->load(\%terms, \%args);

    srand;

    my $builder = $ctx->stash('builder');
    my $tok = $ctx->stash('tokens');

    my %usedPages;
    my $res;

    my $limit = $args->{limit} || 1;

    $limit = @pages if ($limit > @pages);


    while($limit > 0){
        my $randPage = $pages[ rand @pages ];

        while ($usedPages{$randPage->id}) {
            $randPage = $pages[ rand @pages ];
        }

        $usedPages{$randPage->id}++;

        local $ctx->{__stash}{blog} = $randPage->blog;
        local $ctx->{__stash}{blog_id} = $randPage->blog_id;
        local $ctx->{__stash}{entry} = $randPage;
        local $ctx->{current_timestamp} = $randPage->authored_on;
        local $ctx->{modification_timestamp} = $randPage->modified_on;

        my $out = $builder->build($ctx, $tok, { %$cond });

        return $ctx->error( $builder->errstr ) unless defined $out;

        $res .= $out;
        $limit--;
    }

    $res;

} #sub RandomPagesLoop


In my template I have:

CODE
<mt:RandomPages limit="5">
<li><h4><a href="<$mt:PagePermalink$>"><$mt:PageTitle$></a></h4> <$mt:PageExcerpt$></li>
</mt:RandomPages>


But it doesn't display anything and the plugin doesn't throw any errors when publishing.

Any help or advice will be greatly appreciated.

Thanks
OtherNiceMan
Where are you registering the tag?

Does anything show up under plugins?
Uriel Lizama
Thank you for your reply. Im creating the plugin for MT4, so I created my YAML file. Under System Overview->Tools->Plugins I can see that the plugin is active and in the Resources option I can see the registered tag <MTRandomPages>.

So everything appears to be working, only that it doesn't display anything.
OtherNiceMan
Can you post the yaml file please.
Uriel Lizama
QUOTE (OtherNiceMan @ Nov 4 2008, 03:11 PM) *
Can you post the yaml file please.



CODE
name: Random Pages
id: RandomPages
author_link: http://www.baboonsoftware.com/
author_name: Uriel Lizama
description: This plugin provides special tags to get random pages for Movable Type.
version: 1.0
tags:
    block:
        RandomPages: $RandomPages::RandomPages::RandomPagesLoop
OtherNiceMan
Sorry for the back and forth, but is the original perl code all that is in the pl file?
Uriel Lizama
QUOTE (OtherNiceMan @ Nov 4 2008, 05:05 PM) *
Sorry for the back and forth, but is the original perl code all that is in the pl file?


Hey, dont worry about it. Here is the complete code on RandomPages.pm:

CODE
# Good for Nothing Plugin for Movable Type
# Author: Your Name Here, your.email@address.com
# Copyright (C) 2008 Your Name Here
# This file is licensed under the Artistic License, or the same
# terms as Perl itself.
package RandomPages::RandomPages;

use strict;
use MT 4;



sub RandomPagesLoop{

    my ($ctx, $args, $cond) = @_;

    my $folder = $args->{folder} || $args->{folders};
    $args->{categories} = $folder if $folder;

    if($args->{no_folder}) {
        require MT::Folder;
        my $blog_id = $ctx->stash('blog_id');
        my @fols = MT::Folder->load({blog_id => $blog_id});
        my $not_folder;
        foreach my $folder (@fols) {
            if ($not_folder) {
                $not_folder .= " OR ".$folder->label;
            } else {
                $not_folder = $folder->label;
            }
        }
        if ($not_folder) {
            $args->{categories} = "NOT ($not_folder)";
        }
    }

    require MT::Page;
    $args->{class_type} = MT::Page->properties->{class_type};

    my $class = MT->model( $args->{class_type} );

    my $blog_id = $ctx->stash('blog_id');
    my $blog = $ctx->stash('blog');

    my (@filters, %blog_terms, %blog_args, %terms, %args);

    $ctx->set_blog_load_context($args, \%blog_terms, \%blog_args)
        or return $ctx->error($ctx->errstr);
    %terms = %blog_terms;
    %args = %blog_args;

    my @pages = $class->load(\%terms, \%args);

    srand;

    my $builder = $ctx->stash('builder');
    my $tok = $ctx->stash('tokens');

    my %usedPages;
    my $res;

    my $limit = $args->{limit} || 1;

    $limit = @pages if ($limit > @pages);


    while($limit > 0){
        my $randPage = $pages[ rand @pages ];

        while ($usedPages{$randPage->id}) {
            $randPage = $pages[ rand @pages ];
        }

        $usedPages{$randPage->id}++;

        local $ctx->{__stash}{blog} = $randPage->blog;
        local $ctx->{__stash}{blog_id} = $randPage->blog_id;
        local $ctx->{__stash}{entry} = $randPage;
        local $ctx->{current_timestamp} = $randPage->authored_on;
        local $ctx->{modification_timestamp} = $randPage->modified_on;

        my $out = $builder->build($ctx, $tok, { %$cond });

        return $ctx->error( $builder->errstr ) unless defined $out;

        $res .= $out;
        $limit--;
    }

    $res;

} #sub RandomPagesLoop



1; # Every module must return true


Once again, thank you for taking the time to help me.

danwolfgang
Nothing jumps out at me as an obvious problem. Have you tried adding some logging to help troubleshot? You can use the Activity Log to track things. Add some lines to print variables and verify that certain things are happening, like this:
CODE
MT::log('Entered the loop');

Uriel Lizama
QUOTE (danwolfgang @ Nov 6 2008, 07:16 AM) *
Nothing jumps out at me as an obvious problem. Have you tried adding some logging to help troubleshot? You can use the Activity Log to track things. Add some lines to print variables and verify that certain things are happening, like this:
CODE
MT::log('Entered the loop');


That's a great idea, I will try it out and post my findings.

I appreciate your help.
Uriel Lizama
So I added some MT::log calls and it doesn't log anything. I added one just at the top of the function just to be sure that its been called and nothing:

CODE
sub RandomPagesLoop{

    my ($ctx, $args, $cond) = @_;

    MT::log('RandomPages to action');

...
Uriel Lizama
Some other findings that might be of use.

I wanted to see if MT was completely ignoring my tags, so instead of <MTRandomPages> I tried with <MTRandomPages122324>, and MT complained that the tag wasn't recognized, that meant that <MTRandomPages> is recognized. That is a start.

Then I wanted to see if MT complained if it didn't find the registered function RandomPagesLoop, so I renamed the function inside the plugin. And MT didn't complain alltough the function registered for the tag didn't exist.

So I think that for some reason MT is not even trying to call my module to process the ouput for the tag block.
OtherNiceMan
I would try the new version of Log4MT if you are no using it https://trac.endevver.com/movabletype/wiki/code/log4mt (ignore the SSL error)
Uriel Lizama
Thank you all for your help. Just as I thought the function was never called, so what I did is create the plugin the 'old' way. I created a RandomPages.pl and registered the plugin from inside, here is the final code:

CODE
package MT::Plugin::RandomPages;
use base 'MT::Plugin';

use strict;
use MT 4;
use MT::Plugin;


# show plugin information to main menu
my $plugin = __PACKAGE__->new({
    name => 'RandomPages',
    id => 'RandomPages',
    key => 'random_pages_loop',
    version => '1.00',
    author_name => '<__trans phrase="Uriel Lizama">',
    author_link => 'http://baboonsoftware.com/',
    description => '<__trans phrase="This plugin provides special tags to get random pages for Movable Type.">',
});

MT->add_plugin($plugin);


sub init_registry {
    my $plugin = shift;
    my $reg = {
        tags => {
            block => {
                RandomPages => \&random_pages_loop,
            },
        },
    };
    $plugin->registry($reg);
}


sub random_pages_loop{

    my ($ctx, $args, $cond) = @_;


    my $folder = $args->{folder} || $args->{folders};
    $args->{categories} = $folder if $folder;

    if($args->{no_folder}) {
        require MT::Folder;
        my $blog_id = $ctx->stash('blog_id');
        my @fols = MT::Folder->load({blog_id => $blog_id});
        my $not_folder;
        foreach my $folder (@fols) {
            if ($not_folder) {
                $not_folder .= " OR ".$folder->label;
            } else {
                $not_folder = $folder->label;
            }
        }
        if ($not_folder) {
            $args->{categories} = "NOT ($not_folder)";
        }
    }


    require MT::Page;
    $args->{class_type} = MT::Page->properties->{class_type};

    my $class = MT->model( $args->{class_type} );

    my $blog_id = $ctx->stash('blog_id');
    my $blog = $ctx->stash('blog');

    my (@filters, %blog_terms, %blog_args, %terms, %args);

    $ctx->set_blog_load_context($args, \%blog_terms, \%blog_args)
        or return $ctx->error($ctx->errstr);
    %terms = %blog_terms;
    %args = %blog_args;

    my @pages = $class->load(\%terms, \%args);


    srand;

    my $builder = $ctx->stash('builder');
    my $tok = $ctx->stash('tokens');

    my %usedPages;
    my $res;

    my $limit = $args->{limit} || 1;

    $limit = @pages if ($limit > @pages);


    while($limit > 0){
        my $randPage = $pages[ rand @pages ];

        while ($usedPages{$randPage->id}) {
            $randPage = $pages[ rand @pages ];
        }

        $usedPages{$randPage->id}++;

        local $ctx->{__stash}{blog} = $randPage->blog;
        local $ctx->{__stash}{blog_id} = $randPage->blog_id;
        local $ctx->{__stash}{entry} = $randPage;
        local $ctx->{current_timestamp} = $randPage->authored_on;
        local $ctx->{modification_timestamp} = $randPage->modified_on;

        my $out = $builder->build($ctx, $tok, { %$cond });

        return $ctx->error( $builder->errstr ) unless defined $out;

        $res .= $out;
        $limit--;
    }


    $res;

} #sub DisplayRandomPages



1;


Now it's working like a charm biggrin.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2009 Invision Power Services, Inc.