23
Dec 12

Where did my Twitter feed go?

As of March 2013, Twitter say that “we will require every request to the API to be authenticated“. In practical terms, this means your old widget on your blog will most likely break. What to do? Well, there will certainly be some new WordPress widgets coming soon. If you’re building something now and don’t want to wait, it’s slightly more difficult but only slightly.

I’m now using the plugin “oAuth Twitter Feed for Developers” and an edited version of the example code to layout tweets by Emma from Red Earth Design. The example code meets Twitters new design guidelines, too, bonus! I’ve tweaked both a little – this post will tell you how and why. I’m not going to go into how to use the plugin, it has easy to follow directions.

First, the changes I wanted to make:

  • Retweets were being truncated eg:
  • Replies were being included. Mine are usually stupid. I wanted them out.
  • I wanted to use it as a shortcode in which the number of tweets was passed as a parameter
  • After I had sorted all of the above, the tweets were showing up at the top of the page instead of where they were supposed to be. This needed to be fixed.

Instead of going through the changes one by one, I’ll tell you which files I edited and why.

File 1: oauth-twitter-feed-for-developers/StormTwitter.class.php in the oAuth Twitter Feed for Developers plugin files

Towards the end of this file is this line:

$result = $connection->get('statuses/user_timeline', array('screen_name' => $screenname, 'count' => 20, 'trim_user' => true));

I’ve edited it to this:

$result = $connection->get('statuses/user_timeline', array('screen_name' => $screenname, 'count' => 100, 'trim_user' => false, 'exclude_replies' => true));

Here’s what I added / changed:

‘exclude_replies’ => true;  this should be pretty obvious. I wanted to exclude replies.

‘trim_user’ => false;  I had to change this to get the screen name (eg mine is tharsheblows) for authors of retweeted statuses

‘count’ => 100; when I had twenty, I only ended up with fourteen non-reply tweets – I guess the count is applied first, then the replies are excluded? Not sure, can’t be bothered to trawl to find out a definitive answer.

Also, for testing purposes, I changed the cache time below (currently set at one hour) which is in this file. The main thing is to remember to change it back before putting it anywhere you could hit your rate limit:

if ($cache['time'] < (time() - 3600)) 

File 2: Example code to layout tweets

edit 31 December 2012: the code below throws out some empty <a></a>’s. I don’t know why and it still works (but looks ugly and doesn’t validate if you’re into that) so it’s going to the bottom of the list to be fixed. I will update again if I do.

Using the code linked to above, the retweets were causing some problems – once I had the whole tweet, the display went a little wonky. Their information is in the retweeted_status object and needed to be found there. For some reason, I couldn’t find the original tweeter’s screen name, so had to access it like a regular tweet. Anyway.

I also added some extra divs to make it eaiser to style. You’ll end up with something like this:

<div class=”twitter_box”>
<div class=”tweet”>THE TWEET</div>
<div class=”twitter_intents”><p>LINKS TO REPLY, RETWEET AND FAVORITE</p></div>
<p class=”timestamp”>TIMESTAMP LINKED TO STATUS</p>
</div>

Looking at that, I’m not sure I like that layout. I might change it. It really should be a list, shouldn’t it.

The tweets showing up at the top of the page thing was due to the function echo-ing the output as it went along instead of returning it. I changed this.

Here is the final code (it goes in functions.php as usual) – oh, and if you use this, you will want to change “tharsheblows” to whatever your Twitter screen name is. I can’t be bothered to make this non-hard coded:


// dealing with Twitter - adapted from https://github.com/stormuk/storm-twitter-for-wordpress/wiki/Example-code-to-layout-tweets
// http://wordpress.org/extend/plugins/oauth-twitter-feed-for-developers/

function twitter_display($tweet, $status, $the_tweet){
/*
Twitter Developer Display Requirements
https://dev.twitter.com/terms/display-requirements

2.b. Tweet Entities within the Tweet text must be properly linked to their appropriate home on Twitter. For example:
i. User_mentions must link to the mentioned user's profile.
ii. Hashtags must link to a twitter.com search with the hashtag as the query.
iii. Links in Tweet text must be displayed using the display_url
field in the URL entities API response, and link to the original t.co url field.
*/

// i. User_mentions must link to the mentioned user's profile.
foreach($status['entities']['user_mentions'] as $key =&gt; $user_mention){
$the_tweet = preg_replace(
'/@'.$user_mention['screen_name'].'/i',
'&lt;a href="http://www.twitter.com/'.$user_mention['screen_name'].'" target="_blank"&gt;@'.$user_mention['screen_name'].'&lt;/a&gt;',
$the_tweet);
}

// ii. Hashtags must link to a twitter.com search with the hashtag as the query.
foreach($status['entities']['hashtags'] as $key =&gt; $hashtag){
$the_tweet = preg_replace(
'/#'.$hashtag['text'].'/i',
'&lt;a href="https://twitter.com/search?q=%23'.$hashtag['text'].'&amp;src=hash" target="_blank"&gt;#'.$hashtag['text'].'&lt;/a&gt;',
$the_tweet);
}

// iii. Links in Tweet text must be displayed using the display_url
//      field in the URL entities API response, and link to the original t.co url field.
foreach($status['entities']['urls'] as $key =&gt; $link){
$the_tweet = preg_replace(
'<code>'.$link['url'].'</code>',
'&lt;a href="'.$link['url'].'" target="_blank"&gt;'.$link['url'].'&lt;/a&gt;',
$the_tweet);
}
return $the_tweet;
}//end twitter_display

