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-2017 by CiviCRM LLC
46 ini_set('max_execution_time', 3000);
48 if (stristr(PHP_OS
, 'WIN')) {
49 define('CIVICRM_DIRECTORY_SEPARATOR', '/');
50 define('CIVICRM_WINDOWS', 1);
53 define('CIVICRM_DIRECTORY_SEPARATOR', DIRECTORY_SEPARATOR
);
54 define('CIVICRM_WINDOWS', 0);
57 // set installation type - drupal
59 if (defined('PANTHEON_ENVIRONMENT')) {
60 ini_set('session.save_handler', 'files');
65 // unset civicrm session if any
66 if (array_key_exists('CiviCRM', $_SESSION)) {
67 unset($_SESSION['CiviCRM']);
70 if (isset($_GET['civicrm_install_type'])) {
71 $_SESSION['civicrm_install_type'] = $_GET['civicrm_install_type'];
74 if (!isset($_SESSION['civicrm_install_type'])) {
75 $_SESSION['civicrm_install_type'] = "drupal";
82 global $installDirPath;
83 global $installURLPath;
85 $installType = strtolower($_SESSION['civicrm_install_type']);
87 if ($installType == 'drupal' ||
$installType == 'backdrop') {
88 $crmPath = dirname(dirname($_SERVER['SCRIPT_FILENAME']));
89 $installDirPath = $installURLPath = '';
91 elseif ($installType == 'wordpress') {
92 $crmPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
;
93 $installDirPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'install' . DIRECTORY_SEPARATOR
;
94 $installURLPath = WP_PLUGIN_URL
. DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'install' . DIRECTORY_SEPARATOR
;
97 $errorTitle = "Oops! Unsupported installation mode";
98 $errorMsg = sprintf('%s: unknown installation mode. Please refer to the online documentation for more information.', $installType);
99 errorDisplayPage($errorTitle, $errorMsg, FALSE);
102 $pkgPath = $crmPath . DIRECTORY_SEPARATOR
. 'packages';
104 require_once $crmPath . '/CRM/Core/ClassLoader.php';
105 CRM_Core_ClassLoader
::singleton()->register();
107 // Load civicrm database config
108 if (isset($_POST['mysql'])) {
109 $databaseConfig = $_POST['mysql'];
112 $databaseConfig = array(
113 "server" => "localhost",
114 "username" => "civicrm",
116 "database" => "civicrm",
120 if ($installType == 'wordpress') {
121 // Load WP database config
122 if (isset($_POST['mysql'])) {
123 $databaseConfig = $_POST['mysql'];
126 $databaseConfig = array(
128 "username" => DB_USER
,
129 "password" => DB_PASSWORD
,
130 "database" => DB_NAME
,
135 if ($installType == 'drupal') {
136 // Load drupal database config
137 if (isset($_POST['drupal'])) {
138 $drupalConfig = $_POST['drupal'];
141 $drupalConfig = array(
142 "server" => "localhost",
143 "username" => "drupal",
145 "database" => "drupal",
150 if ($installType == 'backdrop') {
151 // Load backdrop database config
152 if (isset($_POST['backdrop'])) {
153 $backdropConfig = $_POST['backdrop'];
156 $backdropConfig = array(
157 "server" => "localhost",
158 "username" => "backdrop",
160 "database" => "backdrop",
166 if (isset($_POST['loadGenerated'])) {
170 require_once dirname(__FILE__
) . CIVICRM_DIRECTORY_SEPARATOR
. 'langs.php';
171 foreach ($langs as $locale => $_) {
172 if ($locale == 'en_US') {
175 if (!file_exists(implode(CIVICRM_DIRECTORY_SEPARATOR
, array($crmPath, 'sql', "civicrm_data.$locale.mysql")))) {
176 unset($langs[$locale]);
180 // Set the locale (required by CRM_Core_Config)
181 // This is mostly sympbolic, since nothing we do during the install
182 // really requires CIVICRM_UF to be defined.
183 $installTypeToUF = array(
184 'wordpress' => 'WordPress',
185 'drupal' => 'Drupal',
186 'backdrop' => 'Backdrop',
189 $uf = (isset($installTypeToUF[$installType]) ?
$installTypeToUF[$installType] : 'Drupal');
190 define('CIVICRM_UF', $uf);
195 $seedLanguage = 'en_US';
197 // CRM-16801 This validates that seedLanguage is valid by looking in $langs.
198 // NB: the variable is initial a $_REQUEST for the initial page reload,
199 // then becomes a $_POST when the installation form is submitted.
200 if (isset($_REQUEST['seedLanguage']) and isset($langs[$_REQUEST['seedLanguage']])) {
201 $seedLanguage = $_REQUEST['seedLanguage'];
202 $tsLocale = $_REQUEST['seedLanguage'];
205 $config = CRM_Core_Config
::singleton(FALSE);
206 $GLOBALS['civicrm_default_error_scope'] = NULL;
208 // The translation files are in the parent directory (l10n)
209 $i18n = CRM_Core_I18n
::singleton();
211 // Support for Arabic, Hebrew, Farsi, etc.
212 // Used in the template.html
213 $short_lang_code = CRM_Core_I18n_PseudoConstant
::shortForLong($tsLocale);
214 $text_direction = (CRM_Core_I18n
::isLanguageRTL($tsLocale) ?
'rtl' : 'ltr');
217 if ($installType == 'drupal') {
218 //CRM-6840 -don't force to install in sites/all/modules/
219 $object = new CRM_Utils_System_Drupal();
220 $cmsPath = $object->cmsRootPath();
222 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
223 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
224 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
225 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
226 'civicrm.settings.php'
229 elseif ($installType == 'backdrop') {
230 $object = new CRM_Utils_System_Backdrop();
231 $cmsPath = $object->cmsRootPath();
232 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
233 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
. 'civicrm.settings.php');
235 elseif ($installType == 'wordpress') {
236 $cmsPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm';
237 $upload_dir = wp_upload_dir();
238 $files_dirname = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm';
239 $wp_civi_settings = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm.settings.php';
240 $wp_civi_settings_deprectated = CIVICRM_PLUGIN_DIR
. 'civicrm.settings.php';
241 if (file_exists($wp_civi_settings_deprectated)) {
242 $alreadyInstalled = $wp_civi_settings_deprectated;
244 elseif (file_exists($wp_civi_settings)) {
245 $alreadyInstalled = $wp_civi_settings;
249 if ($installType == 'drupal') {
250 // Lets check only /modules/.
251 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR
. 'modules', CIVICRM_DIRECTORY_SEPARATOR
) . '/';
253 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
254 $directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array('sites', 'all', 'modules'));
255 $errorTitle = ts("Oops! Please correct your install location");
256 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
257 errorDisplayPage($errorTitle, $errorMsg);
261 if ($installType == 'backdrop') {
262 // Lets check only /modules/.
263 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR
. 'modules', CIVICRM_DIRECTORY_SEPARATOR
) . '/';
265 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
266 $directory = 'modules';
267 $errorTitle = ts("Oops! Please correct your install location");
268 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
269 errorDisplayPage($errorTitle, $errorMsg);
273 // Exit with error if CiviCRM has already been installed.
274 if ($alreadyInstalled) {
275 $errorTitle = ts("Oops! CiviCRM is already installed");
276 $settings_directory = $cmsPath;
278 if ($installType == 'drupal') {
279 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array(
280 ts('[your Drupal root directory]'),
285 if ($installType == 'backdrop') {
286 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array(
287 ts('[your Backdrop root directory]'),
292 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, ts('Installation Guide'), NULL, NULL, "wiki");
293 $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));
294 errorDisplayPage($errorTitle, $errorMsg, FALSE);
297 $versionFile = $crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'civicrm-version.php';
298 if (file_exists($versionFile)) {
299 require_once $versionFile;
300 $civicrm_version = civicrmVersion();
303 $civicrm_version = 'unknown';
306 if ($installType == 'drupal') {
307 // Ensure that they have downloaded the correct version of CiviCRM
308 if ($civicrm_version['cms'] != 'Drupal' && $civicrm_version['cms'] != 'Drupal6') {
309 $errorTitle = ts("Oops! Incorrect CiviCRM version");
310 $errorMsg = ts("This installer can only be used for the Drupal version of CiviCRM.");
311 errorDisplayPage($errorTitle, $errorMsg);
314 define('DRUPAL_ROOT', $cmsPath);
315 $drupalVersionFiles = array(
317 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'modules', 'system', 'system.module')),
319 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'includes', 'bootstrap.inc')),
321 foreach ($drupalVersionFiles as $drupalVersionFile) {
322 if (file_exists($drupalVersionFile)) {
323 require_once $drupalVersionFile;
327 if (!defined('VERSION') or version_compare(VERSION
, '6.0') < 0) {
328 $errorTitle = ts("Oops! Incorrect Drupal version");
329 $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)));
330 errorDisplayPage($errorTitle, $errorMsg);
333 elseif ($installType == 'backdrop') {
334 // Ensure that they have downloaded the correct version of CiviCRM
335 if ($civicrm_version['cms'] != 'Backdrop') {
336 $errorTitle = ts("Oops! Incorrect CiviCRM version");
337 $errorMsg = ts("This installer can only be used for the Backdrop version of CiviCRM.");
338 errorDisplayPage($errorTitle, $errorMsg);
341 define('BACKDROP_ROOT', $cmsPath);
343 $backdropVersionFiles = array(
345 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'core', 'includes', 'bootstrap.inc')),
347 foreach ($backdropVersionFiles as $backdropVersionFile) {
348 if (file_exists($backdropVersionFile)) {
349 require_once $backdropVersionFile;
352 if (!defined('BACKDROP_VERSION') or version_compare(BACKDROP_VERSION
, '1.0') < 0) {
353 $errorTitle = ts("Oops! Incorrect Backdrop version");
354 $errorMsg = ts("This version of CiviCRM can only be used with Backdrop 1.x. Please ensure that '%1' exists if you are running Backdrop 1.0 and over.", array(1 => implode("' or '", $backdropVersionFiles)));
355 errorDisplayPage($errorTitle, $errorMsg);
358 elseif ($installType == 'wordpress') {
360 $civicrm_version['cms'] = 'WordPress';
362 // Ensure that they have downloaded the correct version of CiviCRM
363 if ($civicrm_version['cms'] != 'WordPress') {
364 $errorTitle = ts("Oops! Incorrect CiviCRM version");
365 $errorMsg = ts("This installer can only be used for the WordPress version of CiviCRM.");
366 errorDisplayPage($errorTitle, $errorMsg);
370 // Check requirements
371 $req = new InstallRequirements();
374 if ($req->hasErrors()) {
375 $hasErrorOtherThanDatabase = TRUE;
378 if ($databaseConfig) {
379 $dbReq = new InstallRequirements();
380 $dbReq->checkdatabase($databaseConfig, 'CiviCRM');
381 if ($installType == 'drupal') {
382 $dbReq->checkdatabase($drupalConfig, 'Drupal');
384 if ($installType == 'backdrop') {
385 $dbReq->checkdatabase($backdropConfig, 'Backdrop');
390 if (isset($_POST['go']) && !$req->hasErrors() && !$dbReq->hasErrors()) {
391 // Confirm before reinstalling
392 if (!isset($_POST['force_reinstall']) && $alreadyInstalled) {
393 include $installDirPath . 'template.html';
396 $inst = new Installer();
397 $inst->install($_POST);
400 // Show the config form
403 include $installDirPath . 'template.html';
407 * This class checks requirements
408 * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array
410 * $description[0] - The test category
411 * $description[1] - The test title
412 * $description[2] - The test error to show, if it goes wrong
414 class InstallRequirements
{
415 var $errors, $warnings, $tests, $conn;
417 // @see CRM_Upgrade_Form::MINIMUM_THREAD_STACK
418 const MINIMUM_THREAD_STACK
= 192;
421 * Just check that the database configuration is okay.
422 * @param $databaseConfig
425 public function checkdatabase($databaseConfig, $dbName) {
426 if ($this->requireFunction('mysqli_connect',
428 ts("PHP Configuration"),
430 ts("MySQL support not included in PHP."),
434 $this->requireMySQLServer($databaseConfig['server'],
436 ts("MySQL %1 Configuration", array(1 => $dbName)),
437 ts("Does the server exist?"),
438 ts("Can't find the a MySQL server on '%1'.", array(1 => $databaseConfig['server'])),
439 $databaseConfig['server'],
442 if ($this->requireMysqlConnection($databaseConfig['server'],
443 $databaseConfig['username'],
444 $databaseConfig['password'],
446 ts("MySQL %1 Configuration", array(1 => $dbName)),
447 ts("Are the access credentials correct?"),
448 ts("That username/password doesn't work"),
452 @$this->requireMySQLVersion("5.1",
454 ts("MySQL %1 Configuration", array(1 => $dbName)),
455 ts("MySQL version at least %1", array(1 => '5.1')),
456 ts("MySQL version %1 or higher is required, you are running MySQL %2.", array(1 => '5.1', 2 => mysqli_get_server_info($this->conn
))),
457 ts("MySQL %1", array(1 => mysqli_get_server_info($this->conn
))),
460 $this->requireMySQLAutoIncrementIncrementOne($databaseConfig['server'],
461 $databaseConfig['username'],
462 $databaseConfig['password'],
464 ts("MySQL %1 Configuration", array(1 => $dbName)),
465 ts("Is auto_increment_increment set to 1"),
466 ts("An auto_increment_increment value greater than 1 is not currently supported. Please see issue CRM-7923 for further details and potential workaround."),
469 $testDetails = array(
470 ts("MySQL %1 Configuration", array(1 => $dbName)),
471 ts("Is the provided database name valid?"),
472 ts("The database name provided is not valid. Please use only 0-9, a-z, A-Z, _ and - as characters in the name."),
474 if (!CRM_Core_DAO
::requireSafeDBName($databaseConfig['database'])) {
475 $this->error($testDetails);
479 $this->testing($testDetails);
481 $this->requireMySQLThreadStack($databaseConfig['server'],
482 $databaseConfig['username'],
483 $databaseConfig['password'],
484 $databaseConfig['database'],
485 self
::MINIMUM_THREAD_STACK
,
487 ts("MySQL %1 Configuration", array(1 => $dbName)),
488 ts("Does MySQL thread_stack meet minimum (%1k)", array(1 => self
::MINIMUM_THREAD_STACK
)),
490 // "The MySQL thread_stack does not meet minimum " . CRM_Upgrade_Form::MINIMUM_THREAD_STACK . "k. Please update thread_stack in my.cnf.",
494 $onlyRequire = ($dbName == 'Drupal' ||
$dbName == 'Backdrop') ?
TRUE : FALSE;
495 $this->requireDatabaseOrCreatePermissions(
496 $databaseConfig['server'],
497 $databaseConfig['username'],
498 $databaseConfig['password'],
499 $databaseConfig['database'],
501 ts("MySQL %1 Configuration", array(1 => $dbName)),
502 ts("Can I access/create the database?"),
503 ts("I can't create new databases and the database '%1' doesn't exist.", array(1 => $databaseConfig['database'])),
507 if ($dbName != 'Drupal' && $dbName != 'Backdrop') {
508 $this->requireMySQLInnoDB($databaseConfig['server'],
509 $databaseConfig['username'],
510 $databaseConfig['password'],
511 $databaseConfig['database'],
513 ts("MySQL %1 Configuration", array(1 => $dbName)),
514 ts("Can I access/create InnoDB tables in the database?"),
515 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."),
518 $this->requireMySQLTempTables($databaseConfig['server'],
519 $databaseConfig['username'],
520 $databaseConfig['password'],
521 $databaseConfig['database'],
523 ts("MySQL %1 Configuration", array(1 => $dbName)),
524 ts('Can I create temporary tables in the database?'),
525 ts('Unable to create temporary tables. This MySQL user is missing the CREATE TEMPORARY TABLES privilege.'),
528 $this->requireMySQLLockTables($databaseConfig['server'],
529 $databaseConfig['username'],
530 $databaseConfig['password'],
531 $databaseConfig['database'],
533 ts("MySQL %1 Configuration", array(1 => $dbName)),
534 ts('Can I create lock tables in the database?'),
535 ts('Unable to lock tables. This MySQL user is missing the LOCK TABLES privilege.'),
538 $this->requireMySQLTrigger($databaseConfig['server'],
539 $databaseConfig['username'],
540 $databaseConfig['password'],
541 $databaseConfig['database'],
543 ts("MySQL %1 Configuration", array(1 => $dbName)),
544 ts('Can I create triggers in the database?'),
545 ts('Unable to create triggers. This MySQL user is missing the CREATE TRIGGERS privilege.'),
553 * Check everything except the database.
555 public function check() {
556 global $crmPath, $installType;
558 $this->errors
= NULL;
560 // See also: CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER
561 $this->requirePHPVersion('5.3.4', array(
562 ts("PHP Configuration"),
563 ts("PHP5 installed"),
565 ts("PHP version %1", array(1 => phpversion())),
568 // Check that we can identify the root folder successfully
569 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'README.md',
571 ts("File permissions"),
572 ts("Does the webserver know where files are stored?"),
573 ts("The webserver isn't letting me identify where files are stored."),
579 // CRM-6485: make sure the path does not contain PATH_SEPARATOR, as we don’t know how to escape it
580 $this->requireNoPathSeparator(
582 ts("File permissions"),
583 ts('Does the CiviCRM path contain PATH_SEPARATOR?'),
584 ts('The path %1 contains PATH_SEPARATOR (the %2 character).', array(1 => $this->getBaseDir(), 2 => PATH_SEPARATOR
)),
589 $requiredDirectories = array('CRM', 'packages', 'templates', 'js', 'api', 'i', 'sql');
590 foreach ($requiredDirectories as $dir) {
591 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. $dir,
593 ts("File permissions"),
594 ts("Folder '%1' exists?", array(1 => $dir)),
595 ts("There is no '%1' folder.", array(1 => $dir)),
600 $configIDSiniDir = NULL;
602 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
603 if ($installType == 'drupal') {
605 // make sure that we can write to sites/default and files/
606 $writableDirectories = array(
607 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
608 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
609 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
611 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
612 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
616 elseif ($installType == 'backdrop') {
618 // make sure that we can write to sites/default and files/
619 $writableDirectories = array(
620 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
625 elseif ($installType == 'wordpress') {
626 // make sure that we can write to uploads/civicrm/
627 $upload_dir = wp_upload_dir();
628 $files_dirname = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm';
629 if (!file_exists($files_dirname)) {
630 wp_mkdir_p($files_dirname);
632 $writableDirectories = array($files_dirname);
635 foreach ($writableDirectories as $dir) {
636 $dirName = CIVICRM_WINDOWS ?
$dir : CIVICRM_DIRECTORY_SEPARATOR
. $dir;
637 $testDetails = array(
638 ts("File permissions"),
639 ts("Is the %1 folder writeable?", array(1 => $dir)),
642 $this->requireWriteable($dirName, $testDetails, TRUE);
645 //check for Config.IDS.ini, file may exist in re-install
646 $configIDSiniDir = array($cmsPath, 'sites', $siteDir, 'files', 'civicrm', 'upload', 'Config.IDS.ini');
648 if (is_array($configIDSiniDir) && !empty($configIDSiniDir)) {
649 $configIDSiniFile = implode(CIVICRM_DIRECTORY_SEPARATOR
, $configIDSiniDir);
650 if (file_exists($configIDSiniFile)) {
651 unlink($configIDSiniFile);
655 // Check for rewriting
656 if (isset($_SERVER['SERVER_SOFTWARE'])) {
657 $webserver = strip_tags(trim($_SERVER['SERVER_SOFTWARE']));
659 elseif (isset($_SERVER['SERVER_SIGNATURE'])) {
660 $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE']));
663 if ($webserver == '') {
664 $webserver = ts("I can't tell what webserver you are running");
667 // Check for $_SERVER configuration
668 $this->requireServerVariables(array('SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'), array(
669 ts("Webserver config"),
670 ts("Recognised webserver"),
671 ts("You seem to be using an unsupported webserver. The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set."),
674 // Check for MySQL support
675 $this->requireFunction('mysqli_connect', array(
676 ts("PHP Configuration"),
678 ts("MySQL support not included in PHP."),
681 // Check for JSON support
682 $this->requireFunction('json_encode', array(
683 ts("PHP Configuration"),
685 ts("JSON support not included in PHP."),
688 // Check for xcache_isset and emit warning if exists
689 $this->checkXCache(array(
690 ts("PHP Configuration"),
691 ts("XCache compatibility"),
692 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."),
695 // Check memory allocation
696 $this->requireMemory(32 * 1024 * 1024,
699 ts("PHP Configuration"),
700 ts("Memory allocated (PHP config option 'memory_limit')"),
701 ts("CiviCRM needs a minimum of %1 MB allocated to PHP, but recommends %2 MB.", array(1 => 32, 2 => 64)),
702 ini_get("memory_limit"),
706 return $this->errors
;
711 * @param $recommended
712 * @param $testDetails
714 public function requireMemory($min, $recommended, $testDetails) {
715 $this->testing($testDetails);
716 $mem = $this->getPHPMemory();
718 if ($mem < $min && $mem > 0) {
719 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
720 $this->error($testDetails);
722 elseif ($mem < $recommended && $mem > 0) {
723 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
724 $this->warning($testDetails);
727 $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));
728 $this->warning($testDetails);
735 public function getPHPMemory() {
736 $memString = ini_get("memory_limit");
738 switch (strtolower(substr($memString, -1))) {
740 return round(substr($memString, 0, -1) * 1024);
743 return round(substr($memString, 0, -1) * 1024 * 1024);
746 return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
749 return round($memString);
753 public function listErrors() {
755 echo "<p>" . ts("The following problems are preventing me from installing CiviCRM:") . "</p>";
756 foreach ($this->errors
as $error) {
757 echo "<li>" . htmlentities($error) . "</li>";
763 * @param null $section
765 public function showTable($section = NULL) {
767 $tests = $this->tests
[$section];
768 echo "<table class=\"testResults\" width=\"100%\">";
769 foreach ($tests as $test => $result) {
770 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
775 foreach ($this->tests
as $section => $tests) {
776 echo "<h3>$section</h3>";
777 echo "<table class=\"testResults\" width=\"100%\">";
779 foreach ($tests as $test => $result) {
780 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
788 * @param string $funcName
789 * @param $testDetails
793 public function requireFunction($funcName, $testDetails) {
794 $this->testing($testDetails);
796 if (!function_exists($funcName)) {
797 $this->error($testDetails);
806 * @param $testDetails
808 public function checkXCache($testDetails) {
809 if (function_exists('xcache_isset') &&
810 ini_get('xcache.size') > 0
812 $this->testing($testDetails);
813 $this->warning($testDetails);
819 * @param $testDetails
820 * @param null $maxVersion
822 public function requirePHPVersion($minVersion, $testDetails, $maxVersion = NULL) {
824 $this->testing($testDetails);
826 $phpVersion = phpversion();
827 $aboveMinVersion = version_compare($phpVersion, $minVersion) >= 0;
828 $belowMaxVersion = $maxVersion ?
version_compare($phpVersion, $maxVersion) < 0 : TRUE;
830 if ($aboveMinVersion && $belowMaxVersion) {
831 if (version_compare(phpversion(), CRM_Upgrade_Incremental_General
::MIN_RECOMMENDED_PHP_VER
) < 0) {
832 $testDetails[2] = ts('This webserver is running an outdated version of PHP (%1). It is strongly recommended to upgrade to PHP %2 or later, as older versions can present a security risk.', array(
834 2 => CRM_Upgrade_Incremental_General
::MIN_RECOMMENDED_PHP_VER
,
836 $this->warning($testDetails);
841 if (!$testDetails[2]) {
842 if (!$aboveMinVersion) {
843 $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));
846 $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));
850 $this->error($testDetails);
854 * @param string $filename
855 * @param $testDetails
856 * @param bool $absolute
858 public function requireFile($filename, $testDetails, $absolute = FALSE) {
859 $this->testing($testDetails);
861 $filename = $this->getBaseDir() . $filename;
863 if (!file_exists($filename)) {
864 $testDetails[2] .= " (" . ts("file '%1' not found", array(1 => $filename)) . ')';
865 $this->error($testDetails);
870 * @param $testDetails
872 public function requireNoPathSeparator($testDetails) {
873 $this->testing($testDetails);
874 if (substr_count($this->getBaseDir(), PATH_SEPARATOR
)) {
875 $this->error($testDetails);
880 * @param string $filename
881 * @param $testDetails
883 public function requireNoFile($filename, $testDetails) {
884 $this->testing($testDetails);
885 $filename = $this->getBaseDir() . $filename;
886 if (file_exists($filename)) {
887 $testDetails[2] .= " (" . ts("file '%1' found", array(1 => $filename)) . ")";
888 $this->error($testDetails);
893 * @param string $filename
894 * @param $testDetails
896 public function moveFileOutOfTheWay($filename, $testDetails) {
897 $this->testing($testDetails);
898 $filename = $this->getBaseDir() . $filename;
899 if (file_exists($filename)) {
900 if (file_exists("$filename.bak")) {
903 rename($filename, "$filename.bak");
908 * @param string $filename
909 * @param $testDetails
910 * @param bool $absolute
912 public function requireWriteable($filename, $testDetails, $absolute = FALSE) {
913 $this->testing($testDetails);
915 $filename = $this->getBaseDir() . $filename;
918 if (!is_writable($filename)) {
920 if (function_exists('posix_getpwuid')) {
921 $user = posix_getpwuid(posix_geteuid());
922 $name = '- ' . $user['name'] . ' -';
925 if (!isset($testDetails[2])) {
926 $testDetails[2] = NULL;
928 $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";
929 $this->error($testDetails);
934 * @param string $moduleName
935 * @param $testDetails
937 public function requireApacheModule($moduleName, $testDetails) {
938 $this->testing($testDetails);
939 if (!in_array($moduleName, apache_get_modules())) {
940 $this->error($testDetails);
946 * @param string $username
948 * @param $testDetails
950 public function requireMysqlConnection($server, $username, $password, $testDetails) {
951 $this->testing($testDetails);
952 $this->conn
= @mysqli_connect
($server, $username, $password);
958 $testDetails[2] .= ": " . mysqli_connect_error();
959 $this->error($testDetails);
965 * @param $testDetails
967 public function requireMySQLServer($server, $testDetails) {
968 $this->testing($testDetails);
969 $conn = @mysqli_connect
($server, NULL, NULL);
971 if ($conn ||
mysqli_connect_errno() < 2000) {
975 $testDetails[2] .= ": " . mysqli_connect_error();
976 $this->error($testDetails);
982 * @param $testDetails
984 public function requireMySQLVersion($version, $testDetails) {
985 $this->testing($testDetails);
987 if (!mysqli_get_server_info($this->conn
)) {
988 $testDetails[2] = ts('Cannot determine the version of MySQL installed. Please ensure at least version %1 is installed.', array(1 => $version));
989 $this->warning($testDetails);
992 list($majorRequested, $minorRequested) = explode('.', $version);
993 list($majorHas, $minorHas) = explode('.', mysqli_get_server_info($this->conn
));
995 if (($majorHas > $majorRequested) ||
($majorHas == $majorRequested && $minorHas >= $minorRequested)) {
999 $testDetails[2] .= "{$majorHas}.{$minorHas}.";
1000 $this->error($testDetails);
1007 * @param string $username
1010 * @param $testDetails
1012 public function requireMySQLInnoDB($server, $username, $password, $database, $testDetails) {
1013 $this->testing($testDetails);
1014 $conn = @mysqli_connect
($server, $username, $password);
1016 $testDetails[2] .= ' ' . ts("Could not determine if MySQL has InnoDB support. Assuming no.");
1017 $this->error($testDetails);
1021 $innodb_support = FALSE;
1022 $result = mysqli_query($conn, "SHOW ENGINES");
1023 while ($values = mysqli_fetch_array($result)) {
1024 if ($values['Engine'] == 'InnoDB') {
1025 if (strtolower($values['Support']) == 'yes' ||
1026 strtolower($values['Support']) == 'default'
1028 $innodb_support = TRUE;
1032 if ($innodb_support) {
1033 $testDetails[3] = ts('MySQL server does have InnoDB support');
1036 $testDetails[2] .= ' ' . ts('Could not determine if MySQL has InnoDB support. Assuming no');
1042 * @param string $username
1045 * @param $testDetails
1047 public function requireMySQLTempTables($server, $username, $password, $database, $testDetails) {
1048 $this->testing($testDetails);
1049 $conn = @mysqli_connect
($server, $username, $password);
1051 $testDetails[2] = ts('Could not login to the database.');
1052 $this->error($testDetails);
1056 if (!@mysqli_select_db
($conn, $database)) {
1057 $testDetails[2] = ts('Could not select the database.');
1058 $this->error($testDetails);
1062 $result = mysqli_query($conn, 'CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)');
1064 $testDetails[2] = ts('Could not create a temp table.');
1065 $this->error($testDetails);
1067 $result = mysqli_query($conn, 'DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1072 * @param string $username
1075 * @param $testDetails
1077 public function requireMySQLTrigger($server, $username, $password, $database, $testDetails) {
1078 $this->testing($testDetails);
1079 $conn = @mysqli_connect
($server, $username, $password);
1081 $testDetails[2] = ts('Could not login to the database.');
1082 $this->error($testDetails);
1086 if (!@mysqli_select_db
($conn, $database)) {
1087 $testDetails[2] = ts('Could not select the database.');
1088 $this->error($testDetails);
1092 $result = mysqli_query($conn, 'CREATE TABLE civicrm_install_temp_table_test (test text)');
1094 $testDetails[2] = ts('Could not create a table in the database.');
1095 $this->error($testDetails);
1098 $result = mysqli_query($conn, 'CREATE TRIGGER civicrm_install_temp_table_test_trigger BEFORE INSERT ON civicrm_install_temp_table_test FOR EACH ROW BEGIN END');
1100 mysqli_query($conn, 'DROP TABLE civicrm_install_temp_table_test');
1101 $testDetails[2] = ts('Could not create a database trigger.');
1102 $this->error($testDetails);
1105 mysqli_query($conn, 'DROP TRIGGER civicrm_install_temp_table_test_trigger');
1106 mysqli_query($conn, 'DROP TABLE civicrm_install_temp_table_test');
1112 * @param string $username
1115 * @param $testDetails
1117 public function requireMySQLLockTables($server, $username, $password, $database, $testDetails) {
1118 $this->testing($testDetails);
1119 $conn = @mysqli_connect
($server, $username, $password);
1121 $testDetails[2] = ts('Could not connect to the database server.');
1122 $this->error($testDetails);
1126 if (!@mysqli_select_db
($conn, $database)) {
1127 $testDetails[2] = ts('Could not select the database.');
1128 $this->error($testDetails);
1132 $result = mysqli_query($conn, 'CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)');
1134 $testDetails[2] = ts('Could not create a table in the database.');
1135 $this->error($testDetails);
1139 $result = mysqli_query($conn, 'LOCK TABLES civicrm_install_temp_table_test WRITE');
1141 $testDetails[2] = ts('Could not obtain a write lock for the database table.');
1142 $this->error($testDetails);
1143 $result = mysqli_query($conn, 'DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1147 $result = mysqli_query($conn, 'UNLOCK TABLES');
1149 $testDetails[2] = ts('Could not release the lock for the database table.');
1150 $this->error($testDetails);
1151 $result = mysqli_query($conn, 'DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1155 $result = mysqli_query($conn, 'DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1160 * @param string $username
1162 * @param $testDetails
1164 public function requireMySQLAutoIncrementIncrementOne($server, $username, $password, $testDetails) {
1165 $this->testing($testDetails);
1166 $conn = @mysqli_connect
($server, $username, $password);
1168 $testDetails[2] = ts('Could not connect to the database server.');
1169 $this->error($testDetails);
1173 $result = mysqli_query($conn, "SHOW variables like 'auto_increment_increment'");
1175 $testDetails[2] = ts('Could not query database server variables.');
1176 $this->error($testDetails);
1180 $values = mysqli_fetch_row($result);
1181 if ($values[1] == 1) {
1182 $testDetails[3] = ts('MySQL server auto_increment_increment is 1');
1185 $this->error($testDetails);
1192 * @param string $username
1195 * @param $minValueKB
1196 * @param $testDetails
1198 public function requireMySQLThreadStack($server, $username, $password, $database, $minValueKB, $testDetails) {
1199 $this->testing($testDetails);
1200 $conn = @mysqli_connect
($server, $username, $password);
1202 $testDetails[2] = ts('Could not connect to the database server.');
1203 $this->error($testDetails);
1207 if (!@mysqli_select_db
($conn, $database)) {
1208 $testDetails[2] = ts('Could not select the database.');
1209 $this->error($testDetails);
1213 $result = mysqli_query($conn, "SHOW VARIABLES LIKE 'thread_stack'"); // bytes => kb
1215 $testDetails[2] = ts('Could not get information about the thread_stack of the database.');
1216 $this->error($testDetails);
1219 $values = mysqli_fetch_row($result);
1220 if ($values[1] < (1024 * $minValueKB)) {
1221 $testDetails[2] = ts('MySQL "thread_stack" is %1 kb', array(1 => ($values[1] / 1024)));
1222 $this->error($testDetails);
1229 * @param string $username
1232 * @param $testDetails
1233 * @param bool $onlyRequire
1235 public function requireDatabaseOrCreatePermissions(
1241 $onlyRequire = FALSE
1243 $this->testing($testDetails);
1244 $conn = @mysqli_connect
($server, $username, $password);
1247 if (@mysqli_select_db
($conn, $database)) {
1248 $okay = "Database '$database' exists";
1250 elseif ($onlyRequire) {
1251 $testDetails[2] = ts("The database: '%1' does not exist.", array(1 => $database));
1252 $this->error($testDetails);
1256 $query = sprintf("CREATE DATABASE %s", mysqli_real_escape_string($conn, $database));
1257 if (@mysqli_query
($conn, $query)) {
1258 $okay = ts("Able to create a new database.");
1261 $testDetails[2] .= " (" . ts("user '%1' doesn't have CREATE DATABASE permissions.", array(1 => $username)) . ")";
1262 $this->error($testDetails);
1268 $testDetails[3] = $okay;
1269 $this->testing($testDetails);
1275 * @param $errorMessage
1277 public function requireServerVariables($varNames, $errorMessage) {
1278 //$this->testing($testDetails);
1279 foreach ($varNames as $varName) {
1280 if (!$_SERVER[$varName]) {
1281 $missing[] = '$_SERVER[' . $varName . ']';
1284 if (!isset($missing)) {
1288 $testDetails[2] = " (" . ts('the following PHP variables are missing: %1', array(1 => implode(", ", $missing))) . ")";
1289 $this->error($testDetails);
1294 * @param $testDetails
1298 public function isRunningApache($testDetails) {
1299 $this->testing($testDetails);
1300 if (function_exists('apache_get_modules') ||
stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) {
1304 $this->warning($testDetails);
1311 public function getBaseDir() {
1312 return dirname($_SERVER['SCRIPT_FILENAME']) . CIVICRM_DIRECTORY_SEPARATOR
;
1316 * @param $testDetails
1318 public function testing($testDetails) {
1319 if (!$testDetails) {
1323 $section = $testDetails[0];
1324 $test = $testDetails[1];
1326 $message = ts("OK");
1327 if (isset($testDetails[3])) {
1328 $message .= " ($testDetails[3])";
1331 $this->tests
[$section][$test] = array("good", $message);
1335 * @param $testDetails
1337 public function error($testDetails) {
1338 $section = $testDetails[0];
1339 $test = $testDetails[1];
1341 $this->tests
[$section][$test] = array("error", $testDetails[2]);
1342 $this->errors
[] = $testDetails;
1346 * @param $testDetails
1348 public function warning($testDetails) {
1349 $section = $testDetails[0];
1350 $test = $testDetails[1];
1352 $this->tests
[$section][$test] = array("warning", $testDetails[2]);
1353 $this->warnings
[] = $testDetails;
1359 public function hasErrors() {
1360 return count($this->errors
);
1366 public function hasWarnings() {
1367 return count($this->warnings
);
1375 class Installer
extends InstallRequirements
{
1382 public function createDatabaseIfNotExists($server, $username, $password, $database) {
1383 $conn = @mysqli_connect
($server, $username, $password);
1385 if (@mysqli_select_db
($conn, $database)) {
1386 // skip if database already present
1389 $query = sprintf("CREATE DATABASE %s", mysqli_real_escape_string($conn, $database));
1390 if (@mysqli_query
($conn, $query)) {
1393 $errorTitle = ts("Oops! Could not create database %1", array(1 => $database));
1394 $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.");
1395 errorDisplayPage($errorTitle, $errorMsg);
1404 public function install($config) {
1405 global $installDirPath;
1407 // create database if does not exists
1408 $this->createDatabaseIfNotExists($config['mysql']['server'],
1409 $config['mysql']['username'],
1410 $config['mysql']['password'],
1411 $config['mysql']['database']
1414 global $installDirPath;
1417 require_once $installDirPath . 'civicrm.php';
1418 civicrm_main($config);
1420 if (!$this->errors
) {
1421 global $installType, $installURLPath;
1423 $registerSiteURL = "https://civicrm.org/register-site";
1424 $commonOutputMessage
1425 = "<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>"
1426 . "<li>" . ts("We have integrated KCFinder with CKEditor and TinyMCE. This allows a user to upload images. All uploaded images are public.") . "</li>";
1431 $installType == 'drupal' &&
1432 version_compare(VERSION
, '7.0-rc1') >= 0
1438 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1439 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1440 $output .= '<head>';
1441 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1442 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1443 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1444 $output .= '</head>';
1445 $output .= '<body>';
1446 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1449 $drupalURL = civicrm_cms_base();
1450 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/people/permissions";
1451 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1453 $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>";
1454 $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>";
1455 $output .= $commonOutputMessage;
1457 // automatically enable CiviCRM module once it is installed successfully.
1458 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1459 global $cmsPath, $crmPath;
1461 // relative / abosolute paths are not working for drupal, hence using chdir()
1464 // Force the re-initialisation of the config singleton on the next call
1465 // since so far, we had used the Config object without loading the DB.
1466 $c = CRM_Core_Config
::singleton(FALSE);
1469 include_once "./includes/bootstrap.inc";
1470 include_once "./includes/unicode.inc";
1472 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1474 // prevent session information from being saved.
1475 drupal_save_session(FALSE);
1477 // Force the current user to anonymous.
1478 $original_user = $GLOBALS['user'];
1479 $GLOBALS['user'] = drupal_anonymous_user();
1481 // explicitly setting error reporting, since we cannot handle drupal related notices
1484 // rebuild modules, so that civicrm is added
1485 system_rebuild_module_data();
1487 // now enable civicrm module.
1488 module_enable(array('civicrm', 'civicrmtheme'));
1490 // clear block, page, theme, and hook caches
1491 drupal_flush_all_caches();
1493 //add basic drupal permissions
1494 civicrm_install_set_drupal_perms();
1496 // restore the user.
1497 $GLOBALS['user'] = $original_user;
1498 drupal_save_session(TRUE);
1500 //change the default language to one chosen
1501 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1502 civicrm_api3('Setting', 'create', array(
1503 'domain_id' => 'current_domain',
1504 'lcMessages' => $config['seedLanguage'],
1510 $output .= '</div>';
1511 $output .= '</body>';
1512 $output .= '</html>';
1516 $installType == 'backdrop'
1522 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1523 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1524 $output .= '<head>';
1525 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1526 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1527 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1528 $output .= '</head>';
1529 $output .= '<body>';
1530 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1533 $backdropURL = civicrm_cms_base();
1534 $backdropPermissionsURL = "{$backdropURL}index.php?q=admin/config/people/permissions";
1535 $backdropURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1537 $output .= "<li>" . ts("Backdrop 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='{$backdropPermissionsURL}'", 2 => "target='_blank' href='http://wiki.civicrm.org/confluence/display/CRMDOC/Default+Permissions+and+Roles'")) . "</li>";
1538 $output .= "<li>" . ts("Use the <a %1>Configuration Checklist</a> to review and configure settings for your new site", array(1 => "target='_blank' href='$backdropURL'")) . "</li>";
1539 $output .= $commonOutputMessage;
1541 // automatically enable CiviCRM module once it is installed successfully.
1542 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1543 global $cmsPath, $crmPath;
1545 // relative / abosolute paths are not working for drupal, hence using chdir()
1548 // Force the re-initialisation of the config singleton on the next call
1549 // since so far, we had used the Config object without loading the DB.
1550 $c = CRM_Core_Config
::singleton(FALSE);
1553 include_once "./core/includes/bootstrap.inc";
1554 include_once "./core/includes/unicode.inc";
1556 backdrop_bootstrap(BACKDROP_BOOTSTRAP_FULL
);
1558 // prevent session information from being saved.
1559 backdrop_save_session(FALSE);
1561 // Force the current user to anonymous.
1562 $original_user = $GLOBALS['user'];
1563 $GLOBALS['user'] = backdrop_anonymous_user();
1565 // explicitly setting error reporting, since we cannot handle drupal related notices
1568 // rebuild modules, so that civicrm is added
1569 system_rebuild_module_data();
1571 // now enable civicrm module.
1572 module_enable(array('civicrm', 'civicrmtheme'));
1574 // clear block, page, theme, and hook caches
1575 backdrop_flush_all_caches();
1577 //add basic backdrop permissions
1578 civicrm_install_set_backdrop_perms();
1580 // restore the user.
1581 $GLOBALS['user'] = $original_user;
1582 backdrop_save_session(TRUE);
1584 //change the default language to one chosen
1585 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1586 civicrm_api3('Setting', 'create', array(
1587 'domain_id' => 'current_domain',
1588 'lcMessages' => $config['seedLanguage'],
1594 $output .= '</div>';
1595 $output .= '</body>';
1596 $output .= '</html>';
1599 elseif ($installType == 'drupal' && version_compare(VERSION
, '6.0') >= 0) {
1603 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1604 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1605 $output .= '<head>';
1606 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1607 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1608 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1609 $output .= '</head>';
1610 $output .= '<body>';
1611 $output .= '<div style="padding: 1em;"><p class="good">' . ts("CiviCRM has been successfully installed") . '</p>';
1614 $drupalURL = civicrm_cms_base();
1615 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/user/permissions";
1616 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1618 $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>";
1619 $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>";
1620 $output .= $commonOutputMessage;
1622 // explicitly setting error reporting, since we cannot handle drupal related notices
1625 // automatically enable CiviCRM module once it is installed successfully.
1626 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1627 global $cmsPath, $crmPath;
1629 // relative / abosolute paths are not working for drupal, hence using chdir()
1632 // Force the re-initialisation of the config singleton on the next call
1633 // since so far, we had used the Config object without loading the DB.
1634 $c = CRM_Core_Config
::singleton(FALSE);
1637 include_once "./includes/bootstrap.inc";
1638 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1640 // rebuild modules, so that civicrm is added
1641 module_rebuild_cache();
1643 // now enable civicrm module.
1644 module_enable(array('civicrm'));
1646 // clear block, page, theme, and hook caches
1647 drupal_flush_all_caches();
1649 //add basic drupal permissions
1650 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)');
1654 elseif ($installType == 'wordpress') {
1655 echo '<h1>' . ts('CiviCRM Installed') . '</h1>';
1656 echo '<div style="padding: 1em;"><p style="background-color: #0C0; border: 1px #070 solid; color: white;">' . ts("CiviCRM has been successfully installed") . '</p>';
1659 $cmsURL = civicrm_cms_base();
1660 $cmsURL .= "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/configtask&reset=1";
1661 $wpPermissionsURL = "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/access/wp-permissions&reset=1";
1663 $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>";
1664 $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>";
1665 $output .= $commonOutputMessage;
1670 $c = CRM_Core_Config
::singleton(FALSE);
1672 $wpInstallRedirect = admin_url("?page=CiviCRM&q=civicrm&reset=1");
1674 window.location = '$wpInstallRedirect';
1679 return $this->errors
;
1684 function civicrm_install_set_drupal_perms() {
1685 if (!function_exists('db_select')) {
1686 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)');
1690 'access all custom data',
1691 'access uploaded files',
1692 'make online contributions',
1696 'register for events',
1698 'view event participants',
1699 'access CiviMail subscribe/unsubscribe pages',
1702 // Adding a permission that has not yet been assigned to a module by
1703 // a hook_permission implementation results in a database error.
1705 $allPerms = array_keys(module_invoke_all('permission'));
1706 foreach (array_diff($perms, $allPerms) as $perm) {
1708 'Cannot grant the %perm permission because it does not yet exist.',
1709 array('%perm' => $perm),
1713 $perms = array_intersect($perms, $allPerms);
1714 user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID
, $perms);
1715 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID
, $perms);
1719 function civicrm_install_set_backdrop_perms() {
1721 'access all custom data',
1722 'access uploaded files',
1723 'make online contributions',
1727 'register for events',
1729 'view event participants',
1730 'access CiviMail subscribe/unsubscribe pages',
1733 // Adding a permission that has not yet been assigned to a module by
1734 // a hook_permission implementation results in a database error.
1736 $allPerms = array_keys(module_invoke_all('permission'));
1737 foreach (array_diff($perms, $allPerms) as $perm) {
1739 'Cannot grant the %perm permission because it does not yet exist.',
1740 array('%perm' => $perm),
1744 $perms = array_intersect($perms, $allPerms);
1745 user_role_grant_permissions(BACKDROP_AUTHENTICATED_ROLE
, $perms);
1746 user_role_grant_permissions(BACKDROP_ANONYMOUS_ROLE
, $perms);
1755 function getSiteDir($cmsPath, $str) {
1756 static $siteDir = '';
1762 $sites = CIVICRM_DIRECTORY_SEPARATOR
. 'sites' . CIVICRM_DIRECTORY_SEPARATOR
;
1763 $modules = CIVICRM_DIRECTORY_SEPARATOR
. 'modules' . CIVICRM_DIRECTORY_SEPARATOR
;
1764 preg_match("/" . preg_quote($sites, CIVICRM_DIRECTORY_SEPARATOR
) .
1765 "([\-a-zA-Z0-9_.]+)" .
1766 preg_quote($modules, CIVICRM_DIRECTORY_SEPARATOR
) . "/",
1767 $_SERVER['SCRIPT_FILENAME'], $matches
1769 $siteDir = isset($matches[1]) ?
$matches[1] : 'default';
1771 if (strtolower($siteDir) == 'all') {
1772 // For this case - use drupal's way of finding out multi-site directory
1773 $uri = explode(CIVICRM_DIRECTORY_SEPARATOR
, $_SERVER['SCRIPT_FILENAME']);
1774 $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
1775 for ($i = count($uri) - 1; $i > 0; $i--) {
1776 for ($j = count($server); $j > 0; $j--) {
1777 $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
1778 if (file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
1779 'sites' . CIVICRM_DIRECTORY_SEPARATOR
. $dir
1786 $siteDir = 'default';
1793 * @param $errorTitle
1797 function errorDisplayPage($errorTitle, $errorMsg, $showRefer = TRUE) {
1799 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, 'Installation Guide', NULL, NULL, "wiki");
1801 if (function_exists('ts')) {
1802 $errorMsg .= '<p>' . ts("<a %1>Refer to the online documentation for more information</a>", array(1 => "href='$docLink'")) . '</p>';
1805 $errorMsg .= '<p>' . sprintf("<a %s>Refer to the online documentation for more information</a>", "href='$docLink'") . '</p>';
1809 include 'error.html';