summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--Makefile8
-rw-r--r--data/lang.txt25
-rw-r--r--data/script.js20
-rw-r--r--data/style.css2
-rw-r--r--lib/VNDB/DB/VN.pm11
-rw-r--r--lib/VNDB/Handler/VNEdit.pm20
-rw-r--r--lib/VNDB/Handler/VNPage.pm3
-rw-r--r--util/sql/func.sql4
-rw-r--r--util/sql/schema.sql1
-rw-r--r--util/updates/update_2.13.sql6
11 files changed, 73 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 2511fb99..6d3e1bf8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,7 @@
cross-site request forgery vulnerabilities
- URL change: /u/logout => /u$id/logout
- Added human confirmation question to the register page
+ - Added "official" flag to vn<->vn relations
- Optimized SQL queries:
- dbScreenshotRandom()
- dbVNGet() with random ordering
diff --git a/Makefile b/Makefile
index ccec9887..af42c25d 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@
# environments. Patches to improve the portability are always welcome.
-.PHONY: all dirs js skins robots chmod chmod-tladmin multi-start multi-stop multi-restart sql-import update-2.10 update-2.11 update-2.12
+.PHONY: all dirs js skins robots chmod chmod-tladmin multi-start multi-stop multi-restart sql-import update-2.10 update-2.11 update-2.12 update-2.13
all: dirs js skins robots data/config.pl
@@ -146,3 +146,9 @@ update-2.12: all
rm www/sitemap.xml.gz
${runpsql} < util/updates/update_2.12.sql
$(multi-start)
+
+update-2.13: all
+ $(multi-stop)
+ ${runpsql} < util/updates/update_2.13.sql
+ $(multi-start)
+
diff --git a/data/lang.txt b/data/lang.txt
index 41751efd..d5a4884a 100644
--- a/data/lang.txt
+++ b/data/lang.txt
@@ -5924,15 +5924,22 @@ cs : Přidat vztah
hu : Összefüggés hozzáadása
nl : Voeg relatie toe
-# <title1> is a <relation> of <title2>
+# <title1> is an [x] official <relation> of <title2>
# this trick doesn't even work very well in English, so just an approximation is fine
:_vnedit_rel_isa
-en : is a
+en : is an
ru : это
cs : je
hu : -
nl : is een
+:_vnedit_rel_official
+en : official
+ru*:
+cs*:
+hu*:
+nl : officiële
+
:_vnedit_rel_of
en : of
ru : для
@@ -6351,6 +6358,20 @@ cs : NSFW
hu : Nem munkabarát
nl : Niet veilig
+:_vndiff_rel_official
+en : official
+ru*:
+cs*:
+hu*:
+nl : officiëel
+
+:_vndiff_rel_unofficial
+en : unofficial
+ru*:
+cs*:
+hu*:
+nl : officieus
+
# VN page (/v+)
diff --git a/data/script.js b/data/script.js
index beac7926..e8367fce 100644
--- a/data/script.js
+++ b/data/script.js
@@ -797,8 +797,8 @@ function vnrLoad() {
// read the current relations
var rels = byId('vnrelations').value.split('|||');
for(var i=0; i<rels.length && rels[0].length>1; i++) {
- var rel = rels[i].split(',', 3);
- vnrAdd(rel[0], rel[1], rel[2]);
+ var rel = rels[i].split(',', 4);
+ vnrAdd(rel[0], rel[1], rel[2]==1?true:false, rel[3]);
}
vnrEmpty();
@@ -821,7 +821,7 @@ function vnrLoad() {
}, vnrFormAdd);
}
-function vnrAdd(rel, vid, title) {
+function vnrAdd(rel, vid, official, title) {
var sel = tag('select', {onchange: vnrSerialize});
var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options;
for(var i=0; i<ops.length; i++)
@@ -829,7 +829,11 @@ function vnrAdd(rel, vid, title) {
byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid},
tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))),
- tag('td', {'class':'tc_rel' }, mt('_vnedit_rel_isa')+' ', sel, ' '+mt('_vnedit_rel_of')),
+ tag('td', {'class':'tc_rel' },
+ mt('_vnedit_rel_isa')+' ',
+ tag('input', {type: 'checkbox', onclick:vnrSerialize, id:'official_'+vid, checked:official}),
+ tag('label', {'for':'official_'+vid}, mt('_vnedit_rel_official')),
+ sel, ' '+mt('_vnedit_rel_of')),
tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)),
tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, mt('_vnedit_rel_del')))
));
@@ -855,6 +859,7 @@ function vnrSerialize() {
r[r.length] = [
rel.options[rel.selectedIndex].value, // relation
trs[i].id.substr(12), // vid
+ byName(byClass(trs[i], 'td', 'tc_rel')[0], 'input')[0].checked ? '1' : '0', // official
getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title
].join(',');
}
@@ -874,6 +879,7 @@ function vnrDel() {
function vnrFormAdd() {
var relnew = byId('relation_new');
var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0];
+ var off = byName(byClass(relnew, 'td', 'tc_rel')[0], 'input')[0];
var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0];
var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0];
var input = txt.value;
@@ -883,12 +889,12 @@ function vnrFormAdd() {
return false;
}
- txt.disabled = sel.disabled = true;
+ txt.disabled = sel.disabled = off.disabled = true;
txt.value = mt('_js_loading');
setText(lnk, mt('_js_loading'));
ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) {
- txt.disabled = sel.disabled = false;
+ txt.disabled = sel.disabled = off.disabled = false;
txt.value = '';
setText(lnk, mt('_vnedit_rel_addbut'));
@@ -900,7 +906,7 @@ function vnrFormAdd() {
if(byId('relation_tr_'+id))
return alert(mt('_vnedit_rel_double'));
- vnrAdd(sel.options[sel.selectedIndex].value, id, items[0].firstChild.nodeValue);
+ vnrAdd(sel.options[sel.selectedIndex].value, id, off.checked, items[0].firstChild.nodeValue);
sel.selectedIndex = 0;
vnrSerialize();
});
diff --git a/data/style.css b/data/style.css
index 638782cc..5e522c01 100644
--- a/data/style.css
+++ b/data/style.css
@@ -741,7 +741,7 @@ b.datepart b { font-weight: normal }
#jt_box_vn_rel h2 { margin: 0 0 3px 0px; }
#jt_box_vn_rel td { padding: 1px 2px; vertical-align: middle; }
#jt_box_vn_rel td.tc_vn { width: 300px; text-align: right }
-#jt_box_vn_rel td.tc_rel { width: 170px; white-space: nowrap }
+#jt_box_vn_rel td.tc_rel { width: 220px; white-space: nowrap }
#jt_box_vn_rel td.tc_title { width: 200px; }
#jt_box_vn_rel td.tc_add { width: 40px; text-align: right }
#jt_box_vn_rel td.tc_vn input { width: 280px; }
diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm
index 0088d18f..6d99ba8a 100644
--- a/lib/VNDB/DB/VN.pm
+++ b/lib/VNDB/DB/VN.pm
@@ -125,11 +125,12 @@ sub dbVNGet {
if($o{what} =~ /relations/) {
push(@{$r->[$r{$_->{vid1}}]{relations}}, {
relation => $_->{relation},
+ official => $_->{official},
id => $_->{vid2},
title => $_->{title},
- original => $_->{original}
+ original => $_->{original},
}) for(@{$self->dbAll(q|
- SELECT rel.vid1, rel.vid2, rel.relation, vr.title, vr.original
+ SELECT rel.vid1, rel.vid2, rel.relation, rel.official, vr.title, vr.original
FROM vn_relations rel
JOIN vn v ON rel.vid2 = v.id
JOIN vn_rev vr ON v.latest = vr.id
@@ -176,9 +177,9 @@ sub dbVNRevisionInsert {
if($o->{relations}) {
$self->dbExec('DELETE FROM edit_vn_relations');
- my $q = join ',', map '(?, ?)', @{$o->{relations}};
- my @val = map +($_->[1], $_->[0]), @{$o->{relations}};
- $self->dbExec("INSERT INTO edit_vn_relations (vid, relation) VALUES $q", @val) if @val;
+ my $q = join ',', map '(?, ?, ?)', @{$o->{relations}};
+ my @val = map +($_->[1], $_->[0], $_->[2]?1:0), @{$o->{relations}};
+ $self->dbExec("INSERT INTO edit_vn_relations (vid, relation, official) VALUES $q", @val) if @val;
}
if($o->{anime}) {
diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm
index bfc37e02..122b432e 100644
--- a/lib/VNDB/Handler/VNEdit.pm
+++ b/lib/VNDB/Handler/VNEdit.pm
@@ -30,7 +30,7 @@ sub edit {
my %b4 = !$vid ? () : (
(map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn img_nsfw ihid ilock|),
anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}),
- vnrelations => join('|||', map $_->{relation}.','.$_->{id}.','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}),
+ 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}}),
);
@@ -62,14 +62,14 @@ sub edit {
if(!$frm->{_err}) {
# 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]+),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{vnrelations} ];
+ my $relations = [ map { /^([a-z]+),([0-9]+),([01]),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3, $4 ] : () } split /\|\|\|/, $frm->{vnrelations} ];
my $screenshots = [ map /^[0-9]+,[01],[0-9]+$/ ? [split /,/] : (), split / +/, $frm->{screenshots} ];
$frm->{ihid} = $frm->{ihid}?1:0;
$frm->{ilock} = $frm->{ilock}?1:0;
$relations = [] if $frm->{ihid};
$frm->{anime} = join ' ', sort { $a <=> $b } keys %$anime;
- $frm->{vnrelations} = join '|||', map $_->[0].','.$_->[1].','.$_->[2], sort { $a->[1] <=> $b->[1]} @{$relations};
+ $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} = join ' ', map sprintf('%d,%d,%d', $_->[0], $_->[1]?1:0, $_->[2]), sort { $a->[0] <=> $b->[0] } @$screenshots;
@@ -96,8 +96,8 @@ sub edit {
# update reverse relations & relation graph
if(!$vid && $#$relations >= 0 || $vid && $frm->{vnrelations} ne $b4{vnrelations}) {
- my %old = $vid ? (map { $_->{id} => $_->{relation} } @{$v->{relations}}) : ();
- my %new = map { $_->[1] => $_->[0] } @$relations;
+ my %old = $vid ? (map +($_->{id} => [ $_->{relation}, $_->{official} ]), @{$v->{relations}}) : ();
+ my %new = map +($_->[1] => [ $_->[0], $_->[2] ]), @$relations;
_updreverse($self, \%old, \%new, $nrev->{iid}, $nrev->{rev});
}
@@ -211,6 +211,8 @@ sub _form {
end;
td class => 'tc_rel';
txt mt('_vnedit_rel_isa').' ';
+ input type => 'checkbox', id => 'official', checked => 'checked';
+ label for => 'official', mt '_vnedit_rel_official';
Select;
option value => $_, mt "_vnrel_$_"
for (sort { $self->{vn_relations}{$a}[0] <=> $self->{vn_relations}{$b}[0] } keys %{$self->{vn_relations}});
@@ -250,7 +252,7 @@ sub _form {
# Update reverse relations and regenerate relation graph
# Arguments: %old. %new, vid, rev
-# %old,%new -> { vid2 => relation, .. }
+# %old,%new -> { vid2 => [ relation, official ], .. }
# from the perspective of vid
# rev is of the related edit
sub _updreverse {
@@ -261,8 +263,8 @@ sub _updreverse {
for (keys %$old, keys %$new) {
if(exists $$old{$_} and !exists $$new{$_}) {
$upd{$_} = undef;
- } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_} ne $$new{$_})) {
- $upd{$_} = $self->{vn_relations}{$$new{$_}}[1];
+ } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_}[0] ne $$new{$_}[0] || !$$old{$_}[1] != !$$new{$_}[1])) {
+ $upd{$_} = [ $self->{vn_relations}{ $$new{$_}[0] }[1], $$new{$_}[1] ];
}
}
return if !keys %upd;
@@ -271,7 +273,7 @@ sub _updreverse {
for my $i (keys %upd) {
my $r = $self->dbVNGet(id => $i, what => 'relations')->[0];
my @newrel = map $_->{id} != $vid ? [ $_->{relation}, $_->{id} ] : (), @{$r->{relations}};
- push @newrel, [ $upd{$i}, $vid ] if $upd{$i};
+ push @newrel, [ $upd{$i}[0], $vid, $upd{$i}[1] ] if $upd{$i};
$self->dbItemEdit(v => $r->{cid},
relations => \@newrel,
editsum => "Reverse relation update caused by revision v$vid.$rev",
diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm
index 0dff5627..32188e00 100644
--- a/lib/VNDB/Handler/VNPage.pm
+++ b/lib/VNDB/Handler/VNPage.pm
@@ -204,7 +204,8 @@ sub _revision {
$_[0] ? sprintf '<a href="http://renai.us/game/%s.shtml">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink'
}],
[ relations => join => '<br />', split => sub {
- my @r = map sprintf('%s: <a href="/v%d" title="%s">%s</a>',
+ my @r = map sprintf('[%s] %s: <a href="/v%d" title="%s">%s</a>',
+ mt($_->{official} ? '_vndiff_rel_official' : '_vndiff_rel_unofficial'),
mt("_vnrel_$_->{relation}"), $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40
), sort { $a->{id} <=> $b->{id} } @{$_[0]};
return @r ? @r : (mt '_revision_empty');
diff --git a/util/sql/func.sql b/util/sql/func.sql
index 7b8b9302..922d1af8 100644
--- a/util/sql/func.sql
+++ b/util/sql/func.sql
@@ -221,7 +221,7 @@ BEGIN
ELSE
INSERT INTO edit_vn SELECT title, alias, img_nsfw, length, "desc", l_wp, l_vnn, image, l_encubed, l_renai, original FROM vn_rev WHERE id = cid;
INSERT INTO edit_vn_anime SELECT aid FROM vn_anime WHERE vid = cid;
- INSERT INTO edit_vn_relations SELECT vid2, relation FROM vn_relations WHERE vid1 = cid;
+ INSERT INTO edit_vn_relations SELECT vid2, relation, official FROM vn_relations WHERE vid1 = cid;
INSERT INTO edit_vn_screenshots SELECT scr, nsfw, rid FROM vn_screenshots WHERE vid = cid;
END IF;
END;
@@ -239,7 +239,7 @@ BEGIN
SELECT INTO r * FROM edit_commit();
INSERT INTO vn_rev SELECT r.cid, r.iid, title, alias, img_nsfw, length, "desc", l_wp, l_vnn, image, l_encubed, l_renai, original FROM edit_vn;
INSERT INTO vn_anime SELECT r.cid, aid FROM edit_vn_anime;
- INSERT INTO vn_relations SELECT r.cid, vid, relation FROM edit_vn_relations;
+ INSERT INTO vn_relations SELECT r.cid, vid, relation, official FROM edit_vn_relations;
INSERT INTO vn_screenshots SELECT r.cid, scr, nsfw, rid FROM edit_vn_screenshots;
UPDATE vn SET latest = r.cid WHERE id = r.iid;
RETURN r;
diff --git a/util/sql/schema.sql b/util/sql/schema.sql
index eeb2e74c..72ecd9cc 100644
--- a/util/sql/schema.sql
+++ b/util/sql/schema.sql
@@ -308,6 +308,7 @@ CREATE TABLE vn_relations (
vid1 integer NOT NULL DEFAULT 0,
vid2 integer NOT NULL DEFAULT 0,
relation vn_relation NOT NULL,
+ official boolean NOT NULL DEFAULT TRUE,
PRIMARY KEY(vid1, vid2)
);
diff --git a/util/updates/update_2.13.sql b/util/updates/update_2.13.sql
new file mode 100644
index 00000000..5171d9eb
--- /dev/null
+++ b/util/updates/update_2.13.sql
@@ -0,0 +1,6 @@
+
+-- "unofficial" flag for vn<->vn relations
+ALTER TABLE vn_relations ADD COLUMN official boolean NOT NULL DEFAULT TRUE;
+
+\i util/sql/func.sql
+