<?xml version="1.0" encoding="utf-8"?>
	<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	
		<title type="text">Blog &#45; John D Wells</title>
		<subtitle type="text"></subtitle>
		<link rel="alternate" type="text/html" href="http://johndwells.com/blog/" />
		<link rel="self" type="application/atom+xml" href="http://johndwells.com/blog/atom" />
		<updated>2015-01-02T16:05:12Z</updated>
		<rights>Copyright (c) 2015, John D Wells</rights>
		<generator uri="http://expressionengine.com/" version="2.8.1">ExpressionEngine</generator>
		<id>tag:johndwells.com,2015:01:02</id>
	
		
			<entry>
				<title>My Wishes for 2015</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/my-wishes-for-2015" />
				<id>tag:johndwells.com,2015:blog/3.98</id>
				<published>2015-01-02T13:43:00Z</published>
				<updated>2015-01-02T16:05:12Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="Business"
						scheme="http://johndwells.com/blog/archives/category/business"
						label="Business" />
				
					<category term="Personal"
						scheme="http://johndwells.com/blog/archives/category/Personal"
						label="Personal" />
				
					<category term="Productivity"
						scheme="http://johndwells.com/blog/archives/category/productivity"
						label="Productivity" />
				
				<content type="html"><![CDATA[
					<p>2014 was a year with mixed reviews - incredible highs, devastating lows, and a frantic pace that seemed to cripple any attempt to take control of the year&#8217;s direction. After a two week hiatus over the holidays to catch my breath, here&#8217;s what I&#8217;d like to get out of 2015.</p>
					<p class="aside">
	<em>This is also not a finely-crafted article, but rather a work in progress - so don&#39;t be surprised if you find unfinished thoughts or even sentences.</em></p>
<p>
	This is not a "New Years Resolution" post at all - it&#39;s more of a diary entry that I&#39;ve decided to publish in the hopes it stands as a signpost that I can return to throughout the months to come. I am notoriously bad at keeping these sort of commitments, and while it&#39;s therefore tempting to temper my aspirations, it&#39;s also true that failure is squarely in the path towards success.</p>
<h2>
	Making, Signing &amp; Keeping Contracts</h2>
<p>
	Our company does a mediocre of the paperwork side of business. We&#39;ve made some minimal strides in the past but as we grow in size and take on bigger (and more costly) projects, we need to get some contracts in place. I&#39;d like to see at a minimum a one-time contract signed between ourselves and clients, establishing things such as:</p>
<ul>
	<li>
		rules of payment</li>
	<li>
		payment or deliverable dispute</li>
	<li>
		early project termination</li>
	<li>
		intellectual property expectations</li>
	<li>
		fee structures</li>
	<li>
		IE8 policy (see below)</li>
	<li>
		included support &amp; warranties</li>
</ul>
<p>
	I&#39;m sure there are other things to cover, and perhaps more contracts to sign. I&#39;m happy to hear suggestions.</p>
<h2>
	Support Revenue</h2>
<p>
	Our cozy relationship with our clients means that we often provide support at no cost. I think it&#39;s time we are compensated for our committment to being a phone call away. &nbsp;I&#39;d be more than happy with a simple nominal fee, even if it only covers 50% of what we may do in return. It would still be a great step in the right direction.</p>
<h2>
	Referral &amp; Markup Revenue</h2>
<p>
	In the past I have always been hesitant to skim money off the top of referrals or white label systems, but the lack of wisdom in that stance is financially crippling, to be honest. &nbsp;We suggest services to our clients, and sometimes even run them on their behalf.</p>
<h2>
	Company Internet/Social Profile</h2>
<p>
	Our company website does a good job of presenting our work, but it does very little to introduce who we are behind the name. Our Facebook page similarly doesn&#39;t do much to show off our personalities; our Twitter page comes the closest, which is a sad testament.</p>
<p>
	I think this is an important task to tackle as I think it will play a central role in acquiring new work this year. &nbsp;I&#39;d love to see us start blogging, or at least start creating something online that is ours and not our clients... actually, that&#39;s exactly what I want: to release, publish, create&nbsp;<em>something</em> that is <a href="http://onedarnleyroad.com">One Darnley Road</a>&#39;s. I don&#39;t care if it&#39;s a page that tells you what time it is, just something to express our creative spirit.</p>
<h2>
	Conference Speaking</h2>
<p>
	I had the huge pleasure of speaking last year at <a href="http://geeuphq.com/">GeeUp</a>; I&#39;d like to try my hand at it again this year. This is a huge undertaking, and a massive time suck, but I get so much out of it personally. To get to this though, I know that I need to publish more, write more, and hone my voice. Otherwise I won&#39;t be invited to the party.</p>
<p>
	Since there&#39;s no other place to put it, here are some quick ideas of things I could write about:</p>
<ul>
	<li>
		how we price responsive designs</li>
	<li>
		how and why we use Preboot</li>
	<li>
		our Craft boilerplate</li>
	<li>
		Preparing a CMS for our clients</li>
</ul>
<h2>
	Alternative Pricing Model</h2>
<p>
	This is a strange one, but - we operate as a traditional agency model when it comes to project scoping &amp; pricing: we discuss the project objectives with a client, ask for a ballpark budget, and then cobble together a project "estimate", usually an X to Y range, and then get to work. There are two problems with how we then proceed:</p>
<ol>
	<li>
		We do not accurately track our time &amp; cost against this X to Y range as we work. In the end, we bill a minimum of X, plus some number that "feels right", below Y - unless something exceptional change or circumstance justifies clearly billing the entire Y amount.</li>
	<li>
		We rush the estimating of this process, and as a result often underestimate the final cost. The client wins almost every time.</li>
</ol>
<p>
	For some clients, this model will have to remain in some shape or form - sure we may be able to improve the accuracy of our "feels right" pricing, but some clients will still require a clear X to Y for the "total" cost of a job before proceeding.</p>
<p>
	However I&#39;d like to try an alternative pricing model, something that is more "agile". The idea is to quote for an in-depth discovery phase, which might even involve some minimal design work if necessary. We may still draw up an "X to Y" as a conversation starter, but the outcome of the discovery phase would be a more accurate X to Y quote which the client would then be invited to consider. Something that would be accompanied by a scoping document and a detailed project schedule. I know this is a no-brainer to some, but for us, or more finely for our clients, this is a big pill to swallow.</p>
<p>
	Along these lines, I&#39;d like to also start the conversation earlier with our clients about ongoing costs - phase 2 or 3 budgets, year 2 or 3 budgets, launch &amp; promotion budgets, etc. &nbsp;It isn&#39;t that I think we mislead clients to think that they will only need to pay once and then have a 100% perfect website for years to come; but I do think we could empart more wisdom to them up front, and help establish working expectations on deliverables &amp; outcomes.</p>
<h2>
	Price Sheet Guide</h2>
<p>
	As mentioned above, we tend to "feel out" the right cost of a job. But we could be more scientific in our approach - much like we count up templates to add cost, and apply markups for things such as responsive design, there are certain features &amp; functional requirements which add a clear additional cost to a project. These should be documented, accounted for in projects, and ideally tracked during project development to refute or confirm the original estimate.</p>
<p>
	For example, slideshows. Slideshows often are tossed around during a project brainstorming and promised without much thought, but when it comes time to build them, their costs can vary widely. Do they contain captions? Might they contain videos? Is this a responsive site? Are there multiple transitions that need to take place? How many slides might we have, should they be lazy loaded? Are they going to take up 100% of the browser height?</p>
<h2>
	Consolidate Hosting</h2>
<p>
	We host personal &amp; client sites across a few hosting companies, and it makes no sense. I&#39;d love to see these consolidated under one roof.</p>
<h2>
	Living Playbook</h2>
<p>
	A friend tipped me off to the <a href="http://playbook.hanno.co/">Hanno Playbook</a>, and it took hold of me like a first love; this is exactly what I think we need for ourselves. One takeaway from the writing is that I liked the idea that it was something that could change over time - rather than articles or blog entries which must be published and never touched again, their Playbook is an ever-evolving document. &nbsp;It also has a mixed audience - it&#39;s both for employees &amp; clients, so that everyone is clearly on the same page.</p>
<p>
	Our version could similarly attempt to document our process, our expectations, our services. We could also publish similar documents which mention favoured tools for development, plugins for site functionality, etc.</p>
<h2>
	Google Apps for Business</h2>
<p>
	I can see a few places where our company might benefit from moving to Google Apps. Better email and collaborative document writing are the two that immediately spring to mind.</p>
<h2>
	Project Checklists</h2>
<p>
	Who doesn&#39;t love checklists? Actually I hate them and love them. Love the idea, usually fall short of the expectations. and never complete. I&#39;ve Googled plenty for various project checklists, and they all miss the mark for our needs. &nbsp;Perhaps it&#39;s time to build our own. I&#39;m talking about checklists for things like:</p>
<ul>
	<li>
		project kickoff</li>
	<li>
		website launch</li>
	<li>
		content planning</li>
	<li>
		project estimating</li>
	<li>
		quality assurance</li>
</ul>
<h2>
	IE8 Policy</h2>
<p>
	I&#39;m the first person to want to say goodbye forever to IE8, but for our typical client base, it&#39;s still a browser we need to pay homage to. But I&#39;m happy to deliver a modest version: Non-JS, non-responsive, non-AJAX. But to do this, we need to clearly indicate this with our clients, and give them an opportunity to pay for an upgrade to support IE8 fully. &nbsp;In fact, this could be extended to any browser outside a "supported" list. I&#39;d be even happier if the fee is non-specific, e.g. tracked &amp; billed as a separate cost.</p>
				]]></content>
			</entry>
		
			<entry>
				<title>Do the Hard Things First &amp;amp; Often</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/do-the-hard-things-first-often" />
				<id>tag:johndwells.com,2014:blog/3.96</id>
				<published>2014-07-02T20:40:00Z</published>
				<updated>2014-07-02T20:48:29Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>This post is one of a few to come: My thoughts on this year’s <a href="http://geeuphq.com" title="GeeUp">GeeUp</a> conference.</p>
					<p>
	<a href="https://twitter.com/joelbradbury">Joel Bradbury</a> gave a great talk about add-on development &amp; support, sharing his experience moving to a rapid, iterative development approach. He began by astutely noting that the things we find hardest at work are also those we tend to ignore and put off. Yet this avoidance tends to only compound the difficulty.</p>
