use strict;
use Carp qw(confess);
use Image::Size;
+use Fcntl ':seek';
-our $VERSION = "1.003";
+our $VERSION = "1.004";
=head1 NAME
(
image =>
{
+ type => "image",
htmltype => "file",
},
string =>
(
description => scalar $self->title,
units => scalar $self->unit,
- rules => scalar $self->rules,
+ rules => [ $self->rules ],
rawtype => scalar $self->type,
htmltype => scalar $self->htmltype,
type => scalar $self->fieldtype,
my ($self) = @_;
if ($self->type eq 'image') {
- return ( $self->data_name, $self->width_name, $self->height_name );
+ return ( $self->data_name, $self->width_name, $self->height_name, $self->display_name );
}
else {
return $self->name;
$opts{htmltype} ||= $field_defs{$opts{type}}{htmltype};
ref $opts{rules} or $opts{rules} = [ split /[,;]/, $opts{rules} ];
+ unshift @{$opts{rules}}, $rule_map{$opts{type}};
if ($opts{cond}) {
my $code = $opts{cond};
}
sub retrieve {
- my ($class, $req, $owner, $errors) = @_;
+ my ($class, $req, $owner, $errors, %opts) = @_;
+ my $api = $opts{api};
my @meta;
my @meta_delete;
my $cgi = $req->cgi;
}
else {
my $new;
- if ($meta->is_text) {
- my ($value) = $cgi->param($cgi_name);
- if (defined $value &&
- ($value =~ /\S/ || $current_meta{$meta->name})) {
- my $error;
- if ($meta->validate(value => $value, error => \$error)) {
+ my %fields =
+ (
+ $cgi_name => $meta->field,
+ );
+ if ($req->validate(fields => \%fields,
+ rules => \%meta_rules,
+ errors => $errors)) {
+ my $values = $req->cgi_fields
+ (
+ fields => \%fields,
+ api => $api,
+ );
+ my $value = $values->{$cgi_name};
+ if ($meta->is_text) {
+ if (defined $value &&
+ ($value =~ /\S/ || $current_meta{$meta->name})) {
+ utf8::encode($value);
push @meta,
{
name => $name,
value => $value,
};
}
- else {
- $errors->{$cgi_name} = $error;
- }
}
- }
- else {
- my $im = $cgi->param($cgi_name);
- my $up = $cgi->upload($cgi_name);
- if (defined $im && $up) {
- my $data = do { local $/; <$up> };
- my ($width, $height, $type) = imgsize(\$data);
-
- if ($width && $height) {
- push @meta,
- (
- {
- name => $meta->data_name,
- value => $data,
- content_type => "image/\L$type",
- },
- {
- name => $meta->width_name,
- value => $width,
- },
- {
- name => $meta->height_name,
- value => $height,
- },
- {
- name => $meta->display_name,
- value => "" . $im,
- },
- );
- }
- else {
- $errors->{$cgi_name} = $type;
+ else {
+ if ($value) {
+ my $up = $value->{fh};
+ binmode $up;
+ seek $up, 0, SEEK_SET;
+ my $data = do { local $/; <$up> };
+ my ($width, $height, $type) = imgsize(\$data);
+
+ if ($width && $height) {
+ push @meta,
+ (
+ {
+ name => $meta->data_name,
+ value => $data,
+ content_type => "image/\L$type",
+ },
+ {
+ name => $meta->width_name,
+ value => $width,
+ },
+ {
+ name => $meta->height_name,
+ value => $height,
+ },
+ {
+ name => $meta->display_name,
+ value => "" . $value->{filename},
+ },
+ );
+ }
}
}
}
sub save {
my ($class, $owner, $meta) = @_;
- for my $meta_delete (@{$meta->{meta}}, map $_->{name}, @{$meta->{delete}}) {
- $owner->delete_meta_by_name($meta_delete->{name});
+ for my $meta_delete (@{$meta->{delete}}, map $_->{name}, @{$meta->{meta}}) {
+ $owner->delete_meta_by_name($meta_delete);
}
for my $meta (@{$meta->{meta}}) {
$owner->add_meta(%$meta, appdata => 1);
use strict;
use Carp 'confess';
-our $VERSION = "1.001";
+our $VERSION = "1.002";
=head1 NAME
sub add_meta {
my ($self, %opts) = @_;
+ my $value_text = delete $opts{value_text};
+ if ($value_text) {
+ utf8::encode($value_text);
+ $opts{value} = $value_text;
+ }
+
require BSE::TB::Metadata;
return BSE::TB::Metadata->make
(
use BSE::Util::HTML;
use Carp qw(cluck confess);
-our $VERSION = "1.030";
+our $VERSION = "1.031";
=head1 NAME
$field->{readonly}
and next FIELD;
my $value;
- if ($field->{htmltype} eq "checkbox") {
+ if ($field->{htmltype} eq "file") {
+ my $fh = $cgi->upload($name);
+ my $filename = $cgi->param($name);
+ if ($fh) {
+ $value = { fh => $fh, filename => "".$filename };
+ }
+ }
+ elsif ($field->{htmltype} eq "checkbox") {
if ($field->{type} eq "int") {
$value = $cgi->param($name) ? 1 : 0;
}
use base qw(Squirrel::Row BSE::MetaOwnerBase);
use Carp 'confess';
-our $VERSION = "1.013";
+our $VERSION = "1.014";
+
+use constant MAX_FILE_DISPLAYNAME_LENGTH => 255;
sub columns {
return qw/id articleId displayName filename sizeInBytes description
{
htmltype => "file",
description => "File",
+ maxlength => MAX_FILE_DISPLAYNAME_LENGTH,
},
description =>
{
description => "Description",
rules => "dh_one_line",
+ maxlength => 255,
},
name =>
{
description => "Identifier",
htmltype => "text",
width => 20,
+ maxlength => 80,
},
contentType =>
{
],
},
},
+ category =>
+ {
+ description => "Category",
+ maxlength => 20,
+ },
);
}
use strict;
use base 'Squirrel::Row';
-our $VERSION = "1.001";
+our $VERSION = "1.002";
sub table {
"bse_article_file_meta";
$_[0]->content_type eq "text/plain"
}
+sub is_text_type {
+ $_[0]->content_type =~ m(^text/);
+}
+
+sub value_text {
+ my ($self) = @_;
+
+ $self->is_text_type or return;
+
+ my $value = $self->value;
+ utf8::decode($value) or return;
+
+ return $value;
+}
+
+sub set_value_text {
+ my ($self, $value) = @_;
+
+ $self->is_text_type or return;
+
+ utf8::encode($value);
+
+ $self->set_value($value);
+
+ 1;
+}
+
1;
@ISA = qw(Exporter);
use Carp qw(confess);
-our $VERSION = "1.008";
+our $VERSION = "1.009";
my $re_real =
qr/
}
}
}
+ if ($rule->{file} || $rule->{image}) {
+ my $fh = $self->upload($field);
+ if ($fh) {
+ my $size = -s $fh;
+ if ($rule->{maxsize} && $size > _kb($rule->{maxbytes})) {
+ $errors->{$field} = _make_error($field, $info, $rule,
+ $info->{maxbytes_error} ||
+ $rule->{maxbytes_error} ||
+ "\$n must be smaller than $rule->{maxsize}");
+ last RULE;
+ }
+ elsif ($rule->{minsize} && $size < _kb($rule->{minsize})) {
+ $errors->{$field} = _make_error($field, $info, $rule,
+ $info->{minbytes_error} ||
+ $rule->{minbytes_error} ||
+ "\$n must be larger than than $rule->{maxsize}");
+ last RULE;
+ }
+ }
+ else {
+ $errors->{$field} = _make_error($field, $info, $rule,
+ $info->{nofile_error} ||
+ $rule->{nofile_error},
+ "\$n isn't a file");
+ last RULE;
+ }
+ }
+ if ($rule->{image}) {
+ my $fh = $self->upload($field);
+ require Image::Size;
+ my ($width, $height, $type) = Image::Size::imgsize($fh->handle);
+ if (!defined $width) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{notimage_error} || $rule->{notimage_error} ||
+ "\$n isn't an image file");
+ last RULE;
+ }
+ elsif ($rule->{imagetype} &&
+ $rule->{imagetype} !~ /\b\Q$type\E\b/i) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{imagetype_error} || $rule->{imagetype_error} ||
+ "\$n isn't a supported image format");
+ last RULE;
+ }
+ elsif ($rule->{minwidth} &&
+ $rule->{minwidth} > $width) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{minwidth_error} || $rule->{minwidth_error} ||
+ "\$n must be at least $rule->{minwidth} pixels wide");
+ last RULE;
+ }
+ elsif ($rule->{minheight} &&
+ $rule->{minheight} > $height) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{minheight_error} || $rule->{minheight_error} ||
+ "\$n must be at least $rule->{minwidth} pixels high");
+ last RULE;
+ }
+ elsif ($rule->{maxwidth} &&
+ $rule->{maxwidth} < $width) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{maxwidth_error} || $rule->{maxwidth_error} ||
+ "\$n must be no more than $rule->{maxwidth} pixels wide");
+ last RULE;
+ }
+ elsif ($rule->{maxheight} &&
+ $rule->{maxheight} < $height) {
+ $errors->{$field} =
+ _make_error($field, $info, $rule,
+ $info->{maxheight_error} || $rule->{maxheight_error} ||
+ "\$n must be no more than $rule->{maxwidth} pixels high");
+ last RULE;
+ }
+ }
if ($rule->{ref}) {
my $method = $rule->{method}
or confess "Missing method in ref rule $rule_name";
$self->{cgi}->param($field);
}
+sub upload {
+ my ($self, $field) = @_;
+
+ $self->{cgi}->upload($field);
+}
+
sub validate {
my ($self, $cgi, $errors) = @_;
return $value;
}
+sub upload {
+ return;
+}
+
sub validate {
my ($self, $hash, $errors) = @_;
<fieldset>
<legend>File metadata</legend>
-<: .for m in metas :>
-<:#= bse.dumper(m.field) |raw :>
+<: .for m in metas -:>
+<:= bse.dumper(m.field) |raw :>
<:#= bse.dumper(m) |raw :>
-<: .set name = "meta_" _ m.name :>
-<: .set mdata = file.meta_by_name(m.name) :>
-<: .set def = mdata ? mdata.value : "" :>
-<: .if m.type eq 'image' :>
-<: .set def = file.meta_by_name(m.display_name).value :>
-<: .end if :>
-<: .if m.ro :>
+<: .set name = "meta_" _ m.name -:>
+<: .set mdata = file.meta_by_name(m.name) -:>
+<: .if m.type eq 'image' -:>
+<: .set def = file.meta_by_name(m.display_name) -:>
+<: .set def = def ? def.value_text : "" -:>
+<: .else -:>
+<: .set def = mdata ? mdata.value_text : "" -:>
+<: .end if -:>
+<: .if m.ro -:>
<: .call "inlinefieldro", name: name, field: m.field,
- options: { default: def } :>
-<: .else :>
+ options: { default: def } -:>
+<: .else -:>
<: .call "inlinefield", name: name, field: m.field,
- options: { delete: 1, default: def } :>
+ options: { delete: 1, default: def } -:>
<: .end if :>
-<: .end for :>
+<: .end for -:>
</fieldset>
<p class="buttons">
<input type="submit" name="a_save_file" value="Save File" />
<:# parameters:
name - the field name
field - a field, as an entry in fields
+ options - various options, including:
+ note - display this text as a note below the field
+ delete - add a delete checkbox
+ default - a custom default value, overrides object
-:>
<:.if field.is_hash -:>
<div>
- <label for="<:= name | html :>"><:= field.nolabel ? "" : field.description | html :>:</label>
+ <label for="<:= name :>"><:= field.nolabel ? "" : field.description | html :>:</label>
<span>
<:-.if field.readonly -:>
<:-.call "display", name:name, options: options -:>
<:-.if options.note -:>
<br /><:= options.note | raw :>
<:-.end if -:>
+ <:-.if options["delete"] -:>
+<br /><input type="checkbox" name="delete_<:= name :>" value="1" id="delete_<:= name :>"><label for="delete_<:= name :>">Delete</label>
+ <:-.end if -:>
</span>
</div>
<:.end if -:>
#!perl -w
use strict;
-use Test::More tests => 37;
+use Test::More tests => 38;
use_ok("BSE::Cfg");
use_ok("Squirrel::Template");
use_ok("BSE::Template");
use_ok("DevHelp::Date");
use_ok("DevHelp::Formatter");
use_ok("DevHelp::HTML");
+use_ok("DevHelp::Validate");
use_ok("BSE::Variables");
use_ok("BSE::TB::AuditLog");
use_ok("BSE::TB::Tag");