Archive for the ‘Time Savers’ category

SQL Import from a file using PHP

March 4th, 2009

On seeing the title of this post your first uncontrollable outburst may be ‘Why on earth would I want to do that?‘. On further reading, you may decide that PHP is the way to get tables created from within an automated install process (WordPress plugin activation or PHP based software ‘installation’). It may trigger another outburst when you see that the code I am about to paste in is more than a single line long (which would be all it would take using the PHP exec() command).

Why not use the Exec command?

Alot of developers cringe at the thought of the exec command in PHP, others have disabled it due to ‘security issues’. My reason for not using it is because my script doesnt just import SQL. It can do two very important things for me:

  • Prioritise the import
  • Prefix the table names

Prioritising the import isn’t essential but it means that your SQL file can be a mess of random statements and no matter where the INSERTs are, they will be grouped and run last to allow the CREATE statements a chance to work.

Prefixing the table names is almost self explanatory. Wordress, which I wrote this script for, allows Database prefixes to be used when setting up a blog. It only makes sense that to avoid conflict when more than one blog is in the same database to prefix my tables with the same string.

How does it all work?

For those interested the code above simply does the following:

  • Imports the file from an absolute path passed to the function into an array split by line
  • Loops through the lines looking for starting words defined as SQL statement keywords in an array and generates a list of complete statements
  • Removes all comments as it goes (comment defined as any line starting with ‘–’
  • Looks for the first backtick character (`) which MUST be present (at least around the table name) and inserts the WordPress Database Prefix
  • Inserts the completed query into an array grouped by those that are INSERT queries and those that aren’t
  • Sorts the new array by a priority figure (new numbers can be added to mark muti-level priority if you like)
  • Runs the queries

Integration

To integrate it into your WordPress plugin then simply copy/paste the code into yours and pass it an absolute path on plugin activation. I also use it to drop tables on a ‘hard’ deactivation by passing it an SQL file full of DROP commands. To integrate it into your NON WordPress site then simply remove all references to $wpdb and substitute ‘$wpdb->prefix’ with your own string or variable name.

The Code

Here is the code although I have also provided it in download form: MySQL Import Script (1.14 kB)

function mysql_import($filename) {
	global $wpdb;

	$return = false;
	$sql_start = array('INSERT', 'UPDATE', 'DELETE', 'DROP', 'GRANT', 'REVOKE', 'CREATE', 'ALTER');
	$sql_run_last = array('INSERT');

	if (file_exists($filename)) {
		$lines = file($filename);
		$queries = array();
		$query = '';

		if (is_array($lines)) {
			foreach ($lines as $line) {
				$line = trim($line);

				if(!preg_match("'^--'", $line)) {
					if (!trim($line)) {
						if ($query != '') {
							$first_word = trim(strtoupper(substr($query, 0, strpos($query, ' '))));
							if (in_array($first_word, $sql_start)) {
								$pos = strpos($query, '`')+1;
								$query = substr($query, 0, $pos) . $wpdb->prefix . substr($query, $pos);
							}

							$priority = 1;
							if (in_array($first_word, $sql_run_last)) {
								$priority = 10;
							} 

							$queries[$priority][] = $query;
							$query = '';
						}
					} else {
						$query .= $line;
					}
				}
			}

			ksort($queries);

			foreach ($queries as $priority=>$to_run) {
				foreach ($to_run as $i=>$sql) {
					$wpdb->query($sql);
				}
			}
		}
	}
}

XLS Download from PHP Class!

January 21st, 2009

Following on from my last post on creating a proper XLS spreadsheet from PHP I have just written a small class which will do all the hard work for you if necessary.

It will handle rows and columns automatically aswell as being able to be passed an array and then generating a spreadsheet download for you.

Download: XLS from PHP Example Class (783 bytes)

Sample usage is as follows:

	//Require the file
	require_once (SHARED_CLASSES_DIR . 'xls.class.php');

	//Instantiate the class.
	$xls = new xls(); 

	//Just build an example array out of test data
	$array = array(
		array(1,2,3,4,'five')
		, array('five','test' ,4,3, 0)
	);

	//Triggers the download using the passed array
	$xls->download_from_array($array);

Note that when instantiating the class you can pass a string as an argument and it will set the name of the XLS download. No need to add .xls to the end because it will do that for you.

Download: XLS from PHP Example Class (783 bytes)

Creating a Downloadable Spreadsheet from PHP

January 16th, 2009

I have written several systems that show data on a page but also provide a CSV download file either through a textarea with formatted data inside to copy and paste or via a download link and creates a file on the fly.

I recently decided that this wasn’t the best way to do it seeing as the people will want to be using Microsoft Excel to view the data. It is possible to write a spreadsheet using PHP and using an example from AppServ I started to do it this way.

The original link is included above but here is my simplified version with smaller more understandable function naming:

