About Jamie on Software

Jamie on Software is the online journal of web developer and writer Jamie Rumbelow.

Jamie likes books, guitars, programming, open source and food. He writes about these things too. This is where he puts the things he writes.

Tags
Tweets
Feeds
We Love
Powered by Squarespace

Entries in expressionengine (8)

Monday
Apr302012

Open source (pour over pasta)

I've been making a real effort to tidy up my open source portfolio recently; getting issues closed, code tidied up, unit test suites written and on the fantastic Travis and people happier!

As part of this transition, I've decided to retire Sparkplugs and open source the code. Big changes are happening in my professional and personal life over the next few months and I feel it would be disingenuous to pretend that I could carry on supporting and developing my formerly commercial add-ons. After all, there haven’t been any updates to my add-ons for a while now, and support has been flakey. The honest truth is I lost my passion.

But onto bigger and better things!

Exciting things are going on over at my GitHub page (https://github.com/jamierumbelow). You’ll find my two most popular CodeIgniter libraries, MY_Model and MY_Controller. You'll find a recent experiment with node.js, Postmaster, an SMTP testing server I'm remarkably proud of. 

Also, you'll find the source to Sparkplugs' two commercial add-ons, Taggable and MojoBlog. I’m sure I’ll still be involved and am happy to answer any support questions through the issue trackers on the GitHub repositories.

It's an exciting time to be in open source and I've realised that I enjoy the atmosphere so much more than the pressures of a commercial add-on retailer.

So go on. Check out my GitHub profile :)

Saturday
Nov052011

Getting to know ExpressionEngine 2's config file - Part 3

This is the belated finale in the trilogy of articles I'm writing about how to customise your ExpressionEngine config.php file to allow for a much more dynamic and customisable ExpressionEngine install.

In Part 1, we looked at the basics, why and how to use the config file most effectively and we built a simple example. In Part 2, we extended our config file to allow for multiple servers without changing any values. Today, in Part 3, we'll look at tidying up our config file and we'll take a look at some of the extensive hidden configuration variables.

Let's take a look at our config file so far:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/* Dynamic Configuration
-------------------------------------------------------------------*/
$ext        = ($_SERVER['SERVER_ADDR'] == '127.0.0.1') ? ‘.local’ : ‘.com’;
$base_url   = $base_url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "https" : "http");
$base_url .= "://".$_SERVER['HTTP_HOST'].$ext;
$admin_url  = $base_url . '/admin.php';

/* ExpressionEngine Configuration
-------------------------------------------------------------------*/
$config['app_version'] = "213";
$config['license_number'] = "0000-0000-0000-0000";
$config['debug'] = "1";
$config['install_lock'] = "";
$config['system_folder'] = "system";
$config['is_system_on'] = "y";
$config['allow_extensions'] = "y";
$config['site_url'] = $base_url;
$config['server_path'] = FCPATH;
$config['cp_url'] = $admin_url;
$config['theme_folder_url'] = $config['site_url']."/themes/";
$config['theme_folder_path'] = $config['server_path']."/themes/";
$config['save_tmpl_files'] = "y";
$config['tmpl_file_basepath'] = $config['server_path']."/templates/";
$config['avatar_url'] = $base_url."/uploads/system/avatars/";
$config['avatar_path'] = $config['server_path']."/uploads/system/avatars/";
$config['photo_url'] = $base_url."/uploads/system/member_photos/";
$config['photo_path'] = $config['server_path']."/uploads/system/member_photos/";
$config['sig_img_url'] = $base_url."/uploads/system/signature_attachments/";
$config['sig_img_path'] = $config['server_path']."/uploads/system/signature_attachments/";
$config['prv_msg_upload_path'] = $config['server_path']."/uploads/system/pm_attachments/";

/* CodeIgniter Configuration
-------------------------------------------------------------------*/
$config['base_url'] = $config['site_url'];
$config['uri_protocol'] = 'AUTO';
$config['language'] = 'english';
$config['charset'] = 'UTF-8';
$config['subclass_prefix'] = 'EE_';
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\\-';
$config['enable_query_strings'] = FALSE;
$config['directory_trigger'] = 'D';
$config['controller_trigger'] = 'C';
$config['function_trigger'] = 'M';
$config['log_threshold'] = 0;
$config['log_path'] = '';
$config['log_date_format'] = 'Y-m-d H:i:s';
$config['time_reference'] = 'local';

/* End of file config.php */
/* Location: ./system/expressionengine/config/config.php */

This is already nice and tidy. But it'd be great to consolidate our database information in here too, wouldn't it? That way, we can change all our system configuration in one file. This is how we do it:

/* Universal database connection settings
-------------------------------------------------------------------*/
$active_group = $ext;
$active_record = TRUE;

