Validate terminal command in PHP

Testing if a function exists in PHP is easy. Testing if a command exists on the system is also easy.

I’ve never really run into the problem of having to create a compatibility suite script to make sure my PHP script will run without trouble. Simple things like checking the version of PHP installed or the version of MySQL are straightforward. This time though, I needed to make sure a command line program existed on the system which I invoke using exec().

First and foremost, we need to check that exec() exists and we can use it. If it does, we then need to use it to execute a command on the server which will output the path to our command. I will be testing for tar in the example.

if( function_exists('exec') )
{
    // send test command to system
    exec('command -v tar >& /dev/null && echo "Found" || echo "Not Found"', $output);

    if( $output[0] == "Found" )
    {
        // command is available
        return TRUE;
    }
    else
    {
        // command is unavailable
        return FALSE;
    }
}

Our focus will be this line:

exec('command -v tar >& /dev/null && echo "Found" || echo "Not Found"', $output);

In the first part of the command we will run command with the -v option. The -v option causes the output of the command to be displayed or return zero if the command is not found. Here’s a short description of the command:

SYNTAX
    command [-pVv] command [arguments ...]
OPTIONS
    -P  Use a default path
    -v  Verbose
    -V  More verbose

The next part of the command we use >& which is a metacharacter in Unix which tells the command to redirect the standard output and standard error. Which in this case, we redirect the output to a file /dev/null. We do this because we want to handle the response of the command with the last part.

The last part of the command we use && which is another metacharacter which tells Unix to execute the following command only if the preceding command succeeds. We also use the || metacharacter which tells Unix to execute the following command if the preceding command fails. To understand it better, it’s just like writing an if-then-else statement:

If( command -v tar >& /dev/null ) Then
    echo "Found"
Else
    echo "Not Found"
End If

Now we need to bring the response back to PHP. We do that with the second parameter of exec(); $output. Every line of output from the command will be returned in $output as an array which we can then run our conditional against.

Short, simple, easy little command. Just replace tar with the command you’d like to check for. You could even take the code and place it into a function to make it easily reusable.

Modular Sidebar in WordPress

Like all good developers, I go back and look at past code to see what I could have improved and how I can apply the new knowledge to a current project.

Both of the projects in question had sidebars with sections that are shared throughout the site. However, not all sections are being displayed at once. Some blocks of HTML would be show on the homepage, another on the about page and both on the contact page. Here is how I coded it in WordPress for each site.

Site One

For this site, there is ‘Live Bulletin’, ‘Make a Donation’, ‘Testimonials’, ‘Downloads’ and ‘Social Networks’ sections. In the sidebar template I had each section in it’s own if statement. For each if statement, I would use WordPress’ Conditional Tags to show or hide certain sections that I needed for a particular page. Here is a quick glance at how my template file was looking:

<div id="sidebar">

	<?php if( !is_page(270) AND !is_page(262) ) : ?>
		<div id="live-bulletin">
			<!-- html code -->
		</div>
	<?php endif; ?>

	<?php if( is_page(270) ) : ?>
		<div id="make-donation">
			<!-- html code -->
		</div>
	<?php endif; ?>

	<?php if( is_home() OR is_page(262) ) : ?>
		<div id="testimonials">
			<!-- html code -->
		</div>
	<?php endif; ?>

	<?php if( is_front_page() OR is_search() OR is_page(890) ) : ?>
		<div id="downloads">
			<!-- html code -->
		</div>
	<?php endif; ?>

	<div id="social-networks">
		<!-- html code (shown on all pages) -->
	</div>

</div>

This sidebar template got pretty messy, very quickly. Little updates such as displaying a section on another page became a hassle. For the next site, I didn’t rush, took my time and tried a different method.

Site Two

I’ll just use the same sections as the previous site for easy comparison. With this next method, I decided to put each section in it’s own function. That way, I could separate the logic from the view easily and make modifications quickly. Here is how this template came out:

<?php function sidebar_livebulletin() { ?>
	<div id="live-bulletin">
		<!-- html code -->
	</div>
<?php } ?>

<?php function sidebar_makedonation() { ?>
	<div id="make-donation">
		<!-- html code -->
	</div>
<?php } ?>

<?php function sidebar_testimonials() { ?>
	<div id="testimonials">
		<!-- html code -->
	</div>
<?php } ?>

<?php function sidebar_downloads() { ?>
	<div id="downloads">
		<!-- html code -->
	</div>
<?php } ?>

<?php function sidebar_socialnetworks() { ?>
	<div id="social-networks">
		<!-- html code -->
	</div>
<?php } ?>

<div id="sidebar">
	<?php
	// Home Page
	if( is_front_page() )
	{
		sidebar_livebulletin();
		sidebar_testimonials();
		sidebar_socialnetworks();
	}

	// About Page
	if( is_page(8) )
	{
		sidebar_testimonials();
		sidebar_downloads();
		sidebar_socialnetworks();
	}

	// Contact Page
	if( is_page(12) )
	{
		sidebar_makedonation();
		sidebar_socialnetworks();
	}
	?>
</div>

Now that is a better looking template! I’ve seen this function-based implementation before and I really like it. Updating this template has proven to be quick and easy. I have already started to adopt this method and will continue too until I establish a better method.

Be A Better Programmer

Aaron Swartz posted an article today on his blog titled: How I Hire Programmers. If you haven’t done so already, read it!

I believe this article is not only for employers looking for a way to hire better programmers. But, it could also be beneficial for an aspiring programmer to work on themselves to be a better candidate for the job.

Below, I’ve picked out a couple quotes and added my response.

“Someone who gets stuff done but isn’t smart is inefficient: non-smart people get stuff done by doing it the hard way and working with them is slow and frustrating.”

Anybody can Google around and find a code snippet, paste it in, and continue working. However, do you know what that snippet of code is doing? Do you know why that block of code works, and how it works? You need to.

Whenever I run into something I don’t know how to solve, I’ll Google it. I’ll find a snippet of code or a tutorial and read through it. I’ll pick it apart, look up function calls, comment the code and even completely rewrite it. Line by line I’ll figure out a better way it could have been written. I will make it mine. You should do the same.

“… do they learn? At some point in the conversation, you’ll probably be explaining something to them. Do they actually understand it or do they just nod and smile? There are people who know stuff about some small area but aren’t curious about others. And there are people who are curious but don’t learn, they ask lots of questions but don’t really listen. You want someone who does all three.”

With the technology of today, always changing and new things being introduced, you can’t afford not to learn something new. Are you intrigued by the API’s and Web Services available? If you’ve never used it before, use it now! Make a simple script, just to test it out. Do that, and you will become a better programmer.

Do any of these sound like you? Take a look at yourself and these points from the article. See how you can make yourself a better programmer.

Google Maps API: Center Point Location

As stated in the [intlink id="315" type="post"]last article[/intlink], I have been working a lot with the Google Maps API for a current client project. The most recent problem, was the application was required to display a quick overview of the current location the user was looking at. The City and the State.

Again, jQuery will be used in this demo and we will be using the GClientGeocoder service.

Loading Google Maps API

Here is the HTML for the map and the initial Google Maps API javascript code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head profile="http://gmpg.org/xfn/11">

	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>Google Maps API: Center Point Location</title>

	<!-- JQUERY -->
	<script type="text/javascript" charset="utf-8" src="javascript/jquery.js"></script>
	<script type="text/javascript" charset="utf-8" src="javascript/jquery.ui.js"></script>

	<!-- GOOGLE MAPS API -->
	<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=YOUR_API_KEY_HERE" type="text/javascript"></script>

	<script type="text/javascript">
	// store the current zoom level for reference with google maps and custom zoom slider
	var currentZoomLevel = 10;

	// map object (global)
	var map;

	// geocoder object (global)
	var geocoder = new GClientGeocoder();

	$(document).ready(function() {
		// create the google map
		map = new GMap2(document.getElementById("map"));

		// set starting center point
		map.setCenter(new GLatLng(37.4419, -122.1419), currentZoomLevel);

		// set map UI as default
		map.setUIToDefault();
	});
	</script>
</head>
<body>

<div id="container">
	<h1>Google Maps API: Center Point Location</h1>

	<div id="content">
		<ul>
			<li><strong>State: </strong><span id="map-state">current state</span></li>
			<li><strong>City: </strong><span id="map-city">current city</span></li>
		</ul>

		<div id="map"></div>
	</div>
</div>

</body>
</html>

Retrieving the Current Location

Now that Google Maps API has been loaded, we need to create a function to get the current center-point’s Longitude and Latitude. Then we need to get the address, via GClientGeocoder. Then we need to strip out the data we need and update our display.

