From b596391fcd05dddc8c37495b663d3be074eac05d Mon Sep 17 00:00:00 2001
From: Mikael Nordfeldth <mmn@hethane.se>
Date: Wed, 6 Jan 2016 15:32:00 +0100
Subject: [PATCH] Avoid having to check for notices without rendered copies in
 upgrade.php

Always call the Notice->getRendered() function to get a rendered copy.
We could perhaps put some sanitation there too in the future
---
 actions/apisearchatom.php                     |  2 +-
 classes/Notice.php                            | 13 ++++++++++--
 lib/apiaction.php                             |  4 ++--
 lib/rss10action.php                           |  4 ++--
 plugins/Activity/lib/systemlistitem.php       |  2 +-
 plugins/Activity/lib/unfollowlistitem.php     |  2 +-
 .../ActivityModerationPlugin.php              |  2 --
 .../ActivityVerbPostPlugin.php                |  4 ++--
 .../DirectionDetectorPlugin.php               |  1 +
 .../lib/useremailsummaryhandler.php           |  2 +-
 plugins/Favorite/classes/Fave.php             |  6 +++---
 plugins/Linkback/lib/util.php                 |  2 +-
 plugins/Mapstraction/actions/map.php          |  2 +-
 plugins/Oembed/actions/oembed.php             |  2 +-
 plugins/Realtime/RealtimePlugin.php           |  4 ++--
 plugins/Share/SharePlugin.php                 |  2 +-
 plugins/SubMirror/classes/SubMirror.php       |  2 +-
 scripts/upgrade.php                           | 21 -------------------
 18 files changed, 32 insertions(+), 45 deletions(-)

diff --git a/actions/apisearchatom.php b/actions/apisearchatom.php
index b686edb00a..7e79808a96 100644
--- a/actions/apisearchatom.php
+++ b/actions/apisearchatom.php
@@ -327,7 +327,7 @@ class ApiSearchAtomAction extends ApiPrivateAuthAction
                                      'rel'  => 'alternate',
                                      'href' => $nurl));
         $this->element('title', null, common_xml_safe_str(trim($notice->content)));
-        $this->element('content', array('type' => 'html'), $notice->rendered);
+        $this->element('content', array('type' => 'html'), $notice->getRendered());
         $this->element('updated', null, common_date_w3dtf($notice->created));
         $this->element('link', array('type' => 'image/png',
                                      // XXX: Twitter uses rel="image" (not valid)
diff --git a/classes/Notice.php b/classes/Notice.php
index 138c9f1b64..25e8da4aaf 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -259,6 +259,14 @@ class Notice extends Managed_DataObject
 
     public function getRendered()
     {
+        if (is_null($this->rendered) || $this->rendered === '') {
+            // update to include rendered content on-the-fly, so we don't have to have a fix-up script in upgrade.php
+            $orig = clone($this);
+            $this->rendered = common_render_content($this->getContent(),
+                                                    $this->getProfile(),
+                                                    $this->hasParent() ? $this->getParent() : null);
+            $this->update($orig);
+        }
         return $this->rendered;
     }
 
@@ -816,6 +824,7 @@ class Notice extends Managed_DataObject
             $content = $actobj->content ?: $actobj->summary;
         }
         $stored->rendered = $actor->isLocal() ? $content : common_purify($content);
+        // yeah, just don't use getRendered() here since it's not inserted yet ;)
         $stored->content = common_strip_html($stored->rendered);
 
         // Maybe a missing act-time should be fatal if the actor is not local?
@@ -1835,7 +1844,7 @@ class Notice extends Managed_DataObject
                 // The notice is probably a share or similar, which don't
                 // have a representational URL of their own.
             }
-            $act->content = common_xml_safe_str($this->rendered);
+            $act->content = common_xml_safe_str($this->getRendered());
 
             $profile = $this->getProfile();
 
@@ -2069,7 +2078,7 @@ class Notice extends Managed_DataObject
             $object->id      = $this->getUri();
             //FIXME: = $object->title ?: sprintf(... because we might get a title from StartActivityObjectFromNotice
             $object->title   = sprintf('New %1$s by %2$s', ActivityObject::canonicalType($object->type), $this->getProfile()->getNickname());
-            $object->content = $this->rendered;
+            $object->content = $this->getRendered();
             $object->link    = $this->getUrl();
 
             $object->extra[] = array('status_net', array('notice_id' => $this->id));
diff --git a/lib/apiaction.php b/lib/apiaction.php
index 9a574008aa..8420bfb51e 100644
--- a/lib/apiaction.php
+++ b/lib/apiaction.php
@@ -408,7 +408,7 @@ class ApiAction extends Action
 
         // StatusNet-specific
 