//twitter shortcode function
function twitter_shortcode($atts){

extract( shortcode_atts( array(
'number' =&gt; '5',
), $atts ) );

$tweets = getTweets($number);
if(is_array($tweets)){

// to use with intents
echo '&lt;script type="text/javascript" src="//platform.twitter.com/widgets.js"&gt;&lt;/script&gt;';
$tweet_box = '&lt;div&gt;';
foreach($tweets as $tweet){

if($tweet['text']){

if (isset($tweet['retweeted_status'])){
$the_tweet = "RT  @".$tweet['retweeted_status']['user']['screen_name'].": ".$tweet['retweeted_status']['text'];
//I had to add in this next foreach to get the tweeter's link correct - not sure why
foreach($tweet['entities']['user_mentions'] as $key =&gt; $user_mention){
$the_tweet = preg_replace(
'/@'.$user_mention['screen_name'].'/i',
'&lt;a href="http://www.twitter.com/'.$user_mention['screen_name'].'" target="_blank"&gt;@'.$user_mention['screen_name'].'&lt;/a&gt;',
$the_tweet);
}
$the_tweet = twitter_display($tweet, $tweet['retweeted_status'], $the_tweet);

}
else{
$the_tweet = $tweet['text'];
$the_tweet = twitter_display($tweet, $tweet, $the_tweet);

}

$tweet_box .= '&lt;div&gt;'.$the_tweet.'&lt;/div&gt;';

// 3. Tweet Actions
//    Reply, Retweet, and Favorite action icons must always be visible for the user to interact with the Tweet. These actions must be implemented using Web Intents or with the authenticated Twitter API.
//    No other social or 3rd party actions similar to Follow, Reply, Retweet and Favorite may be attached to a Tweet.
// get the sprite or images from twitter's developers resource and update your stylesheet
$tweet_box .= '
&lt;div&gt;
&lt;p&gt;&lt;a href="https://twitter.com/intent/tweet?in_reply_to='.$tweet['id_str'].'"&gt;Reply&lt;/a&gt; |
&lt;a href="https://twitter.com/intent/retweet?tweet_id='.$tweet['id_str'].'"&gt;Retweet&lt;/a&gt; |
&lt;a href="https://twitter.com/intent/favorite?tweet_id='.$tweet['id_str'].'"&gt;Favorite&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;';

// 4. Tweet Timestamp
//    The Tweet timestamp must always be visible and include the time and date. e.g., “3:00 PM - 31 May 12”.
// 5. Tweet Permalink
//    The Tweet timestamp must always be linked to the Tweet permalink.
$tweet_box .= '
&lt;p&gt;
&lt;a href="https://twitter.com/tharsheblows/status/'.$tweet['id_str'].'" target="_blank"&gt;posted at
'.date('g:i A \o\n d M Y',strtotime($tweet['created_at'])).'
&lt;/a&gt;
&lt;/p&gt;';
} else {
$tweet_box .= '
&lt;br /&gt;&lt;br /&gt;
&lt;a href="http://twitter.com/tharsheblows" target="_blank"&gt;Click here to for more tweets from tharsheblows&lt;/a&gt;';
}
}//foreach $tweets as $tweet
}//if is_array($tweets)

$tweet_box .= '&lt;p&gt;I\'m &lt;a href="http://twitter.com/tharsheblows" target="_blank"&gt;tharsheblows&lt;/a&gt; on Twitter.&lt;/p&gt;';

$tweet_box .= "&lt;/div&gt;&lt;!-- tweet_box --&gt;";

return $tweet_box;

}//end twitter_shortcode function

add_shortcode('tweets', 'twitter_shortcode');
//end twitter stuff

&nbsp;

I’m using a minimum of css right now:


