/** * Deals with the [macro parameters] substitutions * * See the macroList plugin for details * * @param string $text * @return string */ function applyMacros($text) { $content_macros = getMacros(); preg_match_all('/\\[(\\w+)(.*?)\\]/i', $text, $instances); foreach ($instances[0] as $instance => $macro_instance) { $macroname = strtoupper($instances[1][$instance]); if (array_key_exists($macroname, $content_macros)) { $macro = $content_macros[$macroname]; $p = $instances[2][$instance]; $data = NULL; $class = $macro['class']; if ($p) { $p = trim(utf8::sanitize(str_replace(" ", ' ', strip_tags($p)))); // remove hard spaces and invalid characters $p = preg_replace("~\\s+=\\s+(?=(?:[^\"]*+\"[^\"]*+\")*+[^\"]*+\$)~", "=", $p); // deblank assignment operator preg_match_all("~'[^'\"]++'|\"[^\"]++\"|[^\\s]++~", $p, $l); // parse the parameter list $parms = array(); $k = 0; foreach ($l[0] as $s) { if ($s != ',') { $parms[$k++] = trim($s, '\'"'); // remove any quote marks } } } else { $parms = array(); } $parameters = array(); if (!empty($macro['params'])) { $err = false; foreach ($macro['params'] as $key => $type) { $data = false; if (array_key_exists($key, $parms)) { switch (trim($type, '*')) { case 'int': if (is_numeric($parms[$key])) { $parameters[] = (int) $parms[$key]; } else { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be a number.'), trim($macro_instance, '[]'), $key + 1) . '</span>'; $class = 'error'; } break; case 'string': if (is_string($parms[$key])) { $parameters[] = $parms[$key]; } else { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be a string.'), trim($macro_instance, '[]'), $key + 1) . '</span>'; $class = 'error'; } break; case 'bool': switch (strtolower($parms[$key])) { case "true": $parameters[] = true; break; case "false": $parameters[] = false; break; default: $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be <code>true</code> or <code>false</code>.'), trim($macro_instance, '[]'), $key + 1) . '</span>'; $class = 'error'; break; } break; case 'array': $l = array_slice($parms, $key); $parms = array(); foreach ($l as $key => $p) { $x = explode('=', $p); if (count($x) == 2) { $parms[$x[0]] = $x[1]; } else { $parms[$key] = $x[0]; } } $parameters[] = $parms; break; default: $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d is incorrectly defined.'), trim($macro_instance, '[]'), $key + 1) . '</span>'; $class = 'error'; break; } } else { if (strpos($type, '*') === false) { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d is missing.'), trim($macro_instance, '[]'), $key + 1) . '</span>'; $class = 'error'; } break; } } } else { if (!empty($p)) { $class = 'error'; $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> macro does not take parameters'), trim($macro_instance, '[]')) . '</span>'; } } switch ($class) { case 'error': break; case 'function': case 'procedure': if (is_callable($macro['value'])) { if ($class == 'function') { ob_start(); $data = call_user_func_array($macro['value'], $parameters); if (empty($data)) { $data = ob_get_contents(); } ob_end_clean(); } else { ob_start(); call_user_func_array($macro['value'], $parameters); $data = ob_get_contents(); ob_end_clean(); } if (empty($data)) { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> retuned no data'), trim($macro_instance, '[]')) . '</span>'; } else { $data = "\n<!--Begin " . $macroname . "-->\n" . $data . "\n<!--End " . $macroname . "-->\n"; } } else { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> <code>%2$s</code> is not callable'), trim($macro_instance, '[]'), $macro['value']) . '</span>'; } break; case 'constant': $data = "\n<!--Begin " . $macroname . "-->\n" . $macro['value'] . "\n<!--End " . $macroname . "-->\n"; break; case 'expression': $expression = '$data = ' . $macro['value']; $parms = array_reverse($parms, true); preg_match_all('/\\$\\d+/', $macro['value'], $replacements); foreach ($replacements as $rkey => $v) { if (empty($v)) { unset($replacements[$rkey]); } } if (count($parms) == count($replacements)) { foreach ($parms as $key => $value) { $key++; $expression = preg_replace('/\\$' . $key . '/', db_quote($value), $expression); } eval($expression); if (!isset($data) || is_null($data)) { $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> retuned no data'), trim($macro_instance, '[]')) . '</span>'; } else { $data = "\n<!--Begin " . $macroname . "-->\n" . $data . "\n<!--End " . $macroname . "-->\n"; } } else { $data = '<span class="error">' . sprintf(ngettext('<em>[%1$s]</em> takes %2$d parameter', '<em>[%1$s]</em> takes %2$d parameters', count($replacements)), trim($macro_instance, '[]'), count($replacements)) . '</span>'; } break; } $text = str_replace($macro_instance, $data, $text); } } return $text; }