<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Great Endeavours Beginning</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/" />
    <link rel="self" type="application/atom+xml" href="http://www.bennett.f2s.com/great_endeavours_beginning/atom.xml" />
    <id>tag:www.bennett.f2s.com,2008-02-26:/great_endeavours_beginning//5</id>
    <updated>2008-04-04T11:34:10Z</updated>
    <subtitle>Thoughts on the technical side of starting a new business</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Open Source 4.1</generator>

<entry>
    <title>PHP RSS Parsers</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/04/php-rss-parsers.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.29</id>

    <published>2008-04-04T11:09:47Z</published>
    <updated>2008-04-04T11:34:10Z</updated>

    <summary>So, the next thing to build in my site is an RSS parser. I&apos;m uploading video files to a hosting provider, who generates their own unique ID for each video. However, when users browse my site they want to play...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rss" label="rss" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[So, the next thing to build in my site is an RSS parser. I'm uploading video files to a hosting provider, who generates their own unique ID for each video. However, when users browse my site they want to play these videos, which means that I need to know the hosting provider's ID for the video the user wants to watch.<br /><br />My video host provides an RSS feed of my uploaded content, which includes their IDs. So I need a scheduled task which will poll this feed and parse it so the IDs can be written back to my database.<br /><br />The first try was using <a href="http://magpierss.sourceforge.net/">Magpie RSS</a>, which took about 10 minutes to download, install, and get working. <br /><br /><pre>require_once 'rss_fetch.inc';<br />$url = 'http://myprovider.com/feed.rss';<br />$rss = fetch_rss($url);</pre>$rss is now a structured array containing all the data from the provider's RSS feed, and can be accessed like any other array:<br /><pre>print "Channel: ".$rss-&gt;channel['title'];<br /><br /></pre>The big drawback is that the array only contains the data from the XML elements in the feed - it doesn't include the attributes. My provider's feed conforms to <a href="http://search.yahoo.com/mrss">Yahoo's Media RSS specification</a>, which includes a &lt;media:thumbnail&gt; element where all the thumbnail information is held in attributes:<br /><pre>&lt;media:thumbnail url="http://www.foo.com/keyframe.jpg" width="75" height="50" time="12:05:01.123" /&gt;</pre><br />So the next candidate was <a href="http://simplepie.org/">Simple Pie</a>. This proved to be much more flexible and capable, but a bit more complex to get up and running, but got there in the end:<br /><pre>require_once('simplepie.inc');<br />$rss = new SimplePie();<br />$rss-&gt;set_feed_url('http://myprovider.com/feed.rss');<br />$rss-&gt;enable_cache(false);<br />$rss-&gt;init();<br /><br />foreach ($rss-&gt;get_items() as $item) {<br />&nbsp; $user_data = $item-&gt;get_item_tags('http://myprovider.com/WebService/userdata/0.1/', 'id');<br />&nbsp; $video_id = $user_data[0]['data'];<br /><br />&nbsp; $thumbnail = $item-&gt;get_item_tags('http://search.yahoo.com/mrss/', 'thumbnail');<br />&nbsp; $thumbnail_url = $thumbnail[0]['attribs']['']['url'];<br />}</pre><br />]]>
        
    </content>
</entry>