function updateMapLocation() {
	geocoder.getLocations(map.getCenter().toString(), function(point) {

		var currentAddress = point.Placemark[0].address;
		currentAddress = $.trim(currentAddress);
		var currentAddressMatches = currentAddress.split(/^([^,]*),s([^,]*),s([A-Z]{2})s([0-9]*),s([^,]*)$/);

		if(/^([^,]*),s([a-zA-Z^,]*)[0-9s]*,s[^,]*$/.test(currentAddress)) {
			var currentAddressMatches = currentAddress.split(/^([^,]*),s([a-zA-Z^,]*)[0-9s]*,s[^,]*$/);
		} else if(/^[^,]*,s([^,]*),s([a-zA-Z^,]*)[0-9s]*,s[^,]*$/.test(currentAddress)) {
			var currentAddressMatches = currentAddress.split(/^[^,]*,s([^,]*),s([a-zA-Z^,]*)[0-9s]*,s[^,]*$/);
		}

		var currentCity = currentAddressMatches[1];
		var currentState = currentAddressMatches[2];

		$('span#map-state').html(currentState);
		$('span#map-city').html(currentCity);
	});
}

In the code above, I realized GClientGeocoder was returning addresses for the current center point, in a few different formats. The two regular expression tests determine which format was returned and then splits out the data we need. After the data has been retrieved, we update the HTML display for span#map-state and span#map-city.

Now that we have a function to pull the address portions, we need to call it somewhere! I have two places where I have decided was the best time to update the location. When the maps is loaded (on page load) and anytime the map has been moved or zoomed.

So, we write an if statement to check if maps.isLoaded() and then we need to addListenter() to event moveend.

// once map has fully loaded, update current location in view
if(map.isLoaded()) { updateMapLocation(); }

// update location in view upon changing the map in any way
GEvent.addListener(map, 'moveend', function() { updateMapLocation(); });

Google Maps API: Custom Zoom Slider

Google Maps API is just one of the API’s I’ve been working with recently. The most recent problem I’ve run into that needed to be solved was the ability to create a custom designed zoom slider, replacing the default. The default one was not gonna work for this project and the designer created a better looking one.

While searching online to see if this had already been achieved. I failed to find any example of what I needed to accomplish easily and still be able to reuse the code. So, I decided to take on the feat. But, where to start?

jQuery

I am a huge fan of jQuery and jQuery has a user interface library, jQuery UI. jQuery UI gives us the ability to create a slider widget, which is highly customizable and would work for what I needed to do.

So, go download jQuery and download jQuery UI and we’ll get started! You will also need to get a Google Maps API key.

Setup

To begin, we will have to create an HTML file which loads all of our stylesheets, javascript and google map. Below is the initial HTML code. I have added the HTML for our custom slider already.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head profile="http://gmpg.org/xfn/11">

	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>Google Maps API: Custom Zoom Slider</title>

	<!-- JQUERY -->
	<script type="text/javascript" charset="utf-8" src="javascript/jquery.js"></script>
	<script type="text/javascript" charset="utf-8" src="javascript/jquery.ui.js"></script>

	<!-- GOOGLE MAPS API -->
	<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=YOUR_API_KEY" type="text/javascript"></script>

</head>
<body>

<!-- our custom slider container -->
<div id="zoom-slider">

	<!-- decrease zoom level control -->
	<a id="zoom-control-minus" href="#"></a>

	<!-- zoom slider control -->
	<div id="zoom-range">
		<div id="zoom-path"></div>
	</div>

	<!-- increase zoom level control -->
	<a id="zoom-control-plus" href="#"></a>
</div>

<!-- this is where google maps will load -->
<div id="map"></div>

</body>
</html>

Loading Google Maps API

Next we will need to load the Google Maps API. Here is the code. It is commented pretty well and should be easy to understand.

// store the current zoom level for reference with google maps and custom zoom slider
var currentZoomLevel = 10;

// map object (global)
var map;

$(document).ready(function() {
	// create the google map
	var map = new GMap2(document.getElementById("map"));

	// set starting center point
	map.setCenter(new GLatLng(37.4419, -122.1419), currentZoomLevel);

	// force normal maps type
	map.setMapType(G_NORMAL_MAP);

	// define minimum and maximum zoom levels
	G_NORMAL_MAP.getMinimumResolution = function() { return 0; }
	G_NORMAL_MAP.getMaximumResolution = function() { return 19; }

	// sets the map to "animate" zoom (only on double click and mouse wheel scroll)
	map.enableContinuousZoom();

	// enable the ability to zoom via mouse wheel
	map.enableScrollWheelZoom();
});

You can configure the return values of G_NORMAL_MAP.getMinimumResolution and G_NORMAL_MAP.getMaximumResolution to limit the zoom distance. 0 is the lowest value and 19 being the highest value (20 zoom levels).

Lets Style It!

Now that we have Google Maps loading into our div, we need to style it! Below is the code to style the Google Map and the custom slider. Again, I use a reset stylesheet which is bundled in the download.

