Committer: sbelyaev
Updated: user interface (for sticky and dalayed entries), added new tables for delayed entries,added delayed entries url support
U branches/delayed_entries/bin/upgrading/update-db-general.pl U branches/delayed_entries/cgi-bin/Apache/LiveJournal.pm U branches/delayed_entries/cgi-bin/LJ/Entry.pm U branches/delayed_entries/cgi-bin/LJ/User.pm U branches/delayed_entries/cgi-bin/LJ/Widget/EntryForm.pm U branches/delayed_entries/cgi-bin/ljlib.pl
Modified: branches/delayed_entries/bin/upgrading/update-db-general.pl =================================================================== --- branches/delayed_entries/bin/upgrading/update-db-general.pl 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/bin/upgrading/update-db-general.pl 2011-08-18 13:01:21 UTC (rev 19775) @@ -998,6 +998,38 @@ ) EOC +register_tablecreate("delayedlog2", <<'EOC'); # clustered +CREATE TABLE delayedlog2 ( + journalid INT UNSIGNED NOT NULL, + delayedid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, delayedid), + posterid INT UNSIGNED NOT NULL, + subject CHAR(30), + logtime DATETIME, + posttime DATETIME, + security enum('public','private','usemask') NOT NULL default 'public', + allowmask int(10) unsigned NOT NULL default '0', + year smallint(6) NOT NULL default '0', + month tinyint(4) NOT NULL default '0', + day tinyint(4) NOT NULL default '0', + rlogtime int(10) unsigned NOT NULL default '0', + revptime int(10) unsigned NOT NULL default '0', + KEY (journalid, logtime, posttime, year, month, day), + KEY `rlogtime` (`journalid`,`rlogtime`), + KEY `revptime` (`journalid`,`revptime`) +) +EOC + +# delayed post Storable object (all props/options) +register_tablecreate("delayedblob2", <<'EOC'); # clustered +CREATE TABLE delayedblob2 ( + journalid INT UNSIGNED NOT NULL, + delayedid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, delayedid), + request_stor MEDIUMBLOB +) +EOC + register_tabledrop("ibill_codes"); register_tabledrop("paycredit"); register_tabledrop("payments"); Modified: branches/delayed_entries/cgi-bin/Apache/LiveJournal.pm =================================================================== --- branches/delayed_entries/cgi-bin/Apache/LiveJournal.pm 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/cgi-bin/Apache/LiveJournal.pm 2011-08-18 13:01:21 UTC (rev 19775) @@ -788,8 +788,23 @@ $mode = "entry"; } - } - elsif ( $uuri =~ m|^/(\d\d\d\d)(?:/(\d\d)(?:/(\d\d))?)?(/?)$| ) { + } elsif ($uuri =~ m|^/d(\d+)\.html$|) { + my $u = LJ::load_user($user); + + unless ($u) { + LJ::Request->pnotes ('error' => 'baduser'); + LJ::Request->pnotes ('remote' => LJ::get_remote()); + return LJ::Request::NOT_FOUND; + } + + $ljentry = LJ::DelayedEntry->get_entry_by_id($u, $1); + + if ( $GET{'mode'} eq "reply" || $GET{'replyto'} || $GET{'edit'} ) { + $mode = "reply"; + } else { + $mode = "entry"; + } + } elsif ( $uuri =~ m|^/(\d\d\d\d)(?:/(\d\d)(?:/(\d\d))?)?(/?)$| ) { my ($year, $mon, $day, $slash) = ($1, $2, $3, $4); unless ( $slash ) { Modified: branches/delayed_entries/cgi-bin/LJ/Entry.pm =================================================================== --- branches/delayed_entries/cgi-bin/LJ/Entry.pm 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/cgi-bin/LJ/Entry.pm 2011-08-18 13:01:21 UTC (rev 19775) @@ -157,6 +157,17 @@ return $entry; } +sub is_delayed { + my ($class) = @_; + return 0; +} + +sub delayedid { + my ($class) = @_; + return 0; +} + + sub new_from_url { my ($class, $url) = @_; @@ -277,7 +288,7 @@ sub eventtime_mysql { my $self = shift; __PACKAGE__->preload_rows([ $self ]) unless $self->{_loaded_row}; - return $self->{eventtime}; + return $self->{eventtime}; } sub logtime_mysql { @@ -1812,8 +1823,7 @@ sub get_log2_recent_log { - my ($u, $cid, $update, $notafter, $events_date, $exclude_sticky) = @_; - $exclude_sticky = $exclude_sticky || 0; # optional + my ($u, $cid, $update, $notafter, $events_date) = @_; my $jid = LJ::want_userid($u); $cid ||= $u->{'clusterid'} if ref $u; @@ -1944,15 +1954,6 @@ "AND rlogtime <= ($LJ::EndOfTime - UNIX_TIMESTAMP()) + $max_age" ); - if ( $exclude_sticky ) { - my $uobj = LJ::want_user($u); - my $sticky = $uobj->get_sticky_entry(); - - if ($sticky) { - $sql .= " AND jitemid <> $sticky"; - } - } - my $sth = $db->prepare($sql); $sth->execute($jid); my @row = (); @@ -2000,8 +2001,7 @@ my $ret = []; my $log = LJ::get_log2_recent_log($opts->{'userid'}, $opts->{'clusterid'}, - $opts->{'update'}, $opts->{'notafter'}, $opts->{events_date}, - $opts->{'exclude_sticky'}); + $opts->{'update'}, $opts->{'notafter'}, $opts->{events_date},); ## UNUSED: my $left = $opts->{'itemshow'}; my $notafter = $opts->{'notafter'}; Modified: branches/delayed_entries/cgi-bin/LJ/User.pm =================================================================== --- branches/delayed_entries/cgi-bin/LJ/User.pm 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/cgi-bin/LJ/User.pm 2011-08-18 13:01:21 UTC (rev 19775) @@ -6148,6 +6148,12 @@ return 0; } +# return sticky entries existing +sub has_sticky_entry { + my ($self) = @_; + return !!$self->prop("sticky_entries"); +} + # returns sticky entry jitemid sub get_sticky_entry { my ($self) = @_; @@ -7029,6 +7035,7 @@ # 'O' == pOrtal box id, 'V' == 'vgift', 'E' == ESN subscription id # 'Q' == Notification Inbox, 'G' == 'SMS messaGe' # 'D' == 'moDule embed contents', 'W' == 'Wish-list element' +# 'Y' == delaYed entries # # FIXME: both phonepost and vgift are ljcom. need hooks. but then also # need a separate namespace. perhaps a separate function/table? @@ -7039,7 +7046,7 @@ ################################################################## # IF YOU UPDATE THIS MAKE SURE YOU ADD INITIALIZATION CODE BELOW # - return undef unless $dom =~ /^[LTMPSRKCOVEQGDW]$/; # + return undef unless $dom =~ /^[LTMPSRKCOVEQGDWY]$/; # ################################################################## my $dbh = LJ::get_db_writer(); @@ -7157,6 +7164,9 @@ } elsif ($dom eq "W") { $newmax = $u->selectrow_array("SELECT MAX(wishid) FROM wishlist2 WHERE userid=?", undef, $uid); + } elsif ($dom eq "Y") { + $newmax = $u->selectrow_array("SELECT MAX(delayedid) FROM delayedlog2 WHERE journalid=?", + undef, $uid); } else { die "No user counter initializer defined for area '$dom'.\n"; } @@ -7768,6 +7778,14 @@ # so they store smaller in memcache push @days, [ int($y), int($m), int($d), int($c) ]; } + + $sth = LJ::DelayedEntry->get_daycount_query($u, $secwhere); + while (my ($y, $m, $d, $c) = $sth->fetchrow_array) { + # we force each number from string scalars (from DBI) to int scalars, + # so they store smaller in memcache + push @days, [ int($y), int($m), int($d), int($c) ]; + } + LJ::MemCache::set($memkey, [time, @days]); $release_lock->(); return \@days; Modified: branches/delayed_entries/cgi-bin/LJ/Widget/EntryForm.pm =================================================================== --- branches/delayed_entries/cgi-bin/LJ/Widget/EntryForm.pm 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/cgi-bin/LJ/Widget/EntryForm.pm 2011-08-18 13:01:21 UTC (rev 19775) @@ -480,17 +480,9 @@ $datetime .= "<noscript>" . LJ::html_hidden("date_diff_nojs", "1") . "</noscript>"; - my $backdate_check = LJ::html_check({ - 'type' => "check", - 'id' => "prop_opt_backdated", - 'name' => "prop_opt_backdated", - "value" => 1, - 'selected' => $opts->{'prop_opt_backdated'}, - 'tabindex' => $self->tabindex - }); + my $timeZones = option($remote); + my $help_icon = LJ::help_icon("24hourshelp"); - my $backdate_help_icon = LJ::help_icon_html("backdate", "", ""); - $out .= qq{ <p class='pkg'> <label for='modifydate' class='left'> @@ -502,15 +494,13 @@ </span> <a href='javascript:void(0)' onclick='editdate();' id='currentdate-edit'>$BML::ML{'entryform.date.edit'}</a> + $help_icon </span> <span id='modifydate'>$datetime <?de $BML::ML{'entryform.date.24hournote'} de?> + <br /> - $backdate_check - <label for='prop_opt_backdated' class='right'> - $BML::ML{'entryform.backdated3'} - </label> - $backdate_help_icon + $timeZones </span><!-- end #modifydate --> </p> <noscript> @@ -520,19 +510,6 @@ </noscript> }; - my $sticky = ''; - if ($opts->{jitemid}) { - my $journalu = LJ::load_user($opts->{'usejournal'}) || $remote; - my $sticky_entry = $journalu->get_sticky_entry(); - $sticky = 'checked' if ( $sticky_entry eq $opts->{jitemid}); - } - - $out .= qq{ <p id='sticky_checkbox'class='pkg'> - <input type='checkbox' name='type' value='sticky' $sticky> - $BML::ML{'entryform.sticky.edit'} - </input> - </p> }; - $$onload .= " defaultDate();"; # User Picture @@ -744,6 +721,36 @@ $out .= "<div id='options' class='pkg'>"; my %blocks = ( + 'sticky' => sub { + my $is_checked = sub { + if ($opts->{jitemid}) { + my $journalu = LJ::load_user($opts->{'usejournal'}) || $remote; + my $sticky_entry = $journalu->get_sticky_entry(); + if ( $sticky_entry eq $opts->{jitemid} ) { + return 'checked' + } + } + + if ($opts->{delayed_sticky}) { + return 'checked' + } + }; + + my $sticky_check = LJ::html_check({ + 'type' => "check", + 'class' => 'sticky_type', + 'value' => 'sticky', + 'name' => 'type', + 'id' => 'sticky_type', + 'selected' => $is_checked->(), + $opts->{'prop_opt_preformatted'} || $opts->{'event_format'}, + 'label' => "", + }); + + return qq{$sticky_check <label for='prop_sticky' class='right options'> + $BML::ML{'entryform.sticky.edit'} + </label>}; + }, 'tags' => sub { return if $LJ::DISABLED{'tags'}; @@ -1074,40 +1081,6 @@ }, 'spellcheck' => sub { my $out = ''; - - # extra submit button so make sure it posts the form when - # person presses enter key - my %action_map = ( - 'edit' => 'save', - 'update' => 'update', - ); - if (my $action = $action_map{$opts->{'mode'}}) { - $out .= qq{ - <input type='submit' name='action:$action' - class='hidden_submit' /> - }; - } - my $preview_tabindex = $self->tabindex; - my $preview = qq{ - <input - type="button" - value="$BML::ML{'entryform.preview'}" - onclick="entryPreview(this.form)" - tabindex="$preview_tabindex" - /> - }; - $preview =~ s/\s+/ /sg; # JS doesn't like newlines in string - # literals - - unless ($opts->{'disabled_save'}) { - $out .= $self->wrap_js(qq{ - if (document.getElementById) { - setTimeout( function() { - jQuery( '$preview' ).prependTo( '#entryform-spellcheck-wrapper' ); - }, 0 ); - } - }); - } if ($LJ::SPELLER && !$opts->{'disabled_save'}) { $out .= LJ::html_submit( 'action:spellcheck', @@ -1115,8 +1088,10 @@ { 'tabindex' => $self->tabindex } ) . " "; } - - return $out; + + return qq{<label for='prop_sticky' class='right options'> + $BML::ML{'entryform.spellcheck'} + </label> $out}; }, ); @@ -1125,8 +1100,9 @@ [ 'mood', 'comment_settings' ], [ 'location', 'comment_screening' ], [ 'music', 'content_flag' ], + [ 'spellcheck', 'sticky' ], 'extra', - [ 'lastfm_logo', 'spellcheck' ], + [ 'lastfm_logo' ], ); unless ($opts->{'disabled_save'}) { @@ -1278,7 +1254,44 @@ $out .= "<div id='security_container'>\n"; $out .= "<label for='security'>" . BML::ml('entryform.security2') . " </label>\n"; + + # preview button + + # extra submit button so make sure it posts the form when + # person presses enter key + my %action_map = ( 'edit' => 'save', + 'update' => 'update', ); + + if (my $action = $action_map{$opts->{'mode'}}) { + $out .= qq{ + <input type='submit' name='action:$action' + class='hidden_submit' /> + }; + } + + my $preview_tabindex = $self->tabindex; + my $preview = qq{ + <input + type="button" + value="$BML::ML{'entryform.preview'}" + onclick="entryPreview(this.form)" + tabindex="$preview_tabindex" + /> + }; + $preview =~ s/\s+/ /sg; # JS doesn't like newlines in string + # literals + + unless ($opts->{'disabled_save'}) { + $out .= $self->wrap_js(qq{ + if (document.getElementById) { + setTimeout( function() { + jQuery( '$preview' ).prependTo('#entryform-update-and-edit' ); + }, 0 ); + } + }); + } + $out .= $self->render_security_container_block; if ($opts->{'mode'} eq "update") { my $onclick = ""; @@ -1297,6 +1310,7 @@ } my $disabled = $remote && $remote->is_identity && !$self->usejournal; + $out .= qq{ <div id="entryform-update-and-edit"> }; $out .= LJ::html_submit( 'action:update', @@ -1309,11 +1323,12 @@ 'disabled' => $disabled, } ) . " \n"; + $out .= qq{</div>}; } if ($opts->{'mode'} eq "edit") { my $onclick = $LJ::IS_SSL ? '' : 'return true;'; - + $out .= qq{ <div id="entryform-update-and-edit"> }; $out .= LJ::html_submit( 'action:save', BML::ml('entryform.save'), @@ -1358,8 +1373,10 @@ } ) . "\n"; } + $out .= qq{</div>}; } + $out .= "</div><!-- end #security_container -->\n\n"; $out .= "</div><!-- end #submitbar -->\n\n"; @@ -1518,4 +1535,51 @@ return $out; } +# this one returns a $key => $value list, ordered by keys this way: +# US goes first, then Canada, then all the rest +sub timezone_options { + my $map = DateTime::TimeZone::links(); + + my ( @options, %options ); + + push @options, '' => BML::ml('setting.timezone.option.select'); + + foreach my $key ( sort keys %$map ) { + if ( $key =~ m!^US/! && $key ne 'US/Pacific-New' ) { + $options{ $map->{$key} } = $key; + push @options, $map->{$key} => $key; + } + } + + foreach my $key ( sort keys %$map ) { + if ( $key =~ m!^Canada/! ) { + $options{ $map->{$key} } = $key; + push @options, $map->{$key} => $key; + } + } + + foreach my $key ( DateTime::TimeZone::all_names() ) { + next if $options{$key}; + push @options, $key => $key; + } + + return @options; +} + +sub option { + my ($u) = @_; + + my $timezone = $u->prop("timezone"); + my @options = timezone_options; + + my $ret = LJ::html_select({ + name => "delayed_timezone", + selected => $timezone, + }, @options); + + $ret .= "<br />"; + + return $ret; +} + 1; Modified: branches/delayed_entries/cgi-bin/ljlib.pl =================================================================== --- branches/delayed_entries/cgi-bin/ljlib.pl 2011-08-18 12:44:39 UTC (rev 19774) +++ branches/delayed_entries/cgi-bin/ljlib.pl 2011-08-18 13:01:21 UTC (rev 19775) @@ -104,7 +104,7 @@ "logprop_history", "comet_history", "pingrel", "eventrates", "eventratescounters", - "friending_actions_q", + "friending_actions_q", "delayedlog2", "delayedblob2", ); # keep track of what db locks we have out @@ -916,7 +916,6 @@ 'dateformat' => $opts->{'dateformat'}, 'update' => $LJ::EndOfTime - $fr->[1], # reverse back to normal 'events_date' => $events_date, - 'exclude_sticky' => 1, }); # stamp each with clusterid if from cluster, so ljviews and other @@ -1097,7 +1096,7 @@ $remote = LJ::load_userid($remoteid); } - my $exclude_sticky = $opts->{exclude_sticky} || 0; + my $show_sticky_on_top = $opts->{show_sticky_on_top} || 0; my $max_hints = $LJ::MAX_SCROLLBACK_LASTN; # temporary my $sort_key = "revttime"; @@ -1139,18 +1138,18 @@ if ($skip < 0) { $skip = 0; } if ($skip > $maxskip) { $skip = $maxskip; } my $itemload = $itemshow + $skip; - - # - # modificate 'usual elements to be shown' - # + my $usual_show = $itemshow; - # begin point - $skip = ($skip - 1) if ( $sticky && $skip > 0); - # elements count - my $usual_show = $skip > 0 ? $itemshow : $itemshow - 1; - + if ($show_sticky_on_top && $sticky && $skip > 0) + { + $skip -= 1; + } else { + $usual_show -= 1 if $sticky; + } + my $mask = 0; - if ($remote && ($remote->{'journaltype'} eq "P" || $remote->{'journaltype'} eq "I") && $remoteid != $userid) { + if ($remote && ($remote->{'journaltype'} eq "P" || + $remote->{'journaltype'} eq "I") && $remoteid != $userid) { $mask = LJ::get_groupmask($userid, $remoteid); } @@ -1306,9 +1305,9 @@ WHERE journalid=$userid $sql_select $secwhere $jitemidwhere $securitywhere $posterwhere $after_sql $suspend_where }; - if ($sticky) { + if ( $sticky && $show_sticky_on_top ) { # build request to receive sticky entries - if (!$skip && !$exclude_sticky) { + if (!$skip) { $sticky_sql = "$sql AND jitemid = $sticky "; $sticky_sql .= "ORDER BY journalid, $sort_key "; } @@ -1319,7 +1318,7 @@ $sql .= qq{ ORDER BY journalid, $sort_key - $sql_limit}; + $sql_limit }; unless ($logdb) { $$err = "nodb" if ref $err eq "SCALAR"; @@ -1356,7 +1355,7 @@ } }; - $absorb_data->($sticky_sql) if ( $sticky && !$skip && !$exclude_sticky ); + $absorb_data->($sticky_sql) if ( $sticky && !$skip && $show_sticky_on_top); $absorb_data->($sql); $flush->();