-        $twitter_status['statusnet_html'] = $notice->rendered;
+        $twitter_status['statusnet_html'] = $notice->getRendered();
         $twitter_status['statusnet_conversation_id'] = intval($notice->conversation);
 
         // The event call to handle NoticeSimpleStatusArray lets plugins add data to the output array
@@ -503,7 +503,7 @@ class ApiAction extends Action
 
             // We trim() to avoid extraneous whitespace in the output
 
-            $entry['content'] = common_xml_safe_str(trim($notice->rendered));
+            $entry['content'] = common_xml_safe_str(trim($notice->getRendered()));
             $entry['title'] = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content));
             $entry['link'] = common_local_url('shownotice', array('notice' => $notice->id));
             $entry['published'] = common_date_iso8601($notice->created);
diff --git a/lib/rss10action.php b/lib/rss10action.php
index 137015530b..6940ab4319 100644
--- a/lib/rss10action.php
+++ b/lib/rss10action.php
@@ -209,8 +209,8 @@ class Rss10Action extends ManagedAction
         $this->element('title', null, $title);
         $this->element('link', null, $nurl);
         $this->element('description', null, $profile->nickname."'s status on ".common_exact_date($notice->created));
-        if ($notice->rendered) {
-            $this->element('content:encoded', null, common_xml_safe_str($notice->rendered));
+        if ($notice->getRendered()) {
+            $this->element('content:encoded', null, common_xml_safe_str($notice->getRendered()));
         }
         $this->element('dc:date', null, common_date_w3dtf($notice->created));
         $this->element('dc:creator', null, ($profile->fullname) ? $profile->fullname : $profile->nickname);
diff --git a/plugins/Activity/lib/systemlistitem.php b/plugins/Activity/lib/systemlistitem.php
index 958dfbc495..661fd1fe4c 100644
--- a/plugins/Activity/lib/systemlistitem.php
+++ b/plugins/Activity/lib/systemlistitem.php
@@ -68,7 +68,7 @@ class SystemListItem extends NoticeListItemAdapter
 
         $out->elementStart('div', 'system-activity');
 
-        $out->raw($notice->rendered);
+        $out->raw($notice->getRendered());
 
         $out->elementEnd('div');
     }
diff --git a/plugins/Activity/lib/unfollowlistitem.php b/plugins/Activity/lib/unfollowlistitem.php
index 0ecb8bef5a..276288bf05 100644
--- a/plugins/Activity/lib/unfollowlistitem.php
+++ b/plugins/Activity/lib/unfollowlistitem.php
@@ -68,7 +68,7 @@ class UnfollowListItem extends SystemListItem
 
         $out->elementStart('div', 'unfollow-activity');
 
-        $out->raw($notice->rendered);
+        $out->raw($notice->getRendered());
 
         $out->elementEnd('div');
     }
diff --git a/plugins/ActivityModeration/ActivityModerationPlugin.php b/plugins/ActivityModeration/ActivityModerationPlugin.php
index c7a24ba991..35eb5eb17a 100644
--- a/plugins/ActivityModeration/ActivityModerationPlugin.php
+++ b/plugins/ActivityModeration/ActivityModerationPlugin.php
@@ -144,8 +144,6 @@ class ActivityModerationPlugin extends ActivityVerbHandlerPlugin
         foreach($props as $prop) {
             $stored->$prop = $target->$prop;
         }