<entry>
    <title>What tokens are available in Drupal?</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/03/what-tokens-are-available-in-d.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.28</id>

    <published>2008-03-31T08:41:14Z</published>
    <updated>2008-03-31T09:21:42Z</updated>

    <summary>Drupal has a very powerful module called Tokens, which makes various pieces of data available in other modules. As an example, the Pathauto module will create friendly URLs for any piece of content based on some feature of that content,...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Development Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="pathauto" label="pathauto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tokens" label="tokens" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="usermanagement" label="user management" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[Drupal has a very powerful module called <a href="http://drupal.org/project/token">Tokens</a>, which makes various pieces of data available in other modules. As an example, the <a href="http://drupal.org/project/pathauto">Pathauto</a> module will create friendly URLs for any piece of content based on some feature of that content, using token substitution. By default, a new piece of content will be available at the URL <span class="code">http://www.mysite.com/node/5</span> (assuming you have enabled clean URLs). However, you can create a pathauto rule which creates an alias to make that content available at <span class="code">http://www.mysite.com/reviews/run_fatboy_run</span> - much more SEO-friendly.<br /><br />This pathauto rule looks like this:<br /><span class="code">reviews/[title-raw]</span><br /><br />So far, so good. However, what happens when you want to use some feature of the content other than the title? What other data is available?<br /><br />It turns out this is pretty easy, once you know where to look. In the <span class="code">modules/token</span> directory is an include file for each module which exposes tokens. I wanted to use the user name as a token, so checked in <span class="code">token_user.inc</span>, and found<br /><div class="code">$values['user-raw'] = $account-&gt;uid ? $account-&gt;name : variable_get('anonymous', 'Anonymous');</div><br /><br />so I've now created a pathauto rule on user account page paths of<br /><span class="code">users/[user-raw]</span><br />so every user gets a nice URL to their account page, like <span class="code">http://www.mysite.com/users/bob</span><br /><br />Incidentally, the token_user.inc file also includes a bunch of help text in the overridden hook_token_list function, so it looks as though there is support for displaying this information somewhere in the Drupal admin interface. I can't find it anywhere though, and can't find any documentation around it (other than in the API.txt file to say "This function is used to provide help and inline documentation for all of the possible replacement tokens.", but no clue as to where this help and inline documentation may be). All answers on a postcard please...<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Importing Data Into Drupal CCK</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/03/importing-data-into-drupal-cck.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.27</id>

    <published>2008-03-20T14:46:42Z</published>
    <updated>2008-03-25T09:14:01Z</updated>

    <summary>I&apos;ve now got a bunch of structured data in a relational database, and need to get it into Drupal. I&apos;ve created my content types using CCK. Fortunately, there&apos;s a great overview here which highlights some of the core Drupal tables...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Development Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cck" label="cck" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[<p>I've now got a bunch of structured data in a relational database, and need to get it into Drupal. I've created my content types using CCK. Fortunately, there's a great overview <a href="http://drupal.org/node/133705">here</a> which highlights some of the core Drupal tables I need to populate which aren't immediately apparent.<br /><br />Everything is pretty straightforward, apart from populating deltas for repeating fields in CCK.<br /><br />An example will help here.<br /><br />Suppose I have a content type of person, who can have multiple phone numbers. CCK lets me add a field of type text, which is defined as a repeating field. To the end user, this looks as though you can simply enter as many phone numbers as you like for this person.<br /><br />In the database, CCK creates a table called content_type_person, which holds simple fields (i.e. fields where there can only be one value - things like first name, surname). It also creates a separate table for repeating fields, so phone numbers will be stored in content_field_contact_telephone. This new table is keyed on vid and nid (i.e. the current version of the node this person belongs to), and delta. Delta is a zero-based autoincrementing field, which increments for each new value for this nid.</p>Again, an example will help.<br /><br />I create a new person, which is internally given nid 1 and vid 1, and added to content-type-person. If I add three phone numbers, these are added to content_field_telephone with nid and vid of 1, and deltas of 0, 1 and 2. A second person with nid 2 would get deltas 0, 1 and 2 again:<br /><br />
<table><tbody><tr>
<th>nid&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>vid&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>delta&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>phone</th></tr>
<tr><td>1</td><td>1</td><td>0</td><td>01234 567890</td></tr>
<tr><td>1</td><td>1</td><td>1</td><td>01234 567891</td></tr>
<tr><td>1</td><td>1</td><td>2</td><td>01234 567892</td></tr>
<tr><td>2</td><td>2</td><td>0</td><td>01234 567893</td></tr>
<tr><td>2</td><td>2</td><td>1</td><td>01234 567894</td></tr>
<tr><td>2</td><td>2</td><td>2</td><td>01234 567895</td></tr>
</tbody></table>
<br /><br />
I've got hundreds of people, and several phone numbers for each. I can create the content node OK and get the right nid and vid, but how do I then insert all these into the database, and get nice zero-based incrementing delta values?<br /><br />]]>
        <![CDATA[
The obvious answer (coming from a procedural programmer's perspective) is to write a cursor. However, I have an instinctive dislike of cursors, and felt that there must be a better set-based alternative. And there is - MySQL 5.02 introduced <a href="http://dev.mysql.com/doc/refman/5.0/en/triggers.html">triggers</a>, and this is the key.<br /><br />Some experimentation and testing led to this trigger on the content_field_contact_telephone table:<br /><font face="courier">delimiter |<br />create trigger generate_deltas before insert on content_field_contact_telephone<br />for each row begin<br />&nbsp;&nbsp;&nbsp; set new.delta = (select max(delta)+1 from content_field_contact_telephone where vid = new.vid);<br />end;<br />|</font><br /><br />Bingo! Specify your insert values for nid, vid and phone, and you get nice neat auto-incremented delta values for each nid/vid. Just remember to take the trigger off again once you've finished bulk loading - I'm not sure what impact this would have on the main CCK content handling, but I suspect it wouldn't be pleasant! Even better, load this data into a staging table to generate the deltas, check them over, and then transfer them to your main Drupal tables.<br /> ]]>
    </content>
</entry>

<entry>
    <title>Drupal Tutorials</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/03/drupal-tutorials.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.26</id>

    <published>2008-03-19T09:38:01Z</published>
    <updated>2008-03-19T09:40:34Z</updated>

    <summary>I&apos;m starting to get the hang of Drupal now, largely thanks to Robert Safuto&apos;s video tutorials (especially the one about CCK and Views) - nice one Robert!...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Development Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tutorial" label="tutorial" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[I'm starting to get the hang of Drupal now, largely thanks to <a href="http://learn.awakenedvoice.com/">Robert Safuto's video tutorials</a> (especially the one about <a href="http://learn.awakenedvoice.com/2007/07/30/drupal-cck-and-views-tutorial/">CCK and Views</a>) - nice one Robert! ]]>
        
    </content>
</entry>

<entry>
    <title>Getting started with Drupal</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/03/getting-started-with-drupal.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.25</id>

    <published>2008-03-12T20:20:45Z</published>
    <updated>2008-03-12T22:19:25Z</updated>

    <summary>A few weeks ago, I decided that the best foundation for the site I&apos;m working on would be Drupal. After some discussions around the scale of the site and the likely complexity of our customisations, this seemed to be the...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Development Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="architecture" label="architecture" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="oscommerce" label="oscommerce" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[A few weeks ago, I decided that the best foundation for the site I'm working on would be <a href="http://drupal.org/">Drupal</a>. After some discussions around the scale of the site and the likely complexity of our customisations, this seemed to be the natural choice. One of the key factors in this decision was the perceived <a href="http://cmsreport.com/node/543">strength of Drupal's architecture</a>. As a fairly seasoned developer, I want an architecture which enables me to customise existing functionality and develop new functionality in a consistent and predictable way, with consistent and predictable results.<br /><br />My last project used <a href="http://www.oscommerce.com/">OSCommerce</a> as a foundation, and while I've been able to build a good (if fairly simple) e-commerce site with it, the architecture is somewhat inconsistent. Different parts of the system have varying coding styles and variable naming conventions (which isn't surprising, given it's open source roots), meaning that I have to adopt different coding styles and mindsets when debugging or enhancing different parts. Not insurmountable, but not a good foundation for great endeavours.<br /><br />The other key reasons for choosing Drupal were<br /><ul><li>product maturity</li><li>rich third party module library</li><li>very active developer community, including conferences</li><li>large-scale implementations (like <a href="http://www.mtv.co.uk/">MTV UK</a>)</li><li>open source (i.e. debuggable, extensible, customisable and free!)<br /></li></ul>So today I've been getting into the nuts and bolts of it. In our sprint planning, we've included some basic user profile functionality, as I thought this would be a good place to introduce myself to the Drupal architecture. Wrong, wrong, and wrong.<br /><br />One of our requirements is to support multiple user types, each of which will have different attributes. A good analogy (although not an actual example) would be to have<br /><ul><li>car drivers (who might want to add their car make and model to their profile)</li><li>mechanics (who might want to add specialisms such as engine tuning to their profile)</li></ul>The core Drupal profile module doesn't support this, but a quick run through the modules list reveals <a href="http://drupal.org/project/advanced_profile">Advanced Profile</a>, which does. However<br /><ul><li>Advanced Profile requires Panels, CCK and Node Profile</li><li>Node Profile requires Node Family and Subforms</li></ul>Although it's all pretty easy to install and configure, I'm now trying to get my head around what each of these modules brings to the party, and I suspect this is making my supposed "gentle introduction" more difficult than it really needs to be. Still, I'm sure it will start to make sense tomorrow.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Connecting C# to MySQL</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/03/connecting-c-to-mysql.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.23</id>

    <published>2008-03-01T20:37:12Z</published>
    <updated>2008-03-24T21:36:46Z</updated>

    <summary>My previous lives have left me pretty handy with C#. I only really used .net 1.1 for serious heavy lifting, so I&apos;m finding all kinds of nice suprises (like generics - strongly typed ArrayLists at last!) in .net 3.5 now...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Development Tools" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="c" label="C#" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[My previous lives have left me pretty handy with C#. I only really used .net 1.1 for serious heavy lifting, so I'm finding all kinds of nice suprises (like <a href="http://www.knowdotnet.com/articles/generics101.html">generics</a> - strongly typed ArrayLists at last!) in .net 3.5 now that I've started using Visual Studio 2008 (and finding that the free Express Edition is <a href="http://www.microsoft.com/express/support/faq/default.aspx">fine for commercial development</a> came as a rather nice suprise too!).<br /><br />One of the big down sides with the whole Microsoft ecosystem is the cost of getting off the ground, so as a startup we are going down a pretty standard open source tool route (i.e. LAMP servers). However, we have some fairly sophisticated spidering to be done to get structured data from a fairly large number of web sites of widely varying quality, so in the interests of getting up and running quickly, I've developed the spider in C# (with a fairly massive leg-up from <a href="http://www.jeffheaton.com/source">Jeff Heaton</a> - thanks Jeff!). I need to get the spidered data back into MySQL so that our other applications can use it, which brings me to today's problem.<br /><br />]]>
        <![CDATA[About five years ago I dabbled with MySQL (although in our very pro-Microsoft environment it had to be kept pretty quiet!), and connecting C# apps to it. It was all rather painful - lots of hacking to get things to work, followed by pretty poor performance when it did work. One of the great things about the open source movement though is the pace of change. All it takes now is installing the <a href="http://dev.mysql.com/downloads/connector/net/5.1.html">connector</a>, and away you go:<br /><br /><font face="Courier">using MySql.Data.MySqlClient;<br />...<br />...<br />MySqlConnection conn = new MySqlConnection(builder.ConnectionString);<br />conn.Open();<br />MySqlCommand cmd = new MySqlCommand("select description from products", conn);<br />MySqlDataReader reader = cmd.ExecuteReader();<br />while (reader.Read())<br />{<br />&nbsp;&nbsp;&nbsp; MessageBox.Show("Product description: " + reader.GetString("description"));<br />}<br /><br />reader.Close();<br />conn.Close();</font><br /><br />The only other complication was enabling remote connections to the MySQL server, which (thanks to <a href="http://www.cyberciti.biz/tips/how-do-i-enable-remote-access-to-mysql-database-server.html">a little help</a>) turned out to be as simple as changing /etc/mysql/my.cnf from<br /><br /><font face="Courier">bind-address = 127.0.0.1</font><br />to the actual IP address of the server:<br /><font face="Courier">bind-address = 192.168.187.128</font><br /><br />And away we go!<br /><br /><br /> ]]>
    </content>
</entry>

<entry>
    <title>Sprint 1</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/02/sprint-1.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.24</id>

    <published>2008-02-29T21:10:19Z</published>
    <updated>2008-03-01T21:37:58Z</updated>

    <summary>Let the sprints begin!We&apos;ve had our first sprint planning session, and it&apos;s gone pretty well. Over the past few weeks we have come up with an initial product backlog, and I&apos;ve estimated all the stories using story points. The only...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Scrum/Agile" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="scrum" label="scrum" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="whiteboard" label="whiteboard" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[Let the sprints begin!<br /><br />We've had our first sprint planning session, and it's gone pretty well. Over the past few weeks we have come up with an initial product backlog, and I've estimated all the stories using <a href="http://edgibbs.com/2006/03/11/story-points-estimating/">story points</a>. The only snag is there are over 200 stories! Still, we managed to pick out five to develop and test in the first sprint. We're starting off with two week sprints, and we'll see in the <a href="http://www.scrumforteamsystem.com/processguidance/v2/Process/SprintRetrospective.aspx">retrospectives</a> how well that works out. I'll be trying various ways of presenting stuff on the <a href="http://kw-agiledevelopment.blogspot.com/2007/10/how-to-implement-scrum-in-10-easy-steps_16.html">project whiteboard</a>, and I will post here how well each one works for us.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Let the endeavours begin...</title>
    <link rel="alternate" type="text/html" href="http://www.bennett.f2s.com/great_endeavours_beginning/2008/02/lorem-ipsum.html" />
    <id>tag:www.bennett.f2s.com,2008:/great_endeavours_beginning//5.22</id>

    <published>2008-02-27T11:08:03Z</published>
    <updated>2008-03-01T21:08:34Z</updated>

    <summary>So, day one dawns. I&apos;ve left the heady world of corporate software development, and begun the startup adventure!In this blog I&apos;ll be writing about the whole process of getting a new site developed and launched. I&apos;ll be looking in some...</summary>
    <author>
        <name>MarkB</name>
        <uri>www.bennett.f2s.com</uri>
    </author>
    
        <category term="Scrum/Agile" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="scrum" label="scrum" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.bennett.f2s.com/great_endeavours_beginning/">
        <![CDATA[So, day one dawns. I've left the heady world of corporate software development, and begun the startup adventure!<br /><br />In this blog I'll be writing about the whole process of getting a new site developed and launched. I'll be looking in some depth at all kinds of different tools to do what we need, and writing a fair bit about managing the software development process too. I'll be using Scrum to keep my business partner's creativity in check, and it will be interesting to see how well that works - my last corporate project was something of a Scrum disaster, but I think it can work much better in the startup environment. Time will tell!<br />]]>
        
    </content>
</entry>

</feed>