<p>
	His solution is to do the hard stuff first, and often. The theory behind it is sound: <strong>the more you do something, the better you get at it</strong>. Before you know it, that which was once hard is now easy, perhaps even <em>routine</em>.</p>
<p>
	Joel applied this philosophy to the release cycle of his add-ons, committing to do at least one release per week. While the first few weeks/months proved challenging, he soon was able to not only achieve a release a week, but sometimes more. Now the anguish of pushing a release has been reduced to an inconsequential step along the way, and the generated&nbsp;<em>momentum</em>&nbsp;has freed his time &amp; attention for bug fixes, feature requests, and new product development.</p>
<p>
	Joel also addressed the concept of paid/unpaid support. This has been a hot topic among EE&rsquo;s developer community of late. He decided to approach the problem from the other end: rather than focusing on how to support those finding difficulty in using his software, he now offers paid installations of his add-ons. It&#39;s a pre-emptive support model that not only helps his customers, but his bottom line. Everyone wins.</p>
				]]></content>
			</entry>
		
			<entry>
				<title>When a Simple Conditional Isn&#8217;t</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/when-a-simple-conditional-isnt" />
				<id>tag:johndwells.com,2013:blog/3.93</id>
				<published>2013-05-24T12:30:00Z</published>
				<updated>2014-02-24T23:25:11Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>ExpressionEngine&#8217;s Simple vs. Complex Conditionals is <em>mostly</em> all about a) the variables the conditional is evaluating, and b) the complexity of the conditional statement. But there&#8217;s more to it than that - <em>syntax matters</em>.</p>
					<p>
	<strong>Raise your hand if you knew this one:</strong> wrapping a variable in curly brackets will negate an otherwise perfectly legitimate-looking Simple Conditional.</p>
<p>
	<em>I sure hope I&#39;m not the only one raising my hand.</em></p>
<p>
	Yes, <a href="http://ellislab.com/expressionengine/user-guide/templates/globals/conditionals.html#simple-conditionals">Simple Conditionals</a> are more than just about their lack of logical operators (e.g. no AND, OR), lack of control structures (e.g. no ELSE, ELSEIF), or type of variable (e.g. must be a segment, embed, or global variable). &nbsp;To pass the mustard to be considered a "Simple" conditional, it also must follow a few syntax rules as well.</p>
<p>
	&nbsp;</p>
<p class="aside">
	No writing about EE&#39;s Parse Order is complete without a knowledge bomb from <a href="http://gotolow.com">@low</a>.</p>
<blockquote>
	<p>
		<a href="https://twitter.com/kristengrote">@kristengrote</a> Because of line 3197 of Template.php in EE2.6.1, but I guess that&rsquo;s not what you want to hear. <a href="https://twitter.com/search?q=%23eecms&amp;src=hash">#eecms</a></p>
	&mdash; Lodewijk Schutte (@low) <a href="https://twitter.com/low/statuses/342790208326090752">June 6, 2013</a></blockquote>
<p>
	&nbsp;</p>
<p class="aside">
	<em>It&#39;s especially awesome to notice that EE&#39;s own docs describing what a Simple Conditional is, actually isn&#39;t - "username" is not an early-parsed variable. <a href="http://gotolow.com">@low</a> pointed out that one as well.</em></p>
<p>
	If you&#39;re like me you may be surprised by this, because it is not explicitly mentioned in EE&#39;s <a href="http://ellislab.com/expressionengine/user-guide/templates/globals/conditionals.html#simple-conditionals">documentation</a>. But if you read between the lines (as well as through the <a href="http://ellislab.com/expressionengine/user-guide/templates/globals/conditionals.html#9378" style="line-height: 1.9em;">comments</a>), you&#39;ll see the syntax rules emerge, which are:</p>
<ul>
	<li>
		the left-hand side of the condition MUST be either a&nbsp;segment, embed, or global variable</li>
	<li>
		the right-hand side of the condition MUST be a string (<em>at least at the time that the condition is evaluated</em>)</li>
	<li>
		the left-hand variable MUST NOT have curly brackets and/or quotes around it</li>
</ul>
<h2>
	So what <em>is</em> a Simple Conditional</h2>
<p>
	First, let&#39;s see what&nbsp;<em>is</em> a Simple Conditional. Here, we are comparing a segment variable against a string:</p>
<pre class="brush:ee;">
&#123;if segment_1 == "blog"&#125;&#10;&#9;&lt;h1&gt;Blog!&lt;/h1&gt;&#10;&#123;/if&#125;</pre>
<h2>
	What isn&#39;t a Simple Conditional</h2>
<p>
	Wrapping your variable in curly brackets:</p>
<pre class="brush:ee;">
&#123;if &#123;segment_2&#125; == "blog"&#125;&#10;&#9;...&#10;&#123;/if&#125;&#10;</pre>
<p>
	Wrapping your variable in curly brackets and quotes:</p>
<pre class="brush:ee;">
&#123;if "&#123;segment_1&#125;" == "blog"&#125;&#10;&#9;...&#10;&#123;/if&#125;&#10;</pre>
<p>
	Flipping the placement of your variable and the string you are comparing:</p>
<pre class="brush:ee;">
&#123;if "blog" == segment_1&#125;&#10;&#9;...&#10;&#123;/if&#125;&#10;</pre>
<p>
	Ommitting the quotes around the string just because it&#39;s an integer:</p>
<pre class="brush:ee;">
&#123;if embed:number &lt; 5&#125;&#10;&#9;...&#10;&#123;/if&#125;</pre>
<p>
	Placing an Advanced Conditional within a Simple Conditional:</p>
<pre class="brush:ee;">
&#123;if segment_1 != ""&#125;&#9;&#10;&#9;&#123;exp:class:method&#125;&#10;&#9;&#9;&#123;if var == "foo"&#125;&#10;&#9;&#9;&#9;Lorem&#10;&#9;&#9;&#123;if:else&#125;&#10;&#9;&#9;&#9;Ipsum&#10;&#9;&#9;&#123;/if&#125;&#10;&#9;&#123;/exp:class:method&#125;&#10;&#123;/if&#125;&#10;</pre>
<p>
	<em>Courtesy of @low with a genius solution:&nbsp;</em><a href="https://gist.github.com/low/1391783"><em>https://gist.github.com/low/1391783</em></a></p>
<h2>
	Bonus 1: Comparing 2 early-parsed variables (possible)</h2>
<p>
	Have you ever wanted to compare 2 early-parsed variables? It&#39;s possible, but again, syntax matters. &nbsp;Keeping the above rules in mind, the trick is to get EE to parse the right-hand variable into a string <em>prior</em> to the Simple Conditional stage of the parse order. Like so:</p>
<pre class="brush:ee;">
&#123;if segment_1 == "&#123;embed:segment&#125;"&#125;&#10;&#9;...&#10;&#123;/if&#125;</pre>
<h2>
	Bonus 2: Comparing a non-existent variable (not possible...ish)</h2>
<p>
	Let&#39;s say you&#39;re using <a href="https://twitter.com/_rsan">Rob Sanchez</a>&#39;s awesome <a href="http://devot-ee.com/add-ons/mo-variables">Mo&#39; Variables</a>&nbsp;extension to create an early-parsed variable for a browser cookie named "hometown". If that cookie matches the string value "richmond", you want to run a special query just for those visitors. You&#39;d probably write something like:</p>
<pre class="brush:ee;">
&#123;if cookie:hometown == "richmond"&#125;&#10;&#9;&#123;exp:channel:entries channel="howdyneighbor"&#125;&#10;&#9;&#9;...&#10;&#9;&#123;/exp:channel:entries&#125;&#10;&#123;/if&#125;</pre>
<p>
	If the cookie "hometown" exists (regardless of value, including an empty string), then this conditional would in fact be <em>Simple</em>. <strong>However if the cookie did not yet exist,&nbsp;the above would in fact fail as a Simple Conditional.</strong></p>
<p>
	So how might we construct a Simple Conditional to successfully run against a non-existent variable? Refer to what we learned above: by "casting" the <em>non-existent</em> variable to a string, and comparing it to an <em>existing</em> variable:</p>
<pre class="brush:ee;">
&#123;!-- Where &#39;lv_hometown_default&#39; is an early parsed Low Variable with a value of "richmond" --&#125;&#10;&#123;if lv_hometown_default == "&#123;cookie:hometown&#125;"&#125;&#10;&#9;...&#10;&#123;/if&#125;</pre>
<p>
	Of course if your code fails as a Simple Conditional, it will be fine as an Advanced Conditional, and there&#39;s nothing necessarily wrong with your code! &nbsp;Sometimes though when you&#39;re looking to squeeze out performance gains, the difference matters. &nbsp;Or, and this is more relevant to recent work of our own, if you&#39;re conditionally setting a Preload Replace variable, then it&#39;s of vital importance.</p>
<p>
	Either way, these nuances of EE&#39;s parsing engine are important to master. As always I welcome feedback, correction, and illumination.</p>
				]]></content>
			</entry>
		
			<entry>
				<title>ExpressionEngine Parse Order Be Damned: Advanced Conditionals as Tag Parameters</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/expressionengine-parse-order-advanced-conditionals-as-tag-parameters" />
				<id>tag:johndwells.com,2013:blog/3.77</id>
				<published>2013-03-23T18:48:35Z</published>
				<updated>2013-04-02T12:19:36Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>Once again I&#8217;m shaking my fists at the impossible hoop-jumping gauntlet that is the ExpressionEngine Parse Order. This time I want to pass the result of an Advanced Conditional as a value to a module tag parameter. It&#8217;s been long said it can&#8217;t be done. It&#8217;s time to change that.</p>
					<p>
	Nesting an <a href="http://ellislab.com/expressionengine/user-guide/templates/globals/conditionals.html#global-advanced-conditionals">Advanced Conditional</a> inside a module tag parameter. It&#39;s been said it can&#39;t be done.</p>
