use Newslash::Model::SlashDB;
+use Newslash::Model::Stories::Text;
+use Newslash::Model::Stories::RelatedStories;
+
use DateTime;
use DateTime::Format::MySQL;
use DateTime::Format::ISO8601;
+use List::Util q(any);
use Data::Dumper;
use DateTime;
}
##### sub models
-sub text { return shift->new_instance_of('::Stories::Text'); }
+sub text { return shift->_get_model('::Stories::Text'); }
+sub related_stories { return shift->_get_model('::Stories::RelatedStories'); }
+sub _get_model {
+ my ($self, $class) = @_;
+ $self->{sub_models} ||= {};
+ if (!$self->{sub_models}->{$class}) {
+ $self->{sub_models}->{$class} = $self->new_instance_of($class);
+ }
+ else {
+ if ($self->transaction_mode && !$self->{sub_models}->{$class}->transaction_mode) {
+ $self->{sub_models}->{$class}->use_transaction($self->{_tr_dbh});
+ }
+ }
+ return $self->{sub_models}->{$class};
+}
#========================================================================
for my $story (@$stories) {
my $stoid = $story->{stoid};
- $story->{tags} = $tags->{$stoid} if $tags->{$stoid};
- $story->{topics} = $topics->{$stoid} if $topics->{$stoid};
+ $story->{tags} = $tags->{$stoid} || [];
+ $story->{topics} = $topics->{$stoid} || [];
if ($params->{$stoid}) {
for my $param (@{$params->{$stoid}}) {
$story->{$param->{name}} = $param->{value};
#my ($self, $params, $user, $extra_params, $opts) = @_;
my $self = shift;
my $params = {@_};
+ my $user = $params->{user};
# check id
- my $id = $params->{stoid} || $params->{story_id} || $params->{id};
- if (!$id) {
- $self->set_error("story id not given");
+ my $story;
+ my $stoid = $params->{stoid} || $params->{story_id} || $params->{id};
+ my $sid = $params->{sid};
+ if (!$story) {
+ if ($stoid) {
+ $story = $self->select(stoid => $stoid);
+ }
+ elsif ($sid) {
+ $story = $self->select(sid => $sid);
+ }
+ }
+ if ($story) {
+ $sid = $story->{sid};
+ $stoid = $story->{stoid};
+ }
+
+ if (!$story) {
+ $self->last_error("no story given");
return;
}
# check params
return if !$self->_check_and_regularize_params($params);
- my $stoid = $params->{stoid} || $params->{story_id} || $params->{id};
my $slash_db = Newslash::Model::SlashDB->new($self->{options});
- my $sid = $slash_db->updateStory($stoid, $params);
- return if !$sid;
+ my $add_related = $params->{add_related};
+ delete $params->{add_related} if $add_related;
+ my $add_tags = $params->{add_tags};
+ delete $params->{add_tags} if $add_tags;
+
+ $stoid = $slash_db->updateStory($stoid, $params);
+ return if !$stoid;
$self->_set_tags_from_topics($params->{user}, $stoid, $params->{topics_chosen});
+
+ # set tags
+ if ($add_tags) {
+ my $tags = $self->new_instance_of("Tags");
+ my $globjs = $self->new_instance_of("Newslash::Model::Globjs");
+ my $globj_id = $globjs->getGlobjidFromTargetIfExists("stories", $params->{stoid});
+ for my $tag (@$add_tags) {
+ my $rs = $tags->add(uid => $user->{uid} || $user->{user_id},
+ globj_id => $globj_id,
+ name => $tag);
+ if (!defined $rs) {
+ $self->logger->warn("Stories::update: tag $tag set failed: " . $tags->last_error);
+ }
+ }
+ }
+
+ # insert related story
+ if ($add_related) {
+ for my $related_sid (@$add_related) {
+ my $rs = $self->add_related_story(sid => $sid,
+ related_sid => $related_sid);
+ if (!defined $rs) {
+ $self->logger->warn("Stories::update: insert related story $related_sid to $sid failed: " . $self->last_error);
+ }
+
+ $rs = $self->add_related_story(sid => $related_sid,
+ related_sid => $sid);
+ if (!defined $rs) {
+ $self->logger->warn("Stories::update: insert related story $sid to $related_sid failed: " . $self->last_error);
+ }
+ }
+ }
+
return $stoid;
}
# createStory() deletes topics_chosen, so need to save here.
my $topics_chosen = $params->{topics_chosen};
+ my $add_related = $params->{add_related};
+ delete $params->{add_related} if $add_related;
+ my $add_tags = $params->{add_tags};
+ delete $params->{add_tags} if $add_tags;
+
my $slash_db = Newslash::Model::SlashDB->new($self->{options});
my ($sid, $stoid);
if ($params->{update}) {
my $globjs = $self->new_instance_of("Newslash::Model::Globjs");
my $globj_id = $globjs->getGlobjidFromTargetIfExists("stories", $params->{stoid});
+
+ # set topics
+ my $tags = $self->new_instance_of("Tags");
if ($globj_id) {
- # set tags
- my $tags = $self->new_instance_of("Tags");
for my $tid (keys %$topics_chosen) {
- my $ret = $tags->set_tag(uid => $user->{uid} || $user->{user_id},
- tagname_id => $tid,
- globj_id => $globj_id,
- private => 0,
- );
- #warn "set_tag fault..." if !$ret
+ my $rs = $tags->add(uid => $user->{uid} || $user->{user_id},
+ tagname_id => $tid,
+ globj_id => $globj_id,
+ private => 0,
+ );
+ if (!defined $rs) {
+ $self->logger->warn("Stories::create: tag $tid set failed: " . $tags->last_error);
+ }
+ }
+ }
+
+ # set tags
+ if ($add_tags) {
+ for my $tag (@$add_tags) {
+ my $rs = $tags->add(uid => $user->{uid} || $user->{user_id},
+ globj_id => $globj_id,
+ name => $tag);
+ if (!defined $rs) {
+ $self->logger->warn("Stories::create: tag $tag set failed: " . $tags->last_error);
+ }
}
}
+
+ # insert related story
+ if ($add_related) {
+ for my $related_sid (@$add_related) {
+ my $rs = $self->add_related_story(sid => $sid,
+ related_sid => $related_sid);
+ if (!defined $rs) {
+ $self->logger->warn("insert related story failed: " . $self->last_error);
+ }
+
+ $rs = $self->add_related_story(sid => $related_sid,
+ related_sid => $sid);
+ if (!defined $rs) {
+ $self->logger->warn("Stories::create: insert related story failed: " . $self->last_error);
+ }
+ }
+ }
+
+ # TODO: add firehose item to related_story
+
return wantarray ? ($sid, $stoid) : $stoid;
}
return $related;
}
+sub add_related_story {
+ my $self = shift;
+ my $args = {@_};
+
+ my $story = $args->{story};
+ if (!$story) {
+ if ($args->{stoid}) {
+ $story = $self->select(stoid => $args->{stoid});
+ } elsif ($args->{sid}) {
+ $story = $self->select(sid => $args->{sid});
+ }
+ }
+
+ if (!$story || !$story->{stoid} || !$story->{sid}) {
+ $self->last_error("cannot get target story");
+ return;
+ }
+
+ my $related = $args->{related};
+ if (!$related) {
+ if ($args->{related_stoid}) {
+ $related = $self->select(stoid => $args->{related_stoid});
+ } elsif ($args->{related_sid}) {
+ $related = $self->select(sid => $args->{related_sid});
+ }
+ }
+
+ if (!$related || !$related->{stoid} || !$related->{sid} ) {
+ $self->last_error("cannot get related story");
+ return;
+ }
+
+ # get related item count
+ my $dbh = $self->start_transaction;
+ my $sql = "SELECT rel_stoid FROM related_stories WHERE stoid = ?";
+ my $stoids = $dbh->do($sql, undef, $story->{stoid});
+ $stoids = [] if ref($stoids) ne "ARRAY";
+
+ # check if related story is already set
+ if (any { $_ eq $related->{stoid} } @$stoids) {
+ return 0;
+ }
+
+ # insert
+ my $count = @$stoids;
+ my $rs = $self->related_stories->insert(stoid => $story->{stoid},
+ rel_stoid => $related->{stoid},
+ rel_sid => $related->{sid},
+ ordernum => $count + 1);
+
+ if (!defined $rs) {
+ $self->last_error("insert failed: " . $self->related_stories->last_error);
+ $dbh->rollback;
+ return;
+ }
+ $dbh->commit;
+ return 1;
+}
+
=head2 parameters($stoid)
get story parameters.
my $t = Test::Mojo->new('Newslash::Web');
my $test_man = Newslash::Util::TestMan->new($t);
my $admin;
+my $test_story;
if ($t->app->mode eq 'test') {
$admin = $test_man->create_admin("story_test", "foobar");
+
+ $test_story = $test_man->create_story( user => $admin,
+ uid => $admin->{uid},
+ title => "test story for firehose",
+ dept => "test for firehose",
+ introtext => '<p>foo bar hoge</p>',
+ bodytext => '',
+ topics_chosen => {49 => 10, 2271 => 20},
+ commentstatus => '',
+ tid => 49,
+ time => "2020-11-11 10:00:00");
+ ok($test_story, "create story for test");
+
}
SKIP: {
subtest 'story post/update' => sub {
my $test_title = "テストタイトル";
- my $test_introtext = <<"EOT";
-hylom 曰く、<blockquote><div><p>英国のEU離脱問題についてEUは厳しい姿勢を見せており、離脱後は英市民や英企業が.euドメイン名を取得・更新できなくなる可能性があるそうだ(<a href="https://www.theregister.co.uk/2019/01/07/brit_eu_domain_owners/">The Registerの記事</a>、
-<a href="https://www.forbes.com/sites/annatobin/2019/01/09/brits-could-be-locked-out-of-their-eu-domain-names-after-brexit/">Forbesの記事</a>)。
-<br> <br>
+ my $test_introtext = <<EOT;
+<p>insiderman曰く、</p><blockquote>
-現在英国とEUは離脱条件について議論を進めているが、3月29日までに両者が同意せず「合意なしでの離脱」に至った場合、英市民や他のEU域内に拠点を持たない英企業は.euドメインの利用資格を失う。既存のドメインが即座に失効することはないようだが、ドメイン名の更新や新規ドメイン名登録はできなくなる。そのため、英国政府はそういった事態に備えて.comや.co.ukドメインを取得しておくようアドバイスを行っているという。
-<br> <br>
+<p>はやくも来年発表されるとみられているiPhoneの新モデルの噂が出始めている(<a href="https://www.theverge.com/circuitbreaker/2017/11/13/16644266/apple-iphone-x-plus-rumor-two-fullscreen-phones-2018">The Verge</a>、<a href="http://jbpress.ismedia.jp/articles/-/51619">JBPress</a>、<a href="https://hardware.slashdot.org/story/17/11/14/000224/apple-could-launch-two-new-full-screen-iphones-next-year">Slashdot</a>)。</p>
-英国内では.ukドメインの利用が多いものの、英市民・企業が登録した.euドメインは登録済み.euドメインの10%近くを占めるとのことで、影響は少なくないようだ。</p></div></blockquote>
+<p>KGI SecuritiesのアナリストMing-Chi Kuo氏による予想では、6.5インチ有機ELディスプレイを搭載したモデルがiPhone Xの新たなモデル(「Plus」バージョン)として出るのではないか、とされている。また、iPhone 8 Plusと同等のサイズでiPhone Xのようにフルスクリーン化した6.1インチ液晶ディスプレイ搭載モデルも出る可能性があるとも予測されている。これは、「ハイエンド市場」のさまざまな需要を狙ったものになるという。iPhone Xはその価格も話題となったが、液晶ディスプレイの採用で価格を下げることができるようだ。</p>
+</blockquote>
EOT
- my $tidyed_introtext = $t->app->clean_html($test_introtext);
+ my $related = "https://apple.srad.jp/story/" . $test_story->{sid} . "/";
+ my $tidyed_introtext = $t->app->format_htmltext($test_introtext, "story");
my $test_dept = "テストdept";
my $createtime = strftime('%FT%T', gmtime);
+ my $test_tags = "apple ios iphone hoge";
my $test_data = {
action => 'preview',
item => {
dept => $test_dept,
introtext => $test_introtext,
bodytext => "",
- add_related => "",
- url => "",
+ add_related => $related,
+ tags_string => $test_tags,
mediaurl => "",
mediatype => "",
- email => "",
commentstatus => "enabled",
display => 1,
},
->json_is('/item/stoid', $stoid)
->json_is('/item/title', $test_title)
->json_is('/item/intro_text', $tidyed_introtext)
+ ->json_has('/item/related')
+ ->json_is('/item/related/0/stoid', $test_story->{stoid})
+ ->json_has('/item/tags/0')
+ ->json_has('/item/tags/1')
+ ->json_has('/item/tags/2')
+ ->json_has('/item/tags/3')
+ ->json_like('/item/tags/0/tagname', qr/(hoge|iOS|iPhone|アップル)/)
+ ->json_like('/item/tags/1/tagname', qr/(hoge|iOS|iPhone|アップル)/)
+ ->json_like('/item/tags/2/tagname', qr/(hoge|iOS|iPhone|アップル)/)
+ ->json_like('/item/tags/3/tagname', qr/(hoge|iOS|iPhone|アップル)/)
->json_is('/item/dept', $test_dept);
diag "message: " . $t->tx->res->json("/message") if $t->tx->res->code != 200;
+ #diag "result: " . Dumper $t->tx->res->json;
# update
my $new_title = "テストタイトル2テストテスト";
->status_is(200)
->json_has('/id')
->json_is('/type' => "story");
- diag $t->tx->res->json->{message} if $t->tx->res->code != 200;
+ #diag $t->tx->res->json->{message} if $t->tx->res->code != 200;
# get updated item
$t->get_ok("/api/v1/story?stoid=$stoid")