How to Change Default WordPress Image Sizes in Your Theme

When you upload an image to a WordPress media library, WordPress will create and store a variety of different sized copies of it, by default these are called thumbnail, medium, large and full size. When inserting an image into a post you can select which size you want to insert:

You can alter these default sizes from the admin panel under Settings; Media like this. However, if you’re developing a theme you might want to do this from within your theme’s code in order to ‘enforce’ specific sizes on your users without requiring them to edit admin settings. For example, suppose you’re wanting to maintain a vertical rhythm in your pages by using a fixed line-height in your CSS (e.g. 18px). In that case you’re likely to want your images to conform to that vertical rhythm as well by setting their height to be a multiple of 18px. You can do this by adding the following code to your functions.php:

update_option('thumbnail_size_w', 144);
update_option('thumbnail_size_h', 144);
update_option('medium_size_w', 288);
update_option('medium_size_h', 216);
update_option('large_size_w', 480);
update_option('large_size_h', 360);

In future, that will result in the following settings when you insert an image:

Note that this will not affect previously uploaded images; they’ll still retain the dimensions they were uploaded with. There are various plugins available to convert them to your new sizes though.

Posted in Dev Tips | Leave a comment

What Webkit Prefixes Mean for Clients

Remember when web sites used to show phrases like “Best viewed in Netscape 3.0″? Web browsers used to be riddled with inconsistencies, bugs and proprietary features, thanks in large part to the so-called browser wars. Today we’ve largely solved these problems and as long as you’re using a reasonably up to date browser you, and more importantly your customers, should have pretty much the same experience of any web site in whatever browser you prefer.

There is one fly in the ointment though. It takes the W3C (essentially the internet’s powers that be) quite a long time to ratify new features. Consequently browser manufacturers, the likes of Mozilla, Google and Microsoft, have been allowed to use a feature called experimental vendor specific prefixes. Essentially they’re a way for browsers to temporarily provide features (things like drop shadows and rounded corners) before they’re completely defined by the W3C. The key word here is ‘temporarily’; they’re intended as a stop gap until the real features are fully supported.

Unfortunately, some web developers have been designing web sites on the assumption that these prefixes will be available for all eternity and that’s led to a potential problem. Some of these prefixes have become so ubiquitous that some browser manufacturers are considering implementing prefixes from other vendors in their own browsers; thus breaking both the ‘vendor specific’ and ‘experimental’ aspects.

Whilst this is nothing like as severe as the old browser wars scenario it does have significant implications for the future of stable, simple, cross browser support and may well lead us back into a world where developers have to spend their valuable time, and your valuable cash, hacking together awkward and complex code just to get things to work right.

So, what are the real-world implications for you when you’re looking for someone to produce and maintain your web presence? In short, there are two things you need to consider:

  • Make sure your developer is committed to producing high quality, standards compliant code. Unless you’re an expert yourself, this can be difficult to ascertain but simply asking the question is a great first step and it’s certainly something that should come up in your initial negotiations if not as an explicit statement on their web site.
  • This is just one more reason why it’s important to consider your web site as an ongoing project rather than a fire and forget commission. Make sure you build a solid, long-term relationship with your developer and be prepared to invest at least some minor future effort on web site maintenance and upgrades.
Posted in Dev Tips, For Clients | Leave a comment

Chrome Dev Tools Autosave

Modern browsers now include a set of development tools allowing you to inspect various aspects of your HTML, CSS and scripting from within the browser itself. Nikita Vasilyev has now produced an extension for Chrome which allows changes to CSS ans JS, made in the Chrome dev tools environment, to be automatically saved back into the source files. Excellent.

