<?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>SpinOneSolutions</title>
	<atom:link href="http://www.spinonesolutions.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spinonesolutions.com</link>
	<description>I waste my time so that you don't have to...</description>
	<lastBuildDate>Mon, 16 May 2011 17:01:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Magento Admin Form POST with form_key</title>
		<link>http://www.spinonesolutions.com/2011/01/admin-form-post-form_key/</link>
		<comments>http://www.spinonesolutions.com/2011/01/admin-form-post-form_key/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 16:40:18 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Admin]]></category>
		<category><![CDATA[Form]]></category>
		<category><![CDATA[Post]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=685</guid>
		<description><![CDATA[The other day I was trying to help someone create a Form in the admin side of Magento that would simply POST to a Controller and capture some data. I thought it&#8217;d be fairly simple, I&#8217;ve done it before; I thought. Turns out I had done it before, but I&#8217;ve always used the built in [...]]]></description>
				<content:encoded><![CDATA[<p>The other day I was trying to help someone create a Form in the admin side of Magento that would simply POST to a Controller and capture some data.  I thought it&#8217;d be fairly simple, I&#8217;ve done it before; I thought.</p>
<p>Turns out I had done it before, but I&#8217;ve always used the built in Magento Form widgets, never specified a custom .phtml template and actually tried to write the Form code by hand.  It&#8217;s a little more tricky than I anticipated, but we struggled through it and finally found the catch.</p>
<p>The &#8220;catch&#8221;, as it were, is that you have to send a hidden &#8220;form_key&#8221;.  This lets Magento know that you are who you say you are and not some spoofer posting malicious code to your backend.  Let&#8217;s get started.</p>
<p>Let&#8217;s presume that I&#8217;ve got a Module <strong>Spinonesolutions_Helloworld</strong> in it I&#8217;m going to make a block:</p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/Block/Adminhtml/Adminform.php</strong></p>
<pre class="php" name="code">class Spinonesolutions_Helloworld_Block_Adminhtml_Adminform extends Mage_Adminhtml_Block_Template {
public function __construct() {
    parent::__construct();
    $this-&gt;setTemplate('helloworld/form.phtml');
    $this-&gt;setFormAction(Mage::getUrl('*/*/new'));
  }
}</pre>
<p>It&#8217;s easily seen that I&#8217;m referencing a .phtml template within my Block for the presentation so let&#8217;s make that file as well:</p>
<p><strong>/app/design/adminhtml/default/default/template/hellworld/form.phtml</strong></p>
<pre class="html" name="code">&lt;form action="&lt;? echo $this-&gt;getFormAction(); ?&gt;" method="POST"&gt;
&lt;input type="text" id="var1" name="var1" /&gt;
&lt;input type="submit" id="submit" name="submit" /&gt;
&lt;/form&gt;</pre>
<p>Lastly we need a Controller to handle the POST and to render our Block:</p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/controllers/Adminhtml/AdminformController.php</strong></p>
<pre class="php" name="code">class Spinonesolutions_Helloworld_Adminhtml_AdminformController extends Mage_Adminhtml_Controller_Action {

public function indexAction() {
  $this-&gt;loadLayout();
  $block = $this-&gt;getLayout()-&gt;createBlock('spinonesolutions_helloworld/adminhtml_adminform','admin_form');
  $this-&gt;getLayout()-&gt;getBlock('content')-&gt;append($block);
  $this-&gt;renderLayout();
}

public function newAction() {
  die('here I am!');
}
}</pre>
<p>OK, that&#8217;s it for the architecture.  Let&#8217;s wire it all up with some XML in <strong>config.xml</strong>.  Note this is partial, not a full module definition:</p>
<pre class="xml" name="code">&lt;blocks&gt;
&lt;spinonesolutions_helloworld&gt;
&lt;class&gt;Spinonesolutions_Helloworld_Block&lt;/class&gt;
&lt;/spinonesolutions_helloworld&gt;
&lt;/blocks&gt;
&lt;admin&gt;
&lt;routers&gt;

&lt;adminhtml&gt;
&lt;args&gt;
&lt;modules&gt;
&lt;Spinonesolutions_Helloworld before="Mage_Adminhtml"&gt;Spinonesolutions_Helloworld_Adminhtml&lt;/Spinonesolutions_Helloworld&gt;
&lt;/modules&gt;
&lt;/args&gt;
&lt;/adminhtml&gt;
&lt;/routers&gt;
&lt;/admin&gt;</pre>
<p>Now, if you visit */admin/adminform/index you should see your super simple Form.  If you hit submit your Form will certainly post, but instead of seeing the die output you&#8217;ll be redirected to the Dashboard.  This because we haven&#8217;t sent through the authentication required by Magento&#8217;s internal routing system that will validate our form.  Let&#8217;s change <strong>form.phtml</strong> so that we can POST successfully.</p>
<pre class="html" name="code">&lt;form action="&lt;? echo $this-&gt;getFormAction(); ?&gt;" method="POST"&gt;
&lt;input type="hidden" name="form_key" value="&lt;? echo $this-&gt;getFormKey(); ?&gt;" /&gt;
&lt;input type="text" id="var1" name="var1" /&gt;
&lt;input type="submit" id="submit" name="submit" /&gt;
&lt;/form&gt;</pre>
<p>That&#8217;s all there is to it!  Notice the &#8220;form_key&#8221; hidden variable.  That&#8217;s the key to submitting Forms in the Magento admin.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2011/01/admin-form-post-form_key/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Drupal sess_read() causes logout</title>
		<link>http://www.spinonesolutions.com/2011/01/drupal-sess_read-causes-logout/</link>
		<comments>http://www.spinonesolutions.com/2011/01/drupal-sess_read-causes-logout/#comments</comments>
		<pubDate>Fri, 28 Jan 2011 15:21:30 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[drupal]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=702</guid>
		<description><![CDATA[Affects: Drupal 6.20 If you try to read a value from a session that has not been set your Drupal user will be logged out. Example: sess_write('myValue',TRUE); echo sess_read('myValue'); OK echo sess_read('myValue'); NOT OK, user is logged out.]]></description>
				<content:encoded><![CDATA[<p><em>Affects: Drupal 6.20</em></p>
<p>If you try to read a value from a session that has not been set your Drupal user will be logged out.</p>
<p>Example:</p>
<pre class="php" name="code">sess_write('myValue',TRUE);
echo sess_read('myValue');
</pre>
<p>OK</p>
<pre class="php" name="code">echo sess_read('myValue');
</pre>
<p>NOT OK, user is logged out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2011/01/drupal-sess_read-causes-logout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Magento – Create a globally available static function</title>
		<link>http://www.spinonesolutions.com/2010/12/magento-create-a-globally-available-static-function/</link>
		<comments>http://www.spinonesolutions.com/2010/12/magento-create-a-globally-available-static-function/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 15:00:43 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[global]]></category>
		<category><![CDATA[lib]]></category>
		<category><![CDATA[static]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=608</guid>
		<description><![CDATA[Sometimes, you&#8217;ve got a situation where you want to have a globally available static function.  Most often this occurs (for me) in a debugging context.  Recently I wanted to have FirePHP available from anywhere in my project so I made use of the lib folder. Unlike just about every other article on this site, for [...]]]></description>
				<content:encoded><![CDATA[<p>Sometimes, you&#8217;ve got a situation where you want to have a globally available static function.  Most often this occurs (for me) in a debugging context.  Recently I wanted to have FirePHP available from anywhere in my project so I made use of the <strong>lib</strong> folder.</p>
<p>Unlike just about every other article on this site, for this one we&#8217;re going to be considering the folder <strong>/lib</strong>.  Note that this folder is NOT within local, but resident in the root.  As such changes here should be put within their own sub-folders so that they too will survive an upgrade.</p>
<p>It&#8217;s really quite easy to create your class, just follow the usual Magento naming conventions. I&#8217;m going to create <strong>Spinonesolutions_Devel_FirePHP</strong> so all I do is create the file: <strong>/lib/Spinonesolutions/Devel/FirePHP.php</strong>.  Note the similarity to Model naming.</p>
<p>In here I create my class definition:</p>
<pre class="php" name="code">&lt;?php
class Spinonesolutions_Devel_FirePHP {
  public static function send($var, $label = "DEBUG", $style = "LOG") {
    if (Mage::getIsDeveloperMode()) {
      $request = new Zend_Controller_Request_Http();
      $response = new Zend_Controller_Response_Http();
      $channel = Zend_Wildfire_Channel_HttpHeaders::getInstance();
      $channel-&gt;setRequest($request);
      $channel-&gt;setResponse($response);

      /*
      * Start output buffering
      */
      ob_start();

      Zend_Wildfire_Plugin_FirePhp::send($var, $label, $style);

      /*
      Style     Description
      LOG     Displays a plain log message
      INFO     Displays an info log message
      WARN     Displays a warning log message
      ERROR     Displays an error log message that increments Firebug?s error count
      TRACE     Displays a log message with an expandable stack trace
      EXCEPTION     Displays an error long message with an expandable stack trace
      TABLE     Displays a log message with an expandable table
      */

      /*
      * Flush log data to browser
      */
      $channel-&gt;flush();
      $response-&gt;sendHeaders();
    } else {
      return null;
    }
  }
}</pre>
<p>Now I can call <strong>Spinonesolutions_Devel_FirePHP:send()</strong> anywhere in my project.  Sweet!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/12/magento-create-a-globally-available-static-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The List of Awesome</title>
		<link>http://www.spinonesolutions.com/2010/12/the-list-of-awesome/</link>
		<comments>http://www.spinonesolutions.com/2010/12/the-list-of-awesome/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 19:33:49 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=693</guid>
		<description><![CDATA[jQuery uploadify &#8211; http://www.uploadify.com NIVO Slider &#8211; http://nivo.dev7studios.com Colortip &#8211; http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/ Spritely &#8211; http://spritely.net/ Masonry &#8211; http://desandro.com/resources/jquery-masonry/ Lettering.JS &#8211; http://daverupert.com/2010/09/lettering-js/ YoxView &#8211; http://www.yoxigen.com/yoxview/ tablesorter &#8211; http://tablesorter.com/docs/ jQueryUI &#8211; http://jqueryui.com/ bassistance.de Validation &#8211; http://bassistance.de/jquery-plugins/jquery-plugin-validation/ FancyBox &#8211; http://fancybox.net/]]></description>
				<content:encoded><![CDATA[<h3>jQuery</h3>
<ul>
<li>uploadify &#8211; <a href="http://www.uploadify.com">http://www.uploadify.com</a></li>
<li>NIVO Slider &#8211; <a href="http://nivo.dev7studios.com/">http://nivo.dev7studios.com</a></li>
<li>Colortip &#8211; <a href="http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/">http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/</a></li>
<li>Spritely &#8211; <a href="http://spritely.net/">http://spritely.net/</a></li>
<li>Masonry &#8211; <a href="http://desandro.com/resources/jquery-masonry/">http://desandro.com/resources/jquery-masonry/</a></li>
<li>Lettering.JS &#8211; <a href="http://daverupert.com/2010/09/lettering-js/">http://daverupert.com/2010/09/lettering-js/</a></li>
<li>YoxView &#8211; <a href="http://www.yoxigen.com/yoxview/">http://www.yoxigen.com/yoxview/</a></li>
<li>tablesorter &#8211; <a href="http://tablesorter.com/docs/">http://tablesorter.com/docs/</a></li>
<li>jQueryUI &#8211; <a href="http://jqueryui.com/">http://jqueryui.com/</a></li>
<li>bassistance.de Validation &#8211; <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">http://bassistance.de/jquery-plugins/jquery-plugin-validation/</a></li>
<li>FancyBox &#8211; <a href="http://fancybox.net/">http://fancybox.net/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/12/the-list-of-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Magento config.xml Cron Job</title>
		<link>http://www.spinonesolutions.com/2010/12/magento-config-xml-cron-job/</link>
		<comments>http://www.spinonesolutions.com/2010/12/magento-config-xml-cron-job/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 15:00:27 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cron]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=606</guid>
		<description><![CDATA[It&#8217;s possible to setup process to run on a schedule provided that your server is setup to run cron. All internal cron jobs are run from a single page/script call. You&#8217;ll need to setup your server to either; make a request to /cron.php or execute /cron.sh. The time delta that you set here will be [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s possible to setup process to run on a schedule provided that your server is setup to run cron.  All internal cron jobs are run from a single page/script call.  You&#8217;ll need to setup your server to either; make a request to <strong>/cron.php</strong> or execute <strong>/cron.sh</strong>.</p>
<p>The time delta that you set here will be the minimum delta for your Magento jobs.  IE: If your server&#8217;s cron  requests <strong>/cron.php</strong> every ten minutes and you create a cron job within Magento to run every five minutes, you shouldn&#8217;t be surprised to see it running every ten minutes instead of every five.</p>
<p>This won&#8217;t be a huge deal for all of you who are administering your own box, but for those of you on a shared box; you&#8217;ll likely be limited to a certain minimum delta which you&#8217;ll want to be aware of.</p>
<p>Setting up a cron job is actually really simple so lets take a look.  The configuration lives in <strong>config.xml</strong>, which shouldn&#8217;t be a surprise for you module developers.  Using my default example module <strong>Spinonesolutions_Helloworld:</strong></p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/etc/config.xml (partial)</strong></p>
<pre class="xml" name="code">&lt;config&gt;
...
&lt;crontab&gt;
&lt;jobs&gt;
&lt;spinonesolutions_helloworld&gt;
&lt;schedule&gt;&lt;cron_expr&gt;*/10 * * * *&lt;/cron_expr&gt;&lt;/schedule&gt;
&lt;run&gt;&lt;model&gt;spinonesolutions_helloworld/observer::foobar&lt;/model&gt;&lt;/run&gt;
&lt;/spinonesolutions_helloworld&gt;
&lt;/jobs&gt;
&lt;/crontab&gt;
...
&lt;/config&gt;</pre>
<p>You can do a Google search on cron schedules in order to figure that part out, it&#8217;s outside the scope of this article.  The only other piece that deserves explanation is the static method call between the <strong>run</strong> tag.  As you&#8217;d expect my example call is referencing <strong>Spinonesolutions_Helloworld_Model_Observer</strong> <strong>(/app/code/local/Spinonesolutions/Helloworld/Model/Observer.php).</strong> This file doesn&#8217;t need to contain anything except for a class definition and a static method.</p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/Observer.php</strong></p>
<pre class="php" name="code">&lt;?php
class Spinonesolutions_Helloworld_Model_Observer {
  public static function foobar() {
  }
}</pre>
<p>That&#8217;s it.  Your static method will now be called on the schedule that you set!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/12/magento-config-xml-cron-job/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Magento SQL Setup</title>
		<link>http://www.spinonesolutions.com/2010/11/magento-sql-setup/</link>
		<comments>http://www.spinonesolutions.com/2010/11/magento-sql-setup/#comments</comments>
		<pubDate>Mon, 29 Nov 2010 15:00:31 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=604</guid>
		<description><![CDATA[One of the many aspects to good module development is packaging everything up in such a way that the module is as standalone as possible.  The goal is to provide a third-party with a single package that can take care of itself.  Many modules will make use of custom database tables and/or Magento storage mechanisms. [...]]]></description>
				<content:encoded><![CDATA[<p>One of the many aspects to good module development is packaging everything up in such a way that the module is as standalone as possible.  The goal is to provide a third-party with a single package that can take care of itself.  Many modules will make use of custom database tables and/or Magento storage mechanisms.</p>
<p>The Varien team has provided ways for your module to manage these stores automatically through the &#8220;setup&#8221; functionality.  Let&#8217;s check it out.</p>
<p>First, you have to let Magento know where your setup code is going to live and what version your module is currently at.  You do this in <strong>config.xml. </strong> As an example I&#8217;ll use a module called Helloworld.  You may recognize this Module from the <a title="Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">first article</a>.</p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/etc/config.xml (partial)</strong></p>
<pre class="xml" name="code">&lt;global&gt;
...
&lt;spinonesolutions_helloworld_setup&gt;
&lt;setup&gt;
&lt;module&gt;Spinonesolutions_Helloworld&lt;/module&gt;
&lt;/setup&gt;
&lt;/spinonesolutions_helloworld_setup&gt;
...
&lt;/global&gt;</pre>
<p>The <strong>setup</strong> tag is going to cause Magento to look for a folder within the module called ..<strong>/sql/setup (/Spinonesolutions/Helloworld/sql/setup).</strong> We can change the name of the target folder by changing the tag.  Example: <strong>&lt;foobar_setup&gt;&lt;/foobar_setup&gt;</strong> would prompt Magento to look for ..<strong>/sql/foobar_setup</strong>.</p>
<p>The files that fall within this folder need to follow a strict naming scheme:</p>
<p><strong>mysql4-install-{version}.php</strong></p>
<p><strong>mysql4-upgrade-{versionFrom}-{versionTo}.php</strong></p>
<p>What happens is that Magento will run each file, in succession, until it reaches the version number specified in your <strong>config.xml</strong>.</p>
<p>If you ever need to check to see what version of a module Magento THINKS is installed, browse your database for the table <strong>core_resource</strong> and scan the <strong>codes</strong> till you find your module&#8217;s <strong>code</strong>.</p>
<p>If you ever need to have Magento re-run your setup scripts, just remove the entry from <strong>core_resource</strong> and refresh; the module will then be &#8220;reinstalled&#8221;.</p>
<p>Now lets take a look at some common things to do in a install/upgrade script.  One of the best resources for figuring this stuff out is Varien&#8217;s own codebase.  If you go through some modules in <strong>../core/Mage</strong> you&#8217;ll find all sorts of great material  to copy into your own module.</p>
<h2>Install/Update Wrapper</h2>
<p><strong>../sql/setup/mysql4-install-1.0.0.php</strong></p>
<pre class="php" name="code">&lt;?php
$installer = $this;
/* @var $installer Mage_Core_Model_Resource_Setup */
$connection = $installer-&gt;getConnection();
/* @var $connection Varien_Db_Adapter_Pdo_Mysql */

$installer-&gt;startSetup();
YOUR CODE GOES HERE

$installer-&gt;endSetup();</pre>
<h2>DataBase Table</h2>
<pre name="code" class="php">$installer-&gt;run("
DROP TABLE IF EXISTS {$installer-&gt;getTable('spinonesolutions_helloworld/foo')};
CREATE TABLE {$installer-&gt;getTable('spinonesolutions_helloworld/foo')} (
id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
created_at DATETIME NOT NULL,
modified_at DATETIME NOT NULL,
store_id int(5) UNSIGNED NOT NULL,
PRIMARY KEY (id)
)
ENGINE = InnoDB;
");</pre>
<p>Not much to explain other than the <strong>getTable</strong> function.  The parameter refers to <strong>config.xml -&gt; global -&gt; models -&gt; {resourceModel} -&gt; entities</strong>.</p>
<p><strong>/app/code/local/Spinonesolutions/Helloworld/etc/config.xml (partial)</strong></p>
<pre class="xml" name="code">...
&lt;global&gt;
&lt;models&gt;
...
&lt;spinonesolutions_helloworld&gt;
&lt;class&gt;Spinonesolutions_Helloworld&lt;/class&gt;
&lt;resourceModel&gt;spinonesolutions_helloworld_mysql4&lt;/resourceModel&gt;
&lt;/spinonesolutions_helloworld&gt;
&lt;toms_bluehornet_mysql4&gt;
&lt;class&gt;Spinonesolutions_Helloworld_Model_Mysql4&lt;/class&gt;
&lt;entities&gt;
&lt;foo&gt;&lt;table&gt;spinonesolutions_helloworld_foo&lt;/table&gt;&lt;/foo&gt;
&lt;/entities&gt;
&lt;/toms_bluehornet_mysql4&gt;
...
&lt;/models&gt;
&lt;/global&gt;
...</pre>
<h2>New Attribute</h2>
<pre class="php" name="code">$installer-&gt;addAttribute('catalog_product', 'is_recurring', array(
'group'             =&gt; 'Recurring Profile',
'type'              =&gt; 'int',
'backend'           =&gt; '',
'frontend'          =&gt; '',
'label'             =&gt; 'Enable Recurring Profile',
'note'              =&gt; 'Products with recurring profile participate in catalog as nominal items.',
'input'             =&gt; 'select',
'class'             =&gt; '',
'source'            =&gt; 'eav/entity_attribute_source_boolean',
'global'            =&gt; Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'visible'           =&gt; true,
'required'          =&gt; false,
'user_defined'      =&gt; false,
'default'           =&gt; '',
'searchable'        =&gt; false,
'filterable'        =&gt; false,
'comparable'        =&gt; false,
'visible_on_front'  =&gt; false,
'unique'            =&gt; false,
'apply_to'          =&gt; 'simple,virtual',
'is_configurable'   =&gt; false
));</pre>
<h2>Mage_Eav_Model_Entity_Setup</h2>
<p><strong>Mage_Eav_Model_Entity_Setup</strong> has tons of useful methods to call from your setup script.  The installer itself is an object of type <strong>Mage_Catalog_Model_Resource_Eav_Mysql4_Setup</strong> which extends <strong>Mage_Eav_Model_Entity_Setup</strong> thus all the instance methods are available from <strong>$this</strong> or <strong>$installer </strong>if you use a wrapper like the one shown above.</p>
<p>Questions and comments welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/11/magento-sql-setup/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Drupal json_server Bug Fix</title>
		<link>http://www.spinonesolutions.com/2010/11/drupal-json_server-bug-fix/</link>
		<comments>http://www.spinonesolutions.com/2010/11/drupal-json_server-bug-fix/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 15:00:32 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[json_server]]></category>
		<category><![CDATA[services]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=600</guid>
		<description><![CDATA[I wanted to use the json_server module in conjunction with Drupal&#8217;s services module to enable JSON communications instead of just XMLRPC.  I ran into a couple of issues however: first, the JSON packet wasn&#8217;t being encoded correctly and second, the &#8216;#&#8217; in the array keys was causing issues with the array lookups. I ended up [...]]]></description>
				<content:encoded><![CDATA[<p>I wanted to use the <a href="http://drupal.org/project/json_server">json_server</a> module in conjunction with Drupal&#8217;s <a href="http://drupal.org/project/services">services</a> module to enable JSON communications instead of just XMLRPC.  I ran into a couple of issues however: first, the JSON packet wasn&#8217;t being encoded correctly and second, the &#8216;#&#8217; in the array keys was causing issues with the array lookups.</p>
<p>I ended up writing a super simple module that overrides json_server and corrects the issues.</p>
<p>If you compare the two module&#8217;s contents you&#8217;ll see I only made a couple of really minor tweaks.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/spinonesolutions.rar">You can download it here.</a></p>
<h2>Install</h2>
<p>Download and extract.</p>
<p>Copy the module folder to <strong>/sites/all/modules</strong> or <strong>/sites/{preferred-site}/modules</strong>.</p>
<p>Navigate to Site Building -&gt; Modules.</p>
<p>Scroll down to SpinOneSolutions -&gt; JSON Server and Enable.</p>
<p>Hit Save</p>
<p>Developed on Drupal 6.16</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/11/drupal-json_server-bug-fix/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Magento Custom Widget</title>
		<link>http://www.spinonesolutions.com/2010/10/magento-custom-widget/</link>
		<comments>http://www.spinonesolutions.com/2010/10/magento-custom-widget/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 17:00:24 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Module]]></category>
		<category><![CDATA[Widget]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=602</guid>
		<description><![CDATA[With the latest release of Magento admins now have the ability to create custom “widgets” that can be dropped anywhere on the site to provide additional functionality.  The most common type of widget that I come across is a simple frontend presentation widget.  Basically the developer is asked to display some sort of data in [...]]]></description>
				<content:encoded><![CDATA[<p>With the latest release of Magento admins now have the ability to create custom “widgets” that can be dropped anywhere on the site to provide additional functionality.  The most common type of widget that I come across is a simple frontend presentation widget.  Basically the developer is asked to display some sort of data in a new way.</p>
<p>Widgets can basically be thought of as easily customizable blocks.  The main difference between standard blocks and widgets is that widgets can be added to CMS pages through the WYSIWYG editor and they can easily accept parameters, also defined through the WYSIWYG.  Thus a non-programmer can add quasi-dynamic content to their CMS pages, hurrah!</p>
<p>You should reference previous articles if you want more details about creating custom Modules and Blocks.</p>
<p>As an example I’m going to build a super simple slideshow widget called “Glider”.  It’s going to be a widget that takes four static block_id(s) as parameters and then displays each static block, in succession, as a slideshow.  If you let your imagination work a little you should be able to see some cool possibilities for such a thing, given that you extend it a little.</p>
<p>I’m using static blocks as the source material for each slide because this would allow a content manager to change out the content of a slide by either editing the static block that contains the content or by editing the block id being passed to the widget.  Either way it’s manageable through the interface.</p>
<p>Also note that the template (presentation layer) is going to be statically defined in this example, but you could easily make that a parameter and create multiple templates for the content manager to choose from!</p>
<p>Finally, I’ve used jQuery to build the actual slideshow.  I’m not going to go into very much detail about the presentation of the slideshow as that’s not really the focus of this article.  Feel free to write in if you want to see the details on how to implement jQuery (or any other script).</p>
<p>First let’s setup the Module:</p>
<p><strong>/app/etc/modules/Spinonesolutions_WidgetGlider.xml</strong></p>
<pre class="xml" name="code">&lt;?xml version="1.0"?&gt;
 &lt;config&gt;
 &lt;modules&gt;
 &lt;Spinonesolutions_WidgetGlider&gt;
   &lt;active&gt;true&lt;/active&gt;
   &lt;codePool&gt;local&lt;/codePool&gt;
   &lt;depends&gt;
     &lt;Mage_Cms /&gt;
   &lt;/depends&gt;
 &lt;/Spinonesolutions_WidgetGlider&gt;
 &lt;/modules&gt;
 &lt;/config&gt;</pre>
<p><strong>/app/code/local/Spinonesolutions/WidgetGlider/etc/config.xml</strong></p>
<pre class="xml" name="code">&lt;?xml version="1.0"?&gt;
 &lt;config&gt;
 &lt;modules&gt;
 &lt;Spinonesolutions_WidgetGlider&gt;
   &lt;version&gt;1.0.0&lt;/version&gt;
 &lt;/Spinonesolutions_WidgetGlider&gt;
 &lt;/modules&gt;
 &lt;global&gt;
 &lt;blocks&gt;
   &lt;spinonesolutions_widgetglider&gt;
     &lt;class&gt;Spinonesolutions_WidgetGlider_Block&lt;/class&gt;
   &lt;/spinonesolutions_widgetglider&gt;
 &lt;/blocks&gt;
 &lt;/global&gt;
 &lt;/config&gt;</pre>
<p>OK!  The next thing we need to do is define our widget’s interface.  To do that we create a <strong>widget.xml</strong> file inside our module’s “etc” folder.</p>
<p><strong>/app/code/local/Spinonesolutions/WidgetGlider/etc/widget.xml</strong></p>
<pre class="xml" name="code">&lt;?xml version="1.0"?&gt;
&lt;widgets&gt;
&lt;glider type="spinonesolutions_widgetglider/glider"&gt;
   &lt;name&gt;SpinoneSolutions: Glider&lt;/name&gt;
   &lt;description&gt;Displays the given HTML Sections in a Glider Slideshow&lt;/description&gt;
   &lt;parameters&gt;
     &lt;section1&gt;
       &lt;required&gt;0&lt;/required&gt;
       &lt;visible&gt;1&lt;/visible&gt;
       &lt;label&gt;Section1&lt;/label&gt;
       &lt;type&gt;text&lt;/type&gt;
     &lt;/section1&gt;
     &lt;section2&gt;
       &lt;required&gt;0&lt;/required&gt;
       &lt;visible&gt;1&lt;/visible&gt;
       &lt;label&gt;Section2&lt;/label&gt;
       &lt;type&gt;text&lt;/type&gt;
     &lt;/section2&gt;
     &lt;section3&gt;
       &lt;required&gt;0&lt;/required&gt;
       &lt;visible&gt;1&lt;/visible&gt;
       &lt;label&gt;Section3&lt;/label&gt;
       &lt;type&gt;text&lt;/type&gt;
     &lt;/section3&gt;
     &lt;section4&gt;
       &lt;required&gt;0&lt;/required&gt;
       &lt;visible&gt;1&lt;/visible&gt;
       &lt;label&gt;Section4&lt;/label&gt;
       &lt;type&gt;text&lt;/type&gt;
     &lt;/section4&gt;
     &lt;template&gt;
       &lt;visible&gt;0&lt;/visible&gt;
       &lt;value&gt;widgetglider/banner.phtml&lt;/value&gt;
     &lt;/template&gt;
   &lt;/parameters&gt;
&lt;/glider&gt;
&lt;/widgets&gt;</pre>
<p>You can define any number of widgets in here.  We’re only creating one so I’ve only got a single entry, <strong>glider</strong>.</p>
<p>The <strong>type</strong> attribute tells Magento what class to use when instantiating objects.  I’ve set it as <strong>spinonesolutions_widgetglider/glider</strong>.  If you go back and inspect the config.xml and remember your Magento naming conventions you can surmise that this is going to cause Magento to try and instantiate an object of type <strong>Spinonesolutions_WidgetGlider_Block_Glider</strong>.  That class doesn’t exist yet so we should create it.</p>
<p><strong>/app/code/local/Spinonesolutions/WidgetGlider/Block/Glider.php</strong></p>
<pre class="php" name="code">&lt;?php
class Spinonesolutions_WidgetGlider_Block_Glider extends Mage_Core_Block_Template
implements Mage_Widget_Block_Interface {
  const MAXSECTIONS = 4;
  public $sectionArr = array();

  protected function _construct() {
    parent::_construct();
  }

  protected function _toHtml() {
    for ($i=1;$i &lt;= self::MAXSECTIONS;$i++) {
      if ($this-&gt;getData("section$i")) {
        $blockHTML = $this-&gt;getLayout()-&gt;createBlock('cms/block')-&gt;setBlockId($this-&gt;getData("section$i"))-&gt;toHtml();
        $this-&gt;sectionArr[$i] = $blockHTML;
      }
    }
    return parent::_toHtml();
  }
}</pre>
<p>Let’s inspect the class from top to bottom.  The first thing to notice is that in the declaration it implements <strong>Mage_Widget_Block_Interface</strong>.  This is a requirement for Widgets.</p>
<p>Notice my constant <strong>MAXSECTIONS</strong> is set to 4, the same number of section parameters that I defined in widget.xml.  There’s probably some room for improvement here: one could probably figure out the number of parameters dynamically and then remove the constant.  That would make the widget more flexible for future uses.</p>
<p>I call the <strong>_construct</strong> function so that everything gets setup the way it’s supposed to.</p>
<p>Finally the real work gets done in <strong>_toHtml</strong>.  This function will be called automagically by Magento when it goes to render this object to the screen.</p>
<p>What I do is load up each block that gets passed into the widget and I stuff it’s HTML into an array element.  This way the widget can render any block, independently, by referencing a key in the array.</p>
<p>It’s not the classes job to do the rendering, that’s left to the presentation layer.  This class is just gathering everything that the presentation layer needs.</p>
<p>To move on with the tutorial we need to look back at our widget declaration in <strong>widget.xml</strong>.  I’m sure you noticed the last parameter <strong>template</strong> that I haven’t discussed yet.  Notice that the attribute <strong>visible</strong> is set to false.  What this parameter does is define the template that our widget is going to use for presentation.  My value is <strong>widgetglider/banner.phtml</strong> this template doesn’t exist by default so let’s create it.</p>
<p><strong>/app/design/frontend/default/spinonesolutions/template/widgetglider/banner.phtml</strong></p>
<pre class="php" name="code">&lt;style&gt;
.slideshow {
  position:relative;
}

.slideshow .items div {
  float:left;
  opacity:0.0;
  position:absolute;
  z-index:8;
}

.slideshow .items div.active {
  opacity:1.0;
  z-index:10;
}
&lt;/style&gt;

&lt;script&gt;
function slideSwitch() {
  var active = jQuery('.slideshow .items .active');
  // use this to pull the images in the order they appear in the markup
  var next =  jQuery(active).next().length ? jQuery(active).next() : jQuery('.slideshow .items div:first');
  jQuery(next).css({opacity: 0.0})
  .addClass('active')
  .animate({opacity: 1.0}, 1000, function() {
    jQuery(active).removeClass('active');
  });

  jQuery(active).animate({opacity:0.0}, 1000, function(){
  });
}

// execute your scripts when the DOM is ready. this is mostly a good habit
jQuery('document').ready(function() {
  var active = jQuery('.slideshow .items .active');
  if ( active.length == 0 ) {
    active = jQuery('.slideshow .items div:first');
    active.addClass('active').animate({opacity: 1.0}, 1000);
  }

  jQuery(function() {
    setInterval( "slideSwitch()", 5000 );
  });
});
&lt;/script&gt;
&lt;div class="slideshow"&gt;
  &lt;div class="items"&gt;
    &lt;?php foreach($this-&gt;sectionArr as $key =&gt; $section) { ?&gt;
    &lt;div class=""&gt;
      &lt;?php echo $section; ?&gt;
    &lt;/div&gt;
    &lt;?php } ?&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre>
<p>The first part of that path is determined by the theme that you’ve set in Configuration.</p>
<p>Inspecting this file the real takeaway is simply the foreach loop.  All it does it loop over the array that was defined in the Business Layer and output the HTML stored in each element.  The template file does all the presentation.</p>
<p>The reason for doing things this way is that one can easily envision some department manager coming to you and asking for another, different, presentation of the same data for some other location of your website.  Since you’ve done a good job of separating your layers all you have to do is make a new .phtml file, and then change the <strong>template</strong> parameter of your <strong>widget.xml</strong> file and viola, you’ve got a new presentation of your data.</p>
<p>That does it for the code, all we need to do now is build a little demo using the interface.</p>
<p>Load up the admin and navigate to CMS -&gt; Static Blocks.  Create four static blocks and put an image file into each one.  If you hover your mouse over the row you’ll see the block_id.  Make note of these as you’ll need them for when you create the widget.  Mine are: 6,8,9,10.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/static-blocks.png"><img class="aligncenter size-medium wp-image-624" title="static-blocks" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/static-blocks-700x69.png" alt="static-blocks" width="700" height="69" /></a></p>
<p>Go to CMS -&gt; Pages and create a new CMS page to hold the widget.  Alternatively you could add the widget to a preexisting page.  Switch to the Content Tab.  Click the add Widget icon to add your widget.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/add-widget-button.png"><img class="aligncenter size-full wp-image-625" title="add-widget-button" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/add-widget-button.png" alt="add-widget-button" width="97" height="104" /></a></p>
<p>Choose your new widget from the dropdown menu.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/insert-widget-choose.png"><img class="aligncenter size-medium wp-image-626" title="insert-widget-choose" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/insert-widget-choose-700x356.png" alt="insert-widget-choose" width="700" height="356" /></a></p>
<p>Fill in the block_id(s) of your static blocks.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/insert-widget-filledin.png"><img class="aligncenter size-medium wp-image-627" title="insert-widget-filledin" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/insert-widget-filledin-700x360.png" alt="insert-widget-filledin" width="700" height="360" /></a></p>
<p>Hit Insert.</p>
<p>As a learning exercise click the “Show/HideEditor” button.</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/widget-markup.png"><img class="aligncenter size-medium wp-image-628" title="widget-markup" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/widget-markup-700x114.png" alt="widget-markup" width="700" height="114" /></a></p>
<p>Notice what was generated!  It should be pretty similar to what’s in your <strong>widget.xml</strong> file.  As the smart and curious type the you are also realize that you can change these parameters right here.  Thus the widget.xml file serves a template for your widget, which can be customized later to suit your specific needs.</p>
<p>Ok, save your CMS page.  That’s it!</p>
<p><a href="http://www.spinonesolutions.com/wp-content/uploads/2010/10/glider-demo.png"><img class="aligncenter size-medium wp-image-629" title="glider-demo" src="http://www.spinonesolutions.com/wp-content/uploads/2010/10/glider-demo-700x535.png" alt="glider-demo" width="700" height="535" /></a></p>
<p>You can see my <a title="Glider Demo" href="http://magento.spinonesolutions.com/glider-demo" target="_blank">demo here</a>.</p>
<p>As always, questions and comments welcomed!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/10/magento-custom-widget/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Magento CMS Tags (Directives)</title>
		<link>http://www.spinonesolutions.com/2010/04/magento-cms-tags-directives/</link>
		<comments>http://www.spinonesolutions.com/2010/04/magento-cms-tags-directives/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 15:00:57 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[CMS]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=575</guid>
		<description><![CDATA[Here is, I think, a comprehensive list of tags (directives) available for use within the Magento CMS.  You can use these either in static blocks or CMS pages. Magento: Enterprise ver 1.6.0.0 block Description Outputs a virgin block or loads a defined block. Parameters type : Type of block to be created. id : Id [...]]]></description>
				<content:encoded><![CDATA[<p>Here is, I think, a comprehensive list of tags (directives) available for use within the Magento CMS.  You can use these either in static blocks or CMS pages.</p>
<p>Magento: Enterprise ver 1.6.0.0</p>
<h2>block</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs a virgin block or loads a defined block.</p>
<p><span style="text-decoration: underline;">Parameters</span><br />
<strong>type : </strong>Type of block to be created.<br />
<strong>id : </strong>Id of block to be created.<br />
<strong>output : </strong>The block instance method to call after creation.  If blank &#8220;toHtml()&#8221; will be called by default.<br />
<strong>&lt;parameter&gt; : </strong>Any additional parameters will get key value pairs set in the block&#8217;s Data array.</p>
<p><span style="text-decoration: underline;">Usage</span><br />
{{block type=&#8221;cms/block&#8221;}}<br />
Results in a virgin static block with no data.</p>
<p>{{block id=&#8221;myBlock&#8221;}}<br />
Results in an instance of <strong>myBlock</strong>.</p>
<p>{{block id=&#8221;myBlock&#8221; param1=&#8221;foo&#8221; param2=&#8221;bar&#8221;}}<br />
Results in an instance of <strong>myBlock</strong> with a data array containing key value pairs param1=&gt;&#8221;foo&#8221; param2=&gt;&#8221;bar&#8221;.</p>
<p>{{block id=&#8221;myBlock&#8221; output=&#8221;myMethod&#8221;}}<br />
Results in an instance of <strong>myBlock</strong> after it has called member method <strong>myMethod</strong>.</p>
<p>Note that if you already HAVE a block with this particular ID than it will be loaded.  This is great if you want to include a static block into a CMS page or into another static block!  Just create the block in the CMS section of admin and use the ID that you set.</p>
<p>Any parameter that your block class is sensitive too will work as well.  For example:</p>
<p>{{block id=&#8221;myBlock&#8221; template=&#8221;customfolder/customTemplate.phtml&#8221;}}<br />
Results in an instance of <strong>myBlock</strong> using a custom template.</p>
<h2>layout</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs the contents of the defined layout.</p>
<p><span style="text-decoration: underline;">Parameters<br />
</span><strong>area : </strong>The<strong> </strong>area to load.  If blank the layout&#8217;s default area will be used.<br />
<strong>handle : </strong>The layout handle to load.<br />
<strong>&lt;parameter&gt; : </strong>Any additional parameters will get key value pairs set in the layout&#8217;s Data array.</p>
<p><span style="text-decoration: underline;">Usage<br />
</span>{{layout handle=&#8221;default&#8221;}}<br />
Outputs the <strong>default</strong> layout handle.</p>
<h2>skin</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs the url for a resource in the current skin.</p>
<p><span style="text-decoration: underline;">Parameters<br />
</span><strong>url : </strong>The url to reference within the current skin directory.<br />
<strong>&lt;parameter&gt; : </strong>Any additional parameters will be passed to the getSkinUrl() method.</p>
<p><span style="text-decoration: underline;">Usage</span><br />
{{skin url=&#8221;images/myimage.gif&#8221;}}<br />
Outputs: http://www.mydomain.com/skin/frontend/default/default/images/myimage.gif<br />
Note: This assumes the current theme and skin are default.</p>
<h2>media</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs the Base Media URL.</p>
<p><span style="text-decoration: underline;">Parameters<br />
</span><strong>url : </strong>The url to prefix with the base media url.</p>
<p><span style="text-decoration: underline;">Usage</span><br />
{{media url=&#8221;images/myimage.gif&#8221;}}<br />
Outputs: http://www.mydomain.com/media/images/myimage.gif<br />
Note: This assumes Base Media URL is set to http://www.mydomain.com/media (See Admin-&gt;Configuration-&gt;Web)</p>
<h2>store</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs the store specific Base URL.</p>
<p><span style="text-decoration: underline;">Parameters<br />
</span><strong>direct_url : </strong>The url to prefix with the Base URL.  Note this method does NOT assume internal routing.<br />
<strong>url : </strong>The url to prefix with the Base URL.  Note this method DOES assume internal routing.<br />
<strong>&lt;parameter&gt; : </strong>Any additional parameters will be passed to the getSkinUrl() method.</p>
<p><span style="text-decoration: underline;">Usage<br />
</span>{{store direct_url=&#8221;images/myimage.gif&#8221;}}<br />
Outputs: http://www.mydomain.com/images/myimage.gif</p>
<p>{{store url=&#8221;mens&#8221;}}<br />
Outputs: http://www.mydomain.com/mens/</p>
<p>Note that the Base URL can be different in a multistore setup.</p>
<h2>htmlescape</h2>
<p><span style="text-decoration: underline;">Parameters<br />
</span><strong>var : </strong>The string to be html escaped.<br />
<strong>allowed_tags : </strong>Tags to be allowed in the escaped string</p>
<p><span style="text-decoration: underline;">Usage</span><br />
{{htmlescape var=&#8221;&lt;a href=&#8217;#'&gt;Click Here&lt;/a&gt;&#8221;}}<br />
Outputs: &lt;a href=&#8217;#'&gt;Click Here&lt;/a&gt;<br />
Note: The string is escaped so that the browser does not interpret it as HTML, instead it&#8217;s displayed as a human readable string.</p>
<h2>var</h2>
<p><span style="text-decoration: underline;">Description<br />
</span>Outputs template variables.</p>
<p><span style="text-decoration: underline;">Parameters</span><br />
<strong>variable</strong> : The variable being requested</p>
<p><span style="text-decoration: underline;">Usage<br />
</span>{{var myVariable}<br />
Outputs: Value stored in <strong>myVariable</strong></p>
<h2>protocol</h2>
<p><span style="text-decoration: underline;">Description</span><br />
Outputs the proper protocol (HTTP or HTTPS) depending on current context OR outputs the desired url based on the current protocol.</p>
<p><span style="text-decoration: underline;">Parameters</span><br />
<strong>store : </strong>The desired store<br />
<strong>url : </strong>The url to prefix with the proper protocol<br />
<strong>http : </strong>The url to use if the current protocol is HTTP<br />
<strong>https:</strong> The url to use if the current protocol is HTTPS</p>
<p><span style="text-decoration: underline;">Usage</span><br />
{{protocol url=&#8221;www.mydomain.com/images/checkout/cart.gif&#8221;}}<br />
Outputs: http://www.mydomain.com/images/checkout/cart.gif IF current protocol is HTTP<br />
Outputs: https://www.mydomain.com/images/checkout/cart.gif IF current protocol is HTTPS</p>
<p>{{protocol http=&#8221;http://unsecure.mydomain.com/images/checkout/cart.gif&#8221; https=&#8221;https://secure.mydomain.com/images/checkout/cart.gif&#8221;}}<br />
Outputs: http://unsecure.mydomain.com/images/checkout/cart.gif IF current protocol is HTTP<br />
Outputs: https://secure.mydomain.com/images/checkout/cart.gif IF current protocol is HTTPS</p>
<p>All of these directives are defined in Mage/Core/Model/Email/Template/Filter.php should you want to explore them further.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/04/magento-cms-tags-directives/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PS3 H264/AAC 5.1 Encoding with FFmpeg</title>
		<link>http://www.spinonesolutions.com/2010/04/ps3-h264aac-5-1-encoding-with-ffmpeg/</link>
		<comments>http://www.spinonesolutions.com/2010/04/ps3-h264aac-5-1-encoding-with-ffmpeg/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 17:00:06 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Audio/Video]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[PS3]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=434</guid>
		<description><![CDATA[The Problem: You want to encode video for playback on a PS3 using FFmpeg. The Solution: I&#8217;ve got a working command line option for you right here.  This is a solution, not the only solution. My Setup: Ubuntu 9.10 (Karmic) libx264 (for encoding H264) libfaac (for encoding AAC) mkvtoolnix ffmpeg fuppes I&#8217;m also going to [...]]]></description>
				<content:encoded><![CDATA[<h3>The Problem:</h3>
<p>You want to encode video for playback on a PS3 using FFmpeg.</p>
<h3>The Solution:</h3>
<p>I&#8217;ve got a working command line option for you right here.  This is <em>a</em> solution, not the <em>only</em> solution.</p>
<p>My Setup:<br />
Ubuntu 9.10 (Karmic)<br />
libx264 (for encoding H264)<br />
libfaac (for encoding AAC)<br />
mkvtoolnix<br />
ffmpeg<br />
fuppes</p>
<p>I&#8217;m also going to assume that your input file is a .mkv containing an H264 video track and an AC-3 audio track.  Most of the time this is fair assumption however, it won&#8217;t be correct 100% of the time.</p>
<p>To start, you&#8217;re going to need a current build of FFmpeg. It&#8217;s been a while since I did the build but I <em>think</em> these were my configuration options.</p>
<pre class="xml" name="code">#cd ~/ffmpeg #make distclean
#svn update #sudo ./configure \
--enable-gpl \
--enable-nonfree \
--enable-postproc \
--enable-pthreads \
--enable-x11grab \
--enable-runtime-cpudetect \
--enable-libdc1394 \
--enable-libfaac \
--enable-libfaad \
--enable-libgsm \
--enable-libmp3lame \
--enable-libtheora \
--enable-libvorbis \
--enable-libx264 \
--enable-libxvid \
--arch=x86_64
#make #sudo checkinstall \
--ftrans=no \
--install=yes \
--pkgname=ffmpeg \
--pkversion "4:0.5.svn'date + %Y%m%d'-12ubuntu3" \
--default</pre>
<p>On to what you REALLY wanted to know, here&#8217;s my command sequence.</p>
<pre class="xml" name="code">#mkvextract tracks {input-file}.mkv 1:video.h264
#mkvextract tracks {input-file}.mkv 2:audio.ac3
#ffmpeg -i video.h264 -i audio.ac3 \
-vcodec copy \
-acodec libfaac -ab 320k -ac 6 \
-threads 0 -f mp4 \
{output-file-name}.mp4</pre>
<p>Let&#8217;s break it down line by line so that you can modify it to your needs:<br />
<strong>mkvextract tracks {input-file}.mkv 1:video.h264</strong></p>
<p>Extract track 1 to &#8220;video.h264&#8243;</p>
<p><strong><strong>mkvextract tracks {input-file}.mkv 2:audio.ac3</strong></strong></p>
<p>Extract track 2 to &#8220;audio.ac3&#8243;</p>
<p><strong>ffmpeg -i video.h264 -i audio.ac3</strong></p>
<p>Input video.h264<br />
Input audio.ac3</p>
<p><strong>-vcodec copy</strong></p>
<p>Copy the video track as is.</p>
<p><strong>-acodec libfaac -ab 320k -ac 6</strong></p>
<p>Transform audio track to AAC using libfaac<br />
Set Audio Bitrate to 320k<br />
Set Audio Channels to 6 (5.1)</p>
<p><strong>-threads 0 -f mp4</strong></p>
<p>Let ffmpeg decide how many threads to use<br />
Set the container format to mp4</p>
<p><strong>{output-file-name}.mp4</strong></p>
<p>Output the file as specified</p>
<p>Checkout the ffmpeg <a title="ffmpeg documentation" href="http://ffmpeg.org/ffmpeg-doc.html">documentation</a> for more information about general options.</p>
<p>I donno about you, but I got tired of typing out three commands for every file I wanted to encode, plus all those options&#8230; forget about it!  So I wrote a stupid little shell script to do it for me.</p>
<p>You can download it here: <a href="http://www.spinonesolutions.com/wp-content/uploads/2010/04/ps3encode.gz">ps3encode</a>.  Just plop it somewhere in your filesystem and then make sure it&#8217;s included in your PATH variable and that it has execute permissions.</p>
<p>Usage:</p>
<pre class="xml" name="code">#ps3encode {input-file}.mkv {output-file}.mp4</pre>
<p class="xml">Questions and comments welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/04/ps3-h264aac-5-1-encoding-with-ffmpeg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
