OSDN Git Service

Model::Stories: 'select' method can receive various parameters
authorhylom <hylom@users.sourceforge.jp>
Tue, 22 Nov 2016 10:47:40 +0000 (19:47 +0900)
committerhylom <hylom@users.sourceforge.jp>
Tue, 22 Nov 2016 10:47:40 +0000 (19:47 +0900)
src/newslash_web/lib/Newslash/Model/Stories.pm

index bb96488..02a9e28 100644 (file)
@@ -4,6 +4,7 @@ use Newslash::Model::Base -base;
 use Newslash::Model::SlashDB;
 
 use Data::Dumper;
+use DateTime;
 
 #========================================================================
 
@@ -60,7 +61,6 @@ EOSQL
 
   $sth->execute($limit);
   my $rs = $sth->fetchall_arrayref(+{});
-  $sth->finish;
 
   if (@$rs == 0) {
     $dbh->disconnect();
@@ -133,60 +133,127 @@ HASH of story contents
 =cut
 
 sub select {
-  my ($self, $query_type, $value) = @_;
+    my $self = shift;
+    my $params = {@_};
+    my $query_type;
+    my $value;
+    my $return_single = 0;
+
+    for my $k (qw(sid stoid)) {
+        if ($params->{$k}) {
+            $query_type = $k;
+            $value = $params->{$k};
+            $return_single = 1;
+        }
+    }
 
-  if ($query_type !~ m/\A(sid|stoid)\z/) {
-    return undef;
-  }
+    my @where_clauses;
+    my @query_param;
 
-  my $dbh = $self->connect_db;
-  my $sql = <<"EOSQL";
+    if ($query_type && $value) {
+        push @where_clauses, "stories.$query_type = ?";
+        push @query_param, $value;
+    }
+
+    # show future story?
+    if (!$params->{show_future}) {
+        push @where_clauses, "stories.time <= NOW()";
+    }
+
+    # target period
+    my $date_limit = "";
+    for my $term (qw(years months weeks days hours minutes)) {
+        if (defined $params->{$term}) {
+            my $dt = DateTime->now();
+            $dt->subtract($term => $params->{$term});
+            $date_limit = $dt->ymd("-") . " " . $dt->hms(":");
+        }
+    }
+    if (length $date_limit) {
+        push @where_clauses, "stories.time > ?";
+        push @query_param, $date_limit;
+    }
+
+    my @order_clauses;
+    # set ORDER BY clause
+    my @safe_params = qw(commentcount hits);
+    if (defined $params->{order_by}) {
+        # check order_by's value
+        my $k = $params->{order_by};
+        if (grep {$_ eq $k} @safe_params) {
+            my $order = "DESC";
+            if (defined $params->{order} && $params->{order} eq "ASC") {
+                $order = "ASC";
+            }
+            push @order_clauses, "ORDER BY $k $order";
+        }
+    }
+
+    # set LIMIT clause
+    my $limit_clause = "";
+    if (defined $params->{limit}) {
+        push @order_clauses, "LIMIT ?";
+        push @query_param, $params->{limit};
+    }
+
+    my $where_clause = "WHERE " . join("\n AND ", @where_clauses) . "\n";
+    my $sub_clauses = $where_clause . join("\n", @order_clauses);
+    my $dbh = $self->connect_db;
+    my $sql = <<"EOSQL";
 SELECT stories.*, story_text.*, users.nickname as author
   FROM stories
     LEFT JOIN story_text ON stories.stoid = story_text.stoid
     LEFT JOIN users ON stories.uid = users.uid
-  WHERE stories.$query_type = ?
+    $sub_clauses
 EOSQL
 
-  my $sth = $dbh->prepare($sql);
-
-  $sth->execute($value);
-  my $story = $sth->fetchrow_hashref;
-  $sth->finish;
-
-  if (!$story) {
-    $dbh->disconnect();
-    return undef;
-  }
+    warn $sub_clauses;
+    warn Dumper(@query_param);
 
-  my $stoid = $story->{stoid};
-  if (!$stoid) {
-    $dbh->disconnect();
-    return undef;
-  }
+    my $sth = $dbh->prepare($sql);
+    $sth->execute(@query_param);
+    my $rs = $sth->fetchall_arrayref({});
 
+    if (!$rs) {
+        $dbh->disconnect();
+        return;
+    }
+    if (@$rs == 0) {
+        $dbh->disconnect();
+        return;
+    }
 
-  # get tags
-  $sql = <<"EOSQL";
+    # get tags
+    $sql = <<"EOSQL";
 SELECT story_topics_rendered.*, story_topics_chosen.weight, topics.*
-  FROM story_topics_rendered
+  FROM (SELECT stoid FROM stories $sub_clauses) AS latest
+    INNER JOIN story_topics_rendered ON latest.stoid = story_topics_rendered.stoid
     LEFT JOIN story_topics_chosen ON story_topics_rendered.stoid = story_topics_chosen.stoid
       AND story_topics_rendered.tid = story_topics_chosen.tid
     LEFT JOIN topics ON story_topics_rendered.tid = topics.tid
-  WHERE story_topics_rendered.stoid = ?
 EOSQL
 
-  $sth = $dbh->prepare($sql);
+    $sth = $dbh->prepare($sql);
+    $sth->execute(@query_param);
+    my $topics_table = $sth->fetchall_arrayref(+{});
+    $dbh->disconnect();
 
-  $sth->execute($stoid);
-  my $topics = $sth->fetchall_arrayref(+{});
-  $sth->finish;
-  $dbh->disconnect();
+    my $topics = {};
+    for my $topic (@$topics_table) {
+        if (!$topic->{stoid}) {
+            $topics->{$topic->{stoid}} = [];
+        }
+        push @{$topics->{$topic->{stoid}}}, $topic;
+    }
 
-  $story->{topics} = $topics;
-  $self->_generalize($story);
+    for my $story (@$rs) {
+        my $stoid = $story->{stoid};
+        $story->{topics} = $topics->{$stoid};
+        $self->_generalize($story);
+    }
 
-  return $story;
+    return $rs->[0] if $return_single;
+    return $rs;
 }
 
 =head2 create(\%params, $uid)