NAME
Konstrukt::Doc::Tutorial::Plugin::Note::Actions - 1) Create a simple note taking plugin performing different actions
DESCRIPTION
This tutorial will teach you how to create a simple plugin, which uses the CGI-action -> plugin-method mapping to perform different tasks according to an action
CGI parameter.
This is especially useful, when writing a plugin, where the user can perform several actions like creating content, viewing it, deleting it and so on.
Note: For the setup of the usage of custom plugins see "SETUP" in Konstrukt::Doc::Tutorial::Plugin::Randomline.
CREATE THE PLUGIN
We will create a plugin, that by default shows a note, that is stored in a text file on the server (if exists). It also shows a link to actions, which allow the user to edit and delete the note.
We can identify these actions:
default: show the note, if exists
edit: show a form to edit the note or save the note, if a new one is entered
delete: show a confirmation to delete to note or delete the note if the deletion has been confirmed
First, create a file (e.g. note.html
) with this content:
<& note / &>
<a href="?">show</a>
Create a file note.pm
in your custom plugin directory with this skeleton:
package Konstrukt::Plugin::note;
use strict;
use warnings;
use base 'Konstrukt::SimplePlugin';
#show the note if exists
sub default : Action {
my ($self, $tag, $content, $params) = @_;
print 'note action';
}
#show a form to edit the note or save the note, if a new one is entered
sub edit : Action {
my ($self, $tag, $content, $params) = @_;
print 'edit action';
}
#show a confirmation to delete to note
#or delete the note if the deletion has been confirmed
sub delete : Action {
my ($self, $tag, $content, $params) = @_;
print 'delete action';
}
1;
You can now point your web browser to the web page (e.g. note.html
) and you will see the text:
note action
which is the output of the default action.
You can manually specify the actions, that should be executed by supplying the CGI parameter note_action
. For example, you could call the website with the URL note.html?note_action=edit
and you'll see this text:
edit action
If you enter an action, that does not exist, an error will be produced. If you enter no action, the default action will be executed. Note that you must add the : Action
attribute to your methods to let them be accessible from the outside.
ADD THE LOGIC
We want to read a file from disk and display the contents on the web page. If no note exists, display a form to create one. So we replace the print
statement of the default
action with this code:
my $text = $Konstrukt::File->read("/note.txt");
if (defined $text) {
print $text;
print '
<br />
<a href="?note_action=edit">edit</a><br />
<a href="?note_action=delete">delete</a>';
} else {
$self->edit($tag, $content, $params);
}
Now we add the functionality to edit the note. If no text is specified and a note already exists, a form with the existing text will be displayed. Otherwise an empty form will be displayed. If a new text is specified, we overwrite the existing node.
We replace the print
statement of the edit
action with this code:
if (exists $params->{text}) {
#overwrite note
$Konstrukt::File->write("/note.txt", $params->{text});
$self->default($tag, $content, $params);
} else {
#display a form to edit the note
my $text = $Konstrukt::File->read("/note.txt") || '(no note yet)';
print "
<form action=\"\" method=\"post\">
<input type=\"hidden\" name=\"note_action\" value=\"edit\" />
<textarea name=\"text\">$text</textarea>
<input type=\"submit\" value=\"Save\" />
</form>";
}
Now we only need to handle the deletion of the note. If the CGI parameter delete
is true, the file will be deleted. Otherwise a confirmation to delete the file will be displayed.
We replace the print
statement of the delete
action with this code:
if (exists $params->{delete} and $params->{delete}) {
#delete note
unlink $Konstrukt::File->absolute_path("/note.txt");
print "Note deleted!\n";
$self->default($tag, $content, $params);
} else {
#display a confirmation form
print "
<form action=\"\" method=\"post\">
<input type=\"hidden\" name=\"note_action\" value=\"delete\" />
<input type=\"checkbox\" id=\"delete\" name=\"delete\" value=\"1\" />
<label for=\"delete\">Really delete the note?</label>
<input type=\"submit\" value=\"Delete\" />
</form>";
}
That's it! Restart/reload your Apache, and try it out.
WHAT'S NEXT?
That's a minimal example. Usually you should not print out HTML from your plugins - instead you should use templates, which contain the HTML.
Also the hardcoded filename to the file containing the note is not very flexible. You might use a filename that is specified in a tag attribute:
<& note file="/foo.txt" / &>
This can then be accessed though the $tag
reference:
my $filename = $tag->{tag}->{attributes}->{file};
Additionally you could just store the note in a database.
Templating and database usage are topics of the next tutorials.
APPENDIX: THE COMPLETE PLUGIN
package Konstrukt::Plugin::note;
use strict;
use warnings;
use base 'Konstrukt::SimplePlugin';
#show the note, if exists
sub default : Action {
my ($self, $tag, $content, $params) = @_;
my $text = $Konstrukt::File->read("/note.txt");
if (defined $text) {
print $text;
print '
<br />
<a href="?note_action=edit">edit</a><br />
<a href="?note_action=delete">delete</a>';
} else {
$self->edit($tag, $content, $params);
}
}
#show a form to edit the note or save the note, if a new one is entered
sub edit : Action {
my ($self, $tag, $content, $params) = @_;
if (exists $params->{text}) {
#overwrite note
$Konstrukt::File->write("/note.txt", $params->{text});
$self->default($tag, $content, $params);
} else {
#display a form to edit the note
my $text = $Konstrukt::File->read("/note.txt") || '(no note yet)';
print "
<form action=\"\" method=\"post\">
<input type=\"hidden\" name=\"note_action\" value=\"edit\" />
<textarea name=\"text\">$text</textarea>
<input type=\"submit\" value=\"Save\" />
</form>";
}
}
#show a confirmation to delete to note
#or delete the note if the deletion has been confirmed
sub delete : Action {
my ($self, $tag, $content, $params) = @_;
if (exists $params->{delete} and $params->{delete}) {
#delete note
unlink $Konstrukt::File->absolute_path("/note.txt");
print "Note deleted!\n";
$self->default($tag, $content, $params);
} else {
#display a confirmation form
print "
<form action=\"\" method=\"post\">
<input type=\"hidden\" name=\"note_action\" value=\"delete\" />
<input type=\"checkbox\" id=\"delete\" name=\"delete\" value=\"1\" />
<label for=\"delete\">Really delete the note?</label>
<input type=\"submit\" value=\"Delete\" />
</form>";
}
}
1;
AUTHOR
Copyright 2006 Thomas Wittek (mail at gedankenkonstrukt dot de). All rights reserved.
This document is free software. It is distributed under the same terms as Perl itself.
SEE ALSO
Next: Konstrukt::Doc::Tutorial::Plugin::Note::Template
Previous: Konstrukt::Doc::Tutorial::Plugin::Randomline
Parent: Konstrukt::Doc
See also: Konstrukt::SimplePlugin, Konstrukt::Doc::CreatingPlugins, Konstrukt::File