Smokes your problems, coughs fresh air.

Tag: WordPress (Page 1 of 3)

WordPress for my forest vacation home in Norg

For a decade and a half, my uncle had been maintaining the website for our vacation home in the forests of Drenthe in Dreamweaver. This worked fine, except that:

  1. it didn’t allow me to edit and add content and photos simultaneously;
  2. the website had started to look and feel dated;
  3. it wasn’t mobile-ready; and
  4. all this was affecting its ranking in Google.

That’s why I had been having a new WordPress website in the pipeline since forever. However, in true 80/20 fashion, I was postponing the final steps of copying over the last bits of content and the training of my uncle to edit the website in WordPress instead of in Dreamweaver.

Why WordPress?

The last few websites I built I built myself from scratch, like in the good old days, using a simple static site generation pipeline (basically a fancy Makefile). The reasoning is that comments are too much hassle to moderate anyway, and comments and trackbacks are what WordPress offered me. Apart from that I very much prefer authoring in vim.

But that’s me. Most people, my uncle included, are way more comfortable with WYSIWYG editors—in other words: WordPress its Gutenberg editor.

A mature developer has to be able to sidestep his preferences to deliver something that’s best for the “customer”. (Indeed this post will be me bragging of how mature a developer I am. I do turn 40 tomorrow after all.)

My main “design” goal was that I didn’t want to change too much at once. The site structure and site content had to remain mostly identical, so that we would have fewer points of discussion to surmount before going live.

At the same time, I did want to clean up the content and the formatting. The old website had a distinct lack of bullets, formal headings, use of bold text, etc. (No, I don’t have pictures.) That made the text a bit difficult to parse, especially when the visitor—a potential tenant of our forest home—was just trying to find a specific piece of information at a glance.

Proper formatting makes long page much more accessible.

The new website is not fancy. The theme is just one of WordPress its default themes, and I ended up not even using a graphical header to get the first version online. Important to me is that I can now easily add blog posts (like about a pretty yellow flower that I got to grow there abundantly). Also, whenever now I want to edit some text in one of the informational pages, I can.

The “page with booking information and booking availability gave me the most headaches and demanded the most from my maturity. The first thing to swipe off the table was the use of any type of booking plugin. This turned out to be the most important decision (and a very good call!). The old website (with light-yellow background) had one of those old-fashioned tables with big-ridged borders around every cell. I wanted to at least make this table look good and modern.

I gave the booking periods table a sticky header. That was something at least. What I did not do was giving the individual cells a border. But, as much as he tried liking it, my uncle hated that incarnation of the table. So I put back in some cell borders, which I had already done in the print CSS version.

Then there was the issue that my uncle had gotten used to printing out the booking schedule, and it now spanned a number of pages. Thus I did a lot of tinkering in the print CSS to make it all fit (and to make the table header repeat, just in case). And it turned that both cleaning ladies didn’t like the spacious table layout on the screen either. I had altogether forgot about them as consumers of the table, focusing instead on potential tenants. More squeezing followed, until everybody was happy, and I was … relieved.

The booking schedule of our vacation home in Norg, Drenthe, the Netherlands.

It deserves mentioning that I did all these CSS within WordPress its theme customizer. Normally, I would have preferred to use a child theme for this, but it felt to early to start a child-theme, as long as I haven’t fully committed to a particular parent theme. Also, the CSS for that booking schedule table is some of the worst you might have seen. After all, the HTML is not semantic at all. It’s not like I’m going to train my uncle to specify class names on each cell. Without proper classification, I had to use implicit classification, ending up with selectors such as the td:nth-child(4):not([colspan]):not(:empty) selector that I use to make the background of occupied periods black, but only if they are not some special multi-column note. To scare the CSS wizards out there, here’s the current CSS for the table:

