While those three environments are the most common, you can create any arbitrary environment
with any set of configuration, for example:
embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(1-3)
You can then retrieve the configurations using the key name. The correct configuration is
returned, automatically accounting for the current environment:
embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(15-15)
Environment also works with subclasses of Adaptable, allowing you to maintain separate
configurations for database servers, cache adapters, and other environment-specific classes, for
example:
Connections::add('default', array(
'production' => array(
'type' => 'database',
'adapter' => 'MySql',
'host' => 'db1.application.local',
'login' => 'secure',
'password' => 'secret',
'database' => 'app-production'
),
'development' => array(
'type' => 'database',
'adapter' => 'MySql',
'host' => 'localhost',
'login' => 'root',
'password' => '',
'database' => 'app'
)
));
This allows the database connection named 'default' to be connected to a local database in
development, and a production database in production. You can define environment-specific
configurations for caching, logging, even session storage, i.e.:
Cache::config(array(
'userData' => array(
'development' => array('adapter' => 'File'),
'production' => array('adapter' => 'Memcache')
)
));
When the cache configuration is accessed in the application's code, the correct configuration is
automatically used:
$user = User::find($request->id);
Cache::write('userData', "User.{$request->id}", $user->data(), '+5 days');
In this configuration, the above example will automatically send cache writes to the file
system during local development, and to a memcache server in production.
When writing classes that connect to other external resources, you can automatically take
advantage of environment-specific configurations by extending Adaptable and implementing
your resource-handling functionality in adapter classes.
In addition to managing your environment-specific configurations, Environment will also help
you by automatically detecting which environment your application is running in. For additional
information, see the documentation for Environment::is().
public static function config($name = null) { if (empty(self::$_config)) { $config = Libraries::get('li3_varnish'); $env = Environment::get(); if (isset($config[$env])) { $config += $config[$env]; unset($config[$env]); } foreach ($config as $k => $v) { if (isset(self::$_defaults[$k]) && is_array(self::$_defaults[$k])) { $config[$k] += self::$_defaults[$k]; } } self::$_config = $config + self::$_defaults; } if (isset($name)) { if (isset(self::$_config[$name])) { return self::$_config[$name]; } else { return null; } } return self::$_config; }
/** * Return an instance of the Mandrill class. * * @return Mandrill Instance. */ public static function getInstance() { // Detect when the PID of the current process has changed (from a fork, etc) // and force a reconnect to redis. $pid = getmypid(); if (self::$pid !== $pid) { self::$mandrill = null; self::$pid = $pid; } if (!is_null(self::$mandrill)) { return self::$mandrill; } foreach (array_keys(self::$config) as $param) { if (Environment::get('mandrill.' . $param)) { self::$config[$param] = Environment::get('mandrill.' . $param); } } if (!self::$config['apikey']) { throw new Exception('missing Mandrill Configuration', 500); } try { self::$mandrill = new Mandrill(self::$config['apikey']); } catch (Exception $e) { return null; } return self::$mandrill; }
public function getkycinfo() { $email = strtolower($this->request->query['email']); $kycid = $this->request->query['kycid']; if (substr(Environment::get('locale'), 0, 2) == "en") { $locale = "en"; } else { $locale = Environment::get('locale'); } if ($email == "" || $kycid == "") { return $this->render(array('json' => array('success' => 0))); } $document = Documents::find('first', array('conditions' => array('email' => $email, 'email_code' => $kycid))); $encrypt = $document['hash']; // print_r($function->decrypt($encrypt,CONNECTION_DB_KYC)); if (count($document) == 1) { if ($emails['Verify']['Score'] >= 80) { return $this->render(array('json' => array('success' => 0, 'reason' => 'Aleredy KYC complete'))); } else { return $this->render(array('json' => array('success' => 1, 'id' => $encrypt, 'locale' => $locale))); } } else { return $this->render(array('json' => array('success' => 0))); } }
protected static function _config($model, Behavior $behavior, array $config, array $defaults) { $config += $defaults; if (!$config['locale']) { $config['locale'] = Environment::get('locale'); } if (!$config['locales']) { $config['locales'] = array_keys(Environment::get('locales')); } if (!$config['strategy']) { $connection = get_class($model::connection()); $config['strategy'] = $connection::enabled('arrays') ? 'nested' : 'inline'; } if ($config['strategy'] === 'inline') { foreach ($config['fields'] as $field) { foreach ($config['locales'] as $locale) { if ($locale === $config['locale']) { continue; } if (!$model::hasField($field = static::_composeField($field, $locale))) { throw new Exception("Model `{$model}` is missing translation field `{$field}`"); } } } } return $config; }
public function __construct($options = array()) { $this->_library = Libraries::get('li3_hierarchy'); $this->_cacheDir = $this->_library['path'] . '/resources/tmp/cache'; $defaults['cache'] = Environment::get() == 'production' ? true : false; $this->_options = $this->_library + $defaults; $this->_cache = $this->_options['cache']; }
/** * Constructor for this adapter - sets relevant default configurations for Twig to be used * when instantiating a new Twig_Environment and Twig_Loader_Filesystem. * * @param array $config Optional configuration directives. * Please see http://www.twig-project.org/book/03-Twig-for-Developers for all * available configuration keys and their description. * There are 4 settings that is set * - `cache`: Path to /resources/tmp/cache/templates/ where compiled templates will be stored * - `auto_reload`: If Environment is not production, templates will be reloaded once edited * - `base_template_class`: Overriden to the Template adapter, be carefull with changing this * - `autoescape`: Set to false because the way we inject content is with full html that should not be escaped * @return void */ public function __construct(array $config = array()) { /** * TODO Change hardcoded LITHIUM_APP_PATH to be dynamic */ $defaults = array('cache' => LITHIUM_APP_PATH . '/resources/tmp/cache/templates', 'auto_reload' => !Environment::is('production'), 'base_template_class' => 'li3_twig\\template\\view\\adapter\\Template', 'autoescape' => false); parent::__construct($config + $defaults); }
public function testEnvironmentalDefaults() { $artist = Artists::create(['ja.name' => 'Richard Japper', 'ja.profile' => 'Dreaded Rasta Nihon', 'en.name' => 'Richard', 'en.profile' => 'Dreaded Rasta', 'something_else' => 'Something']); Environment::set('test', ['locales' => ['en' => 'English', 'es' => 'Espanol']]); $artist->_actsAs = ['Translatable' => ['default' => 'ja', 'fields' => ['name', 'profile']]]; $this->assertTrue($artist->save()); $artist = Artists::first(); }
protected function _init() { parent::_init(); Environment::set($this->env); if (file_exists($this->_config['routes'])) { return require $this->_config['routes']; } $this->error("The routes file for this library doesn't exist or can't be found."); }
/** * Configures this helper */ public static function config($config = array()) { $defaults = array('optimize' => Environment::get() == 'production', 'debug' => Environment::get() == 'development', 'stylesPath' => LITHIUM_APP_PATH . DIRECTORY_SEPARATOR . 'webroot' . DIRECTORY_SEPARATOR . 'css', 'scriptsPath' => LITHIUM_APP_PATH . DIRECTORY_SEPARATOR . 'webroot' . DIRECTORY_SEPARATOR . 'js', 'filters' => array()); $config += $defaults; // Merge config static::$config = array_merge(static::$config, $config); // Configure filters static::registerFilters($config['filters']); }
/** * * Determines if we should run any `newrelic_` methods. * * If the configuration for the plugin `shouldRun` does not exist, set * a generic one. * * @return bool */ public static function shouldRun() { if (!is_callable(Libraries::get('li3_newrelic', 'shouldRun'))) { $config = Libraries::get('li3_newrelic'); $config['shouldRun'] = function () { return Environment::is('production') && extension_loaded('newrelic'); }; Libraries::add('li3_newrelic', $config); } return Libraries::get('li3_newrelic', 'shouldRun')->__invoke(); }
/** * Auto run the help command. * * @param string $command Name of the command to return help about. * @return void */ public function run($command = null) { $message = 'Lithium console started in the ' . Environment::get() . ' environment.'; $message .= ' Use the --env=environment key to alter this.'; $this->out($message); if (!$command) { $this->_renderCommands(); return true; } if (!preg_match('/\\\\/', $command)) { $command = ucwords($command); } if (!($class = Libraries::locate('command', $command))) { $this->error("Command `{$command}` not found"); return false; } $command = Inflector::classify($command); if (strpos($command, '\\') !== false) { $command = join('', array_slice(explode("\\", $command), -1)); } $command = strtolower(Inflector::slug($command)); $run = null; $methods = $this->_methods($class); $properties = $this->_properties($class); $info = Inspector::info($class); $this->out('USAGE', 'heading'); if (isset($methods['run'])) { $run = $methods['run']; unset($methods['run']); $this->_renderUsage($command, $run, $properties); } foreach ($methods as $method) { $this->_renderUsage($command, $method); } if (!empty($info['description'])) { $this->nl(); $this->_renderDescription($info); $this->nl(); } if ($properties || $methods) { $this->out('OPTIONS', 'heading'); } if ($run) { $this->_render($run['args']); } if ($methods) { $this->_render($methods); } if ($properties) { $this->_render($properties); } return true; }
/** * Create an entity manager * * @param array $params Parameters * @return object Entity manager * @filter */ protected function createEntityManager() { $configuration = Setup::createAnnotationMetadataConfiguration([$this->_config['models']], Environment::is('development'), $this->_config['proxies'], isset($this->_config['cache']) ? call_user_func($this->_config['cache']) : null); $configuration->setProxyNamespace($this->_config['proxyNamespace']); $eventManager = new EventManager(); $eventManager->addEventListener([Events::postLoad, Events::prePersist, Events::preUpdate], $this); $connection = $this->connectionSettings; $params = compact('connection', 'configuration', 'eventManager'); return $this->_filter(__METHOD__, $params, function ($self, $params) { return EntityManager::create($params['connection'], $params['configuration'], $params['eventManager']); }); }
protected function _verify($request) { $config = Environment::get('service.recaptcha'); $url = 'https://www.google.com/recaptcha/api/siteverify'; $url .= '?secret=' . $config['secretKey']; $url .= '&response=' . $this->request->data['token']; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = json_decode(curl_exec($ch), true); curl_close($ch); return $result['success'] === true; }
public function _init() { parent::_init(); $this->_config = Libraries::get('li3_frontender'); $defaults = array('compress' => false, 'assets_root' => LITHIUM_APP_PATH . "/webroot", 'production' => Environment::get() == 'production', 'locations' => array('node' => '/usr/bin/node', 'coffee' => '/usr/bin/coffee')); $this->_config += $defaults; $this->_production = $this->_config['production']; // remove extra slash if it was included in the library config $this->_config['assets_root'] = substr($this->_config['assets_root'], -1) == "/" ? substr($this->_config['assets_root'], 0, -1) : $this->_config['assets_root']; $this->_paths['styles'] = $this->_config['assets_root'] . "/css/"; $this->_paths['scripts'] = $this->_config['assets_root'] . "/js/"; }
public function sendLoggedQueries() { if ($this->key) { KM::$key = $this->key; } if ($this->logdir) { KM::$log_dir = $this->logdir; } $this->header('Kissmetrics'); $this->out(" - Using Environment: \t" . Environment::get()); $this->out(" - Using log_dir: \t" . KM::$log_dir); $this->out("\nSending..."); KM::send_logged_queries(); }
protected function setUp() { if (empty($this->host)) { $this->host = Environment::get('resque.host'); } if (empty($this->host)) { $this->host = 'localhost'; } if (empty($this->port)) { $this->port = Environment::get('resque.port'); } if (empty($this->port)) { $this->port = 6379; } ResqueProxy::setBackend($this->host . ':' . $this->port); $this->queues = ResqueProxy::queues(); }
/** * Runs a test group or a specific test file based on the passed * parameters. * * @param string $group If set, this test group is run. If not set, a group test may * also be run by passing the 'group' option to the $options parameter. * @param array $options Options array for the test run. Valid options are: * - 'case': The fully namespaced test case to be run. * - 'group': The fully namespaced test group to be run. * - 'filters': An array of filters that the test output should be run through. * @return array A compact array of the title, an array of the results, as well * as an additional array of the results after the $options['filters'] * have been applied. * @filter */ public static function run($group = null, array $options = array()) { $defaults = array('title' => $group, 'filters' => array(), 'reporter' => 'text'); $options += $defaults; $isCase = is_string($group) && preg_match('/Test$/', $group); $items = $isCase ? array(new $group()) : (array) $group; $options['filters'] = Set::normalize($options['filters']); $group = static::_group($items); $report = static::_report($group, $options); return static::_filter(__FUNCTION__, compact('report'), function ($self, $params, $chain) { $environment = Environment::get(); Environment::set('test'); $params['report']->run(); Environment::set($environment); return $params['report']; }); }
/** * * @return void */ public static function __init() { $libraryConfig = Libraries::get('li3_resque'); static::config($libraryConfig + static::$_defaults); if (Environment::get('resque.host')) { static::$_config['host'] = Environment::get('resque.host'); } if (Environment::get('resque.port')) { static::$_config['port'] = Environment::get('resque.port'); } if (!empty(static::$_config['host']) || !empty(static::$_config['port'])) { try { Resque::setBackend(static::$_config['host'] . ':' . static::$_config['port']); } catch (Exception $e) { throw new ConfigException('Could not connect to Resque server'); } } }
public static function terminate() { static::initSession(); static::initAuth(); static::$_data['end'] = microtime(true); static::$_data['environment'] = Environment::get(); static::$_data['events.count'] = count(static::$_data['events']); static::$_data['db.count'] = count(static::$_data['db']); static::$_data['runtime'] = static::$_data['end'] - static::$_data['start']; static::$_data['memory.end'] = memory_get_usage(true); static::$_data['memory.usage'] = memory_get_peak_usage(true); static::$_data['log.count'] = count(static::$_data['log']); if (!Environment::is('production') && static::$_view) { try { echo static::$_view->render(array('element' => 'debug_bar')); } catch (\lithium\template\TemplateException $e) { $view = new View(array('paths' => array('element' => '{:library}/views/elements/{:template}.{:type}.php'))); echo $view->render(array('element' => 'debug_bar'), array(), array('library' => 'li3_debug')); } } }
/** * Dispatches a request based on a request object (an instance of `lithium\console\Request`). * If `$request` is `null`, a new request object is instantiated based on the value of the * `'request'` key in the `$_classes` array. * * @param object $request An instance of a request object with console request information. If * `null`, an instance will be created. * @param array $options * @return object The command action result which is an instance of `lithium\console\Response`. * @filter */ public static function run($request = null, $options = array()) { $defaults = array('request' => array()); $options += $defaults; $classes = static::$_classes; $params = compact('request', 'options'); return static::_filter(__FUNCTION__, $params, function ($self, $params) use($classes) { $request = $params['request']; $options = $params['options']; $router = $classes['router']; $request = $request ?: new $classes['request']($options['request']); $request->params = $router::parse($request); $params = $self::applyRules($request->params); Environment::set($request); try { $callable = $self::invokeMethod('_callable', array($request, $params, $options)); return $self::invokeMethod('_call', array($callable, $request, $params)); } catch (UnexpectedValueException $e) { return (object) array('status' => $e->getMessage() . "\n"); } }); }
/** * Gets an array of settings for the given named configuration in the current * environment. * * @see lithium\core\Environment * @param string $name Name of the configuration. * @return array Settings of the named configuration. */ public function get($name = null) { if ($name === null) { $result = array(); $this->_configurations = array_filter($this->_configurations); foreach ($this->_configurations as $key => $value) { $result[$key] = $this->get($key); } return $result; } $settings =& $this->_configurations; if (!isset($settings[$name])) { return null; } if (isset($settings[$name][0])) { return $settings[$name][0]; } $env = Environment::get(); $config = isset($settings[$name][$env]) ? $settings[$name][$env] : $settings[$name]; $method = is_callable($this->initConfig) ? $this->initConfig : null; $settings[$name][0] = $method ? $method($name, $config) : $config; return $settings[$name][0]; }
/** * Translates a message according to the current or provided locale * and into it's correct plural form. * * Usage: * {{{ * Message::translate('Mind the gap.'); * Message::translate('house', array('count' => 23)); * }}} * * `String::insert()`-style placeholders may be used within the message * and replacements provided directly within the `options` argument. * * Example: * {{{ * Message::translate('I can see {:count} bike.'); * Message::translate('This painting is {:color}.', array( * 'color' => Message::translate('silver'), * )); * }}} * * @see lithium\util\String::insert() * @param string $id The id to use when looking up the translation. * @param array $options Valid options are: * - `'count'`: Used to determine the correct plural form. You can either pass * a signed or unsigned integer, the behavior when passing other types * is yet undefined. * The count is made absolute before being passed to the pluralization * function. This has the effect that that with i.e. an English * pluralization function passing `-1` results in a singular * translation. * - `'locale'`: The target locale, defaults to current locale. * - `'scope'`: The scope of the message. * - `'default'`: Is used as a fall back if `_translated()` returns * without a result. * - `'noop'`: If `true` no whatsoever lookup takes place. * @return string|void The translation or the value of the `'default'` option if none * could be found. */ public static function translate($id, array $options = array()) { $defaults = array('count' => 1, 'locale' => Environment::get('locale'), 'scope' => null, 'default' => null, 'noop' => false); extract($options + $defaults); if ($noop) { $result = null; } else { $result = static::_translated($id, abs($count), $locale, compact('scope')); } if ($result || $default) { return String::insert($result ?: $default, $options); } }
<?php use lithium\core\Environment; if (substr(Environment::get('locale'), 0, 2) == "en") { $locale = "en"; } else { $locale = Environment::get('locale'); } //if(strlen($locale>2)){$locale='en';} // print_r(Environment::get('locale')); // print_r($locale); ?> <div class="well"> </div> <div><h3><?php echo $t('Privacy Policy'); ?> </h3></div> <div class="container-fluid"><p> </p> <p><?php echo $t('This Privacy Policy explains how information about you is collected, used and disclosed by'); ?> <strong>GreenCoinX Inc.</strong> <?php echo $t('doing business as XGC Wallet'); ?> ("<strong><?php echo $t('we'); ?> </strong>" <?php echo $t('or'); ?> "<strong><?php
}); /** * Integration with `Validator`. You can load locale dependent rules into the `Validator` * by specifying them manually or retrieving them with the `Catalog` class. */ foreach (array('phone', 'postalCode', 'ssn') as $name) { Validator::add($name, Catalog::read(true, "validation.{$name}", 'en_US')); } /** * Intercepts dispatching processes in order to set the effective locale by using * the locale of the request or if that is not available retrieving a locale preferred * by the client. */ ActionDispatcher::applyFilter('_callable', function ($self, $params, $chain) { $request = $params['request']; $controller = $chain->next($self, $params, $chain); if (!$request->locale) { $request->params['locale'] = Locale::preferred($request); } Environment::set(Environment::get(), array('locale' => $request->locale)); return $controller; }); ConsoleDispatcher::applyFilter('_callable', function ($self, $params, $chain) { $request = $params['request']; $command = $chain->next($self, $params, $chain); if (!$request->locale) { $request->params['locale'] = Locale::preferred($request); } Environment::set(Environment::get(), array('locale' => $request->locale)); return $command; });
*/ Router::connect('/', 'Pages::view'); /** * Connect the rest of `PagesController`'s URLs. This will route URLs like `/pages/about` to * `PagesController`, rendering `/views/pages/about.html.php` as a static page. */ Router::connect('/pages/{:args}', 'Pages::view'); /** * ### Testing routes * * Add the testing routes. These routes are only connected in non-production environments, and allow * browser-based access to the test suite for running unit and integration tests for the Lithium * core, as well as your own application and any other loaded plugins or frameworks. Browse to * [http://path/to/app/test](/test) to run tests. */ if (!Environment::is('production')) { Router::connect('/test/{:args}', array('controller' => 'lithium\\test\\Controller')); Router::connect('/test', array('controller' => 'lithium\\test\\Controller')); } /** * ### Database object routes * * The routes below are used primarily for accessing database objects, where `{:id}` corresponds to * the primary key of the database object, and can be accessed in the controller as * `$this->request->id`. * * If you're using a relational database, such as MySQL, SQLite or Postgres, where the primary key * is an integer, uncomment the routes below to enable URLs like `/posts/edit/1138`, * `/posts/view/1138.json`, etc. */ // Router::connect('/{:controller}/{:action}/{:id:\d+}.{:type}', array('id' => null));
/** * Tests calling `get()` and `set()` with `true` as the envrionment name, to automatically * select the current environment. * * @return void */ public function testReadWriteWithDefaultEnvironment() { Environment::set('development'); Environment::set(true, array('foo' => 'bar')); $this->assertEqual(array('foo' => 'bar'), Environment::get('development')); $this->assertEqual(Environment::get(true), Environment::get('development')); Environment::set('production'); $this->assertFalse(Environment::get(true)); }
use Airbrake\Connection; use Airbrake\EventHandler; use Airbrake\Exception; use Airbrake\Notice; use Airbrake\Record; use Airbrake\Version; $_config = Libraries::get('li3_airbrake'); if (isset($_config['apiKey']) && !empty($_config['apiKey'])) { if (!isset($_config['notifyOnWarning']) || empty($_config['notifyOnWarning'])) { $_config['notifyOnWarning'] = (bool) (E_NOTICE & error_reporting()); } if (!isset($_config['options'])) { $_config['options'] = array(); } if (!isset($_config['options']['environmentName']) || empty($_config['options']['environmentName'])) { $_config['options']['environmentName'] = Environment::get(); } if (!isset($_config['options']['projectRoot']) || empty($_config['options']['projectRoot'])) { $_config['options']['projectRoot'] = LITHIUM_APP_PATH; } // Setup Airbrake $config = new Configuration($_config['apiKey'], $_config['options']); $client = new Client($config); $handler = new EventHandler($client, (bool) $_config['notifyOnWarning']); // Apply Error handler set_error_handler(function ($errno, $errstr, $errfile = null, $errline = 0, array $errcontext = array()) use($handler) { $handler->onError($errno, $errstr, $errfile, $errline, $errcontext); }); // Apply Exception handler // $previousExceptionHandler = set_exception_handler(); // set_exception_handler(function($exception) use ($handler, $previousExceptionHandler) {
/** * Executes a given task with the given set of arguments. * Called by li3_gearman deamon * * @param string $task Fully qualified task name * @param array $args Arguments for the call * @param array $env Environment settings to merge on $_SERVER * @param array $workload Full workload * @return mixed Returned value */ public function execute($task, array $args = [], array $env = [], array $workload = []) { if (!is_callable($task)) { throw new RuntimeException("Invalid task {$task}"); } $workload += ['id' => null, 'background' => false]; try { $status = $this->getStatus($workload['id']); } catch (Exception $e) { } if (!empty($status) && $status != static::STATUS_PENDING) { throw new Exception("Job #{$workload['id']} not on pending status. Status: {$status}"); } if (array_key_exists('environment', $env)) { Environment::set($env['environment']); unset($env['environment']); } if (!empty($env)) { $_SERVER = $env + $_SERVER; } $result = null; try { $this->setStatus($workload['id'], static::STATUS_RUNNING); if (isset($this->_config['beforeExecute']) && is_callable($this->_config['beforeExecute'])) { call_user_func_array($this->_config['beforeExecute'], [$task, $args]); } $result = call_user_func_array($task, $args); $this->setStatus($workload['id'], static::STATUS_FINISHED); if (isset($this->_config['afterExecute']) && is_callable($this->_config['afterExecute'])) { call_user_func_array($this->_config['afterExecute'], [$task, $args]); } } catch (Exception $e) { error_log('[' . date('r') . '] ' . $e->getMessage()); $this->setStatus($workload['id'], static::STATUS_ERROR); if (isset($this->_config['afterExecute']) && is_callable($this->_config['afterExecute'])) { call_user_func_array($this->_config['afterExecute'], [$task, $args]); } if (isset($this->_config['onException']) && is_callable($this->_config['onException'])) { call_user_func_array($this->_config['onException'], [$task, $args, $e]); } if (!empty($workload['retries']) && !empty($workload['retries']['maximum']) && $workload['retry'] < $workload['retries']['maximum']) { $this->run($task, $args, ['schedule' => new DateTime('now +' . $workload['retries']['increment'][$workload['retry']], new DateTimeZone('UTC')), 'retry' => $workload['retry'] + 1, 'retries' => $workload['retries']] + array_intersect_key($workload, ['configName' => null, 'env' => null, 'background' => null])); } throw $e; } return $result; }
public function match(array $options = array(), $context = null) { $locale = Environment::get('locale'); return parent::match($options + compact('locale'), $context); }
<?php /** * Lithium: the most rad php framework * * @copyright Copyright 2012, Union of Rad, Inc. (http://union-of-rad.org) * @license http://opensource.org/licenses/bsd-license.php The BSD License */ use lithium\core\Environment; ?> <div id="locale-navigation"> <ul> <?php foreach (Environment::get('locales') as $locale => $name) { ?> <li><?php echo $this->html->link($name, compact('locale') + $this->_request->params); ?> </li> <?php } ?> </ul> </div>