theoleschool - commerce http://theoleschool.com/tags/commerce en Templating the Commerce Order Completion Pane http://theoleschool.com/blog/templating-commerce-order-completion-pane <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>I recently found myself working on a fairly simple Drupal Commerce site. There weren't a lot of tricks to it, just a few items and an "express" checkout. So I fired up the <a href="http://drupal.org/project/commerce_kickstart">Commerce Kickstart</a> profile and after a few small tweaks, had it just about right. As we approached the theme, it became obvious that the commerce completion pane was going to take a lot of love. The designers had given us a unique layout for how this page should appear, complete with order specific information displayed in a kaleidoscope of containers. This was going to take some markup, and my first thought was, "it sure would be nice to template this."</p><!--break--> <p>Turns out that's a fairly simple task thanks to <a href="http://api.drupalcommerce.org/api/Drupal%20Commerce/sites!all!modules!commerce!modules!checkout!commerce_checkout.api.php/function/hook_commerce_checkout_pane_info_alter/DC">hook_commerce_checkout_pane_info_alter</a>. The function passes the variable <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #000088;">$checkout_panes</span></code></span> by reference which contains an array of checkout pane arrays. This function is going to allow us to redefine the function that the checkout completion pane is looking to for output. This will look something like:</p> <div class="geshifilter"><div class="drupal6 geshifilter-drupal6" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> my_module_commerce_checkout_pane_info_alter<span style="color: #66cc66;">(</span><span style="color: #66cc66;">&amp;</span><span style="color: #0000ff;">$checkout_panes</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span><br />   <span style="color: #b1b100;">if</span><span style="color: #66cc66;">(</span><a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">(</span><span style="color: #0000ff;">$checkout_panes</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'checkout_completion_message'</span><span style="color: #66cc66;">]</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span><br />     <span style="color: #808080; font-style: italic;">// forget the original include file                     </span><br />     <a href="http://www.php.net/unset"><span style="color: #000066;">unset</span></a><span style="color: #66cc66;">(</span><span style="color: #0000ff;">$checkout_panes</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'checkout_completion_message'</span><span style="color: #66cc66;">]</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'file'</span><span style="color: #66cc66;">]</span><span style="color: #66cc66;">)</span>;<br />     <span style="color: #808080; font-style: italic;">// point at this module</span><br />     <span style="color: #0000ff;">$checkout_panes</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'checkout_completion_message'</span><span style="color: #66cc66;">]</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'module'</span><span style="color: #66cc66;">]</span> = <span style="color: #ff0000;">'my_module'</span>;<br />     <span style="color: #808080; font-style: italic;">// register the new output function</span><br />     <span style="color: #0000ff;">$checkout_panes</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'checkout_completion_message'</span><span style="color: #66cc66;">]</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'base'</span><span style="color: #66cc66;">]</span> = <span style="color: #ff0000;">'my_module_completion_message_pane'</span>;<br />   <span style="color: #66cc66;">}</span><br /><span style="color: #66cc66;">}</span></div></div> <p>The function name we passed above will have <span class="geshifilter"><code class="php geshifilter-php">_checkout_form</code></span> appended. We will need to declare a function to satisfy this and return our output.</p> <div class="geshifilter"><div class="drupal6 geshifilter-drupal6" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> my_module_completion_message_pane_checkout_form<span style="color: #66cc66;">(</span><span style="color: #0000ff;">$form</span>, <span style="color: #66cc66;">&amp;</span><span style="color: #0000ff;">$form_state</span>, <span style="color: #0000ff;">$checkout_pane</span>, <span style="color: #0000ff;">$order</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span><br />   <span style="color: #0000ff;">$pane_form</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>;<br />   <span style="color: #0000ff;">$pane_form</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'message'</span><span style="color: #66cc66;">]</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'#markup'</span> =<span style="color: #66cc66;">&gt;</span> <span style="color: #808080; font-style: italic;">/*markup*/</span><span style="color: #66cc66;">)</span>;<br />   <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$pane_form</span>;<br /><span style="color: #66cc66;">}</span></div></div> <p>From here, we're basically home free. We simply need to replace <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #666666; font-style: italic;">/*markup*/</span></code></span> with the output we desire. Since we are looking to template this, we will need to register a theme implementation for it. The important thing to note is the <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #000088;">$order</span></code></span> variable passed to this function. We'll need that order information in our template, so we pass it along while laying out our <span class="geshifilter"><code class="php geshifilter-php">hook_theme</code></span> call.</p> <div class="geshifilter"><div class="drupal6 geshifilter-drupal6" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> my_module_theme<span style="color: #66cc66;">(</span><span style="color: #0000ff;">$existing</span>, <span style="color: #0000ff;">$type</span>, <span style="color: #0000ff;">$theme</span>, <span style="color: #0000ff;">$path</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span><br />   <span style="color: #b1b100;">return</span> <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><br />     <span style="color: #ff0000;">'my_module_completion'</span> =<span style="color: #66cc66;">&gt;</span> <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><br />       <span style="color: #808080; font-style: italic;">// the template filename, .tpl.php will be appended</span><br />       <span style="color: #ff0000;">'template'</span> =<span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'my_module_completion'</span>,<br />       <span style="color: #808080; font-style: italic;">// include order as a variable in the template</span><br />       <span style="color: #ff0000;">'variables'</span> =<span style="color: #66cc66;">&gt;</span> <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'order'</span> =<span style="color: #66cc66;">&gt;</span> <span style="color: #000000; font-weight: bold;">NULL</span><span style="color: #66cc66;">)</span>,<br />     <span style="color: #66cc66;">)</span>,<br />   <span style="color: #66cc66;">)</span>;<br /><span style="color: #66cc66;">}</span> </div></div> <p>Now that we have a theme implementation that is expecting an order variable, all that remains is to call it as the value for <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #0000ff;">'#markup'</span></code></span> in our output function above.</p> <div class="geshifilter"><div class="drupal6 geshifilter-drupal6" style="font-family:monospace;"><span style="color: #0000ff;">$pane_form</span><span style="color: #66cc66;">[</span><span style="color: #ff0000;">'message'</span><span style="color: #66cc66;">]</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'#markup'</span> =<span style="color: #66cc66;">&gt;</span> <a href="http://api.drupal.org/api/function/theme/6"><span style="color: #000066;">theme</span></a><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'my_module_completion'</span>, <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'order'</span> =<span style="color: #66cc66;">&gt;</span> <span style="color: #0000ff;">$order</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>;</div></div> <p>From here simply create the <span class="geshifilter"><code class="php geshifilter-php">my_module_completion<span style="color: #339933;">.</span>tpl<span style="color: #339933;">.</span>php</code></span> file and theme away! The template will have our order information exposed as the php variable <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #000088;">$order</span></code></span> allowing us to output whatever order information we would like. This is probably a good time to note, that the <span class="geshifilter"><code class="php geshifilter-php"><span style="color: #000088;">$order</span></code></span> variable very well may not be sufficient (it wasn't for us). It contains mostly keys to fetch other bits of data about the order. In our actual implementation we wound up loading the line item (our implementation only allowed one), and some customer information. This can easily be done from the output function you define in <span class="geshifilter"><code class="php geshifilter-php">hook_commerce_checkout_pane_info_alter</code></span> and passed to the template exactly as we did the order variable in this example.</p> <p><em>I admit that this is bordering on being somewhat hackish.</em> I don't think I would take this approach if the Commerce implementation was more complex. If that were the case a better approach may be to <a href="http://api.drupalcommerce.org/api/Drupal%20Commerce/sites%21all%21modules%21commerce%21modules%21checkout%21commerce_checkout.api.php/function/hook_commerce_checkout_pane_info/DC">create a custom checkout pane</a> with the output you would like, assign it to the appropriate checkout pages, and leave the poor checkout completion pane alone. However, in the interest of time and ease in satisfying a theme requirement for a relatively small site, this method worked like a charm. Further, I don't believe that anything has been obfuscated. With some light commenting it should be apparent to anyone who reviews this code, exactly what is going on. With that in mind, take this method as a handy <em>trick</em> if you need to quickly and drastically rework how the checkout completion pane is displayed.</p></div></div></div> Sun, 12 Aug 2012 18:25:26 +0000 rho 161 at http://theoleschool.com