-        //$stored->content = $stored->content ?: _('Notice deleted.');
-        //$stored->rendered = $stored->rendered ?: $stored->rendered;
 
         // Let's see if this has been deleted already.
         try {
diff --git a/plugins/ActivityVerbPost/ActivityVerbPostPlugin.php b/plugins/ActivityVerbPost/ActivityVerbPostPlugin.php
index 5dd0ee12d7..a28009e2fc 100644
--- a/plugins/ActivityVerbPost/ActivityVerbPostPlugin.php
+++ b/plugins/ActivityVerbPost/ActivityVerbPostPlugin.php
@@ -74,7 +74,7 @@ class ActivityVerbPostPlugin extends ActivityVerbHandlerPlugin
         $object->type    = $notice->object_type ?: ActivityObject::NOTE;
         $object->id      = $notice->getUri();
         $object->title   = sprintf('New %1$s by %2$s', ActivityObject::canonicalType($object->type), $notice->getProfile()->getNickname());
-        $object->content = $notice->rendered;
+        $object->content = $notice->getRendered();
         $object->link    = $notice->getUrl();
 
         $object->extra[] = array('status_net', array('notice_id' => $notice->getID()));
@@ -102,7 +102,7 @@ class ActivityVerbPostPlugin extends ActivityVerbHandlerPlugin
 
     protected function showNoticeContent(Notice $stored, HTMLOutputter $out, Profile $scoped=null)
     {
-        $out->raw($stored->rendered);
+        $out->raw($stored->getRendered());
     }
 
     protected function getActionTitle(ManagedAction $action, $verb, Notice $target, Profile $scoped)
diff --git a/plugins/DirectionDetector/DirectionDetectorPlugin.php b/plugins/DirectionDetector/DirectionDetectorPlugin.php
index 561d38cd38..b721ebb20e 100644
--- a/plugins/DirectionDetector/DirectionDetectorPlugin.php
+++ b/plugins/DirectionDetector/DirectionDetectorPlugin.php
@@ -37,6 +37,7 @@ class DirectionDetectorPlugin extends Plugin {
      * @param object $notice notice is going to be saved
      */
     public function onStartNoticeSave($notice){
+        // don't use getRendered() here since it's not saved yet and thus can't ->update in case that would happen
         if(!preg_match('/<span class="rtl">/', $notice->rendered) && self::isRTL($notice->content))
             $notice->rendered = '<span class="rtl">'.$notice->rendered.'</span>';
         return true;
diff --git a/plugins/EmailSummary/lib/useremailsummaryhandler.php b/plugins/EmailSummary/lib/useremailsummaryhandler.php
index f900d93595..621d14122c 100644
--- a/plugins/EmailSummary/lib/useremailsummaryhandler.php
+++ b/plugins/EmailSummary/lib/useremailsummaryhandler.php
@@ -171,7 +171,7 @@ class UserEmailSummaryHandler extends QueueHandler
             $out->element('a', array('href' => $profile->profileurl),
                           $profile->nickname);
             $out->text(' ');
-            $out->raw($notice->rendered);
+            $out->raw($notice->getRendered());
             $out->elementStart('div', array('style' => 'font-size: 0.8em; padding-top: 4px;'));
             $noticeurl = $notice->getLocalUrl();
             // above should always return an URL
diff --git a/plugins/Favorite/classes/Fave.php b/plugins/Favorite/classes/Fave.php
index a5acb66d20..77b97c8093 100644
--- a/plugins/Favorite/classes/Fave.php
+++ b/plugins/Favorite/classes/Fave.php
@@ -63,7 +63,7 @@ class Fave extends Managed_DataObject
         //        notice's nickname and %3$s is the content of the favorited notice.)
         $act->content = sprintf(_('%1$s favorited something by %2$s: %3$s'),
                                 $actor->getNickname(), $target->getProfile()->getNickname(),
-                                $target->rendered ?: $target->content);
+                                $target->getRendered());
         $act->actor   = $actor->asActivityObject();
         $act->target  = $target->asActivityObject();
         $act->objects = array(clone($act->target));
@@ -186,7 +186,7 @@ class Fave extends Managed_DataObject
         //        notice's nickname and %3$s is the content of the favorited notice.)
         $act->content = sprintf(_('%1$s favorited something by %2$s: %3$s'),
                                 $actor->getNickname(), $target->getProfile()->getNickname(),
-                                $target->rendered ?: $target->content);
+                                $target->getRendered());
 
         $act->actor     = $actor->asActivityObject();
         $act->target    = $target->asActivityObject();
@@ -343,7 +343,7 @@ class Fave extends Managed_DataObject
         $actobj->objects = array(clone($actobj->target));
         $actobj->verb = ActivityVerb::FAVORITE;
         $actobj->title = ActivityUtils::verbToTitle($actobj->verb);
-        $actobj->content = $this->getTarget()->rendered ?: $this->getTarget()->content;
+        $actobj->content = $this->getTarget()->getRendered();
         return $actobj;
     }
 
diff --git a/plugins/Linkback/lib/util.php b/plugins/Linkback/lib/util.php
index ee498a4771..2f024dd233 100644
--- a/plugins/Linkback/lib/util.php
+++ b/plugins/Linkback/lib/util.php
@@ -388,7 +388,7 @@ function linkback_save($source, $target, $response, $notice_or_user) {
         //        notice's nickname and %3$s is the content of the favorited notice.)
         $act->content = sprintf(_('%1$s favorited something by %2$s: %3$s'),
                                 $profile->getNickname(), $notice_or_user->getProfile()->getNickname(),
-                                $notice_or_user->rendered ?: $notice_or_user->content);
+                                $notice_or_user->getRendered());
         if($entry['rsvp']) {
             $act->content = $options['rendered'];
         }
diff --git a/plugins/Mapstraction/actions/map.php b/plugins/Mapstraction/actions/map.php
index 48861af994..75a065a26a 100644
--- a/plugins/Mapstraction/actions/map.php
+++ b/plugins/Mapstraction/actions/map.php
@@ -146,7 +146,7 @@ class MapAction extends Action
 
         $arr = $act->twitterStatusArray($notice, true);
         $arr['url'] = $notice->getUrl(true);