<pre class="brush:ee;">
&#123;exp:channel:entries&#10;    status="&#123;if &#39;&#123;segment_3&#125;&#39; == &#39;closed&#39;&#125;closed&#123;if:else&#125;draft&#123;/if&#125;"&#125;&#10;    &#123;title&#125; - &#123;status&#125;&lt;br&gt;&#10;&#123;/exp:channel:entries&#125;</pre>
<p class="aside">
	"You are using advanced conditionals in your tag, and in EE, they don&#39;t parse soon enough for your tag. Your tag is likely seeing all possible conditions when it processes."<br />
	<small><a href="http://ellislab.com/forums/viewthread/204166/#954620" title="Using Mo' Variables in Module Tag Parameters">Using conditionals in channel entries parameters</a></small></p>
<p>
	Ultimately at issue here is the <a href="http://ellislab.com/expressionengine">ExpressionEngine</a>&reg; <a href="http://ellislab.com/expressionengine/user-guide/templates/template_engine.html">Parse Order</a>, which is an obscure yet critical concept that every EE developer will at some point confront (and with the help of fine folks like <a href="http://gotolow.com">Low</a>, hopefully overcome).</p>
<p>
	On most days it sits quietly behind the scenes making things Just Work&trade; and providing the backbone for the simplicity and beauty of EE&#39;s template markup.</p>
<p>
	Then every so often it is the devil-in-the-details gremlin that riddles your project with exceptions, caveats, and "it depends" workarounds - like when it comes to conditional statements. &nbsp;<span style="line-height: 1.9em;">See, in the world of the Parse Order, no two conditionals are the same - they&#39;re either considered "Simple", or "Advanced", and where they sit amongst the Parse Order matters a great deal - especially for performance, but also when we want to use them as a tag parameter.</span></p>
<h2>
	Simple Conditionals - unfashionably early:</h2>
<p>
	<span style="font-size: 14px; line-height: 1.9em;">A conditional is considered "simple" if it is evaluating variables that are already available by the time the template parsing engine reaches the simple conditionals parsing stage (e.g. </span><a href="http://ellislab.com/expressionengine/user-guide/templates/globals/url_segments.html" style="font-size: 14px; line-height: 1.9em;">segment</a><span style="font-size: 14px; line-height: 1.9em;">, </span><a href="http://ellislab.com/expressionengine/user-guide/templates/embedding.html#embed-variables" style="font-size: 14px; line-height: 1.9em;">embed</a><span style="font-size: 14px; line-height: 1.9em;">, and <a href="http://ellislab.com/expressionengine/user-guide/templates/globals/user_defined.html">user-defined&nbsp;</a></span><a href="http://ellislab.com/expressionengine/user-guide/templates/globals/user_defined.html"><span style="line-height: 1.9em;">global variables</span></a><span style="font-size: 14px; line-height: 1.9em;">), the expression evaluates a single variable (i.e. contains no logical operators such as OR, AND), and the conditional does not make use of the else or elseif control structures.</span></p>
<p>
	In short, a simple conditional will look very much like this:</p>
<pre class="brush:ee;">
&#123;if segment_1 == "joe"&#125;&#10;    &lt;h1&gt;Hi Joe!&lt;/h1&gt;&#10;&#123;/if&#125;</pre>
<h2>
	Advanced Conditionals - fashionably late:</h2>
<p>
	Any conditional that isn&#39;t a simple conditional is considered an "advanced" conditional and is evaluated much later in the template parsing order. Advanced Conditionals can use logical operators (ex: OR, AND) to compare multiple variables to multiple values.</p>
<pre class="brush:ee;">
&#123;if username == "joe" OR username == "jane"&#125;&#10;    &lt;h1&gt;Hi &#123;username&#125;!&lt;/h1&gt;&#10;&#123;if:else&#125;&#10;    &lt;h1&gt;Who goes there?&lt;/h1&gt;&#10;&#123;/if&#125;</pre>
<p>
	So when EE serves up each template, the Template Engine makes <em>multiple</em>&nbsp;passes through its contents, as it incrementally steps through each stage of the Parse Order. When it comes to evaluating conditional control structures, you need to know that:</p>
<ul>
	<li>
		Simple Conditionals are processed early, <strong>before</strong> module &amp; plugins tags</li>
	<li>
		Advanced Conditionals are processed late, <strong>after</strong> module &amp; plugin tags</li>
</ul>
<p>
	The takeaway from this is that <strong>you can use a Simple Conditional as part of a tag parameter</strong>, since the conditional will be evaluated prior to the outer tag being run. <strong>However since Advanced Conditionals are parsed late, the outer tag&#39;s parameter will equal the complete, un-evaluated Advanced Conditional string</strong>.</p>
<h2>
	So, what else can we pass as a tag parameter?</h2>
<p>
	That is a great question. We now know we can pass simple conditionals, and referencing the Parse Order we know that we can pass early-parsed variables (segments, embeds and early globals) and preload_replace variables. So how about another plugin?</p>
<p>
	Yes, in fact - <strong>you can pass a plugin as a tag parameter</strong>. If you add <code>parse="inward"</code>&nbsp;to your outer tag, then the Template engine will check if the content of any parameter value appears to be itself a plugin - and if so, it will be parsed immediately. See:</p>
<pre class="brush:ee;">
/* ---------------------------------&#10;/*  Plugin as Parameter&#10;/*&#10;/*  - Example: channel="&#123;exp:some_plugin&#125;"&#10;/*  - A bit of a hidden feature.  Has been tested but not quite&#10;/*  ready to say it is ready for prime time as I might want to &#10;/*  move it to earlier in processing so that if there are &#10;/*  multiple plugins being used as parameters it is only called&#10;/*  once instead of for every single parameter. - Paul&#10;/* ---------------------------------*/&#10;&#10;if (substr_count($this-&gt;tag_data[$i][&#39;tag&#39;], LD.&#39;exp&#39;) &gt; 1 &amp;&amp;&#10;    isset($this-&gt;tag_data[$i][&#39;params&#39;][&#39;parse&#39;]) &amp;&amp;&#10;    $this-&gt;tag_data[$i][&#39;params&#39;][&#39;parse&#39;] == &#39;inward&#39;)&#10;&#123;&#10;....&#10;$this-&gt;log_item("Plugin in Parameter, Processing Plugin First");&#10;....&#10;&#125;</pre>
<p>
	That, dear friends, is straight from the Template Engine itself - around line 1054. Hi, <a href="https://twitter.com/reedmaniac">Paul</a>!&nbsp;<span style="line-height: 1.9em;">By now, I&#39;m hoping you&#39;re with me on this ah-hah moment - because </span><em style="line-height: 1.9em;"><strong>all we need now is a plugin that is specifically designed to evalute Advanced Conditionals</strong></em><span style="line-height: 1.9em;">. And lo and behold, one already exists.</span></p>
<h2>
	The ifElse plugin from Mark Croxton</h2>
<p class="aside">
	You may already know <a href="https://twitter.com/croxton">@croxton</a> from <a href="http://github.com/croxton/Stash">Stash</a>. Or from <a href="http://github.com/croxton/Switchee">Switchee</a>. Or other handy add-ons - you should check him out on <a href="http://github.com/croxton">Github</a>. He&#39;s a mighty clever chap.</p>
<p>
	<strong><a href="http://github.com/croxton/ifElse">ifElse:</a></strong> <em>Early parsing of advanced conditionals in EE templates</em>.&nbsp;<span style="line-height: 1.9em;">With ifElse, Mark has once again done the hard work to make our lives easier - he&#39;s built a plugin that&nbsp;coaxes&nbsp;EE&#39;s Template Engine to parse an advanced conditional </span><em style="line-height: 1.9em;">as if it were a Simple Conditional</em><span style="line-height: 1.9em;"> -&nbsp;which is to say the conditions are evaluated&nbsp;</span><em style="line-height: 1.9em;">before</em><span style="line-height: 1.9em;">&nbsp;evaluating the tags within each control structure. But as an added bonus, ifElse now gives us the ability to pass an Advanced Conditional as a tag parameter.</span></p>
<p>
	So if we add&nbsp;<code>parse="inward"</code>&nbsp;to our outer tag, and wrap our Advanced Conditional in the ifElse plugin, this is what we get:</p>
<pre class="brush:ee;">
&#123;exp:channel:entries&#10;    limit="3"&#10;    parse="inward"&#10;    status="&#123;exp:ifelse&#125;&#123;if &#39;&#123;segment_3&#125;&#39; == &#39;closed&#39;&#125;closed&#123;if:else&#125;draft&#123;/if&#125;&#123;/exp:ifelse&#125;"&#125;&#10;    &#123;title&#125; - &#123;status&#125;&lt;br&gt;&#10;&#123;/exp:channel:entries&#125;</pre>
<p class="aside">
	<em><strong>Update 2nd April:</strong></em><strong> </strong>As has been astutely pointed out a few times now, this is a nonsensical example that is better achieved with a Simple Conditional, since it is operating upon an Early Parsed variable. Keep in mind however that not all variables are parsed early, so there are still going to be times where an Advanced Conditional is unavoidable. My apologies for not choosing a more appropriate example from the outset.</p>
<p>
	And it Just Works&trade; once again - <code>exp:ifelse</code> is run, your condition is evaluated, and either &#39;closed&#39; or &#39;draft&#39; is returned to the <code>status=</code> parameter. It was everything we&#39;d ever hoped for, and more. Horray!</p>
<h2>
	Horray indeed! But before you go, some parting advice</h2>
<p>
	Nesting tags within tags within tags can be taxing for EE&#39;s Template Engine to know where one thing starts and another begins. So adhere to these two rules if you use this approach:</p>
