<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://mikkel.hoegh.org" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Planet Drupal | Mikkel Høgh</title>
  <link>http://mikkel.hoegh.org/planet_drupal.xml</link>
  <atom:link href="http://mikkel.hoegh.org/planet_drupal.xml" rel="self" type="application/rss+xml" />
  <language>en</language>
  <generator>Octopress</generator>
  <description>Planet Drupal RSS feed for http://mikkel.hoegh.org</description>

<item>
    <title>Drupal is still a gated community</title>
    <link>http://mikkel.hoegh.org/2015/05/14/drupal-is-still-a-gated-community/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid
isPermaLink="true">http://mikkel.hoegh.org/2015/05/14/drupal-is-still-a-gated-community/</guid>
    <pubDate>Thu, 14 May 2014 21:03:00 +0200</pubDate>
    <description><![CDATA[
<p>One of the things the Drupal community prides itself on, is how open the community is. And that is generally true, but there's one exception.</p>

<p>And that is the Kafkaesque horror-show we subject any newcomers that would like to publish their code on Drupal.org to. It goes by the name of “<a href="https://www.drupal.org/project/projectapplications">Project Applications</a>“.</p>

<h4 id="neverendingreviews">Never ending reviews</h4>

<p>I know several people who've hit this wall when trying to contribute code. It's not uncommon to wait several months to get someone to review your code. And when it does happen, people are often rejected for tiny code style issues, like not ending their comments with a period or similar.</p>

<p>And even if you manage to satisfy all the reviewers (many of whom are just reviewing to earn “<a href="https://www.drupal.org/node/1975228">Review Bonus</a>”, see below), you can still wait several months for the powers that be to give you the magic stamp of approval. </p>

<p>Consequently, people give up. Who knows how many valuable contributors we lose, because they feel unwelcome and unappreciated? Most of the criticism in <a href="https://www.drupal.org/node/703116">this issue from 2010</a> is still true.</p>

<h4 id="reviewbonus">“Review Bonus”</h4>

<p>As mentioned before, the common answer to people that are frustrated with the waiting time, is that they should go get some brownie points to expect getting reviewed any time soon.</p>

<p>Basically, the messaging goes a bit like this:</p>

<blockquote>
  <p>Oh, you're unsatisfied with having to jump through all these hoops to contribute to our open source project? Here's some more hoops to jump through.</p>
</blockquote>

<p>If there's a more efficient way to make people angry, I can't really think of it.</p>

<p>And as another problem, because of this sweat-equity requirement, you now have newbies reviewing each other's code, with all sorts of perverse incentives to just review quickly and cursorily to get the review bonus, futher exacerbating the problem.</p>

<h4 id="onlyappliestonewbies">Only applies to newbies</h4>

<p>I've never had to gone through this. Neither have many Drupal developers I know. Because we were grandfathered in from the old CVS access system. It also had reviews, but to my memory, these were a lot less strict.</p>

<p>And once you pass the initial review, you're given the keys to the kingdom. After that, you can create as many new project, and publish as much terrible code on Drupal.org as you want to.</p>

<h4 id="doesitwork">Does it work?</h4>

<p>Not really. At the time of this writing, there were about 300 open requests in the <a href="https://www.drupal.org/project/issues/projectapplications?categories=All">Project applications queue</a>, most of them more than a month old.</p>

<h4 id="isthisevennecessary">Is this even necessary?</h4>

<p>In a word, no. I think Drupal is pretty unique in this regard. All other big open source communities I know of have no such requirements.</p>

<p>Packagist for Composer, GitHub, npm, Bower, etc. all allow anyone and everyone to create packages.</p>

<p>I imagine that some would argue that scary things can happen if you allow people to publish code without review. But if someone had sinister intentions, it would not be hard to wait with publishing malicious code until after the review, would it?</p>

<p>It's a bit like we're trying to achieve Apple's model for their App Store on Drupal.org, where everything is reviewed and safe to install. With the important difference that we don't have hundreds of full-time employees to make such reviews in a timely and professional manner.</p>

<h4 id="endthemadness">End the madness</h4>

<p>We can end the madness. We have the new community role on Drupal.org. How about we just require that for code publication, rather than trying to boil the ocean.</p>

<p>To my great shame, I was part of the initial discussions about this system, at DrupalCon Copenhagen in 2010. Back then, we were concerned about review times, and time has proven us right.</p>

<p>It was a valiant attempt. I think it's pretty clear that it does not, and will never, work to the degree we need it to. So let's change, make new people feel welcome again.</p>
]]></description>
  </item>


  <item>
    <title>Presenting the Opening Hours Module</title>
    <link>http://mikkel.hoegh.org/blog/2013/07/20/presenting-the-opening-hours-module/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2013/07/20/presenting-the-opening-hours-module/</guid>
    <pubDate>Sat, 20 Jul 2013 17:42:00 +0200</pubDate>
    <description><![CDATA[<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-teaser.png" width="583" height="180" title="Opening hours on Copenhagen Public Libraries’ web site" ></p>

<p>Do you need to tell your visitors when you are open for business? Your
office hours, when the service desk is open?</p>

<p>Then <a href="https://drupal.org/project/opening_hours">Opening Hours</a> might be the module for you. In this post, I&rsquo;m
going demonstrate how the module can be used, as well as some of the API
capabilities for extending it.</p>

<h2>The backstory</h2>

<p>In the autumn of 2011, <a href="http://bibliotek.kk.dk/">Copenhagen Public Libraries</a> decided that it
was about time they got a better solution for their opening hours.</p>

<p>Since the current site was first launched in 2009, we had been using a
hacked up version of another Drupal module, “office hours”, which was,
to say it mildly, rather user-hostile. It used a cascading rule system
to determine the opening hours, and suffice to say that people other
than myself understood how to use it.</p>

<p>So, we were given the task of coming up with something better, so
<a href="https://twitter.com/rasmusluckow">@rasmusluckow</a>, Joan (who sadly didn&rsquo;t live to see it deployed), and
I made a plan, and I started building the module in november 2011.</p>

<p>The plan was to create an administration interface similar to Google
Calender, with a very visual representation of what&rsquo;s going on.</p>

<p>Copenhagen Public Libraries was still on Drupal 6 back (in fact, it
still is), so we decided to build it for both versions. That meant we
could not easily take advantage of all the new fields hotness in Drupal
7, but it has made it a lot easier to maintain both versions together.</p>

<p>After a lot of development work, tests, and changes, we got the new
system live some time in spring 2012. I remember making an informal bet
with <a href="https://twitter.com/kasperg">@kasperg</a> that I had managed to fix all the wierd date and
timezone bugs. As it turns out, I lost…</p>

<p>Since the start, the module has <a href="https://drupal.org/project/opening_hours">been available on Drupal.org</a>,
but it has seen rather limited use outside the <a href="http://ting.dk/">Ding.TING</a> project for
which it was intended.</p>

<p>I hope to rectify that, and one of the ways is to provide more
documentation, making it easier to get started with the module.</p>

<h2>Installation and configuration</h2>

<p>The module is fairly simple to install as Drupal modules go. It depends
on the <a href="https://drupal.org/project/tipsy">Tipsy</a> and <a href="https://drupal.org/project/date">Date module</a> (for date popups). If you use
<a href="https://drupal.org/project/drush">drush</a>, you can get and install the requirements with a couple of
commands:</p>

<pre><code>drush dl date tipsy opening_hours
drush en taxonomy date_popup tipsy opening_hours
</code></pre>

<p><img class="right" src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-regional-settings.png" width="222" height="269" title="Regional settings" ></p>

<p>If not, download these modules manually, and enable Date Popup, Tipsy
tooltips, as well as Opening hours on the modules page. You might also
want to enable taxonomy for categorising opening hours, but more on that
later.</p>

<p>The Date API settings will allow you to configure which day the week
starts with (monday in most places, sunday in the U.S.).</p>

<h4>Nota bene</h4>

<p>While writing this, I found a bug in the Opening Hours module, that
causes the admin interface not to load correctly, when the opening hours
block is inserted on all pages. If you want to follow this tutorial, you
will need to <a href="https://drupal.org/node/1348432/release">get the latest version of this module</a>,
at the time of this writing, 7.x-1.5-beta1.</p>

<h3>Node type settings</h3>

<p>First off, we need to enable Opening Hours on the node type. In this
example, we&rsquo;re using car dealerships, but it could anything that needs
opening hours.</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-nodetype.png" width="691" height="469" title="Node type settings" ></p>

<h3>Your first opening hours</h3>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-node-tab.png" width="253" height="138" title="The opening hours tab" ></p>

<p>To use the opening hours, go to a node of the type you just enabled
opening hours on, and click the opening hours tab. Then you should see
something like this:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-empty.png" width="411" height="279" title="No hours yet" ></p>

<p>Click the empty cells below the dates to add hours to that date. This
brings up this dialog:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-dialog-empty.png" width="609" height="430" title="Empty dialog" ></p>

<p>The basic use case is quickly managed. Fill out open and closing times,
and if this is the general rule, you can set it to repeat every week.</p>

<p>So if you have open every monday 9:00-17:30, you would do something like
this:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-dialog-filled.png" width="613" height="433" title="Filled dialog" ></p>

<p>Repeating this for all week days, we get something like this:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-week-filled.png" width="502" height="203" title="Filled out week" ></p>

<p>If you made a repeat rule, you can use the navigation at the top to
switch to one of the following weeks and see the same hours.</p>

<h3>Displaying your hours</h3>

<p>Now, you have your hours entered, you probably also want to display them
on your site. The easiest way to accomplish this, is to insert the
opening hours block on the page via the Drupal&rsquo;s block administration:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-block-position.png" width="496" height="99" title="Block administration" ></p>

<p>Once done, you can see the opening hours on the node page, like this:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-block-display.png" width="690" height="425" title="Block administration" ></p>

<h3>Overriding</h3>

<p>Now, that&rsquo;s all well and good, but how about exceptions. Next week,
monday is closed?</p>

<p>No problem, just go back to the administration interface, navigate to
the week in question and click the hours for the day in question.</p>

<p>To mark this day as closed, simply delete its opening hours by clicking
“Delete this instance”.</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-editing.png" width="612" height="433" title="Editing hours" ></p>

<p>If you switched weeks before deleting, you should be presented with a
dialog like this one:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2013-07-20-opening-hours-delete-select.png" width="414" height="326" title="Editing hours" ></p>

<p>This is presented, since you’re deleting something from the middle of
the chain of repeated events, so your intentions might be different,
depending on the situation. You can choose between:</p>

<ol>
<li>Deleting the hours instance for just this week. In this example, that
means that this monday will be closed, but all previous and following
mondays will remain the same.</li>
<li>Deleting this week and all following instances. In this example, it
means that the monday in question will be close, as well as all
mondays after it.</li>
<li>Deleting the entire series. In this example, that means that all
mondays ever will appear to be closed.</li>
<li>Cancelling the deletion, leaving everything as it was.</li>
</ol>


<p>There&rsquo;s a similar workflow when you edit hours, so you can go to say,
week 42 and change the hours, and then apply them to all the following
weeks to have different winter opening hours, for example.</p>

<h3>To be continued</h3>

<p>There&rsquo;s a lot more ground to cover – categorisation, segments,
customisation and API, and this already took half a day to write, so I&rsquo;m
going to pick this up later and expand on it.</p>
]]></description>
  </item>

  <item>
    <title>How to configure Octopress for Drupal Planet syndication</title>
    <link>http://mikkel.hoegh.org/blog/2012/09/17/how-to-configure-octopress-for-drupal-planet-syndication/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2012/09/17/how-to-configure-octopress-for-drupal-planet-syndication/</guid>
    <pubDate>Mon, 17 Sep 2012 14:32:00 +0200</pubDate>
    <description><![CDATA[<p>Since I moved my blog to <a href="http://octopress.org/">Octopress</a>, I&rsquo;ve been struggling with my
blog posts not getting picked up by <a href="http://drupal.org/planet/">Planet Drupal</a>.</p>

<p>When I started using Octopress, it only had a site-wide <a href="http://en.wikipedia.org/wiki/Atom_%28standard%29">Atom feed</a>,
and despite my little experience with Ruby or Liquid, I managed to hack
together <a href="https://github.com/imathis/octopress/pull/201">category-specific feeds for Octopress</a>. These were
merged into Octopress core, so if you get the latest version from the
<code>master</code> branch, you should have these.</p>

<p>Sadly, despite <a href="http://mikkel.hoegh.org/blog/categories/drupal/atom.xml">my feed</a> being <a href="http://feedvalidator.org/check.cgi?url=http%3A%2F%2Fmikkel.hoegh.org%2Fblog%2Fcategories%2Fdrupal%2Fatom.xml">valid Atom 1.0</a>, Planet Drupal does
not parse it properly, and my blog posts were still not included in its
feed. This might not be all that surprising to someone more familiar
with the history of the <a href="https://github.com/drupal/drupal/blob/7.x/modules/aggregator/aggregator.module">aggregator.module</a>, which is the feed
aggregation module that ships with Drupal, that Planet Drupal uses for
its syndication.</p>

<p>Politely said, this module is not one of the parts of Drupal core that
gets the most attention, and its <a href="https://github.com/drupal/drupal/blob/7.x/modules/aggregator/aggregator.parser.inc#L67">feed parsing code</a> is not exactly
state-of-the-art. In fact, it only supports a subset of the Atom spec
and a particular version of the older and inferior <a href="http://en.wikipedia.org/wiki/RSS">RSS</a>. Now, I won&rsquo;t
get into the nasty <a href="http://en.wikipedia.org/wiki/History_of_web_syndication_technology">history of web syndication technology</a>, but
suffice to say that this is one of the instances where I find myself
wishing that the Drupal community wasn&rsquo;t so <a href="http://en.wikipedia.org/wiki/Not_Invented_Here">NIH</a>-prone. (that goes
for you, too, project.module).</p>

<p>So, long story short, if you want to be on Drupal planet, you have to
implement a feed format it understands, so I made an old-school RSS
format, that should correspond almost exactly to what Drupal itself
outputs when it generates feeds.</p>

<h2>The template</h2>

<figure class='code'><figcaption><span>&#8220;Drupal Planet feed template&#8221;  (planet_drupal.xml)</span> <a href='http://mikkel.hoegh.org/downloads/code/planet_drupal.xml'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='xml'><span class='line'>---
</span><span class='line'>layout: nil
</span><span class='line'>---
</span><span class='line'><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span>
</span><span class='line'><span class="nt">&lt;rss</span> <span class="na">version=</span><span class="s">&quot;2.0&quot;</span> <span class="na">xml:base=</span><span class="s">&quot;{{ site.url }}&quot;</span> <span class="na">xmlns:atom=</span><span class="s">&quot;http://www.w3.org/2005/Atom&quot;</span> <span class="na">xmlns:dc=</span><span class="s">&quot;http://purl.org/dc/elements/1.1/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;channel&gt;</span>
</span><span class='line'>  <span class="nt">&lt;title&gt;</span>Planet Drupal | {{ site.title | xml_escape }}<span class="nt">&lt;/title&gt;</span>
</span><span class='line'>  <span class="nt">&lt;link&gt;</span>{{ site.url }}/planet_drupal.xml<span class="nt">&lt;/link&gt;</span>
</span><span class='line'>  <span class="nt">&lt;atom:link</span> <span class="na">href=</span><span class="s">&quot;{{ site.url }}/planet_drupal.xml&quot;</span> <span class="na">rel=</span><span class="s">&quot;self&quot;</span> <span class="na">type=</span><span class="s">&quot;application/rss+xml&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;language&gt;</span>en<span class="nt">&lt;/language&gt;</span>
</span><span class='line'>  <span class="nt">&lt;generator&gt;</span>Octopress<span class="nt">&lt;/generator&gt;</span>
</span><span class='line'>  <span class="nt">&lt;description&gt;</span>Planet Drupal RSS feed for {{ site.url }}<span class="nt">&lt;/description&gt;</span>
</span><span class='line'>
</span><span class='line'>{% for post in site.categories[&#39;Drupal&#39;] limit: 10 %}
</span><span class='line'>  <span class="nt">&lt;item&gt;</span>
</span><span class='line'>    <span class="nt">&lt;title&gt;</span>{{ post.title | xml_escape }}<span class="nt">&lt;/title&gt;</span>
</span><span class='line'>    <span class="nt">&lt;link&gt;</span>{{ site.url }}{{ post.url }}<span class="nt">&lt;/link&gt;</span>
</span><span class='line'>    <span class="nt">&lt;dc:creator&gt;</span>{{ site.author | xml_escape }}<span class="nt">&lt;/dc:creator&gt;</span>
</span><span class='line'>    <span class="nt">&lt;guid</span> <span class="na">isPermaLink=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;</span>{{ site.url }}{{ post.url }}<span class="nt">&lt;/guid&gt;</span>
</span><span class='line'>    <span class="nt">&lt;pubDate&gt;</span>{{ post.date | date: &quot;%a, %d %b %Y %H:%M:%S %z&quot; }}<span class="nt">&lt;/pubDate&gt;</span>
</span><span class='line'>    <span class="nt">&lt;description&gt;</span><span class="cp">&lt;![CDATA[{{ post.content | expand_urls: site.url | cdata_escape }}]]&gt;</span><span class="nt">&lt;/description&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/item&gt;</span>
</span><span class='line'>{% endfor %}
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;/channel&gt;</span>
</span><span class='line'><span class="nt">&lt;/rss&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>How to do it</h2>

<ol>
<li>Download the feed template attached above.</li>
<li><p>Put it somewhere in the <code>source</code> folder of your Octopress site.</p>

<p> I have it at <code>source/planet_drupal.xml</code>, but the name and location
 should make no difference at all. Since I have it at the route of
 the source tree, my feed is available at <a href="http://mikkel.hoegh.org/planet_drupal.xml">http://mikkel.hoegh.org/planet_drupal.xml</a></p></li>
<li>Change the <code>{% for post in site.categories['Drupal'] limit: 10 %}</code>
 line to match the name of the category you want to make a feed of.
 In my case, the category name is <code>Drupal</code>. This is probably case
 sensitive, so be sure to be consistent when categorizing your posts.</li>
<li><p>If you haven&rsquo;t done so already, tag your posts with the right
 category to have them included in the feed.</p>

<p> This is how this post is tagged, for reference. This is standard
 Octopress post metadata.</p>

<pre><code> ---
 layout: post
 title: "How to configure Octopress for Drupal Planet syndication"
 date: 2012-08-12 22:32
 comments: true
 categories: [ Drupal, Octopress ]
 ---
 [post body here]
</code></pre></li>
<li>Redirect your current feed address or report your new feed address to
 the Drupal.org webmasters.</li>
</ol>

]]></description>
  </item>

  <item>
    <title>Shave a couple of stubborn of DIV-wrappers off your Drupal site</title>
    <link>http://mikkel.hoegh.org/blog/2011/10/20/shave-a-couple-stubborn-of-div-wrappers-off-your-drupal-site/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2011/10/20/shave-a-couple-stubborn-of-div-wrappers-off-your-drupal-site/</guid>
    <pubDate>Thu, 20 Oct 2011 19:27:00 +0200</pubDate>
    <description><![CDATA[<p>One of the more annoying things about theming <a href="http://drupal.org/">Drupal</a> sites is having
to wade through the staggering amounts of wrapping <code>&lt;div&gt;</code> elements and
containers. Some of these are are fairly easy to get rid of. Others
require you to override core templates.</p>

<p>I recently found a clean way to get rid of a couple of those. These two
were introduced in Drupal 7, and you will probably find them on almost
all Drupal 7 sites – they look like this:</p>

<p><img src="http://mikkel.hoegh.org/images/static/2011-10-20-revealit-wrappers.png" width="777" height="125" title="Triple wrapped content" ></p>

<p>Or in markup:</p>

<figure class='code'><figcaption><span>The culprits </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;region region-content&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;block-system-main&quot;</span> <span class="na">class=</span><span class="s">&quot;block block-system&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;content&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="c">&lt;!-- Actual page content here --&gt;</span>
</span><span class='line'>    <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/div&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now, the last of these wrappers are actually useful, the rest stems from
one of the changes in Drupal 7, namely that the main page content is now
a block, that can be positioned on the page via Drupal’s block system.</p>

<p>Now, that&rsquo;s a nice concept, but all the site I&rsquo;ve seen do business as
usual, and get around this inconvenience by creating a block region
called “content” and sticking the content-block in there as the only
thing, leaving the region and block wrappers as more DIV-spam in your
site’s markup.</p>

<p>So unless you&rsquo;re actually doing something different with the content
block and/or region, you can just get rid of these extra wrappers by
sticking the two following templates in your theme’s template folder:</p>

<figure class='code'><figcaption><span> (region&#8211;content.tpl.php)</span> <a href='http://mikkel.hoegh.org/downloads/code/region--content.tpl.php'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * @file</span>
</span><span class='line'><span class="sd"> * Render the main content block region.</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * We don&#39;t print all kinds of wrapper divs and titles, just the content.</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">print</span> <span class="nv">$content</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<figure class='code'><figcaption><span> (block&#8211;system&#8211;main.tpl.php)</span> <a href='http://mikkel.hoegh.org/downloads/code/block--system--main.tpl.php'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * @file</span>
</span><span class='line'><span class="sd"> * Render the main content block.</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * We don&#39;t print all kinds of wrapper divs and titles, just the content.</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">print</span> <span class="nv">$content</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Short and sweet :)</p>
]]></description>
  </item>

  <item>
    <title>Using Database-level Foreign Keys in Drupal 7</title>
    <link>http://mikkel.hoegh.org/blog/2011/10/06/using-database-level-foreign-keys-in-drupal-7/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2011/10/06/using-database-level-foreign-keys-in-drupal-7/</guid>
    <pubDate>Thu, 06 Oct 2011 18:05:00 +0200</pubDate>
    <description><![CDATA[<p>If you use a <a href="http://www.postgresql.org/">good database system</a>, foreign keys is an
actual concept on the server that is used to enforce data integrity.</p>

<p>With database-level foreign keys, it becomes impossible to break your
data by deleting data referenced by other data, without also dealing
with the referenced data.</p>

<p>In practice this means that deleting a node from the database could be
as simple as <code>DELETE FROM node WHERE nid = 53 CASCADE</code>, and conversely
it would not be allowed to delete the row from the <code>node</code> table, as long
as it is referenced in <code>node_revision</code>, <code>field_something_something</code> and
the umpteen other tables a <a href="http://drupal.org/">Drupal</a> site is likely to have that depends on
the node table.</p>

<p>Currently, it&rsquo;s neigh-impossible to delete a node or another entity from
the database without using Drupal&rsquo;s API. This is a sticky problem if you
ever need to share the database between systems.</p>

<p>In Drupal 7, the syntax to define foreign keys were introduced to
Drupal’s schema API. The schema API is used to explain the database
structure to Drupal, so it can be understood and utilised by modules
like Views. This understanding is also translated into SQL code, when
tables are created by Drupal’s install scripts.</p>

<p>However, the foreign key syntax introduced in Drupal 7 does not affect
the database structure at all, it is only used inside Drupal for
relating one table to another. Perhaps in time, Drupal will also create
the foreign keys at the database level, but until that happens, you will
need to create them manually. Here&rsquo;s how to do it.</p>

<h2>An example</h2>

<p>In the following example, I define two tables, and then use hook_install
and hook_uninstall to set up and dismantle the foreign keys.</p>

<figure class='code'><figcaption><span> (2011-10-05-foreign-key-example.php)</span> <a href='http://mikkel.hoegh.org/downloads/code/2011-10-05-foreign-key-example.php'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * @file</span>
</span><span class='line'><span class="sd"> * Installation and upgrade code for Zavod supplier.</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Implements hook_schema().</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">function</span> <span class="nf">zavod_supplier_schema</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nv">$schema</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">$schema</span><span class="p">[</span><span class="s1">&#39;zavod_suppliers&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Stock suppliers for Zavod.&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;fields&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>      <span class="s1">&#39;supplier_id&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;The primary identifier for a supplier.&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;serial&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;unsigned&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;not null&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>      <span class="s1">&#39;title&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;The title of this supplier, always treated as non-markup plain text.&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;text&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;not null&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>    <span class="p">),</span>
</span><span class='line'>    <span class="s1">&#39;primary key&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;supplier_id&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">$schema</span><span class="p">[</span><span class="s1">&#39;zavod_supply_orders&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Supply orders for Zavod.&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;fields&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>      <span class="s1">&#39;order_id&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;The primary identifier for a supply order.&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;serial&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;unsigned&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;not null&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>      <span class="s1">&#39;supplier_id&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;{zavod_suppliers}.supplier_id of the supplier that the order is made to.&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;not null&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;unsigned&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>      <span class="s1">&#39;title&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;description&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;The title of this order, always treated as non-markup plain text.&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;text&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;not null&#39;</span> <span class="o">=&gt;</span> <span class="k">TRUE</span><span class="p">,</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>    <span class="p">),</span>
</span><span class='line'>    <span class="s1">&#39;foreign keys&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>      <span class="s1">&#39;zavod_suppliers&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;table&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;zavod_suppliers&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;columns&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;supplier_id&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;supplier_id&#39;</span><span class="p">),</span>
</span><span class='line'>      <span class="p">),</span>
</span><span class='line'>    <span class="p">),</span>
</span><span class='line'>    <span class="s1">&#39;primary key&#39;</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;order_id&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nv">$schema</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Implements hook_install().</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">function</span> <span class="nf">zavod_supplier_install</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Make real foreign keys.</span>
</span><span class='line'>  <span class="nx">db_query</span><span class="p">(</span><span class="s1">&#39;</span>
</span><span class='line'><span class="s1">    ALTER TABLE {zavod_supply_orders}</span>
</span><span class='line'><span class="s1">    ADD CONSTRAINT {zavod_suppliers}</span>
</span><span class='line'><span class="s1">    FOREIGN KEY (supplier_id) REFERENCES {zavod_suppliers} (supplier_id)</span>
</span><span class='line'><span class="s1">  &#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Implements hook_uninstall().</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">function</span> <span class="nf">zavod_supplier_uninstall</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Make real foreign keys.</span>
</span><span class='line'>  <span class="nx">db_query</span><span class="p">(</span><span class="s1">&#39;</span>
</span><span class='line'><span class="s1">    ALTER TABLE {zavod_supply_orders}</span>
</span><span class='line'><span class="s1">    DROP CONSTRAINT IF EXISTS {zavod_suppliers}</span>
</span><span class='line'><span class="s1">  &#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s pretty self-explanatory if you&rsquo;re used to Drupal&rsquo;s schema API. If
you&rsquo;re not, you should definitely learn.</p>
]]></description>
  </item>

  <item>
    <title>How to install multicore Apache Solr on FreeBSD with Jetty</title>
    <link>http://mikkel.hoegh.org/blog/2011/07/24/install-multicore-apache-solr-freebsd-jetty/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2011/07/24/install-multicore-apache-solr-freebsd-jetty/</guid>
    <pubDate>Sun, 24 Jul 2011 00:00:00 +0200</pubDate>
    <description><![CDATA[<p>If you use <a href="http://lucene.apache.org/solr/">Apache Solr</a> with your <a href="http://drupal.org/">Drupal</a> site, you have probably
come across the need to have more than one Solr instance. You may have
multiple sites, or just multiple copies of the same site, production and
staging perhaps?</p>

<p>There are two widely published ways to accomplish that. One is to set up
completely separate Solr instances with whatever Java-server you’re
using. That is somewhat inefficient, and I was unable to get such a
setup working properly anyways. So here’s the alternative, “<a href="http://wiki.apache.org/solr/CoreAdmin">multi core</a>”.</p>

<p>The benefit of using multi core is that you avoid most of the
configuration overhead associated with figuring out how to get multiple
<code>WebAppContainerDeploymentContextFactoryGeneratorWidgetClass</code> instances
(or whatever they’re named in your brand of Java-server) to coexist by
using the same WAR-file but not the same configuration. I spent a lot of
hours trying to accomplish just that.</p>

<p>Instead, all the interesting stuff happens in the Solr configuration,
which is a lot less confusing for a Java novice like me.</p>

<h2>Instructions</h2>

<ol>
<li><p>Install a Java JRE.</p>

<p>You may want to see <a href="http://serverfault.com/questions/1077/how-to-install-java-jre-on-freebsd-with-as-few-dependencies-as-possible">my explanation on how to do this</a>.</p></li>
<li><p>Install <a href="http://jetty.codehaus.org/jetty/">Jetty</a> and Solr.</p>

<p>If you use <code>portmaster</code>, this can be as simple as running <code>portmaster www/jetty textproc/apache-solr</code></p></li>
<li><p>Create a folder for your Solr multi core instance’s configuration and
data files. This could be anywhere, but in this example, I&rsquo;m going to
use <code>/srv/solr</code>.</p></li>
<li><p>Create a <code>/srv/solr/solr.xml</code> file for the configuration, setting up
the different cores into folders.</p>

<p>Mine looks like this:</p>

<p><figure class='code'><figcaption><span> (solr.xml)</span> <a href='http://mikkel.hoegh.org/downloads/code/solr.xml'>download</a></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span>
</span><span class='line'><span class="c">&lt;!&mdash;</span>
</span><span class='line'><span class="c">All (relative) paths are relative to the installation path</span>
</span><span class='line'><span class="c">  </span>
</span><span class='line'><span class="c">  persistent: Save changes made via the API to this file</span>
</span><span class='line'><span class="c">  sharedLib: path to a lib directory that will be shared across all cores</span>
</span><span class='line'><span class="c">&mdash;&gt;</span>
</span><span class='line'><span class="nt">&lt;solr</span> <span class="na">persistent=</span><span class="s">&quot;false&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c">&lt;!&mdash;</span>
</span><span class='line'><span class="c">  adminPath: RequestHandler path to manage cores.  </span>
</span><span class='line'><span class="c">    If &#39;null&#39; (or absent), cores will not be manageable via request handler</span>
</span><span class='line'><span class="c">  &mdash;&gt;</span>
</span><span class='line'>  <span class="nt">&lt;cores</span> <span class="na">adminPath=</span><span class="s">&quot;/admin/cores&quot;</span> <span class="na">sharedLib=</span><span class="s">&quot;lib&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;core</span> <span class="na">name=</span><span class="s">&quot;dev&quot;</span> <span class="na">instanceDir=</span><span class="s">&quot;dev&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>    <span class="nt">&lt;core</span> <span class="na">name=</span><span class="s">&quot;prod&quot;</span> <span class="na">instanceDir=</span><span class="s">&quot;prod&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>    <span class="nt">&lt;core</span> <span class="na">name=</span><span class="s">&quot;stg&quot;</span> <span class="na">instanceDir=</span><span class="s">&quot;stg&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/cores&gt;</span>
</span><span class='line'><span class="nt">&lt;/solr&gt;</span>
</span></code></pre></td></tr></table></div></figure></p></li>
<li><p>Create all the folders referenced in the config file.</p>

<p>We specified four folders, so lets create them via a simple
<code>mkdir dev lib prod stg</code> (while standing in the <code>/srv/solr</code> folder).</p></li>
<li><p>Make these folders owned by the user that will run our Solr
instances. In this example, I’ll use the <code>www</code> account, but it would
be more secure to set up a separate account for running Solr if you
have other web servers running on the same machine.</p>

<p><code>chown www:www dev lib prod stg</code></p></li>
<li><p>For each core you want to set up, copy or symlink the schema and
other configuration files you need into the conf folder in each core
folder. In this example, I&rsquo;m copying the example configuration from
<code>/usr/local/share/examples/apache-solr/solr/conf/</code>. If you&rsquo;re working
with Drupal, be sure to copy the solr configuration it ships with
into each core.</p>

<p><code>mkdir prod/conf</code><br/>
<code>cd prod/conf</code><br/>
<code>cp -r /usr/local/share/examples/apache-solr/solr/conf/* ./</code><br/>
<code>cd ../..</code>
<code>cp -r prod/conf dev/</code>
<code>cp -r prod/conf stg/</code></p></li>
<li><p>Enable Jetty</p>

<p>In this example, we’re going to use <a href="http://jetty.codehaus.org/jetty/">Jetty</a> to run the Solr
service. I am not well versed in the Java lingo for this, but Jetty
is a servlet container, so I guess that means Solr is being run as a
servlet. I also tried this with Tomcat, but that was a lot harder to
configure properly.</p>

<p>Add <code>jetty_enable="YES"</code> on a new line in <code>/etc/rc.conf</code>.</p></li>
<li><p>Copy <code>/usr/local/jetty/etc/jetty.xml</code> to <code>/usr/local/etc</code>.</p></li>
<li><p>Symlink <code>solr.war</code> into <code>/usr/local/jetty/webapps</code></p></li>
</ol>


<p>   <code>cd /usr/local/jetty/webapps</code><br/>
   <code>ln -s /usr/local/share/java/classes/apache-solr-3.2.0.war solr.war</code></p>

<ol>
<li>Symlink <code>/srv/solr</code> into <code>/usr/local/jetty</code></li>
</ol>


<p>   <code>cd /usr/local/jetty</code>
   <code>ln -s /srv/solr</code></p>

<ol>
<li>Start Jetty by running <code>service jetty start</code></li>
</ol>


<p>Hopefully, after all this work, Solr should be ready once its done
booting up.</p>

<p>You can check that it&rsquo;s working by running
<code>curl -iL localhost:8080/solr/prod/admin/</code>. This should output the HTML
for the admin interface.</p>

<p>If you have problems, try running <code>tail -f /usr/local/jetty/jetty.log</code>
in one terminal, and then <code>service jetty restart</code> in another, and look
what goes on as Jetty restart (there&rsquo;ll be a lot of messages flying by,
but the error should be in there somewhere).</p>
]]></description>
  </item>

  <item>
    <title>del.icio.us – can the Drupal community do better?</title>
    <link>http://mikkel.hoegh.org/blog/2010/12/20/delicious-drupal-community-better/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2010/12/20/delicious-drupal-community-better/</guid>
    <pubDate>Mon, 20 Dec 2010 00:00:00 +0100</pubDate>
    <description><![CDATA[<p>As you may know, Yahoo! is in trouble, and has decided to <a href="http://blog.delicious.com/blog/2010/12/whats-next-for-delicious.html">jettison the
social bookmarking service del.icio.us</a> (Delicious).</p>

<p>I am not a big delicious user anymore (actually, I deleted my account
when Microsoft was trying to purchase Yahoo!), but this recent closing
made me wonder if the Drupal community couldn’t do better…</p>

<p>One of the great strengths of Drupal is self-hosting, and a bookmarking
service is not a complicated thing.</p>

<p>Thus, I am planning to put in a bit of effort into having my own
bookmarks section here on this very site. A bookmark content type should
not take long to configure with the <a href="http://drupal.org/project/links">Links</a> module, <a href="http://drupal.org/project/auto_nodetitle">Automatic Nodetitles</a>
to make sure the nodes have the same title as the link
itself, and a bit of <a href="http://drupal.org/project/views">Views</a> work should make it presentable.</p>

<h4>Workflow</h4>

<p>The main issue here is workflow. Nowadays, I use Google Reader’s sharing
interface for “bookmarking” links, since it has a nice interface for
tagging, putting notes on there, etc.</p>

<p>So what’s really missing in my workflow is some way of getting that data
into Drupal, and since Google provides a <a href="https://www.google.com/reader/public/atom/user%2F15265426901976190807%2Fstate%2Fcom.google%2Fbroadcast">very tasty atom feed with lots
of metadata</a> for all my shared entries, it should be doable with
a bit of add-on code for the <a href="http://drupal.org/project/feeds">Feeds</a> module.</p>

<h4>What to do?</h4>

<p>The main thing I would like to know here is if other Drupallers would be
interestered in such a thing, and if anyone has input as to how it best
could be built? I suppose a <a href="http://drupal.org/project/features">Features</a> module could be in order, but I
have not seen a whole lot of those published on Drupal.org. Is it wise?</p>

<p>And where to put my Google Reader for Feeds module integration? I
suppose I could make a separate project for that on d.o, but that seems
a bit overkill-like. Any takers?</p>
]]></description>
  </item>

  <item>
    <title>Relauching my blog on Drupal 7</title>
    <link>http://mikkel.hoegh.org/blog/2010/10/07/relaunching-blog-drupal-7/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2010/10/07/relaunching-blog-drupal-7/</guid>
    <pubDate>Thu, 07 Oct 2010 00:00:00 +0200</pubDate>
    <description><![CDATA[<p>More than a year ago, <a href="http://mikkel.hoegh.org/blog/2009/08/27/going-edge-drupal-7">I was agitating for a move to Drupal 7</a>
for all the blogging developers. As is rather obvious now, Drupal 7 was
not in a state then for public websites. There was outstanding security
issues, no upgrade path, lots of API changes to be made, etc.</p>

<p>However, since that has all been resolved now, I figured it was about
time I moved my blog over. I have obviously been preparing for this for
some time, as I will get back to in later blog posts.</p>

<p>However, I would once again like to encourage fellow developers to
experiment with Drupal 7. The process of building a real, public-facing
website with Drupal 7 so soon in the process have taught me a lot of
Drupals innards, and helped me uncover a fair number of bugs in Drupal
core and contributed modules that have since been fixed.</p>

<p>As you can also see in the <a href="http://drupal.org/drupal-7.0-beta1">7.0 beta 1 accouncement</a>, there is a
lot to be exited about, and as we have entered the beta-phase, upgrades
will be supported from now on, so the site you create with beta 1 should
be upgradable all the way to the final release.</p>

<p>So if you can spare the time to fiddle with it, I highly recommend it.
It is an educative challenge – enjoy :)</p>
]]></description>
  </item>

  <item>
    <title>Protecting your users from phishing with Apache rules and HSTS</title>
    <link>http://mikkel.hoegh.org/blog/2010/09/09/protecting-your-users-phishing-apache-rules-hsts/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2010/09/09/protecting-your-users-phishing-apache-rules-hsts/</guid>
    <pubDate>Thu, 09 Sep 2010 00:00:00 +0200</pubDate>
    <description><![CDATA[<p>HTTP Strict Transport Security or <a href="http://en.wikipedia.org/wiki/Strict_Transport_Security">HSTS</a> is a new security feature in
browsers that enables you tell the browser “<em>always use SSL when
accessing this site</em>”.</p>

<p>Mozilla has a <a href="http://hacks.mozilla.org/2010/08/firefox-4-http-strict-transport-security-force-https/">good blog post explaining HSTS</a>, so I won’t try
to replicate that here, but I’d just like to make it clear that if you
have a site that should always use SSL, be it <a href="http://drupal.org/">Drupal</a> or <a href="http://www.djangoproject.com/">Django</a>
or any other system, this is definitely something you should get set up.</p>

<p>Good examples of these are webmail, server administration and monitoring
tools and general admin backends. If you are running a large
Drupal-site, you should perhaps consider restricting admin-access to a
SSL-protected subdomain.</p>

<p>Currently, it is only supported in Chrome 4 and above, and Firefox 4
beta 5 and beyond, but hopefully the other browser makers will catch up
soon. Its fully backwards compatible, in that it will have no effect if
the browser does not support HSTS.</p>

<h4>How to use it</h4>

<p>Setting it up is very simple. In your <a href="http://httpd.apache.org/">Apache</a> VHost, where you do your
SSL config, just add this line:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Header add Strict-Transport-Security "max-age=15768000"</span></code></pre></td></tr></table></div></figure>


<p>This will tell the browser to remember that this site is SSL/HTTPS only
for the next 6 months. During that time it will simply rewrite any and
all requests to that site to use HTTPS instead of HTTP without ever
communicating insecurely with the server.</p>

<p>If you use <a href="http://wiki.nginx.org/">nginx</a>, the syntax is subtly different. Adding this to
the server section does the trick:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>add_header Strict-Transport-Security max-age=15768000;</span></code></pre></td></tr></table></div></figure>


<h4>Keep your redirects</h4>

<p>An important point is that HSTS only works <em>after</em> the user has received
the header via HTTPS. So you will still need to have a redirect from
your HTTP-site to HTTPS, also for supporting browsers that still do not
understand HSTS.</p>

<p>This is easily accomplished using Apache’s <code>mod_rewrite</code>:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>&lt;IfModule mod_rewrite.c&gt;
</span><span class='line'>  RewriteEngine On
</span><span class='line'>  RewriteCond %{HTTPS} off
</span><span class='line'>  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</span><span class='line'>&lt;/IfModule&gt;</span></code></pre></td></tr></table></div></figure>


<p>Thus, with a few lines of configuration, you can make the web a safer place
to be for your users. So, what are you waiting for?</p>
]]></description>
  </item>

  <item>
    <title>A tip for using PostgreSQL with Drupal 6</title>
    <link>http://mikkel.hoegh.org/blog/2010/08/09/tip-using-postgresql-drupal-6/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2010/08/09/tip-using-postgresql-drupal-6/</guid>
    <pubDate>Mon, 09 Aug 2010 00:00:00 +0200</pubDate>
    <description><![CDATA[<p>If you are using <a href="http://www.postgresql.org/">PostgreSQL</a> for hosting
your <a href="http://drupal.org/">Drupal</a> sites, you might have noticed a lot of
warnings in your logs like these:</p>

<pre><code>Aug  8 18:41:05 s002 postgres[90076]: [5-1] WARNING:  nonstandard use of \\ in a string literal at character 32
Aug  8 18:41:05 s002 postgres[90076]: [5-2] HINT:  Use the escape string syntax for backslashes, e.g., E'\\'.
Aug  8 18:41:05 s002 postgres[90076]: [6-1] WARNING:  nonstandard use of \\ in a string literal at character 122
Aug  8 18:41:05 s002 postgres[90076]: [6-2] HINT:  Use the escape string syntax for backslashes, e.g., E'\\'.
</code></pre>

<p>The immediate cause for this is
<a href="http://drupal.org/node/426008">bug #426008 in Drupal core</a>, but the
issue stems from the fact that PostgreSQL does not conform exactly to
the SQL standard with regards to backslashes in strings. The reasoning
behind this and why its going away (as a default setting) in PostgreSQL
9.1 can be read in <a href="http://momjian.us/main/blogs/pgblog/2010.html#August_9_2010">this excellent blog post by Bruce Momjian</a>.</p>

<h4>But how do I fix it?</h4>

<p>The good news is that this behavior is configurable. You can set
<code>standard_conforming_strings = on</code> in your <code>postgresql.conf</code> and be done
with it. This will be the default setting from PostgreSQL 9.1, and
hopefully the other applications using your database do not depend on
the legacy behavior (if they do, they need fixing).</p>

<p>If that’s not suitable for your setup, there is a few other suggestions
<a href="http://dbaspot.com/forums/postgresql/251026-many-warning-pg-logs-nonstandard-use-string-literalat-character.html#post1004812">in this forum thread</a>.</p>
]]></description>
  </item>

  <item>
    <title>Attention all Drupal Git-mirror users</title>
    <link>http://mikkel.hoegh.org/blog/2009/11/09/attention-all-drupal-git-mirror-users/</link>
    <dc:creator>Mikkel Høgh</dc:creator>
    <guid isPermaLink="true">http://mikkel.hoegh.org/blog/2009/11/09/attention-all-drupal-git-mirror-users/</guid>
    <pubDate>Mon, 09 Nov 2009 00:00:00 +0100</pubDate>
    <description><![CDATA[<p>A long-standing issue with the Git mirrors of Drupal&rsquo;s CVS has been
fixed thanks to <a href="http://drupal.org/user/22211">Damien Tournoud</a>.</p>

<p>The problem is that CVS outputs dates in RCS tags in the somewhat
nonstandard format <em>2009/10/19</em> (<a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a>
specifies dashes, not slashes as separator). The git-cvsimport tool used
for creating the mirrors, however, uses
<a href="http://www.cobite.com/cvsps/">cvsps</a>, that updates the RCS tags to use
the correct format (<em>2009-10-19</em>). Adhering to standards is generally a
good thing, but in this case it was causing merge conflicts when trying
to merge patches created with Git into Drupal (or vice versa).</p>

<p>Damien found a way to resolve the issue, however:</p>

<blockquote><p>Adding DateFormat=old to the CVSROOT/config file fixes the problem.</p></blockquote>

<p>Changing this, however, required a reimport of the entire repository.
Due to the way Git works with commit-ids being a cryptographic hash of
their contents, changing the contents (even if just the RCS tags) means
a rewrite of Git history.</p>

<p>So while the new repository contains the same code, you will not be able
to merge new changes from it into your current checkouts. Damien will
continue both imports for a while, but updates for the old repository
with the incompatible date format will be discontinued at a future date.</p>

<p>What is the bottom line then?</p>

<h4>The executive summary</h4>

<ol>
<li>The Git mirror at git://github.com/drupal/drupal.git has been
rewritten with it&rsquo;s RCS tag date format compatible with CVS defaults.
Please use this mirror for all your future projects.</li>
<li>The Git mirror at git://github.com/mikl/drupal.git will continue to
have the CVS-incompatible format, and will, for a time, continue to be
updated, so you will be able to use it for a little while longer.</li>
<li>There is now no excuse for not using Git for your Drupal core
development work. Enjoy.</li>
</ol>


<p>Finally, I&rsquo;d like to thank Damien for doing all the hard work. I was maintaining the git-cvsimport process myself for a while, and I do not miss it.</p>
]]></description>
  </item>


</channel>
</rss>

