Collapsing directories

Often I get a handoff where there are single files (or a few files) I need from each of a collection of dozens or hundreds of folders. So I’ll often want to “collapse” a directory of subdirectories, isolating all contained files (or a subset) in the parent directory or a new subdirectory.

In bash:

find /foo -iname '*.txt' -exec cp \{\} /dest/ \;

find will find all the files under the path /foo matching the wildcard *.txt, case insensitively (That’s what -iname means). For each file, find will execute cp {} /dest/, with the found file in place of {}.

You can also do this with GNU find and GNU mv:

find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +

Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command.

Translating Programmer Speak

Doing some research on writing QA Test Cases at the erstwhile SoftwareQATest.com, and stumbled on this nugget:

(On the topic of “Why does software have bugs?”)

egos – people prefer to say things like:

  • ‘no problem’
  • ‘piece of cake’
  • ‘I can whip that out in a few hours’
  • ‘it should be easy to update that old code’

instead of:

  • ‘that adds a lot of complexity and we could end up making a lot of mistakes’
  • ‘we have no idea if we can do that; we’ll wing it’
  • ‘I can’t estimate how long it will take, until I take a close look at it’
  • ‘we can’t figure out what that old spaghetti code did in the first place’

If there are too many unrealistic ‘no problem’s’, the result is bugs.

Man, this is really too real, and how many times do I say these very things? Every project I think.

contains() method polyfill

The contains() method determines whether one string may be found within another string, returning true or false as appropriate. Currently, this is an experimental technology, part of the Harmony (EcmaScript 6) proposal, so syntax, functionality etc could very well change.

However, its a handy String Prototype to add, especially when you are trying to test if a URI contains another URI or URI part. You might well ask, why not just pass the directory string to the RegExp constructor? Yeah, have fun with that and all the wonderfull escaping and unescaping you’ll need to do with those backslashes, periods, etc.

Here ’tis;

if (!('contains' in String.prototype)) {
  String.prototype.contains = function(str, startIndex) {
    return -1 !== String.prototype.indexOf.call(this, str, startIndex);
  };
}

Handy Array functions

To find if a value is in an array:

Array.prototype.contains = function (v) {
				for (var i = 0; i < this.length; i++) {
					if (this[i] === v)
						return true;
				}
				return false;
			};

e.g.

var nums = [1,2,3,4];
nums.contains(7) = false

To get an array of unique values from an original array:

			Array.prototype.unique = function () {
				var arr = [];
				for (var i = 0; i < this.length; i++) {
					if (!arr.contains(this[i])) {
						arr.push(this[i]);
					}
				}
				return arr;
			}
var nums = [1,2,3,4,1,2,2,2,1,2,3,4];
nums.unique = [1,2,3,4]

3.6 Audio: So what happens to blogs using the old JetPack shortcode for generating playlists?

Long and short of it, WP 3.6 supports audio (meaning has a player for) out of the box. However, it doesn’t support playlists as JetPack audio did.

Unfortunately, WP has adopted the JP convention of the [audio] shortcode, but the native implementation is crippled. A future release of Jetpack will allow playlists, but it introduces an entirely new shortcode (not unlike the shortcode for my JPEP plugin). The worst part of all  this is that because JP gives precedent to the native WP player, any previous [audio] shortcode that calls a playlist no longer works, as the shortcode it just dumps control to WP. No smart filtering via Jetpack, no nothing.

So, if you use JetPack Easy Playlists or shortcode like [<em>audio one.mp3,two.mp3,three.mp3|titles=Song One,Song Two,Song Three|artists=The Ones, The Twos,The Threes</em>] you are left high and dry with shortcodes that just don’t work anymore. Obivously, this an oversight by Auttomatic.

The only (ugly) solution is found here: http://wordpress.org/support/topic/plugin-jetpack-by-wordpresscom-audio-shortcode-is-not-falling-back-to-flash-in-ie9-ff?replies=13#post-4515607 (read whole thread for the whole nitty gritty). :(

TL;DR: Jetpack supported playlists using the [audio] shortcode, and now it does not.

UPDATE: Jetpack should soon support the old shortcode format again temporarily until playlists are folded into the core. See: http://wordpress.org/support/topic/plugin-jetpack-by-wordpresscom-audio-shortcode-is-not-falling-back-to-flash-in-ie9-ff?replies=18#post-4529908

working with HTML5 getParent and getFile

I have a FileEntry that represents the following file/path: /cognitivemodelsaging/cognitivemodelsaging_lo.mp4
Whenever I call getParent() for the given FileEntry, it returns undefined.  Frustrating.

But the reason why is that getParent does not return a string of the directory name, nor simply a dirEntry object from which you can grab dirEntry.name(). Rather it runs the resultant dirEntry or error object through one of two callback functions.
So rather we need to do something like:

fileEntry.getParent(function(dirEntry) {

console.log("got a parent");

console.log("full path = " + dirEntry.fullPath);

}, function(error) {

console.log("failed to get parent = " + error);

});

Likewise for calling dirEntry.getFile, except in this case we need our first argument to be a filepath (absolute or relative). Another note is that both these calls are asynchronous, and that calling the anonymous callbacks can have repercussions in regard to scope. So it make sense to call named functions declared in a strategic place.

Here is an example in which I call these methods inside a constructor function, and I need the callbacks to have access to some private variables of said function. The function takes a fileEntry object, and constructs a metadata object to be rendered as a table (and eventually be exported as an csv). Relating to our topic at hand, I am changing a metadata default for images to another value if the jpg sits next to a swf.

