Rowlands Group - Latest Articles http://rowlandsgroup.com/articles/feed en What's happening with Drupal Yarns? http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Just a quick update to all of those who were kind enough to participate in an interview with me during Drupal Downunder 2012 to explain what's happening with Drupal Yarns.</p> <p>I've not forgotten you!</p> <p>Things have changed considerably for Nick and myself, both of us have accepted permanent positions with PreviousNext, Australia's largest Drupal Firm. As a result Rowlands Group has effectively wound down all activities.</p> <p>The move came suddenly and this has made it difficult for me to find time to edit and post the Yarns I recorded. Now that the carry-over Rowlands Group work has been completed I'm hoping to have more time to edit and post the remaining Yarns.</p> <p>Thanks again to all who took part and keep an eye out for more posts appearing in late June and throughout July.</p> <p>Lee Rowlands (larowlan).</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns" st_title="What&#039;s happening with Drupal Yarns?" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Sun, 17 Jun 2012 21:33:45 +0000 Lee Rowlands 112 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/06/lee-rowlands/whats-happening-drupal-yarns#comments The 10 Drupal Commandments http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>To help speed up debugging our development work we came up with a basic "go to" checklist. </p> <p>After much success this became our 10 Drupal Commandments.</p> <p>Let us know what your 10 Drupal Commandments are.</p> </div></div></div><div class="galleryformatter galleryview galleryformatter-greenarrows"> <div class="gallery-slides" style="width: 500px; height: 312px;"> <div class="gallery-frame"> <ul> <li class="gallery-slide" id="slide-0-field_images-110"> <a href="http://rowlandsgroup.com/sites/rowlandsgroup.com/files/10_commandments_0.png" title="The 10 Drupal Commandments"><span class="view-full" title="View the full image">View the full image</span></a><img src="http://rowlandsgroup.com/sites/rowlandsgroup.com/files/styles/galleryformatter_slide/public/10_commandments_0.png" width="500" height="312" alt="The 10 Drupal Commandments" title="The 10 Drupal Commandments" /> <div class="panel-overlay"> <div class="overlay-inner"> <h3>The 10 Drupal Commandments</h3> </div> </div> </li> </ul> </div> </div> </div> <div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments" st_title="The 10 Drupal Commandments" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Mon, 19 Mar 2012 06:50:09 +0000 Nick Schuch 110 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/03/nick-schuch/10-drupal-commandments#comments Getting Views Bulk Operations working with Draggable Views. http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><h3>Background</h3> <p>In Drupal 6, <a href="http://drupal.org/project/views_bulk_operations">Views Bulk Operations</a> and <a href="http://drupal.org/project/draggableviews">Draggable Views</a> defined views style plugins in order to deliver their respective functionalities. While this is great it meant you could only have one or the other, not both.<br /> Then Views 3 came along with support for <a href="http://drupal.org/node/769322">views as forms</a>. This is the functionality you see in <a href="http://drupal.org/project/commerce">Drupal Commerce</a> that allows the cart page to be generated using views.</p> <h3>Drupal 7</h3> <p>In order to take advantage of this new functionality, Views Bulk Operations in Drupal 7 was rewritten as a field handler with form support instead of a style plugin. Similarly the new 7.x-2.x branch of Draggable Views is also a rewrite to utilise this functionality.<br /> So this now means you can combine both Draggable functionality with Views Bulk Operations functionality in the one view right?<br /> Unfortunately if you define multiple <em>Bulk Operations</em> in your view, Views Bulk Operations will remove the default Save button added by views. This button is needed by Draggable Views to save the new order. But this is Drupal, so all is not lost - you can add the Save button back with a custom module and some form alter hooks.</p> <h3>Writing the custom module</h3> <p>First of all we need to target the correct form, so grab the form id of the view you're trying to add the save button back to. If you don't know how to do this either inspect the dom and find the form tag or just implement hook_form_alter and output the $form_id parameter till you find the right one.<br /> In this case we'll call our module mymodule and our form id will be views_form_myview_page. In case you didn't guess the format of the form id's generated by views follow a views_form_VIEWID_DISPLAYID patterm. So start with an implementation of hook_form_FORM_ID_alter<br /> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br /> * Implements hook_form_FORM_ID_alter() for views_form_myview_page().<br /> *<br /> * Alter the form to add the 'save' button back in. This button is removed by <br /> * views_bulk_operations - rendering draggableviews non-functional.<br /> *<br /> * @see views_bulk_operations_form<br /> */<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_form_views_form_myview_page_alter</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">$form</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br />&nbsp; </span><span style="color: #FF8000">// Repair the save button removed by views_bulk_operations.<br />&nbsp; // Here we make sure that draggableviews is operating on the form.<br />&nbsp; </span><span style="color: #007700">if (isset(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]) &amp;&amp; !empty(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]) &amp;&amp;<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// And confirm the button is missing.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">!isset(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">])) {<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Then we make sure the user has the correct permissions.<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">if (!</span><span style="color: #0000BB">user_access</span><span style="color: #007700">(</span><span style="color: #DD0000">'access draggableviews'</span><span style="color: #007700">)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// No need to fix save button.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">return;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Now we retrieve the Draggable Views options - Draggable Views allows you to<br />&nbsp;&nbsp;&nbsp; // override the caption on the 'Save' button as well as allow ajax submission.<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$options </span><span style="color: #007700">= </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'view'</span><span style="color: #007700">][</span><span style="color: #DD0000">'#value'</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">field</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">options</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Add back the save button.<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">] = array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Use the label provided by Draggable Views.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #0000BB">$options</span><span style="color: #007700">[</span><span style="color: #DD0000">'save_button_label'</span><span style="color: #007700">]),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Attach a button level submit handler so Views Bulk Operations submit handlers<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // don't fire when the 'Save' button is clicked.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#submit' </span><span style="color: #007700">=&gt; array(</span><span style="color: #DD0000">'draggableviews_views_form_submit'</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Ensure that form level validation does not occur when the 'Save' button is clicked<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (otherwise Views Bulk Operations won't be happy that you've not selected any rows<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // or an operation).<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#validate' </span><span style="color: #007700">=&gt; array(</span><span style="color: #DD0000">'mymodule_psuedo_validate'</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp; );<br /><br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Respect the original Draggable Views ajax configuration option<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">if (</span><span style="color: #0000BB">$options</span><span style="color: #007700">[</span><span style="color: #DD0000">'ajax'</span><span style="color: #007700">]) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">][</span><span style="color: #DD0000">'#ajax'</span><span style="color: #007700">] = array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'callback' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'draggableviews_view_draggabletable_form_ajax'</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp; }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <p>Now we've got our save button back - we just need to write the validation handler 'mymodule_psuedo_validate'.<br /> As you can guess from the name, it doesn't do anything other than prevent the save button firing the form level validation code (without this Views Bulk Operations will return validation errors regarding selection of rows and an operation).</p> <p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br /> * Psuedo validation handler<br /> *<br /> * @param array $form<br /> *&nbsp;&nbsp; the form<br /> * @param array $form_state<br /> *&nbsp;&nbsp; the form state<br /> *<br /> * @see views_bulk_operations_form_validate()<br /> */<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_psuedo_validate</span><span style="color: #007700">(</span><span style="color: #0000BB">$form</span><span style="color: #007700">, &amp;</span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br />&nbsp; </span><span style="color: #FF8000">// We deliberately do nothing here, if this validation handler isn't attached<br />&nbsp; // to our 're-added' save button then views_bulk_operations_form_validate is<br />&nbsp; // called and validation fails.<br /></span><span style="color: #007700">}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <h3>Wrapping up</h3> <p>And that's basically it with this you can create a flexible administration view for your content that rolls both ordering and common administrative tasks into a single form.<br /> Thanks to the maintainers of Views Bulk Operations and Draggable Views for their work on these modules.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views" st_title="Getting Views Bulk Operations working with Draggable Views." class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Wed, 29 Feb 2012 00:31:56 +0000 Lee Rowlands 108 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/02/lee-rowlands/getting-views-bulk-operations-working-draggable-views#comments Programmatically Insert Local Files to Managed Files http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>As numerous posts out there state, this is the way to programmatically add files into Drupal 7's file module tables. </p> <p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">// Load the files contents<br /></span><span style="color: #0000BB">$image </span><span style="color: #007700">= </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(&lt;</span><span style="color: #0000BB">path to file</span><span style="color: #007700">&gt;);<br /><br /></span><span style="color: #FF8000">// Returns the new file object<br /></span><span style="color: #0000BB">$file </span><span style="color: #007700">= </span><span style="color: #0000BB">file_save_data</span><span style="color: #007700">(</span><span style="color: #0000BB">$image</span><span style="color: #007700">, </span><span style="color: #DD0000">'public://&lt;filename&gt;'</span><span style="color: #007700">, </span><span style="color: #0000BB">FILE_EXISTS_RENAME</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <p>However after working on the module <a href="http://drupal.org/sandbox/nick_schuch/1436730">CCTV</a> (Currently getting approval for Full Project) I found that this was not enough.</p> <p>For some background details, CCTV is a module that turns your Drupal site into a IP Camera capture application. Based on the users preference the application can save files up to 1 day in file size (which equates to a very large file). Due to the large file sizes generated by CCTV php runs into memory both max file php configuration and local allocated memory issues. So how do we get around this?</p> <p>After digging through the file modules documentation I found the following solution.</p> <p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$handle </span><span style="color: #007700">= </span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #DD0000">'&lt;path to local file&gt;'</span><span style="color: #007700">, </span><span style="color: #DD0000">'r'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$file </span><span style="color: #007700">= </span><span style="color: #0000BB">file_save_data</span><span style="color: #007700">(</span><span style="color: #0000BB">$handle</span><span style="color: #007700">, </span><span style="color: #DD0000">'public://&lt;filename&gt;'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$handle</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <p>This opens the file in read only mode and using the file module's function file_save_data it copies the file to the public:// file system. This not only makes your code more efficient, but also allows for bypassing around php's max file size constraints.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files" st_title="Programmatically Insert Local Files to Managed Files" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Wed, 22 Feb 2012 03:52:44 +0000 Nick Schuch 107 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/02/nick-schuch/programmatically-insert-local-files-managed-files#comments Drupal Down Under 2012 Impressions http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>In the past few days I attended Drupal Down Under 2012 and wanted to write about my impressions of the conference from someone new to Drupal's perspective.</p> <h2>Location:</h2> <p>Brilliant, the location was central to Melbourne, this was especially good due to it being my first time in Melbourne so I was able to go and see the sites outside of the regular hours of the conference (I recommend this pub, <a href="http://www.niteguide.com.au/Melbourne/Restaurant/EquinoxBarMelbourneCMelbourne">Equinox</a>, its a student pub and has cheap drinks, great meals and a solid outdoor area to watch the world go by......... and back to my impressions.).</p> <h2>Keynote Speakers:</h2> <p>The two keynotes that I saw where Dries Buytaert and Dmitri Gaskin. </p> <p>On the first day we had Dmitri Gaskin give a inspirational keynote on his "Growing Up With Drupal". Dmitri talked about his beginnings as a java developer to program a lego robot he purchased after going to a robot convention. He then was thrown into the Drupal spectrum by his school who wanted to develop a website. Dmitri then learnt as much as he could through online resources and finally the community. He submitted his first patch during this project and the rest is history. Dmitri is a seasoned member of the Drupal community and regularly speaks at his local Drupal Camps. He also prides himself on being the creator of the fabulous "drush make", and for that I would also like to say thankyou! Oh, by the way, did I mention he is now only 16 years of age! Through Dmitri as a test case I have come up with the following equation for when one should start Drupal (or Development of any kind). Take the age you think would be the youngest age you could start developing and minus 10 years off that! There you go, you now have the age you could have started developing and making the world a better place.</p> <p>On the second day we had a very informative keynote on the future of Drupal by its creator Dries Buytaert. The two topics covered were related to where Drupal is heading in the future and his predictions on Drupal in the Business space (Small, Medium, Large Business). Dries explained that he believes that Drupal is well placed with Medium Businesses and will continue span out into the top levels of the Small Business market, while also gaining ground in the lower end of the Large Business spectrum. Dries then went on to explain the primary focus of Drupal 8; Ease of Use (WYSISYG and Mobile). Drupal 8 is going to have greater mobile support by providing HTML5 by default and we will see a greater presence of WYSISYG for the data entry folk. There are quite a few more and I recommend going to the Drupal Down Under site (when posted) to view Dries keynote.</p> <h2>Content:</h2> <p>I had no idea what was going to happen going into this event. I had seen the sessions on paper but had no idea on the format or of the community in which would attend. I attended the following sessions:</p> <p><b>Day 1</b></p> <ul><li>Views API Exposed</li> <li>Field, Widgets and Fomatters - Oh my!</li> <li>Drupal 7 Theming and Template Inheritance</li> <li>Node.js and Drupal</li> <li>Responsive Design</li> </ul><p><b>Day 2</b></p> <ul><li>Poppin Forms that Client Love</li> <li>Ezy-bake Drupal: Cooking sites with Distributions </li> <li>Building an awesome e-commerce site in 25 minutes without losing your soul)</li> </ul><p>First and formost I would like to say that all of these sessions where really well done and taught everyone something new. There are two standouts for me and those are:</p> <p><b>Node.js and Drupal</b> - I went into this session with no knowledge of what Node.js was, I had heard around the web about this Node.js but what was it and what does it give me? For now it gives Drupal fast information streams to users. The examples used where an update to the Drupal Watchdog to make posts appear in real time and a realtime pop up for users to see that a new comment had appeared on a subscribed node. I am really looking forward to seeing where this project goes and I cannot wait to do some work with it myself.</p> <p><b>Ezy-bake Drupal: Cooking sites with Distributions </b> - Having only just come off working on Rowlands Group's first Distribution: Open Music Festival, I was super keen to see how other members of the community got to a working solution on creating a Drupal Distribution. I definitely learnt a lot of valuable inside knowledge from members of the community that have already worked with Distributions and I believe that this knowledge will only make Open Music Festival better. I will be posting a How-To on how to make your own Drupal Distribution later on down the track. </p> <h2>Summary</h2> <p>Drupal Down Under 2012 was the best conference I have been to. I had a great time seeing this amazing Drupal community that we have in Australia and look forward to seeing everyone again in Drupal Down Under: Sydney.</p> <p>I would finally like to thank the organisers and speakers at the event. It would not have been this amazing without amazing people running the show and contributing. I wish to also extend a big thankyou to the interviewee's for the <a href="/drupal-yarns">Drupal Yarns</a> podcast and to apologise to those that we could not get to for interviews. We look forward to getting these podcasts out to you, the community, so you can listen to the truly talented people that I we met at the conference. If you wish to have an interview with us and have it appear on <a href="/drupal-yarns">Drupal Yarns</a> please don't hestitate to sent us <a href="/contact">get in touch</a>.</p> <p>Cheers, </p> </div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions" st_title="Drupal Down Under 2012 Impressions" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> <div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/categories/tags/drupal-downunder">Drupal Downunder</a></div><div class="field-item odd"><a href="/categories/tags/ddu">DDU</a></div><div class="field-item even"><a href="/categories/tags/nodejs">Node.js</a></div></div></div> Tue, 17 Jan 2012 04:31:27 +0000 Nick Schuch 96 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/01/nick-schuch/drupal-down-under-2012-impressions#comments Accessing user's Facebook Photos and Albums with Drupal http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>One of the options for <a href="http://sendmypostcards.com">SendMyPostcards.com</a> is for users to choose from their Facebook Photos and Albums for the front of their postcard.</p> <p>In this article I'll demonstrate how to use the Facebook Graph API from Drupal to access user's details from Facebook including, but not limited to, their albums and photos.</p> <h3>Getting Started</h3> <p>To get started you need the <a href="http://drupal.org/project/fbconnect">fbconnect module</a>. The module has a fairly involved install process that includes:</p> <ul><li>Standard module installation</li> <li>Registration of your site with the Facebook Developer program and obtaining the appropriate API keys etc</li> <li>Downloading the Facebook PHP SDK</li> <li>For Drupal 6, making changes to your page.tpl.php to ensure that fbxml works</li> </ul><p>Detailed instructions can be found in the module's read me files, once the whole thing is setup you should have a Facebook Connect button on the registration and login forms.</p> <h3>Requesting permissions</h3> <p>Fbconnect requests a basic set of permissions when the user registers on your site via Facebook, such as their basic details and the ability to send email to them via facebook. However anything beyond that requires elevated permissions. Eg to see their friends or photos/albums.</p> <p>Luckily fbconnect's api exposes a hook allowing you to add to the requested permissions - hook_fbconnect_login_button_alter. This hook takes one argument $attrs. Using this hook we can request additional permissions. Eg for example to request access to the user's photos:</p> <p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br /> * Implements hook_fbconnect_login_button<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_fbconnect_login_button_alter</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">$attrs</span><span style="color: #007700">) {<br />&nbsp; </span><span style="color: #0000BB">$attrs</span><span style="color: #007700">[</span><span style="color: #DD0000">'perms'</span><span style="color: #007700">] .= </span><span style="color: #DD0000">',user_photos'</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <h3>Using the Facebook Graph API</h3> <h4>Making sure we're ready to make requests</h4> <p>Once we've got the correct permissions, we can access the user's photos while they have an active session on our site and are logged in to Facebook.<br /> First we check if they're logged into Facebook and grab a reference to the :<br /> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">if (!</span><span style="color: #0000BB">user_is_anonymous</span><span style="color: #007700">() &amp;&amp; </span><span style="color: #0000BB">fbconnect_get_fbuid</span><span style="color: #007700">() &amp;&amp; </span><span style="color: #0000BB">_get_user_fbuid</span><span style="color: #007700">(</span><span style="color: #0000BB">$user</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">uid</span><span style="color: #007700">)) {<br />&nbsp; </span><span style="color: #FF8000">// .. processing in here<br /></span><span style="color: #007700">}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div><br /> If they're not logged in we can show a login button, eg in a form builder<br /> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />&nbsp; $form</span><span style="color: #007700">[</span><span style="color: #DD0000">'fbconnect_button'</span><span style="color: #007700">] = array(<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'item'</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#description' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Sign in using Facebook'</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// We use fbconnect_render_button to render the button with our required attributes (note the user_photos permission).<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">fbconnect_render_button</span><span style="color: #007700">(array(</span><span style="color: #DD0000">'perms' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'email,user_photos'</span><span style="color: #007700">)),<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#weight' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #DD0000">'#id' </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">'fbconnect_button'</span><span style="color: #007700">,<br />&nbsp; );<br />&nbsp; if (!</span><span style="color: #0000BB">user_is_anonymous</span><span style="color: #007700">()) {<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// The user is logged into our site but not facebook<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'fbconnect_button'</span><span style="color: #007700">][</span><span style="color: #DD0000">'#description'</span><span style="color: #007700">] = </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Sign in to your Facebook account'</span><span style="color: #007700">);<br />&nbsp; }<br />&nbsp; </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'#submit'</span><span style="color: #007700">][] = </span><span style="color: #DD0000">'fbconnect_redirect_submit'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div><br /> Now this form will end up at the default location that fbconnect_redirect_submit sends them too when the user signs in, if you need it to go back somewhere else, you'll need to implement hook_form_alter for $form_id fbconnect_autoconnect_form and add your own submit callback that sets $form_state['redirect'] - just your everyday run off the mill form_alter to modify the redirect location.</p> <h4>Making the request</h4> <p>Once your user is logged into facebook and your site, you're right to start making requests to the Facebook graph api. Eg fetching their albums and images<br /> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">// First we get a reference to the facebook client, provided by the Facebook PHP SDK and neatly wrapped by fbconnect<br /></span><span style="color: #0000BB">$fb </span><span style="color: #007700">= </span><span style="color: #0000BB">facebook_client</span><span style="color: #007700">();<br /></span><span style="color: #FF8000">// Get their albums<br /></span><span style="color: #0000BB">$albums </span><span style="color: #007700">= </span><span style="color: #0000BB">$fb</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">api</span><span style="color: #007700">(</span><span style="color: #DD0000">'/me/albums'</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">// Loop their albums<br /></span><span style="color: #007700">foreach (</span><span style="color: #0000BB">$albums</span><span style="color: #007700">[</span><span style="color: #DD0000">'data'</span><span style="color: #007700">] as </span><span style="color: #0000BB">$album</span><span style="color: #007700">) {<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$album </span><span style="color: #007700">= (object)</span><span style="color: #0000BB">$album</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">//fetch the images<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$album</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">images </span><span style="color: #007700">= array();<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$images </span><span style="color: #007700">= </span><span style="color: #0000BB">$fb</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">api</span><span style="color: #007700">(</span><span style="color: #DD0000">'/'</span><span style="color: #007700">. </span><span style="color: #0000BB">$album</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">id </span><span style="color: #007700">.</span><span style="color: #DD0000">'/photos?limit=25'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp; foreach (</span><span style="color: #0000BB">$images</span><span style="color: #007700">[</span><span style="color: #DD0000">'data'</span><span style="color: #007700">] as </span><span style="color: #0000BB">$image</span><span style="color: #007700">) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000BB">$image </span><span style="color: #007700">= (object)</span><span style="color: #0000BB">$image</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Do something with the image ....<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #007700">}<br />&nbsp;&nbsp;&nbsp; </span><span style="color: #FF8000">// Do something with the album ....<br />&nbsp; </span><span style="color: #007700">}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div><br /> In terms of the 'something' - for SendMyPostcards.com we temporarily cache the user's albums and images. For performance reasons we only fetch the first 25 images from their first album. We request each subsequent album and page as needed and update the cached object. We don't use any permanent storage of the albums or photos as obviously the user will add to their albums and photos over time and we want to fetch the latest values next time they use the site (or after the cache is cleared). </p> <h3>Taking things further</h3> <p>The graph api is very powerful, for the full reference on what you can access using this technique see <a href="http://developers.facebook.com/docs/reference/api/">the developer documentation</a>.<br /> How have you used the Graph API? Let us know via the comments.</p> </div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal" st_title="Accessing user&#039;s Facebook Photos and Albums with Drupal" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> <div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/categories/tags/facebook">Facebook</a></div><div class="field-item odd"><a href="/categories/tags/graph-api">Graph API</a></div><div class="field-item even"><a href="/categories/tags/fbconnect">fbconnect</a></div><div class="field-item odd"><a href="/category/tags/drupal">Drupal</a></div><div class="field-item even"><a href="/categories/tags/sendmypostcardscom">SendMyPostcards.com</a></div></div></div> Sat, 14 Jan 2012 03:46:48 +0000 Lee Rowlands 85 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2012/01/lee-rowlands/accessing-users-facebook-photos-and-albums-drupal#comments Building a custom content type workflow with Drupal 7 and the Field Permissions module http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Recently we've been working on an employment/mentoring site with Drupal 7 with a quite complex business workflow. The site features a large number of custom processes that mirror the client's off-line operations.</p> <p>At many points of the process there are documents completed that build on the workflow. For a number of reasons we've chosen to implement these documents as nodes rather than webforms - including access controls and other built-in node behaviours. </p> <p>The technical design issue we encountered was that many of the documents are variations on a theme depending on their position in the whole process. Rather than slow down the site performance by adding additional content types, we decided it would be best to merge as many of the <em>largely similar</em> content types into a single form and then show/hide fields based on the process.</p> <p>Enter the <a href="http://drupal.org/project/field_permissions">Field Permissions</a> module. The interface for the module has been cut down from the Drupal 6 version (which shipped as a sub-module of <a href="http://drupal.org/project/cck">CCK</a>) and you can now define what permissions you need to make available on a per-field basis. This is a huge improvement on how it worked in Drupal 6 - with Drupal 6 once you enabled the module <em>access to all fields</em> were then governed by field permissions. With the Drupal 7 version - you get to nominate which fields have their access control governed by field permissions. You can even nominate which permissions you need from - edit any, edit own, view any, view own, delete any and delete own. This means the permissions form is far less cluttered and the default behaviours are far more friendly.</p> <p>So in this case - we took three largely similar forms and combined them into one. Then we used roles to govern whether the fields were visible. As the user progresses through the whole business process, we'll use <a href="http://drupal.org/project/rules">Rules</a> to grant them the permission to see the fields as needed.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module" st_title="Building a custom content type workflow with Drupal 7 and the Field Permissions module" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Mon, 22 Aug 2011 23:47:05 +0000 Robert Bromwich 68 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2011/08/robert/building-custom-content-type-workflow-drupal-7-and-field-permissions-module#comments SASS Mixin for jcarousel, works great with views http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Displaying content using a carousel is a common design pattern, and with Drupal it's pretty easy to use views + jcarousel to whip up a carousel for displaying in blocks etc.<br /> Jcarousel comes with some default skins (tango, ie and default) and whilst they're nice, they rarely fit the design you're working too. So as a result we commonly find ourself leaving the carousel skin as 'None' (in the view style output settings) and just adding in the css via the theme. It's also common to have a number of carousels on one site, each with different sized items and their own particular requirements.<br /> And that's when it can get complicated, jcarousel's javascript requires some pretty specific css.<br /> If you miss the item width or size, or don't setup the clip properly you'll be left with a carousel that just doesn't work. And if you've got several carousels, the maintenance burden for the css starts to build up.<br /> Enter SASS, everyone's favourite css preprocessor.<br /> We're happy to share out SASS mixin for horizontal-jcarousels - the code is pretty self explanatory:<br /> <div class="codeblock"><code>/*<br /> * jcarousel mixin<br /> * @author Lee Rowlands (rowlandsgroup.com)<br /> * @param $selector carousel selector)<br /> * @param $carousel_width <br /> * @param $carousel_height<br /> * @param $carousel_padding <br /> * @param $item_width <br /> * @param $item_height <br /> * @param $item_margin <br /> * @param $button_width <br /> * @param $button_height <br /> * @param $button_image <br /> * @param $button_top<br /> * @param $button_left <br /> * @param $button_right <br /> * @param $button_left_position (background position)<br /> * @param $button_right_position <br /> * @param $button_left_position_hover <br /> * @param $button_right_position_hover <br /> * @param $button_left_position_disabled <br /> * @param $button_right_position_disabled<br /> */<br />@mixin horizontal-jcarousel($selector, $carousel_width: 960px,<br />&nbsp; $carousel_height: 150px, $carousel_padding: 0 50px, $carousel_margin: auto,<br />&nbsp; $item_width: 160px, $item_height: 160px, $item_margin: 0 10px,<br />&nbsp; $button_width: 31px, $button_height: 71px,<br />&nbsp; $button_image: url(../images/carousel.png), $button_top: 10px,<br />&nbsp; $button_left: 42px, $button_right: 42px, $button_left_position: 0 -35px,<br />&nbsp; $button_right_position: 0 -106px, $button_left_position_hover: 0 -35px,<br />&nbsp; $button_right_position_hover: 0 -106px,<br />&nbsp; $button_left_position_disabled: 0 -35px,<br />&nbsp; $button_right_position_disabled: 0 -106px) {<br />&nbsp; #{$selector} {<br />&nbsp;&nbsp;&nbsp; .jcarousel-container-horizontal {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width: $carousel_width;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height: $carousel_height;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; padding: $carousel_padding;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; margin: $carousel_margin;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-clip-horizontal {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width: $carousel_width;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; .jcarousel-item {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; padding: 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width: $item_width;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height: $item_height;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflow: hidden;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; border: none;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list-style: none;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-item-horizontal {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; margin: $item_margin;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-next,<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; display: block;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width: $button_width;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height: $button_height;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-image: $button_image;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; Horizontal Buttons<br />&nbsp;&nbsp;&nbsp;&nbsp; */<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-horizontal {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; position: absolute;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top: $button_top;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; left: $button_left;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_left_position;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-horizontal:active,<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-horizontal:hover {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_left_position_hover<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-disabled-horizontal,<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-disabled-horizontal:hover,<br />&nbsp;&nbsp;&nbsp; .jcarousel-prev-disabled-horizontal:active {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor: default;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_left_position_disabled&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-horizontal {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; position: absolute;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top: $button_top;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; right: $button_right;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_right_position;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-horizontal:active,<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-horizontal:hover {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_right_position_hover;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-disabled-horizontal,<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-disabled-horizontal:hover,<br />&nbsp;&nbsp;&nbsp; .jcarousel-next-disabled-horizontal:active {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor: default;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background-position: $button_right_position_disabled&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }<br />&nbsp; }<br />}</code></div></p> <p>Then adding the necessary css is as simple as<br /> <div class="codeblock"><code>@include horizontal-jcarousel(".view-ClientCarousel")</code></div><br /> Be sure to setup some sensible defaults for the project, it's most likely that the button images won't change over a project - so you should setup your argument defaults to suit the given project.</p> </div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views" st_title="SASS Mixin for jcarousel, works great with views" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> <div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/tags/drupal">Drupal</a></div><div class="field-item odd"><a href="/category/tags/views">Views</a></div><div class="field-item even"><a href="/category/tags/jcarousel">jcarousel</a></div><div class="field-item odd"><a href="/category/tags/sass">SASS</a></div><div class="field-item even"><a href="/category/tags/css">css</a></div></div></div> Fri, 12 Aug 2011 19:51:49 +0000 Lee Rowlands 36 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2011/08/lee-rowlands/sass-mixin-jcarousel-works-great-views#comments Importing really old Drupal 5 sites into Aegir http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Recently we had to take over some old Drupal 5 sites and bring them into our Aegir hosting platform. We had a few problems getting it all running smoothly so though we'd detail the steps involved.</p> <ul><li>copy your doc root files to platforms/yoursite</li> <li>make sure no path specific guff in .htaccess (shared hosting note suPHP_config_path)</li> <li>chown all of the files to aegir:apache/aegir:www-data depending on whether it's a Debian or Red Hat based distro</li> <li>create your database and import your database dump</li> <li>run a database prefix stripper if needed and edit setting.php accordingly</li> <li>edit profile.info, node.info, drupal.info, comments.info and enclose the description in double quotes</li> <li>edit clear.inc in your drush install and add if function_exist('node_types_rebuild') before the call to node_types_rebuild </li> <li>if you've got any modules from drupal.org - be sure to remove the 'information added from drupal.org packaging script on' (there's a bash script floating around to do this)</li> <li>change drush.inc to handle non-array returns for $info (line 665)</li> <li>change your sites/default to something meaningful so the platform verify picks it up</li> <li>create your platform in aegir</li> <li>if it all runs to plan your platform will verify and your site will be imported</li> <li>run the verify task on the imported site</li> <li>migrate your site to the latest drupal 5 build using aegir</li> </ul><p>Obviously the next step from here is to convince the client to upgrade it to Drupal 7 or at the very least Drupal 6.</p> </div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_google"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_email"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir" st_title="Importing really old Drupal 5 sites into Aegir" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> <div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Category:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/category/drupal-planet">Drupal Planet</a></div></div></div><div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/tags/drupal">Drupal</a></div><div class="field-item odd"><a href="/category/tags/aegir">Aegir</a></div></div></div> Wed, 10 Aug 2011 23:56:30 +0000 admin 35 at http://rowlandsgroup.com http://rowlandsgroup.com/articles/2011/08/admin/importing-really-old-drupal-5-sites-aegir#comments New useful store functions for Ext JS http://rowlandsgroup.com/new-useful-store-functions <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Some useful additional store functions </p> <ul><li>getEncodedData</li> <li>setAll</li> <li>getBetween</li> <li>min</li> <li>max </li> </ul><p> Install as follows </p> <p><div class="codeblock"><code>Ext.override(Ext.data.Store, { <br />&nbsp; getEncodedData: function (modifiedOnly){ <br />&nbsp;&nbsp;&nbsp; if(modifiedOnly === true) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c = this.getModifiedRecords(); <br />&nbsp;&nbsp;&nbsp; } else { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c = this.getRange(); <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; var p = new Array(); <br />&nbsp;&nbsp;&nbsp; if(c.length){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i=0; i&amp;lt;c.length; i++) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[i] = c[i].data; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Ext.encode(p); <br />&nbsp;&nbsp;&nbsp; } else { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ''; <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp; }, <br />&nbsp; setAll: function(f,v){ <br />&nbsp;&nbsp;&nbsp; this.each(function(r){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r.set(f,v); <br />&nbsp;&nbsp;&nbsp; }) <br />&nbsp; }, <br />&nbsp; getBetween: function(value, lower, upper){ <br />&nbsp;&nbsp;&nbsp; var rc; <br />&nbsp;&nbsp;&nbsp; this.each(function(r){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var d = r.data; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(value &amp;gt;= (1 * d[lower]) &amp;amp;&amp;amp; value &amp;lt;= (1 * d[upper])) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rc = r; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; }); <br />&nbsp;&nbsp;&nbsp; return rc; <br />&nbsp; }, <br />&nbsp; max : function(property,start,end){ <br />&nbsp;&nbsp;&nbsp; var rs = this.data.items, v = 0; <br />&nbsp;&nbsp;&nbsp; start = start || 0; <br />&nbsp;&nbsp;&nbsp; end = (end || end === 0) ? end : rs.length-1; <br />&nbsp;&nbsp;&nbsp; for(var i = start; i &amp;lt;= end; i++){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v = Math.max(v, (1 * rs[i].data[property]) || 0); <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; return v; <br />&nbsp; }, <br />&nbsp; min : function(property,start,end){ <br />&nbsp;&nbsp;&nbsp; var rs = this.data.items, v = 0; <br />&nbsp;&nbsp;&nbsp; start = start || 0; <br />&nbsp;&nbsp;&nbsp; end = (end || end === 0) ? end : rs.length-1; <br />&nbsp;&nbsp;&nbsp; for(var i = start; i &amp;lt;= end; i++){ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v = Math.min(v, (1 * rs[i].data[property]) || 0); <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; return v; <br />&nbsp; } <br />})</code></div></p> <p>   </p> <p> Usage: </p> <p> <b>getEncodedData</b> </p> <p> Returns string encoded data suitable for submission in Ajax request. </p> <p> Parameters: </p> <ul><li> modifiedOnly - if true only returns modified records</li> </ul><p> <b>getBetween</b> </p> <p> Returns array of records where value between lower and upper </p> <p> Parameters: </p> <ul><li> value: the field to search in</li> <li>lower: lower bound </li> <li>upper: upper bound</li> </ul><p> <b>max</b> </p> <p> Returns maximum value for field property between records start and end </p> <p> Parameters: </p> <ul><li>property: field value to return max from</li> <li>start: start index of records to search (default 0)</li> <li>end: end index of records to search (default store.getCount()) </li> </ul><p> <b>setAll</b> </p> <p> Sets value of field f to value v for all records in the store </p> <p> Parameters: </p> <ul><li>f: field to update</li> <li>v: value to set field to </li> </ul></div></div></div><div class="sharethis-buttons"><span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_google"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_digg"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_delicious"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_email"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_twitter"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_facebook"></span> <span st_url="http://rowlandsgroup.com/new-useful-store-functions" st_title="New useful store functions for Ext JS" class="st_sharethis"></span> <script type='text/javascript'>var switchTo5x=true;</script><script type='text/javascript' src='http://w.sharethis.com/button/buttons.js'></script><script type='text/javascript'>stLight.options({publisher:'dr-5d208cf3-1548-8519-cb10-a07ce4f152ee'});</script></div> Wed, 10 Nov 2010 11:08:12 +0000 Lee Rowlands 21 at http://rowlandsgroup.com http://rowlandsgroup.com/new-useful-store-functions#comments