Installation is straightforward, if a little long-winded. Just follow the instructions. Addy Osmani’s produced a great walkthrough video and accompanying article. There are a few gotchas that might catch out the unwary or the uninitiated though.

  1. Don’t forget to click the ‘Install the Server’ link at the bottomof the ‘How To Install’ section.
  2. If you get errors about npm not being found during the server install (on Windows) then reboot your machine and try again.
  3. Once the server’s installed you need to run ‘autosave’ at a command prompt and this needs to be running whenever you want to autosave from the dev tools. You might want to start this automatically at boot up.
  4. If you’ve got a message in the command prompt after running ‘autosave’ saying something like Dev Tools Autosave 0.3.1 is listening on http://127.0.0.1:9104 then you should be all set.
  5. Note that the extension won’t save changes made to HTML files. So if you’ve got any inline CSS, changes made to it won’t be saved. Your CSS needs to be in an external .css file.
  6. If it seems to be setup OK but it’s still not saving, make sure you’re running the latest version of the extension. Go to chrome://extensions in your browser and check DevTools autosave is running at least version 1.1.1
  7. If you’re using SASS/SCSS/LESS for your CSS then obviously any changes you make to the CSS aren’t going to get ported back into the .sass/.scss/.less files.
  8. Finally, if you’re making quick experimental changes in the browser then keep in the back of your mind that you’re working on your CSS files and you’re busy overwriting their contents. Those quick ‘look-see’ changes you’re making are now persistent so it’s easy to lose stuff if you get too enthusiastic.
Posted in Dev Tips | Leave a comment

Quotation Marks – How to Do Them Properly

In web design, the little things make the difference. Computers have historically used ‘ and ” (the so-called ambidextrous quotation marks) at both the beginning and end of a quotation like so,

“A quotation using ‘ambidextrous’ quotation marks.”

This was because of limitations in the space on typewriter keyboards and the limit of 128 characters available to ASCII. These days we’re a little more sophisticated and we can take advantage of Unicode to give us proper curly quotes, just like the ones typesetters used to use back in the day,

“A quotation using ‘book quote’ quotation marks.”

Of course, this is a tiny detail and most people won’t be conscious of it. That’s why most web designers don’t worry about things like this. Nobody ever complains about the look of quotation marks. Even if somebody did, would anyone really take such a complaint seriously? There are phrases for people who complain about this kind of thing.

However, even though these little things are too small to tickle the conscious mind, they are big enough to irritate that part of the subconscious that decides where people are going to spend their money. They contribute to the feel of a site and that’s why smart people pay other people to create web sites. We’re the people who are obsessive enough to make sure your quotation marks set you apart from the ordinary web sites out there.

Posted in For Clients, Typography | Leave a comment

Drupal Multi-site Installations – The Magic Secret Bits

The objective of this article is to provide the missing background information that most Drupal multi-site tutorials miss out. It’s these nuggets of wisdom that make the difference between a multi-site installation that works and one that’s a right royal PITA to set up and get going. The article supplies the tricks and tips needed whether you’re:

  • On Windows or Linux
  • Using Drupal 6.x or Drupal 7.x
  • Wanting development and production setups
  • Using a shared database or individual ones

Before we discuss the advanced tweaks you might want to do, it’s worth taking a minute to understand how a basic Drupal multi-site installation works. Most of the confusion I’ve seen seems to stem from not really grokking what’s going on during the install. So, we’ll do a quick walkthrough of the major conceptual points of a simple two-site setup.

Supporting Multiple Sites

When you unpack the Drupal code you end up with a two major conceptual components; the Drupal codebase itself and a subfolder (and its children) called sites which is used to store the settings for your individual Drupal sites.

Although all your sites will use the same codebase, Drupal decides which of your sites to show based on the HTTP request that you give it through your browser. So, if you enter http://site1.com in your browser, Drupal will look for a folder called site1.com in its sites sub-folder and display the content as dictated by the contents of that folder. Likewise, if you have a folder within sites called site2.com and you enter http://site2.com in your browser, then Drupal will show the content for site2.com. In summary, create a folder for each site within the sites sub-folder of your Drupal installation. This is the basic mechanism by which multi sites are supported in Drupal but it can be tweaked in a number of ways.

In addition to this, you need to set things up so that requests from your browser for http://site1.com and http://site2.com both get routed to the IP address of the machine hosting your Drupal code. You also need to make sure your web server is routing those requests to the right folder. The exact details of how to do this vary wildly depending on your situation but it’s trivially easy to find out how to do this so I won’t repeat it here. Google is your friend.

