value, and $args[0] must be
// the associative array with all the name=>value placeholder mappings.
//
// If there was en error while substituting (e.g. type mismatch,
// invalid key etc.), it inserts the plain error message into the
// $tmpl, assigns it to $errormsg and returns false. Otherwise
// returns the template after all substitutions.
function sql_placeholder_ex($tmpl, $args, &$errormsg)
{
// Already compiled?.. If not, compile now.
if (is_array($tmpl)) {
$compiled = $tmpl;
} else {
$compiled = sql_compile_placeholder($tmpl);
}
list ($compiled, $tmpl, $has_named) = $compiled;
// If there are at east one named placeholder, use first
// function argument as replecement array.
if ($has_named) $args = @$args[0];
// Make all the replacements.
$p = 0; // scan position
$out = ''; // resulting string
$error = false; // was any error?
foreach ($compiled as $num=>$e) {
list ($key, $type, $start, $length) = $e;
// Pre-string.
$out .= substr($tmpl, $p, $start - $p);
$p = $start + $length;
$repl = ''; // replacement.
$errmsg = ''; // error message on THIS substitution
do {
// Constant-style placeholder?
if ($type === '#') {
$repl = @constant($key);
if (NULL === $repl)
$error = $errmsg = "UNKNOWN_CONSTANT_$key";
break;
}
// Error handling.
if (!isset($args[$key])) {
$error = $errmsg = "UNKNOWN_PLACEHOLDER_$key";
break;
}
// Insert value corresponding to placeholder type.
$a = $args[$key];
if ($type === '') {
// Scalar-style placeholder.
if (is_array($a)) {
$error = $errmsg = "NOT_A_SCALAR_PLACEHOLDER_$key";
break;
}
$repl = "'".addslashes($a)."'";
break;
}
// Array or hash replacement.
if (!is_array($a)) {
$error = $errmsg = "NOT_AN_ARRAY_PLACEHOLDER_$key";
break;
}
if ($type === '@') {
// List-style placeholder.
foreach ($a as $v)
$repl .= ($repl===''? "" : ",")."'".addslashes($v)."'";
} elseif ($type === '%') {
// Hash-style placeholder.
$lerror = array();
foreach ($a as $k=>$v) {
if (!is_string($k)) {
$lerror[$k] = "NOT_A_STRING_KEY_{$k}_FOR_PLACEHOLDER_$key";
} else {
$k = preg_replace('/[^a-zA-Z0-9_]/', '_', $k);
}
$repl .= ($repl===''? "" : ", ").$k."='".@addslashes($v)."'";
}
// On error makes the reeor message.
if (count($lerror)) {
$repl = '';
foreach ($a as $k=>$v) {
if (isset($lerror[$k])) {
$repl .= ($repl===''? "" : ", ").$lerror[$k];
} else {
$k = preg_replace('/[^a-zA-Z0-9_-]/', '_', $k);
$repl .= ($repl===''? "" : ", ").$k."=?";
}
}
$error = $errmsg = $repl;
}
}
} while (false);
if ($errmsg) $compiled[$num]['error'] = $errmsg;
if (!$error) $out .= $repl;
}
$out .= substr($tmpl, $p);
// If there was an error, re-make the resulting string
// ass error message.
if ($error) {
$out = '';
$p = 0; // scan position
foreach ($compiled as $num=>$e) {
list ($key, $type, $start, $length) = $e;
$out .= substr($tmpl, $p, $start - $p);
$p = $start + $length;
if (isset($e['error'])) {
$out .= $e['error'];
} else {
$out .= substr($tmpl, $start, $length);
}
}
// Last post-string.
$out .= substr($tmpl, $p);
$errormsg = $out;
return false;
} else {
$errormsg = false;
return $out;
}
}
// function sql_placeholder(mixed $tmpl, $arg1 [,$arg2 ...])
//
// Note: see description of sql_placeholder_ex() above.
//
// Returns the template after all substitutions or error message
// prefixed with "ERROR: " string.
//
// If there was en error while substituting (e.g. type mismatch,
// invalid key etc.), it inserts the plain error message into the
// $tmpl and returns the string EXACTLY in form of:
// "ERROR: template_with_error_messages".
// It have to raise SQL error when try to execute the query.
// You may also analyse the return value: if it starts with
// "ERROR: ", the substitution have been aborted.
//
// Instead of using array as the second parameter, you may
// pass all the arguments one by one.
//
// If there are at least one named placeholder in the template,
// function must take exactly two arguments, and $arg1 must be
// the associative array with all the name=>value placeholder
// mappings.
function sql_placeholder()
{
$args = func_get_args();
$tmpl = array_shift($args);
$result = sql_placeholder_ex($tmpl, $args, $error);
if ($result === false) return PLACEHOLDER_ERROR_PREFIX.$error;
else return $result;
}
// function sql_pholder(mixed $tmpl, $arg1 [,$arg2 ...])
//
// Note: see description of sql_placeholder_ex() above.
//
// Returns the template after all substitutions or error message
// prefixed with "ERROR: " string.
//
// Instead of using array as the second parameter, you may
// pass all the arguments one by one.
//
// If there are at least one named placeholder in the template,
// function must take exactly two arguments, and $arg1 must be
// the associative array with all the name=>value placeholder
// mappings.
function sql_pholder()
{
$args = func_get_args();
$tmpl = array_shift($args);
$result = sql_placeholder_ex($tmpl, $args, $error);
if ($result === false) {
$error = "Placeholder substitution error. Diagnostics: \"$error\"";
if (function_exists("debug_backtrace")) {
$bt = debug_backtrace();
$error .= " in ".@$bt[0]['file']." on line ".@$bt[0]['line'];
}
trigger_error($error, E_USER_WARNING);
return false;
}
return $result;
}
// No newline or space after that!
?>