diff options
Diffstat (limited to 'lib/VNWeb/TT/TagEdit.pm')
-rw-r--r-- | lib/VNWeb/TT/TagEdit.pm | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/lib/VNWeb/TT/TagEdit.pm b/lib/VNWeb/TT/TagEdit.pm new file mode 100644 index 00000000..115a24bf --- /dev/null +++ b/lib/VNWeb/TT/TagEdit.pm @@ -0,0 +1,154 @@ +package VNWeb::TT::TagEdit; + +use VNWeb::Prelude; + +# TODO: Let users edit their own tag while it's still waiting for approval? + +my $FORM = { + id => { default => undef, vndbid => 'g' }, + name => { maxlength => 250, regex => qr/^[^,\r\n\t]+$/ }, + alias => { maxlength => 1024, regex => qr/^[^,]+$/, default => '' }, + cat => { enum => \%TAG_CATEGORY, default => 'cont' }, + description => { maxlength => 10240 }, + searchable => { anybool => 1, default => 1 }, + applicable => { anybool => 1, default => 1 }, + defaultspoil => { uint => 1, range => [0,2] }, + parents => { aoh => { + parent => { vndbid => 'g' }, + main => { anybool => 1 }, + name => { _when => 'out' }, + } }, + wipevotes => { _when => 'in', anybool => 1 }, + merge => { _when => 'in out', aoh => { + id => { vndbid => 'g' }, + name => { _when => 'out' }, + } }, + hidden => { anybool => 1 }, + locked => { anybool => 1 }, + + authmod => { _when => 'out', anybool => 1 }, + editsum => { _when => 'in out', editsum => 1 }, +}; + +my $FORM_OUT = form_compile out => $FORM; +my $FORM_IN = form_compile in => $FORM; +my $FORM_CMP = form_compile cmp => $FORM; + + +TUWF::get qr{/$RE{grev}/edit}, sub { + my $g = db_entry tuwf->captures('id','rev'); + return tuwf->resNotFound if !$g->{id}; + return tuwf->resDenied if !can_edit g => $g; + + enrich_merge parent => 'SELECT id AS parent, name FROM tags WHERE id IN', $g->{parents}; + + $g->{authmod} = auth->permTagmod; + $g->{editsum} = $g->{chrev} == $g->{maxrev} ? '' : "Reverted to revision $g->{id}.$g->{chrev}"; + $g->{merge} = []; + + framework_ title => "Edit $g->{name}", dbobj => $g, tab => 'edit', sub { + elm_ TagEdit => $FORM_OUT, $g; + }; +}; + + +TUWF::get qr{/(?:$RE{gid}/add|g/new)}, sub { + my $id = tuwf->capture('id'); + my $g = tuwf->dbRowi('SELECT id, name, cat FROM tags WHERE NOT hidden AND id =', \$id); + return tuwf->resDenied if !can_edit g => {}; + return tuwf->resNotFound if $id && !$g->{id}; + + my $e = elm_empty($FORM_OUT); + $e->{authmod} = auth->permTagmod; + if($id) { + $e->{parents} = [{ parent => $g->{id}, main => 1, name => $g->{name} }]; + $e->{cat} = $g->{cat}; + } + + framework_ title => 'Submit a new tag', sub { + article_ sub { + h1_ 'Requesting new tag'; + div_ class => 'notice', sub { + h2_ 'Your tag must be approved'; + p_ sub { + txt_ 'All tags have to be approved by a moderator, so it can take a while before it will show up in the tag list' + .' or on visual novel pages. You can still vote on the tag even if it has not been approved yet.'; + br_; + br_; + txt_ 'Make sure you\'ve read the '; a_ href => '/d10', 'guidelines'; txt_ ' to increase the chances of getting your tag accepted.'; + } + } + } if !auth->permTagmod; + elm_ TagEdit => $FORM_OUT, $e; + }; +}; + + +elm_api TagEdit => $FORM_OUT, $FORM_IN, sub { + my($data) = @_; + my $new = !$data->{id}; + my $e = $new ? {} : db_entry $data->{id} or return tuwf->resNotFound; + return tuwf->resNotFound if !$new && !$e->{id}; + return elm_Unauth if !can_edit g => $e; + + if(!auth->permTagmod) { + $data->{hidden} = $e->{hidden}//1; + $data->{locked} = $e->{locked}//0; + } + + my $re = '[\t\s]*\n[\t\s]*'; + my $dups = tuwf->dbAlli(' + SELECT id, name + FROM (SELECT id, name FROM tags UNION SELECT id, s FROM tags, regexp_split_to_table(alias, ', \$re, ') a(s) WHERE s <> \'\') n(id,name) + WHERE ', sql_and( + $new ? () : sql('id <>', \$data->{id}), + sql 'lower(name) IN', [ map lc($_), $data->{name}, grep length($_), split /$re/, $data->{alias} ] + ) + ); + return elm_DupNames $dups if @$dups; + + # Make sure parent IDs exists and are not a child tag of the current tag (i.e. don't allow cycles) + validate_dbid sub { + 'SELECT id FROM tags WHERE', sql_and + $new ? () : sql('id NOT IN(WITH RECURSIVE t(id) AS (SELECT', \$data->{id}, '::vndbid UNION SELECT tp.id FROM tags_parents tp JOIN t ON t.id = tp.parent) SELECT id FROM t)'), + sql 'id IN', $_[0] + }, map $_->{parent}, $data->{parents}->@*; + die "No or multiple primary parents" if $data->{parents}->@* && 1 != grep $_->{main}, $data->{parents}->@*; + + $data->{description} = bb_subst_links($data->{description}); + + my $changed = 0; + if(!$new && auth->permTagmod && $data->{wipevotes}) { + my $num = tuwf->dbExeci('DELETE FROM tags_vn WHERE tag =', \$e->{id}); + auth->audit(undef, 'tag wipe', "Wiped $num votes on $e->{id}"); + $changed++; + } + + if(!$new && auth->permTagmod && $data->{merge}->@*) { + my @merge = map $_->{id}, $data->{merge}->@*; + # Bugs: + # - Arbitrarily takes one vote if there are duplicates, should ideally try to merge them instead. + # - The 'ignore' flag will be inconsistent if set and the same VN has been voted on for multiple tags. + my $mov = tuwf->dbExeci(' + INSERT INTO tags_vn (tag,vid,uid,vote,spoiler,date,ignore,notes) + SELECT ', \$e->{id}, ',vid,uid,vote,spoiler,date,ignore,notes + FROM tags_vn WHERE tag IN', \@merge, ' + ON CONFLICT (tag,vid,uid) DO NOTHING' + ); + my $del = tuwf->dbExeci('DELETE FROM tags_vn tv WHERE tag IN', \@merge); + my $lst = join ',', @merge; + auth->audit(undef, 'tag merge', "Moved $mov/$del votes from $lst to $e->{id}"); + $changed++; + } + + if($new || form_changed $FORM_CMP, $data, $e) { + my $ch = db_edit g => $e->{id}, $data; + elm_Redirect "/$ch->{nitemid}.$ch->{nrev}"; + } elsif($changed) { + elm_Redirect "/$e->{id}"; + } else { + elm_Unchanged; + } +}; + +1; |