Merge two urls

/**
 * Combine two urls.
 *
 * The urls can be either a string or url parts that consist of:
 *
 *     scheme, host, port, user, pass, path, query, fragment
 *
 * If passed in as parts in an array, the query parameter can be either
 * a string or an array of name/value key pairs.  The query parameters
 * will be added on to the ones from the original url.  If you want to
 * remove query parameters, or any other parts of the url, you need to
 * pass the value in as null.
 *
 * Examples:
 *
 *     urlMerge(
 * 	       '/tests/section/people?id=9405',
 *         array('query' => array('found' => true, 'id' => null))
 *     );
 *
 *     urlMerge(
 * 	       'http://www.example.com/',
 *         array('scheme' => 'https', 'query' => 'foo=bar&test=1'
 *     );
 *
 *     urlMerge(
 * 	       array('path' => '/tests/item', 'query' => 'id=9405'),
 *         'http://www.example.com'
 *     );
 *
 * @param  string|array $original
 * @param  string|array $new
 * @return string
 */
function urlMerge($original, $new)
{
    if (is_string($original)) {
        $original = parse_url($original);
    }
    if (is_string($new)) {
        $new = parse_url($new);
    }
    $qs = null;
    if (!empty($original['query']) && is_string($original['query'])) {
        parse_str($original['query'], $original['query']);
    }
    if (!empty($new['query']) && is_string($new['query'])) {
        parse_str($new['query'], $new['query']);
    }
    if (isset($original['query']) || isset($new['query'])) {
        if (!isset($original['query'])) {
            $qs = $new['query'];
        } elseif (!isset($new['query'])) {
            $qs = $original['query'];
        } else {
            $qs = array_merge($original['query'], $new['query']);
        }
    }
    $result = array_merge($original, $new);
    $result['query'] = $qs;
    foreach ($result as $k => $v) {
        if ($v === null) {
            unset($result[$k]);
        }
    }
    if (!empty($result['query'])) {
        $result['query'] = http_build_query($result['query']);
    }
    return (isset($result['scheme']) ? "{$result['scheme']}://" : '')
		. (isset($result['user']) ? $result['user']
		    . (isset($result['pass']) ? ":{$result['pass']}" : '').'@' : '')
		. (isset($result['host']) ? $result['host'] : '')
		. (isset($result['port']) ? ":{$result['port']}" : '')
		. (isset($result['path']) ? $result['path'] : '')
		. (!empty($result['query']) ? "?{$result['query']}" : '')
		. (isset($result['fragment']) ? "#{$result['fragment']}" : '');
}
Did you like this? Share it:

Dreamhost and procmail – parsing your mail with a script

I have a Dreamhost account and have done for some while. Typically I’m happy with their service, but yesterday was the first real frustration I had with them. I wanted to use procmail to send email to a script for processing. I was sure I had done this before on Dreamhost, but couldn’t seem to get it to work in the wee hours of the night. So after a quick email to support asking if it was possible, they came back with this response:

Unfortunately this is not possible. We do
not offer or support any type of email to script functionality on our
servers.

And this pretty much backed up all the searches I had been doing on line in regards to Dreamhost and using procmail.

Now, where they may not support people doing this, it is my pleasure to tell you that it is possible! And here’s how you do it…
Continue reading ‘Dreamhost and procmail – parsing your mail with a script’

Did you like this? Share it:

Using CSS3 sucks (right now, but I’m sure it’ll get better)

