PHP Scripts

PHP is my web-development language of choice. Please leave a comment if you have any questions about the code.

(back to Programming)

Getting Pretty URLs with phpwiki

The default for the phpwiki wiki software is to have links of the form /index.php/HomePage. This is ugly. To get Wikipedia-style permalinks, append the following to .htaccess and verify that you have the mod_rewrite apache module installed:

RewriteEngine On
RewriteRule ^index\.php/([^\.]*)$ /redir.php?dest=$1
RewriteRule ^([^\.]+)$ /index2.php/$1

Now, move your index.php to index2.php. Create a redir.php file that contains only a redirection:

<?
header( 'Location: /' . $_REQUEST['dest'] );
?>

I am aware that phpwiki does support native link prettifying. However, I couldn’t get it to work and had to solve it in some way.

PHP: Calculate FRES and SMOG of a Text

A few days ago, I set up a site where students can upload their essays for money (Uppsatslotto.se: Tjäna pengar på dina uppsatser), and wanted a nice way for analyzing texts. I found two in particular, FRES (Flesch Reading Ease Score) and SMOG (Simple Measure of Gobledygook). Slightly modified excerpts from the respective Wikipedia articles (licensed under the GNU Free Document License):

The Flesch/Flesch–Kincaid Readability Tests are readability tests designed to indicate how difficult a reading passage is to understand. There are two tests, the Flesch Reading Ease, and the Flesch–Kincaid Grade Level. Although they supposedly use the same measures, just placed into a different scale, the results of the two tests do not always correlate (a text with a better score on the Reading Ease test over another text may end up with a worse score on the Grade Level test). Both sytems were devised by Rudolf Flesch. In the Flesch Reading Ease test, higher scores indicate material that is easier to read; lower numbers mark harder-to-read passages. The formula for the Flesch Reading Ease Score (FRES) test is 206.835 - 1.015 * W/Se - 84.6 * Sy/W where W/Se is the average number of words per sentence and Sy/W is the average number of syllables per word.

SMOG (Simple Measure Of Gobbledygook) is a readability formula that estimates the years of education needed to understand a piece of writing. SMOG is widely used, particularly for checking health messages. The precise SMOG formula yields an outstandingly high 0.985 correlation with the grades of readers who had 100% comprehension of test materials. SMOG was published by G. Harry McLaughlin in 1969 as a more accurate and more easily calculated substitute for the Gunning-Fog Index. The SMOG of a text can be calculated by: 1.0430 * sqrt( 30 * Psy/Se ) + 3.1291.

The following code is a PHP implementation for calculating the required values (number of words, number of sentences, number of syllables, and number of polysyllabic words) and putting it all together using the above mentioned formulae.

1
2
3
4
5
6
7
8
9
10
11
12
// Number of words: number of space series or linebreaks + 1
$wc = preg_match_all( '/[ \r]/', preg_replace( '/ +/', ' ', $text ), $tmp );
// Number of syllables: vowels not followed by another vowel. Quite accurate approximation.
$syc = preg_match_all( '/[aeiouy][^aeiouy]/', $text, $tmp );
// Number of polysyllabic words (>=3 syllables): Vowel, non-spaces, vowel, non-spaces, vowel (or more non-spaces-vowel)
$psyc = preg_match_all( '/[aeiouy]([^ ]*[aeiouy]){2,}/', $text, $tmp );
// Number of sentences: Number of periods, exclamation marks, question marks and linebreaks
$sec = preg_match_all( '/[.!?\r]/', $essayf, $tmp );
// Flesch Reading Ease Score
$fres = 206.835 - 1.015 * ( $wc / $sec ) - 84.6 * ( $syc / $wc );
// Simple Measure of Gobbledygook
$smog = 1.043 * sqrt( $psyc * ( 30 / $sec ) ) + 3.1291;

Generate Slugs from Strings with PHP

In these days of Web 2.0, no site can survive for long without pretty, mod_rewrite-modified permanent links. Everyone uses it. If you look at the URL for this post, for example, it is timjoh.com/generate-slugs-from-strings-with-php. As you might have guessed, I never typed that hyphenated string–WordPress did it all for me. If your PHP script is fed a string that you want a similar slug from, you can use this handy one-liner, with $string being the string that you want to slug.

1
$slug = str_replace( ' ', '-', preg_replace( '/[^a-z0-9- ]/', '', strtolower( $string ) ) );

Or you could use the neater version:

1
2
3
$slug = strtolower( $string ); // lower-case the string
$slug = preg_replace( '/[^a-z0-9- ]/', '', $slug ); // remove all non-alphanumeric characters except for spaces and hyphens
$slug = str_replace( ' ', '-', $slug ); // substitute the spaces with hyphens

