Archive by Author

CodeIgniter Snippets for Visual Studio

I thought I would share something I have been using for quite a while now and find incredibly useful. They are two snippets for Visual Studio that create the standard file start and file end for php files in the codeigniter framework. If you are not sure what I mean then check out the files that make up the framework – you will notice that they all tend to start with:

<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

and end with:

/* End of file MyFile.php */
/* Location: ./path/to/file/MyFile.php */

The line at the start of the file is a security measure to stop files being executed outside the framework, whilst the end is just informative but useful anyhow.

I like to do the same thing with all the files I create for my applications but found the typing tedious and because I use the VS.php in Visual Studio, I decided to write a couple of snippets to do it for me.

If you are not familiar with snippets in Visual Studio or how to get the following xml to work as a snippet, you can read all about then on msdn. Anyhow, without further ado, here they are:

filestart.snippet:

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>filestart</Title>
      <Author>Dan Sargeant</Author>
      <Description>CodeIgniter File start to stop direct script access</Description>
      <HelpUrl></HelpUrl>
      <SnippetTypes>
          <SnippetType>Expansion</SnippetType>
	      <SnippetType>SurroundsWith</SnippetType>
	  </SnippetTypes>
      <Shortcut>filestart</Shortcut>
    </Header>
    <Snippet>
      <Code Language="PHP" Kind="" Delimiter="$"><![CDATA[<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

fileend.snippet:

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>fileend</Title>
      <Author>Dan Sargeant</Author>
      <Description>CodeIgniter file ending</Description>
      <Shortcut>fileend</Shortcut>
      <SnippetTypes>
          <SnippetType>Expansion</SnippetType>
	      <SnippetType>SurroundsWith</SnippetType>
	  </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>filename</ID>
          <ToolTip>Filename</ToolTip>
          <Default>myfile.php</Default>
        </Literal>
        <Literal>
          <ID>directory</ID>
          <ToolTip>Directory</ToolTip>
          <Default>models</Default>
		  </Literal>
      </Declarations>
      <Code Language="PHP"><![CDATA[
/* End of file $filename$*/
/* Location: ./application/$directory$/$filename$*/]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Convert to Apple Lossless Codec: The Easy Way

Playing lossless codecs like APE or FLAC in itunes or on your iphone is not so easy as there is no native support for them. Converting them to the Apple equivalent is also quite tricky. Many people recommend installing media players that support this conversion or purchasing a commercial product to do it. However, there is a free and easy way to convert your files in Windows that does not require any installation.

The key to it is the use of the windows port of ffmpeg. It can convert just about anything to anything. However, it is a command line tool and converts one file at a time which means a lot of typing if you want to convert an entire album. I spent a little time the other day figuring out a small batch file that can be used to convert and entire albumn in on go. I thought I’d share it with you. Just create a file called say, convert.bat and place one of the following in it:

For Monkey’s Audio APE files:

for /f "tokens=*" %%a IN ('dir /b *.ape') do call ffmpeg -i "%%~na%%~xa" -acodec alac "%%~na.m4a"

For FLAC files:

for /f "tokens=*" %%a IN ('dir /b *.flac') do call ffmpeg -i "%%~na%%~xa" -acodec alac "%%~na.m4a"

Then all you have to do is place your batch file, along with ffmpeg.exe into the directory that contains the files you want to convert and run the batch file. It will convert every file in the directory to apple lossless. Easy.

Using Beyond Compare 3 With Git Extensions

It seems I have gained a reputation amongst my peers to be a diff tool hopper. That is, I am on a quest to find the perfect diff tool for my development. I think I have given just about every free tool out there a good run for it’s money and tend to move to the next one when I find myself in a situation that the current tool cannot cope with.

After exhausting all the free options, I made the shift to the commercial tool Beyond Compare 3 a few weeks ago and have not looked back since. So far, it has been awesome. Slick, easy to understand the differences and the pro version even does the three way merging needed for git.

I spend most of my development time, be it C#, VB, PHP or Javascript in the visual studio environment and so when I use git for source control, git extensions is essential. Making both git extensions and Beyond Compare work together is a little bit of trail and error as the very informative source control support page only covers configuring git via the bash. So to save myself the brain ache again and perhaps to help others, I jot these settings down:

Under Global Settings:

Merge tool: BCompare
Path to mergetool: C:/Path/To/BComp.exe
Mergetool command: “C:/Path/To/BComp.exe” “$LOCAL” “$REMOTE” “$BASE” “$MERGED”

Diff tool: BCompare
Path to difftool: C:/Path/To/BComp.exe
Difftool command: “C:/Path/To/BComp.exe” “$LOCAL” “$REMOTE”

Make sure you dont override the tool in the local settings or if you want to set it to BCompare.

CodeIgniter: Using set_value with Form Posts

Today I came across an interesting bug in a codeigniter application I was working on where I encoded ampersands (&amp) were appearing in a report. I did some rudimentary debugging and realised that for some reason, values from a form were being saved to the database html encoded.

I stepped through the code and discovered that I was using the set_value() function to retrieve the value posted from the form. This is a no-go I’m afraid. set_value is supposed to be used to set the values of inputs and textareas in forms within the view itself and as such runs the htmlspecialchars function across the form post value before returning it. There is a function specifically designed for what I wanted: $this->input-post(fieldname). Lesson learned.

Migrating from SVN to Git on MediaTemple (gs)

After seeing a video on using Mecurial on Codeplex I finally took the plunge into distribute revision control. Although Mercurial seemed to have better integration with Visual Studio, which is my main IDE, I decided to use Git instead. This decision was based purely on a gut feeling about which would be the best choice in the long run. If its good enough to write Linux with, it’s good enough for me.

The shift from SVN to Git was surprisingly easier than I expected. I remember SVN being a little frustrating to get going when I first started with that and was expecting a similar experience, especially when I was trying to shift a couple of in-progress projects from one to the other. What I did find however, is that the guides out there, although pretty good, did not quite match what I wanted to do. I thought I would jot it down so I don’t forget when I need to go it again. Its all done by logging into your server using putty or whatever your ssh client is. Lets jump straight in:

Git is installed on the (gs) so we can get straight into it. Firstly create a directly where you would like to keep your repositories:

mkdir /home/#####/data/git

Next create a temporary directory to store the git-svn export of your svn repository:

mkdir /home/#####/data/git/myapp_tmp

Next, create a text file (users.txt) to map your svn users to you git users. It should contain something like:

mysvnuser1 = Git User1 <gituser1@mysite.com>
mysvnuser2 = Git User2  <gituser2@mysite.com>

I saved mine to the /home/#####/data/git/ directory.

Next we initialise our git repository, ready to import the svn repository:

git-svn init file:///path/to/svnrepo/myapp/trunk/ --no-metadata

Note that I use the file:// notation to specify a local path to where my svn repository is kept. In my case it was /home/#####/data/svnrepo/ but it depends on how you set yours up. The no-metadata flag just ensures that only the information we need is transferred. We then need to setup our user mapping file:

git config svn.authorsfile /home/#####/data/git/users.txt

Now for the money shot, we import the data from svn:

git-svn fetch

All going well, your svn repository and all the history should have been imported into your git repository.

The final steps are done in order to tidy up your new git repository so that it is just a standard git repository, without all the svn associations. We remove the svn assocations by cloning it:

git clone myapp_tmp myapp.git

This gives you a myapp.git directory with the actual repository (everything in the .git directory) as well as your working files. As this is on the server, you do not need all the working files, just everything in the .git directory. We can fix that as follows:

cd myapp.git
mv .git .. && rm -fr *
mv ../.git .
mv .git/* .
rmdir .git
git config --bool core.bare true

Most of those commands just move everything out of the .git directory and remove the working files. The final command however marks the repository as a bare repository, i.e. one without the working files.

Thats it. You should now have a git repository on your server that you can clone to your development machine and begin work.

Mocking Session in ASP.NET with Moq and VB.NET

logo

It has been a few years since I have had the chance to explore the latest enhancements to ASP.NET. The development in my day job was locked into traditional ASP.NET forms just before MVC 1.0 was released and there has not been any opportunity to change. TDD, dependency injection and inversion of control containers all slipped by with me staring at them with my nose pressed against the window. I also develop in php with CodeIgniter, so I am quite familiar with the idea of MVC and was thoroughly excited when recently, the company I work for, began brewing the idea for a new project. Now was the time to change, so I stocked up on books and blog articles and began the big catch up. I won’t go on about how great MVC is, especially when I spent many hours battling against the web form paradigm – its such an anti-web way of doing things but with these new ways of working, I now feel a new vigour for .Net web development.

My journey found me working with Moq and although it is pretty self explanatory, most examples and articles are in C# and the documentation for the library is a little sparse. I don’t find the switching between C# and VB.NET very difficult as there is mostly only a syntax difference between them but I did find a problem when, in my unit tests, I needed to assert that entries in the session had been set correctly. So here is how to do it in VB.NET.

Checking a value has been set in Session

The first thing that you need is a session object that you can look at in your tests. It needs to inherit from HttpSessionStateBase and is pretty simple as the session is just a key-value store – we can use a generic dictionary to store the values we want to check:

Public Class HttpSessionMock
    Inherits HttpSessionStateBase
    Private ReadOnly objects As New Dictionary(Of String, Object)()
 
    Default Public Overloads Overrides Property Item(ByVal name As String) As Object
        Get
            Return If((objects.ContainsKey(name)), objects(name), Nothing)
        End Get
        Set(ByVal value As Object)
            objects(name) = value
        End Set
    End Property
 
    Public Overrides Sub Add(ByVal name As String, ByVal value As Object)
        objects.Add(name, value)
    End Sub
End Class

So we now have a session store and we can then use Moq to utilise that in our controller during our test. This is done be setting up a controller context:

 'Create a real mock session object to check value against
 Dim session As New HttpSessionMock()
 
 'Create a moq controller context
 Dim mockcontext As New Mock(Of ControllerContext)
 
 'Ensure our session object is returned when the session is requested
 mockcontext.SetupGet(Function(c As ControllerContext) c.HttpContext.Session).Returns(session)
 
 'set our controller context to be the moq context
 MyController.ControllerContext = mockcontext.Object

We can then run our controller action that sets a value in our mock session object and assert that the correct value is set as follows:

  'run the controller action
 Dim result = MyController.SomeAction()
 
 'assert the session contains the object we expect
 Assert.IsInstanceOfType(session.Item("SessionItemToCheck"), GetType(ExpectedSessionObject))
 
 'TODO:other tests to ensure session item is correct

Ensuring a value is returned from Session

You can use the above real mock session object to do this in exactly the same way but we can also setup Moq to return a particular value from session directly:

'create a test object/value we want session to return
Dim MySessionValue as New SomeObject()
 
'create our moq controller context
Dim mockcontext As New Mock(Of ControllerContext)
 
'ensure our test object gets returned by the moq session
mockcontext.SetupGet(Function(c As ControllerContext) c.HttpContext.Session("SessionItemToTest")).Returns(MySessionValue)
 
'assign our context to the controller	
controller.ControllerContext = mockcontext.Object
 
'TODO: run controller action and assert results

When I look at the code now, I realise that it is quite simple to achieve. However, it took me a little while to get my head around Moq and figure this out as all the examples out there seemed to be trying to do so much more than solely testing session state. It confused me anyhow.

AjaxQueue and jQuery 1.3

800px-Queue_algorithmn The website that I work on for the majority of my time had been running on the rather out of date jQuery 1.2 for quite some time. I recently found myself with a little bit of downtime and decided it was a good time to see if we could upgrade and take advantage of all the speed improvements that the latest version gives us.

On the most part, the upgrade was fairly painless. Most things worked without change but one particular plug-in did not – AjaxQueue. This is a great little control that acts as an add-on to the ajax method of jQuery, allowing a little more control over how concurrent calls are processed. It gives three modes of operation but for us, the most useful of these are abort and queue and from the names it is fairly obvious what they do.

After I upgraded to jQuery 1.3, it did not take me long to realise that the queue mode was broken. I briefly looked around for an alternative plug-in but found that all of them would require too much change to our existing controls. There was no alternative, I had to open up the hood of AjaxQueue and see what had gone wrong.

What I found was that there must of been a change to a method that the plug-in relied on – a method that it seemed, only became publicly available in version 1.3 – queue. Although the function was similar, the conclusion that I came to was that prior to version 1.3, the queue function automatically de-queued any function added and processed it. When using the latest jQuery, the ajax calls were queued but there was no code to start the processing of the queue.

It was slightly more complex I thought it would be to get it going – I had to ensure the queue was only started once. I finally came up with a solution and a newly revived plug-in, the code of which is below. As the original plugin has not been touched for quite some time (2007), I thought it ok to post my modified version here.

(function($) {
 
    var ajax = $.ajax,
        pendingRequests = {},
        synced = [],
        syncedData = [],
        ajaxRunning = [];
 
 
    $.ajax = function(settings) {
        // create settings for compatibility with ajaxSetup
        settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
 
        var port = settings.port;
 
        switch (settings.mode) {
            case "abort":
                if (pendingRequests[port]) {
                    pendingRequests[port].abort();
                }
                return pendingRequests[port] = ajax.apply(this, arguments);
            case "queue":
                var _old = settings.complete;
                settings.complete = function() {
                    if (_old) {
                        _old.apply(this, arguments);
                    }
                    if (jQuery([ajax]).queue("ajax" + port).length > 0) {
                        jQuery([ajax]).dequeue("ajax" + port);
                    } else {
                        ajaxRunning[port] = false;
                    }
                };
 
                jQuery([ajax]).queue("ajax" + port, function() {
                    ajax(settings);
                });
 
                if (jQuery([ajax]).queue("ajax" + port).length == 1 && !ajaxRunning[port]) {
                    ajaxRunning[port] = true;
                    jQuery([ajax]).dequeue("ajax" + port);
                }
 
                return;
            case "sync":
                var pos = synced.length;
 
                synced[pos] = {
                    error: settings.error,
                    success: settings.success,
                    complete: settings.complete,
                    done: false
                };
 
                syncedData[pos] = {
                    error: [],
                    success: [],
                    complete: []
                };
 
                settings.error = function() { syncedData[pos].error = arguments; };
                settings.success = function() { syncedData[pos].success = arguments; };
                settings.complete = function() {
                    syncedData[pos].complete = arguments;
                    synced[pos].done = true;
 
                    if (pos == 0 || !synced[pos - 1])
                        for (var i = pos; i < synced.length && synced[i].done; i++) {
                        if (synced[i].error) synced[i].error.apply(jQuery, syncedData[i].error);
                        if (synced[i].success) synced[i].success.apply(jQuery, syncedData[i].success);
                        if (synced[i].complete) synced[i].complete.apply(jQuery, syncedData[i].complete);
 
                        synced[i] = null;
                        syncedData[i] = null;
                    }
                };
        }
        return ajax.apply(this, arguments);
    };
 
})(jQuery);

Cuesheet Maker Bookmarklet for Discogs.com

Yesterday I discovered I had a few albums that had been ripped as a single track. I prefer having individual tracks and usually head on over to cuesheet heaven to look for the appropriate file that allows me to split them up with the awesome Medieval Cue Splitter. However I had a few tracks that had I could not find the appropriate cuesheet file for. I find myself in this situation fairly regularly and have also noticed that these albums usually have an entry at discogs.com, which has all the details including track lengths.

This got me thinking that it would be awesome to be able to create cue files from discogs.com. So I created the following – a bookmarklet to do just that.

Disclaimer: it is pretty rough and I cannot guarantee that it will work with all discogs.com entries and there is hardly any error checking. I have only used this in Firefox so I cannot guarantee it will work in any other browser. It only pops up a dialogue with the cuesheet contents on it but that was adequate for me to copy and paste it into a text file and tweak it so that it was a valid cuesheet.

The important thing is that it gathers the track names and artists and works out the index times. It also attempts to cope with double cds and also single tracks that are two different records playing at once (common with DJ mixes). Here is the bookmarklet (drag it into your bookmarks tookbar), followed by the code itself:

Drag this to your bookmark toolbar: Create Cue

The code itself:

javascript:(function(){var s=document.createElement('SCRIPT');
s.type='text/javascript';
s.src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js';
s.onload=function() {
	var title = jQuery.trim(jQuery('div.profile h1').text()),
		performer = jQuery.trim(title.substring(0,title.indexOf('-'))),
		file = title + '.mp3', secCount = 0, trkCount = 0, cues = [], cdNo = 1;
	title = jQuery.trim(title.substring(title.indexOf('-')+1));
	tracks = [];
	jQuery('div.tracklist .section_content > table tr').each(function(ix, el) {
		var trackCd = jQuery.trim(jQuery('td.track_pos',this).text());
		if (trackCd && trackCd != '') {
			var track = {}, tracktime = [], isDouble = false;
			trackCd = trackCd.split('-');
			if (trackCd.length > 1) {
				if (jQuery.trim(trackCd[0]) != cdNo) {
					createCue();
					cdNo = trackCd[0];
				} else {
					if (parseInt(trackCd[1]) == trkCount) {
						isDouble = true;
					}
				}
			}
			if (!isDouble) {
				trkCount+=1;
				track['trackno'] = trkCount;
				track['artist']= jQuery.trim(jQuery('td.track_artists',this).text()).replace(/\s-$/g, '').replace(/\n/g, '').replace(/\s+/g,' ');
				track['artist'] = jQuery.trim(track['artist']);
				track['artist'] = (track['artist'] == '') ? performer : track['artist'];
				track['title'] = jQuery.trim(jQuery('td.track_title',this).text()); 
				tracktime =jQuery.trim(jQuery('td.track_duration',this).text()).split(':'); 
				track['index'] = secondsToMinSec(secCount);
				secCount += (tracktime[0] * 60) + (tracktime[1] * 1);
				tracks[tracks.length] = track;	
			}
		}
 
	});
 
	createCue();
 
	//print it out
	var output = '';
	jQuery.each(cues,function(ix, cue) {
		output += cue + '\n\n\n';
	});
 
	alert(output);
 
	function createCue() {
		var quo = unescape('%22'),
			cue = 'TITLE '+quo+title+quo+'\n';
		cue += 'PERFORMER '+quo+performer+quo+'\n';
		cue += 'FILE '+quo+file+quo+' MP3\n';
		jQuery.each(tracks,function(ix, track) {
			cue += '  TRACK '+track.trackno+' AUDIO\n';
			cue += '    TITLE '+quo+track.title+quo+'\n';
			cue += '    PERFORMER '+quo+track.artist+quo+'\n';
			cue += '    INDEX 01 '+quo+track.index+quo+'\n';
		});
		cues[cues.length] = cue;
		//reset
		secCount = 0; trkCount = 0; tracks = [];
	}
 
	function secondsToMinSec(totsec) {
		var min = Math.floor(totsec / 60), 
			sec = (totsec - (min * 60));
		if (min < 10) {
			min = '0' + min.toString();
		}
		if (sec < 10) {
			sec = '0' + sec.toString();
		}
		return min.toString() + ':' + sec.toString() + ':00';
	}
};
document.getElementsByTagName('head')[0].appendChild(s);})();

I hope this helps some people, as it has me. Feel free to improve on it but if you make any changes, please let me know so that I can improve my version too.

Enjoy

Edit: Well it was not long until discogs changed their layout. I have update the code to reflect this. All should be well again.

IIS7 WordPress and Friendly URLs

As a developer who uses Vista as their main OS, I have always found developing php sites a little bit awkward. Php never liked to play nicely with IIS and unless you installed and used Apache, friendly URLs were even more difficult to get working. I use IIS extensively for ASP.NET development and I never liked having both Apache and IIS installed together as they seemed to lock horns at every opportunity. My answer until now was to use VS.php, which runs an instance of Apache on demand, so I only have to use Apache when I need to. This was great for the most part but last week I had the situation where I was trying to work on both an ASP.NET project and a WordPress project at the same time. Stopping and starting web servers every few minutes was getting a little dull.

rewriteThis spurred me on to take some time to see what all the fuss about IIS7 and php was really about. I was pleasantly surprised. Since Vista SP1, it is possible to configure IIS to run php using FastCGI. I won’t go into the detail here, there are plenty of examples on how to configure php in this way. Needless to say, it was not too difficult and I had a test phpinfo(); page displaying in no time. What’s particularly great is that Microsoft has been doing some great work getting php to run as quickly and efficiently as it can on IIS. If you are happy running php version 5.3, over at Php for Windows, you can pick up a version that has been compiled in Visual Studio 2008 which means faster and more stable than before.

The next step in my investigation was to see what could be done with the new url rewrite module for IIS. Another easy thing to install. What’s more, it has the ability to import .htaccess files. I use these extensively when using Apache and I already had one for the WordPress site I was working on. Importing rules is a pleasure because of the neat interface that shows you which rules it can convert and which it cannot. Editing the original .htaccess directives on-screen allows you to fix those rules it is having trouble with. In my case it was just the RewriteBase, which I could happily remove without worrying about it.

One click of the ‘apply’ button and I was up add running. The site was responsive and low and behold, no issues with the friendly urls. Too easy!

Windows Server 2008, ASP.NET, Pre-compiling and Virtual Directories

windowsserver2008 There has been an interesting problem at work over the last couple of weeks. We are in the process of preparing to move service providers and at the same time upgrading all our servers to run Windows Server 2008 and SQL Server 2008. In preparation for this move, we have been upgrading our staging and test servers so we can be sure that everything will work as expected and to iron out the processes, so the move goes as smoothly as possible.

It took about ten minutes before we hit the strangest of problems. It was focused around the way we use a virtual directory to share common code and controls across different websites. The premise is that you create a project to hold your common javascript/images/ascx controls/web services and so on. You then use a virtual directory inside each of your websites that points to the common project. With only a small amount of tweaking for the common ascx controls everything seems to work without too much trouble. That is, until you try to do this on Windows Server 2008.

When we started up our web application on our new environment, we noticed almost immediately that the AJAX calls that used the common web service were failing. The error message was suggesting that the project that contained the common web service has not been compiled correctly. By copying the website across to a Windows 2003 server, we deduced that the problem was specific to 2008 as it worked perfectly on 2003. Having exhausted all the developers ideas on why this would be, we called Microsoft and got them involved in troubleshooting the issue.

A few days later an answer came: do not pre-compile your website. Sure enough, build the website without pre-compilation and it worked perfectly. Microsoft’s explanation was that it was due to a change in the way that Windows Server 2008/IIS7 worked. Fairly cryptic I must say and certainly does not leave me satisfied as to why it would not work and what have they done to stop it working. For us, using Windows Server 2008 and IIS7 is more important than the slight performance hit you get when deploying without pre-compilation. For others it may not be such a desirable solution.