globalvar

Looking through the Blogsome/WPµ source, I came across a Smarty function {globalvar}. “Righto,” I thought, “I’ll google that, and see what comes up.” My template file was the first thing that did. Okay, what this function does is take a Smarty variable, and make it global in the PHP scope. Used in my template, and most Blogsome ones, it sets the variable $comment to be a global one. I haven’t come up with another good use for it, but it’s nice to know.

Connections Template

I’ve put the current contents of my template files up on this page. You’ll always be able to find the latest version of my templates there.

Interesting WordPress Smarty Functions

Here are some interesting Smarty equivalents of WordPress functions I hadn’t come across before:

  • {get_lastpostdate} or {get_lastpostmodified} - returns a timestamp, such as 2005-10-16 07:10:51 that contains the last post date. {get_lastcommentmodified} is identical, but for the last comment.
  • {human_time_diff from=n to=n} - similar to a script I wrote about, and implemented. Limited in that it only does days, not any larger unit. Advantage: done by the server, doesn’t ‘flash’ changing text via JavaScript, neater than my Smarty version.
  • {get_day_link} - much neater than the version I was using! Generates the URI as described. Also {get_page_link}, {get_year_link}, {get_month_link} and {get_feed_link}.
  • {globalvar var=varname value=value} - makes a value a global PHP variable. Very interesting…

Random Post Link

Another Blogsome user wanted a Random Post to be displayed on the home page. I haven’t quite figured out how to get the actual post displayed, but a link to a random post should be pretty easy. Luckily, WP-MU uses post ids. If we can get the latest post id, then we should be able to get a random number between 1 and this. We can then check to see if the post exists (it may have been deleted: WP does not reuse post ids), and if it doesn’t, get another random number, and keep doing this until we find a post id that is still valid. It’s then a simple step to create the permalink. The first problem arises when we try to get the latest post. We could use {the_author_posts}, but this will give us the number of posts, which means if the user has deleted n posts, the last n posts will not be in the selection of random posts. This is not necessarily such a bad thing, as it will mean that older posts are likely to be used. The next problem of {the_author_posts} is that it must be used within The Loop. If we are planning to put the link before we have been through ‘The Loop’, then we should be alright. The third issue of {the_author_posts} is that with a multi-author blog, the random number will be much lower than the total number of posts, meaning even older posts are only likely to be selected from. Another option would be to say “Okay, I want a random post lower in id (ie, older than) every other post on the page.” This makes things much easier, but is limited to the same problem of not being able to be placed before the loop, as we’ll set a variable to the post id on each post as we come to it, and since most blogs are ordered in descending order, the last post visited will (or should) have the lowest id. The problem here is that a category view may have a very low post count, and it’s oldest visible post may be a very early post. The third option would be to say “I want a post that is older than the newest post on the page.” Again, the limit as to where this must appear is present. However, an additional problem is that we may get a link to a post that’s already visible. This third one to me seems to be the best compromise. So how do we get this post id? We’ll need to modify our post.html file under Blogsome. {capture name=max_id}{the_ID}{/capture} {if $smarty.capture.max_id > $max_id}{assign var=max_id value=$smarty.capture.max_id}{/if} This code can go anywhere: I stuck it right at the bottom, out of the way. The next part should only be done once: {math} is quite processor intensive, so do it just where you want the object to appear: {math equation="rand(1,n)" assign=rand_post n=$max_id} Our final code is to grab the permalink and title for this post. However, I cannot yet find a way to get the title, so we are stuck not knowing the post title: Random Post I’ve tried using {get_post} and {get_postdata}, but since the latter returns an Array, it’s not much use. Returned Arrays are no good - the value needs to be assigned to a variable for us to be able to access it. It’s probably possible to alter the query, or rerun a new query, but I’m getting to tired to do this right now.

Limiting Smarty {foreach}

A user on the Blogsome forums wanted to be able to reduce the number of items that appeared in a Smarty generated list. Since the original code was using {foreach}, and I know {section} has a max=n attribute, I thought I’d try that. The problem was that the Array in question: {popularposts} generates $pposts; is not an array that can be accessed by indices. It’s key instead is the number of hits on the pages, so that’s not much good to us. However, it’s possible to use a simple {if} clause, and the {counter} function, to _effectively _limit the number of iterations.

1
2
3
4
5
6
7
    {counter assign=idx print=0}
    {foreach from=$array key=key item=item}
        {counter}
        {if $idx < = n}
            Data to be repeated goes in here.
        {/if}
    {/foreach}

Replacing n with a number will cause n-1 iterations to be displayed. I said effectively above, as the other iterations will actually occur, but no data will actually be printed on the screen, as there is no {else} clause.

Related Stories.

