<?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>Night Blue Fruit Development Blog &#187; PHP</title>
	<atom:link href="http://www.nightbluefruit.com/blog/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nightbluefruit.com/blog</link>
	<description>Sharing what we learn</description>
	<lastBuildDate>Thu, 17 Jun 2010 15:58:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The pain of Drupal</title>
		<link>http://www.nightbluefruit.com/blog/2009/12/the-pain-of-drupal/</link>
		<comments>http://www.nightbluefruit.com/blog/2009/12/the-pain-of-drupal/#comments</comments>
		<pubDate>Sat, 05 Dec 2009 11:14:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[The Internet]]></category>

		<guid isPermaLink="false">http://www.nightbluefruit.com/blog/?p=56</guid>
		<description><![CDATA[I&#8217;ve recently taken on a job that requires modification of a web site built on Drupal, and 3 days in, I feel like I need a 2 week holiday.
Drupal, and its counterpart, Joomla, are Open Source Content Management systems. The idea is that the allow people who don&#8217;t know anything about HTML, PHP, Javascript etc [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently taken on a job that requires modification of a web site built on Drupal, and 3 days in, I feel like I need a 2 week holiday.</p>
<p>Drupal, and its counterpart, Joomla, are Open Source Content Management systems. The idea is that the allow people who don&#8217;t know anything about HTML, PHP, Javascript etc etc to build complex, feature rich websites.</p>
<p>Their use on the web has exploded over recent years, as more and more would be &#8216;web designers&#8217; have started using them as their framework for building websites.</p>
<p>This in turn as led to the development of lots and lots of Drupal plugins and widgets, which add a futher layer of fudge and complexity to something that is already very fudgy and very complex.</p>
<p>Under the hood, its a morass.</p>
<p>Before starting work on the modifications I had to make, I took a look at the MySQL database on which is runs. It had <strong>288 </strong>tables (my own CMS has 12 tables, and even poor old Wordpress only has about 40 tables).</p>
<p>If that wasn&#8217;t bad enough, when I then tried to run a local copy of the website on my laptop, I started to get errors about PHP not having enough memory to run the Drupal scripts. PHP is normally allocated about 16MB of memory as part of its installation; to run Drupal, I had to up this to <strong>64MB!!</strong></p>
<p>Its gets worse. Looking at the raw HTML generated by Drupal, I saw that it was loading <strong>25 different CSS files, </strong>and <strong>14 different Javascript files!</strong> And when I examined the DOM via Firebug, I could see that certain elements were taking CSS properties from up to 4 different files!</p>
<p>All this was bad enough, but it was nothing comparred to actually using the management interface to build content. The admin menu in Drupal has 14 different options, and each of these has a plethora of sub options, all of which refer to vague concepts like Blocks, Views, Modules, Panels, Stories etc (they also refer to a Page, but its isn&#8217;t really clear what a Page is).</p>
<p>My first thought was that it would be actually easier to learn HTML, PHP and Javascript than try and unravel this crap.</p>
<p>I persevered anyway. I made a view changes to pages where I could figure how to make those changes, but none of them appeared on the actual website. This was most probably to do with caching I thought, but there was nothing in the Drupal interface that said &#8216;You should clear your cache to see these changes&#8217;. I also thought  it was quite odd that an app that generates links to 40 odd CSS and Javascript files should be worried about caching.</p>
<p>I looked around for somewhere I could clear the cache, but could find nothing. I eventually googled the subject and found that the clear cache was a sub sub option under the &#8216;Site Configuration&#8217; menu option.</p>
<p>On another occasion, I had to change some User Permissions. When I clicked on the Save button, my laptop started to grind to the extent that I thought it was going to shut itself down to prevent an explosion.</p>
<p>Perhaps my most stressful experience with Drupal was dealing with this <a href="http://drupal.org/node/284392" target="_blank">bug</a>. There are 300 posts on the Drupal Forum thread on this bug, and the upshot of it isn&#8217;t there isn&#8217;t a universal solution. You basically have to figure out what version of a few different modules you are using, and then apply a serious of patches which may or may not break other parts of your installation.</p>
<p>Lets try and use an analogy here.</p>
<p>Building a website with Joomla is like trying to build a house by joining together five or six mobile homes. Its cheap, it doesn&#8217;t take long to put together and it seems like a easy solution to a pressing problem.</p>
<p>What you get is something that is about the same size as a house, and that has certain features of house (eg windows and doors), but that also has 5 bathrooms, 5 kitchens, no corridors and no rooms of any useful size. You also need 5 different electricty meters, and in certain cases, if you want to walk from one room to another, you have to leave house and come in through another door.</p>
<p>Also, if you want to make even minor modifications to the look of your house  in future, you have to take the whole thing apart and stick it back together again.</p>
<p>Don&#8217;t get me wrong. Open source packages like Drupal are essential part of the Internet, but its becoming clear that the more an application tries to be a solution for everything, the more likely it is to become a solution for nothing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nightbluefruit.com/blog/2009/12/the-pain-of-drupal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refreshing an image when filename is the same</title>
		<link>http://www.nightbluefruit.com/blog/2007/09/refreshing-an-image-with-javascript/</link>
		<comments>http://www.nightbluefruit.com/blog/2007/09/refreshing-an-image-with-javascript/#comments</comments>
		<pubDate>Wed, 19 Sep 2007 22:48:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.nightbluefruit.com/blog/?p=8</guid>
		<description><![CDATA[Here&#8217;s a nifty little trick that might get you out of a bind:
Say you have a web app in which the user can change the images by uploading new image files. Say then that the application requires that the image filename remain the same. See the problem?
The image may have changed but your browser is [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a nifty little trick that might get you out of a bind:</p>
<p>Say you have a web app in which the user can change the images by uploading new image files. Say then that the application requires that the image filename remain the same. See the problem?</p>
<p>The image may have changed but your browser is still looking at the same filename, so it will display its cached image. Of course, you could try an edit your HTML to that caching doesn&#8217;t occur, but we like caching, so here&#8217;s a better solution.</p>
<p>An image file, like a script file, can accept an argument when requested with HTTP. For instance, the image below is requested so:</p>
<p>&lt;IMG src=/blog/wp-content/pottery-main.thumbnail.jpg?foo&gt;</p>
<p><img src="http://www.nightbluefruit.com/blog/wp-content/pottery-main.thumbnail.jpg?foo" alt="" /></p>
<p>The cool thing about this is that you attach random arguments to your image calls, either in HTML or in Javascript, which will cause the browser to reload that image every time it is called. Hence, when your user loads a new image, and this image has the same file name as the old image, this method will allow the user to view the new image without having to do a manual refresh.</p>
<p>In Javascript, you can create a random argument using time and date functions. e.g.</p>
<p>my_image.src=&#8221;images/pottery.jpg?&#8221; + (new Date()).getTime();</p>
<p>or</p>
<p>image_td.innerHTML = &#8220;&lt;IMG src=images/pottery.jpg?&#8221; + (new Date()).getTime() + &#8220;&lt;/IMG&gt;&#8221;;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nightbluefruit.com/blog/2007/09/refreshing-an-image-with-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managing images with GD</title>
		<link>http://www.nightbluefruit.com/blog/2007/09/managing-images-with-gd/</link>
		<comments>http://www.nightbluefruit.com/blog/2007/09/managing-images-with-gd/#comments</comments>
		<pubDate>Wed, 12 Sep 2007 22:18:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.nightbluefruit.com/blog/?p=5</guid>
		<description><![CDATA[One of the biggest problems I find with Content Management Systems is that while users are capable of managing web site text, the results are a little less predictable when it comes to managing images.
There are 2 primary problems:
Firstly, a lot of users aren&#8217;t comfortable with scaling images to fit into the spaces designed for [...]]]></description>
			<content:encoded><![CDATA[<p>One of the biggest problems I find with Content Management Systems is that while users are capable of managing web site text, the results are a little less predictable when it comes to managing images.</p>
<p>There are 2 primary problems:</p>
<p>Firstly, a lot of users aren&#8217;t comfortable with scaling images to fit into the spaces designed for them, and secondly, if you allow for this and use the IMG tag to scale the height and width of the image, you get fuzzy distorted images and large files that take an age to load in the browser.</p>
<p>This is why programatically manipulating uploaded images is such a good idea.</p>
<p>There are 2 tools you can use to manipulate images in PHP: GD or ImageMagick</p>
<p>GD is more commonly found in PHP compiles, and ImageMagick can be difficult to install correctly, so lets stick with GD for this discussion.</p>
<p>The problem I faced was this:</p>
<p>I wanted users to be able to upload long images, tall images and square images, but I wanted these to fit into a space 214px x 214px on a website page without having to use the IMG height and width tags.</p>
<p>This meant a 2 step process for the long and tall images: first, resize them so that they were with 214px tall or wide, and then crop them so that they were both 214px tall and 214px wide. I also wanted to make sure I was cropping down to the middle portion of the image, so that I was getting what the user wanted to appear and not the top, bottom or side of the image. The task for square images was a little simpler, in that I only had to resize the image (no cropping).</p>
<p>The PHP function I created is produced here. I&#8217;ve added inline comments to explain.</p>
<p>&lt;?php</p>
<p><strong>#Arguments = source image file, altered image file, required dimesions of altered image</strong></p>
<p>function resize_image($src_image,$dst_image,$xsize,$ysize)<br />
{</p>
<p>list($w,$h) = getimagesize($src_image);</p>
<p><strong>#Deals with images that are wider than they are tall</strong></p>
<p>if ($w &gt; $h) {</p>
<p><strong>#First, resize the image so that 1 side is the required length</strong><br />
$new_height = $ysize;<br />
$new_width = ($ysize / $h) * $w;</p>
<p>$x=$w;<br />
$y=$h;</p>
<p><strong>#Resized temp image</strong></p>
<p>$temp_image = &#8220;images/&#8221; . date(&#8221;U&#8221;) . &#8220;.jpg&#8221;;</p>
<p>$image = imagecreatefromjpeg($src_image);<br />
$crop = imagecreatetruecolor($new_width,$new_height);<br />
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);<br />
imagejpeg($crop,$temp_image,100);</p>
<p><strong># Now use temp image to create final image</strong></p>
<p>list($w,$h) = getimagesize($temp_image);</p>
<p>if ($h &gt;= $ysize) $new_height = $ysize;<br />
if ($h &lt;= $ysize) $new_height = $h;<br />
$new_width = $ysize;</p>
<p><strong>#This bit sets the dimensions for the middle of the image</strong><br />
$x = ($w &#8211; $ysize) / 2;<br />
$y = 0;</p>
<p>$image = imagecreatefromjpeg($temp_image);<br />
$crop = imagecreatetruecolor($new_width,$new_height);<br />
imagecopy ($crop, $image, 0, 0, $x, $y, $new_width, $new_height);</p>
<p><strong>#As above but for images that are taller than they are wide</strong></p>
<p>} elseif ($h &gt; $w) {</p>
<p>$new_width = $xsize;<br />
$new_height = ($xsize / $w) * $h;</p>
<p>$x=$w;<br />
$y=$h;</p>
<p>$temp_image = &#8220;images/shops/&#8221; . date(&#8221;U&#8221;) . &#8220;.jpg&#8221;;</p>
<p>$image = imagecreatefromjpeg($src_image);<br />
$crop = imagecreatetruecolor($new_width,$new_height);<br />
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);<br />
imagejpeg($crop,$temp_image,100);</p>
<p>list($w,$h) = getimagesize($temp_image);</p>
<p>if ($w &gt;= $xsize) $new_width = $xsize;<br />
if ($w &lt;= $xsize) $new_width = $w;<br />
$new_height = $xsize;<br />
$y = ($h &#8211; $xsize) / 2;<br />
$x = 0;</p>
<p>$image = imagecreatefromjpeg($temp_image);<br />
$crop = imagecreatetruecolor($new_width,$new_height);<br />
imagecopy ($crop, $image, 0, 0, $x, $y, $new_width, $new_height);</p>
<p><strong>#Square image; no need for cropping</strong><br />
} elseif ($h == $w) {</p>
<p>$new_width = $xsize;<br />
$new_height = $ysize;</p>
<p>$x=$w;<br />
$y=$h;</p>
<p>$image = imagecreatefromjpeg($src_image);<br />
$crop = imagecreatetruecolor($new_width,$new_height);<br />
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);</p>
<p>}</p>
<p><strong>#Save the new images and discard any temporary images</strong><br />
imagejpeg($crop,$dst_image,100);<br />
imagedestroy($image);<br />
}</p>
<p>?&gt;</p>
<p>Here&#8217;s an example:</p>
<p>This is the original image resized with IMG tags:</p>
<p><img src="http://www.nightbluefruit.com/blog/wp-content/pottery-main.jpg" alt="pottery-main.jpg" width="214" height="214" /></p>
<p>And here is the programatically manipulated image without any IMG tags:</p>
<p><img src="http://www.nightbluefruit.com/blog/wp-content/v1-53.jpg" alt="v1-53.jpg" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nightbluefruit.com/blog/2007/09/managing-images-with-gd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>phpBB Robotic Registrations</title>
		<link>http://www.nightbluefruit.com/blog/2007/08/phpbb-robotic-registrations/</link>
		<comments>http://www.nightbluefruit.com/blog/2007/08/phpbb-robotic-registrations/#comments</comments>
		<pubDate>Tue, 21 Aug 2007 21:10:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[The Internet]]></category>

		<guid isPermaLink="false">http://www.nightbluefruit.com/blog/?p=3</guid>
		<description><![CDATA[Preventing robots from posting on a phpBB forum is easy enough if your prospective users are content to wait for an administrator to moderate the registration, but that isn&#8217;t going to suit everybody.
Requiring moderation on the part of the administrator is also a pain for the administrator, who has to deal with the registration emails [...]]]></description>
			<content:encoded><![CDATA[<p>Preventing robots from posting on a phpBB forum is easy enough if your prospective users are content to wait for an administrator to moderate the registration, but that isn&#8217;t going to suit everybody.</p>
<p>Requiring moderation on the part of the administrator is also a pain for the administrator, who has to deal with the registration emails and decide who is real person and who is not.</p>
<p>I came across this problem for <a href="http://www.planningmatters.ie/pmbb" target="_blank">http://www.planningmatters.ie/pmbb</a></p>
<p>When you first become aware of the problem, your impulse reaction is to head off to Google for a tried and tested solution, but the problem is that once a solution gains any currency, the robot authors figure it out and you&#8217;re back to square one again.</p>
<p>My first solution was to edit the email that is sent to users awaiting activation, asking them to forward that email back to me to confirm they were a real person. I also set up a cron job to run an SQL script to delete non-activated users from the database,  deeming that any user who had not been activated 7 days after initial registration to be a robotic user.</p>
<p>This isn&#8217;t ideal in that it requires an extra step for users, but it does mean that real users get through, and that your database is kept in shape.</p>
<p>However, I was still getting floods of email from attempted robotic registrations, so I set about editing the registration script (includes/usercp_register.php).</p>
<p>This script processes registrations based on whether or not the user has agreed to the disclaimer on the primary registration page. I set an extra PHP $_GET  variable as part of the disclaimer agreement, and amended the later part of the script to check for that variable before processing the registration. I also set the extra variable equal to date(&#8221;DG&#8221;) which means that the variable changes every hour.  You can see this by examining the discliamer links here:</p>
<p><a href="http://www.planningmatters.ie/pmbb/profile.php?mode=register" target="_blank">http://www.planningmatters.ie/pmbb/profile.php?mode=register</a></p>
<p>The fact that the extra variable is not part of the standard phpBB install will ward off a lot of dumber robots, and the fact that it changes will ward off some smarter ones too. However, there are still a lot of robots out there that are clever enough to detect the verification method, so I was still getting some SPAM registrations.</p>
<p>To clear off the final few robots I knew I was going to have to involve the intellect of real users, in that this is probably the only thing that robots can&#8217;t replicate. Hence, I decided to add a really simple, but real, question to the registration page. To do this I edited the following file under the default template:</p>
<p>templates/subSilver/profile_add_body.tpl</p>
<p>I inserted the following extra lines of HTML underneath the Visual Confirmation section:</p>
<p>&lt;tr&gt;<br />
&lt;td class=&#8221;row1&#8243;&gt;&lt;span class=&#8221;gen&#8221;&gt;What is the day today?&lt;/span&gt;&lt;br /&gt;&lt;span class=&#8221;gensmall&#8221;&gt;We ask this question to prevent SPAM registrations. SPAM robots won&#8217;t know the answer.&lt;/span&gt;&lt;/td&gt;<br />
&lt;td class=&#8221;row2&#8243;&gt;&lt;input type=&#8221;text&#8221; class=&#8221;post&#8221; style=&#8221;width: 200px&#8221; name=&#8221;day_today&#8221; size=&#8221;6&#8243;  value=&#8221;" /&gt;&lt;/td&gt;<br />
&lt;/tr&gt;</p>
<p>This adds the following question to the registration form:</p>
<p>&#8220;What is the day today?&#8221;</p>
<p>The answer to which 99.999% of real users on the forum will know.</p>
<p>To check the answer, I then added an extra line to the top of the main registration script:</p>
<p>includes/usercp_register.php</p>
<p>The line I added is:</p>
<p>//ANTI-SPAM DEVICE<br />
if (isset($HTTP_POST_VARS['day_today']) and strtolower($HTTP_POST_VARS['day_today']) != strtolower(date(&#8221;l&#8221;))) die();</p>
<p>This basically ensures that the answer to the question is the same as the day produced by the date() function (case insensitive) and if its not, the script dies.</p>
<p>Previous to adding this, and even with the other changes, I was getting about 20 robot registrations per day. After adding this, it dropped to about 10 per day, so there was still some work to do.</p>
<p>Finally, Occams Razor came to the rescue. I found out that the robots trawl for the &#8220;profile.php&#8221; script and the &#8220;mode=register&#8221; URI, so I set about trying to change these.</p>
<p>They need to be changed in:</p>
<p>includes/page_header.php</p>
<p>includes/usercp_register.php</p>
<p>(remembering of course to rename the file profile.php too)</p>
<p>I changed mine to:</p>
<p>profile.php -&gt; pmatters.php</p>
<p>mode=register -&gt; mode=signupuser</p>
<p>Now, FINALLY, I have stopped getting robotic registrations!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nightbluefruit.com/blog/2007/08/phpbb-robotic-registrations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
