Recent Topics

Sticky Post Hack

Started by on Feb 16, 2005 – Contents updated: Feb 16, 2005

Feb 16, 2005 03:47    

Been a long time for this one. One of my oldest posts was something like "graymatter has sticky posts so how do I do that here?" Now I know: you tweak a table and 4 files. First, modify your blogs table so you can store which post ID is sticky for each blog. You will be able to set this in your back office later, and 0 will mean no sticky post. I did it via phpmyadmin with

ALTER TABLE `evo_blogs` ADD `blog_stickypost_ID` INT( 10 ) DEFAULT '0' NOT NULL

Next crack open admin/b2blogs.php and do 2 hacks. First find and add:

param( 'blog_pingblodotgs', 'integer', 0 );
$edited_Blog->set( 'pingblodotgs', $blog_pingblodotgs );

param( 'blog_stickypost_ID', 'integer', 0 ); // stickypost hack
$edited_Blog->set( 'stickypost_ID', $blog_stickypost_ID ); // stickypost hack


Then find and add:

$blog_pingweblogs = get_bloginfo( 'pingweblogs' );
$blog_pingblodotgs = get_bloginfo( 'pingblodotgs' );
$blog_stickypost_ID = get_bloginfo( 'stickypost_ID' ); // stickypost hack
require( dirname(__FILE__).'/_blogs_advanced.form.php' );

Close it and open admin/_blogs_advanced.form.php then find and add:

<fieldset>
	<legend><?php echo T_('Advanced options') ?></legend>
	<?php
		form_checkbox( 'blog_allowtrackbacks', $blog_allowtrackbacks, T_('Allow trackbacks'), T_("Allow other bloggers to send trackbacks to this blog, letting you know when they refer to it. This will also let you send trackbacks to other blogs.") );
		form_checkbox( 'blog_allowpingbacks', $blog_allowpingbacks, T_('Allow pingbacks'), T_("Allow other bloggers to send pingbacks to this blog, letting you know when they refer to it. This will also let you send pingbacks to other blogs.") );
	?>
</fieldset>

<?php // stickypost hack ?>
<fieldset>
	<legend><?php echo T_('Advanced options') ?></legend>
	<?php
		form_text( 'blog_stickypost_ID', $blog_stickypost_ID, 8, T_('StickyPost ID'), T_('This is the Post ID of the post currently designated as this blog\'s sticky post.  Set it to 0 to have no stickypost') );
	?>
</fieldset>
<?php // end stickypost hack ?>

<?php form_submit(); ?>

Now open b2evocore/_class_blog.php and do 2 changes. Find and add:

var $disp_bloglist = 1;
var $in_bloglist = 1;
var $UID;
var $stickypost_ID; // stickypost hack

then find and add:

	$this->in_bloglist = $db_row->blog_in_bloglist;
	$this->UID = $db_row->blog_UID;
	$this->stickypost_ID = $db_row->blog_stickypost_ID; // stickypost hack
}

Okay now to use it. First, set up the whole stickypost thing. In _main.php find and add:

<!-- =================================== START OF MAIN AREA =================================== -->

<?php // START OF STICKYPOST 