@media screen {
table.wp-block-advgb-table.advgb-table-frontend {
	border-width: 0;
	border-spacing: 0;
	border-collapse: separate;
	table-layout: auto;
}
.wp-block-advgb-table > thead > tr {
	position: sticky;
	top: 0;
}
.wp-block-advgb-table > thead > tr > th {
	background-color: white;
	box-sizing: border-box;
	border-top: 1px solid black;
	border-left: none;
	border-right: 1px solid black;
	border-bottom: 2px solid black;
	padding: 2px 4px;
}
.wp-block-advgb-table > thead > tr > th {
	border-left: 1px solid black;
}
.wp-block-advgb-table > tbody > tr > td {
  border-top: none;
	border-left: none;
	border-right: 1px solid black;
	border-bottom: 1px solid black;
	padding: 2px 4px;
}
.wp-block-advgb-table > tbody > tr > td:first-child {
  border-left: 1px solid black;
}
.wp-block-advgb-table > tbody > tr > td:nth-child(4):not([colspan]) {
	width: 2em;
	font-size: 70%;
}
	.wp-block-advgb-table > tbody > tr > td:nth-child(4):not([colspan]):not(:empty) {
		background-color: black;
		color: white;
	}
.wp-block-advgb-table > tbody > tr > td[rowspan] {
}
}
@media screen and (max-width: 1000px) {
	table.wp-block-advgb-table.advgb-table-frontend {
		position: relative;
		left: -7.6923%;
		max-width: none;
	  font-size: 70%;
	}
	.wp-block-advgb-table > thead > tr > th, .wp-block-advgb-table > tbody > tr > td {
		padding: 0px 1px;
	}
	.wp-block-advgb-table > thead > tr > th {
		overflow-wrap: break-word;
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3):after {
		content: 'Prijs';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4):after {
		content: 'Vrij?';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > tbody > tr > td:first-child {
		min-width: 8ch;
		max-width: 12ch;
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(2) {
		word-spacing: -.2ch;
		min-width: 15ch;
		max-width: 20ch;
	}
}
@media screen and (min-width: 1001px) {	 .wp-block-advgb-table > thead > tr {
		top: 21px;  /* Space from the theme that somehow has a weird z-indexy effect. */
	}
	body.admin-bar .wp-block-advgb-table > thead > tr {
		top: calc(31px + 21px);
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(2) {
		white-space: nowrap;
		max-width: 20em;
  }
}
/* filter bypass hack */@media print {
  .wp-block-advgb-table.advgb-table-frontend {
		width: 100%;
	  border: 1pt solid black important!;
	  border-spacing: 0;
		border-collapse: collapse;
		font-size: 8pt;
		table-layout: auto;
  }
	.wp-block-advgb-table > thead > tr > th {
		border: 2pt solid black !important;
		padding: 2pt 4pt;
	}
	table.wp-block-advgb-table > tbody > tr > td {
		border: 1pt solid black !important;
		padding: 1pt 4pt;
	}
	.wp-block-advgb-table > tbody > tr > td:first-child {
		white-space: nowrap;
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3):after {
		content: 'Prijs';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4):after {
		content: 'Vrij?';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(3) {
		max-width: 8ch;
	}
}

Which reminds me of something quite terrible about Gutenberg. Its table block doesn’t support merged cells, like—what the fuck?—why is this not considered a priority? Fucking hipsters and their having to reinvent the wheel every year and taking years to put all the spokes back into place. The “solution” was to install a plugin—PublishPress Blocks—that among other blocks that I don’t need (and could thankfully turn off) an “Advanced Table Block” that does support cell merging, but with such nasty bugs that it’s really hard to train my uncle to work around them. Sadly, there has been no activity yet to fix either one of them.

That’s it. This project didn’t make me more of a WordPress fan. (I’m no hater either. I think that WordPress its UX, specifically, has long been excellent, and exemplary in its non-nerdiness, quite the contrast with other popular open source CMSs.) But I chose the right tool for the right job and managed to make myself and the other “customers” happy. Since the go-live, I’ve added a number of blog posts already, and it’s great fun to now be able to contribute to this website’s content.


Did this get you interested? Feel free to book a stay in our idyllic vacation home in Norg, Drenthe, the Netherlands

The terrible state of my tech

It’s a bit pathethic how well I have been taking care of my own tech. ever since I started studying. What’s worse: this haven’t improved when I stopped my studies for other ventures. I think the reason for this is exceedingly simple: I don’t like to do work-like things I don’t write about; luckily, I love to structure my goals in writing, and this blog still hasn’t completely collapsed under my neglect.

If I love writing about stuff I do, have I simply not done anything in the past few years? Well, I’ve done things. I’ve even written about them too, in other places, mostly on paper. It’s just that, dispite working for a tech company for the last couple of years, I have done hardly a thing about ridding myself of my private technical debt. Or is it because of working at a tech company, where I’m hard at work fighting technical debts in Python/Django projects and documenting the progress in Redmine?

I won’t mention the reasons why I want to spend time on this weird, hodgy-podgy blog again. Let me just say that the main motivation is not guilt for having created a technical debt. And the actual reasons are better suited for other posts at another time.

Domain Problem Short-term fix Mid-term fix Long-term fix
blog.bigsmoke.us Spam ✔ 2017-07-18 Disable comments and ping/trackbacks on new posts.
2017-07-18 Disable comments and ping/trackbacks on old posts.
2017-07-19 Remove spam.
Security Upgrade WordPress svn:external Automatically upgrade WordPress
www.bigsmoke.us Non-responsive Make responsive
Outdated 2018-10-28 Reduce and update content
* Huge hosting costs Find sinkhole between my NFSN accounts 2019-01-26Move to cheapsolid VM host (TransIP? Tilaa)
blog.omega-research.org Security Move personal posts to blog.bigsmoke.us and replace with redirects
Replace blog with static rendering of blog
opschoot Wheezy fan Replace or re-attach fan.
Neglected backups Backup monitoring: opschoot should register itself when online and I should then be nagged if I don’t backup.
butler Legacy Move files somewhere else (public?)

Using papercite WordPress plugin for academic note-taking

During most of my bachelor, I’ve used paper and pen or pencil to take notes. Halfway my second minor [Okasys], though, I switched to my laptop and LaTeX, which I preferred, because typing is faster than writing and reworking my notes into a halfway decent summary usually proved too time-consuming with hand-written notes. Admittedly, though, although reorganizing my notes became easier with LaTeX, I still didn’t really get to the finished summary stage, because I’m still way too obsessive-compulsive about the whole thing, most of the time. Now, since I figured I use my blog for all sorts of notes, I can just as well let WordPress and Google do some of the organizing for me, while taking notes for my present course. I just have to be a bit more careful about copyright issues (but, if the need strikes, I can always set a post to private).

There are various WordPress plugins for keeping track of academic references. I’m now experimenting with papercite [documentation. From the feature list, I was more interested in the AcademicPress plugin, but the former seems te be more actively developed. However, I’m thinking of switching to a simple footnotes and/or endnotes plug-in, since my use of papercite so far actually doesn’t include maintaining biography files shared by more than one post, and papercite doesn’t support author-year citations anyway. I’m surrounding the text with [bibshow file=custom://data][/bibshow] shortcodes, which references a BibTeX biography stored in a custom field called papercite_data.

Installed MathJax-LaTeX WordPress plugin for blog.bigsmoke.us

Soon, I wish to document some statistical issues I’ve been running into lately due to the lack of understanding maintained by my recipe-level statistics training. Also, I’d like to document some of the things I did learn over the years, and, hopefully, the things I find out while working myself out of the modelling mountain that I currently find so difficult to mount. For this I will need to use some mathematical language, which is why I just installed the MathJaX-LaTeX WordPress plugin. MathJax-LaTeX uses the MathJax JavaScript library to support LaTeX and MathML math equations in WordPress without requiring the browser to have MathML support.

As for testing it, my knowledge (\(K()\)) of MathML (\(M\)) is pretty much nonexistant, while I’m quite comfortable with LaTeX (\(L\)) math exations, which is why I’m typing the LaTeX code “K(M) \ll K(L)” to generate the following simple equation:

\(K(M) \ll K(L)\)

Aihato WordPress maintenance notes

According to Brian Kernighan, “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?” With that in mind I’m re-exposing myself to the spaghetti that is the Aihato WordPress code base.

My last comment on that project stems from December of 2010, although there have been some minor code updates in the meantime—not all of them by me—mostly having to do with the look and feel.

During my Christmas break, I visited the Ytec office to meet with their sysadmin. He made the old Subversion repository available to me again (although, internally, they’ve gone over to Bazaar) and created a new development version of the site (which hadn’t been moved along with the move of the production version to a new server). After some changes to my Makefile, I’m now able to do the whole development/production dance again, and I’ve just tested this by successfully upgrading to WordPress 3.5.1 (all the way from 3.0.5). Yes, this is quite a simple affair, if your setup is 1337:

Upgrading WordPress

I really like it better when the WordPress factory stuff lives in its own directory. I like this better even than using vendor branches to keep track of what’s mine and what’s WordPress’s. Let me show you why (and yes, I could have turned this into a proper script, if I wanted to):

# Get into my working dir
www.aihato.nl
 
# Add the new WP version to the externals
svn propget svn:externals . > /tmp/wp-ext 'wp-3.5.1 http://core.svn.wordpress.org/tags/3.5.1/' >> /tmp/wp-ext
svn update
svn propset svn:externals --file /tmp/wp-ext
 
rm wp # The symbolic link pointing to the old wp-3.0.5
ln -s wp-3.5.1 wp
 
make update-development # to test if the upgrade will fuck up anything major
make deploy-production # because it works
 
svn ci -m "Upgraded WP from wp-3.0.5 to wp-3.5.1."

Rewrite problems after upgrade

Of course, the upgrade had to cause some trouble. This particular trouble was caused by some code in my theme’s functions.php that really belonged in a plugin. I basically made a rogue call to $wp_rewrite->flush_rules(); which caused the rewrite rules to either lack the ones concerning my custom category base (‘/categorie’) or those concerning my custom rewrite endpoints.

To fix this I created an exceedingly simple plugin with just the following code:

add_action('init', 'gallery_endpoint_initialize');
 
register_activation_hook( __FILE__, function() {
  global $wp_rewrite;
 
  add_rewrite_endpoint('gallery', EP_PERMALINK | EP_PAGES);
  $wp_rewrite->flush_rules();
});
 
function gallery_endpoint_initialize() {
  add_rewrite_endpoint('gallery', EP_PERMALINK | EP_PAGES);
  add_filter('query_vars', 'aihato_queryvars');
}
 
function aihato_queryvars($qvars) {
  $qvars[] = 'gallery';
  return $qvars;
}

Thoughts on custom post types for fighter profiles

I commented on custom post types before, in the section on fighter profiles in the extensive summary of the whole development process, and in a comment in my development notes.

The custom post type for fighter profiles that I started implementing as a plugin is still quite high on my feature wishlist. The complex dance with page parent, page template and custom fields has proven to be quite difficult for the guys.

At the time, a real showstopper “bug” was that the featured image box wasn’t displayed with the post type. Now, it took me approximately five minutes to find out that I should have simply added the custom post type to the add_theme_support() call in my theme’s functions.php:

add_theme_support('post-thumbnails', array('post', 'page', 'aihato_fighter'));

Another problem “was that clicking the Insert image button replaced the current page with the upload dialog instead of loading it in a modal dialog through AJAX.” This seems to be resolved in the new WordPress, so postponing the custom post type stuff until it had stabilized a bit in the future has proven to be an excellent strategy. Apparently, that future has arrived.

I do wonder: if I implement the custom post type for fighter profiles now, how do I convert my existing page content to the custom post type? Could I just change the post_type field in the database after adding the necessary function calls to register this new type?

Also, I’m thinking of turning some of the custom fields not just into fancy boxes in the post edit GUI, but into proper taxonomies. This might complicate migration even further, so it’s probably the wisest course to do this thing in phases:

  1. Implement the custom post types with integrated support in the GUI for the custom fields that will remain custom fields under the hood.
  2. Maybe migrate some custom fields (such as fighter discipline) to proper taxonomies.
  3. Modify the theme to use the new custom post type instead of the old pages.
  4. Integrate the fight record stuff with the aihato-events stuff.

The process of moving to fighter profiles to their own custom post type deserves a dedicated post, but this’ll have to wait until I actually continue this process.

Thoughts on improving the photo gallery

There are some annoying bugs in the photo gallery. I want to start out by upgrading all the relevant JavaScript libraries that I used to see how far that will bring me.

Performance-wise, there’s also some low-hanging fruit. Photo’s are often uploaded in high resolution. Instead of forbidding this, I want this to be performance neutral in its effect by, instead of using the full version of the image in many places (such as the gallery, using a huge-ass thumbnail that serves as the “enlarged” version when you click pictures in the gallery and such.

Thoughts on improving the video gallery

With regards to the video gallery, it has turned out the YouTube support is not sufficient. I will have to find a way to base the gallery on all oEmbed links. I have, since initial deployment, already added embed (not oEmbed) support for fightstartv.com:

wp_embed_register_handler('fightstartv', '|http://www\.fightstartv\.com/videos/([a-zA-Z0-9-_]+)/|', 'embed_handler_fightstartv');
 
function embed_handler_fightstartv($matches, $attr, $url, $rawattr) {
  $fstv_html = file_get_contents($url);
  $fstv_html_matches = array();
  preg_match('|"(/upload/[^"/]+.mp4)".*"image": "([^"]+)"|', $fstv_html, $fstv_html_matches);
  $fstv_mp4_url = 'http://www.fightstartv.com' . $fstv_html_matches[1];
  $fstv_image_url = $fstv_html_matches[2];
 
  $embed = '<embed src="http://www.fightstartv.com/wp-content/plugins/vipers-video-quicktags/resources/jw-flv-player/player.swf" height="300" width="600" bgcolor="0x000000" allowscriptaccess="always" allowfullscreen="true" flashvars="file='.urlencode($fstv_mp4_url).'&skin=http%3A%2F%2Fwww.fightstartv.com%2Fwp-content%2Fplugins%2Fvipers-video-quicktags%2Fresources%2Fjw-flv-player%2Fskins%2Fmodieus.swf&volume=100&bufferlength=3&backcolor=0x000000&duration=-1&frontcolor=0xffffff&lightcolor=0xffffff&screencolor=0x000000&autostart=false&image='.urlencode($fstv_image_url).'&ltas.cc=zerfildkisjwvgk&ltas.height=268&ltas.width=700&ltas.y=0&ltas.visible=true&ltas.x=0&adtvideo.height=268&adtvideo.y=0&adtvideo.position=over&adtvideo.width=700&adtvideo.visible=true&adtvideo.x=0&adtvideo.config=http%3A%2F%2Fwww.fightstartv.com%2Fmy_config.xml& adttext.height=268& adttext.width=700& adttext.y=0& adttext.visible=true& adttext.x=0&adttext.y=0&adttext.x=0&adttext.height=268&adttext.visible=true&adttext.config=http%3A%2F%2Fwww.fightstartv.com%2Fadttext.php&adttext.width=600&plugins=hd-2,viral-1,ltas,adtvideo, http://plugins.longtailvideo.com/5/flow/flow-2.swf, adttext,adttext"/>';
    echo $match[0];
 
  return apply_filters('embed_fightstartv', $embed, $matches, $attr, $url, $rawattr);
}

But these videos show up as just links in the film gallery instead of sporting the fancy FancyBox popup. Luckily, thumbnails do work, but more due to a quirk than by actual design. 🙁 This is going to take some time to cleanup, because most of the code concerned is terribly YouTube-centric by design.

Latest video on the homepage

The homepage features a block with the latest video. From my previous notes on this subject: “[… T]o show the latest video on the homepage, I just perform a search for posts which contain a YouTube URL. Then I parse the content a bit, and include the YouTube ID in my own low-res embed code. (The latest video area on the homepage is smaller than the default embed created by WordPress.)”

As of late, no video had been showing there, making me suspect—No I’m not telling you that. It’s actually too embarrassing!

Block with(out) latest video on the home page

Block with(out) latest video on the home page

This had everything to do with a missing hyphen character in the video id character class in the YouTube URL matching regexp within the scraping function:

preg_match('|http://www.youtube.com/watch\?v=([-a-zA-Z0-9]+)|', // better
preg_match('|http://www.youtube.com/watch\?v=([a-zA-Z0-9]+)|', // worse 

With the hyphen added:

Block with latest video on the home page

Block with latest video on the home page

Making post thumbnails crop from the top

WordPress hard crops uploaded images to match the post thumbnail size (set with set_post_thumbnail_size()) and the other alternative image sizes (added through add_image_size()). It does this from the center. This gives horrible results in the common case that a person does not happen to be decapitated and holding his or her head in his or her hands:

Aihato fighter profiles with cut-off heads

In the image editor, there is the ability to edit the thumbnail separately from the actual image, allowing you to manually crop the thumbnail, but this is cumbersome and only allows you to choose between applying the changes to all image sizes, just the thumbnail or to everything but the thumbnail, and I happen to not be using the thumbnail for the fighter profiles.

Basically, what I want is for WordPress to hard crop from the top instead of from the middle of the photo. And this would be an ok default for all photos. I truly don’t get why this isn’t configurable by default.

I found someone suggesting to change image_resize_dimensions() in wp-includes/media.php, because, at the time that he encountered the problem, there were apparently no plugin hooks available. There is a filter now, since WP version 3.4, called “image_resize_dimensions”. A quick Googling for this function/filter name reveals that, apparently, the Codex now even has a ready-to-go recipe to crop thumbnails by keeping the top of the image, instead of the default center.

With this code up and running in a plugin called ‘top-crop’, I consider this problem fixed. No more looking at beheaded fighters and no need for my users to muck around with the image editor (which wouldn’t work anyway because I use to many different image sizes).

My trusty old regenerate-thumbnails and the new AJAX Thumbnail Rebuild are doing their job after me chasing ghosts for hours because of a silent file permission problem on the development web server.

Aihato fighter profiles with heads

Aihato fighter profiles with heads

Relief and anticipation

In retrospect, digging back into the spaghetti isn’t as bad as it could have been, partly because I spent an extraordinary amount of time on documenting all the bumps in the road before. After reacquainting myself, I’m actually less intimidated by the prospect of upping the awesomeness of www.aihato.nl than I was when I actually delivered the product, which goes entirely against the saying at the beginning of this article. Either I’m smarter now than I was a couple of years ago, or I exercised sufficient constraint in introducing complexities (although (mostly well-documented) idiosyncrasies abound).

WordPress admin bar and absolute CSS positioning

WordPress 3.2 introduced an admin bar, which is fixed at the top of the window when you’re logged in. An annoying side-effect that has been bugging me for some time is that, although this pushed down most of my content, HTML elements that used absolute positioning stayed in there old place. This didn’t look particularly good, but I left it hanging for a long time because it only affected logged in users (that is: either me or Halfgaar).

The fix is actually rather simple. I added the following rule:

body {:; }

It may seem non-obvious, but absolutely positioned elements are actually positioned relative to their relatively positioned ancestors. Well, just read the proper explanation at CSS-Tricks. I can’t explain this shit.

WordPress admin bar with correct positioning

How it was supposed to look

WordPress admin bar induced CSS positioning screw-up

How it really looked

Commenting fixed for blog.bigsmoke.us

To my great surprise, thanks to Tobias Sjösten, I found out that commenting was broken on blog.bigsmoke.us. I couldn’t pinpoint the exact problem, but it must have been introduced with some WordPress upgrade somewhere along the line. I never noticed it because it did work for logged in users. (If I must really guess, I suspect a silent ReCaptcha version compatibility problem.)

Upgrading WordPress and wp-recaptcha to their latest versions (3.3.1 and 3.1.4 respectively) seems to have solved the problem.

Posting to WordPress via the command-line

In February I was interested in posting to WordPress from the command-line, a possibility that I enjoyed when I wanted to apply some CLI-magic to some of my MediaWiki installations in the past.

I came across a great Perl module (WordPress::CLI) by Leo Charre. It depends on WordPress::XMLRPC

Another approach is to use the appfs FUSE filesystem, which uses WordPress’ support for the Atom Publishing Protocol. There’s another FUSE filesystem, BlogFS. This one depends on WordPress’ XML-RPC instead of its Atom interface.

Taking control of the wpautop filter

WordPress does automatic paragraph formatting using the wpautop filter, some PHP code originally developed by Matt Mullenweg. For most of the time that this blog has existed, I’ve disabled the wpautop filter using the following two lines in my theme’s functions.php file:

remove_filter('the_content', 'wpautop');
remove_filter('the_excerpt', 'wpautop');

I’m not the only one to do this. But, I’m tired of having to manually type <p>s for every paragraph in every post that I write.

I’d like to be able have it back on, but preferably a bit smarter so that you don’t get all that crap (also common on bulletin boards with empty paragraphs around undetected block-level elements, especially if these are non-standard, related to plugins.

At the very least I want to be able to turn it off for when it does annoy me, on these moments that I don’t want auto-anything. Also, I need this if I don’t want to break the nearly 300 posts that I formatted manually. So, I want to use a custom field to turn the filter on or off.

I found an unpublished plugin (unpublished in the sense that the source isn’t hosted somewhere proper such as wordpress.org/extend/plugins/) which does some of what I want in a somewhat messy unmaintained manner. After years of just entering those damn <p>s (and over a year since this draft was in the making), I decided to do my own plugin for post-by-post (and global) control of the wpautop filter. It’s called wpautop-control:

<?php
/*
Plugin Name: wpautop-control
Plugin URI: http://blog.bigsmoke.us/tag/wpautop-control/
Description: This plugin allows you fine control of when and when not to enable the wpautop filter on posts.
Author: Rowan Rodrik van der Molen
Author URI: http://blog.bigsmoke.us/
Version: 1.0
*/
 
if ( is_admin() ) {
  add_action('admin_menu', 'wpautop_control_menu');
  add_action('admin_init', 'wpautop_control_settings');
 
  function wpautop_control_menu() {
    add_submenu_page('options-general.php', 'wpautop-control', 'wpautop control', 'manage_options', 'wpautop-control-menu', 'wpautop_control_options');
  }
 
  function wpautop_control_options() {
    if (!current_user_can('manage_options'))  {
      wp_die( __('You do not have sufficient permissions to access this page.') );
    }
 
  ?>
  <div class="wrap">
    <h2>wpautop control options</h2>
 
    <form method="post" action="options.php">
      <?php settings_fields('wpautop-control') ?>
      <table class="form-table">
        <tr valign="top">
          <th scope="row">wpautop filter on by default?</th>
          <td>
            <label><input type="radio" name="wpautop_on_by_default" value="1" <?php if ( get_option('wpautop_on_by_default') == '1' ) echo 'checked="1"' ?>> yes</label>
            <label><input type="radio" name="wpautop_on_by_default" value="0" <?php if ( get_option('wpautop_on_by_default') == '0' ) echo 'checked="1"' ?>> no</label>
          </td>
      </table>
 
      <p class="submit">
      <input type="submit" class="button-primary" value="Save Changes" />
      </p>
    </form>
  </div>
  <?php
  }
 
  function wpautop_control_settings() {
    register_setting('wpautop-control', 'wpautop_on_by_default', 'intval');
  }
}
else { // ! is_admin()
  add_filter('the_content', 'wpautop_control_filter', 9);
 
  function wpautop_control_filter($content) {
    global $post;
 
    // Get the keys and values of the custom fields:
    $post_wpautop_value = get_post_meta($post->ID, 'wpautop', true);
 
    $default_wpautop_value = get_option('wpautop_on_by_default');
 
    $remove_filter = false;
    if ( empty($post_wpautop_value) )
      $remove_filter = ! $default_wpautop_value;
    elseif ($post_wpautop_value == 'true')
      $remove_filter = false;
    elseif ($post_wpautop_value == 'false')
      $remove_filter = true;
 
    if ( $remove_filter ) {
      remove_filter('the_content', 'wpautop');
      remove_filter('the_excerpt', 'wpautop');
    }
 
    return $content;
  }
}
 
?>

(I’ve requested the plugin to be added to the WordPress plugin repository, so that it won’t have to be reinvented another 20 times in the next year or so.) 😉

After installing the plugin, you can choose whether to enable or disable wpautop by default. Then, for every post where you want to deviate from the default, you can set the wpautop custom field to ‘true’ or ‘false’.

I want the new default to be to enable the filter, but since all my old posts have been manually formatted, I want all these to have the wpautop field added and set to ‘false’.

Adding the appropriate custom field values to all existing posts is easy thanks to MySQL’s INSERT … SELECT syntax:

INSERT INTO wp_postmeta (post_id, meta_key, meta_value)
     SELECT wp_posts.ID, 'wpautop', 'false'
       FROM wp_posts
      WHERE post_type = 'post';
« Older posts

© 2024 BigSmoke

Theme by Anders NorenUp ↑