--- /dev/null
+AUTHORS
+-------
+
+The following people have written and documented Maypole:
+
+Simon Cozens - Author Emeritus
+Sebastian Riedel - Maintainer (1.x to 2.x)
+Simon Flack - Maintainer ( 2.x to 2.9 )
+Aaron Trevena - Maintainer (2.10 to present)
+Dave Howorth - Developer
+David Baird - Developer
+
+Thanks also to for fixes and other contributions:
+
+Randal Schwartz
+Jester
+Marcus Ramberg
+Steven Simms
+Kevin Connor
+Dagfinn Ilmari Mannsåker
+Danijel Milicevic
+Dave Slack
Deprecated:
Directly accessing the attributes of the request object, or the parameters
in $r->params, or anything else, is DEPRECATED and likely to break in future
- releases. Be good, and use proper method calls.
+ releases. Be good, and use proper method calls.
Incompatible API changes:
Maypole:
- is_applicable() renamed to is_model_applicable(), and returns boolean
instead of a status code. Old-style is_applicable() will still work,
but issues a warning.
+ Maypole::Model
+ - delete and search actions are now deprecated - use do_search and do_delete
+ instead
API additions and enhancements:
Maypole::Application:
- added make_path()
- added make_uri()
- improved exception handling
+ Maypole::Model
+ - do_delete, do_search in place of delete/search actions
Maypole::View::TT:
- new report_error method
- new embedded error report page in __DATA__
lib/Maypole/templates/factory/search_form
lib/Maypole/templates/factory/title
lib/Maypole/templates/factory/view
-lib/Maypole/templates/maypole.css
+lib/Maypole/templates/factory/maypole.css
# http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: Maypole
-version: 2.10
+version: 2.11
version_from: lib/Maypole.pm
installdirs: site
requires:
Class::DBI::SQLite: 0
Digest::MD5: 0
HTTP::Headers: 1.59
+ HTTP::Server::Simple: 0.02
+ HTTP::Server::Simple::Static: 0.01
Template: 0
Template::Plugin::Class: 0
Test::MockModule: 0
UNIVERSAL::moniker: 0
UNIVERSAL::require: 0
+ URI: 0
URI::QueryParam: 0
distribution_type: module
--- /dev/null
+CREATE TABLE style (
+ id integer primary key auto_increment,
+ name varchar(60),
+ notes text
+);
+
+CREATE TABLE pub (
+ id integer primary key auto_increment,
+ name varchar(60),
+ url varchar(120),
+ notes text
+);
+
+CREATE TABLE handpump (
+ id integer primary key auto_increment,
+ beer integer,
+ pub integer
+);
+
+CREATE TABLE beer (
+ id integer primary key auto_increment,
+ brewery integer,
+ style integer,
+ name varchar(30),
+ url varchar(120),
+ score integer(2),
+ price varchar(12),
+ abv varchar(10),
+ notes text
+);
+
+CREATE TABLE brewery (
+ id integer primary key auto_increment,
+ name varchar(30),
+ url varchar(50),
+ notes text
+);
$self->get_user;
my $status = $self->handler_guts;
-
- # moving this here causes unit test failures - need to check why
- # before committing the move
- #$status = $self->__call_process_view unless $self->output;
-
return $status unless $status == OK;
# TODO: require send_output to return a status code
$self->send_output;
-
+
return $status;
}
my $table = $r->table;
my $required_cols = $config->{$table}->{required_cols} || [];
+ my $ignored_cols = $r->{config}{ $r->{table} }{ignore_cols};
- ($obj, my $fatal, my $creating) = $self->_do_update_or_create($r, $obj, $required_cols);
+ ($obj, my $fatal, my $creating) = $self->_do_update_or_create($r, $obj, $required_cols, $ignored_cols);
# handle errors, if none, proceed to view the newly created/updated object
my %errors = $fatal ? (FATAL => $fatal) : $obj->cgi_update_errors;
# reported by Mp::P::Trace
sub _do_update_or_create
{
- my ($self, $r, $obj, $required_cols) = @_;
+ my ($self, $r, $obj, $required_cols, $ignored_cols) = @_;
my $fatal;
my $creating = 0;
if ($obj)
{
# We have something to edit
- eval { $obj->update_from_cgi( $h => {required => $required_cols} ) };
+ eval { $obj->update_from_cgi( $h => {
+ required => $required_cols,
+ ignore => $ignored_cols,
+ } ) };
$fatal = $@;
}
- else
+ else
{
- eval {
- $obj = $self->create_from_cgi( $h => {required => $required_cols} )
+ eval {
+ $obj = $self->create_from_cgi( $h => {
+ required => $required_cols,
+ ignore => $ignored_cols,
+ } )
};
if ($fatal = $@)
return $obj, $fatal, $creating;
}
-
+
sub delete : Exported {
- return shift->SUPER::delete(@_) if caller ne "Maypole::Model::Base";
- my ( $self, $r ) = @_;
- $_->SUPER::delete for @{ $r->objects || [] };
- $r->objects( [ $self->retrieve_all ] );
- $r->{template} = "list";
- $self->list($r);
+ my $self = shift;
+ my ($sub) = (caller(1))[3];
+ $sub =~ /^(.+)::([^:]+)$/;
+ # So subclasses can still send search down ...
+ return ($1 ne "Maypole::Model::Base" && $2 ne "delete") ?
+ $self->SUPER::search(@_) : $self->do_delete(@_);
+}
+
+sub do_delete {
+ my ( $self, $r ) = @_;
+ $_->SUPER::delete for @{ $r->objects || [] };
+ $r->objects( [ $self->retrieve_all ] );
+ $r->{template} = "list";
+ $self->list($r);
}
sub stringify_column {
}
sub search : Exported {
- return shift->SUPER::search(@_) if caller ne "Maypole::Model::Base";
+ my $self = shift;
+ my ($sub) = (caller(1))[3];
+ $sub =~ /^(.+)::([^:]+)$/;
+ # So subclasses can still send search down ...
+ return ($1 ne "Maypole::Model::Base" && $2 ne "search") ?
+ $self->SUPER::search(@_) : $self->do_search(@_);
+}
- # A real CDBI search.
+sub do_search : Exported {
my ( $self, $r ) = @_;
my %fields = map { $_ => 1 } $self->columns;
my $oper = "like"; # For now
in the beerdb and default templates. See the MACRO section of the
L<Template::Manual::Directives> documentation.
+=head1 ACCESSING MAYPOLE VALUES
+
+=head2 request
+
+You can access the request in your templates in order to see the action, table, etc as well
+as parameters passed through forms :
+
+for example
+
+Hello [% request.params.forename %] [% request.params.surname %] !
+
+or
+
+Are you want to [% request.action %] in the [% request.table %] ?
+
+=head2 config
+
+You can access your maypole application configuration through the config variable :
+
+<link base="[% config.uri_base %]"/>
+
+=head2 object and objects
+
+Objects are passed to the request using r->objects($arrayref) and are accessed in the templates
+as an array called objects.
+
+[% FOR objects %] <a href="[% config.uri_base %]/[% request.table %]/view/[% object.id %]"> [% object %] </a> [% END %]
+
=head1 MAYPOLE MACROS AND FILTERS
Maypole provides a collection of useful and powerful macros in the templates/factory/macros
elem.as_XML; %]
</label>
[% IF errors.$col %]
- <span class="error">[% errors.$col %]</span>
+ <span class="error">[% errors.$col | html %]</span>
[% END %]
[% END; %]
[% PROCESS macros %]
[% INCLUDE header %]
[% INCLUDE title %]
+[% user_field = config.auth.user_field || "user" %]
+
<div id="title">You need to log in</div>
<div id="login">
[% IF login_error %]
- <div class="error"> [% login_error %] </div>
+ <div class="error"> [% login_error | html %] </div>
[% END %]
<form method="post" action="[% base %]/[% request.path %]">
<fieldset>
<legend>Login</legend>
<label>
<span class="field">Username:</span>
- <input name="[% config.auth.user_field || "user" %]" type="text" />
+ <input name="[% user_field %]" type="text" value="[% cgi_params.$user_field | html %]" />
</label>
<label>
<span class="field">Password:</span>
- <input name="password" type="password" />
+ <input name="password" type="password" value="[% cgi_params.passwrd | html %]"/>
</label>
<input type="submit" name="login" value="Submit"/>
</fieldset>
SET lnk = base _ "/" _ table _ "/" _ command _ "/" _ additional;
lnk = lnk | uri | html;
'<a href="' _ lnk _ '">';
- label;
+ label | html;
"</a>";
END;
%]
IF object.isa('Maypole::Model::Base');
link(object.table, "view", object.id.join('/'), object);
ELSE;
- object;
+ object | html ;
END;
END;
%]
NEXT IF col == "id" OR col == classmetadata.table _ "_id";
"<td>";
IF col == "url" AND item.url;
- '<a href="'; item.url; '"> '; item.url; '</a>';
+ '<a href="'; item.url | html ; '"> '; item.url; '</a>';
ELSIF col == classmetadata.stringify_column;
maybe_link_view(item);
ELSE;
#%]
[% MACRO view_item(item) BLOCK; %]
[% SET string = classmetadata.stringify_column %]
- <div id="title"> [% item.$string %]</div>
+ <div id="title"> [% item.$string | html %]</div>
[% INCLUDE navbar %]
<table class="view">
<tr>
<td class="field">[% classmetadata.colnames.$string %]</td>
- <td>[% item.$string %]</td>
+ <td>[% item.$string | html %]</td>
</tr>
[% FOR col = classmetadata.columns.list;
NEXT IF col == "id" OR col == string OR col == classmetadata.table _ "_id";;
<td class="field">[% classmetadata.colnames.$col; %]</td>
<td>
[% IF col == "url" && item.url; # Possibly too much magic.
- '<a href="'; item.url; '"> '; item.url; '</a>';
+ '<a href="'; item.url | html ; '"> '; item.url; '</a>';
ELSE;
maybe_link_view(item.$col);
END; %]