Finally, you need to create the sites themselves. To do this you need to copy default.settings.php from the sites\default folder into each of your site folders (sites\site1.com and sites\site2.com in our example), rename it to settings.php and make sure both it and the site specific folder are writeable. The last step is to point your browser to http://site1.com to start the site installation. This process will make changes to your site specific settings.php including storing info about which database Drupal should use for storing the bulk of your settings and content. Repeat this for each of your sites. Oh, don’t forget to set the privs on settings.php back to read only.

That’s it. You’re all done. Note that we’re not setting up any themes or custom modules or views etc. This is just a basic bare-bones Drupal installation.

Overall, what’s happened here is that a single codebase is used by Drupal to translate incoming HTTP requests into pointers to the relevant site-specific subfolder of the main sites folder. The installer builds your site by writing the site-specific setup info into the settings.php file in those folders. These settings.php files, in turn, point Drupal to the relevant database when it’s building content for display.

Development and Production Setups

The above scenario assumes you’re installing straight onto a production server. In practice this is a bad idea and you’ll normally want to build your sites on a development server, usually localhost before you deploy to production and go live. How does Drupal support this situation?

When Drupal is looking for the relevant sites sub-folder, it doesn’t simply look for an exact match in the URL. If you take a look at the comments near the top of settings.php you’ll see the search order that Drupal uses to do this. Making use of this search order usually allows you to build a site in development and then send it to production with a minimal amount of changes.

In Drupal 6 this is the only option you’ve got but in Drupal 7 a new file has been introduced to the top level of the sites folder called example.sites.php. Copy this file to sites.php in the same folder and edit it. Down at the bottom are a couple of example site mappings. Edit these to suit your needs. So, in our example, with sites/site1.com and sites/site2.com sub-folders we would use the following:

<p>$sites['site1'] = 'site1.com';</p>
<p>$sites['site1'] = 'site2.com';</p>

Then, if you’re working on your development server you enter http://site1 in the browser (without the .com suffix) and Drupal will use the sites.php file to map this into a request for the folder sites/site1.com. On your production site, accessed through http://site1.com in the browser (with the .com suffix) Drupal will not use these mappings and will just go straight to the sites/site1.com folder automatically.

Sharing Databases

Some hosting services limit the number of databases you can create. Drupal allows you to share a single database between multiple sites.

Before you run the Drupal installer you need to create your database(s) yourself using something like cPanel or phpMyAdmin. If you want to dedicate a database to each Drupal site then just create databases called site1 and site2. If you want to share a single database between all your Drupal sites then create a database called drupal. Finally if you want to share a single database between all your Drupal sites as well as other stuff then just create a database called shared.

If you’re using either the drupal or the shared options then you’ll need to tell Drupal you’re using a shared database. You do this by specifying a table prefix on the Advanced Settings section of the database configuration page which you’ll encounter as part of the installation script. In our example we might use the prefixes site1_ and site2_.

What About sites/all and sites/default?

In addition to the site specific sub folders we created under the Drupal sites sub folder, you’ll probably also notice Drupal has its own sub folders here called sites/default and sites/all. The first of these is used by Drupal to store your site if it can’t fins a site specific folder like the ones we created. The second is used to store modules and themes that will be available to all your Drupal sites.

Further Reading

Posted in Dev Tips | Leave a comment

Automatic cPanel Backups

Many hosting services allow their customers to administer their web sites using a product called cPanel. One of the features of cPanel is the ability to backup your hosting data, including your databases, email setup and code. Of course, most hosting providers also perform backups for you so you might wonder why you should bother about doing your own as well. But what if the hosting company folds or what if you want to move your site to another hosting provider?

The cPanel backup facility lets you do this manually but it’s also possible to spoof the web form it uses and drive the cPanel engine using a PHP script. That allows you to automate the backup of multiple web sites to an FTP server somewhere and have it run automatically as part of a cron job on a regular basis. Windows devs can get the benefits of cron using Windows Task Scheduler or the excellent pycron by Gerhard Kalab.

The Code

Here’s the script I use to do this. It’s based on work initially done by Justin Cook back in 2006 but cPanel has changed a bit since then and I’ve had to tweak it a little to accommodate these changes. I’ve also dropped in a simple loop through an array to backup multiple sites.

<?php

// Automatic cPanel FTP backup
// This script contains passwords. Do not put it in a public folder.

