summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-10-03 10:15:53 +0200
committerYorhel <git@yorhel.nl>2015-10-03 10:15:53 +0200
commitb75eff0f2cce2050c98ec946aac28b390020fdc5 (patch)
tree2e34fdd690cb06b5f5cb12dbecaa3919e0d16ec6
parent30caa944332fbbb9f6f5a4805f5beeee2b8a506c (diff)
Handle JSON data natively when processing form data
No more need for extra json_encode/json_decode calls, and the form_compare() function is more lenient w.r.t. integer/string comparison. This is the improvement I described in commit ed86cfd12b0bed7352e2be525b8e63cb4d6d5448
-rw-r--r--lib/VNDB/DB/VN.pm4
-rw-r--r--lib/VNDB/Func.pm18
-rw-r--r--lib/VNDB/Handler/Staff.pm14
-rw-r--r--lib/VNDB/Handler/VNEdit.pm39
-rw-r--r--lib/VNDB/Util/FormHTML.pm7
-rwxr-xr-xutil/vndb.pl5
6 files changed, 47 insertions, 40 deletions
diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm
index 54c410b5..5d404b28 100644
--- a/lib/VNDB/DB/VN.pm
+++ b/lib/VNDB/DB/VN.pm
@@ -259,14 +259,14 @@ sub dbVNRevisionInsert {
if($o->{credits}) {
$self->dbExec('DELETE FROM edit_vn_staff');
my $q = join ',', ('(?, ?, ?)') x @{$o->{credits}};
- my @val = map @{$_}[0..2], @{$o->{credits}};
+ my @val = map +($_->{aid}, $_->{role}, $_->{note}), @{$o->{credits}};
$self->dbExec("INSERT INTO edit_vn_staff (aid, role, note) VALUES $q", @val) if @val;
}
if($o->{seiyuu}) {
$self->dbExec('DELETE FROM edit_vn_seiyuu');
my $q = join ',', ('(?, ?, ?)') x @{$o->{seiyuu}};
- my @val = map @{$_}[0..2], @{$o->{seiyuu}};
+ my @val = map +($_->{aid}, $_->{cid}, $_->{note}), @{$o->{seiyuu}};
$self->dbExec("INSERT INTO edit_vn_seiyuu (aid, cid, note) VALUES $q", @val) if @val;
}
}
diff --git a/lib/VNDB/Func.pm b/lib/VNDB/Func.pm
index 02489980..b4848796 100644
--- a/lib/VNDB/Func.pm
+++ b/lib/VNDB/Func.pm
@@ -13,6 +13,7 @@ our @EXPORT = (@VNDBUtil::EXPORT, qw|
childtags charspoil imgpath imgurl fmtvote
json_encode json_decode script_json
mtvoiced mtani mtvnlen mtrlstat mtvnlstat mtbloodt
+ form_compare
|);
@@ -237,5 +238,22 @@ sub mtrlstat { !$_[0] ? mt '_unknown' : mt '_rlist_status_'.$_[0]; }
sub mtvnlstat{ !$_[0] ? mt '_unknown' : mt '_vnlist_status_'.$_[0]; }
sub mtbloodt { $_[0] eq 'unknown' ? mt '_unknown' : mt '_bloodt_'.$_[0]; }
+
+# Compare the keys in %$old with the keys in %$new. Returns 1 if a difference was found, 0 otherwise.
+sub form_compare {
+ my($old, $new) = @_;
+ for my $k (keys %$old) {
+ my($o, $n) = ($old->{$k}, $new->{$k});
+ return 1 if !defined $n || ref $o ne ref $n;
+ if(!ref $o) {
+ return 1 if $o ne $n;
+ } else { # 'json' template
+ return 1 if @$o != @$n;
+ return 1 if grep form_compare($o->[$_], $n->[$_]), 0..$#$o;
+ }
+ }
+ return 0;
+}
+
1;
diff --git a/lib/VNDB/Handler/Staff.pm b/lib/VNDB/Handler/Staff.pm
index fb4a22b3..58cd6299 100644
--- a/lib/VNDB/Handler/Staff.pm
+++ b/lib/VNDB/Handler/Staff.pm
@@ -189,7 +189,7 @@ sub edit {
my %b4 = !$sid ? () : (
(map { $_ => $s->{$_} } qw|name original gender lang desc l_wp l_site l_twitter l_anidb ihid ilock|),
primary => $s->{aid},
- aliases => json_encode [
+ aliases => [
map +{ aid => $_->{id}, name => $_->{name}, orig => $_->{original} },
sort { $a->{name} cmp $b->{name} } @{$s->{aliases}}
],
@@ -220,24 +220,20 @@ sub edit {
);
if(!$frm->{_err}) {
- my $aliases = json_decode $frm->{aliases};
- $aliases = [ sort { $a->{name} cmp $b->{name} } @$aliases ];
+ my $aliases = [ sort { $a->{name} cmp $b->{name} } @{$frm->{aliases}} ];
my %old_aliases = $sid ? ( map +($_->{id} => 1), @{$self->dbStaffAliasIds($sid)} ) : ();
$frm->{primary} = 0 unless exists $old_aliases{$frm->{primary}};
# reset aid to zero for newly added aliases.
$_->{aid} *= $old_aliases{$_->{aid}} ? 1 : 0 for (sort { $a->{name} cmp $b->{name} } @$aliases);
- $frm->{aliases} = json_encode $aliases;
+ $frm->{aliases} = $aliases;
$frm->{ihid} = $frm->{ihid} ?1:0;
$frm->{ilock} = $frm->{ilock}?1:0;
$frm->{aid} = $frm->{primary} if $sid;
$frm->{desc} = $self->bbSubstLinks($frm->{desc});
+ return $self->resRedirect("/s$sid", 'post') if $sid && !form_compare(\%b4, $frm);
- return $self->resRedirect("/s$sid", 'post')
- if $sid && !first { ($frm->{$_}//'') ne ($b4{$_}//'') } keys %b4;
-
- $frm->{aliases} = $aliases;
my $nrev = $self->dbItemEdit ('s' => $sid ? $s->{cid} : undef, %$frm);
return $self->resRedirect("/s$nrev->{iid}.$nrev->{rev}", 'post');
}
@@ -256,7 +252,7 @@ sub edit {
[ hidden => short => 'name' ],
[ hidden => short => 'original' ],
[ hidden => short => 'primary' ],
- [ hidden => short => 'aliases' ],
+ [ json => short => 'aliases' ],
$sid && @{$s->{aliases}} ?
[ static => content => mt('_staffe_form_different') ] : (),
[ static => label => mt('_staffe_form_names'), content => sub {
diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm
index 01a33241..e0a6643e 100644
--- a/lib/VNDB/Handler/VNEdit.pm
+++ b/lib/VNDB/Handler/VNEdit.pm
@@ -89,17 +89,17 @@ sub edit {
my %b4 = !$vid ? () : (
(map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai image img_nsfw ihid ilock|),
- credits => json_encode [
+ credits => [
map { my $c = $_; +{ map { $_ => $c->{$_} } qw|aid role note| } }
sort { $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } @{$v->{credits}}
],
- seiyuu => json_encode [
+ seiyuu => [
map { my $c = $_; +{ map { $_ => $c->{$_} } qw|aid cid note| } }
sort { $a->{aid} <=> $b->{aid} || $a->{cid} <=> $b->{cid} } @{$v->{seiyuu}}
],
anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}),
vnrelations => join('|||', map $_->{relation}.','.$_->{id}.','.($_->{official}?1:0).','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}),
- screenshots => json_encode [
+ screenshots => [
map +{ id => $_->{id}, nsfw => $_->{nsfw}?1:0, rid => $_->{rid} },
sort { $a->{id} <=> $b->{id} } @{$v->{screenshots}}
]
@@ -143,17 +143,15 @@ sub edit {
# handle image upload
$frm->{image} = _uploadimage($self, $frm) if !$nosubmit;
- my $raw_c = !$frm->{_err} && json_decode $frm->{credits};
- my $raw_s = !$frm->{_err} && json_decode $frm->{seiyuu};
my (@credits, @seiyuu);
if(!$nosubmit && !$frm->{_err}) {
# ensure submitted alias IDs exist within database
- my @alist = map $_->{aid}, @$raw_c, @$raw_s;
+ my @alist = map $_->{aid}, @{$frm->{credits}}, @{$frm->{seiyuu}};
my %staff = @alist ? map +($_->{aid}, 1), @{$self->dbStaffGet(aid => \@alist, results => 200)} : ();
# check for duplicate credits
my $last_c = { aid => 0, role => '' };
- for my $c (sort { $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } @$raw_c) {
+ for my $c (sort { $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } @{$frm->{credits}}) {
next unless exists $staff{0+$c->{aid}};
# discard entries with identical name & role
next if $last_c->{aid} == $c->{aid} && $last_c->{role} eq $c->{role};
@@ -162,10 +160,10 @@ sub edit {
}
# if character list is empty, any seiyuu data will be discarded
- if (@$chars && @$raw_s) {
+ if (@$chars && @{$frm->{seiyuu}}) {
my %vn_chars = map +($_->{id} => 1), @$chars;
my $last_s = { aid => 0, cid => 0 };
- for my $s (sort { $a->{aid} <=> $b->{aid} || $a->{cid} <=> $b->{cid} } @$raw_s) {
+ for my $s (sort { $a->{aid} <=> $b->{aid} || $a->{cid} <=> $b->{cid} } @{$frm->{seiyuu}}) {
next unless $staff{0+$s->{aid}} && $vn_chars{0+$s->{cid}}; # weed out odd credits
next if $last_s->{aid} == $s->{aid} && $last_s->{cid} == $s->{cid};
push @seiyuu, $s;
@@ -185,7 +183,6 @@ sub edit {
# parse and re-sort fields that have multiple representations of the same information
my $anime = { map +($_=>1), grep /^[0-9]+$/, split /[ ,]+/, $frm->{anime} };
my $relations = [ map { /^([a-z]+),([0-9]+),([01]),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3, $4 ] : () } split /\|\|\|/, $frm->{vnrelations} ];
- my $screenshots = json_decode $frm->{screenshots};
$frm->{ihid} = $frm->{ihid}?1:0;
$frm->{ilock} = $frm->{ilock}?1:0;
@@ -194,22 +191,18 @@ sub edit {
$frm->{anime} = join ' ', sort { $a <=> $b } keys %$anime;
$frm->{vnrelations} = join '|||', map $_->[0].','.$_->[1].','.($_->[2]?1:0).','.$_->[3], sort { $a->[1] <=> $b->[1]} @{$relations};
$frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0;
- $frm->{screenshots} = json_encode [ sort { $a->{id} <=> $b->{id} } @$screenshots ];
- $frm->{credits} = json_encode \@credits;
- $frm->{seiyuu} = json_encode \@seiyuu;
+ $frm->{screenshots} = [ sort { $a->{id} <=> $b->{id} } @{$frm->{screenshots}} ];
+ $frm->{credits} = \@credits;
+ $frm->{seiyuu} = \@seiyuu;
# nothing changed? just redirect
- return $self->resRedirect("/v$vid", 'post')
- if $vid && !grep $frm->{$_} ne $b4{$_}, keys %b4;
+ return $self->resRedirect("/v$vid", 'post') if $vid && !form_compare(\%b4, $frm);
# perform the edit/add
my $nrev = $self->dbItemEdit(v => $vid ? $v->{cid} : undef,
- (map { $_ => $frm->{$_} } qw|title original image alias desc length l_wp l_encubed l_renai editsum img_nsfw ihid ilock|),
- credits => [ map [ @{$_}{qw|aid role note|} ], @credits ],
- seiyuu => [ map [ @{$_}{qw|aid cid note|} ], @seiyuu ],
+ (map { $_ => $frm->{$_} } qw|title original image alias desc length l_wp l_encubed l_renai editsum img_nsfw ihid ilock credits seiyuu screenshots|),
anime => [ keys %$anime ],
relations => $relations,
- screenshots => $screenshots,
);
# update reverse relations & relation graph
@@ -324,7 +317,7 @@ sub _form {
}]],
vn_staff => [ mt('_vnedit_staff'),
- [ hidden => short => 'credits' ],
+ [ json => short => 'credits' ],
[ static => nolabel => 1, content => sub {
# propagate staff ids and names to javascript
my %staff_data;
@@ -352,7 +345,7 @@ sub _form {
# There's no way to add voice actors in new VN edits since character list
# would be empty anyway.
@{$chars} ? (vn_cast => [ mt('_vnedit_cast'),
- [ hidden => short => 'seiyuu' ],
+ [ json => short => 'seiyuu' ],
[ static => nolabel => 1, content => sub {
if (@$import) {
script_json castimpdata => [
@@ -426,9 +419,9 @@ sub _form {
vn_scr => [ mt('_vnedit_scr'), !@$r ? (
[ static => nolabel => 1, content => mt '_vnedit_scrnorel' ],
) : (
- [ hidden => short => 'screenshots' ],
+ [ json => short => 'screenshots' ],
[ static => nolabel => 1, content => sub {
- my @scr = map $_->{id}, @{ json_decode $frm->{screenshots} };
+ my @scr = map $_->{id}, @{$frm->{screenshots}};
my %scr = map +($_->{id}, [ $_->{width}, $_->{height}]), @scr ? @{$self->dbScreenshotGet(\@scr)} : ();
my @rels = map [ $_->{id}, sprintf '[%s] %s (r%d)', join(',', @{$_->{languages}}), $_->{title}, $_->{id} ], @$r;
script_json screendata => {
diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm
index 611fdf46..9612f904 100644
--- a/lib/VNDB/Util/FormHTML.pm
+++ b/lib/VNDB/Util/FormHTML.pm
@@ -62,6 +62,7 @@ sub htmlFormError {
# and all other elements forming a hash with options specific to that type.
# Type Options
# hidden short, (value)
+# json short, (value) # Same as hidden, but value is passed through json_encode()
# input short, name, (width, pre, post)
# passwd short, name
# static content, (label, nolabel)
@@ -71,16 +72,16 @@ sub htmlFormError {
# text name, short, (rows, cols)
# date name, short
# part title
-# TODO: Find a way to write this function in a readable way...
sub htmlFormPart {
my($self, $frm, $fp) = @_;
my($type, %o) = @$fp;
local $_ = $type;
- if(/hidden/) {
+ if(/hidden/ || /json/) {
Tr class => 'hidden';
td colspan => 2;
- input type => 'hidden', id => $o{short}, name => $o{short}, value => $o{value}||$frm->{$o{short}}||'';
+ my $val = $o{value}||$frm->{$o{short}};
+ input type => 'hidden', id => $o{short}, name => $o{short}, value => /json/ ? json_encode($val||[]) : $val||'';
end;
end;
return
diff --git a/util/vndb.pl b/util/vndb.pl
index ca731ca2..3ca6604f 100755
--- a/util/vndb.pl
+++ b/util/vndb.pl
@@ -55,7 +55,7 @@ TUWF::set(
uname => { regex => qr/^[a-z0-9-]*$/, minlength => 2, maxlength => 15 },
gtin => { func => \&gtintype },
editsum => { maxlength => 5000, minlength => 2 },
- json => { func => \&json_validate, inherit => ['json_fields'], default => '[]' },
+ json => { func => \&json_validate, inherit => ['json_fields'], default => [] },
},
);
TUWF::load_recursive('VNDB::Util', 'VNDB::DB', 'VNDB::Handler');
@@ -141,6 +141,7 @@ sub json_validate {
my($val, $opts) = @_;
my $fields = $opts->{json_fields};
my $data = eval { json_decode $val };
+ $_[0] = $@ ? [] : $data;
return 0 if $@ || ref $data ne 'ARRAY';
my %known_fields = map +($_->{field},1), @$fields;
for my $i (0..$#$data) {
@@ -150,7 +151,5 @@ sub json_validate {
$data->[$i] = kv_validate({ field => sub { $data->[$i]{shift()} } }, $TUWF::OBJ->{_TUWF}{validate_templates}, $fields);
return 0 if $data->[$i]{_err};
}
-
- $_[0] = json_encode $data;
return 1;
}