<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Marcus Povey &#187; #ue</title>
	<atom:link href="http://www.marcus-povey.co.uk/tag/ue/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.marcus-povey.co.uk</link>
	<description>Making the world a better place, one byte at a time...</description>
	<lastBuildDate>Fri, 16 Jul 2010 09:00:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
	<atom:link rel='hub' href='http://www.marcus-povey.co.uk/?pushpress=hub'/>
		<item>
		<title>Multiple site support with MP&#8217;s Multisite Elgg</title>
		<link>http://www.marcus-povey.co.uk/2010/04/19/multiple-site-support-elgg/</link>
		<comments>http://www.marcus-povey.co.uk/2010/04/19/multiple-site-support-elgg/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 08:04:38 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[elgg-multisite]]></category>
		<category><![CDATA[elggmulti]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[mp-multisite-elgg]]></category>
		<category><![CDATA[multisite]]></category>
		<category><![CDATA[ning]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=508</guid>
		<description><![CDATA[I have just Open Sourced an &#8220;itch scratching&#8221; project I&#8217;ve been hacking on for a little while. So, without much further ado, I&#8217;d like to introduce you to Marcus Povey&#8217;s Multisite Elgg! It is currently in Beta and the code could do with a bit of a tidy, but this is Open Source so roll [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.marcus-povey.co.uk/wp-content/elgg-com-logo.gif" alt="" width="150" align="right" />I have just <a href="http://en.wikipedia.org/wiki/Open_source">Open Sourced</a> an &#8220;itch scratching&#8221; project I&#8217;ve been hacking on for a little while. So, without much further ado, I&#8217;d like to introduce you to <a href="http://code.google.com/p/mp-multisite-elgg">Marcus Povey&#8217;s Multisite Elgg</a>!</p>
<p>It is currently in Beta and the code could do with a bit of a tidy, but this is <a href="http://en.wikipedia.org/wiki/Open_source">Open Source</a> so roll up your sleeves and get involved.</p>
<p><strong>What is it?</strong><br />
<a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a> allows you to run multiple separate <a href="http://www.elgg.org">Elgg</a> sites off of the same install of the codebase, saving disk space and making administration a whole bunch easier.</p>
<p>Currently based around the latest Elgg 1.7 release, once installed adding new <a href="http://www.elgg.org">Elgg</a> sites is a matter of clicking on a button and entering in some details.</p>
<p><strong>What can I do with it?</strong><br />
You can do everything that you can do with Elgg, but with the ability to create new networks on demand. This will for example let you:</p>
<ul>
<li>Set up your own version of <a href="http://www.ning.com/">Ning</a>! What with <a href="http://tech.blorge.com/Structure:%20/2010/04/16/ning-cuts-free-accounts-and-40-percent-of-staff/">Ning phasing out free accounts</a>, it is my hope that <a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a> will let a thousand more Nings bloom!</li>
<li>In your organisation or institution, easily set up Elgg sites for each department.</li>
<li>If your one of the Elgg hosting companies out there, you may want to look at multisite in order to simplify your work flow.</li>
<li>&#8230; etc&#8230;</li>
</ul>
<p><strong>Installation</strong><br />
Once you have downloaded the installation package you will need to do a few things in order to get up and running. <a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a> assumes that you have some knowledge of how to set up and run a server &#8211; there is no wizard just yet!</p>
<ol>
<li>﻿﻿﻿<strong>Unzip the package on your web server.</strong></li>
<li><strong>Point your master domain at the contents of the install location on your web server</strong>. This is your master control domain, go here to configure your sites. Because of this you might want to consider putting this behind some further access restrictions.</li>
<li><strong>Point any sub domains to the contents of the docroot folder</strong>, eg (/var/multisite/docroot). This directory forms the base of all your Elgg installs. To make things even more automated you may want to consider making this an <a href="http://ma.tt/2003/10/wildcard-dns-and-sub-domains/">Apache wildcard domain</a>, if your DNS provider supports it.</li>
<li><strong>Chmod 777 docroot/data:</strong> This is the default location for multisite domains.</li>
<li><strong>Install schema/multisite_mysql.sql: </strong><a href="http://www.ntchosting.com/mysql/create-database.html">Create a new database on your Mysql server</a> and install the <a href="http://code.google.com/p/mp-multisite-elgg">Multisite</a> schema &#8211; this is your master control database.</li>
<li><strong>Rename settings.example.php in docroot/elgg/engine/ to settings.php and configure:</strong><br />
<blockquote><p>$CONFIG-&gt;multisite-&gt;dbuser = &#8216;your username&#8217;;<br />
$CONFIG-&gt;multisite-&gt;dbpass = &#8216;password&#8217;;<br />
$CONFIG-&gt;multisite-&gt;dbhost = &#8216;host&#8217;;</p></blockquote>
<p>Make sure this user has sufficient privileges to create and grant access to databases and tables on your server. This will allow the admin tool to create the databases for your hosted sites automatically.</li>
<li><strong>Visit your master domain and configure your admin user</strong></li>
<li><strong>Begin configuring your sites!</strong></li>
</ol>
<p><strong>Creating sites</strong><br />
Once you have created an admin user, adding sites is easy. Currently you can only create one type of site, but in the future <a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a> will let you create sites which have quotas and other access restrictions.</p>
<p>You have a box to enter database details, or you can leave them blank to use <a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a> user defined above (which you may not want to do for security reasons).</p>
<p>You can also select which of the installed plugins you want to allow, this lets have different sites have different plugins available while still installing them on the same codebase.</p>
<p><strong>Contributing</strong><br />
So, that was a brief introduction to <a href="http://code.google.com/p/mp-multisite-elgg">Multisite Elgg</a>. I hope that at least some of you out there find it useful!</p>
<p>As I said before, it&#8217;s <a href="http://en.wikipedia.org/wiki/Open_source">Open Source</a>, so if you want to get involved here are the important details:</p>
<ul>
<li><strong>Project homepage: </strong><a href="http://code.google.com/p/mp-multisite-elgg">http://code.google.com/p/mp-multisite-elgg</a></li>
<li><strong>Bug Tracker: </strong><a href="http://code.google.com/p/mp-multisite-elgg/issues/list">http://code.google.com/p/mp-multisite-elgg/issues/list</a></li>
<li><strong>Code Repository: </strong>svn checkout http://mp-multisite-elgg.googlecode.com/svn/trunk/ mp-multisite-elgg-read-only</li>
<li><strong>Discussion forum:</strong> <a href="http://groups.google.com/group/mp-multisite-elgg">http://groups.google.com/group/mp-multisite-elgg</a></li>
<li><strong><a href="http://mp-multisite-elgg.googlecode.com/files/multisiteelgg-1.7beta.zip">Direct download!</a></strong></li>
</ul>
<p>If you want to contribute patches, feel free to use the bug tracker or discussion forum!</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2010/04/19/multiple-site-support-elgg/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Akismet plugin for Elgg</title>
		<link>http://www.marcus-povey.co.uk/2010/01/18/akismet-plugin-for-elgg/</link>
		<comments>http://www.marcus-povey.co.uk/2010/01/18/akismet-plugin-for-elgg/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 09:59:36 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[akismet]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=387</guid>
		<description><![CDATA[I have just written a very small Akismet plugin for Elgg. When enabled and configured, this plugin will scan newly submitted comments of the &#8216;generic_comment&#8217; annotation class. While spam comments are rarer on Elgg due to the fact that most sites don&#8217;t allow anonymous comments, this could be useful for people who are getting spam [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/david-trattnig/262091025/"><img src="http://farm1.static.flickr.com/82/262091025_9825a64b68_m.jpg" alt="" width="150" align="right" /></a></p>
<p>I have just written a very small <a href="http://community.elgg.org/pg/plugins/marcus/read/385700/akismet">Akismet plugin</a> for <a href="http://elgg.org">Elgg</a>.</p>
<p>When enabled and configured, this plugin will scan newly submitted comments of the &#8216;generic_comment&#8217; annotation class.</p>
<p>While spam comments are rarer on Elgg due to the fact that most sites don&#8217;t allow anonymous comments, this could be useful for people who are getting spam comments from people who have signed up.</p>
<p>This plugin comes into its own when you allow anonymous comments, such as on a site I recently built for a client.</p>
<p>Extending this plugin to scan other content should be fairly straight forward for even a novice coder, but if I have time I&#8217;ll provide an interface to do so.</p>
<p>Anyway, go <a href="http://community.elgg.org/pg/plugins/marcus/read/385700/akismet">get it here</a>, or check out the <a href="https://code.google.com/p/elgg-akismet/">project page</a> on google code!</p>
<p><small><strong><em>Image &#8220;<a href="http://www.flickr.com/photos/david-trattnig/262091025/">Spam! [don't buy]</a>&#8221; by <a href="http://www.flickr.com/photos/david-trattnig/">David Trattnig</a></em></strong></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2010/01/18/akismet-plugin-for-elgg/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Running Elgg on a MySQL cluster</title>
		<link>http://www.marcus-povey.co.uk/2009/09/21/running-elgg-on-a-mysql-cluster/</link>
		<comments>http://www.marcus-povey.co.uk/2009/09/21/running-elgg-on-a-mysql-cluster/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 19:01:49 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysql-proxy]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=308</guid>
		<description><![CDATA[I have recently been exploring some aspects of the Elgg scalability question by exploring how easy it would be to get the latest version of Elgg (1.6) running on a MySQL cluster. In this article I will document the process, but first I should point out: This is highly experimental and not endorsed in any [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/File:Us-nasa-columbia.jpg"><img src="http://upload.wikimedia.org/wikipedia/commons/3/3d/Us-nasa-columbia.jpg" alt="" width="200" align="right" /></a>I have recently been exploring some aspects of the <a href="http://www.marcus-povey.co.uk/2009/01/04/elgg-scalability/">Elgg scalability</a> question by exploring how easy it would be to get the latest version of <a href="http://elgg.org/getelgg.php?forward=elgg1.6.1.zip">Elgg (1.6)</a> running on a <a href="http://en.wikipedia.org/wiki/MySQL_Cluster">MySQL cluster</a>.</p>
<p>In this article I will document the process, but first I should point out:</p>
<ul>
<li>This is highly experimental and not endorsed in any way.</li>
<li>It is built against <a href="http://elgg.org/getelgg.php?forward=elgg1.6.1.zip">Elgg 1.6.1</a></li>
<li>This is not canonical and doesn&#8217;t reflect anything to do with the roadmap</li>
<li>This has not been extensively tested so <em>caveat emptor.</em></li>
</ul>
<h2>Setting up the cluster</h2>
<p>The first step is to set up the cluster on your equipment.</p>
<p>A MySQL cluster consists of a management node and several data nodes connected together by a network. Because I was running rather low on hardware, I cheated here and created each node as a <a href="http://www.virtualbox.org/">Virtual Box</a> image on my laptop &#8211; but the principle is the same.</p>
<p>Each node is an <a href="http://www.ubuntu.com/">Ubuntu</a> install (although you can use pretty much any OS) with two (virtual) network cards, one connected to the wider network (to install packages) and another on an internal network. If you do this for real you should consider removing the internet facing card once you&#8217;ve set everything up since a cluster isn&#8217;t secure enough to be run on the wider internet.</p>
<p>In my test configuration I had three nodes with name/internal IP as follows:</p>
<ul>
<li>HHCluster1/192.168.2.1 &#8211; Management node &amp; web server</li>
<li>HHCluster2/192.168.2.2 &#8211; First data node</li>
<li>HHCluster3/192.168.2.3 &#8211; Second data node</li>
</ul>
<p><strong>HHCluster1 &#8211; The management node</strong></p>
<p>Install mysql, apache etc. This should be a simple matter of apt-getting the relevant packages. Clustering (ndb) support is built into the version of mysql bundled with Ubuntu, but this may not be the case universally so check!</p>
<p>You need to create a file in /etc/mysql/ called <code>ndb_mgmd.cnf</code>, this should contain the following:</p>
<blockquote><p><code><br />
[NDBD DEFAULT]<br />
NoOfReplicas=2 # How many nodes you have<br />
DataMemory=80M    # How much memory to allocate for data storage (change for larger clusters)<br />
IndexMemory=18M   # How much memory to allocate for index storage (change for larger clusters)<br />
[MYSQLD DEFAULT]<br />
[NDB_MGMD DEFAULT]<br />
[TCP DEFAULT]</code></p>
<p><code>[NDB_MGMD]<br />
HostName=192.168.2.1 # IP address of this system</code></p>
<p><code># Now we describe each node on the system</code></p>
<p><code># First data node<br />
HostName=192.168.2.2<br />
DataDir=/var/lib/mysql-cluster<br />
BackupDataDir=/var/lib/mysql-cluster/backup<br />
DataMemory=512M<br />
[NDBD]<br />
# Second data node node<br />
HostName=192.168.2.3<br />
DataDir=/var/lib/mysql-cluster<br />
BackupDataDir=/var/lib/mysql-cluster/backup<br />
DataMemory=512M<br />
</code></p>
<p><code>#one [MYSQLD] per data storage node<br />
[MYSQLD]<br />
[MYSQLD]</code></p></blockquote>
<p><strong>Data nodes (HHCluster2 &amp; 3)</strong><br />
You must now configure your data nodes:</p>
<ol>
<li>Create the data directories, as root type:<br />
<blockquote><p><code>mkdir -p /var/lib/mysql-cluster/backup<br />
chown -R mysql:mysql /var/lib/mysql-cluster</code></p></blockquote>
</li>
<li>Edit your /etc/mysql/my.cnf and add the following to the [mysqld] section:<br />
<blockquote><p><code>ndbcluster<br />
# Replace the following with the IP address of your management server<br />
ndb-connectstring=192.168.2.1</code></p></blockquote>
</li>
<li>Again in /etc/mysql/my.cnf uncomment and edit the [MYSQL_CLUSTER] section so it contains the location of your management server:<br />
<blockquote><p><code>[MYSQL_CLUSTER]<br />
ndb-connectstring=192.168.2.1</code></p></blockquote>
</li>
<li>You need to create your database on each node (this is because clustering operates on a table level rather than a database level):<br />
<blockquote><p><code>CREATE DATABASE elggcluster;</code></p></blockquote>
</li>
</ol>
<p><strong>Starting the cluster</strong></p>
<ol>
<li>Start the management node:<br />
<blockquote><p><code>/etc/init.d/mysql-ndb-mgm start</code></p></blockquote>
</li>
<li>Start your data nodes:<br />
<blockquote><p><code>/etc/init.d/mysql restart<br />
/etc/init.d/mysql-ndb restart</code></p></blockquote>
</li>
</ol>
<p><strong>Verifying the cluster</strong><br />
You should now have the cluster up and running, you can verify this by logging into your management node and typing <code>show</code> in <code>ndb_mgm</code>.</p>
<p style="text-align: center;"><a href="http://www.marcus-povey.co.uk/wp-content/screenshot.png"><img class="aligncenter" src="http://www.marcus-povey.co.uk/wp-content/screenshot.png" border="0" alt="" width="400" /></a></p>
<p style="text-align: left;"><strong>A word on access&#8230;<br />
</strong></p>
<p style="text-align: left;">The cluster is now set up and will replicate tables (created with the ndbcluster engine &#8211; more on that later), but that is only useful to a point. Right now we don&#8217;t have a single endpoint to direct queries to, so this direction needs to be done at the application level.</p>
<p style="text-align: left;">We could take advantage of Elgg&#8217;s built in split read and writes, but this would only allow us to use a maximum of two nodes. A better solution would be to use a load balancer here such as <a href="http://www.ultramonkey.org/">Ultramonkey</a> to direct the query to the appropriate server allowing us to scale much further.</p>
<p style="text-align: left;">I didn&#8217;t really have time to get into this, so I am using the somewhat simpler <a href="http://forge.mysql.com/wiki/MySQL_Proxy">mysql-proxy</a>.</p>
<ol>
<li>On HHCluster1 install and run mysql-proxy:<br />
<blockquote><p><code>apt-get install mysql-proxy<br />
mysql-proxy --proxy-backend-addresses=192.168.2.2:3306 --proxy-backend-addresses=192.168.2.2:3306</code></p></blockquote>
</li>
<li>On your data nodes edit your /etc/mysql/my.cnf file. Find <code>bind-address</code> and change it&#8217;s IP to the node&#8217;s IP address. Also ensure that you have commented out any occurrence of <code>skip-networking.</code></li>
<li>Again on your client nodes, log in to mysql and grant access to your cluster table to a user on HHCluster1 &#8211; for example:<br />
<blockquote><p><code>GRANT ALL ON elggcluster.* TO `root`@`HHCluster1.local` IDENTIFIED BY '[some password]'</code></p></blockquote>
</li>
</ol>
<h2>Installing elgg</h2>
<p>Unfortunately as it stands, you need to make some code changes to the vanilla version of Elgg in order for it to work in a clustered environment. These changes are necessary because of the restrictions placed on us by the ndbcluster engine.</p>
<p>Two things in particular cause us problems &#8211; ndbcluster doesn&#8217;t support FULLTEXT indexes, and it also doesn&#8217;t support indexes over TEXT or BLOB fields.</p>
<p>FULLTEXT is for searching and is largely not used in the vanilla install of elgg, so I removed them. Equally, most indexes blobs one can live without, the exception being on the metastrings table.</p>
<p>Metastrings is accessed a lot, so the index is critical. Therefore I added an extra varchar field which we&#8217;ll modify the code to include the first 50 characters of the indexed text &#8211; this is equivalent to the existing index:</p>
<blockquote><p><code>CREATE TABLE `prefix_metastrings` (<br />
`id` int(11) NOT NULL auto_increment,<br />
`string` TEXT NOT NULL,<br />
<strong>`string_index` varchar(50) NOT NULL,</strong><br />
PRIMARY KEY (`id`),<br />
<strong>KEY `string_index` (`string_index`)</strong><br />
) ENGINE=ndbcluster DEFAULT CHARSET=utf8;</code></p></blockquote>
<p>And the modified query:</p>
<blockquote><p><code>$row = get_data_row("SELECT * from {$CONFIG-&gt;dbprefix}metastrings where string=$cs'$string' and string_index='$string_index' limit 1");</code></p></blockquote>
<p>Mysql&#8217;s optimiser checks the index first so this doesn&#8217;t lose a significant amount of efficiency (at least according to the explain command).</p>
<p>» <a href="http://www.marcus-povey.co.uk/wp-content/elgg-mysql-cluster.sql">Modified schema</a></p>
<p>The next problem is that the system log currently uses INSERT DELAYED to insert the log data. This is also not supported under the clustered engine.</p>
<p>There are a number of approaches we could take including using <a href="http://reference.elgg.org/database_8php.html#d03f827016fde8428fb40f3ee87aa887">Elgg&#8217;s delayed write functionality</a> or writing a plugin which replaces and logs to a different location.</p>
<p>For the purposes of this test I decided to just comment out the code in <a href="http://reference.elgg.org/system__log_8php.html#3ef1dd1a4a83c58012ad92ef2841b356">system_log()</a>.</p>
<p><strong>What won&#8217;t work</strong><br />
Currently there are a couple of core things that won&#8217;t work under these changes, here is a by no means complete summary:</p>
<ul>
<li>The system log (as previously described). This isn&#8217;t too much of a show stopper as the river code introduced in Elgg 1.5 no longer uses this.</li>
<li>The log rotate plugin as this attempts to copy the table into the archive engine type and we can&#8217;t guarantee which node it will be executed on in this scenario.</li>
<li>Any third party plugins which attempt to access the metastrings table directly (of which there should be none as direct table access is a big no no!)</li>
</ul>
<p>Anyway, here is a patch I made against the released version of 1.6.1 with all the code changes I made. Once you have applied this patch to your Elgg install you should be able to proceed with the normal Elgg install.</p>
<p>Let me know any feedback you may have!</p>
<p>» <a href="http://www.marcus-povey.co.uk/wp-content/ElggCluster1.6.1.patch">Elgg Clustering patch for Elgg 1.6.1</a></p>
<p><small><em>Top image &#8220;Birds-eye view of the 10,240-processor SGI Altix supercomputer housed at the NASA Advanced Supercomputing facility.&#8221;</em></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/09/21/running-elgg-on-a-mysql-cluster/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Geocoding Elgg entities</title>
		<link>http://www.marcus-povey.co.uk/2009/08/28/geocoding-elgg-entities/</link>
		<comments>http://www.marcus-povey.co.uk/2009/08/28/geocoding-elgg-entities/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 14:23:24 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[georss]]></category>
		<category><![CDATA[objects]]></category>
		<category><![CDATA[rss]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=280</guid>
		<description><![CDATA[Geotagging and GeoRSS support has been available in Elgg for a little while now, but like so many cool features of the platform, I haven&#8217;t really had the time to draw people&#8217;s attention to it. Although I am drawing your attention to it now, it should be noted that this is still somewhat under development! [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://georss.org/Main_Page"><img src="http://www.marcus-povey.co.uk/wp-content/georss_logo.png" alt="" align="right" /></a>Geotagging and <a href="http://georss.org/Main_Page">GeoRSS</a> support has been available in Elgg for a little while now, but like so many cool features of the platform, I haven&#8217;t really had the time to draw people&#8217;s attention to it.</p>
<p>Although I am drawing your attention to it now, it should be noted that this is still somewhat under development!</p>
<h2>Anatomy of a geocoder</h2>
<p>To begin geocoding your data you will need a geocoder. This is not something that Elgg comes installed with by default, <a href="http://community.elgg.org/pg/plugins/marcus/read/107702/google-maps-geocoder">although here&#8217;s one I coded earlier</a>.</p>
<p>This geocoder users the <a href="http://code.google.com/apis/maps/">Google maps API</a> to do the actual encoding, and provides two primary features.</p>
<ul>
<li>It handles the plugin hook &#8220;geocode&#8221;,&#8221;location&#8221;</li>
<li>It listens to all create events and attempts to tag it with the latitude and longitude &#8211; either from a -&gt;location metadata on the object itself, or from the user&#8217;s current -&gt;location &#8211; you could get more creative, this is a simple example.</li>
</ul>
<p>When you attempt to geocode a location you call the function <a href="http://reference.elgg.org/location_8php.html#3dfde0e2643efcff5feee626e098a368">elgg_geocode_location()</a>. This in turn triggers the above plugin hook and attempts to encode the data.</p>
<p>For efficiency once a location has been geocoded the result is cached. Future attempts to code the same location will return the result from the cache.</p>
<p>Once installed and configured, new content (wire posts etc) will be tagged with a latitude and longitude. Fill in your profile location field and try it out for yourself!</p>
<h2>Location based searches</h2>
<p>Once things are tagged with a location, you can start to use location as a starting point for searching by using some of the <a href="http://reference.elgg.org/location_8php-source.html">location aware search functions in location.php</a>.</p>
<p>This hasn&#8217;t currently been hooked up to the Elgg interface in any way, but that doesn&#8217;t stop you making use of it in your plugins.</p>
<h2>GeoRSS</h2>
<p>This is something you&#8217;ll be pleased to know that you get for free!</p>
<p>As you list your entities using the <a href="http://docs.elgg.org/wiki/Views#Listing_entities">Elgg listing tools</a> using the RSS view, if an entity has a position defined it will be included using standard geoRSS simple notation, i.e:</p>
<blockquote><p><code>&lt;georss:point&gt; 45.256 -71.92 &lt;/georss:point&gt;</code></p></blockquote>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/08/28/geocoding-elgg-entities/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using Elgg&#8217;s REST-like API</title>
		<link>http://www.marcus-povey.co.uk/2009/08/25/using-elggs-rest-like-api/</link>
		<comments>http://www.marcus-povey.co.uk/2009/08/25/using-elggs-rest-like-api/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 14:20:04 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[endpoint]]></category>
		<category><![CDATA[get]]></category>
		<category><![CDATA[handler]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[token]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=272</guid>
		<description><![CDATA[Another one of Elgg&#8216;s less documented but very powerful features is the ability to expose functionality from the core and user modules in a standard way via a REST like API. This gives you the opportunity to develop interoperable web services and provide them to the users of your site, all in a standardised way. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://xkcd.com/262/"><img title="in_ur_reality" src="http://www.marcus-povey.co.uk/wp-content/in_ur_reality.png" alt="in_ur_reality" width="200" align="right" /></a>Another one of <a href="http://www.elgg.org">Elgg</a>&#8216;s less documented but very powerful features is the ability to expose functionality from the core and user modules in a standard way via a REST like API.</p>
<p>This gives you the opportunity to develop interoperable web services and provide them to the users of your site, all in a standardised way.</p>
<h2>The endpoint</h2>
<p>To make an API call you must direct your query at a special URL. This query will be either a GET or a POST query (depending on the command you are executing), the specific endpoint you use depends on the format you want the return value returned in.</p>
<p>The endpoint:</p>
<blockquote><p><code>http://yoursite.com/pg/api/<strong>[protocol]</strong>/<strong>[return format]</strong>/</code></p></blockquote>
<p>Where:</p>
<ul>
<li><strong>[protocol]</strong> is the protocol being used, in this case and for the moment only &#8220;rest&#8221; is supported.</li>
<li><strong>[return format]</strong> is the format you want your information returned in, either &#8220;php&#8221;, &#8220;json&#8221; or &#8220;xml&#8221;.</li>
</ul>
<p>This endpoint should then be passed the method and any parameters as GET variables, so for example:</p>
<blockquote><p><code>http://yoursite.com/pg/api/rest/xml/?method=test.test&amp;myparam=foo&amp;anotherparam=bar</code></p></blockquote>
<p>Would pass &#8220;foo&#8221; and &#8220;bar&#8221; as the given named parameters to the function &#8220;test.test&#8221; and return the result in XML format.</p>
<p>Notice here also that the API uses the &#8220;PG&#8221; page handler extension, this means that it would be a relatively simple matter to add a new API protocol or replace the entire API subsystem in a module &#8211; should you be so inclined.</p>
<p><strong>Return result</strong></p>
<p>The result of the api call will be an entity encoded in your chosen format.</p>
<p>This entity will have a &#8220;status&#8221; parameter &#8211; zero for success, non-zero denotes an error. Result data will be in the &#8220;result&#8221; parameter. You may also receive some messages and debug information.</p>
<h2>Exporting a function</h2>
<p>Any Elgg function &#8211; core or module &#8211; can be exposed via the API, all you have to do is declare it using <code><a href="http://reference.elgg.org/api_8php.html#3ee7de907c28ff90ec8b7ffc52254484">expose_function()</a></code> from within your code, passing the method name, handler and any parameters (note that these parameters must be declared in the same order as they appear in your function).</p>
<p><strong>Listing functions</strong></p>
<p>You can see a list of all registered functions using the built in api command &#8220;system.api.list&#8221;, this is also a useful test to see if your client is configured correctly.</p>
<p>E.g.</p>
<blockquote><p><code>http://yoursite.com/pg/api/rest/xml/?method=system.api.list</code></p></blockquote>
<h2>Authorising and authenticating</h2>
<p>Most commands will require some form of authorisation in order to function. There are two main types of authorisation &#8211; protocol level which determines whether a given client is permitted to connect, and user level where a command whereby a user requires a special token in lieu of a username and password.</p>
<p><strong>Protocol level authentication</strong><br />
Protocol level authentication is a way to ensure that commands only come from approved clients for which you have previously given keys. This is in keeping with many web based API systems and permits you to disconnect clients who abuse your system, or track usage for accountancy purposes.</p>
<p>The client must send a <a href="http://en.wikipedia.org/wiki/HMAC">HMAC</a> signature together with a set of special HTTP headers when making a call. This ensures that the API call is being made from the stated client and that the data has not been tampered with.</p>
<p>Eagle-eyed readers with long memories will see a lot of similarity with the <a href="http://www.marcus-povey.co.uk/2008/02/21/getting-started-with-the-elggvoices-api-part-1-api-basics/">ElggVoices API</a> I wrote about previously.</p>
<p>The HMAC must be constructed over the following data:</p>
<ul>
<li>The Secret Key provided by the target Elgg install (as provided easily by the APIAdmin plugin).</li>
<li>The current unix time in microseconds as a floating point decimal, produced my microtime(true).</li>
<li>Your API key identifying you to the Elgg api server (companion to your secret key).</li>
<li>URLEncoded string representation of any GET variable parameters, eg &#8220;method=test.test&amp;foo=bar&#8221;</li>
<li>If you are sending post data, the hash of this data.</li>
</ul>
<p>Some extra information must be added to the HTTP header in order for this data to be correctly processed:</p>
<ul>
<li><strong>X-Elgg-apikey</strong> &#8211; The API key (not the secret key!)</li>
<li><strong>X-Elgg-time</strong> &#8211; Microtime used in the HMAC calculation</li>
<li><strong>X-Elgg-hmac</strong> &#8211; The HMAC as hex characters.</li>
<li><strong>X-Elgg-hmac-algo</strong> &#8211; The algorithm used in the HMAC calculation &#8211; eg, sha1, md5 etc</li>
</ul>
<p>If you are sending POST data you must also send:</p>
<ul>
<li><strong>X-Elgg-posthash</strong> &#8211; The hash of the POST data.</li>
<li><strong>X-Elgg-posthash-algo</strong> &#8211; The algorithm used to produce the POST data hash &#8211; eg, md5.</li>
<li><strong>Content-type</strong> &#8211; The content type of the data you are sending (if in doubt use <code>application/octet-stream</code>).</li>
<li><strong>Content-Length</strong> &#8211; The length in bytes of your POST data.</li>
</ul>
<p>Much of this will be handled for you if you use the <a href="http://reference.elgg.org/api_8php.html#8b98a982e4462bfa0c752e124bb98c0c">built in Elgg API Client</a>.</p>
<p><strong>User level tokens</strong></p>
<p>User level tokens are used to identify a specific user on the target system, in much the same way as if they were to log in with their user name and password, but without the need to send this for every API call.</p>
<p>Tokens are time limited, and so it will be necessary for your client to periodically refresh the token they use to identify the user.</p>
<p>Tokens are generated by using the API command &#8220;auth.gettoken&#8221; and passing the username and password as parameters, eg:</p>
<blockquote><p><code>http://yoursite.com/pg/api/rest/xml/?method=auth.gettoken&amp;username=foo&amp;password=bar</code></p></blockquote>
<p><strong>Anonymous methods</strong><br />
Anonymous methods (such as &#8220;system.api.list&#8221;) can be executed without any form of authentication, thus accepting connections from any client and regardless of whether they provide a user token. This is useful in certain situations and it goes without saying that you don&#8217;t expose sensitive functionality this way.</p>
<p>To do so set $anonymous=true in your call to expose_function().</p>
<p><small>Image “<a href="http://xkcd.com/262/">In UR Reality</a>” by <a href="http://www.xkcd.com">XKCD</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/08/25/using-elggs-rest-like-api/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The Export Interface</title>
		<link>http://www.marcus-povey.co.uk/2009/08/24/the-export-interface/</link>
		<comments>http://www.marcus-povey.co.uk/2009/08/24/the-export-interface/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 16:42:21 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[export]]></category>
		<category><![CDATA[interface]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=263</guid>
		<description><![CDATA[One of the more hidden features of Elgg is the Export interface. In a nutshell this interface provides an export view for Entities, Metadata, Annotations and relationships which can provide a convenient way of accessing data objects in a machine readable form. Endpoints The export url is constructed in different ways for entities, relationships and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.marcus-povey.co.uk/wp-content/elgg-com-logo.gif" alt="" width="180" align="right" />One of the more hidden features of Elgg is the Export interface.</p>
<p>In a nutshell this interface provides an export view for Entities, Metadata, Annotations and relationships which can provide a convenient way of accessing data objects in a machine readable form.</p>
<h2>Endpoints</h2>
<p>The export url is constructed in different ways for entities, relationships and metadata.</p>
<p>All endpoints begin with:</p>
<blockquote><p><code>http://yoursite.com/export/<strong>[VIEW]</strong>/</code></p></blockquote>
<p>Where [VIEW] is the format you want the data exported in &#8211; e.g. json, opendd, php or default.</p>
<p><strong>Entities</strong><br />
To export a GUID simply add it to the end:</p>
<blockquote><p><code>http://yoursite.com/export/<strong>[VIEW]</strong>/<strong>[GUID]</strong>/</code></p></blockquote>
<p><strong>Annotations &amp; Metadata</strong></p>
<p>Metadata and annotation can be exported by providing the type (&#8216;annotation&#8217; or &#8216;metadata&#8217;) and the appropriate ID.</p>
<blockquote><p><code>http://yoursite.com/export/<strong>[VIEW]</strong>/<strong>[GUID]</strong>/<strong>[annotation|metadata]</strong>/<strong>[annotation_id|metadata_id]</strong>/</code></p></blockquote>
<p><strong>Relationships</strong><br />
Follows the same format as above, but with <strong>[GUID]</strong> being the first guid in the relationship &#8211; in essence the entity to which the relationship &#8220;belongs&#8221;.</p>
<blockquote><p><code>http://yoursite.com/export/<strong>[VIEW]</strong>/<strong>[GUID]</strong>/relationship/<strong>[relationship_id]</strong>/</code></p></blockquote>
<h2>Security</h2>
<p>Some items of data (for example user passwords) are restricted from this export view. Exactly what is output by an output view is governed by <code>$object-&gt;getExportableValues();</code> which returns a list of exportable fields in the entity.</p>
<p>In addition, access permissions on the object are respected &#8211; meaning that if you can&#8217;t see an item in Elgg, you will not be able to see it in the export view either.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/08/24/the-export-interface/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Post processing Elgg views &#8211; Trac tags example</title>
		<link>http://www.marcus-povey.co.uk/2009/07/06/post-processing-elgg-views-trac-tags-example/</link>
		<comments>http://www.marcus-povey.co.uk/2009/07/06/post-processing-elgg-views-trac-tags-example/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 09:43:29 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugin hook]]></category>
		<category><![CDATA[post processing]]></category>
		<category><![CDATA[processing]]></category>
		<category><![CDATA[tags]]></category>
		<category><![CDATA[trac]]></category>
		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=232</guid>
		<description><![CDATA[There are a number of ways that an Elgg plugin developer can manipulate views via the powerful Elgg views system. Most Elgg programmers are by now familiar with extending or replacing existing views, or providing new views for new objects etc. But what if you just wanted to make a simple tweak to an existing [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://trac.edgewall.org"><img title="Trac_Logo_512x512" src="http://www.marcus-povey.co.uk/wp-content/Trac_Logo_512x512-150x150.png" alt="Trac_Logo_512x512" width="150" height="150" align="right" /></a>There are a number of ways that an Elgg plugin developer can manipulate views via the powerful <a href="http://docs.elgg.org/wiki/Views">Elgg views system</a>.</p>
<p>Most Elgg programmers are by now familiar with <a href="http://docs.elgg.org/wiki/Views#Extending_views">extending</a> or replacing existing views, or providing new views for new objects etc.</p>
<p>But what if you just wanted to make a simple tweak to an existing view &#8211; for example to replace all instances of rude words in a feed article, or to turn passive links into active ones?</p>
<p>Well, fortunately Elgg provides a post processing hook for views which can do just that.</p>
<p>After every view has been generated, the framework will trigger a <a href="http://docs.elgg.org/wiki/PluginHooks">plugin hook</a> called &#8220;&#8216;display&#8217;, &#8216;view&#8217;&#8221;. This hook is passed a parameter &#8216;view&#8217; which contains the name of the view being processed (eg. object/blog).</p>
<p>The contents of the view are passed in the <code>$returnvalue</code> variable which you can perform any processing on before returning it from the hook.</p>
<p>I have just uploaded a <a href="http://community.elgg.org/pg/plugins/marcus/read/168854/trac-tags">Trac tags plugin</a> to the <a href="http://community.elgg.org">Elgg community</a> site which provides a good example of this.</p>
<p>The Trac tags plugin is a tiny plugin which uses the views post processing hook to turn <a href="http://trac.edgewall.org">Trac</a> links (e.g. #xxxxx for tickets and [xxxxx] for changesets) into active links into your repository, and here&#8217;s how &#8211; first we register the hook:</p>
<blockquote><p><code>function tractags_init()<br />
{<br />
....<br />
// Register our post processing hook<br />
register_plugin_hook('display', 'view', 'tractags_rewrite');</code></p>
<p><code><br />
// define views we want to rewrite codes on (means we don't have to process *everything*)<br />
$CONFIG-&gt;tractags_views = array(<br />
'object/thewire',<br />
'object/blog'<br />
);</code></p>
<p><code> ....<br />
}</code></p></blockquote>
<p>Then in our handler looks something like this:</p>
<blockquote><p><code>function tractags_rewrite($hook, $entity_type, $returnvalue, $params)<br />
{<br />
global $CONFIG;</code></p>
<p><code>$view = $params['view'];</code></p>
<p><code>if (($view) &amp;&amp; (in_array($view, $CONFIG-&gt;tractags_views)))<br />
{<br />
// Search and replace ticket numbers<br />
$returnvalue =  preg_replace_callback('/(#)([0-9]+)/i',<br />
create_function(<br />
'$matches',<br />
'<br />
global $CONFIG;</code></p>
<p><code>return "&lt;a href=\"{$CONFIG-&gt;trac_baseurl}ticket/{$matches[2]}\"&gt;{$matches[0]}&lt;/a&gt;";<br />
'<br />
), $returnvalue);</code></p>
<p><code>// Search and replace changesets<br />
$returnvalue =  preg_replace_callback('/(\[)([0-9]+)(\])/i',<br />
create_function(<br />
'$matches',<br />
'<br />
global $CONFIG;</code></p>
<p><code>return "&lt;a href=\"{$CONFIG-&gt;trac_baseurl}changeset/{$matches[2]}\"&gt;{$matches[0]}&lt;/a&gt;";<br />
'<br />
), $returnvalue);</code></p>
<p><code>return $returnvalue;<br />
}<br />
}</code></p></blockquote>
<p>I&#8217;m sure you will be able to come up with some much more interesting uses!</p>
<p><small>Image from the <a href="http://trac.edgewall.org">Trac project</a>.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/07/06/post-processing-elgg-views-trac-tags-example/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Loosely coupled Elgg extensions (Captcha example)</title>
		<link>http://www.marcus-povey.co.uk/2009/06/15/loosely-coupled-elgg-extensions-captcha-example/</link>
		<comments>http://www.marcus-povey.co.uk/2009/06/15/loosely-coupled-elgg-extensions-captcha-example/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 16:41:07 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[actions]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[extend]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=206</guid>
		<description><![CDATA[One thing we try and do when working on a new Elgg feature is &#8211; where we can &#8211; couple things together as loosely as possible and provide hooks for third party developers to extend Elgg and fill in any blanks. A good example of where this has been done is the newly introduced Captcha [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://xkcd.com/233/"><img src="http://www.marcus-povey.co.uk/wp-content/a_new_captcha_approach.png" border="0" alt="A new CAPTCHA approach" width="300" align="right" /></a>One thing we try and do when working on a new Elgg feature is &#8211; where we can &#8211; <a href="http://en.wikipedia.org/wiki/Coupling_(computer_science)">couple things together as loosely as possible</a> and provide hooks for third party developers to extend Elgg and fill in any blanks.</p>
<p>A good example of where this has been done is the newly introduced <a href="http://en.wikipedia.org/wiki/Captcha">Captcha</a> functionality available in the latest <a href="http://www.elgg.org/download/nightly/">nightly testing builds of Elgg</a>.</p>
<p>The Captcha functionality is provided by a module which extends a view called &#8220;<a href="https://code.elgg.org/elgg/trunk/views/default/input/captcha.php">input/captcha</a>&#8220;. This view is blank by default but is used in several places such as user registration and the lost password form.</p>
<p>This means two things; firstly that if a Captcha module isn&#8217;t installed or enabled then forms behave normally, and secondly it becomes a trivial matter for third party modules to provide their own Captcha functionality.</p>
<p>This same mechanism is how the <a href="http://community.elgg.org/pg/plugins/marcus/read/142964/example-url-shortening-service-using-3lacc">URL shortener module</a> works by the way.</p>
<p>Next, the Captcha module <a href="http://www.marcus-povey.co.uk/2009/05/08/extendin-actions-in-elgg/">extends a number of actions</a> to require a correctly validated Captcha code. This list itself is the product of a <a href="http://docs.elgg.org/wiki/PluginHooks">plugin hook</a> which returns an array of actions which require Captcha validation:</p>
<blockquote><p><code>$actions = array();<br />
$actions = trigger_plugin_hook('actionlist', 'captcha', null, $actions);</code></p></blockquote>
<blockquote><p><code>...</code></p></blockquote>
<blockquote><p><code>function captcha_actionlist_hook($hook, $entity_type, $returnvalue, $params)<br />
{<br />
if (!is_array($returnvalue))<br />
$returnvalue = array();</code></p>
<p><code>$returnvalue[] = 'register';<br />
$returnvalue[] = 'user/requestnewpassword';</code></p>
<p><code>return $returnvalue;<br />
}</code></p></blockquote>
<p>The reason why the list of actions is provided this way is twofold, firstly it lets modules use Captcha functionality in their own code through a generic interface, and secondly it is harder to spoof than looking for some marker in the form code.</p>
<p>The Captcha itself injects a server generated token into the form, which together with the user&#8217;s response to the characters generated in an image are used to validate that the user is indeed human.</p>
<p>As we can see, Elgg asks to be provided with a Captcha if one is available by including a specific view, but is agnostic as to where (or indeed if) this functionality is supplied.</p>
<p>By using the techniques available to an Elgg programmer I was able to loosely couple the Captcha system to Elgg in such a way that a third party can easily use the same techniques to provide a more advanced module.</p>
<p>Happy coding!</p>
<p><small>Image &#8220;<a href="http://xkcd.com/233/">A new Captcha approach</a>&#8221; by <a href="http://www.xkcd.com">XKCD</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/06/15/loosely-coupled-elgg-extensions-captcha-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending actions in Elgg</title>
		<link>http://www.marcus-povey.co.uk/2009/05/08/extendin-actions-in-elgg/</link>
		<comments>http://www.marcus-povey.co.uk/2009/05/08/extendin-actions-in-elgg/#comments</comments>
		<pubDate>Fri, 08 May 2009 17:01:22 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[actions]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[extending]]></category>
		<category><![CDATA[overriding]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=188</guid>
		<description><![CDATA[Those eagle-eyed developers who have been tracking the Elgg core SVN may have noticed that I have recently committed a bunch of captcha related changes, including a simple captcha module. I just thought I&#8217;d write a quick post about it as this module makes use of a bit of Elgg functionality which has been around [...]]]></description>
			<content:encoded><![CDATA[<p>Those eagle-eyed developers who have been tracking the Elgg core SVN may have noticed that I have recently committed a bunch of <a href="http://en.wikipedia.org/wiki/Captcha">captcha</a> related changes, including a simple captcha module.</p>
<p>I just thought I&#8217;d write a quick post about it as this module makes use of a bit of Elgg functionality which has been around for a while, but that I know a number of plugin developers have missed.</p>
<p>Namely, the ability to extend actions.</p>
<p>When the Elgg framework calls an <a href="http://docs.elgg.org/wiki/Actions">action</a> the Action handler triggers a <a href="http://docs.elgg.org/wiki/PluginHooks">plugin hook</a> called &#8220;action&#8221; before executing the action itself. This hook looks like this:</p>
<blockquote><p><code>$event_result = true;<br />
$event_result = trigger_plugin_hook('action', $action, null, $event_result);</code></p></blockquote>
<p>Where <code>$action</code> is the action being called. If the hook returns false then the main action will not be executed.</p>
<p>The captcha module uses this to intercept the <code>register</code> and <code>user/requestnewpassword</code> actions and redirect them to a function which checks the captcha code. This check returns true if valid or false if not (which prevents the associated action from executing).</p>
<p>This is done as follows:</p>
<blockquote><p><code>register_plugin_hook("action", "register", "captcha_verify_action_hook");<br />
register_plugin_hook("action", "user/requestnewpassword", "captcha_verify_action_hook");</code></p>
<p><code>.<br />
.<br />
.</code></p>
<p><code>function captcha_verify_action_hook($hook, $entity_type, $returnvalue, $params)<br />
{<br />
$token = get_input('captcha_token');<br />
$input = get_input('captcha_input');</code></p>
<p><code> if (($token) &amp;&amp; (captcha_verify_captcha($input, $token)))<br />
return true;</code></p>
<p><code> register_error(elgg_echo('captcha:captchafail'));</code></p>
<p><code> return false;<br />
}<br />
</code></p></blockquote>
<p>As you can see, this lets a plugin extend an existing action without the need to replace the action itself. In the case of the captcha plugin it allows the plugin to provide captcha support in a very loosely coupled way.</p>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/05/08/extendin-actions-in-elgg/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Elgg scalability</title>
		<link>http://www.marcus-povey.co.uk/2009/01/04/elgg-scalability/</link>
		<comments>http://www.marcus-povey.co.uk/2009/01/04/elgg-scalability/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 13:01:22 +0000</pubDate>
		<dc:creator>Marcus Povey</dc:creator>
				<category><![CDATA[elgg]]></category>
		<category><![CDATA[#ue]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://www.marcus-povey.co.uk/?p=124</guid>
		<description><![CDATA[&#8220;I am creating an Elgg network and I am expecting 10 million users, can it cope?&#8221; This question gets asked in one form or another almos tevery week, but I believe this is the wrong question to be asking. Perhaps the more pertinent scalability question is: &#8220;I am creating an Elgg network, how do I [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>&#8220;I am creating an Elgg network and I am expecting 10 million users, can it cope?&#8221;</p></blockquote>
<p>This question gets asked in one form or another almos tevery week, but I believe this is the wrong question to be asking. Perhaps the more pertinent scalability question is:</p>
<blockquote><p>&#8220;I am creating an Elgg network, how do I attract 10 million users?&#8221;</p></blockquote>
<p>This is by far the hardest question to answer and it must be solved before you can seriously address the comparatively simple task of hardware and software scalability.</p>
<p>Attracting users can be accomplished in many ways but it is mainly a matter of marketing, and of course to have a killer idea. As Ben discussed in his presentation at the recent Elgg Conference, this idea must be as useful to user 1 as user 10 million.</p>
<p>The idea has to be solid from day one,  so forget all the trendy &#8220;long tail&#8221; and &#8220;wisdom of crowds&#8221; buzzwords!</p>
<p>Once you manage to solve this most tricky of problems, you can begin to look at the infrastructure. So, can Elgg handle 10 million users out of the box?</p>
<p>Simply, no script in the world can handle this level of usage straight away without some modification and a serious investment in both time and money. You will not be able to unpack Elgg on a cheap shared host and have it handle 10 million users.</p>
<p>This is not an issue with Elgg&#8217;s design (which actually lends itself to many scalability techniques), but simple realism. Elgg has had substantial work done on scalability and optimisation &#8211; reducing queries, caching etc &#8211; and currently performs very well page for page against competitors like Ning and Buddypress.</p>
<p>Asking how many users an Elgg install can support is also a pointless question, because the answer is always going to be <em>&#8220;it depends&#8221;</em>. How many users Elgg can support depends on your hardware, your host (shared or dedicated), your database server, how your users behave and how many of them are active at any given time.</p>
<p>So what should you pay attention to?</p>
<p>Elgg itself is fairly optimal, and will improve over time. If you are dealing with millions of user you will be wanting to look at your server infrastructure &#8211; database server, bandwidth, memory, caching at every level. After this you can look at customised code to squeeze out the last percentage points of performance.</p>
<p>If you are serious about handling high load there is no avoiding the need to spend some time and money investing in your infrastructure. But, these are good problems to have, because it means that you have a successful network!</p>
<p>So in conclusion, my answer to the scalability question is <em>&#8220;Don&#8217;t worry about it until you have to worry about it!&#8221;</em>, get your users in first. Make a killer service that is useful from day one, and then worry about how you will handle millions of concurrent users.</p>
<p>Scalability is a largely solved problem&#8230; building a successful service isn&#8217;t, and is the thing you should be concerned with.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.marcus-povey.co.uk/2009/01/04/elgg-scalability/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>