<dl>
	<dt>
		<strong>1. Use double &amp; single quote nesting with care</strong></dt>
	<dd>
		<p>
			If you&#39;re using double quotes for your outer tag parameters, use single quotes for you nested plugin-tag-as-parameter. Using all of one quote type may yield unexpected results.</p>
	</dd>
	<dt>
		<strong>2. For this technique to work, be sure to wrap early-parsed variables in curly brackets.</strong></dt>
	<dd>
		<p>
			Early-parsed variables (as well as preload_replace variables) should be contained in curly brackets (e.g. <code>&#123;variable&#125;</code>) to be sure the Template Engine can evaluate them early.</p>
		<p>
			<em>Note that for Simple Conditionals it is important to NOT wrap early-parsed variables in curly brackets</em>. Thanks <a href="http://twitter.com/reedmaniac">Paul</a> for the reminder.</p>
	</dd>
</dl>
<p>
	I should also say that I&#39;ve only just discovered this trick, so I&#39;d appreciate hearing feedback on your experiences, in particular if there are any other important caveats or syntax/parse rules to keep in mind. Happy templating all...</p>
<p class="notice">
	<em><strong>Update 1st April:</strong> </em>As Low very correctly pointed out in the comments below, this does rely on an unofficial "hidden" feature, so there is no guarantee that future versions of EE will allow this technique. As always you should choose the solution that best suits the task at hand, and future-proof &amp; maintainability are vital criteria to consider.&nbsp;</p>
				]]></content>
			</entry>
		
			<entry>
				<title>Of The Social Contract, Or Principles of&#8230; Commercial Add&#45;On Development</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/of-the-social-contract-or-principles-of-commercial-add-on-development" />
				<id>tag:johndwells.com,2011:blog/3.61</id>
				<published>2011-02-27T12:00:57Z</published>
				<updated>2011-02-27T19:01:59Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>Thanks to the devot:ee Store, it has never been easier to turn a little pet add-on into a commercial profit-maker. And no doubt the prospect of earning dosh for brilliance has attracted strong talent to the EE community. But amidst this fevered gold rush, are we customers getting our money&#8217;s worth?</p>
					<p>
	This is a topic I&#39;ve been chewing on for a while - biting my tongue at times - struggling to formulate my thoughts into something constructive. In the two years since becoming part of the amazing EE community, a lot has changed. One particularly significant change is a swift and steady move towards commercial add-on development - <em>a move that is starting to feel more like a greed-fueled money-grab, than an indication of higher quality software</em>.</p>
<p>
	Don&#39;t get me wrong: I am all for commercial add-ons. <a href="http://onedarnleyroad.com">At our studio</a> we lobby every day to convince clients that <em>our time and expertise</em> is worth the money we charge. Developers of quality software are equally deserving of fair compensation. So what I am not saying is that I will not pay for your add-on.</p>
<blockquote>
	<p>
		I will happily pay for your add-on. But as a paying customer, I will expect a certain level of product and service.&nbsp;<em>I will expect to get my money&#39;s worth.</em></p>
</blockquote>
<p>
	If you plan to develop commercial add-ons for ExpressionEngine, understand what you are agreeing to - understand that you are becoming part of the&nbsp;<strong>EE Community</strong>, and as such are expected to uphold the spirit of that community: generosity, transparency, responsibility, and professionalism. We are an incredibly eager group of talented professionals that <em>wish to see each other succeed as much as ourselves</em>.</p>
<p>
	In that spirit, here are 10 <a href="http://www.viceland.com/int/dos.php">"DOs" and "DON&#39;Ts"</a> of commercial add-on development that I think we all should live by:</p>
<h2>
	1. I will... Put my name on it</h2>
<p>
	Take for example just a few pillars of greatness:&nbsp;<a href="http://pixelandtonic.com">Brandon Kelly</a>, <a href="http://ee-garage.com">Leevi Graham</a>, <a href="http://masugadesign.com">Ryan Masuga</a>, <a href="http://boldminded.com">Brian Litzinger</a>&nbsp;(I could go on)... I inherently trust and am willing to invest in their add-ons, not simply because from experience I know them to be excellent, but because they put their name on it. They have placed their personal reputation on the line, alongside the reputation of the software they build, which demonstrates a long-term commitment to keeping their products up-to-date and feature-rich. It&#39;s also peace of mind that if something goes wrong, <em>I will know who to turn to for help</em>.</p>
<p class="aside" style="text-align: center">
	<a href="http://lobsterwarmachine.com/" style="border: 0 !important"><img alt="" src="http://johndwells.com/content/uploads/default/lobster-war-machine.png" style="width: 123px; height: 98px; " /></a><br />
	"I smile favorably upon you."</p>
<p>
	Marketing yourself under a clever name is totally fine, just be sure to let us know who&#39;s behind it. &nbsp;<a href="http://lobsterwarmachine.com">L</a><a href="http://lobsterwarmachine.com">obster War Machine</a> is an excellent (and hilarious) example - it takes just a few seconds on the website to know that <a href="http://jackmcdade.com">Jack McDade</a> is the LWM developer - yes, the same Jack behind the indespensible&nbsp;<a href="http://buildwithstructure.com">Structure</a>&nbsp;(also brought to you by <a href="http://rockthenroll.com">Travis Schmeisser</a>).</p>
<p>
	See how much you suddenly trust that gnarly-looking crustacean?</p>
<h2>
	2. I will... Register my add-on with devot:ee</h2>
<p>
	I shouldn&#39;t need to mention this one, but better safe than sorry. Even if you decide to sell your add-on <a href="http://codecanyon.net/">elsewhere</a>, it&#39;s immensely helpful to have your add-on registered on <a href="http://devot-ee.com">devot:ee</a>. And when you do put your add-on up on devot:ee, give as much information as possible: compatibility with other add-ons, hooks used, documentation links, image previews, etc.</p>
<h2>
	3. I will... Provide publically-accessible support</h2>
<p>
	Prior to the launch of EE2, probably 99% of all EE Community activity took place in the <a href="http://expressionengine.com/forums">forums</a>, and for many of us this remains a natural format for seeking &amp; offering help when things go wrong. &nbsp;EllisLab no longer hosts 3rd party add-on support on their forums, but that&#39;s where&nbsp;<a href="http://devot-ee.com">devot:ee</a>&nbsp;has once again stepped in - with every add-on submitted, a specific forum is instantly made available (whether you like it or not, which I think is <em>brilliant</em>).</p>
<p>
	If for some reason you don&#39;t want to use devot:ee&#39;s forums, then consider&nbsp;<a href="http://getsatisfaction.com">Get Satisfaction</a> or <a href="http://tenderapp.com/">Tender Support</a>. &nbsp;But please, offer more than an email address to send to. To me that either says:</p>
<ul>
	<li>
		You don&#39;t want to broadcast to the world when someone encounters a problem with your product, or</li>
	<li>
		You will probably not respond in a timely manner to my support request, but do not want evidence of your slow response time, or</li>
	<li>
		You&#39;re just lazy</li>
</ul>
<h2>
	4. I will... Maintain comprehensive and up-to-date documentation</h2>
<p>
	This is critical, and if you do not take documentation seriously, then I will not take your product seriously. Document everything that relates to:</p>
<ul>
	<li>
		pre-sales questions, such as features, screenshots, video demos, software requirements, 3rd party compatibilities</li>
	<li>
		installation, upgrades, release notes, general usage guidelines</li>
	<li>
		FAQs, common pitfalls, what to do when something goes wrong</li>
</ul>
<h2>
	5. I will... Charge an appropriate pricetag</h2>
<p class="aside">
	<em>At times I&#39;ve considered building open-source alternatives to commercial add-ons that I didn&#39;t think were worth paying for... Clearly <a href="http://wiseupstudio.com/expressionengine/">I&#39;m not the only one</a>.</em></p>
<p>
	Yeah, this is a tough one. With every product there is a sweet spot for pricing, and the EE market is perhaps still too fresh to know exactly how to calculate this number. &nbsp;And in theory yes,&nbsp;<em>if your client wants the capability your add-on provides, then your client should be willing to pay for it</em>.</p>
<p>
	Still I think it&#39;s only reasonable to be sure the pricing of your add-on fits appropriately alongside the baseline cost of EE - $300 USD. Second, consider that sometimes your add-on is as much for the person building the site, as it is for the client requesting a particular feature (<a href="http://devot-ee.com/add-ons/low-variables/">Low Variables</a> is a good example). In which case a lower price point might gain a higher sales volume, making you more money in the long run.</p>
<blockquote>
	<p>
		I can&#39;t help but feel some #eecms commercial addons are just taking the piss charging.</p>
	<p class="attribution">
		<a href="http://twitter.com/#!/leevigraham/status/41796482910797824">@leevigraham via twitter</a>, about 30 seconds ago</p>
</blockquote>
<p>
	If your add-on adds considerable capability to a site, such as&nbsp;e-commerce options <a href="http://brilliantretail.com">BrilliantRetail</a> and <a href="http://cartthrob.com">CartThrob</a>, then you are more justified in charging a higher amount. Again, look to EE for a guide - the Discussion Module for EE is $100 USD.</p>
<p>
	However if your add-on simply scratches an itch or does something very specific, I&#39;d price it very carefully - personally anything above $25 USD and I will start to seriously hold your feet to the fire on this entire list.</p>
<h2>
	6. I will not... Build it once and never update it again</h2>
<p>
	Strangely, when I see a commercial add-on staying at or near a "version 1.0" release for ages, it tells me the developer has checked out. &nbsp;Either that, or it was such a simple add-on to begin with that there&#39;s nothing else to do to make it better. Perhaps then I can just build it myself in a day or two (or an hour or two).</p>
<h2>
	7. I will not... Release something utterly broken</h2>
<p>
	Sounds absurd, right? You&#39;d be surprised - just last week I purchased an add-on that straight out-of-the-box didn&#39;t work. It was missing an important file, which is a simple mistake but potentially costly - and more importantly not professional. The developer behind the add-on was extremely swift in resolving the issue (and even went so far as to give me a free preview to another of their commercial add-ons), but it still stung. &nbsp;It will take a lot to regain my trust in that developer.</p>
<h2>
	8. I will not... Charge you for an add-on that I developed for a client</h2>
<p class="notice">
	<em><strong>Update:</strong> community feedback has challenged this one quite a bit. The general consensus agrees that if the client is aware of your plans to release a commercial product off the back of a job, then fair is fair. Again, the overall message of this is about ensuring the spirit of the commercial venture is pure. Jump to the comments for more.</em></p>
