mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUG Replace phpdotenv with thread-safe replacement
This commit is contained in:
parent
b20bfd28a6
commit
b9cb1e69e6
@ -35,7 +35,7 @@
|
||||
"symfony/config": "^3.2",
|
||||
"symfony/translation": "^2.8",
|
||||
"symfony/yaml": "~3.2",
|
||||
"vlucas/phpdotenv": "^2.4",
|
||||
"m1/env": "^2.1",
|
||||
"php": ">=5.6.0",
|
||||
"ext-intl": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
@ -7,8 +7,8 @@ server.
|
||||
For each of these environments we may require slightly different configurations for our servers. This could be our debug
|
||||
level, caching backends, or - of course - sensitive information such as database credentials.
|
||||
|
||||
To solve this problem of setting variables per environment we use environment variables with the help of the
|
||||
[PHPDotEnv](https://github.com/vlucas/phpdotenv) library by Vance Lucas.
|
||||
To manage environment variables, as well as other server globals, the [api:SilverStripe\Core\Environment] class
|
||||
provides a set of APIs and helpers.
|
||||
|
||||
## Security considerations
|
||||
|
||||
@ -32,13 +32,18 @@ You can set "real" environment variables using Apache. Please
|
||||
|
||||
## How to access the environment variables
|
||||
|
||||
Accessing the environment varaibles is easy and can be done using the `getenv` method or in the `$_ENV` and `$_SERVER`
|
||||
super-globals:
|
||||
Accessing the environment varaibles should be done via the `Environment::getEnv()` method
|
||||
|
||||
```php
|
||||
getenv('SS_DATABASE_CLASS');
|
||||
$_ENV['SS_DATABASE_CLASS'];
|
||||
$_SERVER['SS_DATABASE_CLASS'];
|
||||
use SilverStripe\Core\Environment;
|
||||
Environment::getEnv('SS_DATABASE_CLASS');
|
||||
```
|
||||
|
||||
Individual settings can be assigned via `Environment::setEnv()` or `Environment::putEnv()` methods.
|
||||
|
||||
```php
|
||||
use SilverStripe\Core\Environment;
|
||||
Environment::setEnv('API_KEY', 'AABBCCDDEEFF012345');
|
||||
```
|
||||
|
||||
## Including an extra `.env` file
|
||||
@ -46,12 +51,14 @@ $_SERVER['SS_DATABASE_CLASS'];
|
||||
Sometimes it may be useful to include an extra `.env` file - on a shared local development environment where all
|
||||
database credentials could be the same. To do this, you can add this snippet to your `mysite/_config.php` file:
|
||||
|
||||
Note that by default variables cannot be overloaded from this file; Existing values will be preferred
|
||||
over values in this file.
|
||||
|
||||
```php
|
||||
try {
|
||||
(new \Dotenv\Dotenv('/path/to/env/'))->load();
|
||||
} catch (\Dotenv\Exception\InvalidPathException $e) {
|
||||
// no file found
|
||||
}
|
||||
use SilverStripe\Core\EnvironmentLoader;
|
||||
$env = BASE_PATH . '/mysite/.env';
|
||||
$loader = new EnvironmentLoader();
|
||||
$loader->loadFile($env);
|
||||
```
|
||||
|
||||
## Core environment variables
|
||||
|
@ -500,6 +500,8 @@ SS_BASE_URL="//localhost/"
|
||||
The global values `$database` and `$databaseConfig` have been deprecated, as has `ConfigureFromEnv.php`
|
||||
which is no longer necessary.
|
||||
|
||||
To access environment variables you can use the `SilverStripe\Core\Environment::getEnv()` method.
|
||||
|
||||
See [Environment Management docs](/getting-started/environment_management/) for full details.
|
||||
|
||||
#### Replace usages of Object class
|
||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\Control\Email;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\HTTP;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
@ -159,7 +160,7 @@ class Email extends ViewableData
|
||||
$normalised[$name] = null;
|
||||
}
|
||||
}
|
||||
$extra = getenv($env);
|
||||
$extra = Environment::getEnv($env);
|
||||
if ($extra) {
|
||||
$normalised[$extra] = null;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use Psr\Log\LoggerInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use ReflectionClass;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Environment;
|
||||
|
||||
/**
|
||||
* Assists with building of manifest cache prior to config being available
|
||||
@ -43,7 +44,7 @@ class ManifestCacheFactory extends DefaultCacheFactory
|
||||
public function create($service, array $params = array())
|
||||
{
|
||||
// Override default cache generation with SS_MANIFESTCACHE
|
||||
$cacheClass = getenv('SS_MANIFESTCACHE');
|
||||
$cacheClass = Environment::getEnv('SS_MANIFESTCACHE');
|
||||
if (!$cacheClass) {
|
||||
return parent::create($service, $params);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use SilverStripe\Config\Transformer\YamlTransformer;
|
||||
use SilverStripe\Core\Cache\CacheFactory;
|
||||
use SilverStripe\Core\Config\Middleware\ExtensionMiddleware;
|
||||
use SilverStripe\Core\Config\Middleware\InheritanceMiddleware;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Kernel;
|
||||
use SilverStripe\Core\Manifest\ClassLoader;
|
||||
@ -141,11 +142,12 @@ class CoreConfigFactory
|
||||
|
||||
// Add default rules
|
||||
$envvarset = function ($var, $value = null) {
|
||||
if (getenv($var) === false) {
|
||||
$actual = Environment::getEnv($var);
|
||||
if ($actual === false) {
|
||||
return false;
|
||||
}
|
||||
if ($value) {
|
||||
return getenv($var) === $value;
|
||||
return $actual === $value;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
@ -137,7 +137,7 @@ class CoreKernel implements Kernel
|
||||
}
|
||||
|
||||
// Check getenv
|
||||
if ($env = getenv('SS_ENVIRONMENT_TYPE')) {
|
||||
if ($env = Environment::getEnv('SS_ENVIRONMENT_TYPE')) {
|
||||
return $env;
|
||||
}
|
||||
|
||||
@ -328,32 +328,32 @@ class CoreKernel implements Kernel
|
||||
{
|
||||
/** @skipUpgrade */
|
||||
$databaseConfig = [
|
||||
"type" => getenv('SS_DATABASE_CLASS') ?: 'MySQLDatabase',
|
||||
"server" => getenv('SS_DATABASE_SERVER') ?: 'localhost',
|
||||
"username" => getenv('SS_DATABASE_USERNAME') ?: null,
|
||||
"password" => getenv('SS_DATABASE_PASSWORD') ?: null,
|
||||
"type" => Environment::getEnv('SS_DATABASE_CLASS') ?: 'MySQLDatabase',
|
||||
"server" => Environment::getEnv('SS_DATABASE_SERVER') ?: 'localhost',
|
||||
"username" => Environment::getEnv('SS_DATABASE_USERNAME') ?: null,
|
||||
"password" => Environment::getEnv('SS_DATABASE_PASSWORD') ?: null,
|
||||
];
|
||||
|
||||
// Set the port if called for
|
||||
$dbPort = getenv('SS_DATABASE_PORT');
|
||||
$dbPort = Environment::getEnv('SS_DATABASE_PORT');
|
||||
if ($dbPort) {
|
||||
$databaseConfig['port'] = $dbPort;
|
||||
}
|
||||
|
||||
// Set the timezone if called for
|
||||
$dbTZ = getenv('SS_DATABASE_TIMEZONE');
|
||||
$dbTZ = Environment::getEnv('SS_DATABASE_TIMEZONE');
|
||||
if ($dbTZ) {
|
||||
$databaseConfig['timezone'] = $dbTZ;
|
||||
}
|
||||
|
||||
// For schema enabled drivers:
|
||||
$dbSchema = getenv('SS_DATABASE_SCHEMA');
|
||||
$dbSchema = Environment::getEnv('SS_DATABASE_SCHEMA');
|
||||
if ($dbSchema) {
|
||||
$databaseConfig["schema"] = $dbSchema;
|
||||
}
|
||||
|
||||
// For SQlite3 memory databases (mainly for testing purposes)
|
||||
$dbMemory = getenv('SS_DATABASE_MEMORY');
|
||||
$dbMemory = Environment::getEnv('SS_DATABASE_MEMORY');
|
||||
if ($dbMemory) {
|
||||
$databaseConfig["memory"] = $dbMemory;
|
||||
}
|
||||
@ -368,7 +368,7 @@ class CoreKernel implements Kernel
|
||||
*/
|
||||
protected function getDatabasePrefix()
|
||||
{
|
||||
return getenv('SS_DATABASE_PREFIX') ?: '';
|
||||
return Environment::getEnv('SS_DATABASE_PREFIX') ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -392,14 +392,14 @@ class CoreKernel implements Kernel
|
||||
}
|
||||
|
||||
// Check environment
|
||||
$database = getenv('SS_DATABASE_NAME');
|
||||
$database = Environment::getEnv('SS_DATABASE_NAME');
|
||||
|
||||
if ($database) {
|
||||
return $this->getDatabasePrefix() . $database;
|
||||
}
|
||||
|
||||
// Auto-detect name
|
||||
$chooseName = getenv('SS_DATABASE_CHOOSE_NAME');
|
||||
$chooseName = Environment::getEnv('SS_DATABASE_CHOOSE_NAME');
|
||||
|
||||
if ($chooseName) {
|
||||
// Find directory to build name from
|
||||
@ -529,7 +529,7 @@ class CoreKernel implements Kernel
|
||||
$errorHandler->start();
|
||||
|
||||
// Register error log file
|
||||
$errorLog = getenv('SS_ERROR_LOG');
|
||||
$errorLog = Environment::getEnv('SS_ERROR_LOG');
|
||||
if ($errorLog) {
|
||||
$logger = Injector::inst()->get(LoggerInterface::class);
|
||||
if ($logger instanceof Logger) {
|
||||
|
@ -6,6 +6,11 @@ namespace SilverStripe\Core;
|
||||
* Consolidates access and modification of PHP global variables and settings.
|
||||
* This class should be used sparingly, and only if information cannot be obtained
|
||||
* from a current {@link HTTPRequest} object.
|
||||
*
|
||||
* Acts as the primary store for environment variables, including those loaded
|
||||
* from .env files. Applications should use Environment::getEnv() instead of php's
|
||||
* `getenv` in order to include `.env` configuration, as the system's actual
|
||||
* environment variables are treated immutably.
|
||||
*/
|
||||
class Environment
|
||||
{
|
||||
@ -23,6 +28,13 @@ class Environment
|
||||
*/
|
||||
protected static $timeLimitMax = null;
|
||||
|
||||
/**
|
||||
* Local overrides for all $_ENV var protected from cross-process operations
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $env = [];
|
||||
|
||||
/**
|
||||
* Extract env vars prior to modification
|
||||
*
|
||||
@ -31,7 +43,7 @@ class Environment
|
||||
public static function getVariables()
|
||||
{
|
||||
// Suppress return by-ref
|
||||
return array_merge($GLOBALS, []);
|
||||
return array_merge($GLOBALS, [ 'env' => static::$env ]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,8 +53,14 @@ class Environment
|
||||
*/
|
||||
public static function setVariables(array $vars)
|
||||
{
|
||||
foreach ($vars as $key => $value) {
|
||||
$GLOBALS[$key] = $value;
|
||||
foreach ($vars as $varName => $varValue) {
|
||||
if ($varName === 'env') {
|
||||
continue;
|
||||
}
|
||||
$GLOBALS[$varName] = $varValue;
|
||||
}
|
||||
if (array_key_exists('env', $vars)) {
|
||||
static::$env = $vars['env'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,4 +169,51 @@ class Environment
|
||||
{
|
||||
return static::$timeLimitMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of environment variable
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed Value of the environment variable, or false if not set
|
||||
*/
|
||||
public static function getEnv($name)
|
||||
{
|
||||
switch (true) {
|
||||
case array_key_exists($name, static::$env):
|
||||
return static::$env[$name];
|
||||
case array_key_exists($name, $_ENV):
|
||||
return $_ENV[$name];
|
||||
case array_key_exists($name, $_SERVER):
|
||||
return $_SERVER[$name];
|
||||
default:
|
||||
return getenv($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment variable using php.ini syntax.
|
||||
* Acts as a process-isolated version of putenv()
|
||||
* Note: This will be parsed via parse_ini_string() which handles quoted values
|
||||
*
|
||||
* @param string $string Setting to assign in KEY=VALUE or KEY="VALUE" syntax
|
||||
*/
|
||||
public static function putEnv($string)
|
||||
{
|
||||
// Parse name-value pairs
|
||||
$envVars = parse_ini_string($string) ?: [];
|
||||
foreach ($envVars as $name => $value) {
|
||||
self::setEnv($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment variable via $name / $value pair
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public static function setEnv($name, $value)
|
||||
{
|
||||
static::$env[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
47
src/Core/EnvironmentLoader.php
Normal file
47
src/Core/EnvironmentLoader.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core;
|
||||
|
||||
use M1\Env\Parser;
|
||||
|
||||
/**
|
||||
* Loads environment variables from .env files
|
||||
* Loosely based on https://github.com/vlucas/phpdotenv/blob/master/src/Loader.php
|
||||
*/
|
||||
class EnvironmentLoader
|
||||
{
|
||||
/**
|
||||
* Load environment variables from .env file
|
||||
*
|
||||
* @param string $path Path to the file
|
||||
* @param bool $overload Set to true to allow vars to overload. Recommended to leave false.
|
||||
* @return array|null List of values parsed as an associative array, or null if not loaded
|
||||
* If overloading, this list will reflect the final state for all variables
|
||||
*/
|
||||
public function loadFile($path, $overload = false)
|
||||
{
|
||||
// Not readable
|
||||
if (!file_exists($path) || !is_readable($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Parse and cleanup content
|
||||
$result = [];
|
||||
$variables = Parser::parse(file_get_contents($path));
|
||||
foreach ($variables as $name => $value) {
|
||||
// Conditionally prevent overloading
|
||||
if (!$overload) {
|
||||
$existing = Environment::getEnv($name);
|
||||
if ($existing !== false) {
|
||||
$result[$name] = $existing;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Overload or create var
|
||||
Environment::setEnv($name, $value);
|
||||
$result[$name] = $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ use ReflectionObject;
|
||||
use ReflectionProperty;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
|
||||
/**
|
||||
@ -523,8 +524,9 @@ class Injector implements ContainerInterface
|
||||
|
||||
// Evaluate constants surrounded by back ticks
|
||||
if (preg_match('/^`(?<name>[^`]+)`$/', $value, $matches)) {
|
||||
if (getenv($matches['name']) !== false) {
|
||||
$value = getenv($matches['name']);
|
||||
$envValue = Environment::getEnv($matches['name']);
|
||||
if ($envValue !== false) {
|
||||
$value = $envValue;
|
||||
} elseif (defined($matches['name'])) {
|
||||
$value = constant($matches['name']);
|
||||
} else {
|
||||
|
@ -36,12 +36,12 @@ class TempFolder
|
||||
*/
|
||||
public static function getTempFolderUsername()
|
||||
{
|
||||
$user = getenv('APACHE_RUN_USER');
|
||||
$user = Environment::getEnv('APACHE_RUN_USER');
|
||||
if (!$user) {
|
||||
$user = getenv('USER');
|
||||
$user = Environment::getEnv('USER');
|
||||
}
|
||||
if (!$user) {
|
||||
$user = getenv('USERNAME');
|
||||
$user = Environment::getEnv('USERNAME');
|
||||
}
|
||||
if (!$user && function_exists('posix_getpwuid') && function_exists('posix_getuid')) {
|
||||
$userDetails = posix_getpwuid(posix_getuid());
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
use SilverStripe\Core\Environment;
|
||||
|
||||
/**
|
||||
* Provides environment settings from the current request + environment
|
||||
*
|
||||
@ -42,10 +44,10 @@ class InstallConfig
|
||||
// Guess database config
|
||||
return [
|
||||
'type' => $this->getDatabaseClass($databaseClasses),
|
||||
'server' => getenv('SS_DATABASE_SERVER') ?: 'localhost',
|
||||
'username' => getenv('SS_DATABASE_USERNAME') ?: 'root',
|
||||
'password' => getenv('SS_DATABASE_PASSWORD') ?: '',
|
||||
'database' => getenv('SS_DATABASE_NAME') ?: 'SS_mysite',
|
||||
'server' => Environment::getEnv('SS_DATABASE_SERVER') ?: 'localhost',
|
||||
'username' => Environment::getEnv('SS_DATABASE_USERNAME') ?: 'root',
|
||||
'password' => Environment::getEnv('SS_DATABASE_PASSWORD') ?: '',
|
||||
'database' => Environment::getEnv('SS_DATABASE_NAME') ?: 'SS_mysite',
|
||||
];
|
||||
}
|
||||
|
||||
@ -62,8 +64,8 @@ class InstallConfig
|
||||
}
|
||||
|
||||
return [
|
||||
'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
|
||||
'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '',
|
||||
'username' => Environment::getEnv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
|
||||
'password' => Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD') ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
@ -114,8 +116,9 @@ class InstallConfig
|
||||
*/
|
||||
protected function getDatabaseClass($databaseClasses)
|
||||
{
|
||||
if (getenv('SS_DATABASE_CLASS')) {
|
||||
return getenv('SS_DATABASE_CLASS');
|
||||
$envDatabase = Environment::getEnv('SS_DATABASE_CLASS');
|
||||
if ($envDatabase) {
|
||||
return $envDatabase;
|
||||
}
|
||||
|
||||
// Check supported versions
|
||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\ORM\Connect;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
@ -40,7 +41,7 @@ class TempDatabase
|
||||
*/
|
||||
protected function isDBTemp($name)
|
||||
{
|
||||
$prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$result = preg_match(
|
||||
sprintf('/^%stmpdb_[0-9]+_[0-9]+$/i', preg_quote($prefix, '/')),
|
||||
$name
|
||||
@ -133,7 +134,7 @@ class TempDatabase
|
||||
|
||||
// Create a temporary database, and force the connection to use UTC for time
|
||||
$dbConn = $this->getConn();
|
||||
$prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
do {
|
||||
$dbname = strtolower(sprintf('%stmpdb_%s_%s', $prefix, time(), rand(1000000, 9999999)));
|
||||
} while ($dbConn->databaseExists($dbname));
|
||||
|
@ -8,6 +8,7 @@ use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\ORM\Connect\Database;
|
||||
@ -265,7 +266,7 @@ class DB
|
||||
return false;
|
||||
}
|
||||
|
||||
$prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$pattern = strtolower(sprintf('/^%stmpdb\d{7}$/', $prefix));
|
||||
return (bool)preg_match($pattern, $name);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Control\HTTPResponse_Exception;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\ORM\Connect\DatabaseException;
|
||||
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
|
||||
|
||||
@ -224,9 +225,9 @@ class BasicAuth
|
||||
// Check if site is protected
|
||||
if ($config->get('entire_site_protected')) {
|
||||
$permissionCode = $config->get('entire_site_protected_code');
|
||||
} elseif (getenv(self::USE_BASIC_AUTH)) {
|
||||
} elseif (Environment::getEnv(self::USE_BASIC_AUTH)) {
|
||||
// Convert legacy 1 / true to ADMIN permissions
|
||||
$permissionCode = getenv(self::USE_BASIC_AUTH);
|
||||
$permissionCode = Environment::getEnv(self::USE_BASIC_AUTH);
|
||||
if (!is_string($permissionCode) || is_numeric($permissionCode)) {
|
||||
$permissionCode = self::AUTH_PERMISSION;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\Security;
|
||||
use BadMethodCallException;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
@ -74,7 +75,7 @@ class DefaultAdminService
|
||||
"No default admin configured. Please call hasDefaultAdmin() before getting default admin username"
|
||||
);
|
||||
}
|
||||
return static::$default_username ?: getenv('SS_DEFAULT_ADMIN_USERNAME');
|
||||
return static::$default_username ?: Environment::getEnv('SS_DEFAULT_ADMIN_USERNAME');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,7 +89,7 @@ class DefaultAdminService
|
||||
"No default admin configured. Please call hasDefaultAdmin() before getting default admin password"
|
||||
);
|
||||
}
|
||||
return static::$default_password ?: getenv('SS_DEFAULT_ADMIN_PASSWORD');
|
||||
return static::$default_password ?: Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,8 +101,8 @@ class DefaultAdminService
|
||||
{
|
||||
// Check environment if not explicitly set
|
||||
if (!isset(static::$has_default_admin)) {
|
||||
return !empty(getenv('SS_DEFAULT_ADMIN_USERNAME'))
|
||||
&& !empty(getenv('SS_DEFAULT_ADMIN_PASSWORD'));
|
||||
return !empty(Environment::getEnv('SS_DEFAULT_ADMIN_USERNAME'))
|
||||
&& !empty(Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD'));
|
||||
}
|
||||
return static::$has_default_admin;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use Dotenv\Exception\InvalidPathException;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\EnvironmentLoader;
|
||||
use SilverStripe\Core\TempFolder;
|
||||
|
||||
/**
|
||||
@ -58,24 +58,23 @@ if (!defined('BASE_PATH')) {
|
||||
}
|
||||
|
||||
// Allow a first class env var to be set that disables .env file loading
|
||||
if (!getenv('SS_IGNORE_DOT_ENV')) {
|
||||
if (!Environment::getEnv('SS_IGNORE_DOT_ENV')) {
|
||||
call_user_func(function () {
|
||||
$loader = new EnvironmentLoader();
|
||||
foreach ([BASE_PATH, dirname(BASE_PATH)] as $path) {
|
||||
try {
|
||||
(new Dotenv($path))->load();
|
||||
} catch (InvalidPathException $e) {
|
||||
// no .env found - no big deal
|
||||
continue;
|
||||
// Stop searching after first `.env` file is loaded
|
||||
$dotEnvFile = $path . DIRECTORY_SEPARATOR . '.env';
|
||||
if ($loader->loadFile($dotEnvFile)) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Validate SS_BASE_URL is absolute
|
||||
if (getenv('SS_BASE_URL') && !preg_match('#^(\w+:)?//.*#', getenv('SS_BASE_URL'))) {
|
||||
if (Environment::getEnv('SS_BASE_URL') && !preg_match('#^(\w+:)?//.*#', Environment::getEnv('SS_BASE_URL'))) {
|
||||
call_user_func(function () {
|
||||
$base = getenv('SS_BASE_URL');
|
||||
$base = Environment::getEnv('SS_BASE_URL');
|
||||
user_error(
|
||||
"SS_BASE_URL should be an absolute url with protocol "
|
||||
. "(http://$base) or without protocol (//$base)",
|
||||
@ -83,14 +82,14 @@ if (getenv('SS_BASE_URL') && !preg_match('#^(\w+:)?//.*#', getenv('SS_BASE_URL')
|
||||
);
|
||||
// Treat as protocol-less absolute url
|
||||
$base = '//' . $base;
|
||||
putenv("SS_BASE_URL=$base");
|
||||
Environment::setEnv('SS_BASE_URL', $base);
|
||||
});
|
||||
}
|
||||
|
||||
if (!defined('BASE_URL')) {
|
||||
define('BASE_URL', call_user_func(function () {
|
||||
// Prefer explicitly provided SS_BASE_URL
|
||||
$base = getenv('SS_BASE_URL');
|
||||
$base = Environment::getEnv('SS_BASE_URL');
|
||||
if ($base) {
|
||||
// Strip relative path from SS_BASE_URL
|
||||
return rtrim(parse_url($base, PHP_URL_PATH), '/');
|
||||
|
@ -2,34 +2,35 @@
|
||||
|
||||
// Bootstrap environment variables
|
||||
|
||||
use Dotenv\Loader;
|
||||
|
||||
use SilverStripe\Core\Environment;
|
||||
|
||||
/** @skipUpgrade */
|
||||
if (!getenv('SS_DATABASE_CLASS') && !getenv('SS_DATABASE_USERNAME')) {
|
||||
$loader = new Loader(null);
|
||||
if (!Environment::getEnv('SS_DATABASE_CLASS') && !Environment::getEnv('SS_DATABASE_USERNAME')) {
|
||||
// The default settings let us define the database config via environment vars
|
||||
// Database connection, including PDO and legacy ORM support
|
||||
switch (getenv('DB')) {
|
||||
switch (Environment::getEnv('DB')) {
|
||||
case "PGSQL";
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'PostgrePDODatabase' : 'PostgreSQLDatabase');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'postgres');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', '');
|
||||
$pgDatabaseClass = Environment::getEnv('PDO') ? 'PostgrePDODatabase' : 'PostgreSQLDatabase';
|
||||
Environment::setEnv('SS_DATABASE_CLASS', $pgDatabaseClass);
|
||||
Environment::setEnv('SS_DATABASE_USERNAME', 'postgres');
|
||||
Environment::setEnv('SS_DATABASE_PASSWORD', '');
|
||||
break;
|
||||
|
||||
case "SQLITE":
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'SQLite3PDODatabase' : 'SQLite3Database');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'root');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', '');
|
||||
$loader->setEnvironmentVariable('SS_SQLITE_DATABASE_PATH', ':memory:');
|
||||
$sqliteDatabaseClass = Environment::getEnv('PDO') ? 'SQLite3PDODatabase' : 'SQLite3Database';
|
||||
Environment::setEnv('SS_DATABASE_CLASS', $sqliteDatabaseClass);
|
||||
Environment::setEnv('SS_DATABASE_USERNAME', 'root');
|
||||
Environment::setEnv('SS_DATABASE_PASSWORD', '');
|
||||
Environment::setEnv('SS_SQLITE_DATABASE_PATH', ':memory:');
|
||||
break;
|
||||
|
||||
default:
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_CLASS', getenv('PDO') ? 'MySQLPDODatabase' : 'MySQLDatabase');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_USERNAME', 'root');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_PASSWORD', '');
|
||||
$mysqlDatabaseClass = Environment::getEnv('PDO') ? 'MySQLPDODatabase' : 'MySQLDatabase';
|
||||
Environment::setEnv('SS_DATABASE_CLASS', $mysqlDatabaseClass);
|
||||
Environment::setEnv('SS_DATABASE_USERNAME', 'root');
|
||||
Environment::setEnv('SS_DATABASE_PASSWORD', '');
|
||||
}
|
||||
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_SERVER', '127.0.0.1');
|
||||
$loader->setEnvironmentVariable('SS_DATABASE_CHOOSE_NAME', true);
|
||||
Environment::setEnv('SS_DATABASE_CHOOSE_NAME', 'true');
|
||||
Environment::setEnv('SS_DATABASE_SERVER', '127.0.0.1');
|
||||
}
|
||||
|
83
tests/php/Core/EnvironmentLoaderTest.php
Normal file
83
tests/php/Core/EnvironmentLoaderTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core\Tests;
|
||||
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\EnvironmentLoader;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class EnvironmentLoaderTest extends SapphireTest
|
||||
{
|
||||
public function testStripComments()
|
||||
{
|
||||
$loader = new EnvironmentLoader();
|
||||
|
||||
// No file
|
||||
$this->assertNull($loader->loadFile(__DIR__ . '/EnvironmentTest/nofile.env'));
|
||||
|
||||
// Initial load
|
||||
$vars = $loader->loadFile(__DIR__ . '/EnvironmentTest/test.env');
|
||||
$this->assertCount(7, $vars);
|
||||
$this->assertEquals('first', $vars['TEST_ENV_FIRST']);
|
||||
$this->assertEquals('first', Environment::getEnv('TEST_ENV_FIRST'));
|
||||
$this->assertEquals('start "#notcomment end', $vars['TEST_ENV_SECOND']);
|
||||
$this->assertEquals('start "#notcomment end', Environment::getEnv('TEST_ENV_SECOND'));
|
||||
$this->assertEquals(3, $vars['TEST_ENV_THIRD']);
|
||||
$this->assertEquals(3, Environment::getEnv('TEST_ENV_THIRD'));
|
||||
$this->assertEquals(true, $vars['TEST_ENV_FOURTH']);
|
||||
$this->assertEquals(true, Environment::getEnv('TEST_ENV_FOURTH'));
|
||||
$this->assertEquals('not#comment', $vars['TEST_ENV_FIFTH']);
|
||||
$this->assertEquals('not#comment', Environment::getEnv('TEST_ENV_FIFTH'));
|
||||
$this->assertEquals('not#comment', $vars['TEST_ENV_SIXTH']);
|
||||
$this->assertEquals('not#comment', Environment::getEnv('TEST_ENV_SIXTH'));
|
||||
$this->assertEquals('', $vars['TEST_ENV_SEVENTH']);
|
||||
$this->assertEquals('', Environment::getEnv('TEST_ENV_SEVENTH'));
|
||||
}
|
||||
|
||||
public function testOverloading()
|
||||
{
|
||||
$loader = new EnvironmentLoader();
|
||||
|
||||
// No file
|
||||
$loader->loadFile(__DIR__ . '/EnvironmentTest/test.env');
|
||||
|
||||
// Ensure default behaviour doesn't overload
|
||||
$vars2 = $loader->loadFile(__DIR__ . '/EnvironmentTest/test2.env');
|
||||
$this->assertEquals(
|
||||
[
|
||||
'TEST_ENV_FIRST' => 'first',
|
||||
'TEST_ENV_SECOND' => 'start "#notcomment end',
|
||||
'TEST_ENV_NEWVAR' => 'first-overloaded',
|
||||
'TEST_ENV_NEWVAR2' => 'second-file',
|
||||
],
|
||||
$vars2
|
||||
);
|
||||
$this->assertEquals('first', Environment::getEnv('TEST_ENV_FIRST'));
|
||||
|
||||
// Test overload = true
|
||||
$vars2 = $loader->loadFile(__DIR__ . '/EnvironmentTest/test2.env', true);
|
||||
$this->assertEquals(
|
||||
[
|
||||
'TEST_ENV_FIRST' => 'first-overloaded',
|
||||
'TEST_ENV_SECOND' => 'first-overloaded',
|
||||
'TEST_ENV_NEWVAR' => 'first-overloaded',
|
||||
'TEST_ENV_NEWVAR2' => 'second-file',
|
||||
],
|
||||
$vars2
|
||||
);
|
||||
$this->assertEquals('first-overloaded', Environment::getEnv('TEST_ENV_FIRST'));
|
||||
}
|
||||
|
||||
public function testInterpolation()
|
||||
{
|
||||
$loader = new EnvironmentLoader();
|
||||
$vars = $loader->loadFile(__DIR__ . '/EnvironmentTest/test3.env');
|
||||
$this->assertEquals(
|
||||
[
|
||||
'TEST_ENV_INT_ONE' => 'some var',
|
||||
'TEST_ENV_INT_TWO' => 'some var',
|
||||
],
|
||||
$vars
|
||||
);
|
||||
}
|
||||
}
|
56
tests/php/Core/EnvironmentTest.php
Normal file
56
tests/php/Core/EnvironmentTest.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core\Tests;
|
||||
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class EnvironmentTest extends SapphireTest
|
||||
{
|
||||
public function providerTestPutEnv()
|
||||
{
|
||||
return [
|
||||
['_ENVTEST_BOOL=true', '_ENVTEST_BOOL', true],
|
||||
['_ENVTEST_BOOL_QUOTED="true"', '_ENVTEST_BOOL_QUOTED', 'true'],
|
||||
['_ENVTEST_NUMBER=1', '_ENVTEST_NUMBER', 1],
|
||||
['_ENVTEST_NUMBER_QUOTED="1"', '_ENVTEST_NUMBER_QUOTED', '1'],
|
||||
['_ENVTEST_NUMBER_SPECIAL="value=4"', '_ENVTEST_NUMBER_SPECIAL', 'value=4'],
|
||||
['_ENVTEST_BLANK', '_ENVTEST_BLANK', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestPutenv
|
||||
*/
|
||||
public function testPutEnv($put, $var, $value)
|
||||
{
|
||||
Environment::putEnv($put);
|
||||
$this->assertEquals($value, Environment::getEnv($var));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestPutEnv
|
||||
*/
|
||||
public function testSetEnv($put, $var, $value)
|
||||
{
|
||||
Environment::setEnv($var, $value);
|
||||
$this->assertEquals($value, Environment::getEnv($var));
|
||||
}
|
||||
|
||||
public function testRestoreEnv()
|
||||
{
|
||||
// Set and backup original vars
|
||||
Environment::putEnv('_ENVTEST_RESTORED=initial');
|
||||
$vars = Environment::getVariables();
|
||||
$this->assertEquals('initial', Environment::getEnv('_ENVTEST_RESTORED'));
|
||||
|
||||
// Modify enironment
|
||||
Environment::putEnv('_ENVTEST_RESTORED=new');
|
||||
$this->assertEquals('initial', $vars['env']['_ENVTEST_RESTORED']);
|
||||
$this->assertEquals('new', Environment::getEnv('_ENVTEST_RESTORED'));
|
||||
|
||||
// Restore
|
||||
Environment::setVariables($vars);
|
||||
$this->assertEquals('initial', Environment::getEnv('_ENVTEST_RESTORED'));
|
||||
}
|
||||
}
|
13
tests/php/Core/EnvironmentTest/test.env
Normal file
13
tests/php/Core/EnvironmentTest/test.env
Normal file
@ -0,0 +1,13 @@
|
||||
# Test file
|
||||
|
||||
TEST_ENV_FIRST="first"
|
||||
TEST_ENV_SECOND="start \"#notcomment end"#Comment
|
||||
#Comment
|
||||
TEST_ENV_THIRD = 3 #comment
|
||||
|
||||
TEST_ENV_FOURTH=true #comment
|
||||
TEST_ENV_FIFTH = "not#comment"#comment
|
||||
TEST_ENV_SIXTH="not#comment"
|
||||
|
||||
TEST_ENV_SEVENTH="" #comment
|
||||
|
6
tests/php/Core/EnvironmentTest/test2.env
Normal file
6
tests/php/Core/EnvironmentTest/test2.env
Normal file
@ -0,0 +1,6 @@
|
||||
# Test file
|
||||
|
||||
TEST_ENV_FIRST="first-overloaded"
|
||||
TEST_ENV_SECOND="${TEST_ENV_FIRST}"
|
||||
TEST_ENV_NEWVAR="${TEST_ENV_FIRST}"
|
||||
TEST_ENV_NEWVAR2="second-file"
|
4
tests/php/Core/EnvironmentTest/test3.env
Normal file
4
tests/php/Core/EnvironmentTest/test3.env
Normal file
@ -0,0 +1,4 @@
|
||||
# Test file
|
||||
|
||||
TEST_ENV_INT_ONE="some var"
|
||||
TEST_ENV_INT_TWO="${TEST_ENV_INT_ONE}"
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\Manifest;
|
||||
|
||||
use Dotenv\Loader;
|
||||
use SilverStripe\Config\Collections\MemoryConfigCollection;
|
||||
use SilverStripe\Core\Config\CoreConfigFactory;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Kernel;
|
||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||
@ -100,8 +100,7 @@ class ConfigManifestTest extends SapphireTest
|
||||
|
||||
public function testEnvVarSetRules()
|
||||
{
|
||||
$loader = new Loader(null);
|
||||
$loader->setEnvironmentVariable('ENVVARSET_FOO', 1);
|
||||
Environment::setEnv('ENVVARSET_FOO', '1');
|
||||
$config = $this->getConfigFixtureValue('EnvVarSet');
|
||||
|
||||
$this->assertEquals(
|
||||
@ -137,9 +136,7 @@ class ConfigManifestTest extends SapphireTest
|
||||
|
||||
public function testEnvOrConstantMatchesValueRules()
|
||||
{
|
||||
$loader = new Loader(null);
|
||||
|
||||
$loader->setEnvironmentVariable('CONSTANTMATCHESVALUE_FOO', 'Foo');
|
||||
Environment::setEnv('CONSTANTMATCHESVALUE_FOO', 'Foo');
|
||||
define('CONSTANTMATCHESVALUE_BAR', 'Bar');
|
||||
$config = $this->getConfigFixtureValue('EnvOrConstantMatchesValue');
|
||||
|
||||
@ -194,9 +191,7 @@ class ConfigManifestTest extends SapphireTest
|
||||
|
||||
public function testMultipleRules()
|
||||
{
|
||||
$loader = new Loader(null);
|
||||
|
||||
$loader->setEnvironmentVariable('MULTIPLERULES_ENVVARIABLESET', 1);
|
||||
Environment::setEnv('MULTIPLERULES_ENVVARIABLESET', '1');
|
||||
define('MULTIPLERULES_DEFINEDCONSTANT', 'defined');
|
||||
$config = $this->getConfigFixtureValue('MultipleRules');
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Environment;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Kernel;
|
||||
use SilverStripe\ORM\DB;
|
||||
@ -15,7 +16,7 @@ class DBTest extends SapphireTest
|
||||
{
|
||||
/** @var Kernel $kernel */
|
||||
$kernel = Injector::inst()->get(Kernel::class);
|
||||
$prefix = getenv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
$prefix = Environment::getEnv('SS_DATABASE_PREFIX') ?: 'ss_';
|
||||
|
||||
$kernel->setEnvironment(Kernel::DEV);
|
||||
$this->assertTrue(DB::valid_alternative_database_name($prefix.'tmpdb1234567'));
|
||||
|
Loading…
Reference in New Issue
Block a user