Download the example script here: XLS from PHP Example (723 bytes)

<?php

function xls_BOF() {
	echo pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
}

function xls_EOF() {
	echo pack("ss", 0x0A, 0x00);
}

function xls_write_cell($row, $col, $value='') {
	if (is_numeric($value)) {
		echo pack("sssss", 0x203, 14, $row, $col, 0x0);
		$value = pack("d", $value);
	} else {
		$l = strlen($value);
		echo pack("ssssss", 0x204, 8 + $l, $row, $col, 0x0, $l);
	}

	echo $value;
}

// Send Headers to set the Filename and force a download of the contents of the script
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");

 // Put the filename in \"'s if you want it to include spaces
header("Content-Disposition: attachment;filename=" . $filename . ".xls");
header("Content-Transfer-Encoding: binary ");

xlsBOF(); //Start the Spreadsheet

xls_write_cell(0, 1, 'Column 1');
xls_write_cell(0, 2, 'Column 2');
xls_write_cell(0, 3, 'Column 3');

$row = 1;
for ($i=0; $i<2; $i++) {
	xls_write_cell($row, 0, 'Row ' . $row . ' Column ' . $i);
	xls_write_cell($row, 1, 'Row ' . $row . ' Column ' . $i);
	xls_write_cell($row, 2, 'Row ' . $row . ' Column ' . $i);

	$row++;
}

xlsEOF(); //End the Spreadsheet

exit(); //Exit the script after download

?>

Windows XP Update Popup

January 5th, 2009

The windows update popup has lost me hours of work for the last time!

Please Restart... Please Restart... Please...

Please Restart... Please Restart... Please...

Ok.. so that may be a little over the top, maybe minutes of work but it’s still irritating losing all of the windows I have spend days opening and lovingly arranging. After the umpteenth popup of the day I thought I would Google the answer to turn off this unwanted menace.

I found a site that told me exactly the answer I was hoping for and I was popup free in under 5 minutes. The depressing thing is that it was written in 2006 and it took me nearly three years to build up the inclination to do something about it.

So here’s how to do it:

  • Click on the Start button and choose ‘Run.’
  • Type: gpedit.msc.
  • Expand Local Computer Policy, Computer Configuration, Administrative Templates, Windows Components, Windows Update.
  • Select “Re-prompt for restart with scheduled installations.”
  • Choose “Enable” and then type in how many minutes you want to wait.

I do feel it necessary to put a little disclaimer in here, gpedit is not something that you should really go playing with and I imagine you need to be an administrator on the machine (most home computers are set up so you are the admin) to make the change

I got this handy hint from Tech Target however you are bombarded with advertising as you enter the site. you have been warned.

bbPress Email notification on post

September 9th, 2008

At Newmedias, we use bbPress and have been using the email notification plugin written by thomasklaiber. It sends an email to those registered for forum notifications every time a post is left on a thread that they had registered for.

http://bbpress.org/plugins/topic/post-notification/

I often look at my emails when im away from home on my pda/phone and find it a real pain to have to open the web link in each email to read it. This also means that I can’t download them in my email client for reading later.

My solution to this was blindingly simple,

Put the body of the most recent post into the email itself!

This feature was not available at the time of writing and works very well. The mod is very simple, here’s how i did it.

note: Before doing this to your version of the plugin, make sure that the original author hasn’t added his own version of the same thing!

1) Open notification.php and find the notification_new_post function
2) Paste the following code after the get_topic() call but before the $message=… call

$posts = get_thread($topic_id, 1, 1);
$posts = array_reverse($posts);
$last = array_pop($posts);
$last_text = strip_tags($last->post_text);

3) Overwrite the $message variable to include the new string at the end as follows:

$message = __("There is a new post on: %1\$s \nReply by: %2\$s \n\n%3\$s \n\n%4\$s");

4) Overwrite the sprintf call to the following:

sprintf($message, $topic->topic_title, get_user_name($bb_current_user->ID), get_topic_link($topic_id), $last_text)

(if you are more familiar with php and sprintf then just add the $last_text variable to the end of the list of variables within the existing call)

5) Save, Backup, Upload and test! It should now send the post body with the email

Optionally you can improve the code within this function somewhat…

1) The get_topic call doesn’t need to be in the foreach loop because the topic_id doesn’t change anywhere in the function. Although bbPress uses cacheing, it would still be best practise to move that line and the lines from my step 2 to the line before the foreach loop.

2) Convert the email to HTML by adding the content-type header and setting it to text/html. If you do this then the \n’s will also need to be changed to <br /> and you can optionally remove the strip_tags() from the last line in my step 2

Good luck and let me know about any problems you may have.

Google Charts overview

August 18th, 2008

I came across Google Charts the other day and wanted to let people know what it’s all about. I found it incredibly easy to use to make a simple chart but a little more complicated to make something more complex.

The hello world example is given as follows:

http://chart.apis.google.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World

(should be used within an <img src=”" /> tag)

To be clear, Google Charts does not use an API key system like Google Maps which takes a layer of complication away.

Let me break up the key parts of the url used to generate the above example…
The first part http://chart.apis.google.com/chart? should always be the same followed by a combination of the following:

  • cht = Type of chart you want to make (Common types are p3, lc, bhs, bvs)
  • chd = Chart data stream(s), usually in the form of t:item1,item2,item3
  • chs = Chart size (widthxheight)
  • chl = Chart Label separated by a | per dataset

The next logical step is to look at bar charts because you can do all sorts with datasets/axis/labelling and colouring. See the following example (it’s not as complicated as it looks as I will show):

http://chart.apis.google.com/chart?chs=300x
120&cht=bvg&chg=0,10,1,5&chds=0,25&chxt=y&chxl=0:||5|10|15|20|25&chbh=60&chd=t:10,24,
6&chm=t10,000000,0,0,11|t24,000000,0,1,11|
t6,000000,0,2,11&chl=14/08/08|15/08/08
|18/08/08

This one is different in more ways that the obvious fact that it’s not a pie chart any more; it has labels on the axis, background lines, it’s scaled and there are labels per bar. The additional parts of the url are structured in the following manner:

  • cht=bvg (it was p3 before meaning 3D pie chart, this one is a vertical bar instead)
  • chg = Chart grid accepts 4 arguments: x step, y step, line length, blank length
  • chds = Data scale, arguments are minimum and maximum (this example 0-25)
  • chxt = Defines which axis have labels on (x, y, r)
  • chxl = Defines the labels for above in the form id:label1|label,id:label1|label2
  • chbh = Bar height (or width in this case as we are using a vertical chart)
  • chm  = Labels for each bar, arguments are id, colour, dataset id, dataset index

This has been a very simple guide to understanding how to use Google Charts. There are Infinitely more resources available at: http://code.google.com/apis/chart/

Zen Cart Welcome Email Editor

July 31st, 2008

I’ve just dug up a script that I wrote a while back for someone. It’s not the most advanced thing in the world and it does what it says on the tin.

Within Zen Cart there is a menu on the admin pages called ‘Tools’ which has an option called ‘Email Welcome’. This script is a default Zen Cart page to simply show you what the welcome email looks like.

Screenshot 1

hint: be sure to turn on html emails and it will show you both the html and text versions (default text only is set)

I have modified this script to allow the editing of these pages if you have little or no knowledge of writing PHP although some HTML skill is required.

Zen Cart puts together a number of PHP Defines to build the welcome email and normally when you want to modify it then you have to trawl through three of four files of these defines to get to the one you want.

This script basically does that for you and parses/updates the files necessary with your new information. The following image shows the new page and i’m sure no explanation is needed to show you how to use it.

Screenshot Thumbnail 2

Known Bugs: the only thing I know to be wrong with it is that some defnes reference other defines and this script doesn’t respect that. There are only one or two defines like this so nothing to worry about unless you intend to change the name of the shop owner frequently. If you do change it, however, then just make sure you use this system to update the welcome email at the same time. Nice and easy!

Here’s the download link: Welcome Email Editor for ZenCart (5.29 kB)
UPDATE: Please make sure to chmod your languages/[language]/email_extras.php, languages/[language]/create_account.php and /languages/[language].php files (in both catalogue and admin) to be writable by apache if not this may not work.

Spoofing a Post Request

July 7th, 2008

Ever needed to test what a form does on your site without having to go through and fill the thing in over and over? Alternatively have you ever needed to emulate a post request to a callback script or similar, something which is usually done by a secure server? Well I have!

If this happens then you can emulate the request to yours (or someone elses) server from anywhere using the following code.

<?php

$params = array('http'=>array('method'=>'POST','content'=>$string));
$context = stream_context_create($params);

$fp = @fopen($url, 'rb', false, $context);

if (!$fp) {
	echo 'Failed to open file pointer.';
} else {
	$response = @stream_get_contents($fp);
	if ($response === false) {
		echo 'POST Failed!';
	} else {
		echo $response;
	}
}

?>

Usage

Basically just pass the code above a URL in the variable $url and a formatted string in the format:

key1=var1&key2=var2&…

You should really stick it in a function and wrap in an HTML form but I’m not going to do it all for you! If all goes well then you should see the response from the post request, otherwise the appropriate error message will be shown.

Security Issues

Ever considered where else you could use this script? Ever though about how some people could use this script against your site? It could potentially be used for a DOS attack against anywhere but this is NOT what I recommend it be used for,  It’s just a handy tool for sending POST requests but if you are worried by this then there are a number of things you can do to prevent it.

The best I can think of is sending a DB stored random number with each POST. When your script receives it it should check the DB and delete that record if it exists then run the form, otherwise if it doesn’t exist then display the appropriate error message.