<p>
	I realise this is possibly contentious, but it plain&nbsp;<em>seems a bit cheeky</em> to be paid by a client to develop a bespoke plugin, and then turn around and charge us as well. It reminds me of the <a href="http://www.youtube.com/watch?v=1J3w4cS2MvM">Costanza&#39;s double dip fiasco</a>:</p>
<blockquote>
	<p>
		You dipped the chip, you took a bite, and you dipped again... that&#39;s like putting your whole mouth in the dip!!</p>
</blockquote>
<p>
	Here&#39;s the thing: when you were paid by your client to build that bespoke plugin, I&#39;m 100% certain that at some point, you got help from the community at large - either by pulling apart someone else&#39;s add-on, sending out a tweet, or getting help in a forum. &nbsp;With that help, you delivered a product to your client and were paid (handsomely I hope) for it. And as thanks to us, you turn around and charge us money to use it? Come on.</p>
<p>
	The possible exception to this is if you <strong>promise</strong>&nbsp;to obey the #6&nbsp;<em>I will not...</em> rule and commit to making the add-on better and better over time.</p>
<h2>
	9. I will not... Encrypt my software with IonCube or similar</h2>
<p>
	Not everyone will agree with me on this one either, but <em>encrypting PHP code that I paid for sucks</em>. It seems to go completely against the spirit of PHP in general, but certainly against the spirit of the EE community. If nothing else, it ties my hands to investigate potential bugs or issues with the purchased software - I am out of luck to help myself, at the mercy of the developer to (hopefully) provide me with an update.</p>
<h2>
	10. And if you won&#39;t...</h2>
<p>
	Well, I don&#39;t think you should be selling your add-on. Look, I&#39;m not trying to shut the door on anyone, but I worry about our collective future successes. &nbsp;Change is afoot in the EE universe, and I think it&#39;s only prudent that we do what we can to ensure we are changing in the right direction, and <em>for the right reasons</em>. &nbsp;Pure, unadulterated profit should not be one of them. &nbsp;And in fairness, the above should apply to any commercial software product, and shouldn&#39;t be unique to ExpressionEngine.</p>

				]]></content>
			</entry>
		
			<entry>
				<title>EE Hive&#8217;s Flickr for ExpressionEngine2 now available on GitHub. Wygwam integration coming soon.</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/ee-hive-flickr-for-expressionengine2-now-available-on-github-wygwam" />
				<id>tag:johndwells.com,2011:blog/3.58</id>
				<published>2011-02-11T15:55:47Z</published>
				<updated>2011-02-11T10:42:48Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>Known simply as &#8216;Flickr&#8217;, this modest yet powerful EE2 add-on fully integrates Flickr into your website. <em>And it&#8217;s awesome</em>.<br />Flickr is now Matrix2 compatible, and even more awesomeness is on the way - like integration with Wygwam.</p>
					<p class="aside">
	<em>What are you waiting for?</em><br />
	<a href="http://github.com/ee-hive/Flickr-for-ExpressionEngine">Get Flickr for EE2 now on Github.</a></p>
<p>
	First of all, this is a big shout out to <a href="http://www.brettdewoody.com/">Brett DeWoody</a> and the clever chaps at EE Hive / <a href="http://www.digitalwaxworks.com/">Digital Wax Works</a>. Not only have they built an already brilliant add-on, <em>not only have they released it for free</em>, but they&#39;ve invited other EE developers (like me) to get involved and help make Flickr even better.</p>
<p>
	<strong>I&#39;ve really taken this open source opportunity to heart,</strong> and have begun (perhaps over-enthusiastically) contributing to the project.&nbsp; First order of business was to restore <a href="http://pixelandtonic.com/matrix">Matrix2</a> compatibility, which was completed just prior to its release on Github. This week I&#39;ve been busy with another feature...</p>
<h2>
	Flickr button for Wygwam</h2>
<p>
	I could go on and on (<em>and on</em>) about how awesome <a href="http://pixelandtonic.com/wygwam">Wygwam</a> is - which is also a heavy endorsement for <a href="http://ckeditor.com/">CKEditor</a> as a whole - but I&#39;ll leave that for another time. But as I was first setting up Flickr as a custom fieldtype for a current project, <em>I just knew</em> that my client was going to eventually ask how he could embed a Flickr image into his Wygwam field. I imagined the conversation going something like:</p>
<blockquote>
	<p>
		Open Flickr in a 2nd browser tab, and find the image you want. Click Actions &gt; View all sizes, and then click on your image. Click on &#39;Share This&#39;, select &#39;Grab the HTML/BBCode&#39; and...<br />
		Awe,<em> fuck it</em>, nevermind. I&#39;ll get back to you.</p>
</blockquote>
<p>
	I had little choice. It took a bit of wrestling, a bit of late night sweat and tears. It&#39;s still rough around the edges and needs refining, but here&#39;s what&#39;s soon to come...</p>
<p>
	<img alt="" src="http://johndwells.com/content/uploads/default/flickr_wygwam_button.jpg" /></p>
<p>
	<em>What&#39;s this, a Flickr button? Hmm, I wonder what this does...</em></p>
<p>
	<img alt="" src="http://johndwells.com/content/uploads/default/flickr_wygwam_overlay.jpg" style="width: 550px; height: 460px;" /></p>
<p>
	<em>Neat, a CKEditor overlay! So let&#39;s click on a thumbnail then...</em></p>
<p>
	<img alt="" src="http://johndwells.com/content/uploads/default/flickr_wygwam_select_size.jpg" style="width: 550px; height: 300px;" /></p>
<p>
	<em>Oooh, I get to choose which size image I embed into my Wygwam field!</em></p>
<p>
	Clicking "Insert" drops the selected image size straight into your Wygwam field, and it&#39;s there just as a normal image; you can edit it&#39;s properties, alignment etc by using the CKEditor&#39;s native image button.</p>
<h2>
	But wait, there&#39;s more</h2>
<p>
	Lot&#39;s more is in the works for Flickr. We&#39;ll be moving the authentication settings away from the fieldtype setup and into an extension. All of the documentation could use a good refresh. I hope to investigate the possibility of handling videos coming from Flickr. We also might reconsider how Flickr saves image info in the custom field, and maybe even look at some caching down the road.&nbsp; See, lots to do - stay tuned, or get involved!</p>

				]]></content>
			</entry>
		
			<entry>
				<title>Custom plugin: How to switch MSM sites while mid&#45;rendering of template</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/custom-plugin-how-to-switch-msm-sites-while-mid-rendering-of-template" />
				<id>tag:johndwells.com,2011:blog/3.56</id>
				<published>2011-02-04T12:00:09Z</published>
				<updated>2011-02-04T15:25:11Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>More often than not, EE add-ons assume that you are only interested in the current site being loaded. But, well, <em>you know what they say about ass-u-mptions</em>. Read on to learn how you can switch MSM sites while mid-rendering of a template.</p>
					<p>
	I&#39;m smack in the middle of a monumental MSM build. It&#39;s my second MSM site, and I am once again reminded how <em>I am not in Kansas anymore</em>. &nbsp;It&#39;s still EE, and it&#39;s still awesome, but "gotchas" seem a frustratingly common occurrence.</p>
<p>
	One such "gotcha" is this: as much as EE&#39;s docs claim it&#39;s easy to <strong>mix content across sites</strong>, this is in fact much easier said than done. In particular, many 3rd party add-ons, while claiming to be MSM-compatible, are "hard-coded" to use the current site being visited.</p>
<p>
	Take for example, the glorious <a href="http://buildwithstructure.com">Structure</a> addon. It&#39;s very MSM-capable, allowing you to build tree structures for each of your sites. However none of its tags allow for you to specify which site you&#39;d like to pull navigation from; <em>it always assumes you want to pull navigation from the currently loaded site</em>.</p>
<p>
	For this particular MSM project, that&#39;s exactly the roadblock I encountered last week, and needed to find a workaround. So I set about digging. Here&#39;s what I came up with.</p>
<h2>
	Step 1: Set up your plugin</h2>
<p class="aside">
	This article falls under my "Build Your Own Plugin" mantra that I, and others, have written about before. EE plugins are awesomely fun and simple to write, and put you on the fast track to becoming an EE guru.</p>
<p>
	We&#39;re going to build ourselves a simple plugin that :</p>
<ul>
	<li>
		saves site-specific config settings for the current site into EE&#39;s session object;</li>
	<li>
		accepts site_name as a parameter, and replaces our site-specific config settings with this requested site;</li>
	<li>
		when prompted, reverts back to the current site-specific config settings</li>
</ul>
<p>
	To start off with we need to set up our plugin. In our <code>__construct()</code> method, let&#39;s get an instance of EE, and then set up a session cache array to use later:</p>
<pre class="brush:php;">
&lt;?php&#10;if ( ! defined(&#39;BASEPATH&#39;)) exit(&#39;No direct script access allowed&#39;);&#10;&#10;$plugin_info = array(&#10;&#9;&#39;pi_name&#39;&#9;&#9;&#9;=&gt; &#39;MSM Switch Site,&#10;&#9;&#39;pi_version&#39;&#9;&#9;&#9;=&gt; &#39;1.0.0&#39;,&#10;&#9;&#39;pi_author&#39;&#9;&#9;&#9;=&gt; &#39;Your Name Here&#39;,&#10;&#9;&#39;pi_author_url&#39;&#9;&#9;=&gt; &#39;http://yournamehere.com&#39;,&#10;&#9;&#39;pi_description&#39;&#9;&#9;=&gt; &#39;Switch MSM sites mid-rendering of template&#39;&#10;);&#10;&#10;class Msm_switch_site &#123;&#10;&#10;&#9;var $EE;&#10;&#9;var $cache;&#10;&#10;&#9;function __construct()&#10;&#9;&#123;&#10;&#9;&#9;$this-&gt;EE =&amp; get_instance();&#10;&#10;&#9;&#9;// set up sess cache if not yet exist&#10;&#9;&#9;if( ! array_key_exists(&#39;msm_switch_site&#39;, $this-&gt;EE-&gt;session-&gt;cache))&#10;&#9;&#9;&#123;&#10;&#9;&#9;&#9;$this-&gt;EE-&gt;session-&gt;cache[&#39;msm_switch_site&#39;] = array();&#10;&#9;&#9;&#125;&#10;&#9;&#9;&#10;&#9;&#9;// pass cache object as reference&#10;&#9;&#9;$this-&gt;cache =&amp; $this-&gt;EE-&gt;session-&gt;cache[&#39;msm_switch_site&#39;];&#10;&#9;&#125;&#10;&#125;&#10;</pre>
<h2>
	Step 2: making the switch()</h2>
<p>
	And here&#39;s where the magic happens: first, our <code>switch()</code> method places our current site&#39;s config array into our session. &nbsp;It needs to remember two things:</p>
<ol>
	<li>
		the current site_name</li>
	<li>
		the current site&#39;s config object</li>
</ol>
<p>
	Next, we check for a provided&nbsp;<code>site_name</code> parameter; if passed, then we need to tell EE to load the site&#39;s prefs into the config object (check out lines 27-28). If no <code>site_name</code> is passed, then we will switch back to the current site.</p>
<pre class="brush:php;">
function switch()&#10;&#123;&#10;&#9;// capture the orig site config info&#10;&#9;if( ! array_key_exists(&#39;msm_switch_site&#39;, $this-&gt;cache))&#10;&#9;&#123;&#10;&#9;&#9;$this-&gt;cache[&#39;msm_switch_site_orig_short_name&#39;] = $this-&gt;EE-&gt;config-&gt;item(&#39;site_short_name&#39;);&#10;&#9;&#9;$this-&gt;cache[&#39;msm_switch_site&#39;] = array(&#10;&#9;&#9;&#9;$this-&gt;cache[&#39;msm_switch_site_orig_short_name&#39;] =&gt; $this-&gt;EE-&gt;config-&gt;config&#10;&#9;&#9;);&#10;&#9;&#125;&#10;&#9;&#10;&#9;// if no site_name param was passed, assume we&#39;d like to switch back to orig site&#10;&#9;if( ! $site_name = $this-&gt;EE-&gt;TMPL-&gt;fetch_param(&#39;site_name&#39;))&#10;&#9;&#123;&#10;&#9;&#9;$this-&gt;EE-&gt;config-&gt;config = $this-&gt;cache[&#39;msm_switch_site&#39;][$this-&gt;cache[&#39;msm_switch_site_orig_short_name&#39;]];&#10;&#9;&#125;&#10;&#9;else&#10;&#9;&#123;&#10;&#9;&#9;// do we already have it in the cache?&#10;&#9;&#9;if(array_key_exists($site_name, $this-&gt;cache[&#39;msm_switch_site&#39;]))&#10;&#9;&#9;&#123;&#10;&#9;&#9;&#9;$this-&gt;EE-&gt;config-&gt;config = $this-&gt;cache[&#39;msm_switch_site&#39;][$site_name];&#10;&#9;&#9;&#125;&#10;&#9;&#9;else&#10;&#9;&#9;&#123;&#10;&#9;&#9;&#9;// here&#39;s the single magical line that switches our site config&#10;&#9;&#9;&#9;$this-&gt;EE-&gt;config-&gt;site_prefs($site_name);&#10;&#9;&#9;&#9;$this-&gt;cache[&#39;msm_switch_site&#39;][$site_name] = $this-&gt;EE-&gt;config-&gt;config;&#10;&#9;&#9;&#125;&#10;&#9;&#125;&#10;&#125;</pre>
<p>
	Check out those last couple lines of code again: All we need to do is call&nbsp;<code>$this-&gt;EE-&gt;config-&gt;site_prefs($site_name)</code>; to have EE look up our settings, and re-set all the necessary config items. &nbsp;Then we just have to set this new config object into our cache (in case we need to switch to this site again and again, we can avoid subsequent DB calls).</p>
<h2>
	Step 3: How to use</h2>
<p>
	Let&#39;s again use Structure as an example. &nbsp;Say we want to be guaranteed to show the main navigation of our default site, no matter what site is currently being displayed. &nbsp;It will look like this:</p>
<pre class="brush:php;">
&#123;exp:msm_switch_site:switch site_name=&#39;default_site&#39;&#125;&#10;&#9;&#123;exp:structure:nav_main&#125;&#10;&#123;exp:msm_switch_site:switch&#125;</pre>
<p>
	Line 1 tells EE to switch to the default_site; line 2 calls Structure&#39;s nav_main as usual; line 3 tells EE to switch back to whichever site was currently being displayed.</p>
<p>
	Groovy, eh?</p>

				]]></content>
			</entry>
		
			<entry>
				<title>Stay Up Forever: Take control of EE&#8217;s session time limit (maybe)</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/stay-up-forever-take-control-of-ee-session-time-limit" />
				<id>tag:johndwells.com,2011:blog/3.55</id>
				<published>2011-01-23T21:35:14Z</published>
				<updated>2011-08-19T03:14:16Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>ExpressionEngine&#8217;s hard-coded, 1 hour time limit for CP sessions has always been a real nuisance - frustrated clients have asked repeatedly for it to be extended. I&#8217;m cautiously releasing an add-on that finally grants control of this limit, but I&#8217;d appreciate some help to determine its usefulness &amp; effectiveness.</p>


					<p class="aside">
	<em>Is all of this really necessary?</em><br />
	Not entirely: You can set the <a href="http://expressionengine.com/user_guide/cp/admin/system_admin/security_settings.html">Control Panel Session Type</a> to &#39;Cookies Only&#39; and avoid all of this - plus gain the "keep me logged in" checkbox on login screens.</p>
<p>
	<strong>Update 2: NEVERMIND ALL OF THIS MALARKEY. As of EE 2.2.somethingorother, there are two new hidden configuration variables that allow you to control the session length of both CP users and front-end visitors. See <a href="http://expressionengine.com/user_guide/general/hidden_configuration_variables.html#user_session_ttl">User Session Length</a>&nbsp;and <a href="http://expressionengine.com/user_guide/general/hidden_configuration_variables.html#cp_session_ttl">Control Panel Session Length</a> for more.</strong></p>
<p>
	<strong>Update 1: </strong>Initial tests, with the help of some in the community, find that "forever" might only be 4 hours. The reason behind is mentioned in the "Potential Pitfalls" section below, and further discussed in the Comments section. Still, I&#39;d appreciate more input &amp; feedback.</p>
<p>
	As this <a href="http://expressionengine.com/wiki/Can_I_change_the_length_of_sessions_in_the_Control_Panel/">EE Wiki entry</a> explains, it is not considered possible to increase EE&#39;s session time limit without hacking the core. That&#39;s no good of course, so until now I&#39;ve always considered this task to be off limits.</p>
<p>
	Then this past weekend I began researching possibilities of overriding/extending EE&#39;s core libraries. It&#39;s a <a href="http://expressionengine.com/forums/viewthread/160740/#773192">somewhat controversial topic</a>, and I&#39;ll save my musings for another day. But the upshot of all that tinkering was that I discovered it&#39;s actually quite simple to modify the hard-coded session time limits, by way of the ever-popular <a href="http://expressionengine.com/user_guide/development/extension_hooks/global/session/index.html#sessions_start">sessions_start</a> hook.</p>
<blockquote>
	<p>
		I don&rsquo;t like it when people tell me I can&rsquo;t do something I want to do.</p>
	<p class="attribution">
		- <a href="http://expressionengine.com/forums/viewthread/160740/P18/#828063">Isaac Raways</a>, author of the <a href="http://devot-ee.com/add-ons/wallace/">Wallace</a> extension</p>
</blockquote>
<p>
	When <code>sessions_start</code> hook is called, it&#39;s passed a reference to the EE_Session object; and at least until EllisLab starts protecting class properties (<em>a distinct possibility now that PHP4 support has been dropped</em>), this means it&#39;s a piece of cake to overwrite what&#39;s in place:</p>
<pre class="brush:php;">
// called by EE&#39;s sessions_start hook&#10;function sessions_start($sess)&#10;&#123;&#10;&#9;$sess-&gt;cpan_session_len = 12345; // default is 3600, or 1 hour&#10;&#9;$sess-&gt;user_session_len = 67891; // default is 7200, or 2 hours&#10;&#9;$sess-&gt;session_length = (REQ == &#39;CP&#39;) ? $sess-&gt;cpan_session_len : $sess-&gt;user_session_len;&#10;&#9;return $sess;&#10;&#125;</pre>
<p>
	<em>Could it really be that easy?</em> From my initial tests, yes, yes it is that easy. So I&#39;ve turned it into an add-on: <a href="http://johndwells.com/software/stay-up-forever">Stay Up Forever</a>.</p>
<p>
	Right now, I&#39;m considering this an&nbsp;<strong>early beta release</strong>; it&#39;s the sort of thing that could, if misused or broken, permanently lock you out of the CP and wreak general havoc. &nbsp;So I&#39;m hoping there will be some clever/brave souls out there willing to give this a spin. &nbsp;I&#39;m also hoping anyone from EE&#39;s Core team might be able to highlight any potential pitfalls this add-on might raise.</p>
<h2>
	Possible Pitfalls</h2>
<p>
	For example: I&#39;m aware of EE&#39;s XID hash, for use with <a href="http://expressionengine.com/user_guide/development/guidelines/security.html#secure_forms">secure forms</a>, and these too have a hard-coded shelf-life: 14400 seconds or 4 hours. &nbsp;Initially this had me worried that a CP session set to expire beyond 4 hours might result in lost form submissions, but I found that the XID hash is periodically updated via javascript (read line 13 of themes/javascript/compressed/cp/global.js). &nbsp;However I don&#39;t know if this interval is effected by sleeping/waking your computer, so this is a possible gotcha. &nbsp;I&#39;m keen to hear what others think.</p>
<h2>
	Current Features</h2>
<p>
	Right now, <a href="http://johndwells.com/software/stay-up-forever">Stay Up Forever</a> is about as simple as it gets: install the extension, go to the settings page, and enter how many seconds you wish the CP and non-CP sessions to last. If you leave either value blank, the defaults will be used.</p>
