2013-07-22 03:52:00 +02:00
|
|
|
<?php
|
2017-04-13 03:33:29 +02:00
|
|
|
|
2018-01-12 04:25:02 +01:00
|
|
|
use SilverStripe\Core\Convert;
|
2017-10-16 05:43:12 +02:00
|
|
|
use SilverStripe\Core\Environment;
|
|
|
|
use SilverStripe\Core\EnvironmentLoader;
|
2017-06-22 12:50:45 +02:00
|
|
|
use SilverStripe\Core\TempFolder;
|
2017-04-13 03:33:29 +02:00
|
|
|
|
2013-07-22 03:52:00 +02:00
|
|
|
/**
|
|
|
|
* This file is the Framework constants bootstrap. It will prepare some basic common constants.
|
|
|
|
*
|
|
|
|
* It takes care of:
|
|
|
|
* - Initialisation of necessary constants (mostly paths)
|
|
|
|
*
|
|
|
|
* Initialized constants:
|
|
|
|
* - BASE_URL: Full URL to the webroot, e.g. "http://my-host.com/my-webroot" (no trailing slash).
|
|
|
|
* - BASE_PATH: Absolute path to the webroot, e.g. "/var/www/my-webroot" (no trailing slash).
|
2017-07-17 07:59:40 +02:00
|
|
|
* See Director::baseFolder(). Can be overwritten by Config::modify()->set(Director::class, 'alternate_base_folder', ).
|
2021-11-15 21:35:28 +01:00
|
|
|
* - TEMP_PATH: Path to temporary folder for manifest and template caches. May be relative to project root or an
|
|
|
|
* absolute path. No trailing slash. Can be set with the SS_TEMP_PATH environment variable.
|
|
|
|
* - TEMP_FOLDER: DEPRECATED. Same as TEMP_PATH.
|
2017-08-23 04:20:39 +02:00
|
|
|
* - ASSETS_DIR: Dir for assets folder. e.g. "assets"
|
|
|
|
* - ASSETS_PATH: Full path to assets folder. e.g. "/var/www/my-webroot/assets"
|
2013-07-22 03:52:00 +02:00
|
|
|
* - THEMES_DIR: Path relative to webroot, e.g. "themes"
|
|
|
|
* - THEMES_PATH: Absolute filepath, e.g. "/var/www/my-webroot/themes"
|
|
|
|
* - FRAMEWORK_DIR: Path relative to webroot, e.g. "framework"
|
|
|
|
* - FRAMEWORK_PATH:Absolute filepath, e.g. "/var/www/my-webroot/framework"
|
2022-12-14 04:08:47 +01:00
|
|
|
* - PUBLIC_DIR: Webroot path relative to project root - always evaluates to "public"
|
2018-01-17 16:16:15 +01:00
|
|
|
* - PUBLIC_PATH: Absolute path to webroot, e.g. "/var/www/project/public"
|
2013-07-22 03:52:00 +02:00
|
|
|
* - THIRDPARTY_DIR: Path relative to webroot, e.g. "framework/thirdparty"
|
|
|
|
* - THIRDPARTY_PATH: Absolute filepath, e.g. "/var/www/my-webroot/framework/thirdparty"
|
2021-04-20 18:25:24 +02:00
|
|
|
* - RESOURCES_DIR: Name of the directory where vendor assets will be exposed, e.g. "_resources"
|
2013-07-22 03:52:00 +02:00
|
|
|
*/
|
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
require_once __DIR__ . '/functions.php';
|
|
|
|
|
2013-07-22 03:52:00 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ENVIRONMENT CONFIG
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Define system paths
|
|
|
|
*/
|
2016-11-29 00:31:16 +01:00
|
|
|
if (!defined('BASE_PATH')) {
|
2017-04-13 03:33:29 +02:00
|
|
|
define('BASE_PATH', call_user_func(function () {
|
|
|
|
// Determine BASE_PATH based on the composer autoloader
|
|
|
|
foreach (debug_backtrace() as $backtraceItem) {
|
2019-10-18 04:31:39 +02:00
|
|
|
if (!isset($backtraceItem['file'])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$matched = preg_match(
|
|
|
|
'#^(?<base>.*)(/|\\\\)vendor(/|\\\\)composer(/|\\\\)autoload_real.php#',
|
2022-04-14 03:12:59 +02:00
|
|
|
$backtraceItem['file'] ?? '',
|
2019-10-18 04:31:39 +02:00
|
|
|
$matches
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($matched) {
|
2022-04-14 03:12:59 +02:00
|
|
|
return realpath($matches['base'] ?? '') ?: DIRECTORY_SEPARATOR;
|
2017-04-13 03:33:29 +02:00
|
|
|
}
|
2016-11-29 00:31:16 +01:00
|
|
|
}
|
2016-09-12 05:13:55 +02:00
|
|
|
|
2021-07-08 01:11:39 +02:00
|
|
|
// Determine BASE_PATH by assuming that this file is vendor/silverstripe/framework/src/includes/constants.php
|
|
|
|
// we can then determine the base path
|
|
|
|
$candidateBasePath = rtrim(dirname(__DIR__, 5), DIRECTORY_SEPARATOR);
|
|
|
|
|
2017-04-13 03:33:29 +02:00
|
|
|
// We can't have an empty BASE_PATH. Making it / means that double-slashes occur in places but that's benign.
|
2021-12-13 09:05:33 +01:00
|
|
|
// This likely only happens on chrooted environments
|
2017-04-13 03:33:29 +02:00
|
|
|
return $candidateBasePath ?: DIRECTORY_SEPARATOR;
|
|
|
|
}));
|
2013-07-22 03:52:00 +02:00
|
|
|
}
|
2017-01-30 16:33:56 +01:00
|
|
|
|
2018-01-12 04:25:02 +01:00
|
|
|
// Set public webroot dir / path
|
2018-01-15 02:45:15 +01:00
|
|
|
if (!defined('PUBLIC_DIR')) {
|
2022-12-14 04:08:47 +01:00
|
|
|
define('PUBLIC_DIR', 'public');
|
2018-01-15 02:45:15 +01:00
|
|
|
}
|
|
|
|
if (!defined('PUBLIC_PATH')) {
|
2022-12-14 04:08:47 +01:00
|
|
|
define('PUBLIC_PATH', BASE_PATH . DIRECTORY_SEPARATOR . PUBLIC_DIR);
|
2018-01-15 02:45:15 +01:00
|
|
|
}
|
2018-01-12 04:25:02 +01:00
|
|
|
|
2017-01-30 16:33:56 +01:00
|
|
|
// Allow a first class env var to be set that disables .env file loading
|
2017-10-16 05:43:12 +02:00
|
|
|
if (!Environment::getEnv('SS_IGNORE_DOT_ENV')) {
|
2017-06-22 12:50:45 +02:00
|
|
|
call_user_func(function () {
|
2017-10-16 05:43:12 +02:00
|
|
|
$loader = new EnvironmentLoader();
|
2017-06-22 12:50:45 +02:00
|
|
|
foreach ([BASE_PATH, dirname(BASE_PATH)] as $path) {
|
2017-10-16 05:43:12 +02:00
|
|
|
// Stop searching after first `.env` file is loaded
|
|
|
|
$dotEnvFile = $path . DIRECTORY_SEPARATOR . '.env';
|
|
|
|
if ($loader->loadFile($dotEnvFile)) {
|
|
|
|
break;
|
2017-06-22 12:50:45 +02:00
|
|
|
}
|
2017-01-30 16:33:56 +01:00
|
|
|
}
|
2017-06-22 12:50:45 +02:00
|
|
|
});
|
2017-01-30 16:33:56 +01:00
|
|
|
}
|
|
|
|
|
2017-09-20 00:07:32 +02:00
|
|
|
// Validate SS_BASE_URL is absolute
|
2022-04-14 03:12:59 +02:00
|
|
|
if (Environment::getEnv('SS_BASE_URL') && !preg_match('#^(\w+:)?//.*#', Environment::getEnv('SS_BASE_URL') ?? '')) {
|
2017-09-20 00:07:32 +02:00
|
|
|
call_user_func(function () {
|
2017-10-16 05:43:12 +02:00
|
|
|
$base = Environment::getEnv('SS_BASE_URL');
|
2017-09-20 00:07:32 +02:00
|
|
|
user_error(
|
|
|
|
"SS_BASE_URL should be an absolute url with protocol "
|
|
|
|
. "(http://$base) or without protocol (//$base)",
|
|
|
|
E_USER_WARNING
|
|
|
|
);
|
|
|
|
// Treat as protocol-less absolute url
|
|
|
|
$base = '//' . $base;
|
2017-10-16 05:43:12 +02:00
|
|
|
Environment::setEnv('SS_BASE_URL', $base);
|
2017-09-20 00:07:32 +02:00
|
|
|
});
|
|
|
|
}
|
2017-05-30 13:18:47 +02:00
|
|
|
|
2016-11-29 00:31:16 +01:00
|
|
|
if (!defined('BASE_URL')) {
|
2017-04-13 03:33:29 +02:00
|
|
|
define('BASE_URL', call_user_func(function () {
|
2017-08-24 02:58:04 +02:00
|
|
|
// Prefer explicitly provided SS_BASE_URL
|
2017-10-16 05:43:12 +02:00
|
|
|
$base = Environment::getEnv('SS_BASE_URL');
|
2017-08-24 02:58:04 +02:00
|
|
|
if ($base) {
|
|
|
|
// Strip relative path from SS_BASE_URL
|
2022-04-14 03:12:59 +02:00
|
|
|
return rtrim(parse_url($base ?? '', PHP_URL_PATH) ?? '', '/');
|
2017-08-24 02:58:04 +02:00
|
|
|
}
|
|
|
|
|
2017-12-14 05:42:00 +01:00
|
|
|
// Unless specified, use empty string for base in CLI
|
|
|
|
if (in_array(php_sapi_name(), ['cli', 'phpdbg'])) {
|
2018-02-07 02:25:52 +01:00
|
|
|
return '';
|
2017-12-14 05:42:00 +01:00
|
|
|
}
|
|
|
|
|
2017-04-13 03:33:29 +02:00
|
|
|
// Determine the base URL by comparing SCRIPT_NAME to SCRIPT_FILENAME and getting common elements
|
|
|
|
// This tends not to work on CLI
|
2018-01-12 04:25:02 +01:00
|
|
|
$path = Convert::slashes($_SERVER['SCRIPT_FILENAME']);
|
|
|
|
$scriptName = Convert::slashes($_SERVER['SCRIPT_NAME'], '/');
|
|
|
|
|
|
|
|
// Ensure script is served from public folder (otherwise error)
|
2022-04-14 03:12:59 +02:00
|
|
|
if (stripos($path ?? '', PUBLIC_PATH) !== 0) {
|
2018-02-07 02:25:52 +01:00
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get entire url following PUBLIC_PATH
|
2022-04-14 03:12:59 +02:00
|
|
|
$urlSegmentToRemove = Convert::slashes(substr($path ?? '', strlen(PUBLIC_PATH)), '/');
|
|
|
|
if (substr($scriptName ?? '', -strlen($urlSegmentToRemove ?? '')) !== $urlSegmentToRemove) {
|
2018-02-07 02:25:52 +01:00
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove this from end of SCRIPT_NAME to get url to base
|
2022-04-14 03:12:59 +02:00
|
|
|
$baseURL = substr($scriptName ?? '', 0, -strlen($urlSegmentToRemove ?? ''));
|
|
|
|
$baseURL = rtrim(ltrim($baseURL ?? '', '.'), '/');
|
2018-02-07 02:25:52 +01:00
|
|
|
|
|
|
|
// When htaccess redirects from /base to /base/public folder, we need to only include /public
|
|
|
|
// in the BASE_URL if it's also present in the request
|
2019-03-26 04:29:58 +01:00
|
|
|
if (!$baseURL
|
|
|
|
|| !PUBLIC_DIR
|
|
|
|
|| !isset($_SERVER['REQUEST_URI'])
|
2022-04-14 03:12:59 +02:00
|
|
|
|| substr($baseURL ?? '', -strlen(PUBLIC_DIR)) !== PUBLIC_DIR
|
2018-02-07 02:25:52 +01:00
|
|
|
) {
|
2019-03-26 04:29:58 +01:00
|
|
|
return $baseURL;
|
|
|
|
}
|
|
|
|
|
|
|
|
$requestURI = $_SERVER['REQUEST_URI'];
|
2020-04-10 05:06:14 +02:00
|
|
|
// Check if /base/public or /base are in the request (delimited by /)
|
2022-04-14 03:12:59 +02:00
|
|
|
foreach ([$baseURL, dirname($baseURL ?? '')] as $candidate) {
|
|
|
|
if (stripos($requestURI ?? '', rtrim($candidate ?? '', '/') . '/') === 0) {
|
2019-03-20 02:33:34 +01:00
|
|
|
return $candidate;
|
2017-04-13 03:33:29 +02:00
|
|
|
}
|
2019-03-20 02:33:34 +01:00
|
|
|
}
|
2013-07-22 03:52:00 +02:00
|
|
|
|
2019-03-26 04:29:58 +01:00
|
|
|
// Ambiguous
|
|
|
|
return '';
|
2017-04-13 03:33:29 +02:00
|
|
|
}));
|
2013-07-22 03:52:00 +02:00
|
|
|
}
|
2017-04-13 03:33:29 +02:00
|
|
|
|
2013-07-22 03:52:00 +02:00
|
|
|
define('THEMES_DIR', 'themes');
|
2017-04-13 03:33:29 +02:00
|
|
|
define('THEMES_PATH', BASE_PATH . DIRECTORY_SEPARATOR . THEMES_DIR);
|
|
|
|
|
2013-07-22 03:52:00 +02:00
|
|
|
// Relies on this being in a subdir of the framework.
|
|
|
|
// If it isn't, or is symlinked to a folder with a different name, you must define FRAMEWORK_DIR
|
2016-09-12 05:13:55 +02:00
|
|
|
|
2016-11-01 04:13:06 +01:00
|
|
|
define('FRAMEWORK_PATH', realpath(__DIR__ . '/../../'));
|
2017-04-13 03:33:29 +02:00
|
|
|
if (strpos(FRAMEWORK_PATH, BASE_PATH) !== 0) {
|
2016-11-29 00:31:16 +01:00
|
|
|
throw new Exception("Path error: FRAMEWORK_PATH " . FRAMEWORK_PATH . " not within BASE_PATH " . BASE_PATH);
|
2013-07-22 03:52:00 +02:00
|
|
|
}
|
2017-04-13 03:33:29 +02:00
|
|
|
define('FRAMEWORK_DIR', trim(substr(FRAMEWORK_PATH, strlen(BASE_PATH)), DIRECTORY_SEPARATOR));
|
|
|
|
define('THIRDPARTY_DIR', FRAMEWORK_DIR ? (FRAMEWORK_DIR . '/thirdparty') : 'thirdparty');
|
|
|
|
define('THIRDPARTY_PATH', FRAMEWORK_PATH . DIRECTORY_SEPARATOR . 'thirdparty');
|
2013-07-24 02:09:44 +02:00
|
|
|
|
2016-11-29 00:31:16 +01:00
|
|
|
if (!defined('ASSETS_DIR')) {
|
|
|
|
define('ASSETS_DIR', 'assets');
|
2013-07-24 02:09:44 +02:00
|
|
|
}
|
2016-11-29 00:31:16 +01:00
|
|
|
if (!defined('ASSETS_PATH')) {
|
2018-01-12 04:25:02 +01:00
|
|
|
call_user_func(function () {
|
|
|
|
$paths = [
|
|
|
|
BASE_PATH,
|
2022-12-14 04:08:47 +01:00
|
|
|
PUBLIC_DIR,
|
2018-01-12 04:25:02 +01:00
|
|
|
ASSETS_DIR
|
|
|
|
];
|
2022-04-14 03:12:59 +02:00
|
|
|
define('ASSETS_PATH', implode(DIRECTORY_SEPARATOR, array_filter($paths ?? [])));
|
2018-01-12 04:25:02 +01:00
|
|
|
});
|
2013-10-31 23:25:19 +01:00
|
|
|
}
|
2013-07-22 03:52:00 +02:00
|
|
|
|
2016-11-01 03:45:56 +01:00
|
|
|
// Custom include path - deprecated
|
2016-11-29 00:31:16 +01:00
|
|
|
if (defined('CUSTOM_INCLUDE_PATH')) {
|
2018-01-16 19:39:30 +01:00
|
|
|
set_include_path(CUSTOM_INCLUDE_PATH . PATH_SEPARATOR . get_include_path());
|
2013-07-22 03:52:00 +02:00
|
|
|
}
|
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
// Define the temporary folder if it wasn't defined yet
|
2017-10-09 01:41:34 +02:00
|
|
|
if (!defined('TEMP_PATH')) {
|
|
|
|
if (defined('TEMP_FOLDER')) {
|
|
|
|
define('TEMP_PATH', TEMP_FOLDER);
|
2021-11-15 21:35:28 +01:00
|
|
|
} elseif ($path = Environment::getEnv('SS_TEMP_PATH')) {
|
|
|
|
// If path is relative, rewrite it to be relative to BASE_PATH - as web requests are relative to
|
|
|
|
// public/index.php, and we don't want the TEMP_PATH to be inside the public/ directory by default
|
2022-04-14 03:12:59 +02:00
|
|
|
if (ltrim($path ?? '', DIRECTORY_SEPARATOR) === $path) {
|
2021-11-15 21:35:28 +01:00
|
|
|
$path = BASE_PATH . DIRECTORY_SEPARATOR . $path;
|
|
|
|
}
|
|
|
|
define('TEMP_PATH', $path);
|
2017-10-09 01:41:34 +02:00
|
|
|
} else {
|
|
|
|
define('TEMP_PATH', TempFolder::getTempFolder(BASE_PATH));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Define the temporary folder for backwards compatibility
|
2016-11-29 00:31:16 +01:00
|
|
|
if (!defined('TEMP_FOLDER')) {
|
2017-10-09 01:41:34 +02:00
|
|
|
define('TEMP_FOLDER', TEMP_PATH);
|
2013-07-22 03:52:00 +02:00
|
|
|
}
|
2019-01-09 03:35:45 +01:00
|
|
|
|
2021-12-13 09:05:33 +01:00
|
|
|
// Define the resource dir constant that will be use to exposed vendor assets
|
2019-01-09 03:35:45 +01:00
|
|
|
if (!defined('RESOURCES_DIR')) {
|
|
|
|
$project = new SilverStripe\Core\Manifest\Module(BASE_PATH, BASE_PATH);
|
2022-08-04 01:36:54 +02:00
|
|
|
$resourcesDir = $project->getResourcesDir() ?: '_resources';
|
2022-04-14 03:12:59 +02:00
|
|
|
if (preg_match('/^[_\-a-z0-9]+$/i', $resourcesDir ?? '')) {
|
2019-01-09 03:35:45 +01:00
|
|
|
define('RESOURCES_DIR', $resourcesDir);
|
|
|
|
} else {
|
|
|
|
throw new LogicException(sprintf(
|
|
|
|
'Resources dir error: "%s" is not a valid resources directory name. Update the ' .
|
|
|
|
'`extra.resources-dir` key in your composer.json file',
|
|
|
|
$resourcesDir
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|