$db['.local']['hostname'] = 'localhost';
$db['.local']['username'] = 'root';
$db['.local']['password'] = 'root';
$db['.local']['database'] = 'some_database';
$db['.local']['dbprefix'] = "exp_";
$db['.com']['hostname'] = 'localhost';
$db['.com']['username'] = 'user';
$db['.com']['password'] = 'password';
$db['.com']['database'] = 'database';
$db['.com']['dbprefix'] = "exp_";

$db[$active_group]['dbdriver'] = "mysql";
$db[$active_group]['pconnect'] = FALSE;
$db[$active_group]['swap_pre'] = "exp_";
$db[$active_group]['db_debug'] = FALSE;
$db[$active_group]['cache_on'] = FALSE;
$db[$active_group]['autoinit'] = FALSE;
$db[$active_group]['char_set'] = "utf8";
$db[$active_group]['dbcollat'] = "utf8_general_ci";
$db[$active_group]['cachedir'] = $config['server_path'].$config['system_folder']."/expressionengine/cache/db_cache/";

By extracting out the majority of the variables (the ones that probably won't change depending on environment), and then using the $ext variable to switch the $active_group, we can adjust the database connection settings automatically depending on environment. There's one more thing we need to do. Open up your config/database.php file, empty it, and give it a solitary line:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

require 'config.php';

/* End of file database.php */
/* Location: ./system/expressionengine/config/database.php */

Now, all references to the database configuration will be brought through the DB config file from the config.php file.

Alongside the standard configuration - paths, debug settings, URLs etc - we can customise a lot of ExpressionEngine's behaviour through a little-known technique called hidden configuration variables. A quick TextMate project search for 'Hidden Configuration Variable' bears 33 different variables with which to customise behaviour. Let's look at a couple of them:

$config['allow_textarea_tabs'] = 'y';

If you wish to preserve tabs in textareas, or let the user add a tab character, rather than shift focus to the next input, you can set this config item and all textareas in MarkItUp mode will preserve their tabs. Turning it off is as simple as setting it to 'n'.

Is the automatic JavaScript login reminder in the CP annoying you? Turn it off:

$config['login_reminder'] = 'n';

Do you want your formatted text links to automatically open in a new window?

$config['popup_link'] = 'y';

I'm sure you get the idea. There's a comprehensive list of the hidden configuration variables in the user guide.

I hope that this series has taught you one or two things about customising and using your config.php file to best effect. It's a fantastically powerful weapon to have in your arsenal, and it should make creating dynamic websites with ExpressionEngine much simpler.

Friday
Aug122011

Add-on updates

Over the past few days I've released a couple of updates to some of my ExpressionEngine add-ons

Taggable is now at version 1.4.6, which fixes some pretty major bugs and improves the intutitiveness of the tag searching. It's highly recommended you update your Taggable install to this version.

I've also updated one of my free add-ons, SP Table Select, which allows you to create dropdowns filled with arbitrary data from arbitrary database tables. Version 1.2.0 adds support for the excellent Matrix add-on. Check it out!

http://getsparkplugs.com/taggable
http://devot-ee.com/add-ons/sp-table-select

Tuesday
Apr122011

On Add-on Pricing

Yesterday, Stephen Ou posted a really interesting question on Forrst about the pricing of his upcoming add-on, ArtsyEditor for WordPress. Having experience in add-on development and sales before, I thought I’d spend the time to write up a proper reply. The following is essentially my answer, with a few bits changed. View the original answer here.

I’ve got a fair bit of experience with selling add-ons to CMSes, and, as I’m sure you know, pricing them is a very hard decision to make. Pricing can make or break a business model. Be that as it may, it’s important to remember that if you get it wrong first time, it’s not the end of the world. Pricing is one of those things that you can always change, and that’s a right you should be able to reserve as the creator of a product.

Pricing also needs to be fine-tuned. If you’re not selling enough, try lowering the price slightly, and if you’re selling lots, try raising it. You don’t have to stick to a price. If you believe you’ve created a good product, you’re allowed to be paid a decent price for it. If you’re happy with the price, and it’s what you actually believe it’s worth, your customers will be too.

As for what to actually price it at, it’s very dependant on your audience. My add-ons are for ExpressionEngine and MojoMotor; both commercial platforms. ExpressionEngine users are more than happy to pay a decent amount for a good add-on that saves them time. Likewise, MojoMotor users are happy to pay for an add-on if it is vital to them.

I charge less for my MojoMotor add-on, MojoBlog, than my ExpressionEngine add-on, Taggable, simply because of the cost of each system. The former is inexpensive - $50 - so I charge $15 for my add-on. It’s not a real investment and $15 is easy to throw away on an add-on. I’m luck that I’ve been able to write a fantastic tool for MojoMotor that so many people need, so it sells a very fair number of licenses.

My ExpressionEngine add-ons goes for slightly more, $29, because ExpressionEngine costs that much more. EE add-ons can be even more expensive: some range up to the over $100 mark. A standard license for ExpressionEngine is $199, and many users see this as an investment. Therefore, they’re willing to pay slightly more for add-ons so that they get a good quality product and great support when things go wrong.

Since Artsy Editor is for WordPress, a free and open source platform, you’re going to struggle charging a lot for it. While a few have made successful business from WordPress add-on development (WooThemes comes to mind), the WP community just aren’t used to paying for add-ons.

Also, since they see WP as a platform that they are investing themselves - and, importantly, their time - into, you just can’t charge a per-site license fee. It will have to be re-usable. A one-off fee for unlimited uses.

As for the fee itself, I suggest something around the $20 area, potentially $19. You’re allowing for unlimited uses after all, and you deserve to be remunerated for your time, energy and skill. The $20 is above the “Fuck it, I’ll buy it” price point where you’ll have many sales but very little support and passion surrounding your product, but not so high that you can’t attract the hobbyists and small-timers that the WordPress community is so famous for.

Artsy looks like it’s going to be a fantastic product and I can’t wait to try it out. It’s always good to see more people getting into the add-on space.

For those of you who are already in this space, how do you go about pricing your add-ons?

Monday
Apr112011

Getting to know ExpressionEngine 2's config file - Part 2

In this mini-series I'll be discussing how and why you should use the config.php file to customise your ExpressionEngine installation. In Part 1 I covered the basics, explained why using a config file was helpful and showed you a simple example config file.

Today, I'm going to take a look at making your config.php file much more dynamic. Using this file and a clever bit of PHP code, we can make EE deployment much, much easier.

The very basics of developing and deploying a dynamic website involve setting up various environments in your code. CodeIgniter 2 Core, upon which EE is based, doesn't include environments by default, so we'll have to handle this on our own. CodeIgniter Reactor does, so be sure to check that out.

I set up the domain of my development environment (using virtual hosts with a tool like MAMP Pro) to be the domain itself with the .local extension. I can check to see if I'm running on my local server by checking if the $_SERVER['SERVER_ADDR'] matches 127.0.0.1, the localhost loopback IP.

Add this at the top of your config file:

/* Dynamic Configuration
-------------------------------------------------------------------*/
$ext            = ($_SERVER['SERVER_ADDR'] == '127.0.0.1') ? '.local' : '.com';
$admin_url  = 'http://admin.mysite'.$ext;
$base_url   = 'http://mysite'.$ext;

This switches an $ext variable between .local, the localhost or .com, the live server. I'm also setting a temporary admin URL variable here to be a subdomain. This can change; I prefer to move the system directory out of the web root and set it up as a subdomain. Learn more about using a Masked CP at the EE docs.

What if you're working with multiple servers? Using server variables, we can easily figure out the URL of the current server and use it as a catch-all. Unless you need to do real specific configuration for an environment, this can work well.

$base_url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "https" : "http");
$base_url .= "://".$_SERVER['HTTP_HOST'];

