summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2011-05-01 11:13:42 +0200
committerYorhel <git@yorhel.nl>2011-05-01 11:13:42 +0200
commit2e73fe7c7a174f3349786a69684f6a70101a57c0 (patch)
tree6701c7ca4429a7f59d5d2cd08bf98d8a143aced5 /lib
parentee977448037feeb53736f35809722dd16d3d3d91 (diff)
parent2bf4818105a11abeca313b36d820c3cc397dc5b3 (diff)
Merge branch 'beta'2.20
Conflicts: ChangeLog
Diffstat (limited to 'lib')
-rw-r--r--lib/Multi/Core.pm2
-rw-r--r--lib/Multi/Maintenance.pm18
-rw-r--r--lib/VNDB/DB/Affiliates.pm69
-rw-r--r--lib/VNDB/DB/Misc.pm3
-rw-r--r--lib/VNDB/DB/Releases.pm2
-rw-r--r--lib/VNDB/DB/Users.pm4
-rw-r--r--lib/VNDB/Handler/Affiliates.pm146
-rw-r--r--lib/VNDB/Handler/Chars.pm12
-rw-r--r--lib/VNDB/Handler/Misc.pm7
-rw-r--r--lib/VNDB/Handler/Producers.pm2
-rw-r--r--lib/VNDB/Handler/Releases.pm2
-rw-r--r--lib/VNDB/Handler/Traits.pm6
-rw-r--r--lib/VNDB/Handler/ULists.pm3
-rw-r--r--lib/VNDB/Handler/Users.pm20
-rw-r--r--lib/VNDB/Handler/VNEdit.pm64
-rw-r--r--lib/VNDB/Handler/VNPage.pm49
-rw-r--r--lib/VNDB/Util/Auth.pm5
-rw-r--r--lib/VNDB/Util/CommonHTML.pm17
-rw-r--r--lib/VNDB/Util/FormHTML.pm6
-rw-r--r--lib/VNDB/Util/LayoutHTML.pm13
-rw-r--r--lib/VNDBUtil.pm8
21 files changed, 372 insertions, 86 deletions
diff --git a/lib/Multi/Core.pm b/lib/Multi/Core.pm
index 9eaa6269..3c9d8bae 100644
--- a/lib/Multi/Core.pm
+++ b/lib/Multi/Core.pm
@@ -98,7 +98,7 @@ sub log_msg { # msg
sub log { # level, msg
(my $p = eval { $_[SENDER][2]{$_[CALLER_STATE]}[0] } || '') =~ s/^Multi:://;
log_msg sprintf '%s::%s: %s', $p, $_[CALLER_STATE],
- $_[ARG1] ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0];
+ $#_>ARG0 ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0];
}
diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm
index 5b092d0a..33154f9b 100644
--- a/lib/Multi/Maintenance.pm
+++ b/lib/Multi/Maintenance.pm
@@ -18,13 +18,13 @@ sub spawn {
package_states => [
$p => [qw|
_start shutdown set_daily daily set_monthly monthly log_stats
- vncache_inc tagcache vnpopularity vnrating cleangraphs cleansessions cleannotifications
+ vncache_inc tagcache traitcache vnpopularity vnrating cleangraphs cleansessions cleannotifications
vncache_full usercache statscache logrotate
vnsearch_check vnsearch_gettitles vnsearch_update
|],
],
heap => {
- daily => [qw|vncache_inc tagcache vnpopularity vnrating cleangraphs cleansessions cleannotifications|],
+ daily => [qw|vncache_inc tagcache traitcache vnpopularity vnrating cleangraphs cleansessions cleannotifications|],
monthly => [qw|vncache_full usercache statscache logrotate|],
vnsearch_checkdelay => 3600,
@_,
@@ -46,6 +46,7 @@ sub _start {
sub shutdown {
$_[KERNEL]->delay('daily');
$_[KERNEL]->delay('monthly');
+ $_[KERNEL]->delay('vnsearch_check');
$_[KERNEL]->alias_remove('maintenance');
}
@@ -121,13 +122,19 @@ sub vncache_inc {
sub tagcache {
- # takes about 2 seconds max, still OK
+ # takes about 5 seconds max, still OK
$_[KERNEL]->post(pg => do => 'SELECT tag_vn_calc()', undef, 'log_stats', 'tagcache');
}
+sub traitcache {
+ # still takes less than a second
+ $_[KERNEL]->post(pg => do => 'SELECT traits_chars_calc()', undef, 'log_stats', 'traitcache');
+}
+
+
sub vnpopularity {
- # still takes at most 3 seconds. let's hope that doesn't increase...
+ # takes a bit more than 8 seconds, meh...
$_[KERNEL]->post(pg => do => 'SELECT update_vnpopularity()', undef, 'log_stats', 'vnpopularity');
}
@@ -216,6 +223,9 @@ sub statscache {
q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM vn WHERE hidden = FALSE) WHERE section = 'vn'|,
q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM releases WHERE hidden = FALSE) WHERE section = 'releases'|,
q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM producers WHERE hidden = FALSE) WHERE section = 'producers'|,
+ q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM chars WHERE hidden = FALSE) WHERE section = 'chars'|,
+ q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM tags WHERE state = 2) WHERE section = 'tags'|,
+ q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM traits WHERE state = 2) WHERE section = 'traits'|,
q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM threads WHERE hidden = FALSE) WHERE section = 'threads'|,
q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM threads_posts WHERE hidden = FALSE
AND EXISTS(SELECT 1 FROM threads WHERE threads.id = tid AND threads.hidden = FALSE)) WHERE section = 'threads_posts'|
diff --git a/lib/VNDB/DB/Affiliates.pm b/lib/VNDB/DB/Affiliates.pm
new file mode 100644
index 00000000..51320b47
--- /dev/null
+++ b/lib/VNDB/DB/Affiliates.pm
@@ -0,0 +1,69 @@
+
+package VNDB::DB::Affiliates;
+
+use strict;
+use warnings;
+use POSIX 'strftime';
+use Exporter 'import';
+
+our @EXPORT = qw|dbAffiliateGet dbAffiliateEdit dbAffiliateDel dbAffiliateAdd|;
+
+
+# options: id rids affiliate hidden sort reverse
+# what: release
+sub dbAffiliateGet {
+ my($self, %o) = @_;
+ $o{sort} ||= 'id';
+ $o{reverse} //= 0;
+
+ my %where = (
+ $o{id} ? ('id = ?' => $o{id}) : (),
+ $o{rids} ? ('rid IN(!l)' => [$o{rids}]) : (),
+ defined($o{affiliate}) ? ('affiliate = ?' => $o{affiliate}) : (),
+ defined($o{hidden}) ? ('!s af.hidden' => $o{hidden} ? '' : 'NOT') : (),
+ );
+
+ my $join = $o{what} ? 'JOIN releases r ON r.id = af.rid JOIN releases_rev rr ON rr.id = r.latest' : '';
+ my $select = $o{what} ? ', rr.title' : '';
+
+ my $order = sprintf {
+ id => 'af.id %s',
+ rel => 'rr.title %s',
+ prio => 'af.priority %s',
+ url => 'af.url %s',
+ lastfetch => 'af.lastfetch %s',
+ }->{$o{sort}}, $o{reverse} ? 'DESC' : 'ASC';
+
+ return $self->dbAll(qq|
+ SELECT af.id, af.rid, af.hidden, af.priority, af.affiliate, af.url, af.version,
+ extract('epoch' from af.lastfetch) as lastfetch, af.price$select
+ FROM affiliate_links af
+ $join
+ !W
+ ORDER BY !s|, \%where, $order);
+}
+
+
+sub dbAffiliateDel {
+ my($self, $id) = @_;
+ $self->dbExec('DELETE FROM affiliate_links WHERE id = ?', $id);
+}
+
+
+sub dbAffiliateEdit {
+ my($self, $id, %ops) = @_;
+ my %set;
+ exists($ops{$_}) && ($set{"$_ = ?"} = $ops{$_}) for(qw|rid priority hidden affiliate url version|);
+ return if !keys %set;
+ $self->dbExec('UPDATE affiliate_links !H WHERE id = ?', \%set, $id);
+}
+
+sub dbAffiliateAdd {
+ my($self, %ops) = @_;
+ $self->dbExec('INSERT INTO affiliate_links (rid, priority, hidden, affiliate, url, version) VALUES(!l)',
+ [@ops{qw| rid priority hidden affiliate url version|}]);
+}
+
+
+1;
+
diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm
index 2f98abe2..3155ca56 100644
--- a/lib/VNDB/DB/Misc.pm
+++ b/lib/VNDB/DB/Misc.pm
@@ -64,6 +64,7 @@ sub dbRevisionGet {
# what types should we join?
my @types = (
!$o{type} ? ('v', 'r', 'p', 'c') :
+ ref($o{type}) ? @{$o{type}} :
$o{type} ne 'v' ? $o{type} :
$o{releases} ? ('v', 'r') : 'v'
);
@@ -73,7 +74,7 @@ sub dbRevisionGet {
q{((h.type = 'v' AND vr.vid = ?) OR (h.type = 'r' AND h.id = ANY(ARRAY(SELECT rv.rid FROM releases_vn rv WHERE rv.vid = ?))))} => [$o{iid}, $o{iid}],
) : (
$o{type} ? (
- 'h.type = ?' => $o{type} ) : (),
+ 'h.type IN(!l)' => [ ref($o{type})?$o{type}:[$o{type}] ] ) : (),
$o{iid} ? (
'!sr.!sid = ?' => [ $o{type}, $o{type}, $o{iid} ] ) : (),
),
diff --git a/lib/VNDB/DB/Releases.pm b/lib/VNDB/DB/Releases.pm
index bd2d5bd3..6f9465f8 100644
--- a/lib/VNDB/DB/Releases.pm
+++ b/lib/VNDB/DB/Releases.pm
@@ -12,7 +12,7 @@ our @EXPORT = qw|dbReleaseGet dbReleaseRevisionInsert|;
# Options: id vid pid rev released page results what med sort reverse date_before date_after
# plat lang olang type minage search resolution freeware doujin voiced ani_story ani_ero
-# What: extended changes vn producers platforms media
+# What: extended changes vn producers platforms media affiliates
# Sort: title released minage
sub dbReleaseGet {
my($self, %o) = @_;
diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm
index 17f360cc..abea9bec 100644
--- a/lib/VNDB/DB/Users.pm
+++ b/lib/VNDB/DB/Users.pm
@@ -55,7 +55,7 @@ sub dbUserGet {
qw|id username c_votes c_changes c_tags|,
q|extract('epoch' from registered) as registered|,
$o{what} =~ /extended/ ? (
- qw|mail rank salt ign_votes|,
+ qw|mail perm salt ign_votes|,
q|encode(passwd, 'hex') AS passwd|
) : (),
$o{what} =~ /hide_list/ ? 'up.value AS hide_list' : (),
@@ -118,7 +118,7 @@ sub dbUserEdit {
my %h;
defined $o{$_} && ($h{$_.' = ?'} = $o{$_})
- for (qw| username mail rank salt ign_votes |);
+ for (qw| username mail perm salt ign_votes |);
$h{'passwd = decode(?, \'hex\')'} = $o{passwd}
if defined $o{passwd};
diff --git a/lib/VNDB/Handler/Affiliates.pm b/lib/VNDB/Handler/Affiliates.pm
new file mode 100644
index 00000000..679d6ee2
--- /dev/null
+++ b/lib/VNDB/Handler/Affiliates.pm
@@ -0,0 +1,146 @@
+
+package VNDB::Handler::Affiliates;
+
+use strict;
+use warnings;
+use TUWF ':html';
+use VNDB::Func;
+
+
+TUWF::register(
+ qr{affiliates} => \&list,
+ qr{affiliates/del/([1-9]\d*)} => \&linkdel,
+ qr{affiliates/edit/([1-9]\d*)} => \&edit,
+ qr{affiliates/new} => \&edit,
+);
+
+
+sub list {
+ my $self = shift;
+
+ return $self->htmlDenied if !$self->authCan('affiliate');
+ my $f = $self->formValidate(
+ { get => 'a', required => 0, enum => [ 0..$#{$self->{affiliates}} ] },
+ { get => 'h', required => 0, default => 0, enum => [ -1..1 ] },
+ { get => 'o', required => 0, default => 'a', enum => ['a', 'd'] },
+ { get => 's', required => 0, default => 'rel', enum => [qw|rel prio url lastfetch|] },
+ );
+ return $self->resNotFound if $f->{_err};
+
+ $self->htmlHeader(title => 'Affiliate administration interface');
+ div class => 'mainbox';
+ h1 'Affiliate administration interface';
+ p class => 'browseopts';
+ a defined($f->{a}) && $f->{a} == $_ ? (class => 'optselected') : (), href => "/affiliates?a=$_", $self->{affiliates}[$_]{name}
+ for (grep $self->{affiliates}[$_], 0..$#{$self->{affiliates}});
+ end;
+ if(defined $f->{a}) {
+ p class => 'browseopts';
+ a $f->{h} == -1 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=-1",'all';
+ a $f->{h} == 1 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=1", 'hidden';
+ a $f->{h} == 0 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=0", 'non-hidden';
+ end;
+ }
+ end;
+
+ if(defined $f->{a}) {
+ my $list = $self->dbAffiliateGet(
+ affiliate => $f->{a}, hidden => $f->{h}==-1?undef:$f->{h},
+ what => 'release',
+ sort => $f->{s}, reverse => $f->{o} eq 'd'
+ );
+ $self->htmlBrowse(
+ items => $list,
+ nextpage => 0,
+ options => {p=>0, %$f},
+ pageurl => '',
+ sorturl => "/affiliates?a=$f->{a};h=$f->{h}",
+ header => [
+ ['Release', 'rel'],
+ ['Version'],
+ ['Hid'],
+ ['Prio', 'prio'],
+ ['Price / Lastfetch', 'lastfetch'],
+ ['', 'url' ]
+ ],
+ row => sub {
+ my($s, $n, $l) = @_;
+ Tr $n % 2 ? (class => 'odd') : ();
+ td class => 'tc1'; a href => "/r$l->{rid}", shorten $l->{title}, 50; end;
+ td class => 'tc2', $l->{version} || '<default>';
+ td class => 'tc3', $l->{hidden} ? 'YES' : 'no';
+ td class => 'tc4', $l->{priority};
+ td class => 'tc5', sprintf '%s / %s', $l->{price}, $l->{lastfetch} ? $self->{l10n}->age($l->{lastfetch}) : '-';
+ td class => 'tc6';
+ a href => $l->{url}, 'link';
+ txt ' | ';
+ a href => "/affiliates/edit/$l->{id}", 'edit';
+ txt ' | ';
+ a href => "/affiliates/del/$l->{id}?formcode=".$self->authGetCode("/affiliates/del/$l->{id}"), 'del';
+ end;
+ end;
+ },
+ );
+ }
+ $self->htmlFooter;
+}
+
+
+sub linkdel {
+ my($self, $id) = @_;
+ return $self->htmlDenied if !$self->authCan('affiliate');
+ return if !$self->authCheckCode;
+ my $l = $self->dbAffiliateGet(id => $id)->[0];
+ return $self->resNotFound if !$l;
+ $self->dbAffiliateDel($id);
+ $self->resRedirect("/affiliates?a=$l->{affiliate}");
+}
+
+
+sub edit {
+ my($self, $id) = @_;
+ return $self->htmlDenied if !$self->authCan('affiliate');
+
+ my $r = $id && $self->dbAffiliateGet(id => $id)->[0];
+ return $self->resNotFound if $id && !$r;
+
+ my $frm;
+ if($self->reqMethod eq 'POST') {
+ return if !$self->authCheckCode;
+ $frm = $self->formValidate(
+ { post => 'rid', required => 1, template => 'int' },
+ { post => 'priority', required => 0, default => 0, template => 'int' },
+ { post => 'hidden', required => 0, default => 0, enum => [0,1] },
+ { post => 'affiliate',required => 1, enum => [0..$#{$self->{affiliates}}] },
+ { post => 'url', required => 1 },
+ { post => 'version', required => 0, default => '' },
+ );
+ if(!$frm->{_err}) {
+ $self->dbAffiliateEdit($id, %$frm) if $id;
+ $self->dbAffiliateAdd(%$frm) if !$id;
+ return $self->resRedirect("/affiliates?a=$frm->{affiliate}", 'post');
+ }
+ }
+
+ if($id) {
+ $frm->{$_} = $r->{$_} for(qw|rid priority hidden affiliate url version|);
+ } else {
+ $frm->{rid} = $self->reqGet('rid');
+ }
+
+ $self->htmlHeader(title => 'Edit affiliate link');
+ $self->htmlForm({ frm => $frm, action => $id ? "/affiliates/edit/$id" : '/affiliates/new' }, 'blah' => [ 'Edit affiliate link',
+ [ input => short => 'rid', name => 'Release ID', width => 100 ],
+ [ input => short => 'priority', name => 'Priority', width => 50 ],
+ [ check => short => 'hidden', name => 'Hidden' ],
+ [ select => short => 'affiliate', name => 'Affiliate', options => [ map
+ [ $_, $self->{affiliates}[$_]{name} ], grep $self->{affiliates}[$_], 0..$#{$self->{affiliates}} ] ],
+ [ input => short => 'url', name => 'URL', width => 400 ],
+ [ input => short => 'version', name => 'Version', width => 400 ],
+ ]);
+ $self->htmlFooter;
+}
+
+
+1;
+
diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm
index 7968b66c..8edb6236 100644
--- a/lib/VNDB/Handler/Chars.pm
+++ b/lib/VNDB/Handler/Chars.pm
@@ -233,7 +233,7 @@ sub charTable {
td class => 'chardesc', colspan => 2;
h2 mt '_charp_description';
p;
- lit bb2html $r->{desc};
+ lit bb2html $r->{desc}, 0, 1;
end;
end;
end;
@@ -257,7 +257,7 @@ sub edit {
$rev = undef if !$r || $r->{cid} == $r->{latest};
return $self->htmlDenied if !$self->authCan('charedit')
- || $id && ($r->{locked} && !$self->authCan('lock') || $r->{hidden} && !$self->authCan('del'));
+ || $id && (($r->{locked} || $r->{hidden}) && !$self->authCan('dbmod'));
my %b4 = !$id ? () : (
(map +($_ => $r->{$_}), qw|name original alias desc image ihid ilock s_bust s_waist s_hip height weight bloodt gender main_spoil|),
@@ -331,14 +331,14 @@ sub edit {
$frm->{vns} = \@vns;
my $nrev = $self->dbItemEdit(c => !$copy && $id ? $r->{cid} : undef, %$frm);
-
- # TEMPORARY SOLUTION! I'll investigate more efficient solutions and incremental updates whenever I have more data
- $self->dbExec('SELECT traits_chars_calc()');
-
return $self->resRedirect("/c$nrev->{iid}.$nrev->{rev}", 'post');
}
}
+ if(!$id) {
+ my $vid = $self->formValidate({ get => 'vid', required => 1, template => 'int'});
+ $frm->{vns} //= "$vid->{vid}-0-0-primary" if !$vid->{_err};
+ }
$frm->{$_} //= $b4{$_} for keys %b4;
$frm->{editsum} //= sprintf 'Reverted to revision c%d.%d', $id, $rev if !$copy && $rev;
$frm->{editsum} = sprintf 'New character based on c%d.%d', $id, $r->{rev} if $copy;
diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm
index 8f5b4949..643af1cf 100644
--- a/lib/VNDB/Handler/Misc.pm
+++ b/lib/VNDB/Handler/Misc.pm
@@ -196,7 +196,7 @@ sub history {
{ get => 'p', required => 0, default => 1, template => 'int' },
{ get => 'm', required => 0, default => !$type, enum => [ 0, 1 ] },
{ get => 'h', required => 0, default => 0, enum => [ -1..1 ] },
- { get => 't', required => 0, default => '', enum => [qw|v r p c|] },
+ { get => 't', required => 0, default => '', enum => [qw|v r p c a|] },
{ get => 'e', required => 0, default => 0, enum => [ -1..1 ] },
{ get => 'r', required => 0, default => 0, enum => [ 0, 1 ] },
);
@@ -216,7 +216,7 @@ sub history {
what => 'item user',
$type && $type ne 'u' ? ( type => $type, iid => $id ) : (),
$type eq 'u' ? ( uid => $id ) : (),
- $f->{t} ? ( type => $f->{t} ) : (),
+ $f->{t} ? ( type => $f->{t} eq 'a' ? [qw|v r p|] : $f->{t} ) : (),
page => $f->{p},
results => 50,
auto => $f->{m},
@@ -250,7 +250,7 @@ sub history {
end;
}
if(!$type || $type eq 'u') {
- if($self->authCan('del')) {
+ if($self->authCan('dbmod')) {
p class => 'browseopts';
a $f->{h} == 1 ? (class => 'optselected') : (), href => $u->(h => 1), mt '_hist_filter_hidedel';
a $f->{h} == -1 ? (class => 'optselected') : (), href => $u->(h => -1), mt '_hist_filter_showdel';
@@ -262,6 +262,7 @@ sub history {
a $f->{t} eq 'r' ? (class => 'optselected') : (), href => $u->(t => 'r'), mt '_hist_filter_onlyreleases';
a $f->{t} eq 'p' ? (class => 'optselected') : (), href => $u->(t => 'p'), mt '_hist_filter_onlyproducers';
a $f->{t} eq 'c' ? (class => 'optselected') : (), href => $u->(t => 'c'), mt '_hist_filter_onlychars';
+ a $f->{t} eq 'a' ? (class => 'optselected') : (), href => $u->(t => 'a'), mt '_hist_filter_nochars';
end;
p class => 'browseopts';
a !$f->{e} ? (class => 'optselected') : (), href => $u->(e => 0), mt '_hist_filter_allactions';
diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm
index 5030c1a3..52db6edf 100644
--- a/lib/VNDB/Handler/Producers.pm
+++ b/lib/VNDB/Handler/Producers.pm
@@ -205,7 +205,7 @@ sub edit {
$rev = undef if !$p || $p->{cid} == $p->{latest};
return $self->htmlDenied if !$self->authCan('edit')
- || $pid && ($p->{locked} && !$self->authCan('lock') || $p->{hidden} && !$self->authCan('del'));
+ || $pid && (($p->{locked} || $p->{hidden}) && !$self->authCan('dbmod'));
my %b4 = !$pid ? () : (
(map { $_ => $p->{$_} } qw|type name original lang website desc alias ihid ilock|),
diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm
index 159b7c3f..dd2b278e 100644
--- a/lib/VNDB/Handler/Releases.pm
+++ b/lib/VNDB/Handler/Releases.pm
@@ -280,7 +280,7 @@ sub edit {
return $self->resNotFound if $vid && !$v->{id};
return $self->htmlDenied if !$self->authCan('edit')
- || $rid && ($r->{locked} && !$self->authCan('lock') || $r->{hidden} && !$self->authCan('del'));
+ || $rid && (($r->{locked} || $r->{hidden}) && !$self->authCan('dbmod'));
my $vn = $rid ? $r->{vn} : [{ vid => $vid, title => $v->{title} }];
my %b4 = !$rid ? () : (
diff --git a/lib/VNDB/Handler/Traits.pm b/lib/VNDB/Handler/Traits.pm
index 1f3c2872..ea599ed1 100644
--- a/lib/VNDB/Handler/Traits.pm
+++ b/lib/VNDB/Handler/Traits.pm
@@ -104,8 +104,7 @@ sub traitpage {
if(!@$chars) {
p; br; br; txt mt '_traitp_nochars'; end;
}
- # not really cached at the moment
- # p; br; txt mt '_traitp_cached'; end;
+ p; br; txt mt '_traitp_cached'; end;
end 'div';
@$chars && $self->charBrowseTable($chars, $np, $f, "/i$trait?m=$f->{m}");
@@ -171,9 +170,6 @@ sub traitedit {
} else {
$self->dbTraitEdit($trait, %opts, upddate => $frm->{state} == 2 && $t->{state} != 2) if $trait;
_set_childs_group($self, $trait, $group||$trait) if ($group||0) != ($t->{group}||0);
-
- # TEMPORARY SOLUTION! I'll investigate more efficient solutions and incremental updates whenever I have more data
- $self->dbExec('SELECT traits_chars_calc()');
}
$self->resRedirect("/i$trait", 'post');
return;
diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm
index 363c2262..1c82d982 100644
--- a/lib/VNDB/Handler/ULists.pm
+++ b/lib/VNDB/Handler/ULists.pm
@@ -239,6 +239,7 @@ sub wishlist {
{ post => 'sel', required => 0, default => 0, multi => 1, template => 'int' },
{ post => 'batchedit', required => 1, enum => [ -1, @{$self->{wishlist_status}} ] },
);
+ $frm->{sel} = [ grep $_, @{$frm->{sel}} ]; # weed out "select all" checkbox
if(!$frm->{_err} && @{$frm->{sel}} && $frm->{sel}[0]) {
$self->dbWishListDel($uid, $frm->{sel}) if $frm->{batchedit} == -1;
$self->dbWishListAdd($frm->{sel}, $uid, $frm->{batchedit}) if $frm->{batchedit} >= 0;
@@ -303,6 +304,8 @@ sub wishlist {
$own ? (footer => sub {
Tr;
td colspan => 3;
+ input type => 'checkbox', class => 'checkall', name => 'sel', value => 0;
+ txt ' ';
Select name => 'batchedit', id => 'batchedit';
option mt '_wishlist_select';
optgroup label => mt '_wishlist_changeprio';
diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm
index 75ddb547..dc748f75 100644
--- a/lib/VNDB/Handler/Users.pm
+++ b/lib/VNDB/Handler/Users.pm
@@ -301,7 +301,7 @@ sub edit {
$frm = $self->formValidate(
$self->authCan('usermod') ? (
{ post => 'usrname', template => 'pname', minlength => 2, maxlength => 15 },
- { post => 'rank', enum => [ 1..$#{$self->{user_ranks}} ] },
+ { post => 'perms', required => 0, multi => 1, enum => [ keys %{$self->{permissions}} ] },
{ post => 'ign_votes', required => 0, default => 0 },
) : (),
{ post => 'mail', template => 'mail' },
@@ -318,7 +318,10 @@ sub edit {
$self->dbUserPrefSet($uid, $_ => $frm->{$_}) for (qw|skin customcss show_nsfw hide_list |);
my %o;
$o{username} = $frm->{usrname} if $frm->{usrname};
- $o{rank} = $frm->{rank} if $frm->{rank};
+ if($self->authCan('usermod')) {
+ $o{perm} = 0;
+ $o{perm} += $self->{permissions}{$_} for(@{ delete $frm->{perms} });
+ }
$o{mail} = $frm->{mail};
($o{passwd}, $o{salt}) = $self->authPreparePass($frm->{usrpass}) if $frm->{usrpass};
$o{ign_votes} = $frm->{ign_votes} ? 1 : 0 if $self->authCan('usermod');
@@ -330,8 +333,9 @@ sub edit {
}
# fill out default values
- $frm->{usrname} ||= $u->{username};
- $frm->{$_} ||= $u->{$_} for(qw|rank mail|);
+ $frm->{usrname} ||= $u->{username};
+ $frm->{mail} ||= $u->{mail};
+ $frm->{perms} ||= [ grep $u->{perm} & $self->{permissions}{$_}, keys %{$self->{permissions}} ];
$frm->{$_} //= $u->{prefs}{$_} for(qw|skin customcss show_nsfw hide_list|);
$frm->{ign_votes} = $u->{ign_votes} if !defined $frm->{ign_votes};
@@ -350,8 +354,8 @@ sub edit {
[ part => title => mt '_usere_geninfo' ],
$self->authCan('usermod') ? (
[ input => short => 'usrname', name => mt('_usere_username') ],
- [ select => short => 'rank', name => mt('_usere_rank'), options => [
- map [ $_, mt '_urank_'.$_ ], 1..$#{$self->{user_ranks}} ] ],
+ [ select => short => 'perms', name => mt('_usere_perm'), multi => 1, size => (scalar keys %{$self->{permissions}}), options => [
+ map [ $_, $_ ], sort keys %{$self->{permissions}} ] ],
[ check => short => 'ign_votes', name => mt '_usere_ignvotes' ],
) : (
[ static => label => mt('_usere_username'), content => $frm->{usrname} ],
@@ -611,7 +615,7 @@ sub notifies {
class => 'notifies',
pageurl => "/u$uid/notifies?r=$f->{r}",
header => [
- [ '<input type="checkbox" class="checkall" name="notifysel" value="0" />' ],
+ [ '' ],
[ mt '_usern_col_type' ],
[ mt '_usern_col_age' ],
[ mt '_usern_col_id' ],
@@ -639,6 +643,8 @@ sub notifies {
footer => sub {
Tr;
td colspan => 5;
+ input type => 'checkbox', class => 'checkall', name => 'notifysel', value => 0;
+ txt ' ';
input type => 'submit', name => 'markread', value => mt '_usern_but_markread';
input type => 'submit', name => 'remove', value => mt '_usern_but_remove';
b class => 'grayedout', ' '.mt '_usern_autodel';
diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm
index ce564fc0..d0848c09 100644
--- a/lib/VNDB/Handler/VNEdit.pm
+++ b/lib/VNDB/Handler/VNEdit.pm
@@ -23,12 +23,12 @@ sub edit {
$rev = undef if !$vid || $v->{cid} == $v->{latest};
return $self->htmlDenied if !$self->authCan('edit')
- || $vid && ($v->{locked} && !$self->authCan('lock') || $v->{hidden} && !$self->authCan('del'));
+ || $vid && (($v->{locked} || $v->{hidden}) && !$self->authCan('dbmod'));
my $r = $v ? $self->dbReleaseGet(vid => $v->{id}) : [];
my %b4 = !$vid ? () : (
- (map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn img_nsfw ihid ilock|),
+ (map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn image img_nsfw ihid ilock|),
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 => join(' ', map sprintf('%d,%d,%d', $_->{id}, $_->{nsfw}?1:0, $_->{rid}), @{$v->{screenshots}}),
@@ -48,7 +48,7 @@ sub edit {
{ post => 'l_renai', required => 0, default => '', maxlength => 100 },
{ post => 'l_vnn', required => 0, default => $b4{l_vnn}||0, template => 'int' },
{ post => 'anime', required => 0, default => '' },
- { post => 'previmage', required => 0, default => 0, template => 'int' },
+ { post => 'image', required => 0, default => 0, template => 'int' },
{ post => 'img_nsfw', required => 0, default => 0 },
{ post => 'vnrelations', required => 0, default => '', maxlength => 5000 },
{ post => 'screenshots', required => 0, default => '', maxlength => 1000 },
@@ -60,7 +60,7 @@ sub edit {
push @{$frm->{_err}}, 'badeditsum' if !$frm->{editsum} || lc($frm->{editsum}) eq lc($frm->{desc});
# handle image upload
- my $image = _uploadimage($self, $v, $frm);
+ $frm->{image} = _uploadimage($self, $v, $frm);
if(!$frm->{_err}) {
# parse and re-sort fields that have multiple representations of the same information
@@ -86,15 +86,13 @@ sub edit {
# nothing changed? just redirect
return $self->resRedirect("/v$vid", 'post')
- if $vid && !$self->reqPost('img') && $image == $v->{image}
- && !grep $frm->{$_} ne $b4{$_}, keys %b4;
+ if $vid && !grep $frm->{$_} ne $b4{$_}, keys %b4;
# perform the edit/add
my $nrev = $self->dbItemEdit(v => $vid ? $v->{cid} : undef,
- (map { $_ => $frm->{$_} } qw|title original alias desc length l_wp l_encubed l_renai l_vnn editsum img_nsfw ihid ilock|),
+ (map { $_ => $frm->{$_} } qw|title original image alias desc length l_wp l_encubed l_renai l_vnn editsum img_nsfw ihid ilock|),
anime => [ keys %$anime ],
relations => $relations,
- image => $image,
screenshots => $screenshots,
);
@@ -123,7 +121,7 @@ sub edit {
sub _uploadimage {
my($self, $v, $frm) = @_;
- return $v ? $frm->{previmage} : 0 if $frm->{_err} || !$self->reqPost('img');
+ return $v ? $frm->{image} : 0 if $frm->{_err} || !$self->reqPost('img');
# perform some elementary checks
my $imgdata = $self->reqUploadRaw('img');
@@ -163,29 +161,31 @@ sub _form {
[ static => content => mt '_vnedit_anime_msg' ],
],
- vn_img => [ mt('_vnedit_image'),
- [ hidden => short => 'previmage', value => $v ? $v->{image} : 0 ],
- [ static => nolabel => 1, content => sub {
- div class => 'img';
- p mt '_vnedit_image_none' if !$v || !$v->{image};
- p mt '_vnedit_image_processing' if $v && $v->{image} < 0;
- img src => sprintf("%s/cv/%02d/%d.jpg", $self->{url_static}, $v->{image}%100, $v->{image}), alt => $v->{title} if $v && $v->{image} > 0;
- end;
- div;
-
- h2 mt '_vnedit_image_upload';
- input type => 'file', class => 'text', name => 'img', id => 'img';
- p mt('_vnedit_image_upload_msg');
- br; br; br;
-
- h2 mt '_vnedit_image_nsfw';
- input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw',
- $frm->{img_nsfw} ? (checked => 'checked') : ();
- label class => 'checkbox', for => 'img_nsfw', mt '_vnedit_image_nsfw_check';
- p mt '_vnedit_image_nsfw_msg';
- end 'div';
- }],
- ],
+ vn_img => [ mt('_vnedit_image'), [ static => nolabel => 1, content => sub {
+ div class => 'img';
+ p mt '_vnedit_image_none' if !$v || !$v->{image};
+ p mt '_vnedit_image_processing' if $v && $v->{image} < 0;
+ img src => sprintf("%s/cv/%02d/%d.jpg", $self->{url_static}, $v->{image}%100, $v->{image}), alt => $v->{title} if $v && $v->{image} > 0;
+ end;
+
+ div;
+ h2 mt '_vnedit_image_id';
+ input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}||'';
+ p mt '_vnedit_image_id_msg';
+ br; br;
+
+ h2 mt '_vnedit_image_upload';
+ input type => 'file', class => 'text', name => 'img', id => 'img';
+ p mt('_vnedit_image_upload_msg');
+ br; br; br;
+
+ h2 mt '_vnedit_image_nsfw';
+ input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw',
+ $frm->{img_nsfw} ? (checked => 'checked') : ();
+ label class => 'checkbox', for => 'img_nsfw', mt '_vnedit_image_nsfw_check';
+ p mt '_vnedit_image_nsfw_msg';
+ end 'div';
+ }]],
vn_rel => [ mt('_vnedit_rel'),
[ hidden => short => 'vnrelations' ],
diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm
index 37efb04a..e10b4414 100644
--- a/lib/VNDB/Handler/VNPage.pm
+++ b/lib/VNDB/Handler/VNPage.pm
@@ -141,6 +141,7 @@ sub page {
_relations($self, \$i, $v) if @{$v->{relations}};
_anime($self, \$i, $v) if @{$v->{anime}};
_useroptions($self, \$i, $v) if $self->authInfo->{id};
+ _affiliate_links($self, $r);
Tr;
td class => 'vndesc', colspan => 2;
@@ -404,11 +405,56 @@ sub _useroptions {
}
+sub _affiliate_links {
+ my($self, $r) = @_;
+ return if !keys @$r;
+ my %r = map +($_->{id}, $_), @$r;
+ my $links = $self->dbAffiliateGet(rids => [ keys %r ], hidden => 0);
+ return if !@$links;
+
+ $links = [ sort { $b->{priority}||$self->{affiliates}[$b->{affiliate}]{default_prio} <=> $a->{priority}||$self->{affiliates}[$a->{affiliate}]{default_prio} } @$links ];
+ my $en = VNDB::L10N->get_handle('en');
+
+ Tr; td colspan => 2, id => 'buynow'; # don't call it "affiliate", most adblock filters have that included >_>
+ h1; a rel => 'nofollow', href => $self->{affiliates}[$links->[0]{affiliate}]{link_format} ? $self->{affiliates}[$links->[0]{affiliate}]{link_format}->($links->[0]{url}) : $links->[0]{url}, 'Buy now!'; end;
+ ul;
+ for my $link (@$links) {
+ my $f = $self->{affiliates}[$link->{affiliate}];
+
+ my $rel = $r{$link->{rid}};
+ my $plat = grep($_ eq 'win', @{$rel->{platforms}}) ? '' : ' '.join(' and ', map $en->maketext("_plat_$_"), @{$rel->{platforms}});
+ my $version = join(', ', map $en->maketext("_lang_$_"), @{$rel->{languages}}).$plat.' version';
+
+ li; a rel => 'nofollow', href => $f->{link_format} ? $f->{link_format}->($link->{url}) : $link->{url};
+ use utf8;
+ txt '→ ';
+ txt $link->{version}
+ || ($f->{default_version} && $f->{default_version}->($self, $link, $rel))
+ || $version;
+ txt ' ';
+ acronym class => 'pricenote', title => sprintf('Last updated: %s.', $en->age($link->{lastfetch})), "for $link->{price}*"
+ if $link->{price};
+ txt " at $f->{name}.";
+ end; end;
+ }
+ end;
+ end; end;
+}
+
+
sub _releases {
my($self, $v, $r) = @_;
div class => 'mainbox releases';
- a class => 'addnew', href => "/v$v->{id}/add", mt '_vnpage_rel_add';
+ if($self->authCan('edit')) {
+ p class => 'addnew';
+ if($self->authCan('charedit')) {
+ a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add';
+ txt ' | ';
+ }
+ a href => "/v$v->{id}/add", mt '_vnpage_rel_add';
+ end;
+ }
h1 mt '_vnpage_rel';
if(!@$r) {
p mt '_vnpage_rel_none';
@@ -459,6 +505,7 @@ sub _releases {
}
end;
td class => 'tc6';
+ a href => "/affiliates/new?rid=$rel->{id}", 'a' if $self->authCan('affiliate');
if($rel->{website}) {
a href => $rel->{website}, rel => 'nofollow';
cssicon 'ext', mt '_vnpage_rel_extlink';
diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm
index 88e68edc..89807bef 100644
--- a/lib/VNDB/Util/Auth.pm
+++ b/lib/VNDB/Util/Auth.pm
@@ -88,8 +88,7 @@ sub authInfo {
# a certain action. Argument is the action name as defined in global.pl
sub authCan {
my($self, $act) = @_;
- my $r = $self->{_auth} ? $self->{_auth}{rank} : 0;
- return scalar grep $_ eq $act, @{$self->{user_ranks}[$r]}[0..$#{$self->{user_ranks}[$r]}];
+ return $self->{_auth} ? $self->{_auth}{perm} & $self->{permissions}{$act} : 0;
}
@@ -102,7 +101,7 @@ sub _authCheck {
return 0 if !$user || length($user) > 15 || length($user) < 2 || !$pass;
my $d = $self->dbUserGet(username => $user, what => 'extended notifycount')->[0];
- return 0 if !defined $d->{id} || !$d->{rank};
+ return 0 if !$d->{id};
if(_authEncryptPass($self, $pass, $d->{salt}) eq $d->{passwd}) {
$self->{_auth} = $d;
diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm
index 41370b4b..5f2fb330 100644
--- a/lib/VNDB/Util/CommonHTML.pm
+++ b/lib/VNDB/Util/CommonHTML.pm
@@ -72,8 +72,8 @@ sub htmlMainTabs {
}
if( $type eq 'u' && ($self->authInfo->{id} && $obj->{id} == $self->authInfo->{id} || $self->authCan('usermod'))
- || $type =~ /[vrp]/ && $self->authCan('edit') && (!$obj->{locked} || $self->authCan('lock')) && (!$obj->{hidden} || $self->authCan('del'))
- || $type eq 'c' && $self->authCan('charedit') && (!$obj->{locked} || $self->authCan('lock')) && (!$obj->{hidden} || $self->authCan('del'))
+ || $type =~ /[vrp]/ && $self->authCan('edit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod'))
+ || $type eq 'c' && $self->authCan('charedit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod'))
|| $type =~ /[gi]/ && $self->authCan('tagmod')
) {
li $sel eq 'edit' ? (class => 'tabselected') : ();
@@ -143,7 +143,7 @@ sub htmlHiddenMessage {
end;
end;
end 'div';
- return $self->htmlFooter() || 1 if !$self->authCan('del');
+ return $self->htmlFooter() || 1 if !$self->authCan('dbmod');
return 0;
}
@@ -163,6 +163,15 @@ sub htmlRevision {
div class => 'mainbox revision';
h1 mt '_revision_title', $new->{rev};
+ # character information may be rather spoilerous
+ if($type eq 'c') {
+ div class => 'warning';
+ h2 mt '_revision_spoil_title';
+ lit mt '_revision_spoil_msg', "/c$new->{id}";
+ end;
+ br;br;
+ }
+
# previous/next revision links
a class => 'prev', href => sprintf('/%s%d.%d', $type, $new->{id}, $new->{rev}-1), '<- '.mt '_revision_previous'
if $new->{rev} > 1;
@@ -174,7 +183,7 @@ sub htmlRevision {
# no previous revision, just show info about the revision itself
if(!$old) {
- div;
+ div class => 'rev';
revheader($self, $type, $new);
br;
b mt '_revision_new_summary';
diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm
index 68b6a101..805467f6 100644
--- a/lib/VNDB/Util/FormHTML.pm
+++ b/lib/VNDB/Util/FormHTML.pm
@@ -214,15 +214,11 @@ sub htmlForm {
fieldset class => 'submit';
if($options->{editsum}) {
# hidden / locked checkbox
- if($self->authCan('del')) {
+ if($self->authCan('dbmod')) {
input type => 'checkbox', name => 'ihid', id => 'ihid', value => 1, $options->{frm}{ihid} ? (checked => 'checked') : ();
label for => 'ihid', mt '_form_ihid';
- }
- if($self->authCan('lock')) {
input type => 'checkbox', name => 'ilock', id => 'ilock', value => 1, $options->{frm}{ilock} ? (checked => 'checked') : ();
label for => 'ilock', mt '_form_ilock';
- }
- if($self->authCan('lock') || $self->authCan('del')) {
br; txt mt('_form_hidlock_note'); br;
}
diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm
index 22052a75..752f6728 100644
--- a/lib/VNDB/Util/LayoutHTML.pm
+++ b/lib/VNDB/Util/LayoutHTML.pm
@@ -89,7 +89,6 @@ sub _menu {
my $nc = $self->authInfo->{notifycount};
h2;
a href => $uid, ucfirst $self->authInfo->{username};
- txt ' ('.mt('_urank_'.$self->authInfo->{rank}).')';
end;
div;
a href => "$uid/edit", mt '_menu_myprofile'; br;
@@ -100,9 +99,13 @@ sub _menu {
a href => "$uid/hist", mt '_menu_mychanges'; br;
a href => '/g/links?u='.$self->authInfo->{id}, mt '_menu_mytags'; br;
br;
- a href => '/v/new', mt '_menu_addvn'; br;
- a href => '/p/new', mt '_menu_addproducer'; br;
- a href => '/c/new', mt '_menu_addcharacter'; br;
+ if($self->authCan('edit')) {
+ a href => '/v/new', mt '_menu_addvn'; br;
+ a href => '/p/new', mt '_menu_addproducer'; br;
+ }
+ if($self->authCan('charedit')) {
+ a href => '/c/new', mt '_menu_addcharacter'; br;
+ }
br;
a href => "$uid/logout", mt '_menu_logout';
end;
@@ -130,7 +133,7 @@ sub _menu {
h2 mt '_menu_dbstats';
div;
dl;
- for (qw|vn releases producers users threads posts|) {
+ for (qw|vn releases producers chars tags traits users threads posts|) {
dt mt "_menu_stat_$_";
dd $self->{stats}{$_};
}
diff --git a/lib/VNDBUtil.pm b/lib/VNDBUtil.pm
index a0469a1c..76290013 100644
--- a/lib/VNDBUtil.pm
+++ b/lib/VNDBUtil.pm
@@ -27,8 +27,7 @@ sub shorten {
# v+, v+.+
# http://../
sub bb2html {
- my $raw = shift;
- my $maxlength = shift;
+ my($raw, $maxlength, $charspoil) = @_;
$raw =~ s/\r//g;
return '' if !$raw && $raw ne "0";
@@ -76,7 +75,8 @@ sub bb2html {
next;
} elsif($tag eq '[spoiler]') {
push @open, 'spoiler';
- $result .= '<b class="spoiler">';
+ $result .= !$charspoil ? '<b class="spoiler">'
+ : '<b class="grayedout charspoil charspoil_-1">&lt;hidden by spoiler settings&gt;</b><span class="charspoil charspoil_2 hidden">';
next;
} elsif($tag eq '[quote]') {
push @open, 'quote';
@@ -89,7 +89,7 @@ sub bb2html {
$rmnewline = 1;
next;
} elsif($tag eq '[/spoiler]' && $open[$#open] eq 'spoiler') {
- $result .= '</b>';
+ $result .= !$charspoil ? '</b>' : '</span>';
pop @open;
next;
} elsif($tag eq '[/quote]' && $open[$#open] eq 'quote') {