OSDN Git Service

* Model::Stories: select() uses query builder, support new-table-order
authorhylom <hylom@users.sourceforge.jp>
Fri, 21 Jul 2017 12:43:48 +0000 (21:43 +0900)
committerhylom <hylom@users.sourceforge.jp>
Fri, 21 Jul 2017 12:43:48 +0000 (21:43 +0900)
src/newslash_web/lib/Newslash/Model/Stories.pm

index d4b5447..dfaf22b 100644 (file)
@@ -10,29 +10,6 @@ use DateTime;
 use Newslash::Util::Formatters qw(datetime_to_string);
 
 
-sub _calculate_time_range {
-    my ($self, $params) = @_;
-    my $year = $params->{year};
-    my $month = $params->{month};
-    my $day = $params->{day};
-    my $offset_sec = $params->{offset_sec};
-
-    my $dt_from = DateTime->new(year => $year,
-                           month => $month,
-                           day => $day);
-    my $dt_to = DateTime->new(year => $year,
-                           month => $month,
-                              day => $day);
-    if ($offset_sec) {
-        $dt_from->add(seconds => -$offset_sec);
-        $dt_to->add(seconds => -$offset_sec);
-    }
-    $dt_to->add(days => 1);
-    return (DateTime::Format::MySQL->format_datetime($dt_from),
-            DateTime::Format::MySQL->format_datetime($dt_to));
-    #return ($dt_from->strftime('%F'), $dt_to->strftime('%F'));
-}
-
 sub count {
     my $self = shift;
     my $params = {@_};
@@ -200,36 +177,43 @@ HASH of story contents
 sub select {
     my $self = shift;
     my $params = {@_};
-    my $query_type;
-    my $value;
-    my $return_single = 0;
-
-    # check query type
-    for my $k (qw(sid stoid)) {
-        if ($params->{$k}) {
-            $query_type = $k;
-            $value = $params->{$k};
-            $return_single = 1;
-        }
-    }
-    for my $k (qw(submitter)) {
-        if ($params->{$k}) {
-            $query_type = $k;
-            $value = $params->{$k};
-        }
-    }
 
-    # build WHERE clause
-    my @where_clauses;
-    my @query_param;
-
-    if ($query_type && $value) {
-        push @where_clauses, "stories.$query_type = ?";
-        push @query_param, $value;
-    }
 
+    my $unique_keys = { id => "stories.stoid",
+                        story_id => "stories.stoid",
+                        stoid => "stories.stoid",
+                        sid => "stories.sid",
+                      };
+    my $keys = { user_id => "stories.uid",
+                 uid => "stories.uid",
+                 topic_id => "stories.tid",
+                 tid => "stories.tid",
+                 discussion_id => "stories.discussion",
+                 commentcount => "stories.commentcount",
+                 hits => "stories.hits",
+                 submitter => "stories.submitter",
+                 create_time => "stories.time",
+                 update_time => "stories.last_update",
+               };
+    my $datetime_keys = { create_time => "stories.time",
+                          update_time => "stories.last_update",
+                        };
+    my $timestamp = "stories.time";
+
+    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);
+
+    # TODO: give reasonable LIMIT Value...
+    $limit_clause = "LIMIT 50" if !$limit_clause;
 
     # show future story?
+    my @where_clauses;
     if (!$params->{show_future}) {
         push @where_clauses, "stories.time <= NOW()";
     }
@@ -239,68 +223,19 @@ sub select {
         push @where_clauses, "firehose.public != 'no'";
     }
 
-    # year, month, day
-    if ($params->{year} && $params->{month} && $params->{day}) {
-        my ($time_from, $time_to) = $self->_calculate_time_range($params);
-        push @where_clauses, "stories.time > ? AND stories.time < ?";
-        push @query_param, $time_from, $time_to;
-    }
-
-    # until
-    if ($params->{until}) {
-        push @where_clauses, "stories.time <= ?";
-        push @query_param, $params->{until};
+    if (@where_clauses) {
+        if ($where_clause) {
+            $where_clause = $where_clause . " AND ";
+        }
+        else {
+            $where_clause = "WHERE ";
+        }
+        $where_clause = $where_clause . join(" AND ", @where_clauses);
     }
 
-    if ($params->{since}) {
-        push @where_clauses, "stories.time >= ?";
-        push @query_param, $params->{since};
-    }
+    my @attrs;
+    push @attrs, @$where_values, @$limit_values, @$orderby_values;
 
-    # target period
-    my $date_limit = "";
-    my @units = qw(YEAR MONTH WEEK DAY HOUR MINUTE);
-    my $unit;
-    for my $term (qw(years months weeks days hours minutes)) {
-        $unit = shift @units;
-        if (defined $params->{$term}) {
-            $date_limit = $params->{$term};
-            last;
-        }
-    }
-    if (length $date_limit) {
-        push @where_clauses, "stories.time > NOW() - INTERVAL ? $unit";
-        push @query_param, $date_limit;
-    }
-
-    # build ORDER BY clause
-    # my $order_clause = "";
-    # my @safe_params = qw(commentcount hits time);
-    # 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";
-    #         }
-    #         $order_clause = "ORDER BY $k $order";
-    #     }
-    # }
-    my ($order_clause, $order_values) = $self->build_order_by_clause(keys => [qw(commentcount hits time)], params => $params);
-
-    # build LIMIT clause
-    my $limit_clause = "";
-    if (defined $params->{limit}) {
-        $limit_clause = "LIMIT ?";
-        push @query_param, $params->{limit};
-    }
-
-    # do SELECT
-    my $where_clause = "";
-    if (@where_clauses) {
-        $where_clause = "WHERE " . join("\n AND ", @where_clauses) . "\n";
-    }
     my $dbh = $self->connect_db;
     my $sql = <<"EOSQL";
 SELECT stories.*, story_text.*, users.nickname as author, firehose.public
@@ -310,15 +245,15 @@ SELECT stories.*, story_text.*, users.nickname as author, firehose.public
     LEFT JOIN firehose 
       ON (stories.stoid = firehose.srcid AND firehose.type = "story")
     $where_clause
-    $order_clause
+    $orderby_clause
     $limit_clause
 EOSQL
 
     #warn($sql);
-    #warn(Dumper(@query_param));
+    #warn(Dumper(@attrs));
 
     my $sth = $dbh->prepare($sql);
-    $sth->execute(@query_param);
+    $sth->execute(@attrs);
     my $stories = $sth->fetchall_arrayref({});
 
     if (!$stories) {
@@ -327,7 +262,7 @@ EOSQL
     }
     if (@$stories == 0) {
         $self->disconnect_db();
-        return $return_single ? undef : [];
+        return $unique ? undef : [];
     }
 
     # get tags
@@ -335,7 +270,7 @@ EOSQL
 SELECT tags.*, tagnames.tagname, target.stoid
   FROM (SELECT stories.stoid FROM stories 
         LEFT JOIN firehose ON (stories.stoid = firehose.srcid AND firehose.type = "story")
-        $where_clause $order_clause $limit_clause) AS target
+        $where_clause $orderby_clause $limit_clause) AS target
     LEFT JOIN globjs
       ON target.stoid = globjs.target_id
     LEFT JOIN tags
@@ -346,7 +281,7 @@ SELECT tags.*, tagnames.tagname, target.stoid
 EOSQL
 
     $sth = $dbh->prepare($sql);
-    $sth->execute(@query_param);
+    $sth->execute(@attrs);
     my $tags_table = $sth->fetchall_arrayref({});
 
     # get topics
@@ -354,7 +289,7 @@ EOSQL
 SELECT story_topics_rendered.*, story_topics_chosen.weight, topics.*
   FROM (SELECT stories.stoid FROM stories
         LEFT JOIN firehose ON (stories.stoid = firehose.srcid AND firehose.type = "story")
-        $where_clause $order_clause $limit_clause) AS target
+        $where_clause $orderby_clause $limit_clause) AS target
     LEFT JOIN story_topics_rendered
       ON target.stoid = story_topics_rendered.stoid
     LEFT JOIN story_topics_chosen 
