site/templates/admin/imageclean/preview.tmpl
site/templates/admin/import/import.tmpl
site/templates/admin/import/start.tmpl
+site/templates/admin/include/article_cfg_custom.tmpl
site/templates/admin/include/article_menu.tmpl
site/templates/admin/include/auditentry.tmpl
site/templates/admin/include/audithead.tmpl
use DevHelp::Date qw(dh_parse_date dh_parse_sql_date);
use List::Util qw(first);
use constant MAX_FILE_DISPLAYNAME_LENGTH => 255;
+use constant ARTICLE_CUSTOM_FIELDS_CFG => "article custom fields";
-our $VERSION = "1.029";
+our $VERSION = "1.030";
=head1 NAME
return $article->tag_objects;
}
+my %base_custom_validation =
+ (
+ customDate1 =>
+ {
+ rules => "date",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ customDate2 =>
+ {
+ rules => "date",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ customStr1 =>
+ {
+ htmltype => "text",
+ default => "",
+ },
+ customStr2 =>
+ {
+ htmltype => "text",
+ default => "",
+ },
+ customInt1 =>
+ {
+ rules => "integer",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ customInt2 =>
+ {
+ rules => "integer",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ customInt3 =>
+ {
+ rules => "integer",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ customInt4 =>
+ {
+ rules => "integer",
+ htmltype => "text",
+ width => 10,
+ default => "",
+ },
+ );
+
+sub custom_fields {
+ my $self = shift;
+
+ require DevHelp::Validate;
+ DevHelp::Validate->import;
+ return DevHelp::Validate::dh_configure_fields
+ (
+ \%base_custom_validation,
+ $self->cfg,
+ ARTICLE_CUSTOM_FIELDS_CFG,
+ BSE::DB->single->dbh,
+ );
+}
+
sub low_edit_tags {
my ($self, $acts, $request, $article, $articles, $msg, $errors) = @_;
my $it = BSE::Util::Iterate->new;
my $ito = BSE::Util::Iterate::Objects->new;
my $ita = BSE::Util::Iterate::Article->new(req => $request);
+
+ my $custom = $self->custom_fields;
+ $request->set_variable(custom => $custom);
+
return
(
$request->admin_tags,
$errors->{category} = "msg:bse/admin/edit/category/unknown";
}
}
+
+ require DevHelp::Validate;
+ DevHelp::Validate->import('dh_validate_hash');
+ dh_validate_hash($data, $errors,
+ {
+ fields => $self->custom_fields,
+ optional => 1,
+ },
+ $self->cfg, ARTICLE_CUSTOM_FIELDS_CFG);
}
sub validate {
sub fill_new_data {
my ($self, $req, $data, $articles) = @_;
+ my $custom = $self->custom_fields;
+ for my $key (keys %$custom) {
+ my ($value) = $req->cgi->param($key);
+ if ($custom->{$key}{description} && defined $value) {
+ if ($key =~ /^customDate/) {
+ if ($value =~ /^\s*([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)\s*$/) {
+ $data->{$key} = "$3-$2-$1";
+ }
+ else {
+ $data->{$key} = undef;
+ }
+ }
+ elsif ($key =~ /^customInt/) {
+ if ($value =~ /\S/) {
+ $data->{$key} = $value;
+ }
+ else {
+ $data->{$key} = undef;
+ }
+ }
+ else {
+ $data->{$key} = $value;
+ }
+ }
+ }
+
custom_class($self->{cfg})
->article_fill_new($data, $self->typename);
$article->{$col} = $data->{$col}
if exists $data->{$col} && $col ne 'id' && $col ne 'parentid';
}
+ my $custom = $self->custom_fields;
+ for my $key (keys %$custom) {
+ if ($custom->{$key}{description} && exists $data->{$key}) {
+ if ($key =~ /^customDate/) {
+ if ($data->{key} =~ /^\s*([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)\s*$/) {
+ $article->set($key => "$3-$2-$1");
+ }
+ else {
+ $article->set($key => undef);
+ }
+ }
+ elsif ($key =~ /^customInt/) {
+ if ($data->{$key} =~ /\S/) {
+ $article->set($key => $data->{$key});
+ }
+ else {
+ $article->set($key => undef);
+ }
+ }
+ else {
+ $article->set($key => $data->{$key});
+ }
+ }
+ }
custom_class($self->{cfg})
->article_fill_old($article, $data, $self->typename);
use base 'BSE::Edit::Article';
use BSE::Util::HTML;
use BSE::Util::Tags qw(tag_article);
+use constant CATALOG_CUSTOM_FIELDS_CFG => "catalog custom fields";
-our $VERSION = "1.002";
+our $VERSION = "1.003";
sub base_template_dirs {
return ( "catalog" );
return $self->SUPER::type_default_value($req, $col);
}
+sub custom_fields {
+ my ($self) = @_;
+
+ my $custom = $self->SUPER::custom_fields();
+
+ require DevHelp::Validate;
+ DevHelp::Validate->import;
+ return DevHelp::Validate::dh_configure_fields
+ (
+ $custom,
+ $self->cfg,
+ CATALOG_CUSTOM_FIELDS_CFG,
+ BSE::DB->single->dbh,
+ );
+}
+
1;
use BSE::Util::HTML;
use BSE::CfgInfo 'product_options';
use BSE::Util::Tags qw(tag_hash tag_article);
+use constant PRODUCT_CUSTOM_FIELDS_CFG => "product custom fields";
-our $VERSION = "1.010";
+our $VERSION = "1.011";
=head1 NAME
return $self->refresh($article, $req->cgi, undef, "Values reordered");
}
+sub custom_fields {
+ my ($self) = @_;
+
+ my $custom = $self->SUPER::custom_fields();
+
+ require DevHelp::Validate;
+ DevHelp::Validate->import;
+ return DevHelp::Validate::dh_configure_fields
+ (
+ $custom,
+ $self->cfg,
+ PRODUCT_CUSTOM_FIELDS_CFG,
+ BSE::DB->single->dbh,
+ );
+}
+
sub article_actions {
my $self = shift;
use BSE::Util::HTML;
use Carp qw(cluck confess);
-our $VERSION = "1.014";
+our $VERSION = "1.015";
sub new {
my ($class, %opts) = @_;
};
}
}
+ $self->{field_errors} = $errors;
}
elsif ($errors && !ref $errors) {
push @messages,
map { $_->{type} eq 'html' ? $_->{text} : escape_html($_->{text}) } @$messages
}
+=item field_errors
+
+Return a hash of field errors that have been supplied to
+message()/messages().
+
+=cut
+
+sub field_errors {
+ my ($self) = @_;
+
+ return $self->{field_errors} || {};
+}
+
sub _set_vars {
my ($self) = @_;
@ISA = qw(Exporter);
use Carp qw(confess);
-our $VERSION = "1.001";
+our $VERSION = "1.002";
my %built_ins =
(
maxdate => '+1d',
maxdatemsg => 'The date entered must be in the past',
},
+ integer =>
+ {
+ integer => 1,
+ },
natural =>
{
integer => '0-', # 0 or higher
my $fields = $cfg->entry($section, 'fields', '');
my @names = ( split(/,/, $fields), keys %$field_hash );
+ my @extra_config;
+ push @extra_config, split /,/, $cfg->entry("form validation", "field_config", "");
+ push @extra_config, split /,/, $cfg->entry($section, "field_config", "");
for my $field (@names) {
$cfg_fields->{$field} = {};
- for my $cfg_name (qw(required rules description required_error range_error mindatemsg maxdatemsg ne_error)) {
+ for my $cfg_name (qw(required rules description required_error range_error mindatemsg maxdatemsg ne_error), @extra_config) {
my $value = $cfg->entry($section, "${field}_$cfg_name");
if (defined $value) {
$cfg_fields->{$field}{$cfg_name} = $value;
A valid date in the future.
+=item integer
+
+Any integer.
+
=item natural
An integer greater or equal to zero.
require 5.005;
use strict;
-our $VERSION = "1.003";
+our $VERSION = "1.004";
use Carp;
use BSE::DB;
return $value;
}
+sub get {
+ my ($self, $name) = @_;
+
+ exists $self->{$name}
+ or do { warn "Attempt to get unknown column '$name' in ",ref $self; return };
+
+ return $self->{$name};
+}
+
use vars '$AUTOLOAD';
sub AUTOLOAD {
If the value contains a comma the text up to the comma is removed and
the remains used as the label, otherwise the key is used as the label.
+=head2 [article custom fields]
+
+=head2 [product custom fields]
+
+=head2 [catalog custom fields]
+
+These can be used to define article, product and catalog custom fields
+respectively, in a similar manner to L<formmail>.
+
+The field names are predefined, C<customDate1>, C<customDate2>,
+C<customInt1>, C<customInt2>, C<customInt3>, C<customInt4>,
+C<customStr1> and C<customStr2>, but are only active if a description
+is defined for the field:
+
+ [article custom fields]
+ customInt1_description=Stock Level
+
=head1 AUTHOR
Tony Cook <tony@develop-help.com>
</tr>
<:include admin/include/edit_common.tmpl:>
<:include admin/article_custom.tmpl optional:>
+<:include admin/include/article_cfg_custom.tmpl:>
<tr>
<th>Thumbnail image:</th>
<td>
</tr>
<:include admin/include/edit_common.tmpl:>
<:include admin/catalog_custom.tmpl optional:>
+<:include admin/include/article_cfg_custom.tmpl -:>
<tr>
<th>Thumbnail image:</th>
<td>
(<:alloptions:>)<:or:><:product options:><:eif:> </td>
<td class="help"><:help product options:> <:error_img options:></td>
</tr>
-<:include admin/product_custom.tmpl optional:><:include admin/include/custom/product_custom.tmpl optional:><:include admin/include/product_custom.tmpl optional:>
+<:include admin/product_custom.tmpl optional -:>
+<:include admin/include/custom/product_custom.tmpl optional -:>
+<:include admin/include/product_custom.tmpl optional -:>
+<:include admin/include/article_cfg_custom.tmpl -:>
<tr>
<th>Thumbnail image:</th>
<td>
--- /dev/null
+<:.for f in custom.list -:>
+<:.if f.value.description ne "" -:>
+<tr>
+ <th><:= f.value.description | html :>:</th>
+ <td>
+ <input type="text" name="<:= f.key | html :>" value="<:.call "old", "field":f.key, "default": ifnew ? f.value.default : article.get(f.key) :>" />
+ </td>
+ <td class="help">
+ <:-.call "error_img", "field":f.key -:>
+ </td>
+</tr>
+<: .end if -:>
+<:.end for -:>
\ No newline at end of file
<span>></span>
<:.end if -:>
</div>
-<:-.end define -:>
\ No newline at end of file
+<:-.end define -:>
+
+<:.define old -:>
+<:# parameters: field, default -:>
+<: .if cgi.param(field).defined -:>
+<:= cgi.param(field) -:>
+<: .else -:>
+<:= default | html -:>
+<: .end if -:>
+<:.end define-:>
+
+<:.define error_img -:>
+<:# parameters: field -:>
+<:# this implementation should probably change -:>
+<:= ("error_img " _ field).evaltag -:>
+<:.end if -:>