<?php
/**
* Various tools for array conversion (PHP5+)
*
* The library makes use of a number of constants, ensure these contants arn't
* already defined in your scripts.
*
* This library is entierly stand-alone, however does require you run at least
* PHP5, and at least 5.1.0 for full functionallity.
*
* @license http://creativecommons.org/licenses/by-sa/2.5/au
* @author Stephen Ingram <hide@address.com>
* @copyright Copyright (c) 2009, Margni Group
* @category library
* @package arrayto
*/
/**
* Constant flag for arrayto::ini() so that "sections" will not be created.
*
* @see arrayto::ini()
*/
define('AT_INI_NO_SECTIONS', 1);
/**
* Constant flag for arrayto::dsv() so that a title row will not be generated
* regardless of the input array.
*
* @see arrayto::dsv()
*/
define('AT_DSV_NO_TITLE', 1);
/**
* Constant flag for arrayto::dsv() so that CSV style escaping will not be
* applied.
*
* @see arrayto::dsv()
*/
define('AT_DSV_NO_CSV', 2);
/**
* Library of static methods for converting an array into a variety of formats.
*
* @category library
* @package arrayto
*/
class arrayto
{
/**
* Convert array into ini file format
*
* This creates an ini file suitable for php's parse_ini_file() function.
*
* It is suggested that if an ini file contains sensitive information it
* should use a php extention and be wrapped in a php comment so that if it
* is accessed directly it will not leak such information. Only *nix style
* newlines are used (\n).
*
* @param array $a Array to convert
* @param int $flags Additional options may be specified via the use of
* pre-defined constants. The value of flags can be any
* combination of the following flags, joined with the
* binary OR (|) operator. Available Flags:
* - {@link AT_INI_NO_SECTIONS}: Sections will not be
* created.
*
* @return string INI document, generally ready to be saved to a file.
*/
public static function ini(array $a, $flags = 0)
{
$process_sections = (AT_INI_NO_SECTIONS & $flags
? false
: true
);
if (!is_array($a))
return;
$ret = '';
foreach($a as $k => $v) if (!is_array($v)) {
$ret .= "$k=";
switch($v) {
case is_bool($v):
$ret .= ($v
? 'true'
: 'false'
);
break;
case is_int($v):
case is_float($v):
$ret .= $v;
break;
default:
$ret .= '"'
. str_replace('\\', '\\\\',
str_replace('"', '\"', $v)
)
. '"';
}
$ret .= "\n";
} elseif ($process_sections) {
$ret .= "[$k]\n" . arrayto::ini($v, AT_INI_NO_SECTIONS);
} else {
return self::_error('arrayto::ini(): Ini files only support an array
to a maximum depth of 2.');
}
return $ret;
}
/**
* Convert array into php script
*
* Turn an array into php script defining the array and its contents.
* Variable definition and PHP tags are optional. This method utilizes PHP's
* var_export() function and as such has some draw backs. Prior to PHP 5.1.0
* this will not be able to store nested referances. For complex structures
* you should consider serialize() or simply a different approach.
*
* Suggested use for caching configuration settings from a database into php
* for less resource intensive initialization. Function is recursive for any
* depth array. The output is not particularly human readable as newlines
* and indentation are omitted.
*
* @param array $array Array, any depth, any configuration.
* @param string|NULL $varname Optional, array may be assigned to a
* variable. Defaults to NULL (no variable
* created). If this is used a semicolon will
* also be appended after the array definition.
* @param bool $tags Wrap the array in PHP tags? This is only
* useful when the second argument is also used.
* As such this defaults TRUE. However the
* definition will not be wrapped in PHP tags
* unless the second argument is not null.
* Closing tag is ommitted. Uses full opening
* tag format (<?php)
*
* @return string PHP array defenition, generally ready to be saved into a
* php file.
*/
public static function php(array $array, $varname = null, $tags = null)
{
if ($varname && is_null($tags))
$tags = true;
$ret = ($tags
? "<?php\n"
: ''
);
if ($varname)
$ret .= "$$varname = ";
$ret .= var_export($array);
if ($varname)
$ret .= ';';
return $ret;
}
/**
* Convert array into DSV
*
* 2D arrays will be converted into a simple delimiter-separated values
* format. Delimiter and newline may be specified. If the first array
* contians non-numeric keys a row of column names will be created, unless
* the functionallity is disabled. The default format is rfc4180, or, CSV
* standard for producing "text/csv" files.
*
* If you want to have more control over the title row that must be
* generated seperatley.
*
* @param array $a Numerically indexed 2D array to convert. Each
* value must be a flat array indexd in any manor.
* All 2nd level arrays should be the same length
* otherwise you may not produce a valid DSV file.
* @param string $delimiter Delimiter, defaults to ","
* @param string $newline Newline format, defaults to "CRLF" (\r\n)
* @param int $flags Additional options may be specified via the use
* of pre-defined constants. The value of flags can
* be any combination of the following flags,
* joined with the binary OR (|) operator.
* Available Flags:
* - {@link AT_DSV_NO_TITLE}: A title row will not
* be generated regardless of the input array.
* - {@link AT_DSV_NO_CSV}: CSV style escaping will
* not be applied.
*
* @return string DSV document, generally ready to be saved to a file.
*/
public static function dsv(array $a, $delimiter = ',', $newline = "\r\n", $flags = 0)
{
$title_row = (AT_DSV_NO_TITLE & $flags
? false
: true
);
$format_csv = (AT_DSV_NO_CSV & $flags
? false
: true
);
if (!isset($a[0]))
return self::_error('arrayto::dsc() Must supply a numerically
indexed array starting at 0.');
$delim_length_offset = strlen($delimiter) * -1;
$ret = '';
if ($title_row) {
$ak = array_keys($a[0]);
if (!is_numeric($ak[0])) {
foreach($a[0] as $k => $v)
$ret .= $k . $delimiter;
$ret = substr($ret, 0, $delim_length_offset) . $newline;
}
}
foreach($a as $a2) {
foreach($a2 as $v)
$ret .= (!is_array($v)
? ($format_csv
? (is_numeric($v)
? (strpos(',', $v) !== false
? $v
: '"' . $v . '"'
)
: '"' . str_replace('"', '""', (string)$v) . '"'
)
: $v
)
: 'Array'
)
. $delimiter;
$ret = substr($ret, 0, $delim_length_offset) . $newline;
}
return $ret;
}
/**
* Conveniance method to substitute PHP's trigger_error() function. Always
* returns FALSE.
*
* @param string $error_msg The designated error message for this error.
* It's limited to 1024 characters in length. Any
* additional characters beyond 1024 will be
* truncated.
* @param int $error_type The designated error type for this error. It
* only works with the E_USER family of constants,
* and will default to E_USER_ERROR.
* @return false Unlike PHP's trigger_error() function this method will
* always return false.
*/
private static function _error($error_msg, $error_type = E_USER_ERROR)
{
trigger_error((string)$error_msg, $error_type);
return false;
}
}