Grayside.Org - drupal http://grayside.org/taxonomy/term/1 Drupal is a CMS. You probably knew that. en Guzzle for Drupal: SDK Building http://grayside.org/2012/12/guzzle-drupal-sdk-building <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>For the last few months I&#8217;ve (intermittently) been thinking about how to build a nice <span class="caps">PHP</span> <span class="caps">SDK</span> for working with external APIs from <span class="caps">PHP</span> applications, and Drupal in general.</p> <p>This post is a sort of round up of my thoughts, hopefully I&#8217;ll find time to complete this project so I can post a detailed followup.</p> <h2>Selecting Guzzle</h2> <p>I&#8217;ve come to the conclusion (as has <a href="https://github.com/amazonwebservices/aws-sdk-for-php">Amazon</a>) that <a href="http://guzzlephp.org/">Guzzle</a> is the perfect <span class="caps">HTTP</span> Client framework to build such a thing in <span class="caps">PHP</span>. In the mean time, <a href="http://drupal.org/node/1862398">Drupal 8 has gotten fully onboard with the guzzled goodness</a>. So it&#8217;s looking increasingly like a go-to library.</p> <p>Decoupled architecture, careful obedience to the <span class="caps">HTTP</span> spec, lots of valuable (and optional) features, and a maintainer with a deep knowledge of cURL&#8217;s curlicues makes it a good system to lean on.</p> <h2>Basic Architecture</h2> <p>Guzzle has a very componentized architecture, and in recent months has separated out these components into separately downloadable packages, so you can use <a href="http://getcomposer.org">Composer</a> to get just the pieces you need.</p> <p>It also uses a Symphony-driven plugin architecture, which makes many different behaviors easily swappable. Check out the <a href="http://guzzlephp.org/guide/plugins.html">existing plugin library</a> and realize that most of them are ridiculously easy to override with your own version of the plugin, either implementing the interface or extending what&#8217;s there.</p> <h2>Laying Out the Client</h2> <ul> <li>Have a single &#8220;Client&#8221; class namespaced to the <span class="caps">API</span> you want to integrate.</li> <li>You can use the <a href="http://guzzlephp.org/guide/service/service_descriptions.html">Service Definition <span class="caps">DSL</span></a> to quickly get something working, but I question the performance of doing so. I have some crazy ideas about coupling a discover service with a Guzzle Mimetype to created an automatic client testing harness.</li> <li>You should probably have an abstract &#8220;Command&#8221; (<span class="caps">API</span> Resource) in place to impose any custom behaviors.</li> <li>You should probably group &#8220;categories&#8221; of resources together using a lower level abstract class or interface to impose still more. For example, I want to add some fault tolerance by making certain &#8220;change&#8221; operations enqueue-for-retry on failure.</li> </ul> <h2>Add the Drupal</h2> <p>Using the Adapter interfaces, it took me about 20 minutes apiece to put together Drupal caching and logging plugins. These will be brought in place with the proper <code>use</code> statements in a Drupal-specific Client class I will create as an extension of the generic <span class="caps">SDK</span> client.</p> <p>Similarly, I anticipate extending many of the Command classes with Drupal-specific variants to handle mapping (data conversion) from Drupal entities to the <span class="caps">API</span> payload&nbsp;structure.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/1/guzzle">guzzle</a></div><div class="field-item odd"><a href="/category/1/composer">composer</a></div><div class="field-item even"><a href="/category/1/sdk">sdk</a></div><div class="field-item odd"><a href="/category/1/api">api</a></div><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div></div></div> Wed, 12 Dec 2012 05:42:44 +0000 Grayside 100 at http://grayside.org http://grayside.org/2012/12/guzzle-drupal-sdk-building#comments Drush Snippets: Menu Trace http://grayside.org/2012/08/drush-snippets-menu-trace <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Random snippet of the day, find out what modules are involved in building out a given menu route definition. When you type a <span class="caps">URI</span> into your browser, Drupal&#8217;s menu routing system connects that to your page content by processing the path into instructions for how to build the&nbsp;page.</p> <p>To use this script, copy the text or clone from github as a file, make it executable. It will automatically run with <code>drush php-script</code>. You can use <code>--verbose</code> for &#8220;full array notation&#8221; of each module&#8217;s change to the menu route. Or you can just use <code>--pipe</code> to get a list of modules and go look at the code&nbsp;directly.</p> <script src="https://gist.github.com/3326438.js"> </script> <p>In theory this should work with Drupal 7, but I haven&#8217;t gotten around to testing it&nbsp;yet.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/terms/drupal6">drupal6</a></div><div class="field-item odd"><a href="/category/terms/drush">drush</a></div><div class="field-item even"><a href="/category/1/snippet">snippet</a></div><div class="field-item odd"><a href="/taxonomy/term/1">drupal</a></div></div></div> Sat, 11 Aug 2012 19:08:54 +0000 Grayside 99 at http://grayside.org http://grayside.org/2012/08/drush-snippets-menu-trace#comments Extending Drush Commands http://grayside.org/2012/04/extending-drush-commands <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>The other day around the office, I was surprised to discover not everyone realizes that you can do some crazy stuff around extending drush commands.</p> <p>First step: Read the documentation. Drush is intentionally written to be a command-line foil for Drupal, and if you&#8217;ve built a module, a few minutes digging into the well-done docs will go a long way. Check out the <a href="http://api.drush.ws">Drush <span class="caps">API</span></a> if you are of a mind, or for a more focused burst of hook goodness, get out your terminal and type:</p> <div class="geshifilter"> <div class="text geshifilter-text" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal">$&gt; drush topic docs-api</pre></div> </div> <p>Once you have a grasp of the fine hooks you can use to piggy-back on and around any Drush command, you can take it to the next level.</p> <h3>Adding&nbsp;Options</h3> <p>Adding options to a Drush command allows you to create more sophisticated, controllable extensions to core command behaviors.</p> <p>There are several ways of doing this.</p> <h4>The command allows this&nbsp;already</h4> <p>Let&#8217;s not make this too complicated. Commands are sometimes intended as passthru mechanisms, such as <code>drush rsync</code>. How does it accept any rsynch command? It has a command definition that includes <span class="geshifilter"><code class="text geshifilter-text">allow-additional-options =&gt; TRUE</code></span>.</p> <h4>The user operates in non-strict&nbsp;mode</h4> <p>If the developer can set a flag, so can the user! You might have already seen this warning:</p> <div class="geshifilter"> <div class="text geshifilter-text" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal">Unknown option: --simple. &nbsp;See `drush help help` for available options. To suppress this error, add the option --strict=0.</pre></div> </div> <p>This means that any time the user adds <span class="geshifilter"><code class="text geshifilter-text">--strict=0</code></span> to a drush command invocation (or to their <a href="http://drush.ws/examples/example.drushrc.php">drushrc file</a> for that specific command), your drush code can use <a href="http://api.drush.ws/api/drush/includes!context.inc/function/drush_get_option/5.x"><code>drush_get_option()</code></a> to access the submitted value.</p> <h4>But for the clever command&nbsp;extension&#8230;</h4> <p>You&#8217;ll want to implement <a href="http://api.drush.ws/api/drush/docs!drush.api.php/function/hook_drush_help_alter/5.x"><code>hook_drush_help_alter()</code></a>. Using this hook, you can add new options to a drush command that will be be qualified as &#8220;strict&#8221;, <strong>and</strong> will even show up in the <em>help</em> entry for the command in the user&#8217;s system.</p> <h3>Why didn&#8217;t you show source&nbsp;code?</h3> <p>Well, I had this small idea in mind, but it evolved rather quickly into a legitimate project. Go check out <a href="http://drupal.org/project/drush_notify">Drush Notify</a>. It&#8217;s pretty Ubuntu-specific out the gate, but it serves as a great example of a powerful drush &#8220;extension&#8221; that defines no&nbsp;commands.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/drush">drush</a></div></div></div> Sat, 21 Apr 2012 07:21:54 +0000 Grayside 98 at http://grayside.org http://grayside.org/2012/04/extending-drush-commands#comments Features Module, Then, Now, and in the Future http://grayside.org/2012/03/features-module-then-now-and-future <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Between the <a href="http://drupal.org/project/issues/features">issues queue</a>, Twitter, podcasts, and ad hoc discussions, there is a lot of confusion about what the Features module is all about. As someone that has used and developed in it for a long time, I thought I&#8217;d lend my perspective. My sense is the maintainers are on the same page, but don&#8217;t hold them to this post.</p> <h2>Then</h2> <p>Features is a module to help site builders and command-line gurus easily package up the configuration associated with a specific use case (like a blog), and manage it in code.</p> <p>Unfortunately, there is no standard for doing this, so Features develops a mechanism for wrangling exports. This is sad, because it confuses the use case of the Features module itself.</p> <h2>Now</h2> <p>Unless you are active in the Distributions movement or style of site-building, the sense I get is that this is a common thought process for those that run across Features:</p> <blockquote><p> I need to toss my configuration into code so I can ship my website around. This Features module things has traction. Darn, the <span class="caps">UI</span> sucks, I have to click all these little boxes. And all these info hooks, info alter hooks, and caching layers complicate my day. </p></blockquote> <p>Meanwhile, in #drupal-features, a paraphrase:</p> <blockquote><p> We totally need to get the exporting out of Features. It adds complexity and attracts all these irrelevant use cases to the issue queue. </p></blockquote> <h2>Future</h2> <p>The <a href="http://groups.drupal.org/build-systems-change-management/cmi">Configuration Management Initiative</a> is exciting. From the perspective of a Features user and developer, it finally defines the standard and mechanism for configuration. That means Features finally has a target for how to pull the out-of-scope pieces out.</p> <p>After several conversations at DrupalCon, I&#8217;m expecting we&#8217;ll be seeing a 2.x architectural branch for Features that drops the export stuff. That doesn&#8217;t mean it will become an inconsequential module&#8211;it turns out capturing use cases in configuration is surprisingly complex. People do not agree on what bits and pieces naturally fall together. But that&#8217;s okay, because we are reviving the <a href="http://drupal.org/project/kit">Kit</a> specification. Expect more from me on that in the future, I think standards like that are key to keeping Drupal intuitive as the Distributions-driven approach to Drupal continues to&nbsp;accelerate.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/terms/features">features</a></div><div class="field-item odd"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item even"><a href="/category/1/cmi">cmi</a></div></div></div> Wed, 28 Mar 2012 21:03:03 +0000 Grayside 96 at http://grayside.org http://grayside.org/2012/03/features-module-then-now-and-future#comments Infinite Null: Sorting NULL to Last http://grayside.org/2011/08/infinite-null-sorting-null-last <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><em>Please, keep in mind this post was written for Drupal 6 and Views 2! D7/Views 3 sites might not take so kindly to it.</em></p> <p>Recently I was looking at creating a new Todo Feature with a due date. I cracked open <span class="caps">CCK</span>’s <em>manage fields</em> <span class="caps">UI</span> and added a date field, careful to keep in mind that the default value should be <strong>no date</strong>, which just happens to translate as <span class="caps">NULL</span>. You see, for my Todo use case, not all Todos would have a deadline.</p> <p>My next step was to create a View of all upcoming items. I wanted the next most urgent todo to float to the top of the list. Sadly, <span class="caps">NULL</span> counts as 0 in database land, so my carefully clicked Sort was preloading all my urgent todos with all the lowest priority tasks.</p> <p>Seeing as this was a <span class="caps">SQL</span> problem, I googled the ‘net for viable query tweaks. I found a nice article illustrating exactly what I wanted: <a href="http://www.shawnolson.net/a/730/mysql_sort_order_with_null.html">MySQL Sort Order with <span class="caps">NULL</span></a>. The grand secret? Sort first by whether the duedate is <span class="caps">NULL</span> to flip your empty values to the bottom of the result set.</p> <p>The fastest way for me to apply this tweak to my feature was to hack the Views query. <code>hook_views_query_alter()</code> is usually a horrible decision. Once you’ve put it into code, tweaking your View a lot around your alteration can quickly result in a broken query. Meanwhile:</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_views_query_alter(). &nbsp;*/</span> <span style="color: #000000; font-weight: bold;">function</span> example_views_query_alter<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$view</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'example_listing'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; &nbsp; <a href="http://www.php.net/array_unshift"><span style="color: #990000;">array_unshift</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderby</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'<span class="caps">ISNULL</span>(node_data_field_duedate_field_duedate_value) <span class="caps">ASC</span>'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>(For a longer use case on this Views bandaid, see <a href="http://btmash.com/article/2011-06-09/correcting-views-queries-using-views-query-alter">Correcting views queries using views_query_alter</a>)</p> <p>I arrived here by turning on the <a href="http://drupal.org/project/devel">Devel</a> module, and dropping a <code>dpm($query)</code> into that function first thing. This gave me the array structure of my View, including the various <span class="caps">SQL</span> entries for the <span class="caps">ORDER</span> <span class="caps">BY</span> arguments. A quick and dirty <code>array_unshift()</code> forces the <span class="caps">NULL</span> check for my date field (the alias I also found in the $query object, there are more elegant methods) onto the top of the ordering hierarchy.</p> <p>Bingo! <span class="caps">NULL</span>-dated nodes are sorted to&nbsp;last.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/category/1/sql">sql</a></div><div class="field-item odd"><a href="/category/terms/views">views</a></div><div class="field-item even"><a href="/category/1/views2">views2</a></div><div class="field-item odd"><a href="/taxonomy/term/1">drupal</a></div></div></div> Thu, 25 Aug 2011 04:01:43 +0000 Grayside 94 at http://grayside.org http://grayside.org/2011/08/infinite-null-sorting-null-last#comments Configure Drush in Your Git Repository http://grayside.org/2011/08/configure-drush-your-git-repository <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 neat features of Drush is it&#8217;s configurability. Setting the defaults for various behaviors and command options allows you to build really simplified, specialized workflows. You can create personal settings defaults by dropping a `drushrc.php` file in one of the places Drush will look, such as inside a .drush folder of your home&nbsp;directory.</p> <p>It turns out this little capability has provided some very simple wins for developers at <a href="http://www.goingon.com">GoingOn</a>. We pass around our projects and sites as a subdirectory of a Git repository that contains various things, such as documentation, deployment tools, and drush commands. Unfortunately, this slightly irregular practice disconnects Drush from the Drupal site and excludes those drush commands from the standard directories drush&nbsp;scans.</p> <p>We fix this by making Drush aware of the Git Repo. There is a command-line script you can use to check if you are anywhere in a Git repository. By configuring Drush to check for a Git Repo on every drush bootstrapping, we give Drush a chance to pick up a bonus, repository-specific Drush config&nbsp;file.</p> <p><em>Add this snippet to your drushrc.php&nbsp;file:</em></p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <a href="http://www.php.net/exec"><span style="color: #990000;">exec</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'git rev-parse --show-toplevel 2&gt; /dev/null'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #000088;">$repo</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$repo</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/drush/drushrc.php'</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'include'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$repo</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/drush/commands'</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'alias-path'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$repo</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/drush/aliases'</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>This script checks the current directory for participation in a git repository. If there is one, it looks at the root of the git repository for a &#8216;.drushrc.php&#8217; file to provide repo-specific instructions to Drush. We use this to configure paths to external resources that can vary by code version, as well as setting the Drupal site root for the Drupal site sihpped with that particular&nbsp;repository.</p> <p>The last line also seeks out a `scripts/` directory in the repository root, which it will scan recursively for any files ending in `.drush.inc`. This allows us to ship versioned drush commands with each repo instead of documenting a complex individual installation&nbsp;process.</p> <p>There are many other things you can do with a little poking about in the options for a drushrc file, to learn more start with the <a href="http://drush.ws/examples/example.drushrc.php">drushrc.php example</a>.</p> <p><strong>Update 7/16/2012</strong>: Updated code example to the same provided in Drush docs. You can now leverage this trick outside the root directory of your code repository. Also removed not applicable git context resulting in invalid configuration&nbsp;paths.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/drush">drush</a></div><div class="field-item even"><a href="/taxonomy/term/86">git</a></div></div></div> Sat, 20 Aug 2011 06:53:18 +0000 Grayside 93 at http://grayside.org http://grayside.org/2011/08/configure-drush-your-git-repository#comments D7 Upgrade Process: Backports to Close the Gap http://grayside.org/2011/08/d7-upgrade-process-backports-close-gap <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><em>The following post originally appeared on the <a href="http://goingon.com/blog/d7-upgrade-process-backports-close-gap">GoingOn.com blog</a>.</em></p> <p>After more than a year of continuous investment in <a href="http://goingon.com">GoingOn</a>&#8217;s Drupal 6 platform, the idea of upgrading to Drupal 7 is incredibly daunting. We have custom modules from form behaviors down to the access layer, we have features encapsulating hundreds of exported components, and an aggressive feature release schedule that does not set aside 6 months for a complete rewrite of the codebase just for a new version of Drupal. What to&nbsp;do?</p> <p>We’ve been playing around with the idea of iterating our Drupal 6 platform toward Drupal 7. By pulling markup, design patterns, APIs, and architecture in Drupal 7 down into platform incrementally, we hope to shorten the final leap that will come when upgrading the entire&nbsp;system.</p> <h5>Driving Current Drupal Version Closer to Expected Drupal&nbsp;Version</h5> <p><img src="http://goingon.com/sites/default/files/Drupal_Steps_4.png" alt="" width="200" height="202" /></p> <p><sup>Usability metaphors in site architecture and development practices sometimes works.</sup></p> <p>The extra work involved might well take <em>more aggregate</em> time to develop, but that time will be amortized across small, manageable pieces that can be more intelligently inserted into the development&nbsp;schedule.</p> <p>Here are the backport opportunities we’ve&nbsp;identified:</p> <h3>Design&nbsp;Patterns</h3> <p><a href="http://drupal.org/project/vertical_tabs">Vertical Tabs</a>, <a href="http://drupal.org/project/contextual">Contextual Links</a>, Toolbar, <a href="http://drupal.org/project/elements">Elements</a>, <a href="http://drupal.org/project/contact">Contact</a></p> <p>Many of the design patterns in Drupal 7 are available through a combination of backport modules and creative theming. The Toolbar module doesn’t have a backport, but peeking into the repository for the <a href="http://drupal.org/project/admin_menu">Admin Menu</a> I spy something that makes it <em>look</em> like D7’s&nbsp;Toolbar.</p> <p>By pulling these patterns from D7, we gain two&nbsp;benefits:</p> <ul> <li>We can build out the rest of our user interface around D7 design assumptions, instead of D6 assumptions. This will save effort in a theme redesign and&nbsp;upgrade.</li> </ul> <ul> <li>We can trickle D7 designs in front of our users, allowing them to adjust to a few changes ahead of time instead of waking up one morning to find a completely rearranged&nbsp;website.</li> </ul> <p><em>Our use of Vertical Tabs liberally around node forms is not cutting edge, but has allowed us to package complex forms with a Drupal 7 pattern, instead of resorting to harder-to-maintain multi-step&nbsp;forms.</em></p> <h3>System&nbsp;Plumbing*</h3> <p><a href="http://drupal.org/project/drupal_queue">Drupal Queue</a>, <a href="http://drupal.org/project/adminrole">Admin Role</a>, <a href="http://drupal.org/project/password">Password</a>, <a href="http://drupal.org/project/hook_file">File</a>, <a href="http://drupal.org/project/mailsystem">Mail System</a>, <a href="http://drupal.org/project/simpletest">Simpletest</a></p> <p>The flow of code that goes on under the hood has a few interface points where it is relatively easy to grab a D6 backport and make your modules look just a little more like Drupal 7&nbsp;code.</p> <p>Judging by an <span class="caps">IRC</span> chat I just overheard the files[] mechanism might be dropped for something simpler in one of the next few point&nbsp;releases.</p> <p><em>I hadn’t realized until writing this that <span class="caps">URL</span> Alter was cooked into core. The ability to ignore the special rules around around <a href="http://api.drupal.org/api/drupal/developer--hooks--core.php/function/custom_url_rewrite_inbound/6">custom_url_rewrite_inbound()</a>  and go straight for <a href="http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_url_inbound_alter/7">hook_url_inbound_alter()</a> is great. It also makes our custom code using it D7&nbsp;ready.</em></p> <p>* For purposes of this post, plumbing refers to the flow of code and data between its storage and the rendering process. Pretty broad&nbsp;category.</p> <h3>Database <span class="amp">&amp;</span>&nbsp;Performance</h3> <p><a href="http://pressflow.org/">Pressflow</a>, <a href="http://drupal.org/project/dbtng"><span class="caps">DBTNG</span></a>, <a href="http://drupal.org/project/cache_backport">Cache&nbsp;Backport</a></p> <p>You can get a lot closer to Drupal 7 performance behaviors simply by using Pressflow, which has held backports from and experiments for Drupal 7 for&nbsp;years.</p> <p><em>Most members of the Drupal community are already well aware that if performance is important for your project, grabbing Pressflow is an easy and non-threatening win. By using it for D6, you will be coding against session handling that is closer to D7’s, as well as being able to make use of other performance enhancing systems, such as serving images via <a href="http://drupal.org/project/varnish">Varnish</a> as an ongoing improvement across your upgrade&nbsp;process.</em></p> <h3>Contrib&nbsp;Backports</h3> <p>This is a category of another sort. Usually when you think about Contrib modules for D7, you are looking for the upgraded version of the modules you are already using. However, what if there is a D7 module you want to use, or at least, could use? The D6 version of that module has just become a backport to facilitate your upgrade&nbsp;path.</p> <p>This is a good solution to deal with unmaintained modules that have since been eclipsed by more energetic projects, as well as custom code you don’t really want to see again. We’re pretty excited to start playing with the <a href="http://drupal.org/project/boxes">Boxes </a>module for this&nbsp;reason.</p> <p>I’m going to skip listing competing modules in which one has an upgrade path and not the other. The <a href="http://groups.drupal.org/similar-module-review">Similar Module Review</a> group might have information that will help you find competing modules that may just be a cleaner path&nbsp;forward.</p> <p><em>Thanks to <a href="http://www.lullabot.com/articles/friday-roundup-drupal-8-education-agile-bacon-and-roombas">Lullabot’s Friday Roundup </a>(June 24th) for pointing out backports of Password, Contact, and File. Thanks to David Reid for creating and maintaining what seems like most of these&nbsp;modules.</em></p> <p><em><strong>So, did this work? </strong>We are still putting together the details of this plan. A followup post in a few months will report on how it goes. If you have thoughts about this approach to the upgrade, additional worthwhile backports, or alternate ideas on how to make the time for an upgrade, please post a&nbsp;comment!</em></p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/drupal6">drupal6</a></div><div class="field-item even"><a href="/taxonomy/term/84">drupal7</a></div><div class="field-item odd"><a href="/taxonomy/term/85">upgrade</a></div></div></div> Wed, 17 Aug 2011 05:40:01 +0000 Grayside 92 at http://grayside.org http://grayside.org/2011/08/d7-upgrade-process-backports-close-gap#comments How to Use jQuery to Smoothly Add a Script After Page Load http://grayside.org/2010/11/how-use-jquery-smoothly-add-script-after-page-load <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>A colleague of mine slapped this trick together and I wanted to jot it down:</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal">&nbsp; <span style="color: #000088;">$script_url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://www.example.com/script.js&quot;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; <span style="color: #000088;">$my_js</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot; &nbsp; $(document).ready(function(){ &nbsp; &nbsp; &nbsp; &nbsp; jQuery.getScript('&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$script_url</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;'); &nbsp; &nbsp; &nbsp; &nbsp; });&quot;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; drupal_add_js<span style="color: #009900;">&#40;</span><span style="color: #000088;">$my_js</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'inline'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div> </div> <p>It waits until the page has loaded, then it goes and inline includes an external javascript. The site was loading half-way, then spending a couple seconds processing a bunch of externally-sourced javascript. Now it&#8217;s effectively&nbsp;seamless.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/javascript">javascript</a></div><div class="field-item even"><a href="/category/terms/jquery">jquery</a></div></div></div> Mon, 22 Nov 2010 21:13:04 +0000 Grayside 91 at http://grayside.org http://grayside.org/2010/11/how-use-jquery-smoothly-add-script-after-page-load#comments How to Override a Views Field Template from a Module http://grayside.org/2010/09/how-override-views-field-template-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>Some months ago I wanted the solution to overriding a Views Field template entirely from within a module. I spent hours trawling documentation and issues, and playing with a little trial and error. In the end, I came up with a solution:</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_theme(). &nbsp;*/</span> <span style="color: #000000; font-weight: bold;">function</span> custom_module_theme<span style="color: #009900;">&#40;</span><span style="color: #000088;">$existing</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #b1b100;">return</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; <span style="color: #0000ff;">'views_view_field__view_name__field_name'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'arguments'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'view'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;"><span class="caps">NULL</span></span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'field'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;"><span class="caps">NULL</span></span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'row'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;"><span class="caps">NULL</span></span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'template'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'views-view-field--view-name--field-name'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'original hook'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'views_view_field'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'path'</span> <span style="color: #339933;">=&gt;</span> drupal_get_path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'custom_module'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/theme'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>By defining a Views template in this way, you are doing the equivalent to building your template and dropping it into your Theme&#8217;s directory. This is sufficient for Views to notice the existence of the template from within your module. At that point the standard Views logic of finding the most specific template available for each field comes into play. In this case, every instance of <em>field name</em> in <em>view name</em> will use this template&#8230; unless, of course, I have a more specific template somewhere that targets that field in a specific display.</p> <p>Note that the theme key and template name are the same, but for the swapping of hyphens and underscores. The way both of those are named is critical, else Views will not properly notice the template. All the options listed in <strong>Theme Information</strong> in the Views <span class="caps">UI</span> is available for use here.</p> <p>Note that this is very derivative of the hard work of others, and I will link to it here when I come across it again.</p> <p><strong><a href="http://drupal.org/node/627378">views template overrides in module directory</a> was one of my key references. Since I checked that thread, the marvelous @dereine posted a patch with the intent to guide Views to find theme templates in module directories as well. It <em>Needs Review</em>, so if the code above bores you, go review the&nbsp;patch!</strong></p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/views">views</a></div><div class="field-item even"><a href="/category/terms/theming">theming</a></div></div></div> Wed, 15 Sep 2010 21:07:05 +0000 Grayside 90 at http://grayside.org http://grayside.org/2010/09/how-override-views-field-template-module#comments Modifying Contexts the Old-Fashioned Way http://grayside.org/2010/06/modifying-contexts-old-fashioned-way <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>There are two ways to change <a href="http://drupal.org/project/context">contexts</a>. The new awesomeness is to use <a href="http://drupal.org/project/features">Features</a> or other exportable techniques to create a new version of your modified contexts, and push the old ones out of the way.</p> <p>However, when I avoid hacking [atrium] core, I prefer the old way&#8211;today that&#8217;s alter hooks.</p> <p>Alter hooks in Context allow you to do zany things like modifying the <em>conditions</em> or <em>reactions</em> associated with a given context. Naturally, if the original context slides out from under your original assumptions you&#8217;ll have to make some changes. In the meantime, just remember that using such powerful things as hook_context_load_alter() you can completely break a context if you are not careful.</p> <p>Below are some examples of context manipulations I&#8217;ve learned through a bit of code trawling and error trials.</p> <p>For the sake of (some) future compatibility I am using the Context <span class="caps">API</span> as of 3.0-beta4.</p> <p>&gt; <em><span class="caps">EDIT</span>: The method previously illustrated here for altering context conditions via hook_context_load_alter() was flat-out wrong, and will not work. Unless you were to use it to preload the context_ui just to go to the context ui edit page and click save. Then it would do something.</em></p> <h2>Adding a Content Type Condition</h2> <p>In my approach to integrating Feature Servers into OpenAtrium, I decided to pull the Project content type created by the Feature Server module into the casetracker project context. This required a new condition.</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_context_default_contexts_alter(). &nbsp;*/</span> <span style="color: #000000; font-weight: bold;">function</span> custom_context_default_contexts_alter<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$contexts</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #000088;">$contexts</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'spaces-feature-casetracker'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conditions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'node'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'values'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'fserver_project'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'fserver_project'</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <h2>Adding a Path Condition</h2> <p>In working out <span class="caps">OA</span> Book Manager, I wanted to add my new admin pages to the book context so the sidebar book navigation would stick around. Do you see where this code is broken?</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_context_default_contexts_alter(). &nbsp;\*/</span> <span style="color: #000000; font-weight: bold;">function</span> custom_context_default_contexts_alter<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$contexts</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #000088;">$contexts</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'spaces-feature-book'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conditions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'path'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; <span style="color: #0000ff;">'values'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'notebook/manage/\*'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'notebook/manage/*'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>When manipulating contexts, you need to keep a close lookout for when you are adding new array elements and when you are overriding array elements. By setting the path in this way, I am clearing out any existing path-based conditions. Instead, I should assign the new path element at a deeper part of the array.</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_context_default_contexts_alter(). &nbsp;\*/</span> <span style="color: #000000; font-weight: bold;">function</span> custom_context_default_contexts_alteer<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$contexts</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #000088;">$contexts</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'spaces-feature-book'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conditions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'path'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'values'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'notebook/manage/\*'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'notebook/manage/\*'</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>This code does not blast away existing path conditions.</p> <h2>Adding a Block Reaction</h2> <p>Recently I&#8217;ve been working on creating a dashboard <span class="caps">RSS</span> feed for OpenAtrium. I wanted to add a new block to the user profile page to present some links and use instructions.</p> <div class="geshifilter"> <div class="php geshifilter-php" style="font-family:monospace;"> <pre style="font-family: monospace; font-weight: normal; font-style: normal"><span style="color: #009933; font-style: italic;">/** &nbsp;* Implementation of hook_context_load_alter(). &nbsp;*/</span> <span style="color: #000000; font-weight: bold;">function</span> custom_context_load_alter<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'atrium_profile'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp; &nbsp; <span style="color: #000088;">$block</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'custom-some_new_block'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'module'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'custom'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'delta'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'some_new_block'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'region'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'right'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'weight'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">reactions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'block'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'blocks'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array_merge"><span style="color: #990000;">array_merge</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">reactions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'block'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'blocks'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$block</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#125;</span></pre></div> </div> <p>This time I threw in an array_merge to avoid clobbering the existing&nbsp;blocks.</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Terms:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">drupal</a></div><div class="field-item odd"><a href="/category/terms/context">context</a></div><div class="field-item even"><a href="/category/terms/dont-hack-core">don&#039;t-hack-core</a></div></div></div> Mon, 21 Jun 2010 23:05:01 +0000 Grayside 83 at http://grayside.org http://grayside.org/2010/06/modifying-contexts-old-fashioned-way#comments