summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormorkt <>2014-12-22 11:14:18 +0100
committerYorhel <git@yorhel.nl>2014-12-22 11:20:39 +0100
commitac784a64d0f74f9e04ac41890075c411e50ca823 (patch)
treef527926f531975751563e3d9286ce02212152850 /lib
parentdf383d117908160d1a84ce4519edc0c9bcf08c3b (diff)
Initial implementation of a staff/seiyuu database
Diffstat (limited to 'lib')
-rw-r--r--lib/VNDB/DB/Chars.pm16
-rw-r--r--lib/VNDB/DB/Misc.pm13
-rw-r--r--lib/VNDB/DB/Staff.pm141
-rw-r--r--lib/VNDB/DB/VN.pm18
-rw-r--r--lib/VNDB/Handler/Chars.pm16
-rw-r--r--lib/VNDB/Handler/Misc.pm3
-rw-r--r--lib/VNDB/Handler/Staff.pm412
-rw-r--r--lib/VNDB/Handler/VNPage.pm61
-rw-r--r--lib/VNDB/Util/CommonHTML.pm9
-rw-r--r--lib/VNDB/Util/LayoutHTML.pm2
10 files changed, 669 insertions, 22 deletions
diff --git a/lib/VNDB/DB/Chars.pm b/lib/VNDB/DB/Chars.pm
index 86b3a859..272f9610 100644
--- a/lib/VNDB/DB/Chars.pm
+++ b/lib/VNDB/DB/Chars.pm
@@ -76,10 +76,11 @@ sub dbCharGet {
join(', ', @select), join(' ', @join), \%where
);
- if(@$r && $o{what} =~ /(vns|traits)/) {
+ if(@$r && $o{what} =~ /vns|traits|seiyuu/) {
my %r = map {
$_->{traits} = [];
$_->{vns} = [];
+ $_->{seiyuu} = [];
($_->{cid}, $_)
} @$r;
@@ -107,6 +108,19 @@ sub dbCharGet {
{ 'cv.cid IN(!l)' => [[keys %r]], $1 ? ('cv.vid = ?', $1) : () }
)});
}
+
+ if($o{what} =~ /seiyuu/) {
+ push @{$r{ delete $_->{cid} }{seiyuu}}, $_ for (@{$self->dbAll(q|
+ SELECT cs.cid, sr.sid, sa.name, sa.original, cs.note
+ FROM chars_seiyuu cs
+ JOIN staff_alias sa ON sa.id = cs.aid
+ JOIN staff_rev sr ON sr.id = sa.rid
+ JOIN staff s ON sr.id = s.latest
+ !W
+ ORDER BY sa.name|,
+ { 'cs.cid IN(!l)' => [[ keys %r ]], $o{vid} ? ('vid = ?' => $o{vid}) : () }
+ )});
+ }
}
return wantarray ? ($r, $np) : $r;
}
diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm
index 3155ca56..8927e1ec 100644
--- a/lib/VNDB/DB/Misc.pm
+++ b/lib/VNDB/DB/Misc.pm
@@ -27,7 +27,7 @@ sub dbStats {
sub dbItemEdit {
my($self, $type, $oid, %o) = @_;
- my $fun = {qw|v vn r release p producer c char|}->{$type};
+ my $fun = {qw|v vn r release p producer c char s staff|}->{$type};
$self->dbExec('SELECT edit_!s_init(?)', $fun, $oid);
$self->dbExec('UPDATE edit_revision !H', {
'requester = ?' => $o{uid}||$self->authInfo->{id},
@@ -41,6 +41,7 @@ sub dbItemEdit {
$self->dbProducerRevisionInsert(\%o) if $type eq 'p';
$self->dbReleaseRevisionInsert( \%o) if $type eq 'r';
$self->dbCharRevisionInsert( \%o) if $type eq 'c';
+ $self->dbStaffRevisionInsert( \%o) if $type eq 's';
return $self->dbRow('SELECT * FROM edit_!s_commit()', $fun);
}
@@ -60,10 +61,10 @@ sub dbRevisionGet {
$o{what} ||= '';
$o{releases} = 0 if !$o{type} || $o{type} ne 'v' || !$o{iid};
- my %tables = qw|v vn r releases p producers c chars|;
+ my %tables = qw|v vn r releases p producers c chars s staff|;
# what types should we join?
my @types = (
- !$o{type} ? ('v', 'r', 'p', 'c') :
+ !$o{type} ? qw(v r p c s) :
ref($o{type}) ? @{$o{type}} :
$o{type} ne 'v' ? $o{type} :
$o{releases} ? ('v', 'r') : 'v'
@@ -97,15 +98,17 @@ sub dbRevisionGet {
) : (),
$o{what} =~ /user/ ? 'JOIN users u ON h.requester = u.id' : (),
);
+ push @join, 'LEFT JOIN staff_alias sa ON sa.rid = sr.id AND sa.id = sr.aid' if grep /s/, @types;
+ my %tcolumns = qw(v vr.title r rr.title p pr.name c cr.name s sa.name);
my @select = (
qw|h.id h.type h.requester h.comments h.rev|,
q|extract('epoch' from h.added) as added|,
$o{what} =~ /user/ ? 'u.username' : (),
$o{what} =~ /item/ ? (
'COALESCE('.join(', ', map "${_}r.${_}id", @types).') AS iid',
- 'COALESCE('.join(', ', map /[pc]/ ? "${_}r.name" : "${_}r.title", @types).') AS ititle',
- 'COALESCE('.join(', ', map "${_}r.original", @types).') AS ioriginal',
+ 'COALESCE('.join(', ', map $tcolumns{$_}, @types).') AS ititle',
+ 'COALESCE('.join(', ', map /s/ ? 'sa.original' : "${_}r.original", @types).') AS ioriginal',
) : (),
);
diff --git a/lib/VNDB/DB/Staff.pm b/lib/VNDB/DB/Staff.pm
new file mode 100644
index 00000000..7a732c4d
--- /dev/null
+++ b/lib/VNDB/DB/Staff.pm
@@ -0,0 +1,141 @@
+
+package VNDB::DB::Staff;
+
+use strict;
+use warnings;
+use Exporter 'import';
+
+our @EXPORT = qw|dbStaffGet dbStaffRevisionInsert|;
+
+# options: results, page, id, aid, vid, search, rev
+# what: extended changes roles aliases
+sub dbStaffGet {
+ my $self = shift;
+ my %o = (
+ results => 10,
+ page => 1,
+ what => '',
+ @_
+ );
+
+ $o{search} =~ s/%//g if $o{search};
+
+ my %where = (
+ !$o{id} && !$o{rev} ? ( 's.hidden = FALSE' => 1 ) : (),
+ $o{id} ? ( ref $o{id} ? ('s.id IN(!l)' => [$o{id}]) : ('s.id = ?' => $o{id}) ) : (),
+ $o{aid} ? ( ref $o{aid} ? ('sa.id IN(!l)' => [$o{aid}]) : ('sa.id = ?' => $o{aid}) ) : (),
+ $o{vid} ? ( 'vr.vid = ?' => $o{vid}) : (),
+ $o{search} ?
+ ( '(sa.name ILIKE ? OR sa.original ILIKE ?)', [ map '%%'.$o{search}.'%%', 1..2 ] ) : (),
+ $o{char} ? ( 'LOWER(SUBSTR(sa.name, 1, 1)) = ?' => $o{char} ) : (),
+ defined $o{char} && !$o{char} ?
+ ( '(ASCII(sa.name) < 97 OR ASCII(sa.name) > 122) AND (ASCII(sa.name) < 65 OR ASCII(sa.name) > 90)' => 1 ) : (),
+ $o{rev} ? ( 'c.rev = ?' => $o{rev} ) : (),
+ );
+
+ my @join;
+ push @join, 'JOIN staff s ON '.($o{rev} ? 's.id = sr.sid' : 'sr.id = s.latest');
+ push @join, 'JOIN staff_alias sa ON sa.rid = sr.id'.($o{id}?' AND sa.id = sr.aid':'');
+ push @join, 'JOIN changes c ON c.id = sr.id' if $o{what} =~ /changes/ || $o{rev};
+ push @join, 'JOIN users u ON u.id = c.requester' if $o{what} =~ /changes/;
+ push @join,
+ 'JOIN vn_staff vs ON vs.aid = sa.id',
+ 'JOIN vn_rev vr ON vs.vid = vr.id',
+ 'JOIN vn v ON vr.id = v.latest' if $o{vid};
+# fetch both staff and seiyuu in one query
+# push @join, q|
+# LEFT JOIN vn_staff vs ON vs.aid = sa.id
+# LEFT JOIN (chars_seiyuu cs JOIN chars c ON cs.cid = c.latest)
+# ON cs.aid = sa.id
+# JOIN (vn_rev vr JOIN vn v ON vr.id = v.latest)
+# ON vs.vid = vr.id OR cs.vid = v.id
+# | if $o{vid};
+
+ my $select = 's.id, sr.aid, sa.name, sa.original, sr.gender, sr.lang, sr.id AS cid';
+ $select .= ', sr.desc, sr.l_wp, s.hidden, s.locked' if $o{what} =~ /extended/;
+ $select .= q|, extract('epoch' from c.added) as added, c.requester, c.comments, s.latest, u.username, c.rev, c.ihid, c.ilock| if $o{what} =~ /changes/;
+ $select .= ', vs.role, vs.note' if $o{vid};
+
+ my $order = $o{vid} ? 'ORDER BY vs.role ASC, sa.name ASC' : 'ORDER BY sa.name ASC';
+
+ my($r, $np) = $self->dbPage(\%o, q|
+ SELECT !s
+ FROM staff_rev sr
+ !s
+ !W
+ !s|,
+ $select, join(' ', @join), \%where, $order
+ );
+
+ if (@$r && $o{what} =~ /roles|aliases/) {
+ my %r = map {
+ $_->{roles} = [];
+ $_->{cast} = [];
+ $_->{aliases} = [];
+ ($_->{cid}, $_);
+ } @$r;
+ if ($o{what} =~ /roles/) {
+ push @{$r{ delete $_->{rid} }{roles}}, $_ for (@{$self->dbAll(q|
+ SELECT sa.rid, vr.vid, sa.name, v.c_released, vr.title, vr.original AS t_original, vs.role, vs.note
+ FROM vn_staff vs
+ JOIN vn_rev vr ON vr.id = vs.vid
+ JOIN vn v ON v.latest = vr.id
+ JOIN staff_alias sa ON vs.aid = sa.id
+ WHERE sa.rid IN(!l)
+ ORDER BY v.c_released ASC, vr.title ASC, vs.role ASC|, [ keys %r ]
+ )});
+ push @{$r{ delete $_->{rid} }{cast}}, $_ for (@{$self->dbAll(q|
+ SELECT sa.rid, vr.vid, sa.name, v.c_released, vr.title, vr.original AS t_original, cr.cid, cr.name AS c_name, cs.note
+ FROM chars_seiyuu cs
+ JOIN chars_rev cr ON cr.id = cs.cid
+ JOIN vn v ON v.id = cs.vid
+ JOIN vn_rev vr ON v.latest = vr.id
+ JOIN staff_alias sa ON cs.aid = sa.id
+ WHERE sa.rid IN(!l)
+ ORDER BY v.c_released ASC, vr.title ASC|, [ keys %r ]
+ )});
+ }
+ if ($o{what} =~ /aliases/) {
+ push @{$r{ delete $_->{rid} }{aliases}}, $_ for (@{$self->dbAll(q|
+ SELECT sa.id, sa.rid, sa.name, sa.original
+ FROM staff_alias sa
+ JOIN staff_rev sr ON sr.id = sa.rid
+ WHERE sr.id IN(!l) AND sr.aid <> sa.id
+ ORDER BY sa.name ASC|, [ keys %r ]
+ )});
+ }
+ }
+
+ return wantarray ? ($r, $np) : $r;
+}
+
+# Updates the edit_* tables, used from dbItemEdit()
+# Arguments: { columns in staff_rev and staff_alias},
+sub dbStaffRevisionInsert {
+ my($self, $o) = @_;
+
+ $self->dbExec('DELETE FROM edit_staff_aliases');
+ if ($o->{aid}) {
+ $self->dbExec(q|
+ INSERT INTO edit_staff_aliases (id, name, original) VALUES (?, ?, ?)|,
+ $o->{aid}, $o->{name}, $o->{original});
+ } else {
+ $o->{aid} = $self->dbRow(q|
+ INSERT INTO edit_staff_aliases (name, original) VALUES (?, ?) RETURNING id|,
+ $o->{name}, $o->{original})->{id};
+ }
+
+ my %staff = map exists($o->{$_}) ? (qq|"$_" = ?|, $o->{$_}) : (),
+ qw|aid image gender lang desc l_wp|;
+ $self->dbExec('UPDATE edit_staff !H', \%staff) if %staff;
+ for my $alias (@{$o->{aliases}}) {
+ if ($alias->[0]) {
+ $self->dbExec('INSERT INTO edit_staff_aliases (id, name, original) VALUES (!l)', $alias);
+ } else {
+ $self->dbExec('INSERT INTO edit_staff_aliases (name, original) VALUES (?, ?)',
+ $alias->[1], $alias->[2]);
+ }
+ }
+}
+
+1;
diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm
index 090f9ecb..f6635c07 100644
--- a/lib/VNDB/DB/VN.pm
+++ b/lib/VNDB/DB/VN.pm
@@ -7,7 +7,7 @@ use Exporter 'import';
use VNDB::Func 'gtintype', 'normalize_query';
use Encode 'decode_utf8';
-our @EXPORT = qw|dbVNGet dbVNRevisionInsert dbVNImageId dbScreenshotAdd dbScreenshotGet dbScreenshotRandom dbVNHasChar|;
+our @EXPORT = qw|dbVNGet dbVNRevisionInsert dbVNImageId dbScreenshotAdd dbScreenshotGet dbScreenshotRandom dbVNHasChar dbVNHasStaff|;
# Options: id, rev, char, search, length, lang, olang, plat, tag_inc, tag_exc, tagspoil,
@@ -225,6 +225,13 @@ sub dbVNRevisionInsert {
my $q = join ',', map '(?)', @{$o->{anime}};
$self->dbExec("INSERT INTO edit_vn_anime (aid) VALUES $q", @{$o->{anime}}) if @{$o->{anime}};
}
+
+ if($o->{credits}) {
+ $self->dbExec('DELETE FROM edit_vn_staff');
+ my $q = join ',', ('(?, ?, ?)') x @{$o->{credits}};
+ my @val = map @{$_}[0..2], @{$o->{credits}};
+ $self->dbExec("INSERT INTO edit_vn_staff (aid, role, note) VALUES $q", @val) if @val;
+ }
}
@@ -290,5 +297,14 @@ sub dbVNHasChar {
)->{exists};
}
+
+sub dbVNHasStaff {
+ my($self, $vid) = @_;
+ return $self->dbRow(
+ 'SELECT 1 AS exists FROM vn v JOIN vn_staff vs ON v.latest = vs.vid WHERE v.id = ?', $vid
+ )->{exists};
+}
+
+
1;
diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm
index 7ae95e43..cb829e4c 100644
--- a/lib/VNDB/Handler/Chars.pm
+++ b/lib/VNDB/Handler/Chars.pm
@@ -22,7 +22,7 @@ sub page {
my $r = $self->dbCharGet(
id => $id,
- what => 'extended traits vns'.($rev ? ' changes' : ''),
+ what => 'extended traits vns seiyuu'.($rev ? ' changes' : ''),
$rev ? ( rev => $rev ) : ()
)->[0];
return $self->resNotFound if !$r->{id};
@@ -61,6 +61,9 @@ sub page {
$_->{rid}?sprintf('[<a href="/r%d">r%d</a>]', $_->{rid}, $_->{rid}):'',
mt("_charrole_$_->{role}"), mt("_spoil_$_->{spoil}")), @{$_[0]};
}],
+ [ seiyuu => join => '<br />', split => sub {
+ map sprintf('<a href="/s%d">%s</a>', $_->{sid}, $_->{name}), @{$_[0]}
+ }],
);
}
@@ -226,6 +229,17 @@ sub charTable {
end;
}
+ if (@{$r->{seiyuu}}) {
+ Tr;
+ td class => 'key', mt '_charp_voice';
+ td;
+ for my $s (@{$r->{seiyuu}}) {
+ a href => "/s$s->{sid}", $s->{name}; br;
+ }
+ end;
+ end;
+ }
+
# description
if($r->{desc}) {
Tr class => 'nostripe';
diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm
index 357779bc..1540c5fe 100644
--- a/lib/VNDB/Handler/Misc.pm
+++ b/lib/VNDB/Handler/Misc.pm
@@ -11,7 +11,7 @@ use POSIX 'strftime';
TUWF::register(
qr{}, \&homepage,
- qr{(?:([upvrc])([1-9]\d*)/)?hist}, \&history,
+ qr{(?:([upvrcs])([1-9]\d*)/)?hist},\&history,
qr{d([1-9]\d*)}, \&docpage,
qr{setlang}, \&setlang,
qr{nospam}, \&nospam,
@@ -206,6 +206,7 @@ sub history {
$type eq 'p' ? $self->dbProducerGet(id => $id)->[0] :
$type eq 'r' ? $self->dbReleaseGet(id => $id)->[0] :
$type eq 'c' ? $self->dbCharGet(id => $id)->[0] :
+ $type eq 's' ? $self->dbStaffGet(id => $id)->[0] :
$type eq 'v' ? $self->dbVNGet(id => $id)->[0] : undef;
my $title = mt $type ? ('_hist_title_item', $obj->{title} || $obj->{name} || $obj->{username}) : '_hist_title';
return $self->resNotFound if $type && !$obj->{id};
diff --git a/lib/VNDB/Handler/Staff.pm b/lib/VNDB/Handler/Staff.pm
new file mode 100644
index 00000000..14f0b53d
--- /dev/null
+++ b/lib/VNDB/Handler/Staff.pm
@@ -0,0 +1,412 @@
+
+package VNDB::Handler::Staff;
+
+use strict;
+use warnings;
+use TUWF qw(:html :xml xml_escape);
+use VNDB::Func;
+
+TUWF::register(
+ qr{s([1-9]\d*)(?:\.([1-9]\d*))?} => \&page,
+ qr{s(?:([1-9]\d*)(?:\.([1-9]\d*))?/edit|/new)}
+ => \&edit,
+ qr{s/([a-z0]|all)} => \&list,
+ qr{v([1-9]\d*)/staff/edit} => \&vn_edit,
+ qr{xml/staff.xml} => \&staffxml,
+);
+
+sub page {
+ my($self, $id, $rev) = @_;
+
+ my $s = $self->dbStaffGet(
+ id => $id,
+ what => 'extended aliases roles'.($rev ? ' changes' : ''),
+ $rev ? ( rev => $rev ) : ()
+ )->[0];
+ return $self->resNotFound if !$s->{id};
+
+ $self->htmlHeader(title => $s->{name}, noindex => $rev);
+ $self->htmlMainTabs('s', $s) if $id;
+ return if $self->htmlHiddenMessage('s', $s);
+
+ if($rev) {
+ my $prev = $rev && $rev > 1 && $self->dbStaffGet(id => $id, rev => $rev-1, what => 'changes extended aliases')->[0];
+ $self->htmlRevision('s', $prev, $s,
+ [ name => diff => 1 ],
+ [ original => diff => 1 ],
+ [ gender => serialize => sub { mt "_gender_$_[0]" } ],
+ [ lang => serialize => sub { "$_[0] (".mt("_lang_$_[0]").')' } ],
+ [ l_wp => htmlize => sub {
+ $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink'
+ }],
+ [ desc => diff => qr/[ ,\n\.]/ ],
+# [ image => htmlize => sub {
+# return $_[0] ? sprintf '<img src="%s" />', imgurl(ch => $_[0]) : mt '_stdiff_image_none';
+# }],
+ [ aliases => join => '<br />', split => sub {
+ map sprintf('%s%s', $_->{name}, $_->{original} ? ' ('.$_->{original}.')' : ''), @{$_[0]};
+ }],
+ );
+ }
+
+ div class => 'mainbox';
+ $self->htmlItemMessage('s', $s);
+ div class => 'staffinfo';
+ h1 $s->{name};
+ h2 class => 'alttitle';
+ cssicon "gen $s->{gender}", mt "_gender_$s->{gender}" if $s->{gender} ne 'unknown';
+ txt $s->{original} if $s->{original};
+ end;
+
+ # info table
+ table class => 'stripe';
+
+# Tr;
+# td class => 'key', mt '_staff_gender';
+# td mt "_gender_$s->{gender}";
+# end;
+ Tr;
+ td class => 'key', mt '_staff_language';
+ td mt "_lang_$s->{lang}";
+ end;
+ if (@{$s->{aliases}}) {
+ Tr;
+ td class => 'key', mt '_staff_aliases';
+ td;
+ p;
+ foreach my $alias (@{$s->{aliases}}) {
+ txt $alias->{name};
+ txt ' ('.$alias->{original}.')' if $alias->{original};
+ br;
+ }
+ end;
+ end;
+ end;
+ }
+ if ($s->{l_wp}) {
+ Tr;
+ td colspan => 2;
+ a href => "http://en.wikipedia.org/wiki/$s->{l_wp}", mt '_staff_l_wp';
+ end;
+ end;
+ }
+ end 'table';
+ end;
+
+ # description
+ if($s->{desc}) {
+ div class => 'staffdesc';
+ h2 mt '_staff_bio';
+ p;
+ lit bb2html $s->{desc}, 0, 1;
+ end;
+ end;
+ }
+
+ if (@{$s->{roles}} || @{$s->{cast}}) {
+ div class => 'staffroles';
+ table class => 'stripe';
+ thead;
+ Tr;
+ td class => 'tc1', mt '_staff_col_role';
+ td class => 'tc2', mt '_staff_col_title';
+ td class => 'tc3', mt '_staff_col_released';
+ td class => 'tc4', mt '_staff_col_note';
+ end;
+ end;
+ foreach my $r (@{$s->{roles}}) {
+ Tr;
+ td class => 'tc1', mt '_credit_'.$r->{role};
+ td class => 'tc2'; a href => "/v$r->{vid}", title => $r->{t_original}, $r->{title}; end;
+ td class => 'tc3'; lit $self->{l10n}->datestr($r->{c_released}); end;
+ td class => 'tc4';
+ lit '('.mt('_staff_as').$r->{name}.') ' if $r->{name} ne $s->{name};
+ lit $r->{note};
+ end;
+ end;
+ }
+ if (@{$s->{cast}}) {
+ Tr;
+ td class => 'tc1', colspan => 4; b mt '_staff_col_cast'; end;
+ end;
+ }
+ foreach my $r (@{$s->{cast}}) {
+ Tr;
+ td class => 'tc1'; a href => "/c$r->{cid}", $r->{c_name}; end;
+ td class => 'tc2'; a href => "/v$r->{vid}", title => $r->{t_original}, $r->{title}; end;
+ td class => 'tc3'; lit $self->{l10n}->datestr($r->{c_released}); end;
+ td class => 'tc4';
+ lit '('.mt('_staff_as').$r->{name}.') ' if $r->{name} ne $s->{name};
+ lit $r->{note};
+ end;
+ end;
+ }
+ end 'table';
+ end
+ }
+ clearfloat;
+ end;
+
+ $self->htmlFooter;
+}
+
+
+sub edit {
+ my($self, $sid, $rev) = @_;
+
+ my $s = $sid && $self->dbStaffGet(id => $sid, what => 'changes extended aliases', $rev ? (rev => $rev) : ())->[0];
+ return $self->resNotFound if $sid && !$s->{id};
+ $rev = undef if !$s || $s->{cid} == $s->{latest};
+
+ return $self->htmlDenied if !$self->authCan('edit')
+ || $sid && (($s->{locked} || $s->{hidden}) && !$self->authCan('dbmod'));
+
+ my %b4 = !$sid ? () : (
+ (map { $_ => $s->{$_} } qw|aid name original gender lang desc l_wp ihid ilock|),
+ aliases => join('|||', map sprintf('%d,%s,%s', $_->{id}, $_->{name}, $_->{original}),
+ sort { $a->{name} <=> $b->{name} } @{$s->{aliases}}),
+ );
+ my $frm;
+
+ if ($self->reqMethod eq 'POST') {
+ return if !$self->authCheckCode;
+ $frm = $self->formValidate (
+ { post => 'aid', required => 0, template => 'int' },
+ { post => 'name', maxlength => 200 },
+ { post => 'original', required => 0, maxlength => 200, default => '' },
+ { post => 'desc', required => 0, maxlength => 5000, default => '' },
+ { post => 'gender', required => 0, default => 'unknown', enum => [qw|unknown m f|] },
+ { post => 'lang', enum => $self->{languages} },
+ { post => 'l_wp', required => 0, maxlength => 150, default => '' },
+ { post => 'image', required => 0, default => 0, template => 'int' },
+ { post => 'aliases', required => 0, maxlength => 5000, default => '' },
+ { post => 'editsum', required => 0, maxlength => 5000 },
+ { post => 'ihid', required => 0 },
+ { post => 'ilock', required => 0 },
+ );
+ push @{$frm->{_err}}, 'badeditsum' if !$frm->{editsum} || lc($frm->{editsum}) eq lc($frm->{desc});
+ my @aliases = map { /^(\d+),([^,]*),(.*)$/ ? [ $1, $2, $3 ]: () } split /\|\|\|/, $frm->{aliases};
+ if (!$frm->{_err}) {
+ # parse and normalize
+ $frm->{aliases} = join('|||', map sprintf('%d,%s,%s', @$_), @aliases);
+ $frm->{ihid} = $frm->{ihid} ?1:0;
+ $frm->{ilock} = $frm->{ilock}?1:0;
+
+ return $self->resRedirect("/s$sid", 'post')
+ if $sid && !grep $frm->{$_} ne $b4{$_}, keys %b4;
+ }
+ if(!$frm->{_err}) {
+ $frm->{aliases} = \@aliases;
+ my $nrev = $self->dbItemEdit ('s' => $sid ? $s->{cid} : undef, %$frm);
+ return $self->resRedirect("/s$nrev->{iid}.$nrev->{rev}", 'post');
+ }
+ }
+
+ $frm->{$_} //= $b4{$_} for keys %b4;
+ $frm->{editsum} //= sprintf 'Reverted to revision s%d.%d', $sid, $rev if $rev;
+ $frm->{lang} = 'ja' if !$sid && !defined $frm->{lang};
+
+ my $title = mt $s ? ('_staffe_title_edit', $s->{name}) : '_staffe_title_add';
+ $self->htmlHeader(title => $title, noindex => 1);
+ $self->htmlMainTabs('s', $s, 'edit') if $s;
+ $self->htmlEditMessage('s', $s, $title);
+ $self->htmlForm({ frm => $frm, action => $s ? "/s$sid/edit" : '/s/new', editsum => 1, upload => 1 },
+ staffe_geninfo => [ mt('_staffe_form_generalinfo'),
+ [ hidden => short => 'aid' ],
+ [ input => name => mt('_staffe_form_name'), short => 'name' ],
+ [ input => name => mt('_staffe_form_original'), short => 'original' ],
+ [ static => content => mt('_staffe_form_original_note') ],
+ [ text => name => mt('_staffe_form_note').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 4 ],
+ [ select => name => mt('_staffe_form_gender'),short => 'gender', options => [
+ map [ $_, mt("_gender_$_") ], qw(unknown m f) ] ],
+ [ select => name => mt('_staffe_form_lang'), short => 'lang',
+ options => [ map [ $_, "$_ (".mt("_lang_$_").')' ], sort @{$self->{languages}} ] ],
+ [ input => name => mt('_staffe_form_wikipedia'), short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' ],
+ [ static => content => '<br />' ],
+ ],
+
+ staffe_aliases => [ mt('_staffe_aliases'),
+ [ hidden => short => 'aliases' ],
+ [ static => nolabel => 1, content => sub {
+ table;
+ thead; Tr;
+ td class => 'tc_name', mt '_staffe_form_alias';
+ td class => 'tc_original', mt '_staffe_form_original_alias'; td; end;
+ end; end;
+ tbody id => 'alias_tbl';
+ # filled with javascript
+ end;
+ end;
+ h2 mt '_staffe_aliases_add';
+ table; Tr id => 'alias_new';
+ td class => 'tc_name';
+ input id => 'alias_name', type => 'text', class => 'text'; end;
+ td class => 'tc_original';
+ input id => 'alias_original', type => 'text', class => 'text'; end;
+ td class => 'tc_add';
+ a href => '#', mt '_js_add'; end;
+ end; end;
+ }],
+ ]);
+
+ $self->htmlFooter;
+}
+
+
+sub vn_edit {
+ my($self, $vid) = @_;
+
+ my $v = $self->dbVNGet(id => $vid, what => 'changes')->[0];
+ return $self->resNotFound if !$v->{id};
+
+ return $self->htmlDenied if !$self->authCan('edit')
+ || (($v->{locked} || $v->{hidden}) && !$self->authCan('dbmod'));
+
+ my $s = $self->dbStaffGet(vid => $vid);
+
+ my %b4 = (
+ vid => $vid,
+ credits => join('|||', map sprintf('%d-%s-%s', $_->{aid}, $_->{role}, $_->{note}), @$s),
+ );
+ my $frm;
+ if ($self->reqMethod eq 'POST') {
+ return if !$self->authCheckCode;
+ $frm = $self->formValidate (
+ { post => 'vid', required => 1, template => 'int' },
+ { post => 'credits', required => 0, maxlength => 5000, default => '' },
+ );
+ my @credits = map { /^(\d+)-([^-]+)-(.*)$/ ? [ $1, $2, $3 ]: () } split /\|\|\|/, $frm->{credits};
+ if (!$frm->{_err}) {
+ # parse and normalize
+ $frm->{credits} = join('|||', map sprintf('%d-%s-%s', @$_), @credits);
+
+ return $self->resRedirect("/v$vid/staff#staff", 'post')
+ if !grep $frm->{$_} ne $b4{$_}, keys %b4;
+
+ $frm->{credits} = \@credits;
+ $frm->{editsum} = 'Edit staff';
+ my $nrev = $self->dbItemEdit ('v' => $v->{cid}, %$frm);
+ return $self->resRedirect("/v$nrev->{iid}.$nrev->{rev}", 'post');
+ }
+ }
+ $frm->{$_} //= $b4{$_} for keys %b4;
+
+ my $title = mt ('_vnstaff_edit_title', $v->{title});
+ $self->htmlHeader(title => $title, noindex => 1);
+ $self->htmlMainTabs('v', $v, 'edit');
+ $self->htmlEditMessage('v', $v, $title);
+
+ $self->htmlForm({ frm => $frm, action => "/v$vid/staff/edit" },
+ vnstaffe_credits => [ mt('_vnstaff_edit_credits'),
+ [ hidden => short => 'vid' ],
+ [ hidden => short => 'credits' ],
+ [ static => nolabel => 1, content => sub {
+ table; tbody id => 'credits_tbl';
+ Tr id => 'credits_loading'; td colspan => '4', mt('_js_loading'); end;
+ end; end;
+ h2 mt '_vnstaffe_add';
+ table; Tr;
+ td class => 'tc_staff';
+ input id => 'credit_input', type => 'text', class => 'text'; end;
+ td colspan => 3, '';
+ end; end;
+ }],
+ ]);
+
+ $self->htmlFooter;
+}
+
+
+sub list {
+ my ($self, $char) = @_;
+
+ my $f = $self->formValidate(
+ { get => 'p', required => 0, default => 1, template => 'int' },
+ { get => 'q', required => 0, default => '' },
+ );
+ return $self->resNotFound if $f->{_err};
+
+ my ($list, $np) = $self->dbStaffGet(
+ $char ne 'all' ? ( char => $char ) : (),
+ $f->{q} ? ( search => $f->{q} ) : (),
+ results => 150,
+ page => $f->{p}
+ );
+
+ return $self->resRedirect('/s'.$list->[0]{id}, 'temp')
+ if $f->{q} && @$list == 1 && $f->{p} == 1;
+
+ $self->htmlHeader(title => mt '_sbrowse_title');
+
+ div class => 'mainbox';
+ h1 mt '_sbrowse_title';
+ form action => '/s/all', 'accept-charset' => 'UTF-8', method => 'get';
+ $self->htmlSearchBox('s', $f->{q});
+ end;
+ p class => 'browseopts';
+ for ('all', 'a'..'z', 0) {
+ a href => "/s/$_", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#';
+ }
+ end;
+ end;
+
+ my $pageurl = "/s/$char" . ($f->{q} ? "?q=$f->{q}" : '');
+ $self->htmlBrowseNavigate($pageurl, $f->{p}, $np, 't');
+ div class => 'mainbox staffbrowse';
+ h1 mt $f->{q} ? '_sbrowse_searchres' : '_sbrowse_list';
+ if(!@$list) {
+ p mt '_sbrowse_noresults';
+ } else {
+ # spread the results over 3 equivalent-sized lists
+ my $perlist = @$list/3 < 1 ? 1 : @$list/3;
+ for my $c (0..(@$list < 3 ? $#$list : 2)) {
+ ul;
+ for ($perlist*$c..($perlist*($c+1))-1) {
+ li;
+ my $gender = $list->[$_]{gender};
+ cssicon "gen $gender", mt "_gender_$gender" if $gender ne 'unknown';
+# cssicon 'lang '.$list->[$_]{lang}, mt "_lang_$list->[$_]{lang}";
+ a href => "/s$list->[$_]{id}",
+ title => $list->[$_]{original}, $list->[$_]{name};
+ end;
+ }
+ end;
+ }
+ }
+ clearfloat;
+ end 'div';
+ $self->htmlBrowseNavigate($pageurl, $f->{p}, $np, 'b');
+ $self->htmlFooter;
+}
+
+
+sub staffxml {
+ my $self = shift;
+
+ my $q = $self->formValidate(
+ { get => 'a', required => 0, multi => 1, template => 'int' },
+ { get => 's', required => 0, multi => 1, template => 'int' },
+ { get => 'q', required => 0, maxlength => 500 },
+ );
+ return $self->resNotFound if $q->{_err} || !(@{$q->{s}} || @{$q->{a}} || $q->{q});
+
+ my($list, $np) = $self->dbStaffGet(
+ @{$q->{s}} ? (id => $q->{s}) :
+ @{$q->{a}} ? (aid => $q->{a}) :
+ $q->{q} =~ /^s([1-9]\d*)/ ? (id => $1) :
+ (search => $q->{q}),
+ results => 10,
+ page => 1,
+ );
+
+ $self->resHeader('Content-type' => 'text/xml; charset=UTF-8');
+ xml;
+ tag 'staff', more => $np ? 'yes' : 'no';
+ for(@$list) {
+ tag 'item', id => $_->{id}, aid => $_->{aid}, $_->{name};
+ }
+ end;
+}
+
+1;
+__END__
diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm
index 7d170ce8..be3f8a4c 100644
--- a/lib/VNDB/Handler/VNPage.pm
+++ b/lib/VNDB/Handler/VNPage.pm
@@ -13,7 +13,7 @@ TUWF::register(
qr{v/rand} => \&rand,
qr{v([1-9]\d*)/rg} => \&rg,
qr{v([1-9]\d*)/releases} => \&releases,
- qr{v([1-9]\d*)/(chars)} => \&page,
+ qr{v([1-9]\d*)/(chars|staff)} => \&page,
qr{v([1-9]\d*)(?:\.([1-9]\d*))?} => \&page,
);
@@ -513,7 +513,8 @@ sub page {
my($self, $vid, $rev) = @_;
my $char = $rev && $rev eq 'chars';
- $rev = undef if $char;
+ my $staff = $rev && $rev eq 'staff';
+ $rev = undef if $char || $staff;
my $v = $self->dbVNGet(
id => $vid,
@@ -646,25 +647,38 @@ sub page {
end 'div'; # /mainbox
my $haschar = $self->dbVNHasChar($v->{id});
- if($haschar || $self->authCan('edit')) {
+ my $hasstaff = $self->dbVNHasStaff($v->{id});
+ if($haschar || $hasstaff || $self->authCan('edit')) {
ul class => 'maintabs notfirst';
- if($haschar) {
- li class => 'left '.(!$char ? ' tabselected' : ''); a href => "/v$v->{id}#main", name => 'main', mt '_vnpage_tab_main'; end;
- li class => 'left '.( $char ? ' tabselected' : ''); a href => "/v$v->{id}/chars#chars", name => 'chars', mt '_vnpage_tab_chars'; end;
+ if($haschar || $hasstaff) {
+ li class => 'left '.(!($char || $staff) && ' tabselected'); a href => "/v$v->{id}#main", name => 'main', mt '_vnpage_tab_main'; end;
+ if ($haschar) {
+ li class => 'left '.($char && ' tabselected'); a href => "/v$v->{id}/chars#chars", name => 'chars', mt '_vnpage_tab_chars'; end;
+ }
+ if ($hasstaff) {
+ li class => 'left '.($staff && ' tabselected'); a href => "/v$v->{id}/staff#staff", name => 'staff', mt '_vnpage_tab_staff'; end;
+ }
}
if($self->authCan('edit')) {
li; a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add'; end;
+ if(!$v->{locked}) {
+ li;
+ a href => "/v$v->{id}/staff/edit", mt $hasstaff ? '_vnpage_staff_edit' : '_vnpage_staff_add';
+ end;
+ }
li; a href => "/v$v->{id}/add", mt '_vnpage_rel_add'; end;
}
end;
}
- if(!$char) {
+ if($char) {
+ _chars($self, $haschar, $v);
+ } elsif ($staff) {
+ _staff($self, $hasstaff, $v);
+ } else {
_releases($self, $v, $r);
_stats($self, $v);
_screenshots($self, $v, $r) if @{$v->{screenshots}};
- } else {
- _chars($self, $haschar, $v);
}
$self->htmlFooter;
@@ -1070,5 +1084,34 @@ sub _chars {
}
+sub _staff {
+ my ($self, $has, $v) = @_;
+ my $l = $has && $self->dbStaffGet(vid => $v->{id}, results => 100);
+ return if !$has;
+ div class => 'mainbox';
+ table class => 'stripe';
+ thead;
+ Tr;
+ td class => 'tc1', mt '_staff_col_role';
+ td class => 'tc2', mt '_staff_col_credit';
+ td class => 'tc3', mt '_staff_col_note';
+ end;
+ end;
+ my $last_role = '';
+ for my $s (@$l) {
+ Tr;
+ td class => 'tc1', $s->{role} ne $last_role ? mt '_credit_'.$s->{role} : '';
+ td class => 'tc2';
+ a href => "/s$s->{id}", title => $s->{original}||$s->{name}, $s->{name};
+ end;
+ td class => 'tc3', $s->{note};
+ end;
+ $last_role = $s->{role};
+ }
+ end 'table';
+ end;
+}
+
+
1;
diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm
index d4bba99f..8474f9c7 100644
--- a/lib/VNDB/Util/CommonHTML.pm
+++ b/lib/VNDB/Util/CommonHTML.pm
@@ -27,7 +27,7 @@ sub htmlMainTabs {
return if $type eq 'g' && !$self->authCan('tagmod');
ul class => 'maintabs';
- if($type =~ /[uvrpc]/) {
+ if($type =~ /[uvrpcs]/) {
li $sel eq 'hist' ? (class => 'tabselected') : ();
a href => "/$id/hist", mt '_mtabs_hist';
end;
@@ -73,7 +73,7 @@ sub htmlMainTabs {
}
if( $type eq 'u' && ($self->authInfo->{id} && $obj->{id} == $self->authInfo->{id} || $self->authCan('usermod'))
- || $type =~ /[vrpc]/ && $self->authCan('edit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod'))
+ || $type =~ /[vrpcs]/ && $self->authCan('edit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod'))
|| $type =~ /[gi]/ && $self->authCan('tagmod')
) {
li $sel eq 'edit' ? (class => 'tabselected') : ();
@@ -284,8 +284,8 @@ sub revdiff {
# Arguments: v/r/p, obj
sub htmlEditMessage {
my($self, $type, $obj, $title, $copy) = @_;
- my $num = {v => 0, r => 1, p => 2, c => 3}->{$type};
- my $guidelines = {v => 2, r => 3, p => 4, c => 12}->{$type};
+ my $num = {v => 0, r => 1, p => 2, c => 3, 's' => 4}->{$type};
+ my $guidelines = {v => 2, r => 3, p => 4, c => 12, 's' => 16}->{$type};
div class => 'mainbox';
h1 $title;
@@ -423,6 +423,7 @@ sub htmlSearchBox {
a href => '/v/all', $sel eq 'v' ? (class => 'sel') : (), mt '_searchbox_vn';
a href => '/r', $sel eq 'r' ? (class => 'sel') : (), mt '_searchbox_releases';
a href => '/p/all', $sel eq 'p' ? (class => 'sel') : (), mt '_searchbox_producers';
+ a href => '/s/all', $sel eq 's' ? (class => 'sel') : (), mt '_searchbox_staff';
a href => '/c/all', $sel eq 'c' ? (class => 'sel') : (), mt '_searchbox_chars';
a href => '/g', $sel eq 'g' ? (class => 'sel') : (), mt '_searchbox_tags';
a href => '/i', $sel eq 'i' ? (class => 'sel') : (), mt '_searchbox_traits';
diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm
index 7de7f709..128a18c7 100644
--- a/lib/VNDB/Util/LayoutHTML.pm
+++ b/lib/VNDB/Util/LayoutHTML.pm
@@ -66,6 +66,7 @@ sub _menu {
b class => 'grayedout', '> '; a href => '/g', mt '_menu_tags'; br;
a href => '/r', mt '_menu_releases'; br;
a href => '/p/all', mt '_menu_producers'; br;
+ a href => '/s/all', mt '_menu_staff'; br;
a href => '/c/all', mt '_menu_characters'; br;
b class => 'grayedout', '> '; a href => '/i', mt '_menu_traits'; br;
a href => '/u/all', mt '_menu_users'; br;
@@ -102,6 +103,7 @@ sub _menu {
if($self->authCan('edit')) {
a href => '/v/add', mt '_menu_addvn'; br;
a href => '/p/new', mt '_menu_addproducer'; br;
+ a href => '/s/new', mt '_menu_addstaff'; br;
a href => '/c/new', mt '_menu_addcharacter'; br;
}
br;