@@ -365,7 +300,7 @@ SELECT story_topics_rendered.*, story_topics_chosen.weight, topics.*
 EOSQL
 
     $sth = $dbh->prepare($sql);
-    $sth->execute(@query_param);
+    $sth->execute(@attrs);
     my $topics_table = $sth->fetchall_arrayref({});
     $self->disconnect_db();
 
@@ -395,7 +330,7 @@ EOSQL
         $self->_generalize($story, $params);
     }
 
-    return $stories->[0] if $return_single;
+    return $stories->[0] if $unique;
     return $stories;
 }
 
@@ -759,33 +694,22 @@ sub _generalize {
     my ($self, $story, $params) = @_;
     $params ||= {};
 
-    $story->{content_type} = "story";
+    $story->{id} = $story->{stoid};
+    $story->{create_time} = $story->{time};
+    $story->{update_time} = $story->{last_update};
 
-    #my $max_weight = 0;
     for my $t (@{$story->{topics}}) {
         if ($t->{tid} && $t->{tid} == $story->{tid}) {
             $story->{primary_topic} = $t;
         }
-        #if ($t->{weight} && $t->{weight} > $max_weight) {
-        #    $max_weight = $t->{weight};
-        #}
     }
 
-    $story->{time_string} = datetime_to_string($story->{time});
-    $story->{createtime} = $story->{time};
+    $story->{content_type} = "story";
     $story->{discussion_id} = $story->{discussion};
-    $story->{id} = $story->{stoid};
 
     # no public flag given, public is 'yes'
     $story->{public} = 'yes' if !$story->{public};
 
-    # convert timestamp format
-    if (lc($params->{datetime_format}) eq "javascript") {
-        for my $k (qw{time day_published archive_last_update stuckendtime}) {
-            my $dt = DateTime::Format::MySQL->parse_datetime($story->{$k});
-            $story->{$k} = $dt->strftime('%FT%T');
-        }
-    }
 }
 
 # delete story from database