After hacking through the source, I finally figured out how to make {relatedstories} work. The trick is that it stores the date in a variable called $relatedstories.

    {relatedstories}
    {if $relatedstories}
      <h2>Related Stories</h2>
      <ul>
      {foreach from=$relatedstories key=key item=story}
        <li> <a href="{get_permalink id=$story->ID}" >
            {$story->post_title}</a>
        </li>
      {/foreach}
      </ul>
    {/if}

I’ve got it set up in my sidebar at the moment. It’s smart enough to figure out when it’s not a single post page, and won’t show then, so you don’t need any fancy extra Smarty Tags to only show in single post view. Oh, and it also sets the variable $relatedstoriesWords, so it’s possible to do something like: <h2 title="{$relatedstoriesWords}">Related Stories</h2> and when you hover over the title, it tells you the words it’s looking for. I’m still working on how to truncate the title. {$story->post_title|truncate} fails dismally. Quite annoying.

Choosy Post Display

Someone on the Blogsome Forums wanted to be able to have the main page only display posts from a certain category. To do this, edit your post.html file, and add the following right at the start: {capture name=in_cat}{in_category category='1'}{/capture} {if $smarty.server.REQUEST_URI != '/' || $smarty.capture.in_cat == '1'} Then, right at the end, add {/if} If you are wanting a category other than the default one to be the only one shown on your front page, look up the category id in the dash, and replace the ‘1’ in the first line with this number. This could easily be extended to get a sticky-post setup. I’ll do that later tonight, when I’m drunk. Just to make it a challenge. Happy 30th Sam.

Arguments that don't work

I’ve come across several Smarty Tags that call WordPress functions that have listed arguments that don’t work. I didn’t bother too much about it - usually I can live with it. Then, I realised how I solved one instance of this happening: the Recent Comments plugin.

I downloaded the source to this, and looked at it. Besides there being some spelling mistakes, it had argument names which differed from the documented ones. No wonder it was failing when I tried to change the number of comments, and the comment length! So, looking at the code helped me solve the problem. Maybe it will with the other issues I have come across: most notably {previous_post_link} and {next_post_link}, and {edit_post_link}.

I’ll start with the {edit_post_link}. The codex says the argument I want to change is called text, but the source reveals it to be link. Changing this enabled me to change the text that is presented to whatever I want. The same goes for {edit_comment_link}.

I was originally using the tags {previous_post} and {next_post}, but was unable to change the previous post:|next post: text that appeared. Changing the name of the argument from text to previous and next (as applicable) fixed this. Similarly, since {previous_post} and her sister are deprecated, {previous_post_link} has arguments that differ from those detailed in the Codex. The arguments it (and {next_post_link}) can handle are:

  • format - defaults to &laquo; %link. You need to have the %link where you want the URL to appear! You can add more stuff that you want to appear but not be part of the link itself.
  • link - defaults to %title. Add other text that you want to add into the link area.
  • in_same_cat
  • excluded_categories

Depending upon if you want an image clickable, you can either insert the code into the format or link argument. Just for fun, I included my favicon in the non-link section of the link text (ie, the format argument). I’ll leave it there for a while, just to prove it can be done…in the meantime, I’m going to fix the Codex.

Smarty: Insert / Comment Tags

Smarty This may have some use: {insert}. I noticed it when backing up my templates tonight… • Also, I’d like to make buttons that act like the quicktags in the Blogsome backend for commenting: so it inserts the relevant tags in. Will require some JavaScript, I assume…

Seperating Trackbacks and Comments

I can’t recall if this came up on the Blogsome forums or not, but some people are keen to seperate Trackbacks and Comments in the comment list. Sometimes, and especially for people new to blogs, Trackbacks don’t seem to make that much sense, so I thought I would try doing this on Blogsome. Googling seperate trackbacks comments wordpress turned up several sites, the first one I visited was from way back in July 2004, and was way to complicated to bother with.

The second one was better, and gave me the idea of how to do it. Then I remembered that there is a Template Tag called comment_type. I duplicated the main comment: the commentlist and the {foreach} that cycles through each comment, and used the following bit of code to get the {comment_type} into a variable (so I can test it):

1
    {capture name=comment_type}{comment_type}{/capture}

It’s a simple matter to test this against a known value:

1
    {if $smarty.capture.comment_type != 'Comment'}

And you know that you are working with a Trackback or Pingback. The first iteration of the commentlist only displays non-comments, the second only displays comments (it uses == 'Comment' instead). The last tricky bit was to figure out how to show Trackbacks from my own site in the class='owner' format (on here, in a reddish box rather than green). This required a little trick I had discovered earlier today:

1
    {capture name=author_trackback}trackback@{bloginfo show='url'}{/capture}

And then the test is:

1
    {if $smarty.capture.reader == $smarty.capture.author_trackback|replace:'http://':''}

