/** * Interpolates a multi-dimensional array with another array recursively * * If no source is given, you get a live interpolation where you can directly interpolate * variables that have just been interpolated before * * Don't fetch the return value, the arrays are references. * If you want an unmutable version, rather take ArrayUtil::interpolate * * This is mostly used for option arrays, e.g. config-files * * We take both arrays as a reference to achieve a live-interpolation effect. * You can work with values you just interpolated before * e.g. [ 'path' => '{{rootPath}}/my/path', 'subPaths' => [ '{{path}}/sub/path' ] ] * * If you want to keep the original array, take a copy before * * @param array $array The array to interpolate (Passed by reference) * @param array|null $source The source array for variables. If none given, the input array is taken * @param null $defaultValue The default value for indices that couldnt be resolved * @param string $delimeter The delimeter used for multi-dimension access (Default: Dot (.)) * * @return array The interpolated array (Notice that it's just the same reference to the array you passed */ public static function interpolateMutable(array &$array, array &$source = null, $defaultValue = null, $delimeter = null) { if (!$source) { $source =& $array; } $newKeys = []; foreach ($array as $key => &$val) { if (is_string($key)) { $newKey = StringUtil::interpolate($key, $source, $defaultValue, $delimeter); if ($key !== $newKey) { $newKeys[$key] = $newKey; } } if (is_array($val)) { self::interpolateMutable($val, $source, $defaultValue, $delimeter); } else { if (is_string($val)) { $array[$key] = StringUtil::interpolate($val, $source, $defaultValue, $delimeter); } } } foreach ($newKeys as $key => $newKey) { $array[$newKey] = $array[$key]; unset($array[$key]); } return $array; }
public function init() { $this->prependOptions(['defaultController' => 'index', 'defaultAction' => 'index', 'defaultId' => null, 'defaultFormat' => 'html', 'formats' => ['html', 'json'], 'routeOnRun' => true, 'baseUrl' => null, 'routes' => ['/:controller?/:action?/:id?.:format?' => ["@router", 'dispatchController']]]); $app = $this->getApp(); $app->bind('beforeRun', function () { $routes = $this->getOption('routes'); //Parse route targets foreach ($routes as $route => $callback) { if (is_array($callback) && is_string($callback[0])) { $target = $callback[0]; if ($target[0] !== '@') { break; } $handler = $callback[1]; $target = substr($target, 1); switch ($target) { case 'router': $routes[$route][0] = $this; break; default: $routes[$route] = function (array $routeData) use($target, $handler) { $routeData = call_user_func([$target, $handler], $routeData); return $this->dispatchController($routeData); }; } } } if (isset($this->controller)) { /** * @var \Tale\App\Feature\Controller $controller */ $controller = $this->controller; $controller->registerHelper('getUrl', function ($controller, $path = null, array $args = null, $preserveQuery = false) { $path = $path ? $path : ''; if (isset($controller->request)) { /** * @var \Tale\App\Feature\Controller\Request $req */ $req = $controller->request; $path = StringUtil::interpolate($path, ['controller' => $req->getController(), 'action' => $req->getAction(), 'args' => $req->getArgs(), 'format' => $req->getFormat()]); } $url = $path; $baseUrl = $this->getOption('baseUrl'); if ($baseUrl) { $url = rtrim($baseUrl, '/') . '/' . ltrim($path, '/'); } $query = []; if ($args) { $query = $args; } if ($preserveQuery && isset($controller->webRequest)) { $query = array_replace_recursive($controller->webRequest->getUrlArgs(), $query); } if (!empty($query)) { $url .= '?' . http_build_query($query); } return $url; }); $controller->registerHelper('redirect', function ($controller, $path, array $args = null, $preserveQuery = null) { return new Controller\Response\Redirect($controller->getUrl($path, $args, $preserveQuery)); }); } $this->_router = new AppRouter($routes); }); $app->bind('run', function () use($app) { if ($this->getOption('routeOnRun')) { if ($app->isCliApp()) { $this->routeCliRequest(); } else { $response = $this->routeHttpServerRequest(); $response->apply(); } } }); $app->bind('afterRun', function () { unset($this->_router); }); }