package Newslash::Model::Tags;
#use Newslash::Model::Base -base;
use base Newslash::Model::LegacyDB;
+use Data::Dumper;
+use List::Util qw(any all);
+
+use constant RESERVED_TAG_NAMES => [qw(metanix
+ metanod
+ nix
+ nod
+ poll
+ おもしろおかしい
+ すばらしい洞察
+ オフトピック
+ フレームのもと
+ 不当プラスモデ
+ 不当マイナスモデ
+ 余計なもの
+ 参考になる
+ 既出
+ 興味深い
+ 荒し
+ 荒らし
+ story
+ journal
+ comment
+ submission
+ )];
+
+sub is_reserved_name {
+ my ($self, $tag_name) = @_;
+ return any { $tag_name eq $_ } @{RESERVED_TAG_NAMES()};
+}
+
+sub select_for_items {
+ my ($self, $type, $primary_key, $items) = @_;
+ return if !$items;
+
+ if (ref($items) ne "ARRAY") {
+ $items = [$items];
+ }
+ return if !@$items;
+
+ my $globjs = $self->new_instance_of("Globjs");
+ my $gtid = $globjs->get_gtid($type);
+ return if !$gtid;
+
+ my @target_ids = map { $_->{$primary_key} } @$items;
+
+ # convert primary_key to globjid
+ #my @target_globj_ids;
+ #for my $id (@target_ids) {
+ # my $globj_id = $globjs->get_globjid_from_item($type, $id);
+ # push @target_globj_ids, $globj_id;
+ #}
+
+ my @placeholders = map { "?" } @target_ids;
+ my $placeholder = join(", ", @placeholders);
+ my $sql = <<"EOSQL";
+SELECT * FROM globjs
+ JOIN tags ON globjs.globjid = tags.globjid
+ JOIN tagnames ON tags.tagnameid = tagnames.tagnameid
+ WHERE globjs.gtid = ? AND globjs.target_id IN ($placeholder)
+EOSQL
+
+ my $dbh = $self->connect_db;
+ my $sth = $dbh->prepare($sql);
+ $sth->execute($gtid, @target_ids);
+ my $rs = $sth->fetchall_arrayref({});
+ $self->disconnect_db;
+
+ return if !$rs;
+
+ my $tags_of = {};
+ for my $tag (@$rs) {
+ my $id = $tag->{target_id};
+ $tags_of->{$id} = [] if !$tags_of->{$id};
+ push @{$tags_of->{$id}}, $tag;
+ }
+ return $tags_of;
+}
+
sub get_topics {
my ($self, ) = @_;
my $sql = <<"EOSQL";
return $rs;
}
-sub set_tag {
+sub add {
my $self = shift;
return if $self->check_readonly;
my $params = {@_};
-
my $globj_id = $params->{globj_id};
+
my $uid = $params->{uid} || 1;
my $name = $params->{name};
my $private = $params->{private} ? "yes" : "no";
my $tagname_id = $params->{tagname_id};
if (!$globj_id) {
- $self->set_error("no globj_id", 1);
+ $self->last_error("no globj_id");
return;
}
}
if (!$tagname_id) {
+ $self->last_error("no tagname id");
return;
}
(?, ?, ?, NOW(), $inactivated, ?, ?)
EOSQL
- my $dbh = $params->{dbh} || $self->connect_db;
+ my $dbh = $self->connect_db;
my $rs = $dbh->do($sql, undef, $tagname_id, $globj_id, $uid, $private, $active);
if (!$rs) {
- $self->set_errorno($dbh->{mysql_errorno});
- $self->disconnect_db if !$params->{dbh};
+ $self->set_errorno($dbh->err);
+ $self->disconnect_db;
return;
}
my $id = $dbh->last_insert_id(undef, undef, undef, undef);
- $self->disconnect_db if !$params->{dbh};
+ $self->disconnect_db;
return $id;
}
+sub del {
+ my $self = shift;
+ return if $self->check_readonly;
+ my $params = {@_};
+
+ my $globj_id = $params->{globj_id};
+ my $uid = $params->{uid} || 1;
+ my $name = $params->{name};
+ my $tagname_id = $params->{tagname_id};
+
+ if (!$globj_id) {
+ $self->set_error("no globj_id", 1);
+ return;
+ }
+
+ if ($name) {
+ my $tagname = $self->select_tagnames(tagname => $name);
+ if ($tagname) {
+ $tagname_id = $tagname->{tagnameid};
+ }
+ else {
+ $self->set_error("tagname not found", 2);
+ return;
+ }
+ }
+
+ if (!$tagname_id) {
+ $self->set_error("no tagname_id found", 3);
+ return;
+ }
+
+ my $sql = <<"EOSQL";
+DELETE FROM tags
+ WHERE tagnameid = ?
+ AND globjid = ?
+ AND uid = ?
+EOSQL
+
+ my $dbh = $self->connect_db;
+ my $rs = $dbh->do($sql, undef, $tagname_id, $globj_id, $uid);
+ if (!defined $rs) {
+ $self->set_errorno($dbh->err);
+ $self->disconnect_db;
+ return;
+ }
+ $self->disconnect_db;
+ return $rs;
+}
+
+sub set {
+ my $self = shift;
+ return if $self->check_readonly;
+ my $params = {@_};
+ my $globj_id = $params->{globj_id} || $params->{globjid};
+
+ if (!$globj_id) {
+ $self->set_error("no globj_id", 1);
+ return;
+ }
+ my $tag_names = $params->{names} || $params->{tagnames} || $params->{tag_names};
+
+
+ if (!$tag_names) {
+ if (!$params->{name} && !$params->{tagname} && !$params->{tag_name}) {
+ $self->set_error("no names given", 1);
+ return;
+ }
+ $tag_names = [$params->{name} || $params->{tagname} || $params->{tag_name}];
+ }
+
+ my $uid = $params->{uid} || 1;
+ my $private = $params->{private} ? "yes" : "no";
+ my $active = defined $params->{active} ? $params->{active} : 1;
+ my $tagname_value_of = $self->select_tagnames(tagnames => $tag_names);
+
+ # get tags for globj_id
+ my $existing_tags = $self->select(globjid => $globj_id,
+ uid => $uid);
+ return if !$existing_tags;
+
+ # create tagname
+ my @ids_to_add;
+ my @ids;
+ for my $name (@$tag_names) {
+ my $tagname_id;
+ if (!$tagname_value_of->{$name}) {
+ $tagname_id = $self->create(tagname => $name);
+ $tagname_value_of->{$name} = { tagname => $name,
+ tagnameid => $tagname_id };
+ }
+ else {
+ $tagname_id = $tagname_value_of->{$name}->{tagnameid};
+ }
+
+ push @ids, $tagname_id;
+ if (all { $tagname_id != $_ } @$existing_tags) {
+ push @ids_to_add, $tagname_id;
+ }
+ }
+
+ # add tags
+ my $sql = <<"EOSQL";
+INSERT IGNORE INTO tags
+ (tagnameid, globjid, uid, created_at, inactivated, private, is_active)
+ VALUES
+ (?, ?, ?, NOW(), NULL, ?, ?)
+EOSQL
+
+ my $dbh = $self->start_transaction;
+
+ # add tags
+ for my $tnid (@ids_to_add) {
+ my $rs = $dbh->do($sql, undef, $tnid, $globj_id, $uid, $private, $active);
+ if (!defined $rs) {
+ $self->set_error($dbh->err);
+ $self->rollback;
+ return;
+ }
+ }
+
+ # remove tags
+ my @placeholders = map { "?" } @ids;
+ my $placeholder_str = join(", ", @placeholders);
+ $sql = <<"EOSQL";
+DELETE FROM tags
+ WHERE globjid = ?
+ AND uid = ?
+ AND tagnameid NOT IN ($placeholder_str)
+EOSQL
+ my $rs = $dbh->do($sql, undef, $globj_id, $uid, @ids);
+ if (!defined $rs) {
+ $self->set_error($dbh->err);
+ $self->rollback;
+ return;
+ }
+ $self->commit;
+ return 1;
+}
+
+sub set_tag {
+ return shift->add(@_);
+}
+
sub create {
my $self = shift;
my $params = {@_};
sub select {
my $self = shift;
- return $self->generic_select('tags',
- uniques => [qw(tagid)],
- keys => [qw(tagnameid globjid uid private is_active)],
- params => {@_});
+ my $params = {@_};
+ my $unique_keys = { id => "tags.tagid",
+ tagid => "tags.tagid",
+ };
+ my $keys = { tagnameid => "tags.tagnameid",
+ globjid => "tags.globjid",
+ globj_id => "tags.globjid",
+ uid => "tags.uid",
+ private => "tags.private",
+ is_active => "tags.is_active",
+ tagname => "tagnames.tagname",
+ tag_name => "tagnames.tagname",
+ };
+ my $datetime_keys = { created_at => "tags.created_at",
+ inactivated => "tags.inactivated",
+ };
+ my $timestamp = "tags.created_at";
+
+ my ($where_clause, $where_values, $unique) = $self->build_where_clause(unique_keys => $unique_keys,
+ keys => $keys,
+ datetime_keys => $datetime_keys,
+ timestamp => $timestamp,
+ params => $params);
+ my ($limit_clause, $limit_values) = $self->build_limit_clause(params => $params);
+ my ($orderby_clause, $orderby_values) = $self->build_order_by_clause(keys => $keys,
+ params => $params);
+
+ my @attrs;
+ push @attrs, @$where_values, @$limit_values, @$orderby_values;
+
+ my $dbh = $self->connect_db;
+ my $sql = <<"EOSQL";
+SELECT tags.*, tagnames.*
+ FROM tags
+ LEFT JOIN tagnames ON tags.tagnameid = tagnames.tagnameid
+ $where_clause
+ $orderby_clause
+ $limit_clause
+EOSQL
+
+ my $sth = $dbh->prepare($sql);
+ $sth->execute(@attrs);
+ my $items = $sth->fetchall_arrayref({});
+
+ if (!$items) {
+ $self->disconnect_db();
+ return;
+ }
+ if (@$items == 0) {
+ $self->disconnect_db();
+ return $unique ? undef : [];
+ }
+ return $items;
+
}
sub select_tagnames {
my $self = shift;
my $params = {@_};
+ $params->{tagname} ||= $params->{tag_name};
+ $params->{tagnames} ||= $params->{tag_names};
+
if ($params->{tagname}) {
my $sql = "SELECT * FROM tagnames WHERE tagname = ?";
my $dbh = $self->connect_db;
}
return;
}
+
+ if ($params->{tagnames}) {
+ my @placeholders = map { "?" } @{$params->{tagnames}};
+ my $placeholder_str = join(", ", @placeholders);
+
+ my $sql = "SELECT * FROM tagnames WHERE tagname IN ($placeholder_str)";
+ my $dbh = $self->connect_db;
+ my $sth = $dbh->prepare($sql);
+ $sth->execute(@{$params->{tagnames}});
+ my $rs = $sth->fetchall_hashref("tagname");
+ $self->disconnect_db;
+ if ($rs) {
+ return $rs;
+ }
+ return;
+ }
}