// ********* THE FOLLOWING ITEMS NEED TO BE CONFIGURED *********

// First site details
$sites['0']['domaintobackup'] = "mycompany.com";
$sites['0']['cpaneluser']     = "user1";
$sites['0']['cpanelpass']     = "pass1";
// This is found as part of your cPanel URL
// e.g. https://mycompany.com:2083/frontend/x3Bronze/index.html
$sites['0']['cpanelskin']     = "x3Bronze";

//Second site details
$sites['1']['domaintobackup'] = "example.com";
$sites['1']['cpaneluser']     = "user2";
$sites['1']['cpanelpass']     = "pass2";
$sites['1']['cpanelskin']     = "x3Bronze";

// FTP host details
$ftpmode = "ftp";               // "ftp" for active,
                                // "passiveftp" for passive,
                                // "scp" for scp - most secure
$ftpuser = "ftpuser";
$ftppass = "ftppassword";
$ftphost = "my.ftp.server.com"; // Full hostname or IP address for FTP host
$ftpport = "21";
$ftpfold = "/sitebackups";      // Destination folder for backup files

$notifyemail = "backupwarnings@mycompany.com";
$secure = 0; // Set to 1 for SSL (requires SSL support)
$debug = 0;  // Set to 1 to have web page result appear in your cron log

// *********** NO CONFIGURATION ITEMS BELOW THIS LINE *********

foreach ($sites as $site)
{
  if ($secure)
  {
     $url = "ssl://".$site['domaintobackup'];
     $port = 2083;
  }
  else
  {
     $url = $site['domaintobackup'];
     $port = 2082;
  }

  $socket = fsockopen($url,$port);
  if (!$socket)
  {
    echo "Failed to open socket connection… Bailing out!\n";
    exit;
  }

  $authstr = $site['cpaneluser'] . ":" . $site['cpanelpass'];
  $pass = base64_encode($authstr);

  $params = "dest=$ftpmode&email_radio=1&email=$notifyemail".
            "&server=$ftphost&user=$ftpuser&pass=$ftppass&port=$ftpport".
            "&rdir=$ftpfold&submit=Generate Backup";

  fputs($socket,"POST /frontend/".$site['cpanelskin'].
                "/backup/dofullbackup.html?".$params." HTTP/1.0\r\n");
  fputs($socket,"Host: {$site['domaintobackup']}\r\n");
  fputs($socket,"Authorization: Basic $pass\r\n");
  fputs($socket,"Connection: Close\r\n");
  fputs($socket,"\r\n");

  while (!feof($socket))
  {
    $response = fgets($socket,4096);
    if ($debug)
    {
      echo $response . "\n";
    }
  }

  echo "$site['domaintobackup'] complete.\n";

  fclose($socket);
}

?>

Personally I call this using the PHP CLI in my mobile USB stick XAMPP installation from my crontab and it backs up to the FTP server on my USB stick. Having said that, there are plenty of ways you can use this script and picking the best one really does depend on how you work and what your general development setup is.

Pitfalls and Their Solutions

A few things are worth noting if you’re trying to set this up yourself. There are two top tips for diagnosing problems with this setup:

  • Set $debug=1 in the script so you can see what errors you’re getting if any.
  • Check the incoming connections log on your FTP server to make sure the FTP data is getting through.

More specifically, if you look at the FTP server log and don’t see the connections coming in from the script then make sure your firewall/router is letting the traffic through on the right ports. The ports for FTP are 20 and 21 for the FTP protocol traffic itself and various other ports used for the payload data. Those ports depend on how you have your FTP server setup (see the discussion of passive mode FTP below).

The other potential pitfall with completely missing FTP connections is that you might be running a NAT router and yet not have setup port forwarding for the inbound FTP traffic in order to route it to the IP address of the FTP server itself.

If you’re using passive mode FTP (you probably should be) and you’re seeing connections in the FTP server log but they’re failing after the protocol negotiation with errors like 425 Can't open data connection. then make sure you’ve allowed the incoming data ports through your firewall as well as just the FTP protocol ports of 20 and 21. Setting up the passive mode FTP server settings lets you do this as well as set up the correct external IP address. There’s a great article on how all this works in general at FileZilla.

Posted in Dev Tips | Leave a comment