Now we have these dynamic variables, we can start to use them to make our config values more dynamic:

$config['site_url']                 = $base_url;
$config['cp_url']               = $admin_url;
$config['theme_folder_url'] = $admin_url . '/themes';

Our site URL, CP URL and theme folder URL are now all being set relative to the current environment's URL. This means that we can move our install from our local environment to our live environment without having to fear; the URLs will automagically update themselves.

There are a few more URLs and paths we need to handle.

$config['avatar_url'] = $base_url."/uploads/system/avatars/";
$config['avatar_path'] = $config['server_path']."/uploads/system/avatars/";
$config['photo_url'] = $base_url."/uploads/system/member_photos/";
$config['photo_path'] = $config['server_path']."/uploads/system/member_photos/";
$config['sig_img_url'] = $base_url."/uploads/system/signature_attachments/";
$config['sig_img_path'] = $config['server_path']."/uploads/system/signature_attachments/";
$config['prv_msg_upload_path'] = $config['server_path']."/uploads/system/pm_attachments/";

This is really all it takes to create a dynamic site in ExpressionEngine. The only thing left to do is make our database connecting dynamic. We can do this by checking our base URL in our database.php file.

$local = (bool)(config_item('base_url') == 'http://mysite.local'); 

$db['expressionengine']['hostname'] = "localhost";
$db['expressionengine']['username'] = ($local) ? "root" : "live_db_user";
$db['expressionengine']['password'] = ($local) ? "root" : "live_db_password";
$db['expressionengine']['database'] = ($local) ? "mysite" : "live_db_name";

That was extremely simple to do, but very, very powerful. Our database connection will update itself correctly as our site flicks between local and live servers.

This is great so far, but our config setup isn't quite perfect. In the next article, we'll look at both tidying up your config.php file, and some other cool things you can do.