$value ) {
array_push( $result, self::to_param( $value, $key ) );
}
return implode( '&', $result );
}
/**
* An object independent function to parameratize an object
*
* @param string $value the object to be parameratized
* @param string $key the key to scope under
* @return string
*/
public static function to_param( $value, $key = '' ) {
if ( is_array( $value ) ) {
if ( self::is_assoc( $value ) ) {
return self::assoc_array_to_param( $value, $key );
} else {
return self::array_to_param( $value, $key );
}
} elseif ( is_bool( $value ) ) {
return self::bool_to_param( $value );
} else {
return ( $key ? "$key=" . (string) $value : (string) $value );
}
}
/**
* Determines whether an array is associative or not
* by checking for the presenve of string keys.
*
* @param array
* @return bool
*/
private static function is_assoc( $array ) {
return (bool) count( array_filter( array_keys( $array ), 'is_string' ) );
}
/**
* Returns a hash like array to a query string under a namespace
*
*
* array('foo' => 'bar') // namspace of baz
* baz[foo]=bar
*
*
* @param array $hash
* @param string $namespace
* @return string
*/
private static function assoc_array_to_param( $hash, $namespace = '' ) {
$namespace_array = array_fill( 0, count( $hash ), $namespace );
return implode(
'&',
array_map(
array( 'self', 'assoc_array_to_param_iterator' ),
$hash,
array_keys( $hash ),
$namespace_array
)
);
}
/**
* Because PHP < 5.3 doesn't support anonymous functions, this serves
* as the mapping function for the above method.
*
* @param mixed $value
* @param string $key
* @param string $namespace
* @return string
*/
private static function assoc_array_to_param_iterator( $value, $key, $namespace ) {
$new_key = ( $namespace ? "{$namespace}[$key]" : $key );
return self::to_param( $value, $new_key );
}
/**
* Returns an array paramerterized with a given key
*
*
* array('foo', 'bar', 'baz') // key of hello
* hello[]=foo&hello[]=bar&hello[]=baz
*
*
* This is what is broken in PHP's native `http_build_query`.
* Instead of using empty brackets, it will insert the indices
* of each value instead, which makes it parse as a hash instead
* of an array.
*
* @param array $array
* @param string $key
* @return string
*/
private static function array_to_param( $array, $key ) {
$prefix = "{$key}[]";
$prefix_array = array_fill( 0, count( $array ), $prefix );
return implode( '&', array_map( array( 'self', 'array_to_param_iterator' ), $array, $prefix_array ) );
}
/**
* Because PHP < 5.3 doesn't support anonymous functions, this serves
* as the mapping function for the above method.
*
* @param mixed $value
* @param string $prefix
* @return string
*/
private static function array_to_param_iterator( $value, $prefix ) {
return self::to_param( $value, $prefix );
}
/**
* There's no official pattern for booleans in URLs,
* I though this made the most sense.
*
* @param bool $bool
* @return string
*/
private static function bool_to_param( $bool ) {
return ( $bool ? 'true' : 'false' );
}
}