4 * Note that this installer has been based of the SilverStripe installer.
5 * You can get more information from the SilverStripe Website at
6 * http://www.silverstripe.com/.
8 * Copyright (c) 2006-7, SilverStripe Limited - www.silverstripe.com
11 * License: BSD-3-clause
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are
16 * Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
19 * Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
23 * Neither the name of SilverStripe nor the names of its contributors may
24 * be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
30 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
31 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * Changes and modifications (c) 2007-2015 by CiviCRM LLC
47 ini_set('max_execution_time', 3000);
49 if (stristr(PHP_OS
, 'WIN')) {
50 define('CIVICRM_DIRECTORY_SEPARATOR', '/');
51 define('CIVICRM_WINDOWS', 1);
54 define('CIVICRM_DIRECTORY_SEPARATOR', DIRECTORY_SEPARATOR
);
55 define('CIVICRM_WINDOWS', 0);
58 // set installation type - drupal
63 // unset civicrm session if any
64 if (array_key_exists('CiviCRM', $_SESSION)) {
65 unset($_SESSION['CiviCRM']);
68 if (isset($_GET['civicrm_install_type'])) {
69 $_SESSION['civicrm_install_type'] = $_GET['civicrm_install_type'];
72 if (!isset($_SESSION['civicrm_install_type'])) {
73 $_SESSION['civicrm_install_type'] = "drupal";
80 global $installDirPath;
81 global $installURLPath;
83 $installType = strtolower($_SESSION['civicrm_install_type']);
85 if ($installType == 'drupal') {
86 $crmPath = dirname(dirname($_SERVER['SCRIPT_FILENAME']));
87 $installDirPath = $installURLPath = '';
89 elseif ($installType == 'wordpress') {
90 $crmPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
;
91 $installDirPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'install' . DIRECTORY_SEPARATOR
;
92 $installURLPath = WP_PLUGIN_URL
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'install' . DIRECTORY_SEPARATOR
;
95 $errorTitle = "Oops! Unsupported installation mode";
96 $errorMsg = sprintf('%s: unknown installation mode. Please refer to the online documentation for more information.', $installType);
97 errorDisplayPage($errorTitle, $errorMsg, FALSE);
100 $pkgPath = $crmPath . DIRECTORY_SEPARATOR
. 'packages';
102 require_once $crmPath . '/CRM/Core/ClassLoader.php';
103 CRM_Core_ClassLoader
::singleton()->register();
105 // Load civicrm database config
106 if (isset($_REQUEST['mysql'])) {
107 $databaseConfig = $_REQUEST['mysql'];
110 $databaseConfig = array(
111 "server" => "localhost",
112 "username" => "civicrm",
114 "database" => "civicrm",
118 if ($installType == 'drupal') {
119 // Load drupal database config
120 if (isset($_REQUEST['drupal'])) {
121 $drupalConfig = $_REQUEST['drupal'];
124 $drupalConfig = array(
125 "server" => "localhost",
126 "username" => "drupal",
128 "database" => "drupal",
134 if (isset($_REQUEST['loadGenerated'])) {
138 require_once dirname(__FILE__
) . CIVICRM_DIRECTORY_SEPARATOR
. 'langs.php';
139 foreach ($langs as $locale => $_) {
140 if ($locale == 'en_US') {
143 if (!file_exists(implode(CIVICRM_DIRECTORY_SEPARATOR
, array($crmPath, 'sql', "civicrm_data.$locale.mysql")))) {
144 unset($langs[$locale]);
148 // Set the locale (required by CRM_Core_Config)
149 // This is mostly sympbolic, since nothing we do during the install
150 // really requires CIVICRM_UF to be defined.
151 $installTypeToUF = array(
152 'wordpress' => 'WordPress',
153 'drupal' => 'Drupal',
156 $uf = (isset($installTypeToUF[$installType]) ?
$installTypeToUF[$installType] : 'Drupal');
157 define('CIVICRM_UF', $uf);
162 $seedLanguage = 'en_US';
164 if (isset($_REQUEST['seedLanguage']) and isset($langs[$_REQUEST['seedLanguage']])) {
165 $seedLanguage = $_REQUEST['seedLanguage'];
166 $tsLocale = $_REQUEST['seedLanguage'];
169 $config = CRM_Core_Config
::singleton(FALSE);
170 $GLOBALS['civicrm_default_error_scope'] = NULL;
172 // The translation files are in the parent directory (l10n)
173 $config->gettextResourceDir
= '..' . DIRECTORY_SEPARATOR
. $config->gettextResourceDir
;
174 $i18n = CRM_Core_I18n
::singleton();
177 if ($installType == 'drupal') {
178 //CRM-6840 -don't force to install in sites/all/modules/
179 $object = new CRM_Utils_System_Drupal();
180 $cmsPath = $object->cmsRootPath();
182 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
183 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
184 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
185 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
186 'civicrm.settings.php'
189 elseif ($installType == 'wordpress') {
190 $cmsPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm';
191 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
192 'civicrm.settings.php'
196 if ($installType == 'drupal') {
197 // Lets check only /modules/.
198 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR
. 'modules', CIVICRM_DIRECTORY_SEPARATOR
) . '/';
200 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
201 $directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array('sites', 'all', 'modules'));
202 $errorTitle = ts("Oops! Please correct your install location");
203 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
204 errorDisplayPage($errorTitle, $errorMsg);
208 // Exit with error if CiviCRM has already been installed.
209 if ($alreadyInstalled) {
210 $errorTitle = ts("Oops! CiviCRM is already installed");
211 $settings_directory = $cmsPath;
213 if ($installType == 'drupal') {
214 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array(
215 ts('[your Drupal root directory]'),
221 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, ts('Installation Guide'), NULL, NULL, "wiki");
222 $errorMsg = ts("CiviCRM has already been installed. <ul><li>To <strong>start over</strong>, you must delete or rename the existing CiviCRM settings file - <strong>civicrm.settings.php</strong> - from <strong>%1</strong>.</li><li>To <strong>upgrade an existing installation</strong>, <a href='%2'>refer to the online documentation</a>.</li></ul>", array(1 => $settings_directory, 2 => $docLink));
223 errorDisplayPage($errorTitle, $errorMsg, FALSE);
226 $versionFile = $crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'civicrm-version.php';
227 if (file_exists($versionFile)) {
228 require_once $versionFile;
229 $civicrm_version = civicrmVersion();
232 $civicrm_version = 'unknown';
235 if ($installType == 'drupal') {
236 // Ensure that they have downloaded the correct version of CiviCRM
237 if ($civicrm_version['cms'] != 'Drupal' && $civicrm_version['cms'] != 'Drupal6') {
238 $errorTitle = ts("Oops! Incorrect CiviCRM version");
239 $errorMsg = ts("This installer can only be used for the Drupal version of CiviCRM.");
240 errorDisplayPage($errorTitle, $errorMsg);
243 define('DRUPAL_ROOT', $cmsPath);
244 $drupalVersionFiles = array(
246 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'modules', 'system', 'system.module')),
248 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'includes', 'bootstrap.inc')),
250 foreach ($drupalVersionFiles as $drupalVersionFile) {
251 if (file_exists($drupalVersionFile)) {
252 require_once $drupalVersionFile;
256 if (!defined('VERSION') or version_compare(VERSION
, '6.0') < 0) {
257 $errorTitle = ts("Oops! Incorrect Drupal version");
258 $errorMsg = ts("This version of CiviCRM can only be used with Drupal 6.x or 7.x. Please ensure that '%1' exists if you are running Drupal 7.0 and over.", array(1 => implode("' or '", $drupalVersionFiles)));
259 errorDisplayPage($errorTitle, $errorMsg);
262 elseif ($installType == 'wordpress') {
264 $civicrm_version['cms'] = 'WordPress';
266 // Ensure that they have downloaded the correct version of CiviCRM
267 if ($civicrm_version['cms'] != 'WordPress') {
268 $errorTitle = ts("Oops! Incorrect CiviCRM version");
269 $errorMsg = ts("This installer can only be used for the WordPress version of CiviCRM.");
270 errorDisplayPage($errorTitle, $errorMsg);
274 // Check requirements
275 $req = new InstallRequirements();
278 if ($req->hasErrors()) {
279 $hasErrorOtherThanDatabase = TRUE;
282 if ($databaseConfig) {
283 $dbReq = new InstallRequirements();
284 $dbReq->checkdatabase($databaseConfig, 'CiviCRM');
285 if ($installType == 'drupal') {
286 $dbReq->checkdatabase($drupalConfig, 'Drupal');
291 if (isset($_REQUEST['go']) && !$req->hasErrors() && !$dbReq->hasErrors()) {
292 // Confirm before reinstalling
293 if (!isset($_REQUEST['force_reinstall']) && $alreadyInstalled) {
294 include $installDirPath . 'template.html';
297 $inst = new Installer();
298 $inst->install($_REQUEST);
301 // Show the config form
304 include $installDirPath . 'template.html';
308 * This class checks requirements
309 * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array
311 * $description[0] - The test category
312 * $description[1] - The test title
313 * $description[2] - The test error to show, if it goes wrong
315 class InstallRequirements
{
316 var $errors, $warnings, $tests;
318 // @see CRM_Upgrade_Form::MINIMUM_THREAD_STACK
319 const MINIMUM_THREAD_STACK
= 192;
322 * Just check that the database configuration is okay.
323 * @param $databaseConfig
326 public function checkdatabase($databaseConfig, $dbName) {
327 if ($this->requireFunction('mysql_connect',
329 ts("PHP Configuration"),
331 ts("MySQL support not included in PHP."),
335 $this->requireMySQLServer($databaseConfig['server'],
337 ts("MySQL %1 Configuration", array(1 => $dbName)),
338 ts("Does the server exist?"),
339 ts("Can't find the a MySQL server on '%1'.", array(1 => $databaseConfig['server'])),
340 $databaseConfig['server'],
343 if ($this->requireMysqlConnection($databaseConfig['server'],
344 $databaseConfig['username'],
345 $databaseConfig['password'],
347 ts("MySQL %1 Configuration", array(1 => $dbName)),
348 ts("Are the access credentials correct?"),
349 ts("That username/password doesn't work"),
353 @$this->requireMySQLVersion("5.1",
355 ts("MySQL %1 Configuration", array(1 => $dbName)),
356 ts("MySQL version at least %1", array(1 => '5.1')),
357 ts("MySQL version %1 or higher is required, you are running MySQL %2.", array(1 => '5.1', 2 => mysql_get_server_info())),
358 ts("MySQL %1", array(1 => mysql_get_server_info())),
361 $this->requireMySQLAutoIncrementIncrementOne($databaseConfig['server'],
362 $databaseConfig['username'],
363 $databaseConfig['password'],
365 ts("MySQL %1 Configuration", array(1 => $dbName)),
366 ts("Is auto_increment_increment set to 1"),
367 ts("An auto_increment_increment value greater than 1 is not currently supported. Please see issue CRM-7923 for further details and potential workaround."),
370 $this->requireMySQLThreadStack($databaseConfig['server'],
371 $databaseConfig['username'],
372 $databaseConfig['password'],
373 $databaseConfig['database'],
374 self
::MINIMUM_THREAD_STACK
,
376 ts("MySQL %1 Configuration", array(1 => $dbName)),
377 ts("Does MySQL thread_stack meet minimum (%1k)", array(1 => self
::MINIMUM_THREAD_STACK
)),
379 // "The MySQL thread_stack does not meet minimum " . CRM_Upgrade_Form::MINIMUM_THREAD_STACK . "k. Please update thread_stack in my.cnf.",
383 $onlyRequire = ($dbName == 'Drupal') ?
TRUE : FALSE;
384 $this->requireDatabaseOrCreatePermissions(
385 $databaseConfig['server'],
386 $databaseConfig['username'],
387 $databaseConfig['password'],
388 $databaseConfig['database'],
390 ts("MySQL %1 Configuration", array(1 => $dbName)),
391 ts("Can I access/create the database?"),
392 ts("I can't create new databases and the database '%1' doesn't exist.", array(1 => $databaseConfig['database'])),
396 if ($dbName != 'Drupal') {
397 $this->requireMySQLInnoDB($databaseConfig['server'],
398 $databaseConfig['username'],
399 $databaseConfig['password'],
400 $databaseConfig['database'],
402 ts("MySQL %1 Configuration", array(1 => $dbName)),
403 ts("Can I access/create InnoDB tables in the database?"),
404 ts("Unable to create InnoDB tables. MySQL InnoDB support is required for CiviCRM but is either not available or not enabled in this MySQL database server."),
407 $this->requireMySQLTempTables($databaseConfig['server'],
408 $databaseConfig['username'],
409 $databaseConfig['password'],
410 $databaseConfig['database'],
412 ts("MySQL %1 Configuration", array(1 => $dbName)),
413 ts('Can I create temporary tables in the database?'),
414 ts('Unable to create temporary tables. This MySQL user is missing the CREATE TEMPORARY TABLES privilege.'),
417 $this->requireMySQLLockTables($databaseConfig['server'],
418 $databaseConfig['username'],
419 $databaseConfig['password'],
420 $databaseConfig['database'],
422 ts("MySQL %1 Configuration", array(1 => $dbName)),
423 ts('Can I create lock tables in the database?'),
424 ts('Unable to lock tables. This MySQL user is missing the LOCK TABLES privilege.'),
427 $this->requireMySQLTrigger($databaseConfig['server'],
428 $databaseConfig['username'],
429 $databaseConfig['password'],
430 $databaseConfig['database'],
432 ts("MySQL %1 Configuration", array(1 => $dbName)),
433 ts('Can I create triggers in the database?'),
434 ts('Unable to create triggers. This MySQL user is missing the CREATE TRIGGERS privilege.'),
442 * Check everything except the database.
444 public function check() {
445 global $crmPath, $installType;
447 $this->errors
= NULL;
449 $this->requirePHPVersion('5.3.3', array(
450 ts("PHP Configuration"),
451 ts("PHP5 installed"),
453 ts("PHP version %1", array(1 => phpversion())),
456 // Check that we can identify the root folder successfully
457 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'README.txt',
459 ts("File permissions"),
460 ts("Does the webserver know where files are stored?"),
461 ts("The webserver isn't letting me identify where files are stored."),
467 // CRM-6485: make sure the path does not contain PATH_SEPARATOR, as we don’t know how to escape it
468 $this->requireNoPathSeparator(
470 ts("File permissions"),
471 ts('Does the CiviCRM path contain PATH_SEPARATOR?'),
472 ts('The path %1 contains PATH_SEPARATOR (the %2 character).', array(1 => $this->getBaseDir(), 2 => PATH_SEPARATOR
)),
477 $requiredDirectories = array('CRM', 'packages', 'templates', 'js', 'api', 'i', 'sql');
478 foreach ($requiredDirectories as $dir) {
479 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. $dir,
481 ts("File permissions"),
482 ts("Folder '%1' exists?", array(1 => $dir)),
483 ts("There is no '%1' folder.", array(1 => $dir)),
488 $configIDSiniDir = NULL;
490 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
491 if ($installType == 'drupal') {
493 // make sure that we can write to sites/default and files/
494 $writableDirectories = array(
495 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
496 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
497 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
499 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
500 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
504 elseif ($installType == 'wordpress') {
505 // make sure that we can write to plugins/civicrm and plugins/files/
506 $writableDirectories = array(WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'files', $cmsPath);
509 foreach ($writableDirectories as $dir) {
510 $dirName = CIVICRM_WINDOWS ?
$dir : CIVICRM_DIRECTORY_SEPARATOR
. $dir;
511 $testDetails = array(
512 ts("File permissions"),
513 ts("Is the %1 folder writeable?", array(1 => $dir)),
516 $this->requireWriteable($dirName, $testDetails, TRUE);
519 //check for Config.IDS.ini, file may exist in re-install
520 $configIDSiniDir = array($cmsPath, 'sites', $siteDir, 'files', 'civicrm', 'upload', 'Config.IDS.ini');
522 if (is_array($configIDSiniDir) && !empty($configIDSiniDir)) {
523 $configIDSiniFile = implode(CIVICRM_DIRECTORY_SEPARATOR
, $configIDSiniDir);
524 if (file_exists($configIDSiniFile)) {
525 unlink($configIDSiniFile);
529 // Check for rewriting
530 if (isset($_SERVER['SERVER_SOFTWARE'])) {
531 $webserver = strip_tags(trim($_SERVER['SERVER_SOFTWARE']));
533 elseif (isset($_SERVER['SERVER_SIGNATURE'])) {
534 $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE']));
537 if ($webserver == '') {
538 $webserver = ts("I can't tell what webserver you are running");
541 // Check for $_SERVER configuration
542 $this->requireServerVariables(array('SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'), array(
543 ts("Webserver config"),
544 ts("Recognised webserver"),
545 ts("You seem to be using an unsupported webserver. The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set."),
548 // Check for MySQL support
549 $this->requireFunction('mysql_connect', array(
550 ts("PHP Configuration"),
552 ts("MySQL support not included in PHP."),
555 // Check for JSON support
556 $this->requireFunction('json_encode', array(
557 ts("PHP Configuration"),
559 ts("JSON support not included in PHP."),
562 // Check for xcache_isset and emit warning if exists
563 $this->checkXCache(array(
564 ts("PHP Configuration"),
565 ts("XCache compatibility"),
566 ts("XCache is installed and there are known compatibility issues between XCache and CiviCRM. Consider using an alternative PHP caching mechanism or disable PHP caching altogether."),
569 // Check memory allocation
570 $this->requireMemory(32 * 1024 * 1024,
573 ts("PHP Configuration"),
574 ts("Memory allocated (PHP config option 'memory_limit')"),
575 ts("CiviCRM needs a minimum of %1 MB allocated to PHP, but recommends %2 MB.", array(1 => 32, 2 => 64)),
576 ini_get("memory_limit"),
580 return $this->errors
;
585 * @param $recommended
586 * @param $testDetails
588 public function requireMemory($min, $recommended, $testDetails) {
589 $this->testing($testDetails);
590 $mem = $this->getPHPMemory();
592 if ($mem < $min && $mem > 0) {
593 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
594 $this->error($testDetails);
596 elseif ($mem < $recommended && $mem > 0) {
597 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
598 $this->warning($testDetails);
601 $testDetails[2] .= " " . ts("We can't determine how much memory you have allocated. Install only if you're sure you've allocated at least %1 MB.", array(1 => 32));
602 $this->warning($testDetails);
609 public function getPHPMemory() {
610 $memString = ini_get("memory_limit");
612 switch (strtolower(substr($memString, -1))) {
614 return round(substr($memString, 0, -1) * 1024);
617 return round(substr($memString, 0, -1) * 1024 * 1024);
620 return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
623 return round($memString);
627 public function listErrors() {
629 echo "<p>" . ts("The following problems are preventing me from installing CiviCRM:") . "</p>";
630 foreach ($this->errors
as $error) {
631 echo "<li>" . htmlentities($error) . "</li>";
637 * @param null $section
639 public function showTable($section = NULL) {
641 $tests = $this->tests
[$section];
642 echo "<table class=\"testResults\" width=\"100%\">";
643 foreach ($tests as $test => $result) {
644 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
649 foreach ($this->tests
as $section => $tests) {
650 echo "<h3>$section</h3>";
651 echo "<table class=\"testResults\" width=\"100%\">";
653 foreach ($tests as $test => $result) {
654 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
662 * @param string $funcName
663 * @param $testDetails
667 public function requireFunction($funcName, $testDetails) {
668 $this->testing($testDetails);
670 if (!function_exists($funcName)) {
671 $this->error($testDetails);
680 * @param $testDetails
682 public function checkXCache($testDetails) {
683 if (function_exists('xcache_isset') &&
684 ini_get('xcache.size') > 0
686 $this->testing($testDetails);
687 $this->warning($testDetails);
693 * @param $testDetails
694 * @param null $maxVersion
696 public function requirePHPVersion($minVersion, $testDetails, $maxVersion = NULL) {
698 $this->testing($testDetails);
700 $phpVersion = phpversion();
701 $aboveMinVersion = version_compare($phpVersion, $minVersion) >= 0;
702 $belowMaxVersion = $maxVersion ?
version_compare($phpVersion, $maxVersion) < 0 : TRUE;
704 if ($maxVersion && $aboveMinVersion && $belowMaxVersion) {
707 elseif (!$maxVersion && $aboveMinVersion) {
711 if (!$testDetails[2]) {
712 if (!$aboveMinVersion) {
713 $testDetails[2] = ts("You need PHP version %1 or later, only %2 is installed. Please upgrade your server, or ask your web-host to do so.", array(1 => $minVersion, 2 => $phpVersion));
716 $testDetails[2] = ts("PHP version %1 is not supported. PHP version earlier than %2 is required. You might want to downgrade your server, or ask your web-host to do so.", array(1 => $maxVersion, 2 => $phpVersion));
720 $this->error($testDetails);
724 * @param string $filename
725 * @param $testDetails
726 * @param bool $absolute
728 public function requireFile($filename, $testDetails, $absolute = FALSE) {
729 $this->testing($testDetails);
731 $filename = $this->getBaseDir() . $filename;
733 if (!file_exists($filename)) {
734 $testDetails[2] .= " (" . ts("file '%1' not found", array(1 => $filename)) . ')';
735 $this->error($testDetails);
740 * @param $testDetails
742 public function requireNoPathSeparator($testDetails) {
743 $this->testing($testDetails);
744 if (substr_count($this->getBaseDir(), PATH_SEPARATOR
)) {
745 $this->error($testDetails);
750 * @param string $filename
751 * @param $testDetails
753 public function requireNoFile($filename, $testDetails) {
754 $this->testing($testDetails);
755 $filename = $this->getBaseDir() . $filename;
756 if (file_exists($filename)) {
757 $testDetails[2] .= " (" . ts("file '%1' found", array(1 => $filename)) . ")";
758 $this->error($testDetails);
763 * @param string $filename
764 * @param $testDetails
766 public function moveFileOutOfTheWay($filename, $testDetails) {
767 $this->testing($testDetails);
768 $filename = $this->getBaseDir() . $filename;
769 if (file_exists($filename)) {
770 if (file_exists("$filename.bak")) {
773 rename($filename, "$filename.bak");
778 * @param string $filename
779 * @param $testDetails
780 * @param bool $absolute
782 public function requireWriteable($filename, $testDetails, $absolute = FALSE) {
783 $this->testing($testDetails);
785 $filename = $this->getBaseDir() . $filename;
788 if (!is_writable($filename)) {
790 if (function_exists('posix_getpwuid')) {
791 $user = posix_getpwuid(posix_geteuid());
792 $name = '- ' . $user['name'] . ' -';
795 if (!isset($testDetails[2])) {
796 $testDetails[2] = NULL;
798 $testDetails[2] .= ts("The user account used by your web-server %1 needs to be granted write access to the following directory in order to configure the CiviCRM settings file:", array(1 => $name)) . "\n$filename";
799 $this->error($testDetails);
804 * @param string $moduleName
805 * @param $testDetails
807 public function requireApacheModule($moduleName, $testDetails) {
808 $this->testing($testDetails);
809 if (!in_array($moduleName, apache_get_modules())) {
810 $this->error($testDetails);
816 * @param string $username
818 * @param $testDetails
820 public function requireMysqlConnection($server, $username, $password, $testDetails) {
821 $this->testing($testDetails);
822 $conn = @mysql_connect
($server, $username, $password);
828 $testDetails[2] .= ": " . mysql_error();
829 $this->error($testDetails);
835 * @param $testDetails
837 public function requireMySQLServer($server, $testDetails) {
838 $this->testing($testDetails);
839 $conn = @mysql_connect
($server, NULL, NULL);
841 if ($conn ||
mysql_errno() < 2000) {
845 $testDetails[2] .= ": " . mysql_error();
846 $this->error($testDetails);
852 * @param $testDetails
854 public function requireMySQLVersion($version, $testDetails) {
855 $this->testing($testDetails);
857 if (!mysql_get_server_info()) {
858 $testDetails[2] = ts('Cannot determine the version of MySQL installed. Please ensure at least version %1 is installed.', array(1 => $version));
859 $this->warning($testDetails);
862 list($majorRequested, $minorRequested) = explode('.', $version);
863 list($majorHas, $minorHas) = explode('.', mysql_get_server_info());
865 if (($majorHas > $majorRequested) ||
($majorHas == $majorRequested && $minorHas >= $minorRequested)) {
869 $testDetails[2] .= "{$majorHas}.{$minorHas}.";
870 $this->error($testDetails);
877 * @param string $username
880 * @param $testDetails
882 public function requireMySQLInnoDB($server, $username, $password, $database, $testDetails) {
883 $this->testing($testDetails);
884 $conn = @mysql_connect
($server, $username, $password);
886 $testDetails[2] .= ' ' . ts("Could not determine if MySQL has InnoDB support. Assuming no.");
887 $this->error($testDetails);
891 $innodb_support = FALSE;
892 $result = mysql_query("SHOW ENGINES", $conn);
893 while ($values = mysql_fetch_array($result)) {
894 if ($values['Engine'] == 'InnoDB') {
895 if (strtolower($values['Support']) == 'yes' ||
896 strtolower($values['Support']) == 'default'
898 $innodb_support = TRUE;
902 if ($innodb_support) {
903 $testDetails[3] = ts('MySQL server does have InnoDB support');
906 $testDetails[2] .= ' ' . ts('Could not determine if MySQL has InnoDB support. Assuming no');
912 * @param string $username
915 * @param $testDetails
917 public function requireMySQLTempTables($server, $username, $password, $database, $testDetails) {
918 $this->testing($testDetails);
919 $conn = @mysql_connect
($server, $username, $password);
921 $testDetails[2] = ts('Could not login to the database.');
922 $this->error($testDetails);
926 if (!@mysql_select_db
($database, $conn)) {
927 $testDetails[2] = ts('Could not select the database.');
928 $this->error($testDetails);
932 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
934 $testDetails[2] = ts('Could not create a temp table.');
935 $this->error($testDetails);
937 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
942 * @param string $username
945 * @param $testDetails
947 public function requireMySQLTrigger($server, $username, $password, $database, $testDetails) {
948 $this->testing($testDetails);
949 $conn = @mysql_connect
($server, $username, $password);
951 $testDetails[2] = ts('Could not login to the database.');
952 $this->error($testDetails);
956 if (!@mysql_select_db
($database, $conn)) {
957 $testDetails[2] = ts('Could not select the database.');
958 $this->error($testDetails);
962 $result = mysql_query('CREATE TABLE civicrm_install_temp_table_test (test text)', $conn);
964 $testDetails[2] = ts('Could not create a table in the database.');
965 $this->error($testDetails);
968 $result = mysql_query('CREATE TRIGGER civicrm_install_temp_table_test_trigger BEFORE INSERT ON civicrm_install_temp_table_test FOR EACH ROW BEGIN END');
970 mysql_query('DROP TABLE civicrm_install_temp_table_test');
971 $testDetails[2] = ts('Could not create a database trigger.');
972 $this->error($testDetails);
975 mysql_query('DROP TRIGGER civicrm_install_temp_table_test_trigger');
976 mysql_query('DROP TABLE civicrm_install_temp_table_test');
982 * @param string $username
985 * @param $testDetails
987 public function requireMySQLLockTables($server, $username, $password, $database, $testDetails) {
988 $this->testing($testDetails);
989 $conn = @mysql_connect
($server, $username, $password);
991 $testDetails[2] = ts('Could not connect to the database server.');
992 $this->error($testDetails);
996 if (!@mysql_select_db
($database, $conn)) {
997 $testDetails[2] = ts('Could not select the database.');
998 $this->error($testDetails);
1002 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
1004 $testDetails[2] = ts('Could not create a table in the database.');
1005 $this->error($testDetails);
1009 $result = mysql_query('LOCK TABLES civicrm_install_temp_table_test WRITE', $conn);
1011 $testDetails[2] = ts('Could not obtain a write lock for the database table.');
1012 $this->error($testDetails);
1013 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1017 $result = mysql_query('UNLOCK TABLES', $conn);
1019 $testDetails[2] = ts('Could not release the lock for the database table.');
1020 $this->error($testDetails);
1021 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1025 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1030 * @param string $username
1032 * @param $testDetails
1034 public function requireMySQLAutoIncrementIncrementOne($server, $username, $password, $testDetails) {
1035 $this->testing($testDetails);
1036 $conn = @mysql_connect
($server, $username, $password);
1038 $testDetails[2] = ts('Could not connect to the database server.');
1039 $this->error($testDetails);
1043 $result = mysql_query("SHOW variables like 'auto_increment_increment'", $conn);
1045 $testDetails[2] = ts('Could not query database server variables.');
1046 $this->error($testDetails);
1050 $values = mysql_fetch_row($result);
1051 if ($values[1] == 1) {
1052 $testDetails[3] = ts('MySQL server auto_increment_increment is 1');
1055 $this->error($testDetails);
1062 * @param string $username
1065 * @param $minValueKB
1066 * @param $testDetails
1068 public function requireMySQLThreadStack($server, $username, $password, $database, $minValueKB, $testDetails) {
1069 $this->testing($testDetails);
1070 $conn = @mysql_connect
($server, $username, $password);
1072 $testDetails[2] = ts('Could not connect to the database server.');
1073 $this->error($testDetails);
1077 if (!@mysql_select_db
($database, $conn)) {
1078 $testDetails[2] = ts('Could not select the database.');
1079 $this->error($testDetails);
1083 $result = mysql_query("SHOW VARIABLES LIKE 'thread_stack'", $conn); // bytes => kb
1085 $testDetails[2] = ts('Could not get information about the thread_stack of the database.');
1086 $this->error($testDetails);
1089 $values = mysql_fetch_row($result);
1090 if ($values[1] < (1024 * $minValueKB)) {
1091 $testDetails[2] = ts('MySQL "thread_stack" is %1 kb', array(1 => ($values[1] / 1024)));
1092 $this->error($testDetails);
1099 * @param string $username
1102 * @param $testDetails
1103 * @param bool $onlyRequire
1105 public function requireDatabaseOrCreatePermissions(
1111 $onlyRequire = FALSE
1113 $this->testing($testDetails);
1114 $conn = @mysql_connect
($server, $username, $password);
1117 if (@mysql_select_db
($database)) {
1118 $okay = "Database '$database' exists";
1120 elseif ($onlyRequire) {
1121 $testDetails[2] = ts("The database: '%1' does not exist.", array(1 => $database));
1122 $this->error($testDetails);
1126 if (@mysql_query
("CREATE DATABASE $database")) {
1127 $okay = ts("Able to create a new database.");
1130 $testDetails[2] .= " (" . ts("user '%1' doesn't have CREATE DATABASE permissions.", array(1 => $username)) . ")";
1131 $this->error($testDetails);
1137 $testDetails[3] = $okay;
1138 $this->testing($testDetails);
1144 * @param $errorMessage
1146 public function requireServerVariables($varNames, $errorMessage) {
1147 //$this->testing($testDetails);
1148 foreach ($varNames as $varName) {
1149 if (!$_SERVER[$varName]) {
1150 $missing[] = '$_SERVER[' . $varName . ']';
1153 if (!isset($missing)) {
1157 $testDetails[2] = " (" . ts('the following PHP variables are missing: %1', array(1 => implode(", ", $missing))) . ")";
1158 $this->error($testDetails);
1163 * @param $testDetails
1167 public function isRunningApache($testDetails) {
1168 $this->testing($testDetails);
1169 if (function_exists('apache_get_modules') ||
stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) {
1173 $this->warning($testDetails);
1180 public function getBaseDir() {
1181 return dirname($_SERVER['SCRIPT_FILENAME']) . CIVICRM_DIRECTORY_SEPARATOR
;
1185 * @param $testDetails
1187 public function testing($testDetails) {
1188 if (!$testDetails) {
1192 $section = $testDetails[0];
1193 $test = $testDetails[1];
1195 $message = ts("OK");
1196 if (isset($testDetails[3])) {
1197 $message .= " ($testDetails[3])";
1200 $this->tests
[$section][$test] = array("good", $message);
1204 * @param $testDetails
1206 public function error($testDetails) {
1207 $section = $testDetails[0];
1208 $test = $testDetails[1];
1210 $this->tests
[$section][$test] = array("error", $testDetails[2]);
1211 $this->errors
[] = $testDetails;
1215 * @param $testDetails
1217 public function warning($testDetails) {
1218 $section = $testDetails[0];
1219 $test = $testDetails[1];
1221 $this->tests
[$section][$test] = array("warning", $testDetails[2]);
1222 $this->warnings
[] = $testDetails;
1228 public function hasErrors() {
1229 return count($this->errors
);
1235 public function hasWarnings() {
1236 return count($this->warnings
);
1244 class Installer
extends InstallRequirements
{
1251 public function createDatabaseIfNotExists($server, $username, $password, $database) {
1252 $conn = @mysql_connect
($server, $username, $password);
1254 if (@mysql_select_db
($database)) {
1255 // skip if database already present
1259 if (@mysql_query
("CREATE DATABASE $database")) {
1262 $errorTitle = ts("Oops! Could not create database %1", array(1 => $database));
1263 $errorMsg = ts("We encountered an error when attempting to create the database. Please check your MySQL server permissions and the database name and try again.");
1264 errorDisplayPage($errorTitle, $errorMsg);
1273 public function install($config) {
1274 global $installDirPath;
1276 // create database if does not exists
1277 $this->createDatabaseIfNotExists($config['mysql']['server'],
1278 $config['mysql']['username'],
1279 $config['mysql']['password'],
1280 $config['mysql']['database']
1283 global $installDirPath;
1286 require_once $installDirPath . 'civicrm.php';
1287 civicrm_main($config);
1289 if (!$this->errors
) {
1290 global $installType, $installURLPath;
1292 $registerSiteURL = "https://civicrm.org/register-site";
1293 $commonOutputMessage
1294 = "<li>" . ts("Have you registered this site at CiviCRM.org? If not, please help strengthen the CiviCRM ecosystem by taking a few minutes to <a %1>fill out the site registration form</a>. The information collected will help us prioritize improvements, target our communications and build the community. If you have a technical role for this site, be sure to check Keep in Touch to receive technical updates (a low volume mailing list).", array(1 => "href='$registerSiteURL' target='_blank'")) . "</li>"
1295 . "<li>" . ts("We have integrated KCFinder with CKEditor and TinyMCE. This allows a user to upload images. All uploaded images are public.") . "</li>";
1300 $installType == 'drupal' &&
1301 version_compare(VERSION
, '7.0-rc1') >= 0
1307 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1308 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1309 $output .= '<head>';
1310 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1311 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1312 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1313 $output .= '</head>';
1314 $output .= '<body>';
1315 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1318 $drupalURL = civicrm_cms_base();
1319 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/people/permissions";
1320 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1322 $output .= "<li>" . ts("Drupal user permissions have been automatically set - giving anonymous and authenticated users access to public CiviCRM forms and features. We recommend that you <a %1>review these permissions</a> to ensure that they are appropriate for your requirements (<a %2>learn more...</a>)", array(1 => "target='_blank' href='{$drupalPermissionsURL}'", 2 => "target='_blank' href='http://wiki.civicrm.org/confluence/display/CRMDOC/Default+Permissions+and+Roles'")) . "</li>";
1323 $output .= "<li>" . ts("Use the <a %1>Configuration Checklist</a> to review and configure settings for your new site", array(1 => "target='_blank' href='$drupalURL'")) . "</li>";
1324 $output .= $commonOutputMessage;
1326 // automatically enable CiviCRM module once it is installed successfully.
1327 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1328 global $cmsPath, $crmPath;
1330 // relative / abosolute paths are not working for drupal, hence using chdir()
1333 // Force the re-initialisation of the config singleton on the next call
1334 // since so far, we had used the Config object without loading the DB.
1335 $c = CRM_Core_Config
::singleton(FALSE);
1338 include_once "./includes/bootstrap.inc";
1339 include_once "./includes/unicode.inc";
1341 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1343 // prevent session information from being saved.
1344 drupal_save_session(FALSE);
1346 // Force the current user to anonymous.
1347 $original_user = $GLOBALS['user'];
1348 $GLOBALS['user'] = drupal_anonymous_user();
1350 // explicitly setting error reporting, since we cannot handle drupal related notices
1353 // rebuild modules, so that civicrm is added
1354 system_rebuild_module_data();
1356 // now enable civicrm module.
1357 module_enable(array('civicrm', 'civicrmtheme'));
1359 // clear block, page, theme, and hook caches
1360 drupal_flush_all_caches();
1362 //add basic drupal permissions
1363 civicrm_install_set_drupal_perms();
1365 // restore the user.
1366 $GLOBALS['user'] = $original_user;
1367 drupal_save_session(TRUE);
1369 //change the default language to one chosen
1370 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1371 // This ensures that defaults get set, otherwise the user will login
1372 // and most configurations will be empty, not set to en_US defaults.
1373 civicrm_api3('Setting', 'revert');
1375 civicrm_api3('Setting', 'create', array(
1376 'domain_id' => 'current_domain',
1377 'lcMessages' => $config['seedLanguage'],
1383 $output .= '</div>';
1384 $output .= '</body>';
1385 $output .= '</html>';
1388 elseif ($installType == 'drupal' && version_compare(VERSION
, '6.0') >= 0) {
1392 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1393 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1394 $output .= '<head>';
1395 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1396 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1397 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1398 $output .= '</head>';
1399 $output .= '<body>';
1400 $output .= '<div style="padding: 1em;"><p class="good">' . ts("CiviCRM has been successfully installed") . '</p>';
1403 $drupalURL = civicrm_cms_base();
1404 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/user/permissions";
1405 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1407 $output .= "<li>" . ts("Drupal user permissions have been automatically set - giving anonymous and authenticated users access to public CiviCRM forms and features. We recommend that you <a %1>review these permissions</a> to ensure that they are appropriate for your requirements (<a %2>learn more...</a>)", array(1 => "target='_blank' href='{$drupalPermissionsURL}'", 2 => "target='_blank' href='http://wiki.civicrm.org/confluence/display/CRMDOC/Default+Permissions+and+Roles'")) . "</li>";
1408 $output .= "<li>" . ts("Use the <a %1>Configuration Checklist</a> to review and configure settings for your new site", array(1 => "target='_blank' href='$drupalURL'")) . "</li>";
1409 $output .= $commonOutputMessage;
1411 // explicitly setting error reporting, since we cannot handle drupal related notices
1414 // automatically enable CiviCRM module once it is installed successfully.
1415 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1416 global $cmsPath, $crmPath;
1418 // relative / abosolute paths are not working for drupal, hence using chdir()
1421 // Force the re-initialisation of the config singleton on the next call
1422 // since so far, we had used the Config object without loading the DB.
1423 $c = CRM_Core_Config
::singleton(FALSE);
1426 include_once "./includes/bootstrap.inc";
1427 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1429 // rebuild modules, so that civicrm is added
1430 module_rebuild_cache();
1432 // now enable civicrm module.
1433 module_enable(array('civicrm'));
1435 // clear block, page, theme, and hook caches
1436 drupal_flush_all_caches();
1438 //add basic drupal permissions
1439 db_query('UPDATE {permission} SET perm = CONCAT( perm, \', access CiviMail subscribe/unsubscribe pages, access all custom data, access uploaded files, make online contributions, profile create, profile edit, profile view, register for events, view event info\') WHERE rid IN (1, 2)');
1443 elseif ($installType == 'wordpress') {
1444 echo '<h1>' . ts('CiviCRM Installed') . '</h1>';
1445 echo '<div style="padding: 1em;"><p style="background-color: #0C0; border: 1px #070 solid; color: white;">' . ts("CiviCRM has been successfully installed") . '</p>';
1448 $cmsURL = civicrm_cms_base();
1449 $cmsURL .= "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/configtask&reset=1";
1450 $wpPermissionsURL = "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/access/wp-permissions&reset=1";
1452 $output .= "<li>" . ts("WordPress user permissions have been automatically set - giving Anonymous and Subscribers access to public CiviCRM forms and features. We recommend that you <a %1>review these permissions</a> to ensure that they are appropriate for your requirements (<a %2>learn more...</a>)", array(1 => "target='_blank' href='{$wpPermissionsURL}'", 2 => "target='_blank' href='http://wiki.civicrm.org/confluence/display/CRMDOC/Default+Permissions+and+Roles'")) . "</li>";
1453 $output .= "<li>" . ts("Use the <a %1>Configuration Checklist</a> to review and configure settings for your new site", array(1 => "target='_blank' href='$cmsURL'")) . "</li>";
1454 $output .= $commonOutputMessage;
1459 $c = CRM_Core_Config
::singleton(FALSE);
1464 return $this->errors
;
1469 function civicrm_install_set_drupal_perms() {
1470 if (!function_exists('db_select')) {
1471 db_query('UPDATE {permission} SET perm = CONCAT( perm, \', access CiviMail subscribe/unsubscribe pages, access all custom data, access uploaded files, make online contributions, profile listings and forms, register for events, view event info, view event participants\') WHERE rid IN (1, 2)');
1475 'access all custom data',
1476 'access uploaded files',
1477 'make online contributions',
1481 'register for events',
1483 'view event participants',
1484 'access CiviMail subscribe/unsubscribe pages',
1487 // Adding a permission that has not yet been assigned to a module by
1488 // a hook_permission implementation results in a database error.
1490 $allPerms = array_keys(module_invoke_all('permission'));
1491 foreach (array_diff($perms, $allPerms) as $perm) {
1493 'Cannot grant the %perm permission because it does not yet exist.',
1494 array('%perm' => $perm),
1498 $perms = array_intersect($perms, $allPerms);
1499 user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID
, $perms);
1500 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID
, $perms);
1510 function getSiteDir($cmsPath, $str) {
1511 static $siteDir = '';
1517 $sites = CIVICRM_DIRECTORY_SEPARATOR
. 'sites' . CIVICRM_DIRECTORY_SEPARATOR
;
1518 $modules = CIVICRM_DIRECTORY_SEPARATOR
. 'modules' . CIVICRM_DIRECTORY_SEPARATOR
;
1519 preg_match("/" . preg_quote($sites, CIVICRM_DIRECTORY_SEPARATOR
) .
1520 "([\-a-zA-Z0-9_.]+)" .
1521 preg_quote($modules, CIVICRM_DIRECTORY_SEPARATOR
) . "/",
1522 $_SERVER['SCRIPT_FILENAME'], $matches
1524 $siteDir = isset($matches[1]) ?
$matches[1] : 'default';
1526 if (strtolower($siteDir) == 'all') {
1527 // For this case - use drupal's way of finding out multi-site directory
1528 $uri = explode(CIVICRM_DIRECTORY_SEPARATOR
, $_SERVER['SCRIPT_FILENAME']);
1529 $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
1530 for ($i = count($uri) - 1; $i > 0; $i--) {
1531 for ($j = count($server); $j > 0; $j--) {
1532 $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
1533 if (file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
1534 'sites' . CIVICRM_DIRECTORY_SEPARATOR
. $dir
1541 $siteDir = 'default';
1548 * @param $errorTitle
1552 function errorDisplayPage($errorTitle, $errorMsg, $showRefer = TRUE) {
1554 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, 'Installation Guide', NULL, NULL, "wiki");
1556 if (function_exists('ts')) {
1557 $errorMsg .= '<p>' . ts("<a %1>Refer to the online documentation for more information</a>", array(1 => "href='$docLink'")) . '</p>';
1560 $errorMsg .= '<p>' . sprintf("<a %s>Refer to the online documentation for more information</a>", "href='$docLink'") . '</p>';
1564 include 'error.html';