I am a jack of all trades. Excepting those trades I do not like. I am a web developer of simple, reliable solutions to problems.

Twitch for Blinksale

Twitch for Blinksale - An iPhone app for BlinksaleAfter many late nights, long weekends, and a couple of months I am finally finished with version 1.0 of Twitch for Blinksale.

Twitch for Blinksale is the first native iPhone/iOS client for the popular invoicing service Blinksale. With Twitch, you can manage all of your invoicing needs right from your iPhone.

Its clean, professional design highlights the information you need. Updating invoices on-the-go has never been easier.

Invoices Features:

  • View, add, update invoices.
  • Send invoices to clients with or without payment link.
  • Receive payment for invoices.

Client Features:

  • View and add clients.
  • Add people to clients.
  • Contact clients directly from phone (using the iPhone’s phone and mail apps)

More:

  • Convenient, “Pull To Refresh” design on invoice and client views makes reloading data a cinch.
  • Tested on multiple iPhone devices and OS versions.
  • Very stable.
  • Secure credential storage in keychain.

Screenshots:


 

Twitch for Blinksale is available for purchase in the App Store.

Available in the iPhone app store

Bulk Updating Image Sizes in @ShopPlugin

This will be two helper scripts I’ve written in a row for Shopp.

We found a situation recently where we had images with different sizes in Shopp, making uniform usage difficult at times. To compensate for this, we exported the images again. Since we use a consistent naming scheme, we didn’t have to worry about names.

We then uploaded these new images over the existing images in the /wp-content/uploads/shopp folder.

In a perfect world, this would be all there was to it, but unfortunately Shopp stores width and height information about an image in the database. This meant each table entry had to be updated. Enter this script.

It automatically scans your uploads directory and looks for images that have a different size than is stored in the database. It then updates the size.

WARNING: This script is DESTRUCTIVE. It can potentially screw up your database so PLEASE make sure you have a full backup. This is provided without any warranty whatsoever. I have only tested this on Shopp 1.1.17 and have no idea how it will work/not work on other versions.

<?php
//Adjust to point to root from where this script is located
require '../wp-load.php';
 
//Edit this path
$path = '/var/www/vhosts/domain/httpdocs/wp-content/uploads/shopp';
 
// END EDITS. You shouldn't have to edit below this line.
 
header("Content-Type: text/plain");
ini_set("auto_detect_line_endings", 1); 
$dir_handle = opendir($path);
$row = 1;
$csv_data = array();
while (false !== ($file = readdir($dir_handle))) 
{
	if ($file != "." && $file != "..") 
	{		
		$width_regex = '/((?<=width\\";i:)[0-9]{1,4})|((?<=width=\\")[0-9]{1,4})/';
		$height_regex = '/((?<=height\\";i:)[0-9]{1,4})|((?<=height=\\")[0-9]{1,4})/';
		$query = "select value from wp_shopp_meta where value LIKE '%\"".$file."\"%'";
		$info = getimagesize($path."/".$file);
 
		$existing_properties = $wpdb->get_var($query);
 
		if(strlen($existing_properties) > 10)
		{
			$new_width = $info[0];
			$new_height = $info[1];
 
			preg_match($width_regex, $existing_properties, $old_width);
			preg_match($height_regex, $existing_properties, $old_height);
 
 
			if(($new_width != $old_width[0] || $new_height != $old_height[0]) && !(empty($old_width[0]) || empty($old_height[0])))
			{
				echo "Updating $file. Old width/height: ".$old_width[0]."/".$old_height[0]." New width/height: $new_width/$new_height";
 
				$new_properties = preg_replace($width_regex, $new_width, $existing_properties);
				$new_properties = preg_replace($height_regex, $new_height, $new_properties);
 
				if(strlen($new_properties) > 10)
				{
					$query_update = "update wp_shopp_meta set value = '".mysql_real_escape_string($new_properties)."' where value LIKE '%\"".$file."\"%'";
 
					//echo "Query update: ".$query_update."\n";
 
					$update = $wpdb->query($query_update);
 
					if($update == 0)
					{
						echo " --- FAILED. No rows changed. Didn't update.\n";
					}
					else if($update > 1)
					{
						echo " --- POSSIBLE FAILURE. Updated too many rows.($update)\n";
					}
					else
					{
						echo " --- SUCCESS\n";
					}
				}
				else
				{
					echo "--- FAILED. New properties string suspiciously short.";
				}
			}
		}
	}
}
?>

Hope it helps. Let me know if there are questions.