/*oauth twitter stuff */
.twitter_box{padding: 10px 0 0 0; border-bottom: 1px #E2E2E2 solid;}
.twitter_intents p{text-align: right; font-size: 80%; margin-bottom: 0; padding-bottom: 0;}
p.timestamp {font-size:80%; text-align: right; padding: 0; margin-bottom: 3px; }

And that’s it!

 

 


04
Feb 12

Importing products from Magento to WP e-commerce

If you have come to this post looking for an easy, straightforward way to get products from Magento to WordPress e-commerce, this is not for you.  If you don’t mind digging around in databases and unclear directions, then welcome, sorry for the mess, have a seat (just shoo off the cat there – oh, is that a hairball? let me get you a new cushion).

I had a tiny shop in Magento Community 1.4.1.0 (because I was too scared to update it, that’s why) but decided to move it all to WordPress using the WP e-Commerce plugin.  Even though the shop is quite small, I didn’t want to have to put in every product by hand.  So here’s what I did… (nb: as these weren’t large tables and I didn’t know what I was doing, I decided to dump the whole table and edit down to what I needed in Excel.  You might want to do it properly. You might not.  Also, I’m setting up WordPress on another server, so don’t have both of these installed on one.)

  1. In Magento: export the catalog_product_flat_1 table to a csv file
  2. Neaten up a version of csv file so you have the columns: Description, Additional Description, Product Name, Price, SKU, weight, weight unit, stock quantity, is limited quantity
  3. Save another version keeping at least the name and the relative image path intact (this is used for the images, as might be obvious)
  4. In the “import” tab of the plugin, import the file

Easy peasy, lemon squeezy.  Except, of course, where are the images?  They are nowhere.  They are not there.  Bastards.  So here’s where it gets a little dodgy and you’ll have to use these following directions as a guide.

    1. Find your images in Magento and download them.  You can figure out their path using the catalog_product_rule_flat_1 table
    2. In WordPress admin, upload them into the media library.  Have a cup of coffee.
    3. You need to know the post ids of the product posts and the post ids of the image posts (attachment paths are saved as posts when uploaded) – go into wp_posts and export those.

At this point it gets a little fuzzy, so I’m going to stop numbering the steps.  This is all step 5.

The table wp_postmeta is where the linking of the image to the post happens –

post_id is the post id of the product post and meta_value is the post id of the image post.  What you need to do is write a series of insert statements eg:

insert into wp_postmeta (post_id, meta_key, meta_value) VALUES (18,’_thumbnail_id’,29);

I think I put the post ids on my copy of the Magento table with the image paths (edited down to filenames) then used the image filename – the same(ish – enough) in both the Magento table and the WP table – to match up the image post ids to the product post ids.  That might not make a lot of sense but you should be able to look at what you have and figure out how to get everything together.  I then simply wrote my statements in Excel:

=CONCATENATE(A18, “VALUES (“,B18,”,’_thumbnail_id’,”,C18,”);”)
where: A18 = insert into wp_postmeta(  ; B18 = the product post id ; C18 = the corresponding image post id

and slapped them into the table.

Result!

 This only gives one image per product but that’s fine for me.


24
Jan 12

Show me the menu! (or How to put a vertical Superfish menu in WordPress)

edited on 28 December 2012: I have been having the worst trouble getting Superfish to work in WordPress so came back to this. There is one major edit, you need to change the wp_nav_menu parameter ‘theme_location’ to ‘menu’ – I’m now using WordPress 3.5, so this might have to do with one of the recent upgrades. Please note, that you don’t have to use the vertical menu, just take out sf-vertical in the wp_nav_menu menu_class bit.

=====

Doesn’t everyone want a vertical slidey (according to my spellchecker, “slidey” is not a word. Really? Weird.) menu?  No?  Ok then, stop here.

If you do want a slidey (I’m just going to keep using the word, that’ll teach ’em) menu and have figured out that the one you want is J Birch’s excellent jQuery plugin Superfish (it is the one you want btw) and have read Kavin’s excellent tutorial but still need a bit of help and want it vertical, then here you go.

Oh damn, I meant to add in that thing that makes code show up properly.  Hang on.  Ah – the Syntax Highlighter plugin by Alex Gorbatchev should work.  It does!  Excellent.

Here are the steps you want to take, in plain-ish English:

  1. Download the Superfish plugin.
  2. Upload the plugin to your template directory (it needs to be unzipped either before or after upload obvs) – I renamed the folder “Superfish-1.4.8” to “superfish”.
  3. In your wp_nav_menu bit (in header.php or wherever), use ‘menu_class’ => ‘sf-menu sf-vertical’ eg:
    wp_nav_menu( array( ‘sort_column’ => ‘menu_order’, ‘menu_class’ => ‘sf-menu sf-vertical’, ‘theme_location’ => ‘primary-menu’ ) );  — this is what needed to be edited. Change ‘theme_location’ to ‘menu’ to get the right menu. Below is correct sample code.

    wp_nav_menu( array( 'sort_column' => 'menu_order', 'menu_class' => 'sf-menu sf-vertical', 'menu' => 'primary-menu' ) ); 

    I’m using a custom nav menu, ‘primary-menu’ – don’t just copy and paste the above.

  4. Make a file with the following – mine is named jqsf.js (taken from this support thread) – and upload to your superfish (or whatever you’ve named it)/js directory
    $(document).ready(function(){
    $("ul.sf-menu").superfish({
    animation: {height:'show'},   // slide-down effect without fade-in
    delay:     1200               // 1.2 second delay on mouseout
    });
    });

    This initialises Superfish and is where you can change the animation options and various bits and bobs.  It’s good fun to play with these.

  5. In your template’s style.css file, disable / delete any and all styles relating to the navigation lists – you can add them back later when it’s working.  (Setting a width on the ul caused mine to break which is easy enough to fix but took a while to figure out.)
  6. Add the following to your functions.php file – this assumes you’ve named the directories and files the same as I did.  This is, in large part, taken from Kavin’s tutorial mentioned above. He goes through it more thoroughly, so have a look there if you have questions.
    //jQuery Insert From Google - via http://digwp.com/2009/06/use-google-hosted-javascript-libraries-still-the-right-way/
    if (!is_admin()) add_action("wp_enqueue_scripts", "my_jquery_enqueue", 11);
    function my_jquery_enqueue() {
    $scriptdir=get_bloginfo( 'template_url' );
    wp_deregister_script('jquery');
    wp_register_script('jquery', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js", false, null);// Register the Superfish javascript file
    wp_register_script( 'superfish', $scriptdir.'/superfish/js/superfish.js', false, '1.4.8');// Register the file you made that initialises Superfish
    wp_register_script( 'jqsf', $scriptdir.'/superfish/js/jqsf.js', false);// Now the superfish CSS - you need superfish.css AND superfish-vertical for the vertical menu
    wp_register_style( 'superfish-css', $scriptdir.'/superfish/css/superfish.css', false, '1.4.8');
    wp_register_style( 'superfish-vertical-css', $scriptdir.'/superfish/css/superfish-vertical.css', false);//Put all the scripts and styles in the header where they belong
    wp_enqueue_script('jquery');
    wp_enqueue_script('superfish');
    wp_enqueue_script('jqsf');wp_enqueue_style('superfish-css');
    wp_enqueue_style('superfish-vertical-css');
    }
    

And that’s it.  You should have a working vertical menu.  You’ll need to style it – just edit the superfish.css style.  It’s well annotated, so you shouldn’t have any trouble.  The site I used this on is not yet ready for public consumption, but I will update this post when it is.


04
Jan 12

WordPress for iOS

Setting up this app [edit: it allows me to post to this self-hosted WordPress blog using my iPhone]. It’s slow on my phone so I will finish on my computer which is just over there. Give me a minute, I need a hot drink.

Sorry that took so long.  I put in some laundry, made it so that a client could use the app, wrote an email explaining how to do it and fixed a few bits and bobs on the site (at the end).  I also had a little bit of mug angst getting the tea.  I generally use the same mugs over and over but worry about the less frequently used mugs getting a complex, so used the cat mug.  Then I took a photo of it, because posts are nicer with photos and I thought the cat mug would appreciate it.

There is a reason everything takes me forever to do.

Back to setting up the app.  It was easy enough to download from the app store – search “WordPress” and it’s WordPress for iOS.  The first error I had was:

412 Precondition Failed. The precondition on the request for the URL /blog/xmlrpc.php evaluated to false.

Something like that, at any rate.  The file path was different.  It’s easy enough to fix, add:

to your .htaccess file as per the instructions on the WordPress support forum.  My second error was:

xml-rpc services are disabled on this site.  An admin user can enable them at … options-writing.php

Easy to fix, simply go to your dashboard, then Settings -> Writing, and tick the box under Remote Publishing labeled XML-RPC.

Tick the box. It's easy.

There you go! Or at least, there I went. I didn’t have any further errors except user errors (couldn’t type my password properly) and it worked fine. It was sloooow on my phone though but I’m on an iPhone 3GS running OS 4.2.1.  Getting a new one soon.

What I did on the site:

Put in a proper favicon in the ico format, using ConvertICO.com. My Firefox isn’t showing the favicon for some reason but it can be a little tempermental, I think it’s all the crap I have installed.  There was something else, too, but I forget what.