| 24 | | MT::Template::Context->add_container_tag('AllKeywords' => \&all_keywords); |
|---|
| 25 | | MT::Template::Context->add_container_tag('EntryAllKeywords' => \&entry_all_keywords); |
|---|
| 26 | | MT::Template::Context->add_tag('AllKeyword' => \&all_keyword); |
|---|
| 27 | | MT::Template::Context->add_tag('AllKeywordCount' => \&all_keyword_count); |
|---|
| 28 | | MT::Template::Context->add_tag('AllKeywordsTotal' => \&all_keywords_total); |
|---|
| 29 | | MT::Template::Context->add_tag('AllKeywordsTotalSum' => \&all_keywords_total_sum); |
|---|
| | 25 | if (MT->can('add_callback')) { |
|---|
| | 26 | my $mt = MT->instance; |
|---|
| | 27 | MT->add_callback((ref $mt eq 'MT::App::CMS' ? 'AppPostEntrySave' : 'MT::Entry::post_save'), |
|---|
| | 28 | 10, $plugin, \&update_indexes); |
|---|
| | 29 | } |
|---|
| | 30 | |
|---|
| | 31 | my $FORCE_REFRESH = 0; |
|---|
| | 32 | sub update_indexes { |
|---|
| | 33 | my ($eh, $app, $entry) = @_; |
|---|
| | 34 | return unless $plugin; |
|---|
| | 35 | require MT::Entry; |
|---|
| | 36 | my $blog_id = $entry->blog_id; |
|---|
| | 37 | require MT::PluginData; |
|---|
| | 38 | my $pd = MT::PluginData->load({ plugin => $plugin->name, |
|---|
| | 39 | key => $blog_id }); |
|---|
| | 40 | my (%eindex, %tindex); |
|---|
| | 41 | my $data; |
|---|
| | 42 | if (!$pd || $FORCE_REFRESH) { |
|---|
| | 43 | $pd = new MT::PluginData(); |
|---|
| | 44 | $pd->plugin($plugin->name); |
|---|
| | 45 | $pd->key($blog_id); |
|---|
| | 46 | $data = $pd->data() || {}; |
|---|
| | 47 | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| | 48 | status => MT::Entry::RELEASE() }); |
|---|
| | 49 | while (my $e = $iter->()) { |
|---|
| | 50 | my @tags = split_tags($e->keywords, 1) or next; |
|---|
| | 51 | $eindex{$e->id} = { tags => \@tags, |
|---|
| | 52 | created_on => $e->created_on }; |
|---|
| | 53 | } |
|---|
| | 54 | } else { |
|---|
| | 55 | $data = $pd->data() || {}; |
|---|
| | 56 | my $entry_id = $entry->id; |
|---|
| | 57 | %eindex = %{$data->{eindex}}; |
|---|
| | 58 | delete $eindex{$entry_id} if exists $eindex{$entry_id}; |
|---|
| | 59 | if ($entry->status == MT::Entry::RELEASE()) { |
|---|
| | 60 | my @tags = split_tags($entry->keywords, 1); |
|---|
| | 61 | $eindex{$entry_id} = { tags => \@tags, |
|---|
| | 62 | created_on => $entry->created_on }; |
|---|
| | 63 | } |
|---|
| | 64 | } |
|---|
| | 65 | foreach my $eid (keys %eindex) { |
|---|
| | 66 | map { push @{$tindex{$_}}, $eid } @{$eindex{$eid}->{tags}}; |
|---|
| | 67 | } |
|---|
| | 68 | $data->{eindex} = \%eindex; |
|---|
| | 69 | $data->{tindex} = \%tindex; |
|---|
| | 70 | $pd->data($data); |
|---|
| | 71 | $pd->save or die $pd->errstr; |
|---|
| | 72 | } |
|---|
| | 73 | |
|---|
| | 74 | MT::Template::Context->add_container_tag('Tags' => \&tags); |
|---|
| | 75 | MT::Template::Context->add_container_tag('EntryTags' => \&entry_tags); |
|---|
| | 76 | MT::Template::Context->add_tag('Tag' => \&tag); |
|---|
| | 77 | MT::Template::Context->add_tag('TagCount' => \&tag_count); |
|---|
| | 78 | MT::Template::Context->add_tag('TagsTotal' => \&tags_total); |
|---|
| | 79 | MT::Template::Context->add_tag('TagsTotalSum' => \&tags_total_sum); |
|---|
| 88 | | require MT::Entry; |
|---|
| 89 | | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| 90 | | status => MT::Entry::RELEASE() }); |
|---|
| 91 | | my %all_keywords = (); |
|---|
| 92 | | while (my $e = $iter->()) { |
|---|
| 93 | | next unless $e->keywords; |
|---|
| 94 | | my @keywords = split_keywords($e->keywords, $case_sensitive); |
|---|
| 95 | | foreach my $keyword (@keywords) { |
|---|
| 96 | | if (exists($all_keywords{$keyword})) { |
|---|
| 97 | | $all_keywords{$keyword}++; |
|---|
| 98 | | } else { |
|---|
| 99 | | $all_keywords{$keyword} = 1; |
|---|
| | 170 | my %tags = (); |
|---|
| | 171 | |
|---|
| | 172 | my $data = get_pdata($blog_id); |
|---|
| | 173 | if ($data) { |
|---|
| | 174 | my %tindex = %{$data->{tindex}}; |
|---|
| | 175 | if ($case_sensitive) { |
|---|
| | 176 | map { $tags{$_} = scalar(@{$tindex{$_}}) } keys %tindex; |
|---|
| | 177 | } else { |
|---|
| | 178 | map { $tags{lc $_} += scalar(@{$tindex{$_}}) } keys %tindex; |
|---|
| | 179 | } |
|---|
| | 180 | } else { |
|---|
| | 181 | require MT::Entry; |
|---|
| | 182 | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| | 183 | status => MT::Entry::RELEASE() }); |
|---|
| | 184 | while (my $e = $iter->()) { |
|---|
| | 185 | next unless $e->keywords; |
|---|
| | 186 | my @etags = split_tags($e->keywords, $case_sensitive); |
|---|
| | 187 | foreach my $etag (@etags) { |
|---|
| | 188 | $tags{$etag} = exists $tags{$etag} ? $tags{$etag} + 1 : 1; |
|---|
| 213 | | my $i = 0; |
|---|
| 214 | | while (my $e = $iter->()) { |
|---|
| 215 | | last if $lastn && $i >= $lastn; |
|---|
| 216 | | next unless $e->keywords; |
|---|
| 217 | | my @keywords = split_keywords($e->keywords, $case_sensitive); |
|---|
| 218 | | my $check = 1; |
|---|
| 219 | | foreach my $pattern (@patterns) { |
|---|
| 220 | | unless (scalar grep { $_ eq $pattern } @keywords) { |
|---|
| 221 | | $check = 0; |
|---|
| 222 | | last; |
|---|
| 223 | | } |
|---|
| 224 | | } |
|---|
| 225 | | if ($check) { |
|---|
| 226 | | push @entries, $e; |
|---|
| 227 | | $i++; |
|---|
| 228 | | } |
|---|
| 229 | | } |
|---|
| 230 | | return '' unless @entries; |
|---|
| 231 | | |
|---|
| 232 | | my $res = ''; |
|---|
| 233 | | my $tokens = $ctx->stash('tokens'); |
|---|
| 234 | | my $builder = $ctx->stash('builder'); |
|---|
| 235 | | $i = 0; |
|---|
| 236 | | for my $e (@entries) { |
|---|
| 237 | | local $ctx->{__stash}{entry} = $e; |
|---|
| 238 | | local $ctx->{current_timestamp} = $e->created_on; |
|---|
| 239 | | local $ctx->{modification_timestamp} = $e->modified_on; |
|---|
| 240 | | my $out = $builder->build($ctx, $tokens, { |
|---|
| 241 | | %$cond, |
|---|
| 242 | | EntryIfExtended => $e->text_more ? 1 : 0, |
|---|
| 243 | | EntryIfAllowComments => $e->allow_comments, |
|---|
| 244 | | EntryIfCommentsOpen => $e->allow_comments && $e->allow_comments eq '1', |
|---|
| 245 | | EntryIfAllowPings => $e->allow_pings, |
|---|
| 246 | | EntriesHeader => !$i, |
|---|
| 247 | | EntriesFooter => !defined $entries[$i+1] |
|---|
| 248 | | }); |
|---|
| 249 | | return $ctx->error($ctx->errstr) unless defined $out; |
|---|
| 250 | | $res .= $out; |
|---|
| 251 | | $i++; |
|---|
| 252 | | } |
|---|
| 253 | | $res; |
|---|
| 254 | | } |
|---|
| 255 | | |
|---|
| 256 | | sub most_related_entries { |
|---|
| 257 | | my ($ctx, $args, $cond) = @_; |
|---|
| 258 | | my $entry = $ctx->stash('entry') |
|---|
| 259 | | or return $ctx->_no_entry_error('MTMostRelatedEntries'); |
|---|
| 260 | | return '' unless $entry->keywords; |
|---|
| 261 | | |
|---|
| 262 | | # case_sensitive option (0/1, default = 0) |
|---|
| 263 | | my $case_sensitive = $args->{case_sensitive} || 0; |
|---|
| 264 | | # lastn option (default = 0, no cutoff) |
|---|
| 265 | | my $lastn = $args->{lastn} || 0; |
|---|
| 266 | | |
|---|
| 267 | | my @patterns = split_keywords($entry->keywords, $case_sensitive); |
|---|
| 268 | | |
|---|
| 269 | | my $blog_id = $ctx->stash('blog_id'); |
|---|
| 270 | | require MT::Entry; |
|---|
| 271 | | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| 272 | | status => MT::Entry::RELEASE() }, |
|---|
| 273 | | { sort => 'created_on', |
|---|
| 274 | | direction => 'descend' }); |
|---|
| 275 | | my @entries; |
|---|
| 276 | | my %matches = (); |
|---|
| 277 | | while (my $e = $iter->()) { |
|---|
| 278 | | next unless $e->keywords; |
|---|
| 279 | | next if $e->id == $entry->id; |
|---|
| 280 | | my @keywords = split_keywords($e->keywords, $case_sensitive); |
|---|
| 281 | | my $count = 0; |
|---|
| 282 | | foreach my $pattern (@patterns) { |
|---|
| 283 | | $count++ if (scalar grep { $_ eq $pattern } @keywords); |
|---|
| 284 | | } |
|---|
| 285 | | if ($count) { |
|---|
| 286 | | push @entries, $e; |
|---|
| 287 | | $matches{ $e->id } = $count; |
|---|
| 288 | | } |
|---|
| 289 | | } |
|---|
| 290 | | return '' unless @entries; |
|---|
| 291 | | |
|---|
| 292 | | @entries = sort { $matches{$b->id} <=> $matches{$a->id} } @entries; |
|---|
| 293 | | splice(@entries, $lastn) if $lastn && (scalar @entries > $lastn); |
|---|
| | 298 | |
|---|
| | 299 | my $data = get_pdata($blog_id); |
|---|
| | 300 | if ($data) { |
|---|
| | 301 | my %tindex = %{$data->{tindex}}; |
|---|
| | 302 | my %eindex = %{$data->{eindex}}; |
|---|
| | 303 | my %match; |
|---|
| | 304 | if ($case_sensitive) { |
|---|
| | 305 | foreach my $tag (@patterns) { |
|---|
| | 306 | foreach my $eid (@{$tindex{$tag}}) { |
|---|
| | 307 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 308 | $match{$eid} + 1 : 1; |
|---|
| | 309 | } |
|---|
| | 310 | } |
|---|
| | 311 | } else { |
|---|
| | 312 | foreach my $tag (@patterns) { |
|---|
| | 313 | foreach my $mtag (grep { lc $_ == $tag } keys %tindex) { |
|---|
| | 314 | foreach my $eid (@{$tindex{$mtag}}) { |
|---|
| | 315 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 316 | $match{$eid} + 1 : 1; |
|---|
| | 317 | } |
|---|
| | 318 | } |
|---|
| | 319 | } |
|---|
| | 320 | } |
|---|
| | 321 | my $count = scalar @patterns; |
|---|
| | 322 | my @eids = grep { $match{$_} == $count } keys %match or return; |
|---|
| | 323 | @eids = sort { $eindex{$b}->{created_on} <=> $eindex{$a}->{created_on} } @eids; |
|---|
| | 324 | require MT::Entry; |
|---|
| | 325 | map { push @entries, MT::Entry->load($_) } @eids; |
|---|
| | 326 | # The above code is sticked to "created_on", "descend". |
|---|
| | 327 | } else { |
|---|
| | 328 | require MT::Entry; |
|---|
| | 329 | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| | 330 | status => MT::Entry::RELEASE() }, |
|---|
| | 331 | { sort => $sort_by, |
|---|
| | 332 | direction => $sort_order }); |
|---|
| | 333 | my $i = 0; |
|---|
| | 334 | while (my $e = $iter->()) { |
|---|
| | 335 | last if $lastn && $i >= $lastn; |
|---|
| | 336 | next unless $e->keywords; |
|---|
| | 337 | my @tags = split_tags($e->keywords, $case_sensitive); |
|---|
| | 338 | my $check = 1; |
|---|
| | 339 | foreach my $pattern (@patterns) { |
|---|
| | 340 | unless (scalar grep { $_ eq $pattern } @tags) { |
|---|
| | 341 | $check = 0; |
|---|
| | 342 | last; |
|---|
| | 343 | } |
|---|
| | 344 | } |
|---|
| | 345 | if ($check) { |
|---|
| | 346 | push @entries, $e; |
|---|
| | 347 | $i++; |
|---|
| | 348 | } |
|---|
| | 349 | } |
|---|
| | 350 | return '' unless @entries; |
|---|
| | 351 | } |
|---|
| | 377 | sub most_related_entries { |
|---|
| | 378 | my ($ctx, $args, $cond) = @_; |
|---|
| | 379 | my $entry = $ctx->stash('entry') |
|---|
| | 380 | or return $ctx->_no_entry_error('MTMostRelatedEntries'); |
|---|
| | 381 | return '' unless $entry->keywords; |
|---|
| | 382 | |
|---|
| | 383 | # case_sensitive option (0/1, default = 1) |
|---|
| | 384 | my $case_sensitive = defined $args->{case_sensitive} ? |
|---|
| | 385 | $args->{case_sensitive} : 1; |
|---|
| | 386 | # lastn option (default = 0, no cutoff) |
|---|
| | 387 | my $lastn = $args->{lastn} || 0; |
|---|
| | 388 | |
|---|
| | 389 | my @patterns = split_tags($entry->keywords, $case_sensitive) |
|---|
| | 390 | or return ''; |
|---|
| | 391 | |
|---|
| | 392 | my $blog_id = $ctx->stash('blog_id'); |
|---|
| | 393 | my @entries; |
|---|
| | 394 | my %match = (); |
|---|
| | 395 | |
|---|
| | 396 | my $data = get_pdata($blog_id); |
|---|
| | 397 | if ($data) { |
|---|
| | 398 | my %tindex = %{$data->{tindex}}; |
|---|
| | 399 | my %eindex = %{$data->{eindex}}; |
|---|
| | 400 | my %match; |
|---|
| | 401 | if ($case_sensitive) { |
|---|
| | 402 | foreach my $tag (@patterns) { |
|---|
| | 403 | foreach my $eid (@{$tindex{$tag}}) { |
|---|
| | 404 | next if $eid == $entry->id; |
|---|
| | 405 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 406 | $match{$eid} + 1 : 1; |
|---|
| | 407 | } |
|---|
| | 408 | } |
|---|
| | 409 | } else { |
|---|
| | 410 | foreach my $tag (@patterns) { |
|---|
| | 411 | foreach my $mtag (grep { lc $_ == $tag } keys %tindex) { |
|---|
| | 412 | foreach my $eid (@{$tindex{$mtag}}) { |
|---|
| | 413 | next if $eid == $entry->id; |
|---|
| | 414 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 415 | $match{$eid} + 1 : 1; |
|---|
| | 416 | } |
|---|
| | 417 | } |
|---|
| | 418 | } |
|---|
| | 419 | } |
|---|
| | 420 | my @eids = keys %match or return ''; |
|---|
| | 421 | @eids = sort { $eindex{$b}->{created_on} <=> $eindex{$a}->{created_on} } @eids; |
|---|
| | 422 | @eids = sort { $match{$b} <=> $match{$a} } @eids; |
|---|
| | 423 | splice(@eids, $lastn) if $lastn && (scalar @eids > $lastn); |
|---|
| | 424 | require MT::Entry; |
|---|
| | 425 | map { push @entries, MT::Entry->load($_) } @eids; |
|---|
| | 426 | return '' unless @entries; |
|---|
| | 427 | } else { |
|---|
| | 428 | require MT::Entry; |
|---|
| | 429 | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| | 430 | status => MT::Entry::RELEASE() }, |
|---|
| | 431 | { sort => 'created_on', |
|---|
| | 432 | direction => 'descend' }); |
|---|
| | 433 | while (my $e = $iter->()) { |
|---|
| | 434 | next unless $e->keywords; |
|---|
| | 435 | next if $e->id == $entry->id; |
|---|
| | 436 | my @tags = split_tags($e->keywords, $case_sensitive); |
|---|
| | 437 | my $count = 0; |
|---|
| | 438 | foreach my $pattern (@patterns) { |
|---|
| | 439 | $count++ if (scalar grep { $_ eq $pattern } @tags); |
|---|
| | 440 | } |
|---|
| | 441 | if ($count) { |
|---|
| | 442 | push @entries, $e; |
|---|
| | 443 | $match{ $e->id } = $count; |
|---|
| | 444 | } |
|---|
| | 445 | } |
|---|
| | 446 | return '' unless @entries; |
|---|
| | 447 | |
|---|
| | 448 | @entries = sort { $match{$b->id} <=> $match{$a->id} } @entries; |
|---|
| | 449 | splice(@entries, $lastn) if $lastn && (scalar @entries > $lastn); |
|---|
| | 450 | } |
|---|
| | 451 | |
|---|
| | 452 | my $res = ''; |
|---|
| | 453 | my $tokens = $ctx->stash('tokens'); |
|---|
| | 454 | my $builder = $ctx->stash('builder'); |
|---|
| | 455 | my $i = 0; |
|---|
| | 456 | for my $e (@entries) { |
|---|
| | 457 | local $ctx->{__stash}{entry} = $e; |
|---|
| | 458 | local $ctx->{current_timestamp} = $e->created_on; |
|---|
| | 459 | local $ctx->{modification_timestamp} = $e->modified_on; |
|---|
| | 460 | my $out = $builder->build($ctx, $tokens, { |
|---|
| | 461 | %$cond, |
|---|
| | 462 | EntryIfExtended => $e->text_more ? 1 : 0, |
|---|
| | 463 | EntryIfAllowComments => $e->allow_comments, |
|---|
| | 464 | EntryIfCommentsOpen => $e->allow_comments && $e->allow_comments eq '1', |
|---|
| | 465 | EntryIfAllowPings => $e->allow_pings, |
|---|
| | 466 | EntriesHeader => !$i, |
|---|
| | 467 | EntriesFooter => !defined $entries[$i+1] |
|---|
| | 468 | }); |
|---|
| | 469 | return $ctx->error($ctx->errstr) unless defined $out; |
|---|
| | 470 | $res .= $out; |
|---|
| | 471 | $i++; |
|---|
| | 472 | } |
|---|
| | 473 | $res; |
|---|
| | 474 | } |
|---|
| | 475 | |
|---|
| 345 | | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| 346 | | status => MT::Entry::RELEASE() }, |
|---|
| 347 | | { sort => $sort_by, |
|---|
| 348 | | direction => $sort_order }); |
|---|
| 349 | | my @results; |
|---|
| 350 | | while (my $e = $iter->()) { |
|---|
| 351 | | next unless $e->keywords; |
|---|
| 352 | | my @keywords = split_keywords($e->keywords, $case_sensitive); |
|---|
| 353 | | my $check = 1; |
|---|
| 354 | | foreach my $pattern (@patterns) { |
|---|
| 355 | | unless (scalar grep { $_ eq $pattern } @keywords) { |
|---|
| 356 | | $check = 0; |
|---|
| 357 | | last; |
|---|
| 358 | | } |
|---|
| 359 | | } |
|---|
| 360 | | push @results, $e if $check; |
|---|
| | 504 | |
|---|
| | 505 | my $data = get_pdata($blog_id); |
|---|
| | 506 | if ($data) { |
|---|
| | 507 | my %tindex = %{$data->{tindex}}; |
|---|
| | 508 | my %eindex = %{$data->{eindex}}; |
|---|
| | 509 | my %match; |
|---|
| | 510 | if ($case_sensitive) { |
|---|
| | 511 | foreach my $tag (@patterns) { |
|---|
| | 512 | foreach my $eid (@{$tindex{$tag}}) { |
|---|
| | 513 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 514 | $match{$eid} + 1 : 1; |
|---|
| | 515 | } |
|---|
| | 516 | } |
|---|
| | 517 | } else { |
|---|
| | 518 | foreach my $tag (@patterns) { |
|---|
| | 519 | foreach my $mtag (grep { lc $_ == $tag } keys %tindex) { |
|---|
| | 520 | foreach my $eid (@{$tindex{$mtag}}) { |
|---|
| | 521 | $match{$eid} = exists $match{$eid} ? |
|---|
| | 522 | $match{$eid} + 1 : 1; |
|---|
| | 523 | } |
|---|
| | 524 | } |
|---|
| | 525 | } |
|---|
| | 526 | } |
|---|
| | 527 | my $count = scalar @patterns; |
|---|
| | 528 | my @eids = grep { $match{$_} == $count } keys %match |
|---|
| | 529 | or return; |
|---|
| | 530 | @eids = sort { $eindex{$b}->{created_on} <=> $eindex{$a}->{created_on} } @eids; |
|---|
| | 531 | require MT::Entry; |
|---|
| | 532 | map { push @results, MT::Entry->load($_) } @eids; |
|---|
| | 533 | # The above code is sticked to "created_on", "descend". |
|---|
| | 534 | } else { |
|---|
| | 535 | my $iter = MT::Entry->load_iter({ blog_id => $blog_id, |
|---|
| | 536 | status => MT::Entry::RELEASE() }, |
|---|
| | 537 | { sort => $sort_by, |
|---|
| | 538 | direction => $sort_order }); |
|---|
| | 539 | while (my $e = $iter->()) { |
|---|
| | 540 | next unless $e->keywords; |
|---|
| | 541 | my @tags = split_tags($e->keywords, $case_sensitive) |
|---|
| | 542 | or next; |
|---|
| | 543 | my $check = 1; |
|---|
| | 544 | foreach my $pattern (@patterns) { |
|---|
| | 545 | unless (scalar grep { $_ eq $pattern } @tags) { |
|---|
| | 546 | $check = 0; |
|---|
| | 547 | last; |
|---|
| | 548 | } |
|---|
| | 549 | } |
|---|
| | 550 | push @results, $e if $check; |
|---|
| | 551 | } |
|---|