/** * Pre-expands %placeholders% in string. * @internal */ public static function preExpand($s, array $params, $check = array()) { if (!is_string($s)) { return $s; } $parts = preg_split('#%([\\w.-]*)%#i', $s, -1, PREG_SPLIT_DELIM_CAPTURE); $res = ''; foreach ($parts as $n => $part) { if ($n % 2 === 0) { $res .= str_replace('%', '%%', $part); } elseif ($part === '') { $res .= '%%'; } elseif (isset($check[$part])) { throw new Nette\InvalidArgumentException('Circular reference detected for variables: ' . implode(', ', array_keys($check)) . '.'); } else { try { $val = Nette\Utils\Arrays::get($params, explode('.', $part)); } catch (Nette\InvalidArgumentException $e) { $res .= "%{$part}%"; continue; } $val = self::preExpand($val, $params, $check + array($part => 1)); if (strlen($part) + 2 === strlen($s)) { if (is_array($val)) { array_walk_recursive($val, function (&$val) use($params, $check, $part) { $val = Configurator::preExpand($val, $params, $check + array($part => 1)); }); } return $val; } if (!is_scalar($val)) { throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '{$part}' into '{$s}'."); } $res .= $val; } } return $res; }