01 Dec 2010
Recently I was working on a website for a small business client. They wanted a simple system to allow them to easily update a section of their website. Since it was a small website, I wanted to accomplish this without putting too much time but still creating something user-friendly and easy to use that can get the job done. The main site was made using CodeIgniter. So we decided to create a WordPress blog for the client where they could put their content and I would pull that content inside their CI website. Here’s how:
First of all, install WordPress in a folder called blog in your website. It would be located at the top level directory of the website. So it would be alongside the system folder of the CI installation. If you already have a DB for your site, have WordPress add tables to that same DB with a prefix to make things simple (although this is not a requirement).
Once that’s done. All you have to do is add the following line in the at the top of your CodeIgniter’s index.php file. Change the path to wp-blog-header.php as needed to point to your wordpress’s root directory.
<?php
require('blog/wp-blog-header.php');
One you get that dialed in, rest is pretty straight forward. All of WordPress’ native API functions should now be accessible to you. So you could throw in a WordPress loop in any of the CI views like for example:
Articles.php (View):
<?php
if ($type == 'Tag') { query_posts('tag='.$id.'&posts_per_page=-1'); }
else if ($type == 'Category') { query_posts('category_name='.$id.'&posts_per_page=-1'); }
else { query_posts('posts_per_page=-1'); }
while (have_posts()) : the_post(); // Loop
?>
<a href="<?=base_url();?>Research/Article/<?php the_ID(); ?>"><h4><?php the_title(); ?></h4></a>
By <?php the_author(); ?>
<p class="details"><? the_time('F jS, Y') ?></p>
<?php the_excerpt(); ?>
<hr/>
<?php
endwhile; // End Loop
?>
…and a sidebar on the same which which would list out all the tags and categories to select from:
<!-- SIDE BAR -->
<div id="sideBar">
<h3>Categories:</h3>
<?php
$args = array(
'show_option_all' => '',
'orderby' => 'name',
'order' => 'ASC',
'show_last_update' => '0',
'style' => 'none',
'show_count' => '0',
'hide_empty' => '1',
'use_desc_for_title' => '1',
'child_of' => '0',
'feed' => '',
'feed_type' => '',
'feed_image' => '',
'exclude' => '',
'exclude_tree' => '',
'include' => '',
'current_category' => '0',
'hierarchical' => 'true',
'title_li' => __( 'Categories' ),
'number' => NULL,
'echo' => '1',
'depth' => '0');
wp_list_categories( $args ); ?>
<br>
<h3>Tags:</h3>
<?php
$args = array(
'smallest' => '12',
'largest' => '12',
'unit' => 'px',
'number' => '45',
'format' => 'flat',
'separator' => ' ',
'orderby' => 'name',
'order' => 'ASC',
'exclude' => '',
'include' => '',
'link' => 'custom',
'taxonomy' => 'post_tag',
'echo' => true,
'link_url' => base_url()."Research/Articles/Tag/");
wp_tag_cloud( $args ); ?>
</div>
<!-- /SIDE BAR -->
Article.php (View):
<!-- CONTENT -->
<div id="mainContent">
<!-- LEFT NAV -->
<div id="leftNav">
<a href="<?=base_url();?>Research/Articles" class="selected">Articles</a>
</div>
<!-- /LEFT NAV -->
<!-- MAIN COL -->
<div id="mainColWide">
<h1><?= $post->post_title ?></h1>
<p class="details"><?= the_time('F j, Y') ?></p>
<?= wpautop($post->post_content) ?>
<br/><br/>
<a href="<?=base_url();?>Research/Articles">back</a>
</div>
<!-- /MAIN COL -->
<br class="clearFloat" />
</div>
<!-- /CONTENT -->
Research.php (Controller):
<?php
class Research extends Base_Controller {
function Research()
{
parent::Base_Controller();
}
function Index()
{
$this->data['content'] = $this->load->view('Research/index.php', $this->data, true);
$this->load->view('layouts/master' ,$this->data);
}
function Articles($type = '', $id = '')
{
$this->data['type'] = $type;
$this->data['id'] = $id;
$this->data['content'] = $this->load->view('Research/articles.php', $this->data, true);
$this->load->view('layouts/master' ,$this->data);
}
function Article($id)
{
$this->data['post'] = get_post($id);
$this->data['id'] = $id;
$this->data['content'] = $this->load->view('Research/article.php', $this->data, true);
$this->load->view('layouts/master' ,$this->data);
}
}
That’s it! This would allow us to browse all the blog entries without leaving the CI site. Other helper functions can also be found in WordPress’s documentation which can assist you in integrating the design.
18 Mar 2010
Here’s a code snippet of parsing a typical WordPress RSS feed using LINQ. Note, we have to skip the first image from the media element since that’s usually a gravatar of the author.
Everything else is pretty straight forward.
private void BindBlogFeed()
{
XDocument doc = XDocument.Load("http://blogworkseverytime.wordpress.com/feed/");
XNamespace content = "http://purl.org/rss/1.0/modules/content/";
XNamespace media = "http://search.yahoo.com/mrss/";
var query = (from feed in doc.Descendants("item")
orderby DateTime.Parse(feed.Element("pubDate").Value) descending
select new
{
Title = feed.Element("title").Value,
Description = HttpUtility.HtmlDecode(feed.Element("description").Value),
Content = HttpUtility.HtmlDecode(feed.Element(content.GetName("encoded")).Value),
Image = (from img in feed.Elements(media.GetName("content"))
where img.Attribute("url").Value.Contains("gravatar") == false
select img.Attribute("url").Value).FirstOrDefault() ?? "",
Link = feed.Element("link").Value,
Date = DateTime.Parse(feed.Element("pubDate").Value).ToShortDateString()
});
lvFirstBlogFeed.DataSource = query.Take(1).ToList();
lvFirstBlogFeed.DataBind();
lvRemainingBlogFeed.DataSource = query.Skip(1).ToList();
lvRemainingBlogFeed.DataBind();
}
26 Jan 2010
In this post I will talk about how to create a Facebook Connect site using the CodeIgniter framework.
So first of all, before you being, download the Facebook Platform client library from here. Extract the files and copy everything inside /php folder (including the ‘jsonwrapper’ folder) to the /system/plugins folder of your CI application. Once you do that, rename the facebook.php file to facebook_pi.php. Doing so will make CI recognize the library as a plugin. Now you will be able to reference the library just how you would reference any other plugins as you will see below.
Once you’ve done that. We are all set to write some code. The first key step to this is to extend the base controller and create a Facebook Controller that can handle user authentication and pass other needed variables. This extended controller would have to reside in /system/application/libraries/MY_Controller.php:
class Facebook_Controller extends Controller {
var $facebook;
var $fb_uid;
var $fb_user_details;
var $user;
var $permissions_to_request;
var $logged_in;
public $data;
function Facebook_Controller() {
parent::Controller();
$this->output->set_header("Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
$this->output->set_header("Pragma: no-cache");
// Created some Facebook helper functions to make things easier and pull API Key, Secret Key, Base URLs, etc from the Facebook config file.
$this->__fbApiKey = get_facebook_api_key();
$this->__fbSecret = get_facebook_secret_key();
// Prevent the 'Undefined index: facebook_config' notice from being thrown.
$GLOBALS['facebook_config']['debug'] = NULL;
// Create a Facebook client API object.
$this->facebook = new Facebook($this->__fbApiKey, $this->__fbSecret);
$this->fb_uid = $this->facebook->get_loggedin_user();
//Check to see if the user is logged in with facebook
if($this->fb_uid)
{
$fb_uid = $this->fb_uid;
//If this is the first login with the site
if(!$this->_get_user_session_object($fb_uid))
{
//Check to see if user is in the db
$this->load->model('User_model');
$this->user = $this->User_model->get_user_by_fb_uid($fb_uid);
$this->fb_user_details = $this->Facebook_model->get_user_details($fb_uid);
//If its not in the db, do an insert
if(!$this->user)
{
$user_data = array('fb_uid' => $fb_uid, 'created_at' => date('Y-m-d H:i:s'));
$user_id = $this->User_model->insert_user($user_data);
//Give them a default username
$user_data = array('username' => 'user'.$user_id);
$this->User_model->update_user($user_id, $user_data);
$this->user = $this->User_model->get_user_by_user_id($user_id);
}
$this->_set_user_session_object($fb_uid, $this->user);
$this->_set_user_details_session_object($fb_uid, $this->fb_user_details);
//Check to see if user has all the required permissions
$has_publish_stream_permission = $this->facebook->api_client->call_method('Users.hasAppPermission',array('ext_perm'=>'publish_stream', 'uid'=>$fb_uid));
$has_email_permission = $this->facebook->api_client->call_method('Users.hasAppPermission',array('ext_perm'=>'email', 'uid'=>$fb_uid));
//Request the missing permissions
$permissions_to_request = $has_publish_stream_permission == 0 ? "publish_stream" : null;
if($permissions_to_request)
$permissions_to_request .= ",";
$permissions_to_request .= $has_email_permission == 0 ? "email" : null;
// I wanted to use this approach but it left a trailing comma in the end so it didn't work out. I'm sure there is a way around it.
//$arry_permissions_to_request = array($has_publish_stream_permission == 0 ? "publish_stream" : null, $has_email_permission == 0 ? ",email" : null);
//$permissions_to_request = implode(",", $arry_permissions_to_request);
$this->permissions_to_request = $permissions_to_request;
}
else
{
//Load the user object back from the session
$this->user = $this->_get_user_session_object($this->fb_uid);
$this->fb_user_details = $this->_get_user_details_session_object($this->fb_uid);
}
}
//Set master page data variables
$this->data['user'] = $this->user;
$this->data['fb_user_details'] = $this->fb_user_details;
$this->logged_in = ($this->user && $this->fb_uid)? true : false;
$this->data['logged_in'] = $this->logged_in;
$this->data['request_permissions'] = $this->permissions_to_request ? true : false;
$this->data['permissions_to_request'] = $this->permissions_to_request;
$this->data['fb_login_prompt'] = false;
$this->data['current_controller'] = get_class($this);
}
function _get_user_session_object($fb_uid)
{
return $this->session->userdata($fb_uid.'_user_object');
}
function _get_user_details_session_object($fb_uid)
{
return $this->session->userdata($fb_uid.'_user_details_object');
}
function _set_user_session_object($fb_uid, $user)
{
$this->session->set_userdata($fb_uid.'_user_object', $user);
}
function _set_user_details_session_object($fb_uid, $fb_user_details)
{
$this->session->set_userdata($fb_uid.'_user_details_object', $fb_user_details);
}
}
Once we have that setup, we can go ahead and create a master page which will load the header, footer, navigation and all the other site-wide global elements. Part of which, the header, could look something like this, it would show the user’s profile pic & name when logged in and show a Facebook Connect button when logged out. You can put this master page inside /system/application/views/layouts/master.php:
<div id="header">
<?php if (!$logged_in) { ?>
<div style="margin-top:18px">
<a href="#" id="fbconnect_login_button" class="fbconnect_login_button" onclick="FB.Connect.requireSession(); return false;" >
<img id="fb_login_image" src="http://static.ak.fbcdn.net/images/fbconnect/login-buttons/connect_light_medium_long.gif" style="border:0;" alt="Connect"/>
</a>
</div>
<?php } else { ?>
<div class="floatR">
<fb:profile-pic uid="<?=$user['fb_uid']?>" size="square" facebook-logo="true"></fb:profile-pic>
</div>
<div class="floatR" style="margin-top:13px">
Welcome, <?=$fb_user_details[0]['name']?>
<br />
<a href="#" onclick="FB.Connect.logout(function() { facebook_onlogout(); }); facebook_onlogout()">Logout of Facebook</a>
</div>
<br class="clearFloat" />
<?php } ?>
</div>
Content area would just be one variable which will load the content from the page controller as we will see further on:
<div id="mainContent">
<?=$content?>
</div>
And finally, the most important part, the footer which would load & initialize the Facebook library, take care of prompting for the right permissions, and require the user to login on certain pages based on the controller:
<div id="footer">
<script type="text/javascript">
function setFocus() { window.document.<?=$current_controller?>.focus(); }
</script>
<script src="<?=get_static_facebook_root();?>/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>
<script type="text/javascript">
FB.init("<?=get_facebook_api_key();?>", "<?=base_url();?>xd_receiver.htm", {"reloadIfSessionStateChanged":true});
</script>
<script src="<?=base_url();?>shared/js/fbconnect.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
facebook_onload(<?=$logged_in?>);
<?php if ($request_permissions) { ?>facebook_prompt_permission("<?=$permissions_to_request?>");<?php } ?>
};
</script>
<?php if ($fb_login_prompt && !$logged_in) { ?>
<script type="text/javascript">
FB.ensureInit(function() {
FB.Connect.requireSession(null, function(){ location.href = "<?=base_url();?>home"; });
});
</script>
<?php } ?>
</div>
As you can see, I’ve used some JavaScript in fbconnect.js to help us invoke the permissions and/or dialog box as needed:
/*
* The facebook_onload statement is printed out in the PHP. If the user's logged in
* status has changed since the last page load, then refresh the page to pick up
* the change.
*
* This helps enforce the concept of "single sign on", so that if a user is signed into
* Facebook when they visit your site, they will be automatically logged in -
* without any need to click the login button.
*
* @param already_logged_into_facebook reports whether the server thinks the user
* is logged in, based on their cookies
*
*/
function facebook_onload(already_logged_into_facebook) {
// user state is either: has a session, or does not.
// if the state has changed, detect that and reload.
FB.ensureInit(function() {
FB.Facebook.get_sessionState().waitUntilReady(function(session) {
var is_now_logged_into_facebook = session ? true : false;
// if the new state is the same as the old (i.e., nothing changed)
// then do nothing
if (is_now_logged_into_facebook == already_logged_into_facebook) {
return;
}
// otherwise, refresh to pick up the state change
refresh_page();
});
});
}
function facebook_onlogin_ready() {
refresh_page();
}
function facebook_onlogout() {
$.post("./Logout", null, null);
}
function refresh_page() {
location.reload(true);
}
function facebook_prompt_permission(permission) {
FB.ensureInit(function() {
FB.Connect.showPermissionDialog(permission);
});
}
Now that we have the master page setup, we can inject our content into the master page from any page controller:
class Test extends Facebook_Controller {
function Test()
{
parent::Facebook_Controller();
}
function Index()
{
$this->data['fb_login_prompt'] = true;
$this->data['content'] = $this->load->view('test', $this->data, true);
$this->load->view('layouts/master' ,$this->data);
}
So, thats it! Now you should have a fully functional Facebook connect site in CodeIgniter!
Inspired by:
http://junal.wordpress.com/2008/01/20/a-sample-facebook-application-with-codeigniter/
http://www.simpleprojectz.com/2008/10/facebook-codeigniter/
http://codeigniter.com/forums/viewthread/120393/
20 Jun 2009
If you’re running WordPress on IIS7 like this blog and if you want clean URLs without the “index.php” you can do the following.
Although before you get started you need to make sure you have FastCGI and URL Rewrite Module installed on your IIS7.
If you’re missing one of those things, you can check out these guides:
Once you’ve done that, go to the “Settings” section in your WordPress admin area and click on “Premalinks”:
On that page, choose the “Custom, specify below” option and enter
“/%year%/%monthnum%/%postname%/” (or any other format of your choosing) in the “Custom structure” text box.
After you save the settings, you’ll notice that all your blog posts will have their URLs in the format you specified earlier. Although if you try to click on one of them you’ll get a 404 - File Not Found error. Thats because we still haven’t told the server where to go when it gets those requests.
To do so, you’ll have to create a Web.Config file (if you don’t have one already) in the same directory as your WordPress blog. Once you’ve done that, paste the following inside configuration->system.webServer element:
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
Click here to download the entire Web.Config file.
That rewrite rule we added above will match any requested URL and if that URL does not corresponds to a file or a folder on a file system, then it will rewrite the URL to Index.php. At that point, WordPress will determine which content to serve based on the REQUEST_URI server variable that contains the original URL before it was modified by the rule.
After you’ve saved the Web.config file, fire up any one of the permalinks in your WordPress blog. If everything went as expected, you’ll see the correct content returned by the web server for every permalink.
06 May 2009
Lately I’ve been working on my side project called Twime. So as part of that project, I wanted to add the ability to parse URLs, usernames and hashtags from the user’s Twitter timeline. Here’s how I went about doing that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;
public static class HTMLParser
{
public static string Link(this string s, string url)
{
return string.Format("<a href=\"{0}\" target=\"_blank\">{1}</a>", url, s);
}
public static string ParseURL(this string s)
{
return Regex.Replace(s, @"(http(s)?://)?([\w-]+\.)+[\w-]+(/\S\w[\w- ;,./?%&=]\S*)?", new MatchEvaluator(HTMLParser.URL));
}
public static string ParseUsername(this string s)
{
return Regex.Replace(s, "(@)((?:[A-Za-z0-9-_]*))", new MatchEvaluator(HTMLParser.Username));
}
public static string ParseHashtag(this string s)
{
return Regex.Replace(s, "(#)((?:[A-Za-z0-9-_]*))", new MatchEvaluator(HTMLParser.Hashtag));
}
private static string Hashtag(Match m)
{
string x = m.ToString();
string tag = x.Replace("#", "%23");
return x.Link("http://search.twitter.com/search?q=" + tag);
}
private static string Username(Match m)
{
string x = m.ToString();
string username = x.Replace("@", "");
return x.Link("http://twitter.com/" + username);
}
private static string URL(Match m)
{
string x = m.ToString();
return x.Link(x);
}
}
So as you can see I’m using the new Extension Methods feature in C# 3.0.
Now I can simply just call the extension methods like this:
string tweet = "Just blogged about how to parse HTML from the @twitter timeline - http://jes.al/2009/05/how-to-parse-twitter-usernames-hashtags-and-urls-in-c-30/ #programming";
Response.Write(tweet.ParseURL().ParseUsername().ParseHashtag());
and the result should looks something like this:
Just blogged about how to parse html from the @twitter timeline - http://jes.al/2009/05/how-to-parse-twitter-usernames-hashtags-and-urls-in-c-30/ #programming
Just be sure to call ParseURL method before ParseUsername and ParseHashtag. The other two methods will add URLs to the usernames and hashtags and you don’t want ParseURL to confuse those links with the original links present in the text.
This was inspired by Simon Whatley’s post about doing something similar using prototyping with JavaScript.