/* Globals
------------------------------------------------------*/
body { font:75% helvetica, arial, sans-serif; background:#fff; color:#333; text-align:center; }

/* Google Map
------------------------------------------------------*/
#map { margin-top:25px; height:300px; width:518px; border:1px solid #fff; }

/* Custom Slider
------------------------------------------------------*/
#zoom-slider { margin:0 auto; position:relative; height:28px; width:203px; background:url(../images/zoom-slider-background.jpg) no-repeat; }
	/* minus button */
	#zoom-slider #zoom-control-minus { position:absolute; top:9px; left:11px; display:block; height:10px; width:10px; background:url(../images/zoom-control-minus.jpg) no-repeat; overflow:hidden; text-indent:-9999em; }
	/* plus button */
	#zoom-slider #zoom-control-plus { position:absolute; top:9px; right:11px; display:block; height:10px; width:10px; background:url(../images/zoom-control-plus.jpg) no-repeat; overflow:hidden; text-indent:-9999em; }
	/* container for the zoom 'handle' */
	#zoom-slider #zoom-range { position:absolute; top:9px; left:31px; height:10px; width:140px; background:url(../images/zoom-slider-range.jpg) no-repeat; z-index:1; }
		/* the zoom handle */
		#zoom-slider #zoom-range .ui-slider-handle { position:absolute; top:0px; margin-left:-5px; height:10px; width:10px; background:url(../images/zoom-control-handle.png) no-repeat; border:0; cursor:pointer; z-index:2; outline:none; }
		/* size path handle can travel*/
		#zoom-slider #zoom-range #zoom-path { position:absolute; height:10px; width:130px; top:0px; left:5px; cursor:pointer; }

The zoom slider will now look like this (images bundled in the download):

zoom-slider-image

Make It Work

Now that we have everything looking nice and loading correctly, we need to make it work! Using jQuery UI and the Slider Widget, we will hook the div#zoom-slider div#zoom-path and allow jQuery UI to do it’s magic. however, we still need to hook the plus and minus buttons and make the slider communicate with Google Maps to update our map. In the Javascript, after we are done setting up Google Maps, we will need to place this code.

$(function() {
	// slider target
	var target = $('#zoom-slider #zoom-path');

	// create the slider
	target.slider({
		orientation: 	'horizontal',
		value: 			currentZoomLevel,
		min: 			parseInt(G_NORMAL_MAP.getMinimumResolution()),
		max: 			parseInt(G_NORMAL_MAP.getMaximumResolution()),
		step: 			1,
		animate: 		true,
		stop: function() {
			map.setZoom(parseInt(target.slider('option','value')));
		}
	});

	// update slider on zoom with double click
	GEvent.addListener(map, 'moveend', function() { target.slider('option','value', map.getZoom()); });

	// maximum slider value
	var maxValue = parseInt(target.slider('option', 'max'));

	// minimum slider value
	var minValue = parseInt(target.slider('option', 'min'));

	// hook increase zoom control
	$('#zoom-control-plus').click(function() {
		// current slider value
		var currentValue = parseInt(target.slider('option','value'));

		// current slider value increased by 1
		var newValue = currentValue+1;

		// is new value greater than max value?
		if(newValue <= maxValue) {
			// increase slider value
			target.slider('option', 'value', newValue);
			map.setZoom(newValue);
		} else {
			// slider is at max value
			target.slider('option', 'value', maxValue);
			map.setZoom(maxValue);
		}
		return false;
	});

	// hook decrease zoom control
	$('#zoom-control-minus').click(function() {
		// current slider value
		var currentValue = parseInt(target.slider('option','value'));

		// current slider value increased by 1
		var newValue = currentValue-1;

		// is new value greater than max value?
		if(newValue >= minValue) {
			// increase slider value
			target.slider('option', 'value', newValue);
			map.setZoom(newValue);
		} else {
			// slider is at max value
			target.slider('option', 'value', minValue);
			map.setZoom(minValue);
		}
		return false;
	});
});

Slider does a nice job of incrementing and decrementing the value and moving the handle the appropriate distance. Anytime the slider moves we need to update the map. Anytime the map moves we need to update the slider.

So, when initializing the slider, we hook the stop event of the slider. Each time the slider “stops” movement, we update the map zoom using the Google Map API function setZoom(). So, now we know when we move the slider, the map will update as well!

Next, we hook the moveend event of Google Maps. If the user double clicks the map to zoom in and out or uses the scroll wheel to zoom in and out, we update the zoom value of the slider using $.slider('option', 'value', map.getZoom()). So, now we know when the map moves the slider will move as well.

Next, we need to hook the plus and minus buttons to allow a user to click them to zoom in and out. Using jQuery, we will bind each click event to update the map and slider values. The plus button will continue to zoom in until we reach the maximum zoom value. The minus button will continue to zoom out until we reach the minimum zoom value.