<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Steve Taylor &#187; WordPress</title>
	<atom:link href="http://sltaylor.co.uk/blog/category/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://sltaylor.co.uk</link>
	<description>Freelance WordPress developer in London - XHTML, CSS &#38; design</description>
	<lastBuildDate>Mon, 19 Jul 2010 09:39:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>WordCamp UK 2010</title>
		<link>http://sltaylor.co.uk/blog/wordcamp-uk-2010/</link>
		<comments>http://sltaylor.co.uk/blog/wordcamp-uk-2010/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 23:32:30 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=355</guid>
		<description><![CDATA[I&#8217;m just back from WordCamp UK 2010 in Manchester. Another inspiring gathering of WordPress people, from the curious to the obsessed, with a fantastic, vibrant city as the backdrop. I&#8217;m too exhausted now for a detailed write-up, but I want to jot some things down while they&#8217;re fresh. Here&#8217;s the main things that stick in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m just back from WordCamp UK 2010 in Manchester. Another inspiring gathering of WordPress people, from the curious to the obsessed, with a fantastic, vibrant city as the backdrop.</p>
<p>I&#8217;m too exhausted now for a detailed write-up, but I want to jot some things down while they&#8217;re fresh. Here&#8217;s the main things that stick in my mind&#8230;</p>
<h2>Themes</h2>
<p>There was a lot about themes. Much discussion of the debate about the Thesis premium theme&#8217;s apparent flaunting of the WP GPL license (check <a href="http://markjaquith.wordpress.com/2010/07/17/why-wordpress-themes-are-derivative-of-wordpress/">Mark Jaquith&#8217;s post</a> for the best overview of this heated debate).</p>
<p>WP stalwarts <a href="http://www.mkjones.co.uk/">Michael Kimb Jones</a> and <a href="http://jonnya.net/">Jonny Allbut</a> took us around the world of premium themes, free themes, theme frameworks&#8230; and on that last note, introduced the beta of their new WP theme framework, <a href="http://wonderflux.com/">Wonderflux</a>.</p>
<p>I&#8217;m still agnostic about theme frameworks. Myself, I have a basic &#8220;theme foundation&#8221;, which I keep improving and tweaking, and is my lightweight starting point for all my custom themes.</p>
<p>There&#8217;s been <a href="http://digwp.com/2010/07/the-frameworks-discussion/">a great discussion on theme frameworks at digwp.com</a>, and I was interested to see how many people concur with my approach (don&#8217;t we all like loads of people agreeing with us? ;-). That said, there were some good arguments for frameworks. Most framework advocates seemed to favour Justin Tadlock&#8217;s <a href="http://themehybrid.com/themes/hybrid">Hybrid</a>, which is definitely something I&#8217;m looking at. Justin&#8217;s code and attitude are usually impeccable, and everyone says his premium support rocks.</p>
<p>Wonderflux seems like another possible contender to check out&#8212;Jonny Allbut likewise is a fully-fledged WP believer with a great attitude and a good head for code. If I start doing larger projects more regularly for clients who are keen on easily upgrading their theme to support the latest WP features, I&#8217;ll start building with one of these frameworks. There&#8217;s a bit of a learning curve involved, but really there&#8217;s only one way to find out if it&#8217;s worth it&#8230;</p>
<p>One thing for my own stripped-down theme foundation, though. Jonny stressed that even if you&#8217;re not using frameworks, you should definitely be using <a href="http://codex.wordpress.org/Child_Themes">child themes</a> (the mechanism at the root of  most theme frameworks). I suspect he&#8217;s right. I&#8217;ll be looking into this soon.</p>
<h2>Plugins</h2>
<p>Michael Kimb Jones&#8217; session on good plugins was very informative, although it was a shame there wasn&#8217;t time for the audience to chip their suggestions in. The best summary is a list of the ones I thought stood out:</p>
<ul>
<li><a href="http://wordpress.org/extend/plugins/import-html-pages/">Import HTML Pages</a>. A nifty way to quickly convert a flat HTML site to WordPress.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-table-reloaded/">WP Table Reloaded</a>. Apparently imperfect (of course) but much-needed improvement on the hideous table editing with TinyMCE.</li>
<li><a href="http://wordpress.org/extend/plugins/mingle/">Mingle</a>. Seems like &#8220;BuddyPress Lite&#8221;&#8212;social networking features for a single-site installation of WP.</li>
<li><a href="http://wordpress.org/extend/plugins/white-label-cms/">White Label CMS</a>. Allows some client-friendly mods to the WP admin area (logos, hiding unused menus, etc.).</li>
<li><a href="http://wordpress.org/extend/plugins/wp-cms-post-control/">WP CMS Post Control</a>. More control over the WP admin area, configuring what boxes appear for different users.</li>
<li><a href="http://www.gravityforms.com/">Gravity Forms</a>. You pay for it, but there was a lot of positive feeling for this powerful but very user-friendly forms plugin.</li>
</ul>
<h2>BackPress</h2>
<p>I missed lead WP developer Peter Westwood&#8217;s session on <a href="http://backpress.org/">BackPress</a>, but it sounds like a great project. It&#8217;s seems to be a library of functionality for web applications, based on WP, but stripped-down. The beauty of this is that you can now build your own apps making use of your knowledge of mega-useful WP stuff like the <code>wpdb</code> class, user management, taxonomies, etc.</p>
<h2>WordCamp UK?</h2>
<p>Unfortunately things ended on a bit of a sour note during the final discussion.</p>
<p>Last year in Cardiff there was a discussion about whether there should be a more &#8220;corporate&#8221; element to the gathering, with paid training sessions and seminars. WordCamp regulars rightly objected strongly, while stressing that they had nothing against this kind of thing happening&#8212;just not under the &#8220;WordCamp&#8221; banner. There was talk of splitting off some sort of &#8220;WordCon&#8221;, but I&#8217;ve not heard anything more of this.</p>
<p>This year, the heated debate came when we started discussing WordCamp UK 2011. <a href="http://jane.wordpress.com/">Jane Wells</a>, who&#8217;s been doing some amazing user interface work on WordPress at <a href="http://www.automattic.com/">Automattic</a> over the past few years, chimed in to remind us that <a href="http://central.wordcamp.org/about/">the ethos of WordCamps</a> is about being local and decentralized, and that a WordCamp <em>UK</em> is going against this. There was the strong suggestion that they (the <a href="http://wordpressfoundation.org/">WordPress Foundation</a> I guess, who own the WordCamp trademark) might crack down and stop such a national gathering using the WordCamp name. There was, to put it mildly, a lot of resistance, from the eminently reasonable to the rather annoyed (thankfully the arguments never actually got ugly, just pointless).</p>
<p>Now, I think everyone&#8217;s intentions here are good, and I think it should all work out in the end, despite that thing about the road to Hell. Jane genuinely wants to keep a local flavour to WordCamps, a philosophy which has a tremendous amount going for it. However, I think there&#8217;s an element here of the sociogeography of America being applied in a very different country with inappropriate rigour.</p>
<p>WordCamp USA would indeed be a humungous thing, which would tend towards becoming depersonalized, and alienate a lot of people purely through the vast distances involved. City-based WordCamps are the obvious, natural format. Jane mentioned&#8212;to stress that this wasn&#8217;t just being down on the UK&#8212;that they have similar situations in India, China and Australia. Again, I can&#8217;t see how these countries&#8217; geographic dynamics can be applied on this little island.</p>
<p>WordCamp UK has so far been held in Birmingham, Cardiff and Manchester. It&#8217;s kind of nice it not being in London. I live in London, but this is the other factor that, together with the island&#8217;s small size, changes things a bit. London dominates, often too much. Touring a nice little conference around other parts of the country seems to be a great way of bringing a good WordPress vibe to these places. And it really doesn&#8217;t feel like it&#8217;s some &#8220;central&#8221; authority bestowing itself upon the poor provinces. It feels like a localized event, infused with other parts of the country in the way that is possible in this dense, small country, and which makes it what it is.</p>
<p>Anyway, I don&#8217;t want to press this. I think the worst-case scenario is that what is now WordCamp UK gets &#8220;rebranded&#8221;. Hopefully if it has to break with the WordCamp trademark, it won&#8217;t break with the &#8220;semi-organized <a href="http://en.wikipedia.org/wiki/BarCamp">BarCamp</a>&#8221; ethos. I actually think this is next to impossible, as the core organizers are so committed to this. If we have to &#8220;fork&#8221; WordCamp to create a touring national WordPress event, it would be entirely wrong to see it as a break with the open and informal attitude of WordCamp&#8212;they don&#8217;t have a trademark on that. There&#8217;s no reason why we can&#8217;t mix this attitude with a healthy cross-pollination of people from many different places. There were quite a few Scandinavians there this weekend, because the WordPress community there hasn&#8217;t kicked off any meetups or WordCamps yet. There&#8217;s room for this kind of thing in the UK, in Europe, because it&#8217;s good and it&#8217;s possible.</p>
<p>Jane seemed set in the idea that having a WordCamp <em>UK</em> was placing this event as &#8220;bigger&#8221; and &#8220;better&#8221; than any city-based WordCamp that was set up in the UK. I think this was her major mistake. I don&#8217;t think a soul in the room had ever even thought like this. I can immediately see what&#8217;s &#8220;better&#8221; about a completely localized meetup (which, strangely, we don&#8217;t have in London). I can also see what&#8217;s &#8220;better&#8221; about a national event. When two things are both &#8220;better&#8221;, neither&#8217;s better&#8212;they&#8217;re just different. Wouldn&#8217;t stopping one of them reduce diversity? I think it would, so it&#8217;ll probably carry on, by whatever name necessary.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/wordcamp-uk-2010/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Solving WordPress problems</title>
		<link>http://sltaylor.co.uk/blog/solving-wordpress-problems/</link>
		<comments>http://sltaylor.co.uk/blog/solving-wordpress-problems/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 10:17:26 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=347</guid>
		<description><![CDATA[I periodically get queries about WordPress issues through this site, often in relation to code I&#8217;ve posted here. These days I&#8217;m usually far too busy to go into deep, free coding consultation; and usually when I do help out I&#8217;m just Googling and using the same resources available to everyone. I totally appreciate that I [...]]]></description>
			<content:encoded><![CDATA[<p>I periodically get queries about WordPress issues through this site, often in relation to code I&#8217;ve posted here. These days I&#8217;m usually far too busy to go into deep, free coding consultation; and usually when I do help out I&#8217;m just Googling and using the same resources available to everyone.</p>
<p>I totally appreciate that I might have much more experience than some people, and I&#8217;ll have a few little hints that could save a lot of time. But sometimes people emailing me seem to be doing something that I fully confess to being guilty of, in the past and even now: shouting out for help too soon instead of stepping back and tackling the problem properly.</p>
<p>So, here&#8217;s a little guide I can point people to, partly in lieu of an email reply template. If you&#8217;re facing a WordPress coding problem that either looks daunting right from the start, or is driving you insane after hours of trying, the following hints can help a lot.</p>
<p><span id="more-347"></span></p>
<ol>
<li>
<h2>Take a deep breath</h2>
<p>Literally. Take few calm, deep breaths. Maybe have a break, make some tea, do some washing up, something mundane with your hands. If time isn&#8217;t too pressing, sleep on it and have a go in the bright morning light. Very often tricky coding problems solve themselves in half-sleep states, or within seconds of sitting down in front of the issue with a fresh mind.</p>
</li>
<li>
<h2>Try it out!</h2>
<p>I feel no compunction in being withering about this, because I&#8217;m putting myself down as much as anyone. But <em>really</em>&#8212;how many times do we fire off a question to a list or forum asking whether XYZ will work or not when there&#8217;s something very close to hand that will tell us immediately: <em>giving it a go</em>! Try stuff out in a test environment. Try, tweak, try again&#8230; It&#8217;s very simple ;-)</p>
</li>
<li>
<h2>Search and ye shall probably find</h2>
<p>I can&#8217;t tell you how many replies I&#8217;ve sent to coding enquiries which basically consist of links to Google searches. I know this has an edge of facetious impatience about it, but most times it&#8217;s a plain answer. The solutions are sometimes right there, in the first page of results of a simple search.</p>
<p>I&#8217;ll mention one specific thing here, which is that although I don&#8217;t have it bookmarked, <a href="http://stackoverflow.com/">Stack Overflow</a> posts come up very frequently in tackling coding issues, and they&#8217;re often the best. One to watch for.</p>
</li>
<li>
<h2>Essential WordPress resources</h2>
<ul>
<li>
<h3><a href="http://codex.wordpress.org/">The Codex</a></h3>
<p>It&#8217;s far from perfect, but it&#8217;s often essential, especially the <a href="http://codex.wordpress.org/Template_Tags">Template Tags</a> and the <a href="http://codex.wordpress.org/Function_Reference">Function Reference</a>.</p>
</li>
<li>
<h3>3rd-party WP reference</h3>
<p>There&#8217;s some good &#8220;unofficial&#8221; WP documentation sites / reworkings, including the <a href="http://adambrown.info/p/wp_hooks/">WP Hooks Database</a> (docs on actions and filters), a <a href="http://wpdocs.labs.thedextrousweb.com/">WP API browser</a>, <a href="http://wplookup.com/">WP Lookup</a> (a good interface for search WP resources), the <a href="http://wp-roadmap.com/demo/">Roadmap</a> (not being updated it seems, but a good way of seeing the order in which files and hooks are processed for any particular WP request), and tools to <a href="http://xref.yoast.com/wp.html">search the WP source</a>.</p>
</li>
</ul>
</li>
<li>
<h2><a href="http://wordpress.org/support/">WP support forums</a></h2>
<p>Someone may have solved the issue already. If not, someone might have a moment to help&#8230;</p>
</li>
<li>
<h2><a href="http://lists.automattic.com/mailman/listinfo/wp-hackers">wp-hackers</a></h2>
<p>This is one of the key WP development community resources, for coding issues a little more advanced than you&#8217;ll find in the forums.</p>
</li>
<li>
<h2>Ask for free advice from a WP developer</h2>
<p>Well, I&#8217;m writing this to try and suggest other routes, so obviously this should be a last resort ;-)  That said, if you&#8217;re really stuck after trying all the above, you never know. The WP community does have many people like me who, because they appreciate making a living from other people&#8217;s work given for free, will occasionally devote a little time to helping a fellow developer out just for the hell of it&#8230;</p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/solving-wordpress-problems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enforce strong WordPress passwords</title>
		<link>http://sltaylor.co.uk/blog/enforce-strong-wordpress-passwords/</link>
		<comments>http://sltaylor.co.uk/blog/enforce-strong-wordpress-passwords/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 14:29:31 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=338</guid>
		<description><![CDATA[Here we go with some more nifty code for you WordPress developers&#8230; As ever, this code is roughly tested but probably not for novices. It&#8217;s designed to drop into a custom theme&#8217;s functions.php file. It probably should be a plugin, and it might make it one day when it&#8217;s thoroughly tested and I get time&#8230; [...]]]></description>
			<content:encoded><![CDATA[<p>Here we go with some more nifty code for you WordPress developers&#8230; As ever, this code is roughly tested but probably not for novices. It&#8217;s designed to drop into a custom theme&#8217;s <code>functions.php</code> file. It probably should be a plugin, and it might make it one day when it&#8217;s thoroughly tested and I get time&#8230;</p>
<p>Anyway, it&#8217;s a solution to a problem that I&#8217;m very surprised isn&#8217;t built into the WP core (as an option at least), and isn&#8217;t addressed by any easily found plugin or code already out there. As we know, WP provides a good &#8220;password strength meter&#8221; on the user profile page, which is great as strong passwords are (or should be) one of the first lines of defence against attacks on your site. But it&#8217;s just an <em>indicator</em>&#8212;there&#8217;s nothing stopping someone using &#8220;password&#8221; as their password, or something dumb like that. All you need is one Administrator or Editor with a dumb password, and the whole site is highly vulnerable.</p>
<p>How about a little enforcement?</p>
<p><span id="more-338"></span></p>
<p>The code below basically replicates the WP core password meter check, translated from JavaScript to PHP, and uses it to validate passwords that are entered.</p>
<pre name="code" class="php">// Enforce strong passwords
function slt_strongPasswords( $errors ) {
	$enforce = true;
	$args = func_get_args();
	$userID = $args[2]->ID;
	if ( $userID ) {
		// User ID specified - omit check for user levels below 5
		$userInfo = get_userdata( $userID );
		if ( $userInfo->user_level < 5 ) {
			$enforce = false;
		}
	} else {
		// No ID yet, adding new user - omit check for "weaker" roles
		if ( in_array( $_POST["role"], array( "subscriber", "author", "contributor" ) ) ) {
			$enforce = false;
		}
	}
	if ( $enforce &#038;&#038; !$errors->get_error_data("pass") &#038;&#038; $_POST["pass1"] &#038;&#038; slt_passwordStrength( $_POST["pass1"], $_POST["user_login"] ) != 4 ) {
			$errors->add( 'pass', __( '<strong>ERROR</strong>: Please make the password a strong one.' ) );
	}
	return $errors;
}
add_action( 'user_profile_update_errors', 'slt_strongPasswords', 0, 3 );

// Check for password strength
// Copied from JS function in WP core: /wp-admin/js/password-strength-meter.js
function slt_passwordStrength( $i, $f ) {
	$h = 1; $e = 2; $b = 3; $a = 4; $d = 0; $g = null; $c = null;
	if ( strlen( $i ) < 4 )
		return $h;
	if ( strtolower( $i ) == strtolower( $f ) )
		return $e;
	if ( preg_match( "/[0-9]/", $i ) )
		$d += 10;
	if ( preg_match( "/[a-z]/", $i ) )
		$d += 26;
	if ( preg_match( "/[A-Z]/", $i ) )
		$d += 26;
	if ( preg_match( "/[^a-zA-Z0-9]/", $i ) )
		$d += 31;
	$g = log( pow( $d, strlen( $i ) ) );
	$c = $g / log( 2 );
	if ( $c < 40 )
		return $e;
	if ( $c < 56 )
		return $b;
	return $a;
}</pre>
<p>A few notes:</p>
<ul>
<li>Initially, in <code>slt_strongPasswords()</code>, which is hooked to the <code>user_profile_update_errors</code> action, we check whether we're editing or creating a user here. This enables a check on the user level / role. Here, I'm only enforcing the strong password for "executive" users, i.e. those whose role lets them significantly affect the site. I'm taking this to be Editors (or, in the <a href="http://codex.wordpress.org/Roles_and_Capabilities#User_Levels">old style</a>, Level 5) and above. I'm well aware that <a href="http://codex.wordpress.org/Roles_and_Capabilities">roles and capabilities</a> in WP, and possible <a href="http://wordpress.org/extend/plugins/members/">modifications</a> of that system, mean that this may not be a one-size-fits-all solution. Obviously, adapt as necessary for your system---and do chip in here with any suggestions for better / different checks. If you want to enforce strong passwords for <em>all</em> users, just delete or comment out lines 4-17.</li>
<li>I've translated the WP core JavaScript function that runs the password strength meter here into PHP. If you root around in the core source (<code>/wp-admin/js/user-profile.dev.js</code>, you'll see that the value <code>4</code> is returned for "strong" passwords. Here, where there is enforcement, I'm limiting allowed passwords to "strong" only. Again, tweak this if you want to---perhaps different strengths enforced for different user roles.</li>
<li>One slight hole I know is here is if someone changes a user's password at the same time as changing their role from something like Subscriber to Administrator. A weak password would get through this. Also, an account with a weak password could just be changed to an Administrator, and if no new password is entered, again, the check wouldn't be triggered. I'm assuming that people on the editing other's accounts will be trusted and know what they're doing. But still, it's an area where this code could definitely be improved---certainly it'd be necessary before making this a plugin.</li>
</ul>
<p>Let me know if this is useful and if you find any bugs or suggestions for improvement!</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/enforce-strong-wordpress-passwords/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Compare the WordPress post date</title>
		<link>http://sltaylor.co.uk/blog/compare-wordpress-post-date/</link>
		<comments>http://sltaylor.co.uk/blog/compare-wordpress-post-date/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 18:58:34 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=319</guid>
		<description><![CDATA[I find PHP&#8217;s date handling a bit confusing. It&#8217;s easy when you know how, of course; but even at the same time as appreciating that it&#8217;s good in the end that it offers a lot of flexibility, it&#8217;s sometimes seemed like there are too many hoops to jump through to do some simple date operations. [...]]]></description>
			<content:encoded><![CDATA[<p>I find PHP&#8217;s date handling a bit confusing. It&#8217;s easy when you know how, of course; but even at the same time as appreciating that it&#8217;s good in the end that it offers a lot of flexibility, it&#8217;s sometimes seemed like there are too many hoops to jump through to do some simple date operations.</p>
<p>Anyway, I&#8217;ve just cracked a minor issue I&#8217;m working on thanks to <a href="http://www.highlystructured.com/comparing_dates_php.html">this post</a> and <a href="http://wordpress.org/support/topic/313756">this thread</a>. I&#8217;m posting the solution here for my quick reference as much as anything&#8230;</p>
<p>Problem: how to check if a WordPress <code>post_date</code> (from a <code>$post</code> object) is from a day in the future? Solution:</p>
<pre name="code" class="php">$postDate = strtotime( $post->post_date );
$todaysDate = strtotime( date( 'Y-m-d' ) );
if ( $postDate > $todaysDate ) {
	[ post is from the future! ]
} else {
	[ post is from today or the past]
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/compare-wordpress-post-date/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding scripts to the WordPress login or registration form</title>
		<link>http://sltaylor.co.uk/blog/adding-scripts-wordpress-login-registration-form/</link>
		<comments>http://sltaylor.co.uk/blog/adding-scripts-wordpress-login-registration-form/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 22:24:49 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=295</guid>
		<description><![CDATA[Most WP developers know by now that the right way to add script libraries from a plugin or theme is to use the wp_enqueue_script function. It makes sure scripts aren&#8217;t loaded more than once, and so on. However, I just had some problems getting some jQuery to run on the login / registration form. I [...]]]></description>
			<content:encoded><![CDATA[<p>Most WP developers know by now that the right way to add script libraries from a plugin or theme is to use the <a href="http://codex.wordpress.org/Function_Reference/wp_enqueue_script"><code>wp_enqueue_script</code></a> function. It makes sure scripts aren&#8217;t loaded more than once, and so on.</p>
<p>However, I just had some problems getting some jQuery to run on the login / registration form. I used <code>wp_enqueue_script</code> like a good WP developer but&#8230; no go. Where&#8217;s my jQuery?</p>
<p>It seems the answer lies in the fact that after scripts are enqueued in a normal WP page, they get spit out by something inside the call to <code>wp_head()</code>. I guess you could add <code>wp_head()</code> to the login header, but who wants all those redundant plugin scripts and styles that (presumably) aren&#8217;t even meant to be there.</p>
<p>After a bit of diggiing around it seems that the solution is the <code>wp_print_scripts()</code> function. So, to get jQuery working on the login form, put these lines in the code you hook onto <code>login_head</code>:</p>
<pre name="code" class="php">wp_enqueue_script( 'jquery' );
wp_print_scripts();</pre>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/adding-scripts-wordpress-login-registration-form/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easy child page creation for WordPress</title>
		<link>http://sltaylor.co.uk/blog/easy-child-page-creation-wordpress/</link>
		<comments>http://sltaylor.co.uk/blog/easy-child-page-creation-wordpress/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 20:37:57 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=284</guid>
		<description><![CDATA[Here&#8217;s a quickie that can help with WordPress sites that have a lot of pages. If some of the pages have longish titles, the &#8220;Parent Page&#8221; drop-down on the edit page screen can get unwieldy. The scroller for the drop-down can run off the right side of the screen. OK, it&#8217;s fine (often easier) to [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quickie that can help with WordPress sites that have a lot of pages. If some of the pages have longish titles, the &#8220;Parent Page&#8221; drop-down on the edit page screen can get unwieldy. The scroller for the drop-down can run off the right side of the screen.</p>
<p>OK, it&#8217;s fine (often easier) to use the keyboard to navigate drop-downs. But not everyone knows how to, and even so, with a large amount of pages, selecting the right parent can become a pain.</p>
<p>I think I adapted the following code from a plugin or someone else&#8217;s post. Thanks whoever you are, but frankly I&#8217;m so busy at the moment I&#8217;ve forgotten where it came from! Anyway, if you drop the following into your custom theme&#8217;s <code>functions.php</code>, you&#8217;ll get a new &#8220;Create child&#8221; link under every page listed in WP admin, when you hover over the title:</p>
<pre name="code" class="php">function slt_childPageAction( $actions, $page ) {
	$actions["create-child"] = '&lt;a href="/wp-admin/page-new.php?parent_id=' . $page-&gt;ID . '" title="Create a new page with this page as its parent"&gt;Create child&lt;/a&gt;';
	return $actions;
}
add_filter( 'page_row_actions', 'slt_childPageAction', 10, 2 );
function slt_setChildPage() {
	global $post;
	if ( $post-&gt;post_type == "page" &amp;&amp; $post-&gt;post_parent == 0 &amp;&amp; isset( $_GET["parent_id"] ) &amp;&amp; is_numeric( $_GET["parent_id"] ) )
		echo '&lt;script type="text/javascript"&gt;jQuery( document ).ready( function($) { $("#parent_id").val("' . $_GET["parent_id"] . '"); } );&lt;/script&gt;';
}
add_action( 'edit_page_form', 'slt_setChildPage' );</pre>
<p>The first bit adds the page action link. The second bit adds some jQuery to the right edit screen to set the specified parent, if it&#8217;s been passed. I couldn&#8217;t find another way to set the drop-down&#8230; Well, it works!</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/easy-child-page-creation-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control your own WordPress custom fields</title>
		<link>http://sltaylor.co.uk/blog/control-your-own-wordpress-custom-fields/</link>
		<comments>http://sltaylor.co.uk/blog/control-your-own-wordpress-custom-fields/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 12:53:01 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=269</guid>
		<description><![CDATA[I&#8217;m currently working on a client&#8217;s WordPress site where there&#8217;s quite a few bits of custom functionality in my custom theme that rely on them entering values for posts or pages using WP&#8217;s custom fields. Custom fields are really flexible. However, they&#8217;re not perfectly user-friendly. For instance, if no post or page is currently using [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently working on a client&#8217;s WordPress site where there&#8217;s quite a few bits of custom functionality in my custom theme that rely on them entering values for posts or pages using WP&#8217;s <a href="http://justintadlock.com/archives/2007/10/24/using-wordpress-custom-fields-introduction">custom fields</a>.</p>
<p>Custom fields are really flexible. However, they&#8217;re not perfectly user-friendly. For instance, if no post or page is currently using a custom field that you&#8217;ve built functionality on, the user has to enter the name as well as the value of the field the first time it&#8217;s used. The drop-down of field names is dynamically gathered from the fields currently in use. Also, sometimes you want to make things easier for clients by having inline tips, and inputs that suit the field (e.g. a checkbox or select drop-down instead of just a plain text entry).</p>
<p>So, I set about piecing together a way to take over the Custom Fields meta box&#8230;</p>
<p><span id="more-269"></span></p>
<p>First off, if you&#8217;re not developing custom themes, and you want a flexible plugin that will do this sort of thing, including an easy interface for defining custom fields, what I&#8217;ve got here isn&#8217;t for you. You might want to check out <a href="http://wordpress.org/extend/plugins/custom-field-template/">Custom Field Template</a>, <a href="http://flutter.freshout.us/">Flutter</a>, or <a href="http://wordpress.org/extend/plugins/magic-fields/">Magic Fields</a>. Really, the power in any of those blows the code below out the water. My concern here is some lean, only-what-you-need code that you have total control over.</p>
<p>Before we begin, here&#8217;s a taster. This is a grab from a page edit screen on the project I&#8217;ve developed this code for:</p>
<p><a href="http://sltaylor.co.uk/wp-content/uploads/2009/10/custom-fields.gif"><img src="http://sltaylor.co.uk/wp-content/uploads/2009/10/custom-fields-550x355.gif" alt="custom-fields" title="custom-fields" width="550" height="355" class="aligncenter size-large wp-image-290" /></a></p>
<p>I started off working with Function&#8217;s <a href="http://wefunction.com/2009/10/revisited-creating-custom-write-panels-in-wordpress/">Custom Write Panels</a> code, but their approach ended up being most concerned with post &#8220;metadata&#8221;. It&#8217;s all stored in one field in the <code>postmeta</code> table, in a serialized array. Which is great if you just need a clump of different values to output for any particular post. My needs are more diverse, and I often access individual fields for various reasons.</p>
<p>(<strong>TIP:</strong> If you store custom fields separately, as I will, and do end up wanting to grab them all at once, use <a href="http://codex.wordpress.org/Function_Reference/get_post_custom"><code>get_post_custom()</code></a>.)</p>
<p>One more shout. I don&#8217;t know PHP objects very well, I&#8217;m absorbing it as I go. My class structure for this code was taken from the very useful <a href="http://pressography.com/plugins/wordpress-plugin-template/">WordPress Plugin Template</a> from Pressography.</p>
<p>OK, let&#8217;s see what we&#8217;ve got. I&#8217;ll go through it step-by-step. This code is designed to go into your custom theme&#8217;s <code>functions.php</code> file&#8212;though if you wouldn&#8217;t have guessed, it might not be for you! (N.B. It must <em>not</em> be placed into <code>/wp-includes/functions.php</code>&#8212;see <a href="/blog/control-your-own-wordpress-custom-fields/#comment-3812">comments below</a>.)</p>
<pre name="code" class="php">if ( !class_exists('myCustomFields') ) {

	class myCustomFields {
		/**
		* @var  string  $prefix  The prefix for storing custom fields in the postmeta table
		*/
		var $prefix = '_mcf_';</pre>
<p>First a simple check to prevent class clashes, and the definition of the first property. This is the prefix that we&#8217;ll use for the <code>meta_key</code> when we store values in the <code>postmeta</code> table.</p>
<p>An important point to note here is that if you put an underscore at the start of a <code>meta_key</code>, <a href="http://codex.wordpress.org/Function_Reference/add_post_meta#Making_a_.22Hidden.22_Custom_Field">the custom field will be &#8220;hidden&#8221;</a>. That means it won&#8217;t show up in the default Custom Fields meta box. This code will include the option to hide that default box anyway, but there might be situations where you want to keep that in place for other reasons, alongside <em>your</em> custom fields box. In this case, it&#8217;s good to keep <em>your</em> fields in <em>your</em> box with this method.</p>
<pre name="code" class="php">		/**
		* @var  array  $customFields  Defines the custom fields available
		*/
		var $customFields =	array(
			array(
				"name"			=&gt; "block-of-text",
				"title"			=&gt; "A block of text",
				"description"	=&gt; "",
				"type"			=&gt; "textarea",
				"scope"			=&gt;	array( "page" ),
				"capability"	=&gt; "edit_pages"
			),
			array(
				"name"			=&gt; "short-text",
				"title"			=&gt; "A short bit of text",
				"description"	=&gt; "",
				"type"			=&gt;	"text",
				"scope"			=&gt;	array( "post" ),
				"capability"	=&gt; "edit_posts"
			),
			array(
				"name"			=&gt; "checkbox",
				"title"			=&gt; "Checkbox",
				"description"	=&gt; "",
				"type"			=&gt; "checkbox",
				"scope"			=&gt;	array( "post", "page" ),
				"capability"	=&gt; "manage_options"
			)
		);
		/**</pre>
<p>Now we define our custom fields. I&#8217;ve set up a little system that&#8217;s quite flexible, and included examples of three common field types. Obviously, you can extend this however you want. The field types are up to you. I&#8217;ve been using custom types that create, say, drop-downs of users of a certain role, things like that.</p>
<p>Anyway, the basic values set for each field are:</p>
<ul>
<li><b>name</b>: This gets used with the prefix to create the <code>meta_key</code> for the field.</li>
<li><b>title</b>: This is for the form&#8217;s <code>&lt;label&gt;</code>.</li>
<li><b>description</b>: This is a bit of descriptive text that goes under the field input, to help remind the user what it&#8217;s for.</li>
<li><b>type</b>: The types above happen to correspond to HTML form input types, but they don&#8217;t have to.</li>
<li><b>scope</b>: Where should these fields get used? Here it&#8217;s simply about whether they go on post or page screens, but again, you can make your own scopes up to restrict the fields to certain sections of your site, pages using certain templates, etc.</li>
<li><b>capability</b>: Which capability is required to edit the field? If you don&#8217;t understand WordPress capabilities, Justin Tadlock has an excellent <a href="http://justintadlock.com/archives/2009/08/30/users-roles-and-capabilities-in-wordpress">introduction to users, roles and capabilities</a>.</li>
</ul>
<pre name="code" class="php">		/**
		* PHP 4 Compatible Constructor
		*/
		function myCustomFields() { $this-&gt;__construct(); }
		/**
		* PHP 5 Constructor
		*/
		function __construct() {
			add_action( 'admin_menu', array( &amp;$this, 'createCustomFields' ) );
			add_action( 'save_post', array( &amp;$this, 'saveCustomFields' ), 1, 2 );
			// Comment this line out if you want to keep default custom fields meta box
			add_action( 'do_meta_boxes', array( &amp;$this, 'removeDefaultCustomFields' ), 10, 3 );
		}
		/**
		* Remove the default Custom Fields meta box
		*/
		function removeDefaultCustomFields( $type, $context, $post ) {
			foreach ( array( 'normal', 'advanced', 'side' ) as $context ) {
				remove_meta_box( 'postcustom', 'post', $context );
				remove_meta_box( 'postcustom', 'page', $context );
				//Use the line below instead of the line above for WP versions older than 2.9.1
				//remove_meta_box( 'pagecustomdiv', 'page', $context );
			}
		}
		/**
		* Create the new Custom Fields meta box
		*/
		function createCustomFields() {
			if ( function_exists( 'add_meta_box' ) ) {
				add_meta_box( 'my-custom-fields', 'Custom Fields', array( &amp;$this, 'displayCustomFields' ), 'page', 'normal', 'high' );
				add_meta_box( 'my-custom-fields', 'Custom Fields', array( &amp;$this, 'displayCustomFields' ), 'post', 'normal', 'high' );
			}
		}</pre>
<p>Now there&#8217;s the class&#8217;s constructor, which basically adds the action hooks for outputting the new meta box, saving values when the form&#8217;s submitted, and removing the default Custom Fields meta box if necessary.</p>
<p>Then there&#8217;s the functions to remove the default box, and to create the new one. In this code, it&#8217;s assumed that the new box will be there whatever on post and page screens. If you have a system where you only need it on one or the other, or have more complex conditions, you&#8217;ll need to adapt the <code>createCustomFields()</code> function.</p>
<p>Note that older versions of WordPress will need a slightly different line of code to remove the default box on page screens. (Thanks to <a href="http://www.afcincinnati.com/">Bryan Casteel</a> for this fix!)</p>
<pre name="code" class="php">		/**
		* Display the new Custom Fields meta box
		*/
		function displayCustomFields() {
			global $post;
			?&gt;
			&lt;div class="form-wrap"&gt;
				&lt;?php
				wp_nonce_field( 'my-custom-fields', 'my-custom-fields_wpnonce', false, true );
				foreach ( $this-&gt;customFields as $customField ) {
					// Check scope
					$scope = $customField[ 'scope' ];
					$output = false;
					foreach ( $scope as $scopeItem ) {
						switch ( $scopeItem ) {
							case "post": {
								// Output on any post screen
								if ( basename( $_SERVER['SCRIPT_FILENAME'] )=="post-new.php" || $post-&gt;post_type=="post" )
									$output = true;
								break;
							}
							case "page": {
								// Output on any page screen
								if ( basename( $_SERVER['SCRIPT_FILENAME'] )=="page-new.php" || $post-&gt;post_type=="page" )
									$output = true;
								break;
							}
						}
						if ( $output ) break;
					}
					// Check capability
					if ( !current_user_can( $customField['capability'], $post->ID ) )
						$output = false;</pre>
<p>Here&#8217;s the start of the output of the new custom fields box. We used <code>wp_nonce_field()</code> to improve <a href="http://markjaquith.wordpress.com/2006/06/02/wordpress-203-nonces/">security</a>, then start our loop through all the defined fields.</p>
<p>The first check is on the scope of the field, which is an array of strings indicating the context in which they should be used. Outputting defaults to false, then gets set to true if any of the scope conditions are fulfilled. As I said earlier, you can define your own scopes for particular needs&#8212;the sky&#8217;s the limit.</p>
<p>Then there&#8217;s a quick check on the capability.</p>
<pre name="code" class="php">					// Output if allowed
					if ( $output ) { ?&gt;
						&lt;div class="form-field form-required"&gt;
							&lt;?php
							switch ( $customField[ 'type' ] ) {
								case "checkbox": {
									// Checkbox
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'" style="display:inline;"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;&amp;nbsp;&amp;nbsp;';
									echo '&lt;input type="checkbox" name="' . $this-&gt;prefix . $customField['name'] . '" id="' . $this-&gt;prefix . $customField['name'] . '" value="yes"';
									if ( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField['name'], true ) == "yes" )
										echo ' checked="checked"';
									echo '" style="width: auto;" /&gt;';
									break;
								}
								case "textarea": {
									// Text area
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;';
									echo '&lt;textarea name="' . $this-&gt;prefix . $customField[ 'name' ] . '" id="' . $this-&gt;prefix . $customField[ 'name' ] . '" columns="30" rows="3"&gt;' . htmlspecialchars( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField[ 'name' ], true ) ) . '&lt;/textarea&gt;';
									break;
								}
								default: {
									// Plain text field
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;';
									echo '&lt;input type="text" name="' . $this-&gt;prefix . $customField[ 'name' ] . '" id="' . $this-&gt;prefix . $customField[ 'name' ] . '" value="' . htmlspecialchars( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField[ 'name' ], true ) ) . '" /&gt;';
									break;
								}
							}
							?&gt;
							&lt;?php if ( $customField[ 'description' ] ) echo '&lt;p&gt;' . $customField[ 'description' ] . '&lt;/p&gt;'; ?&gt;
					&lt;?php
					}
				} ?&gt;
			&lt;/div&gt;
			&lt;?php
		}</pre>
<p>Now the output&#8212;pretty self-explanatory!</p>
<pre name="code" class="php">		/**
		* Save the new Custom Fields values
		*/
		function saveCustomFields( $post_id, $post ) {
			if ( !wp_verify_nonce( $_POST[ 'my-custom-fields_wpnonce' ], 'my-custom-fields' ) )
				return;
			if ( !current_user_can( 'edit_post', $post_id ) )
				return;
			if ( $post-&gt;post_type != 'page' &#038;&#038; $post-&gt;post_type != 'post' )
				return;
			foreach ( $this-&gt;customFields as $customField ) {
				if ( current_user_can( $customField['capability'], $post_id ) ) {
					if ( isset( $_POST[ $this->prefix . $customField['name'] ] ) &#038;&#038; trim( $_POST[ $this->prefix . $customField['name'] ] ) ) {
						update_post_meta( $post_id, $this->prefix . $customField[ 'name' ], $_POST[ $this->prefix . $customField['name'] ] );
					} else {
						delete_post_meta( $post_id, $this->prefix . $customField[ 'name' ] );
					}
				}
			}
		}

	} // End Class

} // End if class exists statement

// Instantiate the class
if ( class_exists('myCustomFields') ) {
	$myCustomFields_var = new myCustomFields();
}</pre>
<p>Finally, a function to save the values when the form is submitted. The nonce is checked, then we loop through all the fields, checking that the capability is there and the field has been submitted. Then, we either add / update the field value if there is one, or delete it. You might want to just add / update, and store empty values for fields that apply to a post or page, but don&#8217;t have anything set. I thought I&#8217;d err on the side of keeping the database lean.</p>
<p>Then we instantiate the class, and that&#8217;s it.</p>
<h2>The full code</h2>
<p>Below is the code in full. To use it:</p>
<ol>
<li>Paste it into your <code>functions.php</code>.</li>
<li>Change the <code>$prefix</code> if you want.</li>
<li>Adapt the <code>$customFields</code> array to define your fields.</li>
<li>If you&#8217;ve added your own scopes, add <code>case</code> statements for them around line 82.</li>
<li>If you&#8217;ve added your own field types, add <code>case</code> statements for them around line 105.</li>
</ol>
<p>I&#8217;ve been adapting certain bits as a write this post, making the bits that are specific to my use of the code more general for this example, so forgive me if there&#8217;s any bugs that have crept in. Let me know if you find any problems with the code!</p>
<pre name="code" class="php">if ( !class_exists('myCustomFields') ) {

	class myCustomFields {
		/**
		* @var  string  $prefix  The prefix for storing custom fields in the postmeta table
		*/
		var $prefix = '_mcf_';
		/**
		* @var  array  $customFields  Defines the custom fields available
		*/
		var $customFields =	array(
			array(
				"name"			=&gt; "block-of-text",
				"title"			=&gt; "A block of text",
				"description"	=&gt; "",
				"type"			=&gt; "textarea",
				"scope"			=&gt;	array( "page" ),
				"capability"	=&gt; "edit_pages"
			),
			array(
				"name"			=&gt; "short-text",
				"title"			=&gt; "A short bit of text",
				"description"	=&gt; "",
				"type"			=&gt;	"text",
				"scope"			=&gt;	array( "post" ),
				"capability"	=&gt; "edit_posts"
			),
			array(
				"name"			=&gt; "checkbox",
				"title"			=&gt; "Checkbox",
				"description"	=&gt; "",
				"type"			=&gt; "checkbox",
				"scope"			=&gt;	array( "post", "page" ),
				"capability"	=&gt; "manage_options"
			)
		);
		/**
		* PHP 4 Compatible Constructor
		*/
		function myCustomFields() { $this-&gt;__construct(); }
		/**
		* PHP 5 Constructor
		*/
		function __construct() {
			add_action( 'admin_menu', array( &amp;$this, 'createCustomFields' ) );
			add_action( 'save_post', array( &amp;$this, 'saveCustomFields' ), 1, 2 );
			// Comment this line out if you want to keep default custom fields meta box
			add_action( 'do_meta_boxes', array( &amp;$this, 'removeDefaultCustomFields' ), 10, 3 );
		}
		/**
		* Remove the default Custom Fields meta box
		*/
		function removeDefaultCustomFields( $type, $context, $post ) {
			foreach ( array( 'normal', 'advanced', 'side' ) as $context ) {
				remove_meta_box( 'postcustom', 'post', $context );
				remove_meta_box( 'postcustom', 'page', $context );
				//Use the line below instead of the line above for WP versions older than 2.9.1
				//remove_meta_box( 'pagecustomdiv', 'page', $context );
			}
		}
		/**
		* Create the new Custom Fields meta box
		*/
		function createCustomFields() {
			if ( function_exists( 'add_meta_box' ) ) {
				add_meta_box( 'my-custom-fields', 'Custom Fields', array( &amp;$this, 'displayCustomFields' ), 'page', 'normal', 'high' );
				add_meta_box( 'my-custom-fields', 'Custom Fields', array( &amp;$this, 'displayCustomFields' ), 'post', 'normal', 'high' );
			}
		}
		/**
		* Display the new Custom Fields meta box
		*/
		function displayCustomFields() {
			global $post;
			?&gt;
			&lt;div class="form-wrap"&gt;
				&lt;?php
				wp_nonce_field( 'my-custom-fields', 'my-custom-fields_wpnonce', false, true );
				foreach ( $this-&gt;customFields as $customField ) {
					// Check scope
					$scope = $customField[ 'scope' ];
					$output = false;
					foreach ( $scope as $scopeItem ) {
						switch ( $scopeItem ) {
							case "post": {
								// Output on any post screen
								if ( basename( $_SERVER['SCRIPT_FILENAME'] )=="post-new.php" || $post-&gt;post_type=="post" )
									$output = true;
								break;
							}
							case "page": {
								// Output on any page screen
								if ( basename( $_SERVER['SCRIPT_FILENAME'] )=="page-new.php" || $post-&gt;post_type=="page" )
									$output = true;
								break;
							}
						}
						if ( $output ) break;
					}
					// Check capability
					if ( !current_user_can( $customField['capability'], $post->ID ) )
						$output = false;
					// Output if allowed
					if ( $output ) { ?&gt;
						&lt;div class="form-field form-required"&gt;
							&lt;?php
							switch ( $customField[ 'type' ] ) {
								case "checkbox": {
									// Checkbox
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'" style="display:inline;"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;&amp;nbsp;&amp;nbsp;';
									echo '&lt;input type="checkbox" name="' . $this-&gt;prefix . $customField['name'] . '" id="' . $this-&gt;prefix . $customField['name'] . '" value="yes"';
									if ( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField['name'], true ) == "yes" )
										echo ' checked="checked"';
									echo '" style="width: auto;" /&gt;';
									break;
								}
								case "textarea": {
									// Text area
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;';
									echo '&lt;textarea name="' . $this-&gt;prefix . $customField[ 'name' ] . '" id="' . $this-&gt;prefix . $customField[ 'name' ] . '" columns="30" rows="3"&gt;' . htmlspecialchars( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField[ 'name' ], true ) ) . '&lt;/textarea&gt;';
									break;
								}
								default: {
									// Plain text field
									echo '&lt;label for="' . $this-&gt;prefix . $customField[ 'name' ] .'"&gt;&lt;b&gt;' . $customField[ 'title' ] . '&lt;/b&gt;&lt;/label&gt;';
									echo '&lt;input type="text" name="' . $this-&gt;prefix . $customField[ 'name' ] . '" id="' . $this-&gt;prefix . $customField[ 'name' ] . '" value="' . htmlspecialchars( get_post_meta( $post-&gt;ID, $this-&gt;prefix . $customField[ 'name' ], true ) ) . '" /&gt;';
									break;
								}
							}
							?&gt;
							&lt;?php if ( $customField[ 'description' ] ) echo '&lt;p&gt;' . $customField[ 'description' ] . '&lt;/p&gt;'; ?&gt;
						&lt;/div&gt;
					&lt;?php
					}
				} ?&gt;
			&lt;/div&gt;
			&lt;?php
		}
		/**
		* Save the new Custom Fields values
		*/
		function saveCustomFields( $post_id, $post ) {
			if ( !wp_verify_nonce( $_POST[ 'my-custom-fields_wpnonce' ], 'my-custom-fields' ) )
				return;
			if ( !current_user_can( 'edit_post', $post_id ) )
				return;
			if ( $post-&gt;post_type != 'page' &#038;&#038; $post-&gt;post_type != 'post' )
				return;
			foreach ( $this-&gt;customFields as $customField ) {
				if ( current_user_can( $customField['capability'], $post_id ) ) {
					if ( isset( $_POST[ $this->prefix . $customField['name'] ] ) &#038;&#038; trim( $_POST[ $this->prefix . $customField['name'] ] ) ) {
						update_post_meta( $post_id, $this->prefix . $customField[ 'name' ], $_POST[ $this->prefix . $customField['name'] ] );
					} else {
						delete_post_meta( $post_id, $this->prefix . $customField[ 'name' ] );
					}
				}
			}
		}

	} // End Class

} // End if class exists statement

// Instantiate the class
if ( class_exists('myCustomFields') ) {
	$myCustomFields_var = new myCustomFields();
}</pre>
<p><strong class="alert">UPDATE 18/11/09:</strong> I&#8217;ve just found an important issue with using the <code>save_post</code> hook. Alex King explains it <a href="http://alexking.org/blog/2008/09/06/wordpress-26x-duplicate-custom-field-issue">here</a>. The executive summary is that when the <code>saveCustomFields</code> function above is added to the <code>save_post</code> hook, it&#8217;s now set to receive 2 arguments&#8212;the post ID, as before, plus the post&#8217;s data. Using the passed <code>$post</code> argument, the save function checks that the <code>post_type</code> is &#8220;page&#8221; or &#8220;post&#8221;. This stops the save code being run for autosaves or saving revisions, which could create duplicate postmeta fields.</p>
<p><strong class="alert">UPDATE 5/3/10:</strong> I&#8217;ve been alerted to a recent change in WordPress 2.9.1+ that affects the code in the <code>removeDefaultCustomFields</code> function to remove the default Custom Fields box on page screens. The change is highlighted in the above code.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/control-your-own-wordpress-custom-fields/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>Get WordPress users by role</title>
		<link>http://sltaylor.co.uk/blog/get-wordpress-users-by-role/</link>
		<comments>http://sltaylor.co.uk/blog/get-wordpress-users-by-role/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 02:07:17 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=261</guid>
		<description><![CDATA[There&#8217;s a few posts around that reveal a nifty use of the WP_User_Search class that&#8217;s part of WordPress&#8217; core code, in order to select all users that have a specific role (the trick seems to have originated with John Kolbert). But&#8230; WP_User_Search is only loaded when you&#8217;re inside the WP admin area. What about front-end [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a few posts around that reveal a nifty use of the <code>WP_User_Search</code> class that&#8217;s part of WordPress&#8217; core code, in order to select all users that have a specific role (the trick seems to have originated with <a href="http://www.johnkolbert.com/wordpress/how-to-get-all-users-with-a-specific-role/">John Kolbert</a>).</p>
<p>But&#8230; <code>WP_User_Search</code> is only loaded when you&#8217;re inside the WP admin area. What about front-end template code?</p>
<p><span id="more-261"></span></p>
<p>I decided to track down the SQL that <code>WP_User_Search</code> comes up with for the search (using <a href="http://codex.wordpress.org/Function_Reference/wpdb_Class#Class_Variables"><code>$wpdb-&gt;queries</code></a>), and write a custom function wrapper which will work the same way wherever.</p>
<p>I&#8217;m not quite sure if there&#8217;s any advantage to including the use of <code>WP_User_Search</code> as well as the back-up SQL, as they pretty much do the same thing. I dunno.</p>
<p>Anyway, here&#8217;s the code. This is for pasting into your theme&#8217;s <code>functions.php</code> file. It&#8217;ll return an array of user IDs.</p>
<pre name="code" class="php">function getUsersByRole( $role ) {
	if ( class_exists( 'WP_User_Search' ) ) {
		$wp_user_search = new WP_User_Search( '', '', $role );
		$userIDs = $wp_user_search-&gt;get_results();
	} else {
		global $wpdb;
		$userIDs = $wpdb-&gt;get_col('
			SELECT ID
			FROM '.$wpdb-&gt;users.' INNER JOIN '.$wpdb-&gt;usermeta.'
			ON '.$wpdb-&gt;users.'.ID = '.$wpdb-&gt;usermeta.'.user_id
			WHERE '.$wpdb-&gt;usermeta.'.meta_key = \''.$wpdb-&gt;prefix.'capabilities\'
			AND '.$wpdb-&gt;usermeta.'.meta_value LIKE \'%"'.$role.'"%\'
		');
	}
	return $userIDs;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/get-wordpress-users-by-role/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New WordPress plugin: Lock Pages</title>
		<link>http://sltaylor.co.uk/blog/new-wordpress-plugin-lock-pages/</link>
		<comments>http://sltaylor.co.uk/blog/new-wordpress-plugin-lock-pages/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 23:24:30 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=256</guid>
		<description><![CDATA[I&#8217;m very please to announce my first WordPress plugin! It&#8217;s called Lock Pages. The idea came from work with various clients where certain pages started to get moved around, or just vanished. A page can &#8220;move&#8221; by having its parent page or the slug changed. Sometimes clients would delete a page and replace it with [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very please to announce my first WordPress plugin! It&#8217;s called <a href="/wordpress/plugins/lock-pages/">Lock Pages</a>.</p>
<p>The idea came from work with various clients where certain pages started to get moved around, or just vanished. A page can &#8220;move&#8221; by having its parent page or the slug changed. Sometimes clients would delete a page and replace it with an updated version which had a slightly different slug.</p>
<p>Of course, many of these things just stem from usually harmless habits picked up from working with files on a computer. But on a website, you want to persist your URLs as long as possible. Unless absolutely necessary, pages should be kept with the same permalink, to avoid breaking links and to maximize PageRank and such like.</p>
<p><span id="more-256"></span></p>
<p>So, I created this plugin that lets you either lock <em>all</em> pages, or just particular pages. A page being &#8220;locked&#8221; means the slug can&#8217;t be edited, the parent can&#8217;t be changed, and it can&#8217;t be deleted. (Although, of course admins can still do these things.)</p>
<p>There&#8217;s a little more to it than that, but not much. It&#8217;s relatively simple. I&#8217;ve not yet got it going on any production sites, so technically it&#8217;s still in beta. But I&#8217;ve given it enough testing now to feel it should be announced. And yes, when I find a moment and I&#8217;ve tested it on production sites, I&#8217;ll prep it for release on the wordpress.org plugins repository.</p>
<p>Anyway, do <a href="/wordpress/plugins/lock-pages/">check it out and let me know what you think&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/new-wordpress-plugin-lock-pages/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Plugins that detect whether they&#8217;re being used</title>
		<link>http://sltaylor.co.uk/blog/plugins-detect-being-used/</link>
		<comments>http://sltaylor.co.uk/blog/plugins-detect-being-used/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 12:41:15 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=228</guid>
		<description><![CDATA[There&#8217;s been a few posts round and about recently with people chipping in to make suggestions for WordPress plugins. Here&#8217;s my tuppence worth&#8230; Ideally, all active plugins should provide an &#8220;Am I being used?&#8221; option (alongside the usual &#8220;Deactivate&#8221; and &#8220;Edit&#8221; links on the WP plugins page). This would scan the system and detect whether [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a few posts <a href="http://justintadlock.com/archives/2009/09/22/plugin-and-theme-authors-should-force-users-to-upgrade">round</a> and <a href="http://digwp.com/2009/10/ideas-for-plugins/">about</a> recently with people chipping in to make suggestions for WordPress plugins. Here&#8217;s my tuppence worth&#8230;</p>
<p><span id="more-228"></span></p>
<p>Ideally, all active plugins should provide an &#8220;Am I being used?&#8221; option (alongside the usual &#8220;Deactivate&#8221; and &#8220;Edit&#8221; links on the WP plugins page). This would scan the system and detect whether or not there&#8217;s any current content, widgets, etc. that depend on the plugin being activated.</p>
<p>This might not always be 100% testable. In such cases, part of the test should include alerts regarding ways in which the plugin might be in use that are only manually detectable.</p>
<p>However, this kind of mechanical detection would help <em>a lot</em> when you&#8217;re scanning the list of plugins on a site, wondering whether or not all the active plugins are actually needed. Encouraging this kind of functionality might go a long way to helping reduce needless plugin overheads on WP installations.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/plugins-detect-being-used/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
