/** * Loads configuration from file and process it. * @return DI\Container */ public function loadConfig($file, $section = NULL) { if ($file === NULL) { $file = $this->defaultConfigFile; } $container = $this->container; $file = $container->expand($file); if (!is_file($file)) { $file = preg_replace('#\\.neon$#', '.ini', $file); // back compatibility } if ($section === NULL) { if (PHP_SAPI === 'cli') { $section = Environment::CONSOLE; } else { $section = $container->params['productionMode'] ? Environment::PRODUCTION : Environment::DEVELOPMENT; } } $cache = new Cache($container->templateCacheStorage, 'Nette.Configurator'); $cacheKey = array((array) $container->params, $file, $section); $cached = $cache->load($cacheKey); if ($cached) { require $cached['file']; fclose($cached['handle']); return $this->container; } $config = Nette\Config\Config::fromFile($file, $section); $code = "<?php\n// source file {$file}\n\n"; // back compatibility with singular names foreach (array('service', 'variable') as $item) { if (isset($config[$item])) { trigger_error(basename($file) . ": Section '{$item}' is deprecated; use plural form '{$item}s' instead.", E_USER_WARNING); $config[$item . 's'] = $config[$item]; unset($config[$item]); } } // process services if (isset($config['services'])) { foreach ($config['services'] as $key => &$def) { if (preg_match('#^Nette\\\\.*\\\\I?([a-zA-Z]+)$#', strtr($key, '-', '\\'), $m)) { // back compatibility $m[1][0] = strtolower($m[1][0]); trigger_error(basename($file) . ": service name '{$key}' has been renamed to '{$m['1']}'", E_USER_WARNING); $key = $m[1]; } if (is_array($def)) { if (method_exists(get_called_class(), "createService{$key}") && !isset($def['factory']) && !isset($def['class'])) { $def['factory'] = array(get_called_class(), "createService{$key}"); } if (isset($def['option'])) { $def['arguments'][] = $def['option']; } if (!empty($def['run'])) { $def['tags'] = array('run'); } } } $builder = new DI\ContainerBuilder(); $code .= $builder->generateCode($config['services']); unset($config['services']); } // consolidate variables if (!isset($config['variables'])) { $config['variables'] = array(); } foreach ($config as $key => $value) { if (!in_array($key, array('variables', 'services', 'php', 'const', 'mode'))) { $config['variables'][$key] = $value; } } // pre-expand variables at compile-time $variables = $config['variables']; array_walk_recursive($config, function (&$val) use($variables) { $val = Configurator::preExpand($val, $variables); }); // add variables foreach ($config['variables'] as $key => $value) { $code .= $this->generateCode('$container->params[?] = ?', $key, $value); } // PHP settings if (isset($config['php'])) { foreach ($config['php'] as $key => $value) { if (is_array($value)) { // back compatibility - flatten INI dots foreach ($value as $k => $v) { $code .= $this->configurePhp("{$key}.{$k}", $v); } } else { $code .= $this->configurePhp($key, $value); } } } // define constants if (isset($config['const'])) { foreach ($config['const'] as $key => $value) { $code .= $this->generateCode('define', $key, $value); } } // set modes - back compatibility if (isset($config['mode'])) { foreach ($config['mode'] as $mode => $state) { trigger_error(basename($file) . ": Section 'mode' is deprecated; use '{$mode}Mode' in section 'variables' instead.", E_USER_WARNING); $code .= $this->generateCode('$container->params[?] = ?', $mode . 'Mode', (bool) $state); } } // pre-loading $code .= self::preloadEnvironment($container); // auto-start services $code .= 'foreach ($container->getServiceNamesByTag("run") as $name => $foo) { $container->getService($name); }' . "\n"; $cache->save($cacheKey, $code, array(Cache::FILES => $file)); Nette\Utils\LimitedScope::evaluate($code, array('container' => $container)); return $this->container; }
/** * Loads configuration from file and process it. * @return DI\Container */ public function loadConfig($file, $section = NULL) { if ($file === NULL) { $file = $this->defaultConfigFile; } $container = $this->container; $file = $container->expand($file); if (!is_file($file)) { $file = preg_replace('#\.neon$#', '.ini', $file); // back compatibility } if ($section === NULL) { if (PHP_SAPI === 'cli') { $section = Environment::CONSOLE; } else { $section = $container->params['productionMode'] ? Environment::PRODUCTION : Environment::DEVELOPMENT; } } $cache = new Cache($container->templateCacheStorage, 'Nette.Configurator'); $cacheKey = array((array) $container->params, $file, $section); $cached = $cache->load($cacheKey); if ($cached) { require $cached['file']; fclose($cached['handle']); return $this->container; } $config = Nette\Config\Config::fromFile($file, $section); $code = "<?php\n// source file $file\n\n"; // back compatibility with singular names foreach (array('service', 'variable') as $item) { if (isset($config[$item])) { trigger_error(basename($file) . ": Section '$item' is deprecated; use plural form '{$item}s' instead.", E_USER_WARNING); $config[$item . 's'] = $config[$item]; unset($config[$item]); } } // add expanded variables while (!empty($config['variables'])) { $old = $config['variables']; foreach ($config['variables'] as $key => $value) { try { $code .= $this->generateCode('$container->params[?] = ?', $key, $container->params[$key] = $container->expand($value)); unset($config['variables'][$key]); } catch (Nette\InvalidArgumentException $e) {} } if ($old === $config['variables']) { throw new InvalidStateException("Unable to expand variables: " . implode(', ', array_keys($old)) . "."); } } unset($config['variables']); // process services if (isset($config['services'])) { foreach ($config['services'] as $key => & $def) { if (preg_match('#^Nette\\\\.*\\\\I?([a-zA-Z]+)$#', strtr($key, '-', '\\'), $m)) { // back compatibility $m[1][0] = strtolower($m[1][0]); trigger_error(basename($file) . ": service name '$key' has been renamed to '$m[1]'", E_USER_WARNING); $key = $m[1]; } if (is_array($def)) { if (method_exists(get_called_class(), "createService$key") && !isset($def['factory']) && !isset($def['class'])) { $def['factory'] = array(get_called_class(), "createService$key"); } if (isset($def['option'])) { $def['arguments'][] = $def['option']; } if (!empty($def['run'])) { $def['tags'] = array('run'); } } } $builder = new DI\ContainerBuilder; /**/$code .= $builder->generateCode($config['services']);/**/ /*5.2* $code .= $this->generateCode('$builder = new '.get_class($builder).'; $builder->addDefinitions($container, ?)', $config['services']);*/ unset($config['services']); } // expand variables array_walk_recursive($config, function(&$val) use ($container) { $val = $container->expand($val); }); // PHP settings if (isset($config['php'])) { foreach ($config['php'] as $key => $value) { if (is_array($value)) { // back compatibility - flatten INI dots foreach ($value as $k => $v) { $code .= $this->configurePhp("$key.$k", $v); } } else { $code .= $this->configurePhp($key, $value); } } unset($config['php']); } // define constants if (isset($config['const'])) { foreach ($config['const'] as $key => $value) { $code .= $this->generateCode('define', $key, $value); } unset($config['const']); } // set modes - back compatibility if (isset($config['mode'])) { trigger_error(basename($file) . ": Section 'mode' is deprecated; use 'params' instead.", E_USER_WARNING); foreach ($config['mode'] as $mode => $state) { $code .= $this->generateCode('$container->params[?] = ?', $mode . 'Mode', (bool) $state); } unset($config['mode']); } // other foreach ($config as $key => $value) { $code .= $this->generateCode('$container->params[?] = ' . (is_array($value) ? 'Nette\ArrayHash::from(?)' : '?'), $key, $value); } // pre-loading $code .= self::preloadEnvironment($container); // auto-start services $code .= 'foreach ($container->getServiceNamesByTag("run") as $name => $foo) { $container->getService($name); }' . "\n"; $cache->save($cacheKey, $code, array( Cache::FILES => $file, )); Nette\Utils\LimitedScope::evaluate($code, array('container' => $container)); return $this->container; }