(This assumes you have used my previous method for styling your own comments differently). The full text of my comments.html template then:

    <div id="commentarea">
    {if $post->ping_status}
        <p class='indented'>{_e text='The <acronym title="Uniform Resource Identifier">URI</acronym> to TrackBack this entry is:'} <em>{trackback_url}</em></p>
    {/if}
    
    <p class='indented'>{comments_rss_link link_text='<span class="rss"><abbr title="Really Simple Syndication">RSS</abbr></span> feed for comments on this post.'}</p>
    
    <h3 class="comments">{comments_number zero="Responses" one="1 Response" more="% Responses"} to &#8220;{the_title}&#8221;
    {if $post->comment_status == 'open'}
    <a href="#postcomment" title="{_e text='Leave a comment';}">&raquo;</a>
    {/if}
    </h3>
    
    {if $comments != ''}
      {capture name=author}{the_author_email}{/capture}
      {capture name=author_trackback}trackback@{bloginfo show='url'}{/capture}
    
      <h3 class="comments">Trackbacks / Pingbacks</h3>
      <ol class="commentlist">
      {foreach from=$comments key=key item=comment}
        {globalvar var='comment' value=$comment}
        {capture name=comment_type}{comment_type}{/capture}
        {if $smarty.capture.comment_type != 'Comment'}
            {capture name=reader}{comment_author_email}{/capture}
            {if $smarty.capture.reader == $smarty.capture.author_trackback|replace:'http://':''}
            <li class="owner" id="comment-{comment_ID}">
            {else}
            <li class="alt" id="comment-{comment_ID}">
            {/if}
            From the site {comment_author_link}:
        {comment_text}
            Posted on {comment_date} at {comment_time}.
            {edit_comment_link text="Edit this trackback", before='<span class="button">' after="</span>"}
        </li>
        {/if}
      {/foreach}
      </ol>
    
      <h3 class="comments">Comments</h3>
      <ol class="commentlist">
      {foreach from=$comments key=key item=comment}
        {globalvar var='comment' value=$comment}
        {capture name=comment_type}{comment_type}{/capture}
        {if $smarty.capture.comment_type == 'Comment'}
            {capture name=reader}{comment_author_email}{/capture}
            {if $smarty.capture.reader == $smarty.capture.author}
        <li class="owner" id="comment-{comment_ID}">
            {else}
        <li class="alt" id="comment-{comment_ID}">
            {/if}
                <script type="text/javascript">document.write('<div class="right"><img src="http://www.gravatar.com/avatar.php?gravatar_id='); document.write(hex_md5("{comment_author_email}")); document.write('&size=50" /><\/div>'); </script>
                On <a href="#comment-{comment_ID}">{comment_date} at {comment_time}</a>, {comment_author_link} said: 
              {comment_text}
                {edit_comment_link text="Edit this comment", before='<span class="button">' after="</span>"}
        </li>
         {/if}
      {/foreach}
      </ol>
    
    {else} _<!-- this is displayed if there are no comments so far -->_
        <p class='indented'>{_e text="No comments yet."}</p>
    {/if}
    
    <h3  class="comments">{_e text="Leave a Reply"}</h3>
    {if 'open' == $post->comment_status}
         <form action="{$siteurl}/wp-comments-post.php" method="post" id="commentform">
        <p>
          <input type="text" name="author" id="author" class="textarea" value="{insert name=var var=comment_author}" size="28" tabindex="1" />
           <label for="author">{_e text="Name"}</label> {if $req != ''} {_e text='(required)'} {/if}
        <input type="hidden" name="comment_post_ID" value="{$post->ID}" />
        <input type="hidden" name="redirect_to" value="{$redirect_to}" />
        </p>
    
        <p>
          <input type="text" name="email" id="email" value="{insert name=var var=comment_author_email}" size="28" tabindex="2" />
           <label for="email">{_e text="E-mail"}</label> {if $req != ''} {_e text='(required)'}{/if}
        </p>
    
        <p>
          <input type="text" name="url" id="url" value="{insert name=var var=comment_author_url}" size="28" tabindex="3" />
           <label for="url">{_e text="<acronym title='Uniform Resource Identifier'>URI</acronym>"}</label>
        </p>
    
        <p>
          <label for="comment">{_e text="Your Comment"}</label>
        <br />
          <textarea name="comment" id="comment" cols="60" rows="12" tabindex="4"></textarea>
              <input type="hidden" id="textarea_next_time" name="textarea_next_time" value="60,12" />
        </p>
    
        <p>
          _<!--input disabled name="preview" type="image" tabindex="5" src="/images/preview.png" size="75%" /-->_
          <input name="submit" type="image" tabindex="6" src="/images/post_comment.png" size="75%" />
        </p>
    
    <p>{_e text="Line and paragraph breaks automatic, e-mail address never displayed, <acronym title='Hypertext Markup Language'>HTML</acronym> allowed:"} <code>{allowed_tags}</code>, 'Smart' Smileys.</p>
    
    
    </form>
    {else} _<!-- comments are closed -->_
    <p>{_e text="Sorry, the comment form is closed at this time."}</p>
    {/if}
    </div>