-        $arr['html'] = $notice->rendered;
+        $arr['html'] = $notice->getRendered();
         $arr['source'] = $arr['source'];
 
         if (!empty($notice->reply_to)) {
diff --git a/plugins/Oembed/actions/oembed.php b/plugins/Oembed/actions/oembed.php
index ccba4c42a5..88ba52aa9f 100644
--- a/plugins/Oembed/actions/oembed.php
+++ b/plugins/Oembed/actions/oembed.php
@@ -88,7 +88,7 @@ class OembedAction extends Action
             $oembed['author_name']=$authorname;
             $oembed['author_url']=$profile->profileurl;
             $oembed['url']=$notice->getUrl();
-            $oembed['html']=$notice->rendered;
+            $oembed['html']=$notice->getRendered();
             break;
 
         case 'attachment':
diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php
index fbfb0aae30..172e9272af 100644
--- a/plugins/Realtime/RealtimePlugin.php
+++ b/plugins/Realtime/RealtimePlugin.php
@@ -322,7 +322,7 @@ class RealtimePlugin extends Plugin
 
         $arr = $act->twitterStatusArray($notice, true);
         $arr['url'] = $notice->getUrl(true);
-        $arr['html'] = htmlspecialchars($notice->rendered);
+        $arr['html'] = htmlspecialchars($notice->getRendered());
         $arr['source'] = htmlspecialchars($arr['source']);
         $arr['conversation_url'] = $notice->getConversationUrl();
 
@@ -335,7 +335,7 @@ class RealtimePlugin extends Plugin
             $original = Notice::getKV('id', $notice->repeat_of);
             if ($original instanceof Notice) {
                 $arr['retweeted_status']['url'] = $original->getUrl(true);
-                $arr['retweeted_status']['html'] = htmlspecialchars($original->rendered);
+                $arr['retweeted_status']['html'] = htmlspecialchars($original->getRendered());
                 $arr['retweeted_status']['source'] = htmlspecialchars($original->source);
                 $originalProfile = $original->getProfile();
                 $arr['retweeted_status']['user']['profile_url'] = $originalProfile->profileurl;
diff --git a/plugins/Share/SharePlugin.php b/plugins/Share/SharePlugin.php
index d1aece5c3d..d34bcc779e 100644
--- a/plugins/Share/SharePlugin.php
+++ b/plugins/Share/SharePlugin.php
@@ -170,7 +170,7 @@ class SharePlugin extends ActivityVerbHandlerPlugin
         $object          = new Activity();
         $object->actor   = $stored->getProfile()->asActivityObject();
         $object->verb    = ActivityVerb::SHARE;
-        $object->content = $stored->rendered;
+        $object->content = $stored->getRendered();
         $this->extendActivity($stored, $object);
 
         return $object;
diff --git a/plugins/SubMirror/classes/SubMirror.php b/plugins/SubMirror/classes/SubMirror.php
index de63841e72..a24f7fad5c 100644
--- a/plugins/SubMirror/classes/SubMirror.php
+++ b/plugins/SubMirror/classes/SubMirror.php
@@ -195,7 +195,7 @@ class SubMirror extends Managed_DataObject
     {
         $options = array('is_local' => Notice::LOCAL_PUBLIC,
                          'url' => $notice->getUrl(), // pass through the foreign link...
-                         'rendered' => $notice->rendered);
+                         'rendered' => $notice->getRendered());
 
         $saved = Notice::saveNew($profile->id,
                                  $notice->content,
diff --git a/scripts/upgrade.php b/scripts/upgrade.php
index 33b0baa35c..56c81c8b31 100755
--- a/scripts/upgrade.php
+++ b/scripts/upgrade.php
@@ -41,7 +41,6 @@ function main()
 
         // These replace old "fixup_*" scripts
 
-        fixupNoticeRendered();
         fixupNoticeConversation();
         initConversation();
         fixupGroupURI();
@@ -94,26 +93,6 @@ function updateSchemaPlugins()
     printfnq("DONE.\n");
 }
 
-function fixupNoticeRendered()
-{
-    printfnq("Ensuring all notices have rendered HTML...");
-
-    $notice = new Notice();
-
-    $notice->whereAdd('rendered IS NULL');
-    $notice->find();
-
-    while ($notice->fetch()) {
-        $original = clone($notice);
-        $notice->rendered = common_render_content($notice->content,
-                                                  $notice->getProfile(),
-                                                  $notice->hasParent() ? $notice->getParent() : null);
-        $notice->update($original);
-    }
-
-    printfnq("DONE.\n");
-}
-
 function fixupNoticeConversation()
 {
     printfnq("Ensuring all notices have a conversation ID...");
-- 
2.39.5