if( $disp == 'posts' ) { // only do this for multi-post pages

$sql = "SELECT blog_stickypost_ID FROM $tableblogs WHERE blog_ID = $blog";
$sticky_post = $DB->get_var($sql);
$Item = Item_get_by_ID( $sticky_post );

if( $sticky_post ) { // only do this if stickypost is not 0

$sql = "SELECT postcat_post_ID, postcat_cat_ID FROM $tablepostcats WHERE postcat_post_ID = $sticky_post ORDER BY postcat_post_ID, postcat_cat_ID";
$rows = $DB->get_results( $sql, ARRAY_A );
if( count( $rows ) ) foreach( $rows as $myrow ) {
	$postcat_post_ID = $myrow["postcat_post_ID"];
	if( ! isset( $cache_postcats[$postcat_post_ID] ) ) {
		 $cache_postcats[$postcat_post_ID] = array();
		 }
	$cache_postcats[$postcat_post_ID][] = $myrow["postcat_cat_ID"];
	}
?>

What that does is a couple of things. If you're not on a multi-post page get out - don't do the sticky. If stickypost is set to 0 don't do the sticky. cache_postcats is normally set by the posts loop, so we cheat and set it here for the sticky.

Next add all the stuff that makes a post be a post, but not the stuff that adds comments and the comment form. After the above add:

	<div class="bPost" lang="<?php $Item->lang() ?>">
		<?php
			locale_temp_switch( $Item->locale ); // Temporarily switch to post locale
			$Item->anchor(); // Anchor for permalinks to refer to
		?>
		<div class="bSmallHead">
		<a href="<?php $Item->permalink() ?>" title="<?php echo T_('Permanent link to full entry') ?>"><img src="img/icon_minipost.gif" alt="Permalink" width="12" height="9" class="middle" /></a>
		<?php
			$Item->issue_time();
			echo ', ', T_('Categories'), ': ';
			$Item->categories();
			echo ', ';
			$Item->wordcount();
			echo ' ', T_('words'), ' &nbsp; ';
			locale_flag( $Item->locale, 'h10px' );
		?>
		</div>
		<h3 class="bTitle"><?php $Item->title(); ?></h3>
		<div class="bText">
			<?php $Item->content(); ?>
			<?php link_pages() ?>
		</div>
		<div class="bSmallPrint">
			<a href="<?php $Item->permalink() ?>" title="<?php echo T_('Permanent link to full entry') ?>" class="permalink_right"><img src="img/chain_link.gif" alt="<?php echo T_('Permalink') ?>" width="14" height="14" border="0" class="middle" /></a>
			<?php $Item->feedback_link( 'comments' ) // Link to comments ?>
			<?php $Item->feedback_link( 'trackbacks', ' &bull; ' ) // Link to trackbacks ?>
			<?php $Item->feedback_link( 'pingbacks', ' &bull; ' ) // Link to trackbacks ?>
			<?php $Item->edit_link( ' &bull; ' ) // Link to backoffice for editing ?>
			<?php $Item->trackback_rdf() // trackback autodiscovery information ?>
		</div>
			<?php 
			locale_restore_previous();	// Restore previous locale (Blog locale)
			?>
	</div>

It's just the post loop. No biggie, only this is only going to run once for the sticky. If you want to style your sticky differently then use new class names and stuff. It's just a post though, so whatever you can do with a post you can do here.

Now to close out the sticky in 3 easy steps. After the above add:

<?php 
unset($cache_postcats);

} // end if stickypost is not 0

} // end if disp=posts

// END OF STICKYPOST ?>

<?php // ------------------------------------ START OF POSTS ----------------------------------------

Only thing left to take care of, other than setting your sticky, is to tell the regular posts loop to ignore the stickypost. You already showed it right? Still in _main.php, find and add:

if( isset($MainList) ) while( $Item = $MainList->get_item() )
{
	if( $Item->get('ID') == $sticky_post ) { 
		continue;
		}
	$MainList->date_if_changed();

Cool. Now go to your back office and select a blog then the advanced tab. You should have a new thingie at the end for the sticky post ID number. That's where you will tell it which post is sticky, or 0 for no stickypost.

doo doop da doop doop Fresh Air!
doo doop da doop doop Times Square!

I think that's it. What's funny here is I have no use for this hack. It just bugged me that it didn't exist.

doo doop da doop doop - doo doop da doop doop
Aw whatever. I'm going flying. Who needs this code stuff when it's blowing 20+ on The Guadalupe Rim?

Mar 14, 2005 12:13

EdB -

I specially registered just so I can post a reply to say thanks! Your post was incredibly helpful, especially for someone like me who just recently installed B2 and know pretty much nothing about php. It's an awesome hack!

Now I noticed that the sticky has Permalink buttons the regular posts don't have. Is there a way I can remove the Permalinks so the sticky resembles a regular post?

My blog is at http://www.chingster.com/blog if you guys are curious. It is very much still under construction as you can tell! B)

Mar 14, 2005 12:34

In the code block that follows where I say "Next add all the stuff that makes a post be a post, but not the stuff that adds comments and the comment form. After the above add:" you will want to compare THAT to the actual post loop for your skin. One thing I see is that you have "permalink, time, cats, words, flag" above your title on your sticky but not your ... ? ... loosies? Those things come from this part:

      <div class="bSmallHead">
      <a href="<?php $Item->permalink() ?>" title="<?php echo T_('Permanent link to full entry') ?>"><img src="img/icon_minipost.gif" alt="Permalink" width="12" height="9" class="middle" /></a>
      <?php
         $Item->issue_time();
         echo ', ', T_('Categories'), ': ';
         $Item->categories();
         echo ', ';
         $Item->wordcount();
         echo ' ', T_('words'), ' &nbsp; ';
         locale_flag( $Item->locale, 'h10px' );
      ?>
      </div>


so delete that from the stickypost portion and that will be like your regular posts.

Your skin (looks like Guadeloupe?) has a title then a date and time and author over on the right, so you would have to look at your original post loop in _main.php and see where the title comes from, then duplicate the stuff for date/time/author in your stickypost loop.

It's not exactly *easy* but it's not hard either. For example the title comes from "<?php $Item->title(); ?>" so you look right after that for something that talks about date or date time and just copy paste. Don't forget to also copy your div or tag classes so you'll get the right look to everything.

Mar 14, 2005 12:54

Ah I missed that part, but just took care of it right now. I decided to leave the sticky a bit different looking than from the regular posts. And yes the skin is guadeloupe.

I also just started getting this error when I try logging out. I will poke around a bit if anyone has any other suggestions.

Warning: Cannot modify header information - headers already sent by (output started at /home/chs8425/public_html/blog/b2evocore/_class_blog.php:427) in /home/chs8425/public_html/blog/b2evocore/_functions_users.php on line 172

...(up to line 178)

Warning: Cannot modify header information - headers already sent by (output started at /home/chs8425/public_html/blog/b2evocore/_class_blog.php:427) in /home/chs8425/public_html/blog/htsrv/login.php on line 34

...(up to line 41 skipping a few)

Mar 14, 2005 13:29

Check for white space at the end of every file you've done any editing to. Even just opening something and saving it. White space being ANYTHING - extra lines, extra spaces - after the closing ?>. Some editors are really bad about throwing junk in there so you might want to check your files using good old notepad. Also it might not be the files the errors name - could be that those files are kicking out the errors induced somewhere else. Start by checking the files you know you opened in an editor and saved.

Sep 23, 2005 05:32

This is a nice hack. I just got it running on a test blog. Just as an informative post, it seems to not pay attention to the fact that a post is labelled as private. The post still seems to show up, even if marked private. My test blog is .12.

jj.

Sep 23, 2005 05:50

Good catch. I didn't even think about stuff like that way back in the day... It's something we can do, but my brain is shot from chasing all the variations of blah.to through the antispam list. By the way it won't care about protected posts either - just that it can find a post ID that matches what you told it in your back office. I'll have to think about it again because it's another hack I did but don't use. My sorry excuse for a brain says "just put in a note that says post status doesn't matter" but that's not a cool answer. I'm thinking it should, as a minimum, care about protected posts. That way you could use your stickypost to sort of broadcast something to your bloggers but not the world. Private ones get a bit deeper to deal with. I think.

Nov 19, 2005 22:49

Anyone tried this with "Dawn"? Does it still work?

jj.

Nov 19, 2005 22:58

I haven't tried it yet, but I should. I should get myself a 'clean' .9.1 installation and add this hack to test it. As to the 'private' issue: I don't think I gave that any thought at all. I figured the user would want a stickypost to say something to the world, so I sort of assumed it would be a public post.

If I find the time to test this on dawn before phoenix comes out I'll see about making sure that private posts are kept private. It'll be hard though because the way I did this was to say "to heck with everything b2evo does about putting posts out there on the web - just show me post #N first".

NO PROMISES!!! I've made too many promises here that I can't deliver on, so I've learned to say "no promises". I also add the thread to my list of watched topics so I can come back to it when I have time to spare.

Nov 19, 2005 23:26

Oh, not a problem at all about the 'private' thing.. The only reason I even mentioned it in that earlier post was because I had installed the hack, and was testing it on a private post to make sure it worked properly before publishing the post. I was logged in with firefox. When I checked it with IE I had noticed that it also appeared there, though I wasn't logged in. So, again, that's the only reason I even brought it up. As you said, a stickyposted post would 99.999% of the time be meant for public display anyway, so to me it's a non-issue.

jj.

Nov 23, 2005 06:14

Here's another one... (I'm not picking on you EdB, I swear it!). Stickypost acts pretty funky when a post is crossposted across blogs. The bSmallHead and bSmallPrint sections show up, but the body of the post does not.

I thought that with all the direct database meddling I did in the last 48 hours something got seriously screwed up, but I tried a different post from the same blog, which wasn't crossposted, and it worked just fine.

Only reason I bring it up is because others might be crossposting on their blogs and might run into the same thing.

jj.

Jan 16, 2006 23:19

My approach requires a little more hands in the works to make updates, but it required no hacks.

1) Create the post you want to make sticky.

2) Go into phpmyadmin on your server and add a field "post_sticky" to the posts table (may have a prefix depending on how your server is set up). I created it as tinyint, with default 0.

