2011-10-29 05:40:07 +02:00
< ? php
/************************************************************************************
************************************************************************************
** **
** If you can read this text in your browser then you don ' t have PHP installed . **
2013-10-23 10:10:42 +02:00
** Please install PHP 5.3 . 3 or higher , preferably PHP 5.3 . 4 +. **
2011-10-29 05:40:07 +02:00
** **
************************************************************************************
************************************************************************************/
/**
* SilverStripe CMS Installer
2012-03-24 04:38:57 +01:00
* This installer doesn 't use any of the fancy SilverStripe stuff in case it' s unsupported .
2011-10-29 05:40:07 +02:00
*/
// speed up mysql_connect timeout if the server can't be found
ini_set ( 'mysql.connect_timeout' , 5 );
2012-06-26 23:41:08 +02:00
// Don't die half was through installation; that does more harm than good
2011-10-29 05:40:07 +02:00
ini_set ( 'max_execution_time' , 0 );
2013-10-03 23:05:28 +02:00
// set display_errors php setting to on to force installer to avoid blank screen of death.
// get the original value so it can be used in PHP requirement checks later in this script.
$originalDisplayErrorsValue = ini_get ( 'display_errors' );
ini_set ( 'display_errors' , '1' );
2012-04-14 03:25:12 +02:00
error_reporting ( E_ALL | E_STRICT );
2011-10-29 05:40:07 +02:00
2012-04-27 01:01:30 +02:00
// Attempt to start a session so that the username and password can be sent back to the user.
2013-10-16 22:17:22 +02:00
if ( function_exists ( 'session_start' ) && ! session_id ()) {
2012-04-27 01:01:30 +02:00
session_start ();
}
2013-05-22 13:29:19 +02:00
/**
* Include _ss_environment . php file
*/
2013-05-24 16:29:39 +02:00
$usingEnv = false ;
$envFileExists = false ;
2013-01-18 14:50:24 +01:00
//define the name of the environment file
$envFile = '_ss_environment.php' ;
2013-05-22 13:29:19 +02:00
//define the dirs to start scanning from (have to add the trailing slash)
// we're going to check the realpath AND the path as the script sees it
$dirsToCheck = array (
realpath ( '.' ),
dirname ( $_SERVER [ 'SCRIPT_FILENAME' ])
);
//if they are the same, remove one of them
2013-10-16 22:17:22 +02:00
if ( $dirsToCheck [ 0 ] == $dirsToCheck [ 1 ]) {
2013-05-22 13:29:19 +02:00
unset ( $dirsToCheck [ 1 ]);
}
2013-10-16 22:17:22 +02:00
foreach ( $dirsToCheck as $dir ) {
2013-01-18 14:50:24 +01:00
//check this dir and every parent dir (until we hit the base of the drive)
2013-05-22 13:29:19 +02:00
// or until we hit a dir we can't read
2013-10-16 22:11:06 +02:00
do {
2013-05-22 13:29:19 +02:00
//add the trailing slash we need to concatenate properly
$dir .= DIRECTORY_SEPARATOR ;
//if it's readable, go ahead
2013-10-16 22:17:22 +02:00
if ( @ is_readable ( $dir )) {
2013-10-16 22:11:06 +02:00
//if the file exists, then we include it, set relevant vars and break out
2013-10-16 22:17:22 +02:00
if ( file_exists ( $dir . $envFile )) {
2013-10-16 22:11:06 +02:00
include_once ( $dir . $envFile );
$envFileExists = true ;
//legacy variable assignment
$usingEnv = true ;
2013-05-22 13:29:19 +02:00
//break out of BOTH loops because we found the $envFile
break ( 2 );
}
2013-10-16 22:11:06 +02:00
} else {
2013-05-22 13:29:19 +02:00
//break out of the while loop, we can't read the dir
2013-10-16 22:11:06 +02:00
break ;
}
2013-05-22 13:29:19 +02:00
//go up a directory
$dir = dirname ( $dir );
2013-10-16 22:11:06 +02:00
//here we need to check that the path of the last dir and the next one are
2013-01-18 14:50:24 +01:00
// not the same, if they are, we have hit the root of the drive
2013-10-16 22:17:22 +02:00
} while ( dirname ( $dir ) != $dir );
2013-05-22 13:29:19 +02:00
}
2011-10-29 05:40:07 +02:00
if ( $envFileExists ) {
if ( ! empty ( $_REQUEST [ 'useEnv' ])) {
$usingEnv = true ;
} else {
$usingEnv = false ;
}
}
2013-11-01 01:53:53 +01:00
require_once FRAMEWORK_NAME . '/core/Constants.php' ; // this also includes TempPath.php
2012-04-17 00:52:28 +02:00
require_once FRAMEWORK_NAME . '/dev/install/DatabaseConfigurationHelper.php' ;
require_once FRAMEWORK_NAME . '/dev/install/DatabaseAdapterRegistry.php' ;
2011-10-29 05:40:07 +02:00
// Set default locale, but try and sniff from the user agent
2012-04-17 00:52:28 +02:00
$defaultLocale = 'en_US' ;
$locales = array (
2013-10-16 22:11:06 +02:00
'af_ZA' => 'Afrikaans (South Africa)' ,
'ar_EG' => 'Arabic (Egypt)' ,
'hy_AM' => 'Armenian (Armenia)' ,
'ast_ES' => 'Asturian (Spain)' ,
'az_AZ' => 'Azerbaijani (Azerbaijan)' ,
'bs_BA' => 'Bosnian (Bosnia and Herzegovina)' ,
'bg_BG' => 'Bulgarian (Bulgaria)' ,
'ca_ES' => 'Catalan (Spain)' ,
'zh_CN' => 'Chinese (China)' ,
'zh_TW' => 'Chinese (Taiwan)' ,
'hr_HR' => 'Croatian (Croatia)' ,
'cs_CZ' => 'Czech (Czech Republic)' ,
'da_DK' => 'Danish (Denmark)' ,
'nl_NL' => 'Dutch (Netherlands)' ,
'en_GB' => 'English (United Kingdom)' ,
'en_US' => 'English (United States)' ,
'eo_XX' => 'Esperanto' ,
'et_EE' => 'Estonian (Estonia)' ,
'fo_FO' => 'Faroese (Faroe Islands)' ,
'fi_FI' => 'Finnish (Finland)' ,
'fr_FR' => 'French (France)' ,
'de_DE' => 'German (Germany)' ,
'el_GR' => 'Greek (Greece)' ,
'he_IL' => 'Hebrew (Israel)' ,
'hu_HU' => 'Hungarian (Hungary)' ,
'is_IS' => 'Icelandic (Iceland)' ,
'id_ID' => 'Indonesian (Indonesia)' ,
'it_IT' => 'Italian (Italy)' ,
'ja_JP' => 'Japanese (Japan)' ,
'km_KH' => 'Khmer (Cambodia)' ,
'lc_XX' => 'LOLCAT' ,
'lv_LV' => 'Latvian (Latvia)' ,
'lt_LT' => 'Lithuanian (Lithuania)' ,
'ms_MY' => 'Malay (Malaysia)' ,
'mi_NZ' => 'Maori (New Zealand)' ,
'ne_NP' => 'Nepali (Nepal)' ,
'nb_NO' => 'Norwegian' ,
'fa_IR' => 'Persian (Iran)' ,
'pl_PL' => 'Polish (Poland)' ,
'pt_BR' => 'Portuguese (Brazil)' ,
'pa_IN' => 'Punjabi (India)' ,
'ro_RO' => 'Romanian (Romania)' ,
'ru_RU' => 'Russian (Russia)' ,
'sr_RS' => 'Serbian (Serbia)' ,
'si_LK' => 'Sinhalese (Sri Lanka)' ,
'sk_SK' => 'Slovak (Slovakia)' ,
'sl_SI' => 'Slovenian (Slovenia)' ,
'es_AR' => 'Spanish (Argentina)' ,
'es_MX' => 'Spanish (Mexico)' ,
'es_ES' => 'Spanish (Spain)' ,
'sv_SE' => 'Swedish (Sweden)' ,
'th_TH' => 'Thai (Thailand)' ,
'tr_TR' => 'Turkish (Turkey)' ,
'uk_UA' => 'Ukrainian (Ukraine)' ,
'uz_UZ' => 'Uzbek (Uzbekistan)' ,
'vi_VN' => 'Vietnamese (Vietnam)' ,
2012-04-17 00:52:28 +02:00
);
2011-10-29 05:40:07 +02:00
// Discover which databases are available
DatabaseAdapterRegistry :: autodiscover ();
// Determine which external database modules are USABLE
foreach ( DatabaseAdapterRegistry :: get_adapters () as $class => $details ) {
$databaseClasses [ $class ] = $details ;
if ( file_exists ( $details [ 'helperPath' ])) {
$databaseClasses [ $class ][ 'hasModule' ] = true ;
include_once ( $details [ 'helperPath' ]);
} else {
$databaseClasses [ $class ][ 'hasModule' ] = false ;
}
}
// Load database config
if ( isset ( $_REQUEST [ 'db' ])) {
if ( isset ( $_REQUEST [ 'db' ][ 'type' ])) $type = $_REQUEST [ 'db' ][ 'type' ];
else $type = $_REQUEST [ 'db' ][ 'type' ] = defined ( 'SS_DATABASE_CLASS' ) ? SS_DATABASE_CLASS : 'MySQLDatabase' ;
// Disabled inputs don't submit anything - we need to use the environment (except the database name)
if ( $usingEnv ) {
$_REQUEST [ 'db' ][ $type ] = $databaseConfig = array (
" type " => defined ( 'SS_DATABASE_CLASS' ) ? SS_DATABASE_CLASS : $type ,
" server " => defined ( 'SS_DATABASE_SERVER' ) ? SS_DATABASE_SERVER : " localhost " ,
" username " => defined ( 'SS_DATABASE_USERNAME' ) ? SS_DATABASE_USERNAME : " root " ,
" password " => defined ( 'SS_DATABASE_PASSWORD' ) ? SS_DATABASE_PASSWORD : " " ,
" database " => $_REQUEST [ 'db' ][ $type ][ 'database' ],
);
} else {
// Normal behaviour without the environment
$databaseConfig = $_REQUEST [ 'db' ][ $type ];
$databaseConfig [ 'type' ] = $type ;
}
} else {
$type = $_REQUEST [ 'db' ][ 'type' ] = defined ( 'SS_DATABASE_CLASS' ) ? SS_DATABASE_CLASS : 'MySQLDatabase' ;
$_REQUEST [ 'db' ][ $type ] = $databaseConfig = array (
" type " => $type ,
" server " => defined ( 'SS_DATABASE_SERVER' ) ? SS_DATABASE_SERVER : " localhost " ,
" username " => defined ( 'SS_DATABASE_USERNAME' ) ? SS_DATABASE_USERNAME : " root " ,
" password " => defined ( 'SS_DATABASE_PASSWORD' ) ? SS_DATABASE_PASSWORD : " " ,
" database " => isset ( $_SERVER [ 'argv' ][ 2 ]) ? $_SERVER [ 'argv' ][ 2 ] : " SS_mysite " ,
);
}
if ( isset ( $_REQUEST [ 'admin' ])) {
// Disabled inputs don't submit anything - we need to use the environment (except the database name)
if ( $usingEnv ) {
$_REQUEST [ 'admin' ] = $adminConfig = array (
'username' => defined ( 'SS_DEFAULT_ADMIN_USERNAME' ) ? SS_DEFAULT_ADMIN_USERNAME : 'admin' ,
'password' => defined ( 'SS_DEFAULT_ADMIN_PASSWORD' ) ? SS_DEFAULT_ADMIN_PASSWORD : '' ,
);
} else {
$adminConfig = $_REQUEST [ 'admin' ];
}
} else {
$_REQUEST [ 'admin' ] = $adminConfig = array (
'username' => defined ( 'SS_DEFAULT_ADMIN_USERNAME' ) ? SS_DEFAULT_ADMIN_USERNAME : 'admin' ,
'password' => defined ( 'SS_DEFAULT_ADMIN_PASSWORD' ) ? SS_DEFAULT_ADMIN_PASSWORD : '' ,
);
}
$alreadyInstalled = false ;
if ( file_exists ( 'mysite/_config.php' )) {
// Find the $database variable in the relevant config file without having to execute the config file
if ( preg_match ( " / \\ \$ database \ s*= \ s*[^ \n \r ]+[ \n \r ]/ " , file_get_contents ( " mysite/_config.php " ), $parts )) {
eval ( $parts [ 0 ]);
if ( $database ) $alreadyInstalled = true ;
2013-10-16 22:11:06 +02:00
// Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has
// already gone ahead
2011-10-29 05:40:07 +02:00
} else if ( preg_match ( " / \\ \$ databaseConfig \ s*= \ s*[^ \n \r ]+[ \n \r ]/ " , file_get_contents ( " mysite/_config.php " ), $parts )) {
$alreadyInstalled = true ;
}
}
2012-03-24 04:38:57 +01:00
if ( file_exists ( FRAMEWORK_NAME . '/silverstripe_version' )) {
$silverstripe_version = file_get_contents ( FRAMEWORK_NAME . '/silverstripe_version' );
2011-10-29 05:40:07 +02:00
} else {
$silverstripe_version = " unknown " ;
}
// Check requirements
$req = new InstallRequirements ();
$req -> check ();
$webserverConfigFile = '' ;
if ( $req -> isIIS ()) {
$webserverConfigFile = 'web.config' ;
} else {
$webserverConfigFile = '.htaccess' ;
}
if ( $req -> hasErrors ()) {
$hasErrorOtherThanDatabase = true ;
2012-04-16 03:11:21 +02:00
$phpIniLocation = php_ini_loaded_file ();
2011-10-29 05:40:07 +02:00
}
if ( $databaseConfig ) {
$dbReq = new InstallRequirements ();
$dbReq -> checkDatabase ( $databaseConfig );
}
if ( $adminConfig ) {
$adminReq = new InstallRequirements ();
$adminReq -> checkAdminConfig ( $adminConfig );
}
// Actual processor
$installFromCli = ( isset ( $_SERVER [ 'argv' ][ 1 ]) && $_SERVER [ 'argv' ][ 1 ] == 'install' );
// CLI-install error message. exit(1) will halt any makefile.
if ( $installFromCli && ( $req -> hasErrors () || $dbReq -> hasErrors ())) {
echo " Cannot install due to errors: \n " ;
$req -> listErrors ();
$dbReq -> listErrors ();
exit ( 1 );
}
if (( isset ( $_REQUEST [ 'go' ]) || $installFromCli ) && ! $req -> hasErrors () && ! $dbReq -> hasErrors () && $adminConfig [ 'username' ] && $adminConfig [ 'password' ]) {
// Confirm before reinstalling
if ( ! $installFromCli && $alreadyInstalled ) {
2012-03-24 04:38:57 +01:00
include ( FRAMEWORK_NAME . '/dev/install/config-form.html' );
2011-10-29 05:40:07 +02:00
} else {
$inst = new Installer ();
if ( $_REQUEST ) $inst -> install ( $_REQUEST );
else $inst -> install ( array (
'db' => $databaseConfig ,
'admin' => $adminConfig ,
));
}
// Show the config form
} else {
2012-03-24 04:38:57 +01:00
include ( FRAMEWORK_NAME . '/dev/install/config-form.html' );
2011-10-29 05:40:07 +02:00
}
/**
* This class checks requirements
* Each of the requireXXX functions takes an argument which gives a user description of the test .
* It ' s an array of 3 parts :
* $description [ 0 ] - The test catetgory
* $description [ 1 ] - The test title
* $description [ 2 ] - The test error to show , if it goes wrong
*/
class InstallRequirements {
var $errors , $warnings , $tests ;
/**
* Check the database configuration . These are done one after another
* starting with checking the database function exists in PHP , and
* continuing onto more difficult checks like database permissions .
*/
function checkDatabase ( $databaseConfig ) {
if ( $this -> requireDatabaseFunctions (
$databaseConfig ,
array (
" Database Configuration " ,
" Database support " ,
" Database support in PHP " ,
$this -> getDatabaseTypeNice ( $databaseConfig [ 'type' ])
)
)) {
if ( $this -> requireDatabaseServer (
$databaseConfig ,
array (
" Database Configuration " ,
" Database server " ,
$databaseConfig [ 'type' ] == 'SQLiteDatabase' ? " I couldn't write to path ' $databaseConfig[path] ' " : " I couldn't find a database server on ' $databaseConfig[server] ' " ,
$databaseConfig [ 'type' ] == 'SQLiteDatabase' ? $databaseConfig [ 'path' ] : $databaseConfig [ 'server' ]
)
)) {
if ( $this -> requireDatabaseConnection (
$databaseConfig ,
array (
" Database Configuration " ,
2012-04-26 21:43:38 +02:00
" Database access credentials " ,
2011-10-29 05:40:07 +02:00
" That username/password doesn't work "
)
)) {
if ( $this -> requireDatabaseVersion (
$databaseConfig ,
array (
" Database Configuration " ,
2012-04-26 21:43:38 +02:00
" Database server version requirement " ,
2011-10-29 05:40:07 +02:00
'' ,
'Version ' . $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]) -> getDatabaseVersion ( $databaseConfig )
)
)) {
2013-03-21 15:04:51 +01:00
if ( $this -> requireDatabaseOrCreatePermissions (
2011-10-29 05:40:07 +02:00
$databaseConfig ,
array (
" Database Configuration " ,
" Can I access/create the database " ,
" I can't create new databases and the database ' $databaseConfig[database] ' doesn't exist "
)
2013-03-21 15:04:51 +01:00
)) {
$this -> requireDatabaseAlterPermissions (
$databaseConfig ,
array (
" Database Configuration " ,
" Can I ALTER tables " ,
" I don't have permission to ALTER tables "
)
);
}
2011-10-29 05:40:07 +02:00
}
}
}
}
}
function checkAdminConfig ( $adminConfig ) {
if ( ! $adminConfig [ 'username' ]) {
$this -> error ( array ( '' , 'Please enter a username!' ));
}
if ( ! $adminConfig [ 'password' ]) {
$this -> error ( array ( '' , 'Please enter a password!' ));
}
}
/**
* Check if the web server is IIS .
* @ return boolean
*/
function isIIS ( $version = 7 ) {
if ( strpos ( $this -> findWebserver (), 'IIS/' . $version ) !== false ) {
return true ;
} else {
return false ;
}
}
function isApache () {
if ( strpos ( $this -> findWebserver (), 'Apache' ) !== false ) {
return true ;
} else {
return false ;
}
}
/**
* Find the webserver software running on the PHP host .
* @ return string | boolean Server software or boolean FALSE
*/
function findWebserver () {
// Try finding from SERVER_SIGNATURE or SERVER_SOFTWARE
$webserver = @ $_SERVER [ 'SERVER_SIGNATURE' ];
if ( ! $webserver ) $webserver = @ $_SERVER [ 'SERVER_SOFTWARE' ];
if ( $webserver ) return strip_tags ( trim ( $webserver ));
else return false ;
}
/**
* Check everything except the database
*/
function check () {
$this -> errors = null ;
$isApache = $this -> isApache ();
$isIIS = $this -> isIIS ( 7 );
$webserver = $this -> findWebserver ();
2013-10-23 10:10:42 +02:00
$this -> requirePHPVersion ( '5.3.4' , '5.3.3' , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" PHP5 installed " ,
null ,
" PHP version " . phpversion ()
));
2011-10-29 05:40:07 +02:00
// Check that we can identify the root folder successfully
2012-03-24 04:38:57 +01:00
$this -> requireFile ( FRAMEWORK_NAME . '/dev/install/config-form.html' , array ( " File permissions " ,
2011-10-29 05:40:07 +02:00
" Does the webserver know where files are stored? " ,
" The webserver isn't letting me identify where files are stored. " ,
$this -> getBaseDir ()
));
$this -> requireModule ( 'mysite' , array ( " File permissions " , " mysite/ directory exists? " ));
2012-03-24 04:38:57 +01:00
$this -> requireModule ( FRAMEWORK_NAME , array ( " File permissions " , FRAMEWORK_NAME . " / directory exists? " ));
2011-10-29 05:40:07 +02:00
if ( $isApache ) {
2013-10-16 22:00:20 +02:00
$this -> checkApacheVersion ( array (
2013-10-16 22:11:06 +02:00
" Webserver Configuration " ,
" Webserver is not Apache 1.x " , " SilverStripe requires Apache version 2 or greater " ,
$webserver
));
2011-10-29 05:40:07 +02:00
$this -> requireWriteable ( '.htaccess' , array ( " File permissions " , " Is the .htaccess file writeable? " , null ));
} elseif ( $isIIS ) {
$this -> requireWriteable ( 'web.config' , array ( " File permissions " , " Is the web.config file writeable? " , null ));
}
2013-10-16 22:00:20 +02:00
$this -> requireWriteable ( 'mysite/_config.php' , array (
2013-10-16 22:11:06 +02:00
" File permissions " ,
" Is the mysite/_config.php file writeable? " ,
null
));
2013-10-16 22:17:22 +02:00
if ( ! $this -> checkModuleExists ( 'cms' )) {
2013-10-16 22:00:20 +02:00
$this -> requireWriteable ( 'mysite/code/RootURLController.php' , array (
2013-10-16 22:11:06 +02:00
" File permissions " ,
" Is the mysite/code/RootURLController.php file writeable? " ,
null
));
2011-10-29 06:23:09 +02:00
}
2011-10-29 05:40:07 +02:00
$this -> requireWriteable ( 'assets' , array ( " File permissions " , " Is the assets/ directory writeable? " , null ));
2013-11-01 01:53:53 +01:00
try {
$tempFolder = getTempFolder ();
} catch ( Exception $e ) {
$tempFolder = false ;
}
2011-10-29 05:40:07 +02:00
$this -> requireTempFolder ( array ( 'File permissions' , 'Is a temporary directory available?' , null , $tempFolder ));
if ( $tempFolder ) {
// in addition to the temp folder being available, check it is writable
2013-10-16 22:00:20 +02:00
$this -> requireWriteable ( $tempFolder , array (
2013-10-16 22:11:06 +02:00
" File permissions " ,
sprintf ( " Is the temporary directory writeable? " , $tempFolder ),
null
), true );
2011-10-29 05:40:07 +02:00
}
// Check for web server, unless we're calling the installer from the command-line
2012-04-15 05:05:20 +02:00
$this -> isRunningWebServer ( array ( " Webserver Configuration " , " Server software " , " Unknown " , $webserver ));
2011-10-29 05:40:07 +02:00
2012-04-15 05:05:20 +02:00
if ( $isApache ) {
2013-10-16 22:00:20 +02:00
$this -> requireApacheRewriteModule ( 'mod_rewrite' , array (
2013-10-16 22:11:06 +02:00
" Webserver Configuration " ,
" URL rewriting support " ,
" You need mod_rewrite to use friendly URLs with SilverStripe, but it is not enabled. "
));
2012-04-15 05:05:20 +02:00
} elseif ( $isIIS ) {
2013-10-16 22:00:20 +02:00
$this -> requireIISRewriteModule ( 'IIS_UrlRewriteModule' , array (
2013-10-16 22:11:06 +02:00
" Webserver Configuration " ,
" URL rewriting support " ,
" You need to enable the IIS URL Rewrite Module to use friendly URLs with SilverStripe, "
. " but it is not installed or enabled. Download it for IIS 7 from http://www.iis.net/expand/URLRewrite "
));
2012-04-15 05:05:20 +02:00
} else {
2013-10-16 22:00:20 +02:00
$this -> warning ( array (
2013-10-16 22:11:06 +02:00
" Webserver Configuration " ,
" URL rewriting support " ,
" I can't tell whether any rewriting module is running. You may need to configure a rewriting rule yourself. " ));
2011-10-29 05:40:07 +02:00
}
2013-10-16 22:11:06 +02:00
$this -> requireServerVariables ( array ( 'SCRIPT_NAME' , 'HTTP_HOST' , 'SCRIPT_FILENAME' ), array (
" Webserver Configuration " ,
" Recognised webserver " ,
" You seem to be using an unsupported webserver. "
. " The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set. "
));
2013-05-08 12:48:50 +02:00
2013-10-16 22:00:20 +02:00
$this -> requirePostSupport ( array (
2013-10-16 22:11:06 +02:00
" Webserver Configuration " ,
" POST Support " ,
'I can\'t find $_POST, make sure POST is enabled.'
));
2012-04-15 05:05:20 +02:00
2011-10-29 05:40:07 +02:00
// Check for GD support
2013-10-16 22:17:22 +02:00
if ( ! $this -> requireFunction ( " imagecreatetruecolor " , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" GD2 support " ,
" PHP must have GD version 2. "
2013-10-16 22:00:20 +02:00
))) {
$this -> requireFunction ( " imagecreate " , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" GD2 support " ,
" GD support for PHP not included. "
));
2011-10-29 05:40:07 +02:00
}
// Check for XML support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'xml_set_object' , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" XML support " ,
" XML support not included in PHP. "
));
2013-10-16 22:00:20 +02:00
$this -> requireClass ( 'DOMDocument' , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" DOM/XML support " ,
" DOM/XML support not included in PHP. "
));
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'simplexml_load_file' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'SimpleXML support' ,
'SimpleXML support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for token_get_all
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'token_get_all' , array (
2013-10-16 22:11:06 +02:00
" PHP Configuration " ,
" Tokenizer support " ,
" Tokenizer support not included in PHP. "
));
2012-04-22 07:45:56 +02:00
// Check for CType support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'ctype_digit' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'CType support' ,
'CType support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for session support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'session_start' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'Session support' ,
'Session support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for iconv support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'iconv' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'iconv support' ,
'iconv support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for hash support
2012-05-14 04:06:25 +02:00
$this -> requireFunction ( 'hash' , array ( 'PHP Configuration' , 'hash support' , 'hash support not included in PHP.' ));
// Check for mbstring support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'mb_internal_encoding' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'mbstring support' ,
'mbstring support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for Reflection support
2013-10-16 22:00:20 +02:00
$this -> requireClass ( 'ReflectionClass' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'Reflection support' ,
'Reflection support not included in PHP.'
));
2011-10-29 05:40:07 +02:00
// Check for Standard PHP Library (SPL) support
2013-10-16 22:00:20 +02:00
$this -> requireFunction ( 'spl_classes' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'SPL support' ,
'Standard PHP Library (SPL) not included in PHP.'
));
2011-10-29 05:40:07 +02:00
2013-10-16 22:00:20 +02:00
$this -> requireDateTimezone ( array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'date.timezone setting and validity' ,
'date.timezone option in php.ini must be set correctly.' ,
ini_get ( 'date.timezone' )
));
2011-10-29 05:40:07 +02:00
2013-10-16 22:00:20 +02:00
$this -> suggestClass ( 'finfo' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'fileinfo support' ,
'fileinfo should be enabled in PHP. SilverStripe uses it for MIME type detection of files. '
. 'SilverStripe will still operate, but email attachments and sending files to browser '
. '(e.g. export data to CSV) may not work correctly without finfo.'
));
2012-05-14 04:06:25 +02:00
2013-10-16 22:00:20 +02:00
$this -> suggestFunction ( 'curl_init' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'curl support' ,
'curl should be enabled in PHP. SilverStripe uses it for consuming web services'
. ' via the RestfulService class and many modules rely on it.'
));
2013-05-11 08:31:02 +02:00
2013-10-16 22:00:20 +02:00
$this -> suggestClass ( 'tidy' , array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'tidy support' ,
'Tidy provides a library of code to clean up your html. '
. 'SilverStripe will operate fine without tidy but HTMLCleaner will not be effective.'
));
2013-05-11 08:31:02 +02:00
2013-10-16 22:00:20 +02:00
$this -> suggestPHPSetting ( 'asp_tags' , array ( false ), array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'asp_tags option' ,
'This should be turned off as it can cause issues with SilverStripe'
));
2013-10-16 22:00:20 +02:00
$this -> requirePHPSetting ( 'magic_quotes_gpc' , array ( false ), array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'magic_quotes_gpc option' ,
'This should be turned off, as it can cause issues with cookies. '
. 'More specifically, unserializing data stored in cookies.'
));
2013-10-16 22:00:20 +02:00
$this -> suggestPHPSetting ( 'display_errors' , array ( false ), array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'display_errors option' ,
'Unless you\'re in a development environment, this should be turned off, '
. 'as it can expose sensitive data to website users.'
));
2013-10-16 22:00:20 +02:00
// on some weirdly configured webservers arg_separator.output is set to &
2013-10-16 22:11:06 +02:00
// which will results in links like ?param=value&foo=bar which will not be i
2013-10-16 22:00:20 +02:00
$this -> suggestPHPSetting ( 'arg_separator.output' , array ( '&' , '' ), array (
2013-10-16 22:11:06 +02:00
'PHP Configuration' ,
'arg_separator.output option' ,
'This option defines how URL parameters are concatenated. '
. 'If not set to \'&\' this may cause issues with URL GET parameters'
));
2011-10-29 05:40:07 +02:00
// Check memory allocation
2013-10-16 22:11:06 +02:00
$this -> requireMemory ( 32 * 1024 * 1024 , 64 * 1024 * 1024 , array (
" PHP Configuration " ,
" Memory allocation (PHP config option 'memory_limit') " ,
" SilverStripe needs a minimum of 32M allocated to PHP, but recommends 64M. " ,
ini_get ( " memory_limit " )
));
2011-10-29 05:40:07 +02:00
return $this -> errors ;
}
function suggestPHPSetting ( $settingName , $settingValues , $testDetails ) {
$this -> testing ( $testDetails );
2013-05-08 12:48:50 +02:00
2013-10-03 23:05:28 +02:00
// special case for display_errors, check the original value before
// it was changed at the start of this script.
2013-10-23 05:32:31 +02:00
if ( $settingName == 'display_errors' ) {
2013-10-16 11:28:33 +02:00
global $originalDisplayErrorsValue ;
2013-10-03 23:05:28 +02:00
$val = $originalDisplayErrorsValue ;
} else {
$val = ini_get ( $settingName );
}
2011-10-29 05:40:07 +02:00
if ( ! in_array ( $val , $settingValues ) && $val != $settingValues ) {
$testDetails [ 2 ] = " $settingName is set to ' $val ' in php.ini. $testDetails[2] " ;
$this -> warning ( $testDetails );
}
}
2013-05-25 02:28:05 +02:00
function requirePHPSetting ( $settingName , $settingValues , $testDetails ) {
$this -> testing ( $testDetails );
$val = ini_get ( $settingName );
if ( ! in_array ( $val , $settingValues ) && $val != $settingValues ) {
$testDetails [ 2 ] = " $settingName is set to ' $val ' in php.ini. $testDetails[2] " ;
$this -> error ( $testDetails );
2011-10-29 05:40:07 +02:00
}
}
2012-05-14 04:06:25 +02:00
function suggestClass ( $class , $testDetails ) {
$this -> testing ( $testDetails );
2013-05-08 12:48:50 +02:00
2012-05-14 04:06:25 +02:00
if ( ! class_exists ( $class )) {
$this -> warning ( $testDetails );
}
}
2013-05-11 08:31:02 +02:00
function suggestFunction ( $class , $testDetails ) {
$this -> testing ( $testDetails );
if ( ! function_exists ( $class )) {
$this -> warning ( $testDetails );
}
}
2011-10-29 05:40:07 +02:00
function requireDateTimezone ( $testDetails ) {
$this -> testing ( $testDetails );
2013-05-08 12:48:50 +02:00
2011-10-29 05:40:07 +02:00
$result = ini_get ( 'date.timezone' ) && in_array ( ini_get ( 'date.timezone' ), timezone_identifiers_list ());
if ( ! $result ) {
$this -> error ( $testDetails );
}
}
function requireMemory ( $min , $recommended , $testDetails ) {
$_SESSION [ 'forcemem' ] = false ;
$mem = $this -> getPHPMemory ();
if ( $mem < ( 64 * 1024 * 1024 )) {
ini_set ( 'memory_limit' , '64M' );
$mem = $this -> getPHPMemory ();
$testDetails [ 3 ] = ini_get ( " memory_limit " );
}
$this -> testing ( $testDetails );
if ( $mem < $min && $mem > 0 ) {
$testDetails [ 2 ] .= " You only have " . ini_get ( " memory_limit " ) . " allocated " ;
$this -> error ( $testDetails );
} else if ( $mem < $recommended && $mem > 0 ) {
$testDetails [ 2 ] .= " You only have " . ini_get ( " memory_limit " ) . " allocated " ;
$this -> warning ( $testDetails );
} elseif ( $mem == 0 ) {
2013-10-16 22:00:20 +02:00
$testDetails [ 2 ] .= " We can't determine how much memory you have allocated. "
2013-10-16 22:11:06 +02:00
. " Install only if you're sure you've allocated at least 20 MB. " ;
2011-10-29 05:40:07 +02:00
$this -> warning ( $testDetails );
}
}
function getPHPMemory () {
$memString = ini_get ( " memory_limit " );
2013-10-16 22:17:22 +02:00
switch ( strtolower ( substr ( $memString , - 1 ))) {
2011-10-29 05:40:07 +02:00
case " k " :
2013-10-16 22:11:06 +02:00
return round ( substr ( $memString , 0 , - 1 ) * 1024 );
2011-10-29 05:40:07 +02:00
case " m " :
2013-10-16 22:11:06 +02:00
return round ( substr ( $memString , 0 , - 1 ) * 1024 * 1024 );
2011-10-29 05:40:07 +02:00
case " g " :
2013-10-16 22:11:06 +02:00
return round ( substr ( $memString , 0 , - 1 ) * 1024 * 1024 * 1024 );
2011-10-29 05:40:07 +02:00
default :
return round ( $memString );
}
}
function listErrors () {
if ( $this -> errors ) {
echo " <p>The following problems are preventing me from installing SilverStripe CMS:</p> \n \n " ;
foreach ( $this -> errors as $error ) {
2011-11-29 10:43:06 +01:00
echo " <li> " . htmlentities ( implode ( " , " , $error ), ENT_COMPAT , 'UTF-8' ) . " </li> \n " ;
2011-10-29 05:40:07 +02:00
}
}
}
function showTable ( $section = null ) {
if ( $section ) {
$tests = $this -> tests [ $section ];
$id = strtolower ( str_replace ( ' ' , '_' , $section ));
echo " <table id= \" { $id } _results \" class= \" testResults \" width= \" 100% \" > " ;
foreach ( $tests as $test => $result ) {
2013-10-16 22:00:20 +02:00
echo " <tr class= \" $result[0] \" ><td> $test </td><td> "
2013-10-16 22:11:06 +02:00
. nl2br ( htmlentities ( $result [ 1 ], ENT_COMPAT , 'UTF-8' )) . " </td></tr> " ;
2011-10-29 05:40:07 +02:00
}
echo " </table> " ;
} else {
foreach ( $this -> tests as $section => $tests ) {
$failedRequirements = 0 ;
$warningRequirements = 0 ;
$output = " " ;
foreach ( $tests as $test => $result ) {
if ( isset ( $result [ '0' ])) {
switch ( $result [ '0' ]) {
case 'error' :
$failedRequirements ++ ;
break ;
case 'warning' :
$warningRequirements ++ ;
break ;
}
}
2013-10-16 22:00:20 +02:00
$output .= " <tr class= \" $result[0] \" ><td> $test </td><td> "
2013-10-16 22:11:06 +02:00
. nl2br ( htmlentities ( $result [ 1 ], ENT_COMPAT , 'UTF-8' )) . " </td></tr> " ;
2011-10-29 05:40:07 +02:00
}
$className = " good " ;
$text = " All Requirements Pass " ;
$pluralWarnings = ( $warningRequirements == 1 ) ? 'Warning' : 'Warnings' ;
if ( $failedRequirements > 0 ) {
$className = " error " ;
$pluralWarnings = ( $warningRequirements == 1 ) ? 'Warning' : 'Warnings' ;
2013-10-16 22:11:06 +02:00
$text = $failedRequirements . ' Failed and ' . $warningRequirements . ' ' . $pluralWarnings ;
2013-10-16 22:17:22 +02:00
} else if ( $warningRequirements > 0 ) {
2011-10-29 05:40:07 +02:00
$className = " warning " ;
2013-10-16 22:11:06 +02:00
$text = " All Requirements Pass but " . $warningRequirements . ' ' . $pluralWarnings ;
2011-10-29 05:40:07 +02:00
}
2012-04-11 02:21:56 +02:00
echo " <h5 class='requirement $className '> $section <a href='#'>Show All Requirements</a> <span> $text </span></h5> " ;
2011-10-29 05:40:07 +02:00
echo " <table class= \" testResults \" > " ;
echo $output ;
echo " </table> " ;
}
}
}
function requireFunction ( $funcName , $testDetails ) {
$this -> testing ( $testDetails );
2013-10-16 22:00:20 +02:00
2013-05-08 12:48:50 +02:00
if ( ! function_exists ( $funcName )) {
$this -> error ( $testDetails );
2013-10-16 22:11:06 +02:00
} else {
return true ;
2013-05-08 12:48:50 +02:00
}
2011-10-29 05:40:07 +02:00
}
function requireClass ( $className , $testDetails ) {
$this -> testing ( $testDetails );
2013-10-16 22:17:22 +02:00
if ( ! class_exists ( $className )) {
2013-10-16 22:11:06 +02:00
$this -> error ( $testDetails );
} else {
return false ;
}
2011-10-29 05:40:07 +02:00
}
/**
* Require that the given class doesn ' t exist
*/
function requireNoClasses ( $classNames , $testDetails ) {
$this -> testing ( $testDetails );
$badClasses = array ();
foreach ( $classNames as $className ) {
if ( class_exists ( $className )) $badClasses [] = $className ;
}
if ( $badClasses ) {
$testDetails [ 2 ] .= " . The following classes are at fault: " . implode ( ', ' , $badClasses );
$this -> error ( $testDetails );
2013-10-16 22:11:06 +02:00
} else {
return true ;
2011-10-29 05:40:07 +02:00
}
}
2013-05-25 08:05:53 +02:00
function checkApacheVersion ( $testDetails ) {
$this -> testing ( $testDetails );
$is1pointx = preg_match ( '#Apache[/ ]1\.#' , $testDetails [ 3 ]);
if ( $is1pointx ) {
$this -> error ( $testDetails );
}
return true ;
}
2011-10-29 05:40:07 +02:00
function requirePHPVersion ( $recommendedVersion , $requiredVersion , $testDetails ) {
$this -> testing ( $testDetails );
$installedVersion = phpversion ();
if ( version_compare ( $installedVersion , $requiredVersion , '<' )) {
$testDetails [ 2 ] = " SilverStripe requires PHP version $requiredVersion or later. \n
PHP version $installedVersion is currently installed . \n
While SilverStripe requires at least PHP version $requiredVersion , upgrading to $recommendedVersion or later is recommended . \n
If you are installing SilverStripe on a shared web server , please ask your web hosting provider to upgrade PHP for you . " ;
$this -> error ( $testDetails );
return ;
}
if ( version_compare ( $installedVersion , $recommendedVersion , '<' )) {
$testDetails [ 2 ] = " PHP version $installedVersion is currently installed. \n
Upgrading to at least PHP version $recommendedVersion is recommended . \n
SilverStripe should run , but you may run into issues . Future releases may require a later version of PHP . \n " ;
$this -> warning ( $testDetails );
return ;
}
return true ;
}
2011-10-29 06:23:09 +02:00
/**
* Check that a module exists
*/
function checkModuleExists ( $dirname ) {
$path = $this -> getBaseDir () . $dirname ;
return file_exists ( $path ) && ( $dirname == 'mysite' || file_exists ( $path . '/_config.php' ));
}
2011-10-29 05:40:07 +02:00
/**
* The same as { @ link requireFile ()} but does additional checks
* to ensure the module directory is intact .
*/
function requireModule ( $dirname , $testDetails ) {
$this -> testing ( $testDetails );
$path = $this -> getBaseDir () . $dirname ;
if ( ! file_exists ( $path )) {
$testDetails [ 2 ] .= " Directory ' $path ' not found. Please make sure you have uploaded the SilverStripe files to your webserver correctly. " ;
$this -> error ( $testDetails );
} elseif ( ! file_exists ( $path . '/_config.php' ) && $dirname != 'mysite' ) {
2013-10-16 22:00:20 +02:00
$testDetails [ 2 ] .= " Directory ' $path ' exists, but is missing files. Please make sure you have uploaded "
2013-10-16 22:11:06 +02:00
. " the SilverStripe files to your webserver correctly. " ;
2011-10-29 05:40:07 +02:00
$this -> error ( $testDetails );
}
}
function requireFile ( $filename , $testDetails ) {
$this -> testing ( $testDetails );
$filename = $this -> getBaseDir () . $filename ;
if ( ! file_exists ( $filename )) {
$testDetails [ 2 ] .= " (file ' $filename ' not found) " ;
$this -> error ( $testDetails );
}
}
function requireWriteable ( $filename , $testDetails , $absolute = false ) {
$this -> testing ( $testDetails );
if ( $absolute ) {
$filename = str_replace ( '/' , DIRECTORY_SEPARATOR , $filename );
} else {
$filename = $this -> getBaseDir () . str_replace ( '/' , DIRECTORY_SEPARATOR , $filename );
}
if ( file_exists ( $filename )) $isWriteable = is_writeable ( $filename );
else $isWriteable = is_writeable ( dirname ( $filename ));
if ( ! $isWriteable ) {
if ( function_exists ( 'posix_getgroups' )) {
$userID = posix_geteuid ();
$user = posix_getpwuid ( $userID );
2013-10-16 22:11:06 +02:00
$currentOwnerID = fileowner ( file_exists ( $filename ) ? $filename : dirname ( $filename ));
2011-10-29 05:40:07 +02:00
$currentOwner = posix_getpwuid ( $currentOwnerID );
2013-10-16 22:00:20 +02:00
$testDetails [ 2 ] .= " User ' $user[name] ' needs to be able to write to this file: \n $filename\n\nThe "
2013-10-16 22:11:06 +02:00
. " file is currently owned by ' $currentOwner[name] '. " ;
2011-10-29 05:40:07 +02:00
if ( $user [ 'name' ] == $currentOwner [ 'name' ]) {
$testDetails [ 2 ] .= " We recommend that you make the file writeable. " ;
} else {
$groups = posix_getgroups ();
$groupList = array ();
foreach ( $groups as $group ) {
$groupInfo = posix_getgrgid ( $group );
if ( in_array ( $currentOwner [ 'name' ], $groupInfo [ 'members' ])) $groupList [] = $groupInfo [ 'name' ];
}
if ( $groupList ) {
2013-10-16 22:00:20 +02:00
$testDetails [ 2 ] .= " We recommend that you make the file group-writeable "
2013-10-16 22:11:06 +02:00
. " and change the group to one of these groups: \n - " . implode ( " \n - " , $groupList )
2011-10-29 05:40:07 +02:00
. " \n \n For example: \n chmod g+w $filename\nchgrp " . $groupList [ 0 ] . " $filename " ;
} else {
2013-10-16 22:00:20 +02:00
$testDetails [ 2 ] .= " There is no user-group that contains both the web-server user and the "
2013-10-16 22:11:06 +02:00
. " owner of this file. Change the ownership of the file, create a new group, or "
. " temporarily make the file writeable by everyone during the install process. " ;
2011-10-29 05:40:07 +02:00
}
}
} else {
$testDetails [ 2 ] .= " The webserver user needs to be able to write to this file: \n $filename " ;
}
$this -> error ( $testDetails );
}
}
function requireTempFolder ( $testDetails ) {
$this -> testing ( $testDetails );
2013-11-01 01:53:53 +01:00
try {
$tempFolder = getTempFolder ();
} catch ( Exception $e ) {
$tempFolder = false ;
}
2011-10-29 05:40:07 +02:00
if ( ! $tempFolder ) {
$testDetails [ 2 ] = " Permission problem gaining access to a temp directory. " .
" Please create a folder named silverstripe-cache in the base directory " .
2012-04-17 00:52:28 +02:00
" of the installation and ensure it has the adequate permissions. " ;
2011-10-29 05:40:07 +02:00
$this -> error ( $testDetails );
2012-04-16 02:19:55 +02:00
}
2011-10-29 05:40:07 +02:00
}
function requireApacheModule ( $moduleName , $testDetails ) {
$this -> testing ( $testDetails );
if ( ! in_array ( $moduleName , apache_get_modules ())) {
$this -> error ( $testDetails );
return false ;
} else {
return true ;
}
}
function testApacheRewriteExists ( $moduleName = 'mod_rewrite' ) {
if ( function_exists ( 'apache_get_modules' ) && in_array ( $moduleName , apache_get_modules ())) {
return true ;
} elseif ( isset ( $_SERVER [ 'HTTP_MOD_REWRITE' ]) && $_SERVER [ 'HTTP_MOD_REWRITE' ] == 'On' ) {
return true ;
} else {
return false ;
}
}
function testIISRewriteModuleExists ( $moduleName = 'IIS_UrlRewriteModule' ) {
if ( isset ( $_SERVER [ $moduleName ]) && $_SERVER [ $moduleName ]) {
return true ;
} else {
return false ;
}
}
function requireApacheRewriteModule ( $moduleName , $testDetails ) {
$this -> testing ( $testDetails );
if ( $this -> testApacheRewriteExists ()) {
return true ;
} else {
$this -> warning ( $testDetails );
return false ;
}
}
/**
* Determines if the web server has any rewriting capability .
* @ return boolean
*/
function hasRewritingCapability () {
return ( $this -> testApacheRewriteExists () || $this -> testIISRewriteModuleExists ());
}
function requireIISRewriteModule ( $moduleName , $testDetails ) {
$this -> testing ( $testDetails );
if ( $this -> testIISRewriteModuleExists ()) {
return true ;
} else {
$this -> warning ( $testDetails );
return false ;
}
}
function getDatabaseTypeNice ( $databaseClass ) {
return substr ( $databaseClass , 0 , - 8 );
}
/**
* Get an instance of a helper class for the specific database .
* @ param string $databaseClass e . g . MySQLDatabase or MSSQLDatabase
*/
function getDatabaseConfigurationHelper ( $databaseClass ) {
$adapters = DatabaseAdapterRegistry :: get_adapters ();
if ( isset ( $adapters [ $databaseClass ])) {
$helperPath = $adapters [ $databaseClass ][ 'helperPath' ];
$class = str_replace ( '.php' , '' , basename ( $helperPath ));
}
return ( class_exists ( $class )) ? new $class () : new MySQLDatabaseConfigurationHelper ();
}
function requireDatabaseFunctions ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
$result = $helper -> requireDatabaseFunctions ( $databaseConfig );
if ( $result ) {
return true ;
} else {
$this -> error ( $testDetails );
return false ;
}
}
function requireDatabaseConnection ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
$result = $helper -> requireDatabaseConnection ( $databaseConfig );
if ( $result [ 'success' ]) {
return true ;
} else {
$testDetails [ 2 ] .= " : " . $result [ 'error' ];
$this -> error ( $testDetails );
return false ;
}
}
function requireDatabaseVersion ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
if ( method_exists ( $helper , 'requireDatabaseVersion' )) {
$result = $helper -> requireDatabaseVersion ( $databaseConfig );
if ( $result [ 'success' ]) {
return true ;
} else {
$testDetails [ 2 ] .= $result [ 'error' ];
$this -> warning ( $testDetails );
return false ;
}
}
// Skipped test because this database has no required version
return true ;
}
function requireDatabaseServer ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
$result = $helper -> requireDatabaseServer ( $databaseConfig );
if ( $result [ 'success' ]) {
return true ;
} else {
$testDetails [ 2 ] .= " : " . $result [ 'error' ];
$this -> error ( $testDetails );
return false ;
}
}
function requireDatabaseOrCreatePermissions ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
$result = $helper -> requireDatabaseOrCreatePermissions ( $databaseConfig );
if ( $result [ 'success' ]) {
if ( $result [ 'alreadyExists' ]) $testDetails [ 3 ] = " Database $databaseConfig[database] " ;
else $testDetails [ 3 ] = " Able to create a new database " ;
$this -> testing ( $testDetails );
return true ;
} else {
if ( !@ $result [ 'cannotCreate' ]) {
$testDetails [ 2 ] .= " . Please create the database manually. " ;
} else {
$testDetails [ 2 ] .= " (user ' $databaseConfig[username] ' doesn't have CREATE DATABASE permissions.) " ;
}
$this -> error ( $testDetails );
return false ;
}
}
2013-03-21 15:04:51 +01:00
function requireDatabaseAlterPermissions ( $databaseConfig , $testDetails ) {
$this -> testing ( $testDetails );
$helper = $this -> getDatabaseConfigurationHelper ( $databaseConfig [ 'type' ]);
$result = $helper -> requireDatabaseAlterPermissions ( $databaseConfig );
if ( $result [ 'success' ]) {
return true ;
} else {
$testDetails [ 2 ] = " Silverstripe cannot alter tables. This won't prevent installation, however it may "
. " cause issues if you try to run a /dev/build once installed. " ;
$this -> warning ( $testDetails );
return ;
}
}
2013-05-08 12:48:50 +02:00
function requireServerVariables ( $varNames , $testDetails ) {
$this -> testing ( $testDetails );
$missing = array ();
2013-10-16 22:00:20 +02:00
2011-10-29 05:40:07 +02:00
foreach ( $varNames as $varName ) {
2013-10-16 22:17:22 +02:00
if ( ! isset ( $_SERVER [ $varName ]) || ! $_SERVER [ $varName ]) {
2013-05-08 12:48:50 +02:00
$missing [] = '$_SERVER[' . $varName . ']' ;
2013-10-16 22:11:06 +02:00
}
2011-10-29 05:40:07 +02:00
}
2013-05-08 12:48:50 +02:00
if ( ! $missing ) {
2011-10-29 05:40:07 +02:00
return true ;
} else {
$testDetails [ 2 ] .= " (the following PHP variables are missing: " . implode ( " , " , $missing ) . " ) " ;
$this -> error ( $testDetails );
}
}
2013-05-08 12:48:50 +02:00
function requirePostSupport ( $testDetails ) {
$this -> testing ( $testDetails );
if ( ! isset ( $_POST )) {
$this -> error ( $testDetails );
return false ;
}
return true ;
}
2011-10-29 05:40:07 +02:00
function isRunningWebServer ( $testDetails ) {
$this -> testing ( $testDetails );
if ( $testDetails [ 3 ]) {
return true ;
} else {
$this -> warning ( $testDetails );
return false ;
}
}
// Must be PHP4 compatible
var $baseDir ;
2013-10-16 22:11:06 +02:00
2011-10-29 05:40:07 +02:00
function getBaseDir () {
// Cache the value so that when the installer mucks with SCRIPT_FILENAME half way through, this method
// still returns the correct value.
if ( ! $this -> baseDir ) $this -> baseDir = realpath ( dirname ( $_SERVER [ 'SCRIPT_FILENAME' ])) . DIRECTORY_SEPARATOR ;
return $this -> baseDir ;
}
function testing ( $testDetails ) {
if ( ! $testDetails ) return ;
$section = $testDetails [ 0 ];
$test = $testDetails [ 1 ];
$message = " OK " ;
if ( isset ( $testDetails [ 3 ])) $message .= " ( $testDetails[3] ) " ;
$this -> tests [ $section ][ $test ] = array ( " good " , $message );
}
function error ( $testDetails ) {
$section = $testDetails [ 0 ];
$test = $testDetails [ 1 ];
2012-04-22 07:45:56 +02:00
$this -> tests [ $section ][ $test ] = array ( " error " , @ $testDetails [ 2 ]);
2011-10-29 05:40:07 +02:00
$this -> errors [] = $testDetails ;
}
function warning ( $testDetails ) {
$section = $testDetails [ 0 ];
$test = $testDetails [ 1 ];
2012-04-22 07:45:56 +02:00
$this -> tests [ $section ][ $test ] = array ( " warning " , @ $testDetails [ 2 ]);
2011-10-29 05:40:07 +02:00
$this -> warnings [] = $testDetails ;
}
function hasErrors () {
return sizeof ( $this -> errors );
}
function hasWarnings () {
return sizeof ( $this -> warnings );
}
}
class Installer extends InstallRequirements {
function __construct () {
// Cache the baseDir value
$this -> getBaseDir ();
}
function install ( $config ) {
2013-10-16 22:11:06 +02:00
?>
< html >
< head >
< meta charset = " utf-8 " />
< title > Installing SilverStripe ...</ title >
< link rel = " stylesheet " type = " text/css " href = " <?php echo FRAMEWORK_NAME; ?>/dev/install/css/install.css " />
< script src = " <?php echo FRAMEWORK_NAME; ?>/thirdparty/jquery/jquery.js " ></ script >
</ head >
< body >
2012-04-05 02:01:27 +02:00
< div class = " install-header " >
< div class = " inner " >
< div class = " brand " >
< span class = " logo " ></ span >
2013-10-16 22:11:06 +02:00
2012-04-05 02:01:27 +02:00
< h1 > SilverStripe </ h1 >
2011-10-29 05:40:07 +02:00
</ div >
2013-10-16 22:00:20 +02:00
</ div >
2012-04-05 02:01:27 +02:00
</ div >
< div id = " Navigation " >& nbsp ; </ div >
< div class = " clear " ><!-- --></ div >
< div class = " main " >
< div class = " inner " >
2012-04-11 16:49:31 +02:00
< h2 > Installing SilverStripe ...</ h2 >
2013-10-16 22:11:06 +02:00
2012-04-05 02:01:27 +02:00
< p > I am now running through the installation steps ( this should take about 30 seconds ) </ p >
2013-10-16 22:11:06 +02:00
2012-04-05 02:01:27 +02:00
< p > If you receive a fatal error , refresh this page to continue the installation </ p >
< ul >
2011-10-29 05:40:07 +02:00
< ? php
$webserver = $this -> findWebserver ();
$isIIS = $this -> isIIS ();
$isApache = $this -> isApache ();
flush ();
if ( isset ( $config [ 'stats' ])) {
2012-03-24 04:38:57 +01:00
if ( file_exists ( FRAMEWORK_NAME . '/silverstripe_version' )) {
$silverstripe_version = file_get_contents ( FRAMEWORK_NAME . '/silverstripe_version' );
2011-10-29 05:40:07 +02:00
} else {
$silverstripe_version = " unknown " ;
}
$phpVersion = urlencode ( phpversion ());
$encWebserver = urlencode ( $webserver );
$dbType = $config [ 'db' ][ 'type' ];
// Try to determine the database version from the helper
$databaseVersion = $config [ 'db' ][ 'type' ];
$helper = $this -> getDatabaseConfigurationHelper ( $dbType );
if ( $helper && method_exists ( $helper , 'getDatabaseVersion' )) {
$databaseVersion = urlencode ( $dbType . ': ' . $helper -> getDatabaseVersion ( $config [ 'db' ][ $dbType ]));
}
$url = " http://ss2stat.silverstripe.com/Installation/add?SilverStripe= $silverstripe_version &PHP= $phpVersion &Database= $databaseVersion &WebServer= $encWebserver " ;
if ( isset ( $_SESSION [ 'StatsID' ]) && $_SESSION [ 'StatsID' ]) {
$url .= '&ID=' . $_SESSION [ 'StatsID' ];
}
@ $_SESSION [ 'StatsID' ] = file_get_contents ( $url );
}
if ( file_exists ( 'mysite/_config.php' )) {
// Truncate the contents of _config instead of deleting it - we can't re-create it because Windows handles permissions slightly
// differently to UNIX based filesystems - it takes the permissions from the parent directory instead of retaining them
$fh = fopen ( 'mysite/_config.php' , 'wb' );
fclose ( $fh );
}
2012-05-16 14:34:42 +02:00
// Escape user input for safe insertion into PHP file
$theme = isset ( $_POST [ 'template' ]) ? addcslashes ( $_POST [ 'template' ], " \ ' " ) : 'simple' ;
$locale = isset ( $_POST [ 'locale' ]) ? addcslashes ( $_POST [ 'locale' ], " \ ' " ) : 'en_US' ;
$type = addcslashes ( $config [ 'db' ][ 'type' ], " \ ' " );
2011-10-29 05:40:07 +02:00
$dbConfig = $config [ 'db' ][ $type ];
2012-05-16 14:34:42 +02:00
$dbConfig = array_map ( create_function ( '$v' , 'return addcslashes($v, "\\\'");' ), $dbConfig );
2012-04-16 02:19:55 +02:00
if ( ! isset ( $dbConfig [ 'path' ])) $dbConfig [ 'path' ] = '' ;
2011-10-29 05:40:07 +02:00
if ( ! $dbConfig ) {
echo " <p style= \" color: red \" >Bad config submitted</p><pre> " ;
print_r ( $config );
echo " </pre> " ;
die ();
}
// Write the config file
global $usingEnv ;
if ( $usingEnv ) {
$this -> statusMessage ( " Setting up 'mysite/_config.php' for use with _ss_environment.php... " );
$this -> writeToFile ( " mysite/_config.php " , <<< PHP
< ? php
global \ $project ;
\ $project = 'mysite' ;
global \ $database ;
\ $database = '{$dbConfig[' database ']}' ;
require_once ( 'conf/ConfigureFromEnv.php' );
// Set the site locale
i18n :: set_locale ( '$locale' );
PHP
);
} else {
$this -> statusMessage ( " Setting up 'mysite/_config.php'... " );
$escapedPassword = addslashes ( $dbConfig [ 'password' ]);
$this -> writeToFile ( " mysite/_config.php " , <<< PHP
< ? php
global \ $project ;
\ $project = 'mysite' ;
global \ $databaseConfig ;
\ $databaseConfig = array (
" type " => '{$type}' ,
" server " => '{$dbConfig[' server ']}' ,
" username " => '{$dbConfig[' username ']}' ,
" password " => '{$escapedPassword}' ,
" database " => '{$dbConfig[' database ']}' ,
" path " => '{$dbConfig[' path ']}' ,
);
// Set the site locale
i18n :: set_locale ( '$locale' );
2011-10-29 06:23:09 +02:00
PHP
);
}
2013-10-16 22:17:22 +02:00
if ( ! $this -> checkModuleExists ( 'cms' )) {
2011-10-29 06:23:09 +02:00
$this -> writeToFile ( " mysite/code/RootURLController.php " , <<< PHP
< ? php
class RootURLController extends Controller {
function index () {
echo " <html>Your site is now set up. Start adding controllers to mysite to get started.</html> " ;
}
}
2011-10-29 05:40:07 +02:00
PHP
);
}
// Write the appropriate web server configuration file for rewriting support
if ( $this -> hasRewritingCapability ()) {
if ( $isApache ) {
$this -> statusMessage ( " Setting up '.htaccess' file... " );
$this -> createHtaccess ();
} elseif ( $isIIS ) {
$this -> statusMessage ( " Setting up 'web.config' file... " );
$this -> createWebConfig ();
}
}
2012-03-24 04:38:57 +01:00
// Load the SilverStripe runtime
$_SERVER [ 'SCRIPT_FILENAME' ] = dirname ( realpath ( $_SERVER [ 'SCRIPT_FILENAME' ])) . '/' . FRAMEWORK_NAME . '/main.php' ;
chdir ( FRAMEWORK_NAME );
2011-10-29 05:40:07 +02:00
// Rebuild the manifest
$_GET [ 'flush' ] = true ;
// Show errors as if you're in development mode
$_SESSION [ 'isDev' ] = 1 ;
$this -> statusMessage ( " Building database schema... " );
2012-04-17 00:52:28 +02:00
require_once 'core/Core.php' ;
2011-10-29 05:40:07 +02:00
// Build database
$con = new Controller ();
$con -> pushCurrent ();
global $databaseConfig ;
DB :: connect ( $databaseConfig );
$dbAdmin = new DatabaseAdmin ();
$dbAdmin -> init ();
$dbAdmin -> doBuild ( true );
// Create default administrator user and group in database
// (not using Security::setDefaultAdmin())
$adminMember = Security :: findAnAdministrator ();
$adminMember -> Email = $config [ 'admin' ][ 'username' ];
$adminMember -> Password = $config [ 'admin' ][ 'password' ];
$adminMember -> PasswordEncryption = Security :: get_password_encryption_algorithm ();
try {
2012-04-16 02:19:55 +02:00
$this -> statusMessage ( 'Creating default CMS admin account...' );
2011-10-29 05:40:07 +02:00
$adminMember -> write ();
} catch ( Exception $e ) {
2012-04-16 02:19:55 +02:00
$this -> statusMessage (
sprintf ( 'Warning: Default CMS admin account could not be created (error: %s)' , $e -> getMessage ())
);
2011-10-29 05:40:07 +02:00
}
// Syncing filesystem (so /assets/Uploads is available instantly, see ticket #2266)
2012-04-16 02:19:55 +02:00
// show a warning if there was a problem doing so
try {
$this -> statusMessage ( 'Creating initial filesystem assets...' );
Filesystem :: sync ();
} catch ( Exception $e ) {
$this -> statusMessage (
sprintf ( 'Warning: Creating initial filesystem assets failed (error: %s)' , $e -> getMessage ())
);
}
2011-10-29 05:40:07 +02:00
$_SESSION [ 'username' ] = $config [ 'admin' ][ 'username' ];
$_SESSION [ 'password' ] = $config [ 'admin' ][ 'password' ];
if ( ! $this -> errors ) {
if ( isset ( $_SERVER [ 'HTTP_HOST' ]) && $this -> hasRewritingCapability ()) {
$this -> statusMessage ( " Checking that friendly URLs work... " );
$this -> checkRewrite ();
} else {
2013-08-02 01:00:26 +02:00
require_once 'core/startup/ParameterConfirmationToken.php' ;
$token = new ParameterConfirmationToken ( 'flush' );
$params = http_build_query ( $token -> params ());
2011-10-29 06:23:09 +02:00
$destinationURL = 'index.php/' .
2013-08-02 01:00:26 +02:00
( $this -> checkModuleExists ( 'cms' ) ? " home/successfullyinstalled? $params " : " ? $params " );
2011-10-29 06:23:09 +02:00
2011-10-29 05:40:07 +02:00
echo <<< HTML
< li > SilverStripe successfully installed ; I am now redirecting you to your SilverStripe site ...</ li >
< script >
setTimeout ( function () {
2011-10-29 06:23:09 +02:00
window . location = " $destinationURL " ;
2011-10-29 05:40:07 +02:00
}, 2000 );
</ script >
< noscript >
2013-03-23 12:06:54 +01:00
< li >< a href = " $destinationURL " > Click here to access your site .</ a ></ li >
2011-10-29 05:40:07 +02:00
</ noscript >
HTML ;
}
}
return $this -> errors ;
}
function writeToFile ( $filename , $content ) {
$base = $this -> getBaseDir ();
$this -> statusMessage ( " Setting up $base $filename " );
if (( @ $fh = fopen ( $base . $filename , 'wb' )) && fwrite ( $fh , $content ) && fclose ( $fh )) {
return true ;
} else {
$this -> error ( " Couldn't write to file $base $filename " );
}
}
function createHtaccess () {
$start = " ### SILVERSTRIPE START ### \n " ;
$end = " \n ### SILVERSTRIPE END ### " ;
$base = dirname ( $_SERVER [ 'SCRIPT_NAME' ]);
if ( defined ( 'DIRECTORY_SEPARATOR' )) $base = str_replace ( DIRECTORY_SEPARATOR , '/' , $base );
else $base = str_replace ( " \\ " , '/' , $base );
if ( $base != '.' ) $baseClause = " RewriteBase ' $base ' \n " ;
else $baseClause = " " ;
2012-03-24 04:38:57 +01:00
$modulePath = FRAMEWORK_NAME ;
2011-10-29 05:40:07 +02:00
$rewrite = <<< TEXT
< Files *. ss >
Order deny , allow
Deny from all
Allow from 127.0 . 0.1
</ Files >
< Files web . config >
Order deny , allow
Deny from all
2013-01-29 02:20:12 +01:00
</ Files >
# This denies access to all yml files, since developers might include sensitive
# information in them. See the docs for work-arounds to serve some yaml files
< Files *. yml >
Order allow , deny
Deny from all
2011-10-29 05:40:07 +02:00
</ Files >
ErrorDocument 404 / assets / error - 404. html
ErrorDocument 500 / assets / error - 500. html
< IfModule mod_rewrite . c >
SetEnv HTTP_MOD_REWRITE On
RewriteEngine On
$baseClause
2013-04-20 09:45:18 +02:00
RewriteRule ^ vendor ( /| $ ) - [ F , L , NC ]
RewriteRule silverstripe - cache ( /| $ ) - [ F , L , NC ]
RewriteRule composer\ . ( json | lock ) - [ F , L , NC ]
2011-10-29 05:40:07 +02:00
RewriteCond % { REQUEST_URI } ^ ( .* ) $
RewriteCond % { REQUEST_FILENAME } !- f
2012-12-04 02:36:59 +01:00
RewriteCond % { REQUEST_URI } ! \ . php $
2012-03-24 04:38:57 +01:00
RewriteRule .* $modulePath / main . php ? url =% 1 &% { QUERY_STRING } [ L ]
2011-10-29 05:40:07 +02:00
</ IfModule >
TEXT ;
if ( file_exists ( '.htaccess' )) {
$htaccess = file_get_contents ( '.htaccess' );
if ( strpos ( $htaccess , '### SILVERSTRIPE START ###' ) === false && strpos ( $htaccess , '### SILVERSTRIPE END ###' ) === false ) {
$htaccess .= " \n ### SILVERSTRIPE START ### \n ### SILVERSTRIPE END ### \n " ;
}
if ( strpos ( $htaccess , '### SILVERSTRIPE START ###' ) !== false && strpos ( $htaccess , '### SILVERSTRIPE END ###' ) !== false ) {
$start = substr ( $htaccess , 0 , strpos ( $htaccess , '### SILVERSTRIPE START ###' )) . " ### SILVERSTRIPE START ### \n " ;
$end = " \n " . substr ( $htaccess , strpos ( $htaccess , '### SILVERSTRIPE END ###' ));
}
}
$this -> writeToFile ( '.htaccess' , $start . $rewrite . $end );
}
/**
* Writes basic configuration to the web . config for IIS
* so that rewriting capability can be use .
*/
function createWebConfig () {
2012-03-24 04:38:57 +01:00
$modulePath = FRAMEWORK_NAME ;
2011-10-29 05:40:07 +02:00
$content = <<< TEXT
< ? xml version = " 1.0 " encoding = " utf-8 " ?>
< configuration >
< system . webServer >
< security >
< requestFiltering >
< hiddenSegments applyToWebDAV = " false " >
< add segment = " silverstripe-cache " />
2013-04-03 04:59:14 +02:00
< add segment = " vendor " />
< add segment = " composer.json " />
< add segment = " composer.lock " />
2011-10-29 05:40:07 +02:00
</ hiddenSegments >
2013-04-03 04:59:14 +02:00
< fileExtensions allowUnlisted = " true " >
< add fileExtension = " .ss " allowed = " false " />
< add fileExtension = " .yml " allowed = " false " />
</ fileExtensions >
2011-10-29 05:40:07 +02:00
</ requestFiltering >
</ security >
< rewrite >
< rules >
< rule name = " SilverStripe Clean URLs " stopProcessing = " true " >
< match url = " ^(.*) $ " />
< conditions >
< add input = " { REQUEST_FILENAME} " matchType = " IsFile " negate = " true " />
</ conditions >
2012-03-24 04:38:57 +01:00
< action type = " Rewrite " url = " $modulePath /main.php?url= { R:1} " appendQueryString = " true " />
2011-10-29 05:40:07 +02:00
</ rule >
</ rules >
</ rewrite >
</ system . webServer >
</ configuration >
TEXT ;
$this -> writeToFile ( 'web.config' , $content );
}
function checkRewrite () {
2013-08-02 01:00:26 +02:00
require_once 'core/startup/ParameterConfirmationToken.php' ;
$token = new ParameterConfirmationToken ( 'flush' );
$params = http_build_query ( $token -> params ());
2011-10-29 06:23:09 +02:00
$destinationURL = str_replace ( 'install.php' , '' , $_SERVER [ 'SCRIPT_NAME' ]) .
2013-08-02 01:00:26 +02:00
( $this -> checkModuleExists ( 'cms' ) ? " home/successfullyinstalled? $params " : " ? $params " );
2011-10-29 06:23:09 +02:00
2011-10-29 05:40:07 +02:00
echo <<< HTML
< li id = " ModRewriteResult " > Testing ...</ li >
< script >
if ( typeof $ == 'undefined' ) {
document . getElemenyById ( 'ModeRewriteResult' ) . innerHTML = " I can't run jQuery ajax to set rewriting; I will redirect you to the homepage to see if everything is working. " ;
setTimeout ( function () {
2011-10-29 06:23:09 +02:00
window . location = " $destinationURL " ;
2011-10-29 05:40:07 +02:00
}, 10000 );
} else {
$ . ajax ({
method : 'get' ,
url : 'InstallerTest/testrewrite' ,
complete : function ( response ) {
2012-08-15 03:42:54 +02:00
var r = response . responseText . replace ( / [ ^ A - Z ] ? / g , " " );
if ( r === " OK " ) {
2011-10-29 05:40:07 +02:00
$ ( '#ModRewriteResult' ) . html ( " Friendly URLs set up successfully; I am now redirecting you to your SilverStripe site... " )
setTimeout ( function () {
2011-10-29 06:23:09 +02:00
window . location = " $destinationURL " ;
2011-10-29 05:40:07 +02:00
}, 2000 );
} else {
$ ( '#ModRewriteResult' ) . html ( " Friendly URLs are not working. This is most likely because a rewrite module isn't configured "
+ " correctly on your site. You may need to get your web host or server administrator to do this for you: "
+ " <ul> "
+ " <li><strong>mod_rewrite</strong> or other rewrite module is enabled on your web server</li> "
+ " <li><strong>AllowOverride All</strong> is set for the directory where SilverStripe is installed</li> "
+ " </ul> " );
}
}
});
}
</ script >
< noscript >
2011-10-29 06:23:09 +02:00
< li >< a href = " $destinationURL " > Click here </ a > to check friendly URLs are working . If you get a 404 then something is wrong .</ li >
2011-10-29 05:40:07 +02:00
</ noscript >
HTML ;
}
function var_export_array_nokeys ( $array ) {
$retval = " array( \n " ;
foreach ( $array as $item ) {
$retval .= " \t ' " ;
$retval .= trim ( $item );
$retval .= " ', \n " ;
}
$retval .= " ) " ;
return $retval ;
}
/**
* Show an installation status message .
* The output differs depending on whether this is CLI or web based
*/
function statusMessage ( $msg ) {
echo " <li> $msg </li> \n " ;
flush ();
}
}