520 lines
16 KiB
Perl
520 lines
16 KiB
Perl
# This code was forked from the LiveJournal project owned and operated
|
|
# by Live Journal, Inc. The code has been modified and expanded by
|
|
# Dreamwidth Studios, LLC. These files were originally licensed under
|
|
# the terms of the license supplied by Live Journal, Inc, which can
|
|
# currently be found at:
|
|
#
|
|
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
|
|
#
|
|
# In accordance with the original license, this code and all its
|
|
# modifications are provided under the GNU General Public License.
|
|
# A copy of that license can be found in the LICENSE file included as
|
|
# part of this distribution.
|
|
|
|
# Event that is fired when there is a new post in a journal.
|
|
# sarg1 = optional tag id to filter on
|
|
# sarg2 = optional poster id to filter on (in a community)
|
|
|
|
package LJ::Event::JournalNewEntry;
|
|
use strict;
|
|
use Scalar::Util qw(blessed);
|
|
use LJ::Entry;
|
|
use Carp qw(croak);
|
|
use base 'LJ::Event';
|
|
|
|
sub new {
|
|
my ( $class, $entry ) = @_;
|
|
croak 'Not an LJ::Entry' unless blessed $entry && $entry->isa("LJ::Entry");
|
|
return $class->SUPER::new( $entry->journal, $entry->ditemid );
|
|
}
|
|
|
|
sub arg_list {
|
|
return ("Entry ditemid");
|
|
}
|
|
|
|
sub is_common { 1 }
|
|
|
|
sub entry {
|
|
my $self = shift;
|
|
return LJ::Entry->new( $self->u, ditemid => $self->arg1 );
|
|
}
|
|
|
|
sub matches_filter {
|
|
my ( $self, $subscr ) = @_;
|
|
|
|
return 0 unless $subscr->available_for_user;
|
|
|
|
my $ditemid = $self->arg1;
|
|
my $evtju = $self->event_journal;
|
|
return 0 unless $evtju && $ditemid; # TODO: throw error?
|
|
|
|
my $entry = LJ::Entry->new( $evtju, ditemid => $ditemid );
|
|
return 0 unless $entry && $entry->valid; # TODO: throw error?
|
|
return 0 unless $entry->visible_to( $subscr->owner );
|
|
|
|
# filter by tag?
|
|
my $stagid = $subscr->arg1;
|
|
if ($stagid) {
|
|
my $usertaginfo = LJ::Tags::get_usertags( $entry->journal, { remote => $subscr->owner } );
|
|
|
|
if ($usertaginfo) {
|
|
my %tagmap = (); # tagname => tagid
|
|
while ( my ( $tagid, $taginfo ) = each %$usertaginfo ) {
|
|
$tagmap{ $taginfo->{name} } = $tagid;
|
|
}
|
|
|
|
return 0 unless grep { $tagmap{$_} == $stagid } $entry->tags;
|
|
}
|
|
}
|
|
|
|
# filter by user?
|
|
my $suserid = $subscr->arg2;
|
|
my $su = LJ::load_userid($suserid);
|
|
if ($su) {
|
|
return 0 unless $subscr->journalid && $entry->poster->equals($su);
|
|
}
|
|
|
|
# all posts by friends
|
|
return 1 if !$subscr->journalid && $subscr->owner->watches( $self->event_journal );
|
|
|
|
# a post on a specific journal
|
|
return $evtju->equals( $subscr->journal );
|
|
}
|
|
|
|
sub _can_view_content {
|
|
my ( $self, $entry, $target ) = @_;
|
|
|
|
return undef unless $entry && $entry->valid;
|
|
return undef unless $entry->visible_to($target);
|
|
|
|
return 1;
|
|
}
|
|
|
|
sub content {
|
|
my ( $self, $target ) = @_;
|
|
my $entry = $self->entry;
|
|
return undef unless $self->_can_view_content( $entry, $target );
|
|
|
|
my $entry_body = $entry->event_html(
|
|
{
|
|
# double negatives, ouch!
|
|
ljcut_disable => !$target->cut_inbox,
|
|
cuturl => $entry->url,
|
|
sandbox => 1,
|
|
preformatted => $entry->prop("opt_preformatted"),
|
|
}
|
|
) . $self->as_html_tags($target);
|
|
|
|
$entry_body = "<div class='actions_top'>" . $self->as_html_actions . "</div>" . $entry_body
|
|
if LJ::has_too_many( $entry_body, linebreaks => 10, chars => 2000 );
|
|
$entry_body .= $self->as_html_actions;
|
|
|
|
my $admin_post = "";
|
|
if ( $entry->admin_post ) {
|
|
$admin_post = '<div class="AdminPost">'
|
|
. LJ::Lang::get_default_text( "esn.journal_new_entry.admin_post",
|
|
{ img => LJ::img('admin-post') } )
|
|
. '</div>';
|
|
}
|
|
|
|
return $admin_post . $entry_body;
|
|
}
|
|
|
|
sub as_html_tags {
|
|
my ( $self, $u ) = @_;
|
|
my $tags = '';
|
|
my $url = $self->entry->journal->journal_base;
|
|
|
|
# this is retrieving the values of a hash - needs sorting
|
|
my @taglist = sort { $a cmp $b } $self->entry->tags;
|
|
|
|
# add tag info for entries that have tags
|
|
if (@taglist) {
|
|
my @htmltags = ();
|
|
push @htmltags, qq{<a href="$url/tag/$_">$_</a>} foreach @taglist;
|
|
|
|
$tags =
|
|
"<div class='entry-tags'>"
|
|
. LJ::Lang::get_default_text( 'esn.tags.short', { tags => join( ', ', @htmltags ) } )
|
|
. "</div>";
|
|
}
|
|
return $tags;
|
|
|
|
}
|
|
|
|
sub content_summary {
|
|
my ( $self, $target ) = @_;
|
|
|
|
my $entry = $self->entry;
|
|
return undef unless $self->_can_view_content( $entry, $target );
|
|
|
|
my $truncated;
|
|
my $event_summary = $entry->event_html_summary( 300, { cuturl => $entry->url }, \$truncated );
|
|
my $ret = $event_summary;
|
|
$ret .= "..." if $truncated;
|
|
$ret .= $self->as_html_actions;
|
|
|
|
return $ret;
|
|
}
|
|
|
|
sub as_string {
|
|
my $self = shift;
|
|
my $entry = $self->entry;
|
|
my $about = $entry->subject_text ? ' titled "' . $entry->subject_text . '"' : '';
|
|
my $poster = $entry->poster->user;
|
|
my $journal = $entry->journal->user;
|
|
|
|
return "$poster has posted a new entry$about at " . $entry->url
|
|
if $entry->journal->is_person;
|
|
|
|
return "$poster has posted a new entry$about in $journal at " . $entry->url;
|
|
}
|
|
|
|
sub as_html {
|
|
my ( $self, $target ) = @_;
|
|
|
|
croak "No target passed to as_html" unless LJ::isu($target);
|
|
|
|
my $journal = $self->u;
|
|
my $entry = $self->entry;
|
|
|
|
return sprintf( "(Deleted entry in %s)", $journal->ljuser_display )
|
|
unless $entry && $entry->valid;
|
|
return "(You are not authorized to view this entry)"
|
|
unless $self->entry->visible_to($target);
|
|
|
|
my $ju = LJ::ljuser($journal);
|
|
my $pu = LJ::ljuser( $entry->poster );
|
|
my $url = $entry->url;
|
|
|
|
my $about = $entry->subject_text ? ' titled "' . $entry->subject_text . '"' : '';
|
|
my $where = $journal->equals( $entry->poster ) ? "$pu" : "$pu in $ju";
|
|
|
|
return "New <a href=\"$url\">entry</a>$about by $where.";
|
|
}
|
|
|
|
sub as_html_actions {
|
|
my ($self) = @_;
|
|
|
|
my $entry = $self->entry;
|
|
my $url = $entry->url;
|
|
my $reply_url = $entry->url( mode => 'reply' );
|
|
|
|
my $ret .= "<div class='actions'>";
|
|
$ret .= " <a href='$reply_url'>Reply</a> |";
|
|
$ret .= " <a href='$url'>Link</a>";
|
|
$ret .= "</div>";
|
|
|
|
return $ret;
|
|
}
|
|
|
|
my @_ml_strings_en = (
|
|
'esn.journal_new_entry.posted_new_entry', # '[[who]] posted a new entry in [[journal]]!',
|
|
'esn.journal_new_entry.updated_their_journal', # '[[who]] updated their journal!',
|
|
'esn.hi', # 'Hi [[username]],',
|
|
'esn.journal_new_entry.about', # ' titled "[[title]]"',
|
|
'esn.tags', # 'The entry is tagged "[[tags]]"',
|
|
'esn.tags.short',
|
|
'esn.journal_new_entry.head_comm2'
|
|
, # 'There is a new entry by [[poster]][[about]][[postsecurity]] in [[journal]]![[tags]]',
|
|
'esn.journal_new_entry.head_user2'
|
|
, # '[[poster]] has posted a new entry[[about]][[postsecurity]].[[tags]]',
|
|
'esn.you_can', # 'You can:',
|
|
'esn.view_entry.nosubject', # '[[openlink]]View entry [[ditemid]][[closelink]]'
|
|
'esn.view_entry.subject', # '[[openlink]]View entry titled [[subject]][[closelink]]',
|
|
'esn.reply_to_entry', # '[[openlink]]Leave a reply to this entry[[closelink]]',
|
|
'esn.read_recent_entries', # '[[openlink]]Read the recent entries in [[journal]][[closelink]]',
|
|
'esn.join_community'
|
|
, # '[[openlink]]Join [[journal]] to read Members-only entries[[closelink]]',
|
|
'esn.read_user_entries', # '[[openlink]]Read [[poster]]\'s recent entries[[closelink]]',
|
|
'esn.add_watch' # '[[openlink]]Subscribe to [[journal]][[closelink]]',
|
|
);
|
|
|
|
sub as_email_subject {
|
|
my ( $self, $u ) = @_;
|
|
|
|
# Precache text lines
|
|
LJ::Lang::get_default_text_multi( \@_ml_strings_en );
|
|
|
|
if ( $self->entry->journal->is_comm ) {
|
|
return LJ::Lang::get_default_text(
|
|
'esn.journal_new_entry.posted_new_entry',
|
|
{
|
|
who => $self->entry->poster->display_username,
|
|
journal => $self->entry->journal->display_username,
|
|
}
|
|
);
|
|
}
|
|
else {
|
|
return LJ::Lang::get_default_text(
|
|
'esn.journal_new_entry.updated_their_journal',
|
|
{
|
|
who => $self->entry->journal->display_username,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
sub _as_email {
|
|
my ( $self, $u, $is_html ) = @_;
|
|
|
|
my $username = $is_html ? $u->ljuser_display : $u->display_username;
|
|
|
|
my $poster_text = $self->entry->poster->display_username;
|
|
my $poster = $is_html ? $self->entry->poster->ljuser_display : $poster_text;
|
|
|
|
# $journal - html or plaintext version depends of $is_html
|
|
# $journal_text - text version
|
|
# $journal_user - text version, local journal user (ext_* if OpenId).
|
|
|
|
my $journal_text = $self->entry->journal->display_username;
|
|
my $journal = $is_html ? $self->entry->journal->ljuser_display : $journal_text;
|
|
my $journal_user = $self->entry->journal->user;
|
|
|
|
my $entry_url = $self->entry->url;
|
|
my $journal_url = $self->entry->journal->journal_base;
|
|
|
|
my $subject_text = $self->entry->subject_text;
|
|
|
|
# Precache text lines, using DEFAULT_LANG for $u
|
|
my $lang = $LJ::DEFAULT_LANG;
|
|
LJ::Lang::get_text_multi( $lang, undef, \@_ml_strings_en );
|
|
|
|
my $email = LJ::Lang::get_text( $lang, 'esn.hi', undef, { username => $username } ) . "\n\n";
|
|
my $about =
|
|
$subject_text
|
|
? (
|
|
LJ::Lang::get_text(
|
|
$lang, 'esn.journal_new_entry.about',
|
|
undef, { title => $self->entry->subject_text }
|
|
)
|
|
)
|
|
: '';
|
|
|
|
my $tags = '';
|
|
|
|
# add tag info for entries that have tags
|
|
if ( my @taglist = sort { $a cmp $b } $self->entry->tags ) {
|
|
$tags = ' '
|
|
. LJ::Lang::get_text( $lang, 'esn.tags', undef, { tags => join( ', ', @taglist ) } );
|
|
}
|
|
|
|
# indicate post security if it is locked or filtered
|
|
my $postsecurity = '';
|
|
if ( $self->entry->security eq 'usemask' ) {
|
|
$postsecurity = ' [locked]';
|
|
}
|
|
|
|
my $head_ml = 'esn.journal_new_entry.head_user2';
|
|
my $entry = $self->entry;
|
|
if ( $entry->journal->is_comm ) {
|
|
$head_ml = 'esn.journal_new_entry.head_comm2';
|
|
|
|
$head_ml .= '.admin_post'
|
|
if $entry->admin_post;
|
|
}
|
|
|
|
$email .= LJ::Lang::get_text(
|
|
$lang, $head_ml, undef,
|
|
{
|
|
poster => $poster,
|
|
about => $about,
|
|
journal => $journal,
|
|
tags => $tags,
|
|
}
|
|
) . "\n\n";
|
|
|
|
# make hyperlinks for options
|
|
# tags 'poster' and 'journal' cannot contain html <a> tags
|
|
# when it used between [[openlink]] and [[closelink]] tags.
|
|
my $vars = {
|
|
poster => $poster_text,
|
|
journal => $journal_text,
|
|
ditemid => $self->entry->ditemid,
|
|
subject => $subject_text,
|
|
};
|
|
|
|
my $has_subject = $subject_text ? "subject" : "nosubject";
|
|
$email .= LJ::Lang::get_text( $lang, 'esn.you_can', undef )
|
|
. $self->format_options(
|
|
$is_html, $lang, $vars,
|
|
{
|
|
"esn.view_entry.$has_subject" => [ 1, $entry_url ],
|
|
'esn.reply_to_entry' => [ 2, "$entry_url?mode=reply" ],
|
|
'esn.read_recent_entries' => [ $self->entry->journal->is_comm ? 3 : 0, $journal_url ],
|
|
'esn.join_community' => [
|
|
( $self->entry->journal->is_comm && !$u->member_of( $self->entry->journal ) )
|
|
? 4
|
|
: 0,
|
|
"$LJ::SITEROOT/circle/$journal_user/edit"
|
|
],
|
|
'esn.read_user_entries' => [ ( $self->entry->journal->is_comm ) ? 0 : 5, $journal_url ],
|
|
'esn.add_watch' => [
|
|
$u->watches( $self->entry->journal ) ? 0 : 6,
|
|
"$LJ::SITEROOT/circle/$journal_user/edit?action=subscribe"
|
|
],
|
|
}
|
|
);
|
|
|
|
return $email;
|
|
}
|
|
|
|
sub as_email_string {
|
|
my ( $self, $u ) = @_;
|
|
return unless $self->entry && $self->entry->valid;
|
|
|
|
return _as_email( $self, $u, 0 );
|
|
}
|
|
|
|
sub as_email_html {
|
|
my ( $self, $u ) = @_;
|
|
return unless $self->entry && $self->entry->valid;
|
|
|
|
return _as_email( $self, $u, 1 );
|
|
}
|
|
|
|
sub subscription_applicable {
|
|
my ( $class, $subscr ) = @_;
|
|
|
|
return 1 unless $subscr->arg1;
|
|
|
|
# subscription is for entries with tags.
|
|
# not applicable if user has no tags
|
|
my $journal = $subscr->journal;
|
|
|
|
return 1 unless $journal; # ?
|
|
|
|
my $usertags = LJ::Tags::get_usertags($journal);
|
|
|
|
if ( $usertags && ( scalar keys %$usertags ) ) {
|
|
my @unsub = $class->unsubscribed_tags($subscr);
|
|
return ( scalar @unsub ) ? 1 : 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
# returns list of (hashref of (tagid => name))
|
|
sub unsubscribed_tags {
|
|
my ( $class, $subscr ) = @_;
|
|
|
|
my $journal = $subscr->journal;
|
|
return () unless $journal;
|
|
|
|
my $usertags = LJ::Tags::get_usertags( $journal, { remote => $subscr->owner } );
|
|
return () unless $usertags;
|
|
|
|
my @tagids = sort { $usertags->{$a}->{name} cmp $usertags->{$b}->{name} } keys %$usertags;
|
|
return grep { $_ } map {
|
|
$subscr->owner->has_subscription(
|
|
etypeid => $class->etypeid,
|
|
arg1 => $_,
|
|
journal => $journal
|
|
) ? undef : { $_ => $usertags->{$_}->{name} };
|
|
} @tagids;
|
|
}
|
|
|
|
sub subscription_as_html {
|
|
my ( $class, $subscr ) = @_;
|
|
|
|
my $journal = $subscr->journal;
|
|
|
|
# are we filtering on a tag?
|
|
my $arg1 = $subscr->arg1;
|
|
my $usertags;
|
|
|
|
if ( $arg1 eq '?' ) {
|
|
my @unsub_tags = $class->unsubscribed_tags($subscr);
|
|
my %entry_tags = $subscr->entry ? map { $_ => 1 } $subscr->entry->tags : ();
|
|
|
|
my @entrytagdropdown;
|
|
my @fulltagdropdown;
|
|
|
|
foreach my $unsub_tag (@unsub_tags) {
|
|
while ( my ( $tagid, $name ) = each %$unsub_tag ) {
|
|
if ( $entry_tags{$name} ) {
|
|
push @entrytagdropdown, { value => $tagid, text => $name };
|
|
}
|
|
else {
|
|
push @fulltagdropdown, { value => $tagid, text => $name };
|
|
}
|
|
}
|
|
}
|
|
|
|
my @tagdropdown;
|
|
|
|
if (@entrytagdropdown) {
|
|
@tagdropdown = (
|
|
{
|
|
optgroup => LJ::Lang::ml('event.journal_new_entry.taglist.entry'),
|
|
items => \@entrytagdropdown
|
|
},
|
|
{
|
|
optgroup => LJ::Lang::ml('event.journal_new_entry.taglist.full'),
|
|
items => \@fulltagdropdown
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
@tagdropdown = @fulltagdropdown;
|
|
}
|
|
|
|
$usertags = LJ::html_select(
|
|
{
|
|
name => $subscr->freeze('arg1'),
|
|
},
|
|
@tagdropdown
|
|
);
|
|
|
|
}
|
|
elsif ($arg1) {
|
|
$usertags =
|
|
LJ::Tags::get_usertags( $journal, { remote => $subscr->owner } )->{$arg1}->{'name'};
|
|
}
|
|
|
|
if ($arg1) {
|
|
return BML::ml(
|
|
'event.journal_new_entry.tag.' . ( $journal->is_comm ? 'community' : 'user' ),
|
|
{
|
|
user => $journal->ljuser_display,
|
|
tags => $usertags,
|
|
}
|
|
);
|
|
}
|
|
|
|
# are we filtering on a poster?
|
|
my $arg2 = $subscr->arg2;
|
|
|
|
if ($arg2) {
|
|
my $postu = LJ::load_userid($arg2);
|
|
if ($postu) {
|
|
return BML::ml(
|
|
'event.journal_new_entry.poster',
|
|
{
|
|
user => $journal->ljuser_display,
|
|
poster => $postu->ljuser_display,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
return BML::ml('event.journal_new_entry.friendlist') unless $journal;
|
|
|
|
return BML::ml(
|
|
'event.journal_new_entry.' . ( $journal->is_comm ? 'community' : 'user' ),
|
|
{
|
|
user => $journal->ljuser_display,
|
|
}
|
|
);
|
|
}
|
|
|
|
# when was this entry made?
|
|
sub eventtime_unix {
|
|
my $self = shift;
|
|
my $entry = $self->entry;
|
|
return $entry ? $entry->logtime_unix : $self->SUPER::eventtime_unix;
|
|
}
|
|
|
|
sub zero_journalid_subs_means { undef }
|
|
|
|
1;
|