3) Browse the posts table to find the post you want to be sticky and edit it. Put a "1" in the "post_sticky" field.

4) Edit your /conf/_config.php file and add a line:
$orderby = 'sticky issue_date';

Any time I want to change or even add to the list of sticky posts, I just use the phpmyadmin tool to add a 1 in the sticky field for the post. It's not a pretty interface, but I don't have to worry about tracking down hacks in standard files as patches come out - just backup my config.php file.

It works because the default sort order is DESC by issue_date (see _class_itemlist.php) . You can set many other fields from class_itemlist.php, (like if you want to order by title instead of date) just by declaring them in your config.php file.

Tom Campbell
http://blog.tacampbell.net

Jan 17, 2006 00:56

You could of course use a seperate blog for your sticky posts and then you can reduce it to a simple skintag ;)

¥

Jan 17, 2006 20:48

Yer i think ¥åßßå's or tacampbell's way of doing it seems more logical and effecient...

Jan 17, 2006 20:58

links are bad

Edit: Wrong topic....

Jan 20, 2006 15:03

tacampbell wrote:

My approach requires a little more hands in the works to make updates, but it required no hacks.

1) Create the post you want to make sticky.

2) Go into phpmyadmin on your server and add a field "post_sticky" to the posts table (may have a prefix depending on how your server is set up). I created it as tinyint, with default 0.

3) Browse the posts table to find the post you want to be sticky and edit it. Put a "1" in the "post_sticky" field.

4) Edit your /conf/_config.php file and add a line:
$orderby = 'sticky issue_date';

Any time I want to change or even add to the list of sticky posts, I just use the phpmyadmin tool to add a 1 in the sticky field for the post. It's not a pretty interface, but I don't have to worry about tracking down hacks in standard files as patches come out - just backup my config.php file.

It works because the default sort order is DESC by issue_date (see _class_itemlist.php) . You can set many other fields from class_itemlist.php, (like if you want to order by title instead of date) just by declaring them in your config.php file.

Tom Campbell
http://blog.tacampbell.net

It looks great to have that to on my website. I did the 4 steps but I get an error when I have done that.

The error I get is:

MySQL error!

Unknown column 'post_issue_date' in 'order clause'(Errno=1054)

Your query: Get ID list for Item List (Main|Lastpostdate) Query

SELECT DISTINCT post_ID

FROM evo_posts INNER JOIN evo_postcats ON post_ID = postcat_post_ID
INNER JOIN evo_categories ON postcat_cat_ID = cat_ID
WHERE (cat_blog_ID = 2)
AND ( ( post_status IN ('published') ) )
AND (post_datestart <= '2006-01-20 08:56:48')
ORDER BY post_sticky DESC, post_issue_date DESC
LIMIT 5

Backtrace:

1. db->print_error( "", "Get ID list for Item List (Main|Lastpostdate) Query" )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/_db.class.php:557
2. db->query( "SELECT DISTINCT post_ID FROM T_posts INNER JOIN T_po...", "Get ID list for Item List (Main|Lastpostdate) Query" )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/_db.class.php:759
3. db->get_col( "SELECT DISTINCT post_ID FROM T_posts INNER JOIN T_po...", 0, "Get ID list for Item List (Main|Lastpostdate) Query" )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/_db.class.php:782
4. db->get_list( "SELECT DISTINCT post_ID FROM T_posts INNER JOIN T_po...", 0, "Get ID list for Item List (Main|Lastpostdate) Query" )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/_itemlist.class.php:403
5. itemlist->itemlist( 2, Array(0), NULL, NULL, -1, NULL, Array(0), NULL, "DESC", "sticky issue_date", 0, NULL, NULL, NULL, "", "AND", NULL, 0, "", "", "now", "", NULL )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/_blog_main.inc.php:292
6. require( "/var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/evocore/..." )
File: /var/www/virtual/jdefluiter.byethost11.com/htdocs/blogs/justinweblog_stub.php:58

Ignored last: 1

Hope someone can help. I have set the settings back to normal. So you can't see the error on my site. I think the problem is with the settings of the order by. (btw I have te latest versoin of B2evo quess it is 1.6 or something)

Thanks

Jan 23, 2006 10:48

Nobody knows what I'm doing Wrong???

Jan 23, 2006 11:22

change issue_date to datecreated ;)

¥


Form is loading...

Social CMS software – This forum is powered by b2evolution CMS, a complete engine for your website.