<p>
	Default values will also be used if the configured time limit is set below 60 seconds; it&#39;s a safety measure to ensure you always have a minimum amount of time to log in, should anything go totally haywire.</p>
<p>
	It is&nbsp;<a href="http://ee-garage.com/nsm-addon-updater">NSM Add-on Updater</a> compatible, so you&#39;ll be notified of updates (why on earth is this not already part of core?).</p>
<h2>
	Potential Features</h2>
<p>
	So far I can think of a few features/improvements:</p>
<ol>
	<li>
		EE1x support</li>
	<li>
		Human-readable settings (e.g. &#39;3 hours&#39;, &#39;1 day&#39;, etc)</li>
	<li>
		Settings per member group, as <a href="http://expressionengine.com/archived_forums/viewthread/153189/#771476">suggested here</a></li>
	<li>
		Better Settings form, instructions etc</li>
</ol>
<h2>
	Join the Party</h2>
<p>
	That&#39;s all for now: drop a comment below if you have feedback or ideas. &nbsp;And head over to the <a href="http://johndwells.com/software/stay-up-forever">downloads area</a>&nbsp;to get your copy now.</p>

				]]></content>
			</entry>
		
			<entry>
				<title>Homegrown plugin to create template &#8220;partials&#8221; for ExpressionEngine</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/homegrown-plugin-to-create-template-partials-for-expressionengine" />
				<id>tag:johndwells.com,2011:blog/3.40</id>
				<published>2011-01-09T13:43:14Z</published>
				<updated>2011-01-10T09:36:15Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>Template &#8220;partials&#8221; functionality for ExpressionEngine: Embrace the DRY principle, reduce embed parsing and simplify your template ecosystem with this roll-your-own plugin.</p>
					<p class="aside">
	<strong>SIDE NOTE:</strong> If you&#39;d rather not hack together your own plugin, there are a number of 3rd party add-ons that can help you achieve the same approach outlined in this article; I&#39;ve provided links to these alternatives at the bottom of the page.</p>
<p>
	Generally speaking, a &ldquo;partial&rdquo; is a template that can be passed, as a variable, to another template for output. Their purpose is to provide a convenient way to include common content across multiple templates.&nbsp; Most frameworks (RoR, CodeIgniter, FuelPHP etc) all have their own flavour of template partials, and ExpressionEngine&rsquo;s embeds &amp; snippets more or less the job - but not without a few downsides.</p>
<p>
	I&#39;m going to discuss a technique that attempts to remedy these downsides. It will involve getting your hands dirty rolling our own EE plugin. &nbsp;It will be simple, limited, but hopefully demonstrate the potential at our fingertips.</p>
<h2>
	What We Have Now</h2>
<p>
	I&rsquo;m willing to bet that if you were to open up any one of your templates in EE, it might look something like this:</p>
<pre class="brush:ee;">
&#123;embed="embeds/_html_head"&#125;&#10;&lt;body class="blog"&gt;&#10;&#9;&lt;div id="wrapper"&gt;&#10;&#9;&#9;&#123;embed="embeds/_main_navigation" nav_active="blog"&#125;&#10;&#9;&#9;&lt;div id="content"&gt;&#10;&#9;&#9;&#9;&#123;exp:channel:entries ...&#125;&#10;&#9;&#9;&#9;&#9;...&#10;&#9;&#9;&#9;&#123;/exp:channel:entries&#125;&#10;&#9;&#9;&lt;/div&gt;&#10;&#9;&#9;&#123;snippet_sidebar&#125;&#10;&#9;&#9;&#123;embed="embeds/_footer"&#125;&#10;&#9;&lt;/div&gt;&#10;&#9;&#123;embed="embeds/_html_foot"&#125;&#10;&lt;/body&gt;&#10;&lt;/html&gt;&#10;</pre>
<p>
	It&rsquo;s a fairly standard setup, especially if you&rsquo;ve crossed over from the world of Wordpress and are accustomed to functions like <code>get_header()</code>&nbsp;&amp; <code>get_footer()</code> sprinkled throughout your theme files.&nbsp; And at a glance, it&rsquo;s a super convenience, allowing you to include common content across your site. &nbsp;<em>EE&rsquo;s embeds and snippets are great</em>.</p>
<p>
	But the downsides? I see three:</p>
<ol>
	<li>
		Passing content into your embeds is cumbersome at best</li>
	<li>
		Each EE embed adds significant overhead to the parsing engine</li>
	<li>
		You still have to repeat that general markup structure for every template file that&rsquo;s directly responsible for outputting content to the browser.</li>
</ol>
<p>
	Now, downside #1 can be remedied somewhat by simply wrapping more of your template with your&nbsp;<code>&#123;exp:channel:entries&#125;</code>&nbsp;tag, but it does little if you want to pass more than simple strings into an embed. &nbsp;Even so, downsides #2 and #3 remain, and these two are of greater concern. So let&rsquo;s see if we can fix them all.</p>
<h2>
	What We Need</h2>
<p>
	We need a solution that solves our 3 problems above, plus meets an additional requirement I&#39;d like to add:</p>
<ol>
	<li>
		Reduced quantity of embeds</li>
	<li>
		DRY template pattern with a <em>single</em>&nbsp;"wrapper" template</li>
	<li>
		Chunks of content can easily be passed to that wrapper template</li>
	<li>
		Lightweight and bespoke plugin that <em>meets our needs, our flavour of development, and frees us from relying on a 3rd party developer</em></li>
</ol>
<p>
	<strong>Let me pause on the last point:</strong> I&#39;m a huge proponent of self-reliance; of becoming familiar and comfortable with the core code base that you work on; and of <a href="http://37signals.com">tools that do one job and do that job well</a>. &nbsp;EE plugins are surprisingly easy to build yourself, open up a whoop-ass can of power, and can even&nbsp;speed up your templates. &nbsp;You would do yourself a great service to learn how to roll your own EE plugins.</p>
<h2>
	What It Will Look Like</h2>
<p>
	So, we are going to build a "Partials" plugin that allows us to assign chunks of content to variables that are saved and then rendered later on by a single template. &nbsp;This "wrapper" template will contain our entire page structure, as well as markup that had previously been distributed across our earlier embeds (in our examples, those were <code>_html_head</code>, <code>_main_navigation</code>, <code>_footer</code> and <code>_html_foot</code>).</p>
<p>
	<strong>That&#39;s right, </strong><em>we are going to go from 4 template embeds down to 1</em>.</p>
<p>
	Here&#39;s what our calling template will look like:</p>
<pre class="brush:ee;">
&#123;embed="embeds/_wrapper" body_class="blog" nav_active="blog"&#125;&#10;&#123;exp:channel:entries ...&#125;&#10;&#9;&#123;exp:partials:set name="page_title"&#125;&#123;title&#125;&#123;/exp:partials:set&#125;&#10;&#9;&#123;exp:partials:set name="content"&#125;&#10;&#9;&#9;&#123;channel_body&#125;&#10;&#9;&#123;/exp:partials:set&#125;&#10;&#123;/exp:channel:entries&#125;&#10;</pre>
<p>
	You may notice we call our wrapper template first, but then "set" content later. Don&#39;t worry though, as the wrapper template will be embeded <em>last</em>, because of EE&#39;s <a href="http://expressionengine.com/wiki/Parse_Order/">parse order</a>. However&nbsp;if you prefer, you&#39;re welcome to place the <code>&#123;embed&#125;</code> call at the end of your template. It will work all the same.</p>
<p>
	Lines 3-6 are where the magic happens: we <em>set</em> two new partials and fill them with content. Our first partial is a simple string; our second contains our entire body content from our channel.</p>
<p>
	Let&#39;s look at our wrapper template now:</p>
<pre class="brush:ee;">
&lt;!DOCTYPE html&gt; &#10;&lt;html&gt;&#10;&lt;head&gt; &#10;&#9;&lt;title&gt;&#123;exp:partials:get name="page_title"&#125; | &#123;site_name&#125;&lt;/title&gt;&#10;&lt;/head&gt;&#10;&lt;body class="&#123;embed:body_class&#125;"&gt;&#10;&#9;&lt;div id="wrapper"&gt;&#10;&#9;&#9;&lt;ul id="main_navigation" class="&#123;embed:nav_active&#125;"&gt;&#10;&#9;&#9;&#9;...&#10;&#9;&#9;&lt;/ul&gt;&#10;&#9;&#9;&lt;div id="content"&gt;&#10;&#9;&#9;&#9;&#123;exp:partials:get name="content"&#125;&#10;&#9;&#9;&lt;/div&gt;&#10;&#9;&#9;&#123;snippet_sidebar&#125;&#10;&#9;&#9;&lt;div id="footer"&gt;&#10;&#9;&#9;&#9;...&#10;&#9;&#9;&lt;/div&gt;&#10;&#9;&#9;&#123;snippet_analytics&#125;&#10;&#9;&lt;/div&gt;&#10;&lt;/body&gt;&#10;&lt;/html&gt;&#10;</pre>
<p>
	Look, no more embeds! What&#39;s more, this reads as a complete template; everything is in one place, and any changes to the foundation of your markup structure only needs to be made here.&nbsp;At line 4 we can see where we <em>get</em>&nbsp;one of our template partials, &#39;page_title&#39;; then at line 12 we <em>get</em> our second, &#39;content&#39;.</p>
<h2>
	The Plugin, Finally</h2>
<p class="aside">
	<em>If you&#39;re wholly unfamiliar with EE plugins, head over to the <a href="http://expressionengine.com/user_guide/development/plugins.html">User Guide</a> and have a quick scan to get the basic idea.</em></p>
<p>
	And now, to the main event. Copy-and-paste this code into <code>/system/expressionengine/third_party/partials/pi.partials.php</code>, and modify the first few lines to suit; that&#39;s right, put your name in there! After all this is going to be your plugin, not mine.</p>