This turns the string I'm an U_G_L_Y string! into the slug im-an-ugly-string. Note that it is often useful to shorten the slug; no-one wants a metre-wide URL. It is also important to check so that the slug doesn’t already exist. We can add to the code a loop that appends an ID number to the slug in case it already exists, making it unique.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$slug = strtolower( $string ); // lower-case the string
$slug = preg_replace( '/[^a-z0-9- ]/', '', $slug ); // remove all non-alphanumeric characters except for spaces and hyphens
$slug = str_replace( ' ', '-', $slug ); // substitute the spaces with hyphens
$i = ''; // start with no appended value
while ( slugExists( $slug . $i ) ) { // if the slug already exists..
    $i++; // increment the appended value
    # it is bad practice to increment a string
    # but in this case, it simplifies the code
}
$slug .= $i; // append the value to the real slug
 
function slugExists( $slug ) {
    # this is just an example function;
    # the real function depends on the layout of your script
    $query = sprintf( 'SELECT post_id FROM posts WHERE post_slug = \'%s\'', // write the MySQL query
        mysql_real_escape_string( $slug ) // escape the string correctly (make sure that magic_quotes_gpc is turned off)
    );
    $result = mysql_query( $query ); // assuming that we are connected to MySQL
    if ( mysql_num_rows( $result ) ) { // if a post with this slug was found..
        return TRUE; // ..this slug exists
    } else { // if not..
        return FALSE; // ..this slug does not exist
    }
}

Now you can slug whatever you want, without fearing collisions. This means that you can even use the slug column as an ID instead of post_id in this example.

List of bbPress Template Functions

In order to ease template writing for bbPress, i compiled a list of all the template functions in the current version (bbPress 0.8.1). It was done swiftly with grep -oe ^function.*\) bb-includes/template-functions.php | sort > functions.txt.

(more…)

Put bbPress in Maintenance Mode

If you want to test a new plugin or theme in bbPress, you might want to disable the site for regular users. Add the following code to the end of bb-settings.php:

1
2
3
if ( ! bb_current_user_can( 'administrate' ) ) {
  die( '<p>The site is down for maintenance.</p>' );
}

This modification will only show pages for users who have the “administrate” capability. Make sure that you log in before you upload the new bb-settings.php.

Bug in Matt Mullenweg’s “Hello Dolly”

I was looking through the source code of Matt Mullenweg’s WordPress plugin, Hello Dolly, which is shipped with the latest WordPress releases. It contains a minor bug on line 44:

$chosen = wptexturize( $lyrics[ mt_rand(0, count($lyrics) ) ] );

The range in the mt_rand() is too large. Suppose there is only one line, then mt_rand()’s range will be 0 to 1 — that’s one too much, since only element 0 exists. When this bug occurs, no text will be displayed. The risk for it to occur in the standard Hello Dolly plugin is 1 in 29, which is the number of lines plus one (the 0).

The bug could be fixed easily by changing count($lyrics) to count($lyrics) - 1.

Reverse Blog Name and Post Title in WordPress Title

I thought that it’d look a bit nicer with “Some Post Title — Timblog” as the HTML document’s title instead of “Timblog — Some Post Title”. As a reflex, I went to the WordPress Codex and checked for the functions’ syntax. They had example code for reversing the blog’s name (”Timblog”) and the post’s title (”Some Post Title”):

wp_title(' ');
if(wp_title(' ', false)) { echo '--'; }
bloginfo('name');

However, you should use the trinary operator (A ? B : C) whenever you can, because it’s so cool. I’d prefer this code:

wp_title(' ');
echo ( wp_title( ' ', false ) ? '--' : '' );
bloginfo( 'name' );

PHP: Get a Random Element from Array, Biased

This is a function that fetches a random element from an array. However, it’s not like array_rand(), because you can bias the results so that some elements have a better chance of being picked. This is done by having an associated array with the elements to be fetched as keys and the relative probability as the values.

$items = array(
	'A' => 3,
	'B' => 1,
	'C' => 1,
);
 
function getRandElement( $array ) {
	$tot_prob = array_sum( $array );
	foreach ( $array as $element => $element_prob ) {
		if ( mt_rand( 1, $tot_prob ) <= $element_prob ) {
			return $element;
		} else {
			$tot_prob -= $element_prob;
		}
	}
	return 0;
}
 
echo getRandElement( $items );

This code has a 60% chance of echoing an A, 20% chance for B and 20% for C.us aa loansfinance about banking loans scams businessabout low fee loan paydayaccount savings cash loanday loan saving pay accountpay account savings using day loanday saving account loan paybad credit actual loan company Map

FireStats iconAnvänder FireStats