Anyway, you can see how in my “success” callback, I’m updating an external data array and re-rendering a table based on the async results.

function Asset (entry){

				console.dir(entry);

				var _fileParts = entry.name.split('.');
				console.log("fileParts",_fileParts);
				var _ext = _fileParts.splice(-1,1).toString();
				console.log("ext",_ext);
				var _fileName = _fileParts.join('.');
				console.log("fileName",_fileName);
				var _nameArray =  _fileName.split('_');
				console.log("nameArray",_nameArray);
				var _quality = (_ext === 'mp4') ? _nameArray.splice(-1,1).toString() : 'lo';
				console.log("quality",_quality);

				this.filename = entry.fullPath;
				this.nb_asset_type = 'UNKNOWN';
				this.video_resolution_label = "low";
				this.video_inline_pixel_height = null;
				this.video_inline_pixel_width = null;
				this.video_native_pixel_height = null;
				this.video_native_pixel_width = null;
				this.video_bitrate = null;
				this.flash_pixel_height = null;
				this.flash_pixel_width = null;
				this.flash_version = null;
				this.flash_params = null;
				this.flash_variables = null;

				this.setter = function() {
					for(var prop in arguments[0])   {
						if(this.hasOwnProperty(prop))   {
							this[prop]=arguments[0][prop];
						}
					}
				}

				switch(_ext) {
				case "mp4" :
				this.nb_asset_type = "video";
				if (_quality === "hi") {
					this.video_resolution_label = "high";
					this.nb_asset_type += " (high res.)";
					this.video_inline_pixel_height = 600;
					this.video_inline_pixel_width =  800;
					this.video_native_pixel_height = 600;
					this.video_native_pixel_width = 800;
					this.video_bitrate = 768;
				}
				else if (_quality === "med") {
					this.video_resolution_label = "medium";
					this.nb_asset_type += "  (medium res.)";
					this.video_inline_pixel_height = 360;
					this.video_inline_pixel_width =  480;
					this.video_native_pixel_height = 360;
					this.video_native_pixel_width = 480;
					this.video_bitrate = 512;
				}
				else {
					this.nb_asset_type += " (low res.)";
					this.video_inline_pixel_height = 240;
					this.video_inline_pixel_width =  320;
					this.video_native_pixel_height = 240;
					this.video_native_pixel_width = 320;
					this.video_bitrate = 256;
				}
				break;
				case "xml" :
				this.nb_asset_type = "video closed_caption file";
				break;
				case "jpg" :
				this.nb_asset_type = "video poster image";
				break;
				case "txt" :
				this.nb_asset_type = "video transcript";
				break;
				case "swf":
				this.nb_asset_type = "flash";
				this.flash_pixel_height = 595;
				this.flash_version = 7;
				break;
				default :
				this.nb_asset_type = "UNKNOWN";
				break;
			}

			function foundSWF(){
				data[position - 2].nb_asset_type = "flash poster image";
				$container.handsontable('render');
			}

			function noSWF(){
				nb_asset_type = "video poster image";
			}

			if (_ext == "jpg") {
					entries[i].getParent(function(dirEntry) {
					dirEntry.getFile(_fileName+'.swf', {},
					foundSWF,
					noSWF);
				},
				function(error) {
					nb_asset_type = error.name;
				})
				}

			}

Count Photos in a WordPress Gallery

You may wish to display a count  of the photos in your Gallery for a given post, possibly on the front index. I’ve often seen this done with SQL queries, which always made me cringe a bit. Its also advised that you count the post children, going over an array like:

$images =& get_children( 'post_type=attachment&post_mime_type=image' );

The problem here is that galleries, especially under the new media manager paradigm, don’t necessarily contain just images attached to the post. They actually could contain none, some or all.

So, the best way is actually to use get_shortcode_regex to grab the gallery shortcode. From there, we can count the “id” arguments, which represent universal identifiers for the photos regardless of what post they are attached to. If we don’t find any such arguments, we know that just the unadorned “[ gallery ]” is being used, meaning its safe to count images attachments.

if ( has_post_format( 'gallery' )) {
						// or filter by custom post type or category
						$pattern = get_shortcode_regex();
						preg_match('/'.$pattern.'/s', $post->post_content, $matches);
						if (is_array($matches) && $matches[2] == 'gallery') {
						   // do something
						   preg_match('/\[ gallery ids=\"(.*?)\"]/',$matches[0],$ids);
						  if (is_array($ids) && $ids[1] ) {
							$photos = explode(',',$ids[1]);
						  } else {
							$photos = get_children( array( 'post_parent' => $post->ID, 'post_type'   => 'image' ) );
						  }
						  echo count($photos ).' photos in this gallery.';
						}
					}

Jetpack Audio Embed Shortcode: A fix for Flash fallback not working

If you’re using all mp3’s or otherwise triggering flash fallback with your audio embed, check to make sure that the “player.swf” that Jetpack is trying to use is actually up. For example, http://en.wordpress.com/wp-content/plugins/audio-player/player.swf or http://s0.wp.com/wp-content/plugins/audio-player/player.swf (At the time of this post, these both return 404). If these are down, you’ll need to use a local copy of “player.swf” until they go back up.

Here is a temporary fix:

Grab this old plugin (what Jetpack’s audio support is based from). Don’t install it, though. Find the “player.swf” file inside “\audio-player.2.0.4.6\audio-player\assets” Place this somewhere on your site, a good place is in your plugin directory.
Then go to “/wp-content/plugins/jetpack/modules/shortcodes” on your ftp, and edit “audio.php” Change line 237 to your local copy of “player.swf.” Change back when Automattic get their ish together.