<?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>Lee Waterman</title>
	<atom:link href="http://leewaterman.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://leewaterman.com</link>
	<description></description>
	<lastBuildDate>Mon, 24 May 2010 08:21:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Facebook Conversion Tracking Prestashop Module</title>
		<link>http://leewaterman.com/facebook-conversion-tracking-prestashop-module/</link>
		<comments>http://leewaterman.com/facebook-conversion-tracking-prestashop-module/#comments</comments>
		<pubDate>Wed, 05 May 2010 08:41:38 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[prestashop backoffice]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=310</guid>
		<description><![CDATA[The Facebook Conversion Tracking Prestashop Module. Need to track your ROI from Facebook Ads? With this easy to use Prestashop module you can. This module automatically adds the tracking conversion code when a customer makes a purchase so you can measure if your Ads are working. You can download the Facebook Conversion Tracking Prestashop Module [...]]]></description>
			<content:encoded><![CDATA[<p>The Facebook Conversion Tracking Prestashop Module.</p>
<p><strong>Need to track your ROI from Facebook Ads? With this  easy to use Prestashop module you can. This module automatically adds the tracking conversion code when a customer makes a purchase so you can measure if your Ads are working.<br />
</strong></p>
<p>You can download the Facebook Conversion Tracking Prestashop Module using the link below:<br />
<a title="Facebook Conversion Tracking Prestashop Module" href="http://bit.ly/duckl9">Facebook Conversion Tracking Prestashop Module</a></p>
<p><a href="http://leewaterman.com/wp-content/uploads/2010/05/fbtracking.gif" rel="lightbox[310]"><img class="alignnone size-medium wp-image-318" title="fbtracking" src="http://leewaterman.com/wp-content/uploads/2010/05/fbtracking-300x285.gif" alt="" width="300" height="285" /></a></p>
<div style='display:none' id="post-refEl-310"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/facebook-conversion-tracking-prestashop-module/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone 3G tethering on your iPad</title>
		<link>http://leewaterman.com/iphone-3g-tethering-on-your-ipad/</link>
		<comments>http://leewaterman.com/iphone-3g-tethering-on-your-ipad/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 21:17:53 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=299</guid>
		<description><![CDATA[Will this be possible? Here are the price points: Will there be a reason to get the WiFi + 3G if tethering is possible?]]></description>
			<content:encoded><![CDATA[<p>Will this be possible?</p>
<p><a href="http://leewaterman.com/wp-content/uploads/2010/01/ipad-tethering.jpg" rel="lightbox[299]"><img class="alignnone size-full wp-image-306" title="ipad-tethering" src="http://leewaterman.com/wp-content/uploads/2010/01/ipad-tethering.jpg" alt="" width="437" height="267" /></a></p>
<p>Here are the price points:</p>
<p><a href="http://leewaterman.com/wp-content/uploads/2010/01/price.jpg" rel="lightbox[299]"><img class="alignnone size-medium wp-image-300" title="price" src="http://leewaterman.com/wp-content/uploads/2010/01/price-300x142.jpg" alt="" width="300" height="142" /></a></p>
<p>Will there be a reason to get the WiFi + 3G if tethering is possible?</p>
<div style='display:none' id="post-refEl-299"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/iphone-3g-tethering-on-your-ipad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bicio GoRide iPhone Bike Mount</title>
		<link>http://leewaterman.com/bicio-goride-iphone-bike-mount/</link>
		<comments>http://leewaterman.com/bicio-goride-iphone-bike-mount/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 22:11:13 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone accessories]]></category>
		<category><![CDATA[iPhone bike mount]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=290</guid>
		<description><![CDATA[The GoRide iPhone Bike Mount is designed to be mounted on your bikes handlebars, and it is designed to give you access to your iPhone whilst you are riding your bike without sacrificing safety and convenience. Bicio GoRide iPhone Bike Mount It comes with a protective case which you can keep on your iPhone all [...]]]></description>
			<content:encoded><![CDATA[<p>The GoRide iPhone Bike Mount is designed to be mounted on your bikes handlebars, and it is designed to give you access to your iPhone whilst you are riding your bike without sacrificing safety and convenience.</p>
<div class="wp-caption alignnone" style="width: 370px"><img class="  " title="Bicio GoRide iPhone Bike Mount" src="http://www.geeky-gadgets.com/wp-content/uploads/2009/11/Bicio-GoRide-iPhone-Bike-Mount_1.jpg" alt="Bicio-GoRide-iPhone-Bike-Mount" width="360" height="360" /><p class="wp-caption-text">Bicio GoRide iPhone Bike Mount</p></div>
<p>Bicio GoRide iPhone Bike Mount</p>
<p>It comes with a protective case which you can keep on your iPhone all the time if you want, the case then slots straight into the bike mount and you are ready to go out on your bike without to much effort.</p>
<p>If you want one, the Bicio GoRide iPhone Bike Mount is available now for $29.99 from <a href="http://www.bicio.com/GoRide_iphoneBikeMount.php">Bicio</a>.</p>
<div style='display:none' id="post-refEl-290"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/bicio-goride-iphone-bike-mount/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>eHow &#8211; How to Repair the Glass on an iPhone</title>
		<link>http://leewaterman.com/ehow-how-to-repair-the-glass-on-an-iphone/</link>
		<comments>http://leewaterman.com/ehow-how-to-repair-the-glass-on-an-iphone/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 02:38:53 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Repair]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=275</guid>
		<description><![CDATA[By Alyssa LaRenzie eHow Contributing Writer If your iPhone 3G screen is cracked, check first with Apple to see if your warranty covers the repair or a replacement. This repair can be difficult and should be attempted only if the image behind the glass screen is visible. With those precautions, repairing it yourself should cost [...]]]></description>
			<content:encoded><![CDATA[<div class="Content" id="ArticleSteps">
<div class="Column2">
<div class="info">
<div class="author">
<div style="float:left;margin:15px;" class="AuthorBadge ContributorBadge"><a class="userAvatar avatarSmall" title="DS_f3f0ca5c-8a00-4c3c-a2ee-cfcc8c69d329" rel="nofollow" href="http://www.ehow.com/members/ds_f3f0ca5c-8a00-4c3c-a2ee-cfcc8c69d329.html"><img src="http://cdn-sitelife.ehow.com/ver1.0/Content/images/store/7/3/976abd08-a727-43f8-a3cc-f59f9ec1ec53.Small.jpg" alt="ds_f3f0ca5c-8a00-4c3c-a2ee-cfcc8c69d329" /></a></div>
<div class="AuthorBadge ContributorBadge"><span>By</span> <a href="http://www.ehow.com/members/ds_f3f0ca5c-8a00-4c3c-a2ee-cfcc8c69d329.html">Alyssa LaRenzie</a><cite><span class="about"> </span></cite></div>
<div class="AuthorBadge ContributorBadge"><cite><span class="about">eHow Contributing Writer</span></cite></div>
<div class="AuthorBadge ContributorBadge"><span class="about"><br />
</span></div>
<p></p>
<div class="AuthorBadge ContributorBadge">If your iPhone 3G screen is cracked, check first with Apple to see if your warranty covers the repair or a replacement. This repair can be difficult and should be attempted only if the image behind the glass screen is visible.</div>
</div>
<div class="Details">
<p id="intelliTxt">With those precautions, repairing it yourself should cost about $45. This method by <a href="http://leewaterman.com">Lee Waterman</a> received several positive reviews.<span> </span></p>
</div>
</div>
<p><span>Difficulty:</span> Moderately Challenging</p>
<div class="article FLC">
<div class="sectionTitle FLC">
<h2 class="Heading3a">Instructions</h2>
</div>
<div class="thingsYouNeed">
<p></p>
<h4 class="Heading4a">Things You&#8217;ll Need:</h4>
<p></p>
<ul class="BulletList">
<li> <a href="http://www.ehow.com/shop_iphone.html">iPhone</a></li>
<li> <a href="http://iphoneshopusa.com/11-iphone-3g-touch-panel-brand-new.html">Glass screen with digitizer</a></li>
<li> <a href="http://iphoneshopusa.com/13-iphone-3g-adhesive-strips-for-iphone-3g-touch-panel-digitizer-and-touch-screen.html">Adhesive strips</a></li>
<li> <a href="http://iphoneshopusa.com/35-iphone-3g-screen-touch-panel-removal-suction-cup-tool.html">Suction cup</a></li>
<li> <span>Paper clips</span></li>
<li> <span>Tweezers</span></li>
<li> <a href="http://iphoneshopusa.com/37-iphone-3g-3gs-magnetic-small-tip-screwdrivers.html">Small Phillips screwdriver</a></li>
<li> <span>Hair dryer</span></li>
</ul>
</div>
<ol id="intelliTxt">
<h4 class="Heading4a">Taking the iPhone apart</h4>
<li>
<div class="stepBg">Step <span>1</span></div>
<p>Turn off the iPhone. Remove the SIM card by inserting a paper clip into the small hole at the top. Remove the two screws at the bottom. Push the suction cup onto the glass. Pull up to separate the glass.</li>
<li>
<div class="stepBg">Step <span>2</span></div>
<p>Three cables will hold the two pieces together. Remove the first two using a paper clip. The third is beneath a tab under the first two cables. The last cable should be pulled out gently.</li>
<li>
<div class="stepBg">Step <span>3</span></div>
<p>On the screen, remove six screws: two on one side, one on the bottom of the surface behind the glass, one visible on the other side and two under tape on that side.</li>
<li>
<div class="stepBg">Step <span>4</span></div>
<p>To remove the LCD, use a paper clip on the sides to hook the bottom corner that has a circle, and pull out.</p>
<p><br clear="all" /></p>
<h4 class="Heading4a">Removing the broken glass</h4>
</li>
<li>
<div class="stepBg">Step <span>1</span></div>
<p>Using tweezers, remove the black tape behind the glass on each of the four edges.</li>
<li>
<div class="stepBg">Step <span>2</span></div>
<p>Use a hair dryer around the edges of the glass for about 5 minutes to heat the glue.</li>
<li>
<div class="stepBg">Step <span>3</span></div>
<p>Pry the glass from the plastic holder. Be sure to remove all the broken glass.</p>
<p><br clear="all" /></p>
<h4 class="Heading4a">Installing the glass</h4>
</li>
<li>
<div class="stepBg">Step <span>1</span></div>
<p>Put the adhesive strips at the top and bottom of the plastic holder.</li>
<li>
<div class="stepBg">Step <span>2</span></div>
<p>On the new glass screen, remove all the film from the black bottom and top, leaving the protective film on the glass so no fingerprints will get inside. There will probably be two pieces of film on the black parts.</li>
<li>
<div class="stepBg">Step <span>3</span></div>
<p>Line up the glass with the holder, making sure the cable goes under the holder. When the two pieces match up, press down to stick the glass to the adhesive strips.</li>
<li>
<div class="stepBg">Step <span>4</span></div>
<p>Remove the film from the glass.</p>
<p><br clear="all" /></p>
<h4 class="Heading4a">Reassembly</h4>
</li>
<li>
<div class="stepBg">Step <span>1</span></div>
<p>Put the LCD back in the holder with all the holes for the screws aligned. Press it in place. Replace all the screws.</li>
<li>
<div class="stepBg">Step <span>2</span></div>
<p>Press all the cables into place in the reverse order of their removal.</li>
<li>
<div class="stepBg">Step <span>3</span></div>
<p>Align the two pieces &#8212; the screen and the unit &#8212; and press them together with the holes lined up.</li>
<li>
<div class="stepBg">Step <span>4</span></div>
<p>Replace the screws and your SIM card.</li>
</ol>
</div>
<p><script type="text/javascript">// <![CDATA[
 			jQuery('.article ol .image').each(function(i,e){ 				var $this = jQuery(this); 				$this.find('img').error(function(){ 					jQuery(this).remove(); 					$this.remove(); 				}); 			});
// ]]&gt;</script></p>
<p><br clear="all" /><br />
Tips &amp; Warnings</p>
<div class="resources tips">
<ul>
<li class="FLC">
<div class="text"><a href="http://iphoneshopusa.com/18-iphone-3g-adhesive-strips-for-iphone-3g-touch-panel-digitizer-and-touch-screen.html">The glass screen with digitizer and adhesive strips can be purchased online.</a></div>
</li>
<li class="FLC">
<div class="text">Attempting this repair may void your warranty. It could also break your phone if you are unsuccessful.</div>
</li>
</ul>
</div>
<div class="resources">
<h2 class="sectionTitle Heading3a">References</h2>
<ul class="BulletList">
<li><a href="http://reviews.cnet.com/8301-19512_7-10115078-233.html">CNET</a></li>
<li><a href="http://www.youtube.com/watch?v=4mboB8p-sdw&amp;annotation_id=annotation_100572&amp;feature=iv">Lee Waterman Video</a></li>
<li><a href="http://www.ehow.com/how_5427498_repair-glass-iphone.html">eHow</a></li>
</ul>
</div>
<div class="resources">
<h2 class="sectionTitle Heading3a">Resources</h2>
<ul class="BulletList">
<li><a rel="nofollow" href="http://www.iphoneshopusa.com/" target="_blank">iPhone Shop</a></li>
</ul>
</div>
</div>
</div>
<div style='display:none' id="post-refEl-275"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/ehow-how-to-repair-the-glass-on-an-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prestashop Manually Converting Carts to Orders</title>
		<link>http://leewaterman.com/prestashop-manually-converting-carts-to-orders/</link>
		<comments>http://leewaterman.com/prestashop-manually-converting-carts-to-orders/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 08:27:10 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[prestashop backoffice]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=249</guid>
		<description><![CDATA[Prestashop Cart2Order Module I recently had the need to convert customer carts into actual orders and since there wasn&#8217;t an easy way to do that with the base install code and a module didn&#8217;t exist, I wrote my own. Basically what this simple module does is convert a customer cart into an order. Here&#8217;s how [...]]]></description>
			<content:encoded><![CDATA[<h2>Prestashop Cart2Order Module</h2>
<p>I recently had the need to convert customer carts into actual orders and since there wasn&#8217;t an easy way to do that with the base install code and a module didn&#8217;t exist, I wrote my own.</p>
<p>Basically what this simple module does is convert a customer cart into an order. Here&#8217;s how it works by example:</p>
<p>If you have, say for instance Google Checkout and Paypal payment modules installed, then you will have the option to convert a customer&#8217;s cart using one of those installed payment modules.</p>
<p><a href="http://leewaterman.com/wp-content/uploads/2009/11/1.jpg" rel="lightbox[249]"><img class="alignnone size-medium wp-image-295" title="-1" src="http://leewaterman.com/wp-content/uploads/2009/11/1-300x162.jpg" alt="" width="300" height="162" /></a></p>
<p>You can download the Cart2Order module using the link below:<br />
<a title="Cart2Order Prestashop Module" onclick="javascript:pageTracker._trackPageview(/wp-content/uploads/2009/11/cart2order_0_4_0.tar');" href="http://iphoneshopusa.com/prestashop-modules/77-cart-2-order-payment.html">Cart2Order Prestashop Module</a></p>
<p>Forum discussion link below:<br />
<a href="http://bit.ly/oTglW">http://bit.ly/oTglW</a></p>
<div style='display:none' id="post-refEl-249"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/prestashop-manually-converting-carts-to-orders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preventing the copying of your site design templates</title>
		<link>http://leewaterman.com/preventing-the-copying-of-your-site-design-templates/</link>
		<comments>http://leewaterman.com/preventing-the-copying-of-your-site-design-templates/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 23:45:30 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[copying]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=245</guid>
		<description><![CDATA[I was browsing the prestashop forum and ended up on a thread concerning an issue with people stealing a site design by downloading the template files from the theme directory. It struck me that this is probably something that those of you who use other template systems with your sites may also face, so thought [...]]]></description>
			<content:encoded><![CDATA[<p>I was browsing the prestashop forum and ended up on a thread concerning an issue with people stealing a site design by downloading the template files from the theme directory. It struck me that this is probably something that those of you who use other template systems with your sites may also face, so thought I&#8217;d post the solution here too.</p>
<p>The problem is that although php files cannot be viewed directly on your browser, other source files can be e.g. files ending in .tpl</p>
<p>For example take a look at the following file that has the default permissions:</p>
<p><a title="unprotected example" onclick="window.open(this.href); return false;" onkeypress="window.open(this.href); return false;" href="http://iphoneshopusa.com/themes/prestashop/404.tpl">Unprotected template file</a></p>
<p>The best way to protect your site is to change the permissions on these files to 600. This will make them accessible only by your own code on the server and present anyone nosey enough to try and look at them with a 403 (forbidden) error. The same is true for php files (although these shouldn&#8217;t display the source unless your server configuration is broken).</p>
<p>Have a look at this file with the permissions set to 600:</p>
<p><a title="protected example" onclick="window.open(this.href); return false;" onkeypress="window.open(this.href); return false;" href="http://iphoneshopusa.com/themes/iphoneshopusa/404.tpl">Protected template file</a></p>
<p>Simple.</p>
<div style='display:none' id="post-refEl-245"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/preventing-the-copying-of-your-site-design-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Customising Prestashop Module Templates</title>
		<link>http://leewaterman.com/customising-prestashop-module-templates/</link>
		<comments>http://leewaterman.com/customising-prestashop-module-templates/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 23:13:22 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=242</guid>
		<description><![CDATA[Please don&#8217;t edit those originals! I came across this little gem a while ago on the Prestashop forum, and thought I would draw attention to it in the hopes that it will help someone, somewhere. I&#8217;m not one to complain, but my pet hate is folks who edit the original source files on their stores, [...]]]></description>
			<content:encoded><![CDATA[<h2>Please don&#8217;t edit those originals!</h2>
<p></p>
<p>I came across this little gem a while ago on the Prestashop forum, and thought I would draw attention to it in the hopes that it will help someone, somewhere.</p>
<p><span id="more-709"></span></p>
<p>I&#8217;m not one to complain, but my pet hate is folks who edit the original source files on their stores, when there&#8217;s no need to. It bugged me in Zen Cart when people happily modified the &#8220;classic&#8221; and &#8220;default&#8221; template files, then wondered why it was difficult to upgrade&#8230; and lo and behold folks started doing the same thing to the Prestashop default theme too. Aaaargh!! How hard is it to make a copy, rename it and edit that version instead?</p>
<p>Where my purist instincts failed however, way back in the bad old days, was when it came to the .tpl files that were stored in the module directories themselves &#8212; there seems like there&#8217;s no choice but to edit them if you want to customise the output for your store &#8212; or is there!</p>
<p>The answer is surprisingly simple, and will make you nod your head in grateful appreciation&#8230; all you need to do is create a modules/<modulename> directory in your custom theme directory (well you aren&#8217;t going to be working in the default theme directory now are you), copy the original .tpl from the module directory into it and edit away to your heart&#8217;s content.</p>
<p>As an example, you can take the template file from the blockadvertising module (blockadvertising.tpl) and make a copy under /themes/mycooltheme/modules/blockadvertising. Now modify the copy of the original that looked like:</p>
<pre class="brush: php">
<!-- MODULE Block advertising -->
<div class="advertising_block">
	<a href="http://www.prestashop.com" title="{l s='Advertising' mod='blockadvertising'}"><img src="{$image}" alt="{l s='Advertising' mod='blockadvertising'}" /></a>
</div>

<!-- /MODULE Block advertising -->
</pre>
<p>to</p>
<pre class="brush: php">
<!-- My MODULE Block advertising -->
<div class="advertising_block">
	<a href="http://www.ecartservice.net" title="{l s='Advertising' mod='blockadvertising'}"><img src="{$image}" alt="{l s='A fantastic site for Prestashop goodies' mod='blockadvertising'}" /></a>
</div>

<!-- /My MODULE Block advertising -->
</pre>
<p>Pure joy! Although the observant will notice that unless you edit the {$image} variable and place a static path to your graphic in its place, then you&#8217;ll have to change the picture in the module directory&#8230;. well you can&#8217;t have it all I guess.</p>
<div style='display:none' id="post-refEl-242"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/customising-prestashop-module-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing your own Prestashop Module &#8211; Part 5</title>
		<link>http://leewaterman.com/writing-your-own-prestashop-module-part-5/</link>
		<comments>http://leewaterman.com/writing-your-own-prestashop-module-part-5/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 22:49:02 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[prestashop backoffice]]></category>
		<category><![CDATA[template module]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=225</guid>
		<description><![CDATA[The finishing touches Introduction In this final part of our basic module writing tutorial series we&#8217;ll look at the final steps to transform our Tutorialthird module class into a base template that we can use to kick start the writing of new modules. Rather than republish the same old code again we&#8217;ll only discuss the [...]]]></description>
			<content:encoded><![CDATA[<h2>The finishing touches</h2>
<p></p>
<h3>Introduction</h3>
<p>In this final part of our basic module writing tutorial series we&#8217;ll look at the final steps to transform our Tutorialthird module class into a base template that we can use to kick start the writing of new modules. Rather than republish the same old code again we&#8217;ll only discuss the changes, but I&#8217;ve added a download link at the end of this part so you can grab the final code and use it as the basis for your own projects. We&#8217;re going to call this module &#8220;Skeleton&#8221; &#8211; a name that we&#8217;ll replace with our own when it comes to producing new modules based on it.</p>
<p><span id="more-603"></span></p>
<h3>Styling the configuration form</h3>
<p>The first changes we&#8217;re going to make are purely cosmetic, however this is an important element since we want to provide a consistent interface for our users.  Our form code looked like:</p>
<pre class="brush: php">
	private function _displayForm()
	{
		$this-&gt;_html .= '
		&lt;form action=&quot;'.$_SERVER['REQUEST_URI'].'&quot; method=&quot;post&quot;&gt;
				&lt;label&gt;'.$this-&gt;l('Message to the world').'&lt;/label&gt;
				&lt;div class=&quot;margin-form&quot;&gt;

					&lt;input type=&quot;text&quot; name=&quot;our_message&quot; /&gt;
				&lt;/div&gt;
				&lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;'.$this-&gt;l('Update').'&quot; class=&quot;button&quot; /&gt;

		&lt;/form&gt;';
	}
</pre>
<p>The convention for these configuration screens is to wrap the settings in a fieldset, and we&#8217;ll also need to add a nice friendly (translatable) legend complete with icon. Our code will now look like:</p>
<pre class="brush: php">
	private function _displayForm()
	{
		$this-&gt;_html .= '
		&lt;form action=&quot;'.$_SERVER['REQUEST_URI'].'&quot; method=&quot;post&quot;&gt;

			&lt;fieldset&gt;
				&lt;legend&gt;&lt;img src=&quot;../img/admin/cog.gif&quot; alt=&quot;&quot; class=&quot;middle&quot; /&gt;'.$this-&gt;l('Settings').'&lt;/legend&gt;

				&lt;label&gt;'.$this-&gt;l('Message to the world').'&lt;/label&gt;
				&lt;div class=&quot;margin-form&quot;&gt;
					&lt;input type=&quot;text&quot; name=&quot;our_message&quot; /&gt;

				&lt;/div&gt;
			&lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;'.$this-&gt;l('Update').'&quot; class=&quot;button&quot; /&gt;

			&lt;/fieldset&gt;
		&lt;/form&gt;';
	}
</pre>
<p>Our final cosmetic change is to add a heading at the top of our settings screen just in case the user has forgotten where they are! We do this by adding the following line at the start of the getContent() function:</p>
<pre class="brush: php">
$this-&gt;_html .= '&lt;h2&gt;'.$this-&gt;displayName.'&lt;/h2&gt;';
</pre>
<h3>Pre-populating configuration form fields</h3>
<p>Another missing element from our original tutorial design was the display of the current settings in the module configuration form, and even when the form returns from updating the values the fields are blank, so we need to fix this glitch too. There are two possibilities that we need to handle:</p>
<ol>
<li>Initial display of the form should display the current configuration (if any)</li>
<li>After a form update we should display the data entered by the user</li>
</ol>
<p>We can use the Configuration::get() function to retrieve the current settings from the database, and Tools::getValue() to get the field contents. The Tools::getValue() function takes a second parameter which is useful in this context, as this specifies a &#8220;default&#8221; to use should the field be empty. We can now set the &#8220;value&#8221; attribute of our input tag appropriately using these two functions, so our final form input code will be:</p>
<pre class="brush: php">
&lt;input type=&quot;text&quot; name=&quot;our_message&quot; value=&quot;'.Tools::getValue('our_message', Configuration::get($this-&gt;name.'_message')).'&quot;/&gt;
</pre>
<p>Another useful change to make when dealing with several fields in a configuration for is to move the database update code to it&#8217;s own private function. For this we will replace the line:</p>
<pre class="brush: php">

if (!sizeof($this-&gt;_postErrors))
	{
		Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'), true);
		$this-&gt;_html .= '&lt;div class=&quot;conf confirm&quot;&gt;'.$this-&gt;l('Settings updated').'&lt;/div&gt;';
	}
</pre>
<p>with the following:</p>
<pre class="brush: php">
if (!sizeof($this-&gt;_postErrors))
	$this-&gt;_postProcess();
</pre>
<p>And we add the new private member function to our class to handle the actual updates in a single, easily identified location:</p>
<pre class="brush: php">
	private function _postProcess()
	{
		Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'), true);

		$this-&gt;_html .= '&lt;div class=&quot;conf confirm&quot;&gt;'.$this-&gt;l('Settings updated').'&lt;/div&gt;';
	}
</pre>
<h3>Handling other field types</h3>
<p>In the final download of the skeleton module I&#8217;ve also added examples of other types of fields that will act as useful shortcuts to creating your module configuration form. This covers checkboxes, radio buttons, textarea and drop-down lists. All you need to do is add/rename the fields, add any validation required to the _postValidation() function and modify the update code in the _postProcess() function appropriately.</p>
<p>For mandatory settings you should also test for their presence in the install function and take appropriate action to prevent your module causing errors in the Front Office e.g. by setting appropriate defaults using the Configuration::updateValue() function. Alternatively this can be performed in the module constructor, although it is more correct to perform this within install().</p>
<h3>Adding multiple display location hooks</h3>
<p>Our Tutorialthird module could only display our content in the left column since this was the only hook we implemented. Luckily it&#8217;s very easy to implement the &#8220;Transplant a module&#8221; BackOffice functionality in our code. In the simplest form we will just use the same output in all locations, but if required all of these additional hooks can produce different results.</p>
<p>To produce the same output in all the popular locations, we merely need to implement the additional hook functions in our module and call the original hook code to generate the output. Note that we only actually call registerHook() for the default one in the install() member function, and let the Back Office handle the registration of the others.</p>
<pre class="brush: php">
	function hookRightColumn($params)
	{
		return $this-&gt;hookLeftColumn($params);
	}

	function hookTop($params)
	{
		return $this-&gt;hookLeftColumn($params);
	}

	function hookHome($params)
	{
		return $this-&gt;hookLeftColumn($params);
	}

	function hookFooter($params)
	{
		return $this-&gt;hookLeftColumn($params);
	}
</pre>
<h3>Summary</h3>
<p>Over this series of articles you should have learned how the basic module system works in Prestashop and be able to code modules that deliver output to the different presentation areas in the Front Office. You&#8217;ll also have a good code framework to base your own modules on. You may have noticed that at no time have we actually used smarty or its template files in the creation of our module &#8212; this is deliberate as they can be seen as a separate entity from the module design itself.</p>
<p>Smarty is highly flexible, but the choice to use it is based on many factors, and for performance reasons it is best to avoid its use if at all possible. Later articles will explore how and when to use smarty to enhance your modules functionality though, as it is a fundamental part of the Prestashop architecture.</p>
<p>You can download the complete skeleton module code using the link below:</p>
<p><a onclick="javascript:pageTracker._trackPageview('/wp-content/uploads/2009/11/skeleton_0_1_0.zip');"  href="/wp-content/uploads/2009/11/skeleton_0_1_0.zip" title="Skeleton Prestashop Module">Skeleton v0.1.0</a></p>
<div style='display:none' id="post-refEl-225"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/writing-your-own-prestashop-module-part-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing your own Prestashop Module &#8211; Part 4</title>
		<link>http://leewaterman.com/writing-your-own-prestashop-module-part-4/</link>
		<comments>http://leewaterman.com/writing-your-own-prestashop-module-part-4/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 22:35:29 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[form validation]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=221</guid>
		<description><![CDATA[Form Validation and Security Introduction While being sufficiently functional for what it does, the module we created in Part 2 does present us with some issues to consider when implementing &#8220;real world&#8221; modules to extend Prestashop. In particular the user input we captured with our form was written directly to the configuration entry without any [...]]]></description>
			<content:encoded><![CDATA[<h2>Form Validation and Security</h2>
<p></p>
<h3>Introduction</h3>
<p>While being sufficiently functional for what it does, the module we created in Part 2 does present us with some issues to consider when implementing &#8220;real world&#8221; modules to extend Prestashop. In particular the user input we captured with our form was written directly to the configuration entry without any checking to determine whether it was valid, nor did we take account of the type of data being entered.</p>
<p>In this tutorial we will look at the general issue of form input checking and security, both for Back Office and Front Office forms and user input as well as looking at improving our code both functionally and aesthetically.</p>
<p><span id="more-519"></span></p>
<h3>The Configuration class revisited</h3>
<p>In Part 3 we touched briefly on an additional parameter that may be passed to the Configuration::updateValue() class method. If you recall the function has the following form:</p>
<pre class="brush: php">updateValue($key, $values, $html = false);</pre>
<p>In Part 3 we ignored the $html parameter and allowed the function to use the default value of &#8220;false&#8221;. In doing this we actually inadvertently added the first element of security and validation to our code. When set to &#8220;false&#8221; the updateValue() method actually pre-processes the value to be written using the following code ($string is the input value passed to the function):</p>
<pre class="brush: php">$string = strip_tags(nl2br2($string));</pre>
<p>You can test this out by entering some HTML into the configuration screen for the module we created in Part 3. You should see that any html tags in your input are removed. We could modify the TutorialSecond module to allow input of html in the form, by changing line 29 in the source file to:</p>
<pre class="brush: php">Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message', true));</pre>
<p>This illustrates the fundamental principle that we need to employ throughout our own code to ensure that it is secure and operates predictably. Thankfully Prestashop provides us with some tools that we can use in our own code to make it more secure and robust.</p>
<h3>Validation</h3>
<p>Prestashop provides us with a class called Validate that we can use to determine whether any user input we accept is valid or not. The list of member functions is rather large, but it&#8217;s worth reproducing some of them here to illustrate the point &#8212; for a complete list you should consult the classes/Validate.php file in your Prestashop distribution.</p>
<pre class="brush: php">
isEmail($email);
isFloat($float);
isUnsignedFloat($float);
isCleanHtml($html);
isDate($date);
isBool($bool);
isPhoneNumber($phoneNumber);
isPostCode($postcode);
isInt($int);
isUnsignedInt($int);
isUnsignedId($id);
isNullOrUnsignedId($id);
isUrl($url);
isAbsoluteUrl($url);
isFileName($name);
</pre>
<p>As an example we can use the isCleanHtml() function from the list above as a test in our module to prevent XSS (cross site scripting) &#8212; that way we can allow html input reasonable safely.</p>
<h4>Validating our form data</h4>
<p>As before we&#8217;re going to create a new module based on the previous version. Why not try modifying the Tutorialsecond class yourself to create the Tutorialthird module? If you&#8217;d rather not, then just expand and copy the code below as appropriate!</p>
<pre class="brush: php">
&lt;?php
class Tutorialthird extends Module
{
	private $_html = '';

	function __construct()
	{
		$this-&gt;name = 'tutorialthird';
		parent::__construct();

		$this-&gt;tab = 'eCartService.net Tutorials';
		$this-&gt;version = '0.1.0';
		$this-&gt;displayName = $this-&gt;l('Third Tutorial Module');
		$this-&gt;description = $this-&gt;l('Our third module - Security and Validation');
	}

	public function install()
	{
		parent::install();

		if (!$this-&gt;registerHook('leftColumn'))
			return false;
	}

	public function getContent()
	{
		if (Tools::isSubmit('submit'))
		{
			Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'));
		}

		$this-&gt;_displayForm();

		return $this-&gt;_html;
	}

	private function _displayForm()
	{
		$this-&gt;_html .= '
		&lt;form action=&quot;'.$_SERVER['REQUEST_URI'].'&quot; method=&quot;post&quot;&gt;

				&lt;label&gt;'.$this-&gt;l('Message to the world').'&lt;/label&gt;
				&lt;div class=&quot;margin-form&quot;&gt;
					&lt;input type=&quot;text&quot; name=&quot;our_message&quot; /&gt;

				&lt;/div&gt;
				&lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;'.$this-&gt;l('Update').'&quot; class=&quot;button&quot; /&gt;

		&lt;/form&gt;';
	}

	public function hookLeftColumn()
	{
		return '&lt;div class=&quot;block&quot;&gt;&lt;h4&gt;'. Configuration::get($this-&gt;name.'_message') . '&lt;/h4&gt;&lt;/div&gt;';
	}

}
// End of: tutorialthird.php
</pre>
<p>The first stage in the process is to modify our getContent() function to add the validation step:</p>
<pre class="brush: php">
	public function getContent()
	{
		if (Tools::isSubmit('submit'))
		{
			$this-&gt;_postValidation();

			if (!sizeof($this-&gt;_postErrors))
			{
				Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'), true);
				$this-&gt;_html .= '&lt;div class=&quot;conf confirm&quot;&gt;'.$this-&gt;l('Settings updated').'&lt;/div&gt;';
			}
			else
			{
				foreach ($this-&gt;_postErrors AS $err)
				{
					$this-&gt;_html .= '&lt;div class=&quot;alert error&quot;&gt;'.$err.'&lt;/div&gt;';
				}
			}
		}

		$this-&gt;_displayForm();

		return $this-&gt;_html;
	}
</pre>
<p>We also need to add a declaration for the $_postErrors member variable we&#8217;ve introduced at the beginning of our class definition e.g.</p>
<pre class="brush: php">
class Tutorialthird extends Module
{
	private $_html = '';
	private $_postErrors = array();
</pre>
<p>The logic flow when we post data to getContent() is now to call our _Validation() function to test the fields submitted and to set our $_postErrors array with any error messages. If there are errors we can display them prior to redisplaying the form. If the validation checks are passed, then we display a &#8220;success&#8221; message to give visual feedback that the configuration has been updated. A simple XSS test in the _Validation() function for our example could be:</p>
<pre class="brush: php">
	private function _postValidation()
	{
		if (!Validate::isCleanHtml(Tools::getValue('our_message')))
			$this-&gt;_postErrors[] = $this-&gt;l('The message you entered was not allowed, sorry');
	}
</pre>
<p>Obviously you aren&#8217;t limited to using the tests supplied by the Validate class, and you can also apply multiple tests to each field submitted &#8212; to test for length etc. The basic principle is the same in all cases, no matter how complex your validation requirements are.</p>
<h3>Summary</h3>
<p>In this article we&#8217;ve improved on our form handling by adding validation of user input for added security and/or reliability. We&#8217;ve also added some visual feedback when the configuration has been updated successfully. In the <a href="/03082009/writing-your-own-prestashop-module-part-5/" title="Writing a module part 5">final part</a> of this series we&#8217;ll add some final cosmetic touches to our form to standardise the interface and improve usability. We&#8217;ll also look at ideas for improving and extending the &#8220;template&#8221; module we&#8217;ve created.</p>
<div style='display:none' id="post-refEl-221"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/writing-your-own-prestashop-module-part-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing your own Prestashop Module &#8211; Part 3</title>
		<link>http://leewaterman.com/writing-your-own-prestashop-module-part-3/</link>
		<comments>http://leewaterman.com/writing-your-own-prestashop-module-part-3/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 22:28:21 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[prestashop]]></category>

		<guid isPermaLink="false">http://leewaterman.com/?p=214</guid>
		<description><![CDATA[Storing Module Configuration Introduction In the third part of this series we’ll look at how we can store configuration data for our modules in the Prestashop database, and how we can allow users to interact with this data to control the module’s behaviour. We will also briefly touch on how we can generate output from [...]]]></description>
			<content:encoded><![CDATA[<h2>Storing Module Configuration</h2>
<p></p>
<h3>Introduction</h3>
<p>In the third part of this series we’ll look at how we can store configuration data for our modules in the Prestashop database, and how we can allow users to interact with this data to control the module’s behaviour. We will also briefly touch on how we can generate output from our module to provide visual feedback of the configuration changes.</p>
<p><span id="more-475"> </span></p>
<h3>Managing user settings</h3>
<p>We’re going to call this module “TutorialSecond” so we again need to create a new module directory and class file — which will be named “tutorialsecond” and “tutorialsecond.php” respectively. The class file (tutorialsecond.php) should contain the following:</p>
<pre class="brush: php">&lt;?php
class Tutorialsecond extends Module
{
	private $_html = '';

	function __construct()
	{
		$this-&gt;name = 'tutorialsecond';
		parent::__construct();

		$this-&gt;tab = 'eCartService.net Tutorials';
		$this-&gt;version = '0.1.0';
		$this-&gt;displayName = $this-&gt;l('Second Tutorial Module');
		$this-&gt;description = $this-&gt;l('Our second module - A "Hello world" redux');
	}

	public function getContent()
	{

	}

	private function _displayForm()
	{

	}

}
// End of: tutorialsecond.php</pre>
<p>You will notice that we have implemented two new member functions ::getContent() and ::_displayForm(). If you upload the file to your server and install this module at this stage you should see a new option on the modules list screen for ‘Second Tutorial Module’. There will now be a “&gt;&gt; Configure” link in the module entry, although clicking it will merely return an empty Back Office page. The presence of the ::getContent() member function is responsible for this as it provides the interface between our module and the Back Office.</p>
<p>In addition to these two new functions we have also added the $_html private member variable, which we will use later in this article to build the required output for display in the Back Office.</p>
<h3>Storing and Retrieving Configuration Data</h3>
<p>Prestashop provides a “Configuration” class which offers several member functions to manipulate configuration data, but the two key functions that will be most commonly used are:</p>
<pre class="brush: php">Configuration::updateValue($key, $values, $html = false);
Configuration::get($key, $id_lang = NULL);</pre>
<p>The Configuration::updateValue() function allows us to store a configuration option in the database (optionally in multiple languages in which case the $values parameter will be an array) and the Configuration::get() function allows us to retrieve configuration data for a selected or store default language. We will ignore the parameters that have default values for now, but will revisit the $html parameter in the Configuration::updateValue() function in the next article when we look at the subject of form validation.</p>
<h3>Implementing the Configure Screen</h3>
<p>In our source file we created a private member function _displayForm(). This is entirely optional as all of the interface code could be placed in the getContent() member function, however it is highly recommended that you separate this out for the sake of easier code maintenance. We’ll create a simple form within this function from with which we can capture store owner input.</p>
<pre class="brush: php">	private function _displayForm()
	{
		$this-&gt;_html .= '
		&lt;form action="'.$_SERVER['REQUEST_URI'].'" method="post"&gt;
				&lt;label&gt;'.$this-&gt;l('Message to the world').'&lt;/label&gt;
				&lt;div class="margin-form"&gt;

					&lt;input type="text" name="our_message" /&gt;
				&lt;/div&gt;
				&lt;input type="submit" name="submit" value="'.$this-&gt;l('Update').'" class="button" /&gt;

		&lt;/form&gt;';
	}</pre>
<p>You can see that the ::_displayForm() function simply appends standard html form code to our $_html member variable, with the form target being $_SERVER['REQUEST_URI']. Prestashop’s Back Office architecture will route this to our ::getContent class member function for us to handle when the form is posted.</p>
<p>We next need to add code to our ::getContent() function to actually display the form and handle the form submission.</p>
<pre class="brush: php">	public function getContent()
	{
		if (Tools::isSubmit('submit'))
		{
			Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'));
		}

		$this-&gt;_displayForm();

		return $this-&gt;_html;
	}</pre>
<p>The ::getContent() function first uses another Prestashop class “Tools” to test whether we are handling the post action from the form, or whether this function is being called in another way i.e. a click on the “Configure” link in the module list — the parameter is the name we gave to our “update” button in the form.</p>
<p>If the function is being called directly by the Back Office (in which case Tools::isSubmit(’submit’) will return false), then we call the form rendering function we created above and return the output, captured in the $this-&gt;_html variable, to the Back Office for display.</p>
<p>If the function is being called as a result of our form being posted, then we can store our configuration parameter in the database with the value entered on our form. We again use the Tools class to obtain the value of the form variable using the call to Tools::getValue(’our_message’) where ‘our_message’ is the name of the input field in our form.</p>
<p>You can see that I have added the name of our module to the beginning of the configuration item name — this is to ensure that the configuration key is unique as the namespace for these keys is shared for the entire store.</p>
<p>Once we have stored our configuration data the form is again displayed, ready for more input if required.</p>
<h3>Module Output on a Page</h3>
<p>We now have a method of capturing input from the store owner and saving it in the database, so the next obvious step would be to do something with it e.g. display it on a page. In part 1 of the series we talked about “hooks” in relation to modules adding functionality. In order to utilise this we need to tell PrestaShop that our module would like to hook into the Front office and we do this using the following function (defined in the Module base class):</p>
<pre class="brush: php">$this-&gt;registerHook($hook_name);</pre>
<p>The $hook_name parameter refers to one of the different points that the Prestashop core allows modules to insert output and/or data processing, but for now we will use one in particular — “leftColumn’, which allows us to add content in the left column of all pages. In order to initialise the hook we need to add the following new override in our own class:</p>
<pre class="brush: php">	public function install()
	{
		parent::install();

		if (!$this-&gt;registerHook('leftColumn'))
			return false;
	}</pre>
<p>This tells Prestashop to execute our module hook when it is rendering the content for the left column of all pages. We next need to add a function to handle the hook callback. The convention is to name the function as the Hook name preceded by “hook”:</p>
<pre class="brush: php">	public function hookLeftColumn()
	{
		return '&lt;div class="block"&gt;&lt;h4&gt;'. Configuration::get($this-&gt;name.'_message') . '&lt;/h4&gt;&lt;/div&gt;';
	}</pre>
<p>In our simple example we are just wrapping our configuration parameter in some standard html markup so that it is displayed correctly on our page.</p>
<p>If you have already installed the module you should now uninstall then reinstall to ensure that the hook is correctly registered with the Prestashop core. Now you can enter a value in the configuration screen for the module — e.g. ‘Hello World’, and it will be output as the heading of a box in the left column of your store. The full code for the second example should now look like:</p>
<pre class="brush: php">&lt;?php
class Tutorialsecond extends Module
{
	private $_html = '';

	function __construct()
	{
		$this-&gt;name = 'tutorialsecond';
		parent::__construct();

		$this-&gt;tab = 'eCartService.net Tutorials';
		$this-&gt;version = '0.1.0';
		$this-&gt;displayName = $this-&gt;l('Second Tutorial Module');
		$this-&gt;description = $this-&gt;l('Our second module - A "Hello world" redux');
	}

	public function install()
	{
		parent::install();

		if (!$this-&gt;registerHook('leftColumn'))
			return false;
	}

	public function getContent()
	{
		if (Tools::isSubmit('submit'))
		{
			Configuration::updateValue($this-&gt;name.'_message', Tools::getValue('our_message'));
		}

		$this-&gt;_displayForm();

		return $this-&gt;_html;
	}

	private function _displayForm()
	{
		$this-&gt;_html .= '
		&lt;form action="'.$_SERVER['REQUEST_URI'].'" method="post"&gt;

				&lt;label&gt;'.$this-&gt;l('Message to the world').'&lt;/label&gt;
				&lt;div class="margin-form"&gt;
					&lt;input type="text" name="our_message" /&gt;

				&lt;/div&gt;
				&lt;input type="submit" name="submit" value="'.$this-&gt;l('Update').'" class="button" /&gt;

		&lt;/form&gt;';
	}

	public function hookLeftColumn()
	{
		return '&lt;div class="block"&gt;&lt;h4&gt;'. Configuration::get($this-&gt;name.'_message') . '&lt;/h4&gt;&lt;/div&gt;';
	}

}
// End of: tutorialsecond.php</pre>
<h3>Summary</h3>
<p>In this article we have extended our first module to include a basic configuration form and have used a hook function to display output from our module in the left column of our pages. In the next part of this series we will look at improving the configuration facility into something that could be used in a real module implementation. This will include validating user input to the form, pre-populating the form fields as appropriate based on the current configuration and displaying module errors and warnings in the Back Office screens.</p>
<div style='display:none' id="post-refEl-214"></div>]]></content:encoded>
			<wfw:commentRss>http://leewaterman.com/writing-your-own-prestashop-module-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
