<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][9369] trunk: Fix notice errors when an activity is generated for a post having no title.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://buddypress.trac.wordpress.org/changeset/9369">9369</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/9369","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>imath</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-01-17 04:46:05 +0000 (Sat, 17 Jan 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Fix notice errors when an activity is generated for a post having no title.

Post types activities are using dynamic action strings when the activity is displayed in the stream and when the activity is saved into the database. In this particular case, once the post is published, we are "faking" an activity object to which we add two extra properties : the post_title and the post_url. To avoid switching blogs too many times, we are saving the post title into an activity meta. To know if we must build the action string for insert or display, we are checking the post_title property of the activity object. When a post is published without a title, the `empty()` check was not right. Changing for an `isset()` check prevents the notice errors.

props boonebgorges

Fixes <a href="http://buddypress.trac.wordpress.org/ticket/6119">#6119</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcbpblogsbpblogsactivityphp">trunk/src/bp-blogs/bp-blogs-activity.php</a></li>
<li><a href="#trunktestsphpunittestcasesblogsactivityphp">trunk/tests/phpunit/testcases/blogs/activity.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcbpblogsbpblogsactivityphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-blogs/bp-blogs-activity.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-blogs/bp-blogs-activity.php  2015-01-17 03:24:11 UTC (rev 9368)
+++ trunk/src/bp-blogs/bp-blogs-activity.php    2015-01-17 04:46:05 UTC (rev 9369)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -117,35 +117,68 @@
</span><span class="cx" style="display: block; padding: 0 10px">                bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( empty( $activity->post_url ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * When the post is published we are faking an activity object
+        * to which we add 2 properties :
+        * - the post url
+        * - the post title
+        * This is done to build the 'post link' part of the activity
+        * action string.
+        * NB: in this case the activity has not yet been created.
+        */
+       if ( isset( $activity->post_url ) ) {
+               $post_url = $activity->post_url;
+
+       /**
+        * The post_url property is not set, we need to build the url
+        * thanks to the post id which is also saved as the secondary
+        * item id property of the activity object.
+        */
+       } else {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $post_url = add_query_arg( 'p', $activity->secondary_item_id, trailingslashit( $blog_url ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        } else {
-               $post_url = $activity->post_url;
</del><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( empty( $activity->post_title ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Should be the case when the post has just been published
+       if ( isset( $activity->post_title ) ) {
+               $post_title = $activity->post_title;
+
+       // If activity already exists try to get the post title from activity meta
+       } else if ( ! empty( $activity->id ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        } else {
-               $post_title = $activity->post_title;
</del><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Should only be empty at the time of post creation
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * In case the post was published without a title
+        * or the activity meta was not found
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( empty( $post_title ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Defaults to no title
+               $post_title = esc_html__( '(no title)', 'buddypress' );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 switch_to_blog( $activity->item_id );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $post = get_post( $activity->secondary_item_id );
</span><span class="cx" style="display: block; padding: 0 10px">                if ( is_a( $post, 'WP_Post' ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $post_title = $post->post_title;
-                       bp_activity_update_meta( $activity->id, 'post_title', $post_title );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Does the post have a title ?
+                       if ( ! empty( $post->post_title ) ) {
+                               $post_title = $post->post_title;
+                       }
+
+                       // Make sure the activity exists before saving the post title in activity meta
+                       if ( ! empty( $activity->id ) ) {
+                               bp_activity_update_meta( $activity->id, 'post_title', $post_title );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                restore_current_blog();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // Build the 'post link' part of the activity action string
</ins><span class="cx" style="display: block; padding: 0 10px">         $post_link  = '<a href="' . $post_url . '">' . $post_title . '</a>';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $user_link = bp_core_get_userlink( $activity->user_id );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // Build the complete activity action string
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( is_multisite() ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $action  = sprintf( __( '%1$s wrote a new post, %2$s, on the site %3$s', 'buddypress' ), $user_link, $post_link, '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
</span><span class="cx" style="display: block; padding: 0 10px">        } else {
</span></span></pre></div>
<a id="trunktestsphpunittestcasesblogsactivityphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/testcases/blogs/activity.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/testcases/blogs/activity.php  2015-01-17 03:24:11 UTC (rev 9368)
+++ trunk/tests/phpunit/testcases/blogs/activity.php    2015-01-17 04:46:05 UTC (rev 9369)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -310,6 +310,110 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @group activity_action
+        * @group bp_blogs_format_activity_action_new_blog_post
+        */
+       public function test_bp_blogs_format_activity_action_new_blog_post_no_title() {
+               if ( is_multisite() ) {
+                       return;
+               }
+
+               $bp = buddypress();
+               $activity_actions = $bp->activity->actions;
+               $bp->activity->actions = new stdClass();
+
+               $u = $this->factory->user->create();
+               $p = wp_insert_post( array(
+                       'post_author' => $u,
+                       'post_title'  => '', // no title: the object of the test
+                       'post_status' => 'publish',
+                       'post_content' => 'foo bar',
+               ) );
+
+               $user_link = bp_core_get_userlink( $u );
+               $blog_url = get_home_url();
+               $post_url = add_query_arg( 'p', $p, trailingslashit( $blog_url ) );
+               $post_link = '<a href="' . $post_url . '">(no title)</a>';
+
+               // Set activity actions
+               bp_activity_get_actions();
+
+               $a_obj = bp_activity_get( array(
+                       'item_id'           => 1,
+                       'secondary_item_id' => $p,
+               ) );
+
+               $expected = sprintf( '%s wrote a new post, %s', $user_link, $post_link );
+
+               $this->assertSame( $expected, $a_obj['activities'][0]->action );
+
+               // Reset activity actions
+               $bp->activity->actions = $activity_actions;
+               $bp->activity->track = array();
+       }
+
+       /**
+        * @group activity_action
+        * @group bp_blogs_format_activity_action_new_blog_post
+        */
+       public function test_bp_blogs_format_activity_action_new_blog_post_updated_without_title() {
+               if ( is_multisite() ) {
+                       return;
+               }
+
+               $bp = buddypress();
+               $activity_actions = $bp->activity->actions;
+               $bp->activity->actions = new stdClass();
+
+               $u = $this->factory->user->create();
+               $p = wp_insert_post( array(
+                       'post_author' => $u,
+                       'post_title'  => 'foo',
+                       'post_status' => 'publish',
+                       'post_content' => 'foo bar',
+               ) );
+
+               $user_link  = bp_core_get_userlink( $u );
+               $blog_url   = get_home_url();
+               $post_url   = add_query_arg( 'p', $p, trailingslashit( $blog_url ) );
+               $post_title = get_the_title( $p );
+               $post_link  = '<a href="' . $post_url . '">' . $post_title . '</a>';
+
+               // Set actions
+               bp_activity_get_actions();
+
+               $a_obj = bp_activity_get( array(
+                       'item_id'           => 1,
+                       'secondary_item_id' => $p,
+               ) );
+
+               $expected = sprintf( '%s wrote a new post, %s', $user_link, $post_link );
+
+               $this->assertSame( $expected, $a_obj['activities'][0]->action );
+
+               // Update the post by removing its title
+               wp_update_post( array(
+                       'ID'         => $p,
+                       'post_title' => '',
+               ) );
+
+               // we now expect the (no title) post link
+               $post_link = '<a href="' . $post_url . '">(no title)</a>';
+               $expected = sprintf( '%s wrote a new post, %s', $user_link, $post_link );
+
+               $a_obj = bp_activity_get( array(
+                       'item_id'           => 1,
+                       'secondary_item_id' => $p,
+               ) );
+
+               $this->assertSame( $expected, $a_obj['activities'][0]->action );
+
+               // Reset activity actions
+               $bp->activity->actions = $activity_actions;
+               $bp->activity->track = array();
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Dopey passthrough method so we can check that the correct values
</span><span class="cx" style="display: block; padding: 0 10px">         * are being passed to the filter
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span></span></pre>
</div>
</div>

</body>
</html>