<pre class="brush:php;">
&lt;?php&#10;if ( ! defined(&#39;BASEPATH&#39;)) exit(&#39;No direct script access allowed&#39;);&#10;$plugin_info = array(&#10;  &#39;pi_name&#39; =&gt; &#39;Homegrown Partials&#39;,&#10;  &#39;pi_version&#39; =&gt;&#39;1.0.0&#39;,&#10;  &#39;pi_author&#39; =&gt;&#39;Your Name Here&#39;,&#10;  &#39;pi_author_url&#39; =&gt; &#39;http://yoursite.com&#39;,&#10;  &#39;pi_description&#39; =&gt; &#39;Homegrown Partials - Template partials plugin for EE&#39;&#10;  );&#10;&#10;class Partials &#123;&#10;&#10;&#9;public $EE;&#10;&#10;&#9;/*&#10;&#9; * PHP5 constructor&#10;&#9; * get instance of EE, and set up our session cache&#10;&#9; */&#10;&#9;public function __construct()&#10;&#9;&#123;&#10;&#9;&#9;$this-&gt;EE = get_instance();&#10;&#9;&#9;if ( ! array_key_exists(&#39;partials&#39;, $this-&gt;EE-&gt;session-&gt;cache))&#10;&#9;&#9;&#123;&#10;&#9;&#9;&#9;$this-&gt;EE-&gt;session-&gt;cache[&#39;partials&#39;] = array();&#10;&#9;&#9;&#125;&#10;&#9;&#125;&#10;&#9;// END&#10;&#10;&#9;/*&#10;&#9; * Set content in session&#10;&#9; */&#10;&#9;public function set()&#10;&#9;&#123;&#10;&#9;&#9;$name = strtolower($this-&gt;EE-&gt;TMPL-&gt;fetch_param(&#39;name&#39;));&#10;&#9;&#9;$this-&gt;EE-&gt;session-&gt;cache[&#39;partials&#39;][$name] = $this-&gt;EE-&gt;TMPL-&gt;tagdata;&#10;&#9;&#125;&#10;&#9;// END&#10;&#9;&#10;&#9;/*&#10;&#9; * Get content from session&#10;&#9; */&#10;&#9;public function get()&#10;&#9;&#123;&#10;&#9;&#9;$name = strtolower($this-&gt;EE-&gt;TMPL-&gt;fetch_param(&#39;name&#39;));&#10;&#9;&#9;if (array_key_exists($name, $this-&gt;EE-&gt;session-&gt;cache[&#39;partials&#39;])&#10;&#9;&#9;&#123;&#10;&#9;&#9;&#9;return $this-&gt;EE-&gt;session-&gt;cache[&#39;partials&#39;][$name];&#10;&#9;&#9;&#125;&#10;&#9;&#125;&#10;&#9;// END&#10;&#125;&#10;/* End of file pi.partials.php */&#10;/* Location: ./system/expressionengine/third_party/partials/pi.partials.php */</pre>
<p>
	So the first half of our plugin is standard boilerplate stuff; set up our info array (EE needs this), and get an instance of the $EE object. Things get interesting around line 22, when we add an array to EE&#39;s session cache. All cache data is only available for this page request, and is wiped as soon as the request is over.</p>
<p>
	After that, we create two basic methods; one for <code>&#123;exp:partials:set&#125;</code> and one for <code>&#123;exp:partials:get</code>&#125;. Partials::set() retrieves our name parameter and passes all tagdata (everything between <code>&#123;exp:partials:set&#125; ... &#123;/exp:partials:set&#125;</code> into our cache array, where <code>$name</code> is the key. &nbsp;Then <code>&#123;exp:partials:get&#125;</code> simply retrieves that cached tagdata based on the same <code>$name</code> value.</p>
<p>
	And since this is ours, and not something we&#39;re releasing to the community, we don&#39;t need to be super safe - forgo the tedious checks if $name is a valid value, or if you might be overwriting the array value with something previously saved.&nbsp;<em>So simple.</em></p>
<p>
	<strong>And if you are so inclined, improve upon it</strong>; build in a second parameter that flags whether you should overwrite or append your saved data. &nbsp;Add another parameter that will allow you to append or prepend strings to what is being printed. You could even build multiple variations of the <code>Partials::get()</code> method to output variables differently, depending on your needs.</p>
<p>
	The possibilities are endless, and again since this is For Your Site Only, there&#39;s nothing to stop you!</p>
<h2>
	3rd Party Solutions</h2>
<p>
	This approach is in fact not new, but definitely not well-promoted; a few community developers have built fantastic and feature-rich add-ons that will help you achieve this technique if you&#39;d rather not build your own plugin. &nbsp;A few of these are:</p>
<ul>
	<li>
		<a href="http://devot-ee.com/add-ons/mx-jumper/">MX Jumper</a>&nbsp;- By max Lazar, for EE2, free</li>
	<li>
		<a href="http://studio625.com/ee/reeposition/">REEposition</a> - By Studo625, for EE1, free</li>
	<li>
		<a href="http://ee-garage.com/nsm-transplant">NSM Transplan</a>t - By Leevi Graham, for EE2, $AUD 34.95</li>
	<li>
		<a href="http://emarketsouth.com/add-ons/string-plugin">String Plugin</a> - By eMarketSouth, for EE1.6x and EE2, $9.95</li>
</ul>

				]]></content>
			</entry>
		
			<entry>
				<title>Minimee grows up: version 1.1.0 released</title>
				<link rel="alternate" type="text/html" href="http://johndwells.com/blog/minimee-grows-up-version-1.1.0-released" />
				<id>tag:johndwells.com,2011:blog/3.45</id>
				<published>2011-01-04T19:17:06Z</published>
				<updated>2011-01-09T10:34:07Z</updated>
				<author>
					<name>John D Wells</name>
					<email>hello@johndwells.com</email>
					<uri>http://johndwells.com</uri>				</author>
				
					<category term="EECMS"
						scheme="http://johndwells.com/blog/archives/category/expressionengine"
						label="EECMS" />
				
				<content type="html"><![CDATA[
					<p>Minimee, the ExpressionEngine 2.x plugin that minifies and combines your CSS and JS files, just got better. cURL support, PHP5 cleverness and other goodies await you.</p>
					<p>
	Over the xmas holidays I <a href="http://twitter.com/johndwells/status/19589047752065024">tweeted a call for help</a>&nbsp;to debug some work I&#39;d recently done on Minimee. A few dedicated souls (<a href="http://twitter.com/leepowell">@leepowell</a>, <a href="http://twitter.com/gwcode">@GWcode</a>) were kind enough to jump in and kick its tires. Thanks to their fantastic input, I&#39;m proud to announce Minimee&#39;s 1.1.0 release!</p>
<p>
	You can <a href="http://johndwells.com/software/minimee">download the latest copy of Minimee</a>&nbsp;now.</p>
<h2>
	Highlights of the release</h2>
<p>
	I&#39;ve bumped the version number from 1.0.2 to 1.1.0 due to significant changes under the hood - a slew of improvements that makes Minimee easier and more stable to use.</p>
<h3>
	cURL support</h3>
<p>
	Previously, Minimee relied on <code>file_get_contents()</code> to retrieve external files (which yes, includes <code>&#123;stylesheet=&#125;</code>). Due to an occasional shared hosting glitch, as well as the welcomed PHP5 requirement as of EE 2.1.2, it seemed necessary to add cURL support. &nbsp;While cURL is now the default, I&#39;ve given users the option to specify which method to use if they so desire.</p>
<h3>
	Support for global variables</h3>
<p>
	Support for Global Variables became a request I could no longer ignore: but to keep performance up, Minimee will only trigger EE&#39;s global parsing routine if it detects any existing EE tags.</p>
<h3>
	Yummy PHP5 support</h3>
<p>
	Seeing as EE2.1.2 has dropped PHP4 support, so has Minimee - You might not notice anything different, but it has greatly improved the clarity and structure of the code.</p>
<h3>
	&#39;Intelligent&#39; templating</h3>
<p>
	Previously, Minimee&#39;s output of <code>&lt;link ..&gt;</code> and <code>&lt;script ...&gt;</code> tags were hard-coded; the only thing you could customise was the media parameter for the link tag. Now though, Minimee uses the first HTML tag it encounters as a "template" for output. As long as your first tag is formatted as you so desire, MInimee&#39;s final output will be, too.</p>
<p>
	<em>Of course because of this change, the "media=" parameter is now obsolete.</em></p>
<h3>
	New &#39;debug&#39; mode</h3>
<p>
	There&#39;s a new configuration option to turn on "debugging", which will output HTML comments for any error encountered. Should you encounter difficulty getting Minimee up and running, this should help you quickly nail down the problem.</p>
<p>
	Note: Error and debug messages will always be sent to EE&#39;s logging mechanism (available in /system/codeigniter/system/logs/log-yyyy-mm-dd.php) - as long as you&#39;ve turned on your debug threshold. &nbsp;More on that in Minimee&#39;s <a href="http://johndwells.com/software/minimee">User Guide</a>.</p>
<h3>
	&#39;Strict&#39; mode removed</h3>
<p>
	By default, Minimee used to silently ignore any missing file(s), thereby creating a cached file based on whatever was available at the time. This behaviour could be turned off by setting the mode "strict" to TRUE (via config or param), but frankly all this feature did was cause problems &amp; confusion. &nbsp;Hence I&#39;ve completely removed this feature: <em>now MInimee will only&nbsp;work if all files are found</em>.</p>
<h3>
	From true/false to yes/no</h3>
<p>
	Any configuration settings or parameters that were once boolean (TRUE/FALSE or the string &#39;true&#39;/&#39;false&#39;) should now be set with &#39;yes&#39; or &#39;no&#39;, as appropriate. &nbsp;This was to simplify the normalising of settings. &nbsp;The details behind this deserve a brief article that I&#39;ll publish in a few week&#39;s time.</p>
<h3>
	Jeez, anything else?</h3>
<p>
	Actually yes. A few bug fixes, and a few other tweaks here and there, makes this a very exciting release. As usual if anyone has any problems, you&#39;re encouraged to use the <a href="http://devot-ee.com/add-ons/support/minimee/viewforum/1212/">support forums on devot-ee.com</a>. &nbsp;I keep a close eye on this and do my absolute best to respond in a timely manner.</p>

				]]></content>
			</entry>
		
	
	</feed>