summaryrefslogtreecommitdiff
path: root/lib/VNDB/Util
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2011-01-01 14:31:27 +0100
committerYorhel <git@yorhel.nl>2011-01-01 14:31:27 +0100
commit7fd5b49039f5e9b3367a0a9025f695eeabbcd318 (patch)
treed79f0c59ad425b68244c909e88f36b987c92d997 /lib/VNDB/Util
parenta919a25370b31a4b969bcb663de6acce26bf235d (diff)
Implemented filFetchDB() and converted the VN/Release browser to use it
This will correctly handle fetching stuff from the database when permanent filters are enabled. This update also removes compatibility with some old VN browse URLs. The old 'ti' and 'te' (tag include/exclude) query parameters are now ignored, and searching for a language in the query string (e.g. "q=English") won't enable the language filter.
Diffstat (limited to 'lib/VNDB/Util')
-rw-r--r--lib/VNDB/Util/Misc.pm100
1 files changed, 100 insertions, 0 deletions
diff --git a/lib/VNDB/Util/Misc.pm b/lib/VNDB/Util/Misc.pm
new file mode 100644
index 00000000..2d1554ab
--- /dev/null
+++ b/lib/VNDB/Util/Misc.pm
@@ -0,0 +1,100 @@
+
+package VNDB::Util::Misc;
+
+use strict;
+use warnings;
+use Exporter 'import';
+use VNDB::Func;
+
+our @EXPORT = qw|filFetchDB|;
+
+
+my %filfields = (
+ vn => [qw|length hasani tag_inc tag_exc taginc tagexc tagspoil lang olang plat|],
+ release => [qw|type patch freeware doujin date_before date_after minage lang olang resolution plat med voiced ani_story ani_ero|],
+);
+
+
+# Arguments:
+# type ('vn' or 'release'),
+# filter overwrite (string or undef),
+# when defined and not '', these filters will be used instead of the preferences,
+# must point to a variable, will be modified in-place with the actually used filters
+# options to pass to db*Get() before the filters (hashref or undef)
+# these options can be overwritten by the filters or the next option
+# options to pass to db*Get() after the filters (hashref or undef)
+# these options overwrite all other options (pre-options and filters)
+
+sub filFetchDB {
+ my($self, $type, $overwrite, $pre, $post) = @_;
+ $pre = {} if !$pre;
+ $post = {} if !$post;
+ my $dbfunc = $self->can($type eq 'vn' ? 'dbVNGet' : 'dbReleaseGet');
+ my $prefname = 'fil_'.$type;
+ my $pref = $self->authPref($prefname);
+
+ # simply call the DB if we're not applying filters
+ return $dbfunc->($self, %$pre, %$post) if !$pref && !$overwrite;
+
+ my $filters = fil_parse $overwrite || $pref, @{$filfields{$type}};
+
+ # compatibility
+ $self->authPref($prefname => fil_serialize $filters)
+ if $type eq 'vn' && _fil_vn_compat($self, $filters) && !$overwrite;
+
+ # write the definite filter string in $overwrite
+ $_[2] = fil_serialize({map +(
+ exists($post->{$_}) ? ($_ => $post->{$_}) :
+ exists($filters->{$_}) ? ($_ => $filters->{$_}) :
+ exists($pre->{$_}) ? ($_ => $pre->{$_}) : (),
+ ), @{$filfields{$type}}}) if defined $overwrite;
+
+ return $dbfunc->($self, %$pre, %$filters, %$post) if $overwrite;
+
+ # since incorrect filters can throw a database error, we have to special-case
+ # filters that originate from a preference setting, so that in case these are
+ # the cause of an error, they are removed. Not doing this will result in VNDB
+ # throwing 500's even for non-browse pages. We have to do some low-level
+ # PostgreSQL stuff with savepoints to ensure that an error won't affect our
+ # existing transaction.
+ my $dbh = $self->{_YAWF}{DB}{sql};
+ $dbh->pg_savepoint('filter');
+ my($r, $np);
+ my $OK = eval {
+ ($r, $np) = $dbfunc->($self, %$pre, %$filters, %$post);
+ 1;
+ };
+ $dbh->pg_rollback_to('filter') if !$OK;
+ $dbh->pg_release('filter');
+
+ # error occured, let's try again without filters. if that succeeds we know
+ # it's the fault of the filter preference, and we should remove it.
+ if(!$OK) {
+ ($r, $np) = $dbfunc->($self, %$pre, %$post);
+ # if we're here, it means the previous function didn't die() (duh!)
+ $self->authPref($prefname => '');
+ warn sprintf "Reset filter preference for userid %d. Old: %s\n", $self->authInfo->{id}||0, $pref;
+ }
+ return wantarray ? ($r, $np) : $r;
+}
+
+
+sub _fil_vn_compat {
+ my($self, $fil) = @_;
+
+ # older tag specification (by name rather than ID)
+ if($fil->{taginc} || $fil->{tagexc}) {
+ my $tagfind = sub {
+ return map {
+ my $i = $self->dbTagGet(name => $_)->[0];
+ $i && !$i->{meta} ? $i->{id} : ();
+ } grep $_, ref $_[0] ? @{$_[0]} : ($_[0]||'')
+ };
+ $fil->{tag_inc} //= [ $tagfind->(delete $fil->{taginc}) ] if $fil->{taginc};
+ $fil->{tag_exc} //= [ $tagfind->(delete $fil->{tagexc}) ] if $fil->{tagexc};
+ return 1;
+ }
+
+ return 0;
+}
+