Am I the only one to think that using a number of aspects of CSS3 right now really sucks? The potential it offers is great, but does anyone really think doing something like this for a gradient is a productive use of time?

    background: #9880cc; /* Old browsers */
    background: -moz-linear-gradient(top, #9880cc 0%, #bab3cc 93%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#9880cc), color-stop(93%,#bab3cc)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, #9880cc 0%,#bab3cc 93%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, #9880cc 0%,#bab3cc 93%); /* Opera11.10+ */
    background: -ms-linear-gradient(top, #9880cc 0%,#bab3cc 93%); /* IE10+ */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#9880CC', endColorstr='#BAB3CC',GradientType=0 ); /* IE6-9 */
    background: linear-gradient(top, #9880cc 0%,#bab3cc 93%); /* W3C */

Once upon a time, not that long ago, the trend setters/leaders of the web development community would have lynched you if you so much as dared to use a proprietary tag, be it in the css or the html. Now they’re actively encouraging the above kind of usage?! It’s ridiculous! Firefox, Chrome, Safari, IE and Opera all require different proprietary rules, and then you have the W3C recommended way and then the fallback for older browsers.

A Transform in CSS3 is just as bad:

-moz-transform: scale(0.8) rotate(deg) translate(px, px) skew(deg, deg);
-webkit-transform: scale(0.8) rotate(deg) translate(px, px) skew(deg, deg);
-o-transform: scale(0.8) rotate(deg) translate(px, px) skew(deg, deg);
-ms-transform: scale(0.8) rotate(deg) translate(px, px) skew(deg, deg);
transform: scale(0.8) rotate(deg) translate(px, px) skew(deg, deg);

And this time it’s not the rule value that’s different for each, it’s the rule name!

I think HTML5 (well, XHTML5 for me – I do love a properly closed tag!) and CSS3 are great, don’t get me wrong, and I think we’ve already seen a lot of examples of wonderful sites and demos created using them. But surely how it’s getting there and the asinine number of rules we have to put in for each browser is a major step backwards in what people were trying to achieve only a few years ago? (Ie, a nice compliant standard way of doing things.)

Incidentally; there are a couple great sites that help out doing fancy new CSS3 stuff:

The Ultimate CSS Gradient Generator
CSS3 Generator

Using sites like those can save a bit of sanity.

Did you like this? Share it:

Sorting an array of objects by one or more object property

Quite often I find myself having an array of objects and needing to sort that array by one or more of the properties in the objects… Imagine, for example, getting a large result set from Zend_Db, or something similar, and ordering in the query just takes too long. Or perhaps you’re getting results from a web service and that service doesn’t return the results in the order you’d like to use. Have you ever found yourself in that situation, too? On looking at the usort documentation one day I came across a comment by someone called Will Shaver that did almost what I wanted. With a little adaptation for my own use (being able to change the sort order, for example), it has become one of my favourite functions to use for sorting.

    /**
     * Sort an array of objects.
     *
     * You can pass in one or more properties on which to sort.  If a
     * string is supplied as the sole property, or if you specify a
     * property without a sort order then the sorting will be ascending.
     *
     * If the key of an array is an array, then it will sorted down to that
     * level of node.
     *
     * Example usages:
     *
     * osort($items, 'size');
     * osort($items, array('size', array('time' => SORT_DESC, 'user' => SORT_ASC));
     * osort($items, array('size', array('user', 'forname'))
     *
     * @param array $array
     * @param string|array $properties
     */
    public static function osort(&$array, $properties)
    {
        if (is_string($properties)) {
            $properties = array($properties => SORT_ASC);
        }
        uasort($array, function($a, $b) use ($properties) {
            foreach($properties as $k => $v) {
                if (is_int($k)) {
                    $k = $v;
                    $v = SORT_ASC;
                }
                $collapse = function($node, $props) {
                    if (is_array($props)) {
                        foreach ($props as $prop) {
                            $node = (!isset($node->$prop)) ? null : $node->$prop;
                        }
                        return $node;
                    } else {
                        return (!isset($node->$props)) ? null : $node->$props;
                    }
                };
                $aProp = $collapse($a, $k);
                $bProp = $collapse($b, $k);
                if ($aProp != $bProp) {
                    return ($v == SORT_ASC)
                        ? strnatcasecmp($aProp, $bProp)
                        : strnatcasecmp($bProp, $aProp);
                }
            }
            return 0;
        });
    }

Now a few cools things about the function:

  1. It uses anonymous/lambda functions (or closures, whatever your prefer to call them), and that’s just plain fun
  2. You can sort on more than one property and because the sorting is recursive, it’ll sort the second property within the confines of the first, the third within the confines of the second, and so on. Think sorting in SQL
  3. You can sort in ascending or descending order for any of the properties
  4. It retains key associations so you could use this on an associative array of objects
  5. If the parameter you want to sort on is an array itself then you can use any value (by specifying it’s key) in that array as the sorting value
Did you like this? Share it:

Extend Zend_View_Stream to easily escape view variables

Zend_View_Stream is used pretty much when ever you use Zend_View, and I’ve blogged about how handy it is before.  But as it’s a class like any other, you can extend it to give added functionality.  One such use is to add automatic escaping to your view variables when you want.  So instead of doing:

<?php echo $this->escape($this->var); ?>
<?= $this->escape($this->var); ?>

You could simply do:

<?=~ $this->var; ?>

That’s a lot simpler, isn’t it?
Continue reading ‘Extend Zend_View_Stream to easily escape view variables’

Did you like this? Share it:

Today’s date is the answer

The date today is 10/10/10.

101010 in binary is 42 which is, as we all know, the answer to life the universe and everything in it.

Did you like this? Share it:

PHPNW

image

Usually I’m a total wallflower at conferences, gravitating to only the people I know. This time round I’m trying to change that and speak to people, ask speakers questions, and all that.

Right now, though, I’m enjoying dinner. :)

Did you like this? Share it:

PHPNW Conference 2010

Going to be travelling to the PHPNW Conference today (it’s tomorrow, but I don’t fancy catching the stupidly early train to get there on time), but going over the schedule is a pain… There are just too many good talks! How can I possibly go see them all?! The 11:15 time slot is easy, that’ll be Rob Allen’s talk on ZF 2 – we use it so much at work now that it’d be crazy to not find out what’s coming and how this may affect what we’re currently doing.  Same with the  Michelangelo van Dam talk on unit testing with ZF.  But the 12:15, 15:00 and 16:15 talks?  I have no idea what to choose!  Juozas Kaziukena’s Optimizing Zend Framework might be worth while, but then again, is it all about ZF1 and how much will be relevant for ZF2?  The HipHop talk by Scott McVicar would be interesting. I can’t see it being deployed at my work, should still be a good talk… I’m liking the sound of the Database version control without pain by Harrie Verveer as well!  And that still leaves me with two other time slots to decide on… Sheesh!

The agony of choice, eh? ;-)

Did you like this? Share it:

Keeping Zend Studio’s version of Zend Framework in sync with Zend Server CE (on Windows)

Today I updated my install Zend Server CE.  I have to say that the ease of installing PHP, Apache and MySQL with Zend Server CE is amazing, and then configuring PHP’s extensions and directives with the provided interface is simply a dream!  (Really wish I could afford the full Zend Server, but that’s another matter…)

One thing that irked me, though, was that now my Zend Studio’s version of Zend Framework was different.  That doesn’t seem like a big problem, but I use the include path for my projects and always have ZF on there, which allows me to take advantage of the auto complete and so on.

My first thought was to use a symbolic link to point form the Studio’s folder to the Server CE folder…  But wait, I’m using Windows 7 – surely something as handy as a symbolic link can only be used on Linux machines?  I can understand why you’d think that, but did you know that you can create symlinks on Windows as of Vista?  Oh yes, you read correctly, my friend!  The command to do that is:

mklink /D \Path\To\SymLink \Path\To\Original

So for me, it was a case of doing:

mklink /D "ZendFramework-1" "C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework"

from within my Zend Studio folder, which happened to be:

C:\Program Files (x86)\Zend\Zend Studio - 7.1.1\plugins\org.zend.php.framework.resource_7.2.0.v20100324-1300\resources

I rebuilt my projects and lo-and-behold, a new version of ZF for my projects, and one that’ll always match with what Zend Server CE thinks I’m using. :-)

Did you like this? Share it:

HTPC build – the parts, they be comin’

Actually, for the most part I have gotten the parts.  The only thing I’m waiting on now is the CPU (together with a tube of Arctic Silver 5 compound) and the wifi card.  Hopefully they’ll come soon, because not having the CPU is a bit of a show-stopper.  However, the case…
Continue reading ‘HTPC build – the parts, they be comin’’

Did you like this? Share it: