Move Your Damn WordPress Debug Log so It’s Not Accessible via HTTP


Every time I need to view a WordPress debug log, I get a little belly-side security loophole cringe. It completely depends on what information you stuff into it that would cause a security issue, but it’s so easy to mitigate this risk entirely—by storing (and writing to) the file outside of your document root. It drives me bat-shit crazy that anyone with a browser can simply navigate to the blatantly accessible file and view its contents.

In writing this post I searched a few high profile WordPress sites and found a few debug logs in the mix. Most of them returned with 404s, but I did find a few. No juicy debug information though, but I only spent like five minutes looking.

Anyways, I digress.

So, for some time now I’ve been implementing on any of my client websites the following solution to move the debug log to a safer, inaccessible location.

In your wp-config.php add the following:

define('WP_DEBUG', true);
if ( WP_DEBUG ) {

	// turn off wordpress debug (otherwise it will override)
	define( 'WP_DEBUG_LOG', false );

	// specify new safe path
	$path = realpath( $_SERVER["DOCUMENT_ROOT"] . '/..' ) . '/wp-logs/debug.log';
	// enable php error log
	@ini_set( 'log_errors', 'On' ); // enable or disable php error logging (use 'On' or 'Off')
	@ini_set( 'error_log', $path );


A few notes:

  • All of this code assumes you have access to your servers root filesystem. Check with your host if you’re unsure.
  • The code in it’s current form assumes that the folder and file already exist.
  • If nothing is being written to the file after these changes, you may need to adjust the permissions of the folder and file once created.

And for a bonus I use the following awesome function to write to said log file. Compliments of Stu Miller.

if (!function_exists('write_log')) {
    function write_log ( $log )  {
        if ( true === WP_DEBUG ) {
			if( is_array( $log ) || is_object( $log ) ) {
				error_log( print_r( $log, true ) );
			} else {
				error_log( $log );
Bookmark and Share
Posted in: Uncategorized  |   |  Leave a comment

Convert A Massive CSV To Many CSVs Using PHP

One CSV Many CSVs
I’m in the process of working in a CSV file with roughly 26000+ rows and 20 some odd columns. Each row represents an historical purchase order, including information such as date, time, name, address, product name, product sku, etc. My end goal is to import all these transactions into an existing e-commerce system. The trouble is, is that my import tool can only process 1500 rows in one go, or I get connection reset errors from the server.

The solution here is to break up the master CSV file into discreet 1500 row chucks and save in separate files. So rather than hack my way through Excel, copying and pasting 1500 row chunks into new workbooks (ug…) I decided to write me a little PHP script to do the job. It took about 30 minutes. Not only is this a faster way to breakup these transactions, it is completely error free. There’s a high likelihood I would have missed or duplicated some rows having had done this manually.

Current code assumes your master file is in the same directory as the script. Adjust as necessary.


@ini_set( 'display_errors', 1 );


echo 'start <br/>';

$file_name_base = 'masterfile';
$master_file = "{$file_name_base}.csv";

$fh = fopen( $master_file, "r" );
if( $fh ) { // valid file?

	$i = 0;
	$records_per_file = 1500;
	$header_row = null;

	// loop through csv rows
	while ( ( $row = fgetcsv( $fh, 0, ',' ) ) !== false ) {
		if( $i == 0 ) { // first row?
			// save column names row
			$header_row = $row;

		if( $i % $records_per_file == 0 ) { // time to create a new file?

			// some vars, duh
			$curr_file_name = "{$file_name_base}_{$i}.csv";
			$curr_fh = fopen( $curr_file_name ,"w" );
			if( isset( $header_row ) && !empty( $header_row ) && $i > 0 ) { // we cool?
				// yes, add header row
				fputcsv( $curr_fh, $header_row );
			echo "{$i} - create new file: {$curr_file_name}. <br />";
		fputcsv( $curr_fh, $row );
	echo $i . '<br/>';


Bookmark and Share
Posted in: Code Samples, Development  |  Tagged with: , ,  |  Leave a comment

Launched: Valhalla DSP

Valhalla / Grand Canyon

Gosh, it has been far too long since I posted anything. And for that I’m only apologizing to myself, which is effectively moot because I’m also, at the same time, forgiving myself. I’m sorry, Jibran. You’re forgiven, Jibran. Phew, dodged that emotional bullet.

I have considered a new years resolution to post more stuff about things and stuff that I like, but that will just stress me out. The best I can do is promise to post more often than every three months. That’s a goal I can get behind. I work in the moment. And if the idea in that moment gets old and I don’t write it down semi-humorously then I lose interest and …

(Oh look another episode of Battlestar Galactica is on.)

And from that introduction, this post, is a big one. It’s a combination of eight months of blood, sweat, stress and code that kept me from posting and alas in the end all is certainly well: we have just launched my clients new website, An incredibly simple, easy to use e-commerce site. Well, easy to use from the front-end. Quantum computer complicated, from the back-end. Well that might be an overstatement, but it’s all relative and I think it’s funny.

Who is Valhalla DSP?

Anyways, Valhalla DSP (where DSP stands for digital signal processing) is a Seattle-based company that writes incredibly popular audio plugins for home and professional recording studios all over the world. (And from Norse mythology, Valhalla is an enormous hall in some place called Asgard where the dead go to hangout with more dead people. And the image above is my interpretation, if you didn’t pick up on that.) So go forth and check out the site if you like.

I’m tired now and losing inter …

Bookmark and Share
Posted in: Portfolio, Technology  |   |  Leave a comment

Run Your Own Damn Code after PayPal Calls WooCommerce Back

PalPal Calls WooCommerce Back
This isn’t rocket science, but the WooCoommerce documentation (as robust and complete as it is) isn’t clear about how to hook into a PayPal IPN successful charge webhook call back thingy—yes, that’s its technical name. In fact “isn’t clear” insinuates some level of recognition from them that something like this can be done. But no, not one word about it. Geez. Anyways, like usual, I digress.

But, if you’re like me, you ASSUME everything can be done. I know this can be done. I just have to dig. Where is my shovel? But I’m also curious. Is this a hush hush thing? Like maybe, if they don’t ask, we won’t have to tell that it’s as easy as writing a function. Thank the dogs for StackOverflow—check out this post.

From information garnered from that post and some elbow grease, here is the function I wrote that allows you to run your own damn code after PayPal calls WooCommerce back, which is apparently super top secret. It’s also posted here.

add_action( 'valid-paypal-standard-ipn-request', 'handle_paypal_ipn_response', 10, 1 );

function handle_paypal_ipn_response( $formdata ) {
    if ( !empty( $formdata['invoice'] ) && !empty( $formdata['custom'] ) ) {
		if( $formdata['payment_status'] == 'Completed' ) {

			// unserialize data
			$order_data = unserialize( str_replace('\"', '"', $formdata['custom'] ) );

			// get order
			$order_id = $order_data[0];
			$order = new WC_Order( $order_id );
			// got something to work with?
			if ( $order ) {
				// get user id
				$user_id = get_post_meta( $order_id, '_customer_user', true );
				// get user data
				$user = get_userdata( $user_id );
				// get order items
				$items = $order->get_items();
				// loop thru each item
				foreach( $items as $order_item_id => $item ) {
					$product = new WC_Product( $item['product_id'] );
					// do extra work...


Bookmark and Share
Posted in: Code Samples, Development  |  Tagged with: , , ,  |  Leave a comment

MySQL: Group By Column And Include Its Count

Wave Crashing, MySQLWithout going into too much detail about the why, consider the below table. It’s a snippet of a table I’m working with for an e-commerce site. Any user (user_id) can have different products (product_id), but any user can also have multiple entries of the same product.

id user_id product_id
1 10 50
2 11 50
3 11 51
4 11 51
5 12 50
6 12 50

When displaying this data to a user, say user 11, I can’t do a simple flat list. This would confuse the user, showing multiple entries of the same product. Like this:

select id, user_id, product_id 
FROM wp_wc_licenses 
WHERE user_id = 11;

And the resulting table:

id user_id product_id
2 11 50
3 11 51
4 11 51

The solution
To give the user a more accurate display of their products, I want to group them by product, but also include a count of that product. Here is a much better way to get the data that makes sense.

SELECT id, user_id, product_id, count(*) AS `product_count`
FROM product
WHERE user_id = 11 group by product_id;

And the resulting table:

id user_id product_id product_count
2 11 50 1
2 11 51 2

I found this technique from this post. It saved me from myself, having to process this in PHP. That. Would. Have. Sucked.

Bookmark and Share
Posted in: Code Samples, Development  |  Tagged with:  |  Leave a comment

WooCommerce: How To “Trash” All Orders Really Fast

WooCommerce Logo
Some context
I am working on a WooCommerce installation where I’m dealing with literally thousands of historical orders. All of which I am programmatically importing (including user accounts!) and doing a bunch of special updates, which are numerous and complicated, but not the subject of this post. But this gives you enough context on which to move forward.

As I develop this import tool, these thousands of orders need to be removed (or “trashed”) after each test I make (finding and fixing bugs) because naturally you can’t have duplicate orders. Am I right or what?

The WooCommerce order admin interface is robust and powerful, but not for bulk trashing. I can only send around a maximum of 350 orders to the trash at any one time. So this process of “resetting” the orders is time consuming and cumbersome.

I searched and thought and searched and thought some more, wondering how to quickly trash every single one of those damned orders after each test. And then I remembered: an order is just a custom content type. Well I didn’t forget, but if you’ve ever developed anything, you’re jugging hundreds of lines of code and switching from language to language and from one task to the next. Not everything you work on is at the forefront of your brain, our human RAM, if you will. I think you’re following me. We basically can’t see the forest through the trees.

But then I did remember.

The solution
The order custom content type (shop_order) that is WooCommerce has all the basic functionality that is WordPress. Any content type has a post_status field associated with it and can have values such as: publish, draft, trash, etc. You can read up on post statues, here.

To quickly send all orders to the trash run the following sql command. Super easy. This would work for any content type you’d just need to update the where clause.

update wp_posts set post_status = 'trash' where post_type = 'shop_order';

Then you can go one step further and view your order trash via WordPress admin and click on ‘Empty Trash’. I wouldn’t recommend using this anywhere near a production machine. Use at your own risk. ;)


Bookmark and Share
Posted in: Code Samples, Development  |  Tagged with: , ,  |  Leave a comment

Harvest Launches Mobile Friendly Invoices

Harvest LogoI love Harvest — the time-tracking bombshell of a service. They do more than track time, though. You can generate client invoices, manage projects, run real-time reports and with their mobile or desktop app you can easily switch between projects and tasks at the touch of button (okay, two). As far as I’m concerned this is the best $12 I spend every month. I can’t function without Harvest.

Time tracking, the nightmare
For years, working as an employee for many different companies, time tracking was always a nightmare. One particular Seattle agency (which I won’t name, because it hasn’t any relevance to the point I’m making) had such an archaic and inefficient system that my boss hounded me regularly to logged my time. It’s not that I didn’t value tracking time, it’s that I HATE inefficiencies, so I just wouldn’t do it. My time tracking or lack thereof got so bad that the company actually offered to buy me my own license to the software and have it installed on my work computer (because back then they had only a few seats). Needless to say the system sucked. Anyways, I digress.

Those days are gone with companies like Harvest. And just a couple of days ago they launched a mobile friendly version of client invoices. This not only enable my clients to quickly and easily make payments on the go, but it shows you have a very professional way of doing business. You can read more about it here.

Bookmark and Share
Posted in: News  |  Tagged with: , ,  |  Leave a comment

Proton Mail Indiegogo Campaign Raises $115K In 3 Days

ProtonMail ScreenshotIf you’ve seen or heard of Proton Mail in the news recently you might just be wondering what exactly they are all about. Well, I’ll tell you. Proton Mail is an NSA-proof end-to-end encrypted email service built by scientists from MIT & CERN. You can read an in-depth review here. Yes this is all quite geeky I realize, but what they are building is essential to maintaining private communications in this day and age. And the best part is they are focusing on simplicity and usability. No encryption knowledge necessary.

So anyways, a few days ago they launched an Indiegogo campaign raising $115K to expand their infrastructure to support the overwhelming response they’ve received. And in the time it took me to write this post they’ve hit $119K.

Of course, not everyone is jumping up and down, throwing money at them. One commenter on Indiegogo pointed out a reasonably significant usability issue when sending Proton emails to non-Proton accounts (grammatical errors aside):

So basically If I want to send an encrypted email to my colleagues, what I’m really sending is a link to a web page where they can access through a password. I’m sorry to say but that is not an email. A much more simple and fastest way is to use a P2P encrypted service like Bitmessage

It’s a valid argument, but at this point I don’t see how they could implement it any other way. They do give you the option of not encrypting a particular email, in which case it passes directly into the users inbox. But then why the hell would we use Proton Mail in the first place? Haha.

Bookmark and Share
Posted in: News, Technology  |  Tagged with: , , , ,  |  Leave a comment

“Can You Throw This up on the Website?”

In my profession, occasionally I’ll get an email from a client requesting if I can ‘throw something up on the[ir] website.’ I’ve had good laughs with co-workers and colleagues in the past about this, because this question is ultimately very loaded and is anything but the simplicity the question implies. This question implies that I could do this task as easily as throwing a basketball through a hoop. (Which doesn’t take very long, by the way.)

Now to be fair, there is nothing wrong with this question. I’m sure in other industries (that I know nothing about) I’ve ask similarly naive questions. (Haha… I can’t think of any right now!) The questioner simply doesn’t know what it takes and more importantly doesn’t know what questions to really ask. This is a huge part of my job. To ask questions. It’s amazing actually, as I type this, how many questions I do ask on a daily basis. I have a bit of a complex about asking too many questions. Alas, that’s the way I work. I need information. I need to know how something functions, how it looks, where it goes, how it integrates, how do you, the client, need to administer it, if at all?

So the take away?
As with most challenges in life, you have to think through it. So what if it’s a loaded question? Be nice. I’d have to dig down and figure this out even if a client wrote me a book on what s/he wanted. This is nothing more than an opportunity to hone my communication skills and hopefully help someone understand what it takes to throw something up on their website.

(Of course, if you’re up against a deadline, a one line request like this could prove very frustrating. In which case you’d have to fall back onto your contract and renegotiate or provide a separate quote for the extra work.)

Feel free to tell me your stories in the comments.

Bookmark and Share
Posted in: Development  |   |  Leave a comment

Twitchy Artifacts with 1080i Video in Final Cut Pro X

I was cutting a quick video—which ended up not being so quick—for a friend. One not-so-small clip was recorded in 1080i 60 fps. Once imported into FCPX there were these twitchy artifacts forming every couple seconds during playback.

I searched the web and the problem has to do with needing to first de-interlace the source video. One solution was to download a program called JES Deinterlacer. After a number of failures—the program would freeze after processing a short number of frames—I gave up and went to bed.

The following morning I suspected that the freezing problem was due to the fact that I was working off an external hard drive. No bother. So after copying the file over to my Desktop I was able to process the entire video. The resulting file, after importing into FCPX, was free of those twitching artifacts.

Sadly, however, the quality was degraded. But that is a side effect of de-interlacing. Read more about it here.

Also, one solution was to allow FCPX to do the do-interlacing when you share out a master file, but I had no luck with that. Any time I rendered the project the resulting master file would contain the artifacts.

I am very thankful for the JES Deinterlacer.

Bookmark and Share
Posted in: Video Production  |  Tagged with: , , ,  |  Leave a comment

Most recent work

  • Valhalla DSP A one man Seattle based company, writing pretty sick professional audio plugins. Check ‘em out!
  • Trivial Beersuit A site that provides professional pub trivia to bars and restaurants.

Need hosting?

  • Media Temple My go to hosting provider. You get rockstar hosting and I make a little cash. No pressure, just clean honest fun.

Past work