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
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') {
122 $databaseConfig = array(
124 "username" => DB_USER
,
125 "password" => DB_PASSWORD
,
126 "database" => DB_NAME
,
130 if ($installType == 'drupal') {
131 // Load drupal database config
132 if (isset($_POST['drupal'])) {
133 $drupalConfig = $_POST['drupal'];
136 $drupalConfig = array(
137 "server" => "localhost",
138 "username" => "drupal",
140 "database" => "drupal",
145 if ($installType == 'backdrop') {
146 // Load backdrop database config
147 if (isset($_POST['backdrop'])) {
148 $backdropConfig = $_POST['backdrop'];
151 $backdropConfig = array(
152 "server" => "localhost",
153 "username" => "backdrop",
155 "database" => "backdrop",
161 if (isset($_POST['loadGenerated'])) {
165 require_once dirname(__FILE__
) . CIVICRM_DIRECTORY_SEPARATOR
. 'langs.php';
166 foreach ($langs as $locale => $_) {
167 if ($locale == 'en_US') {
170 if (!file_exists(implode(CIVICRM_DIRECTORY_SEPARATOR
, array($crmPath, 'sql', "civicrm_data.$locale.mysql")))) {
171 unset($langs[$locale]);
175 // Set the locale (required by CRM_Core_Config)
176 // This is mostly sympbolic, since nothing we do during the install
177 // really requires CIVICRM_UF to be defined.
178 $installTypeToUF = array(
179 'wordpress' => 'WordPress',
180 'drupal' => 'Drupal',
181 'backdrop' => 'Backdrop',
184 $uf = (isset($installTypeToUF[$installType]) ?
$installTypeToUF[$installType] : 'Drupal');
185 define('CIVICRM_UF', $uf);
190 $seedLanguage = 'en_US';
192 // CRM-16801 This validates that seedLanguage is valid by looking in $langs.
193 // NB: the variable is initial a $_REQUEST for the initial page reload,
194 // then becomes a $_POST when the installation form is submitted.
195 if (isset($_REQUEST['seedLanguage']) and isset($langs[$_REQUEST['seedLanguage']])) {
196 $seedLanguage = $_REQUEST['seedLanguage'];
197 $tsLocale = $_REQUEST['seedLanguage'];
200 $config = CRM_Core_Config
::singleton(FALSE);
201 $GLOBALS['civicrm_default_error_scope'] = NULL;
203 // The translation files are in the parent directory (l10n)
204 $i18n = CRM_Core_I18n
::singleton();
206 // Support for Arabic, Hebrew, Farsi, etc.
207 // Used in the template.html
208 $short_lang_code = CRM_Core_I18n_PseudoConstant
::shortForLong($tsLocale);
209 $text_direction = (CRM_Core_I18n
::isLanguageRTL($tsLocale) ?
'rtl' : 'ltr');
212 if ($installType == 'drupal') {
213 //CRM-6840 -don't force to install in sites/all/modules/
214 $object = new CRM_Utils_System_Drupal();
215 $cmsPath = $object->cmsRootPath();
217 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
218 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
219 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
220 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
221 'civicrm.settings.php'
224 elseif ($installType == 'backdrop') {
225 $object = new CRM_Utils_System_Backdrop();
226 $cmsPath = $object->cmsRootPath();
227 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
228 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
. 'civicrm.settings.php');
230 elseif ($installType == 'wordpress') {
231 $cmsPath = WP_PLUGIN_DIR
. DIRECTORY_SEPARATOR
. 'civicrm';
232 $upload_dir = wp_upload_dir();
233 $files_dirname = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm';
234 $wp_civi_settings = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm' . DIRECTORY_SEPARATOR
. 'civicrm.settings.php';
235 $wp_civi_settings_deprectated = CIVICRM_PLUGIN_DIR
. 'civicrm.settings.php';
236 if (file_exists($wp_civi_settings_deprectated)) {
237 $alreadyInstalled = $wp_civi_settings_deprectated;
239 elseif (file_exists($wp_civi_settings)) {
240 $alreadyInstalled = $wp_civi_settings;
244 if ($installType == 'drupal') {
245 // Lets check only /modules/.
246 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR
. 'modules', CIVICRM_DIRECTORY_SEPARATOR
) . '/';
248 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
249 $directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array('sites', 'all', 'modules'));
250 $errorTitle = ts("Oops! Please correct your install location");
251 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
252 errorDisplayPage($errorTitle, $errorMsg);
256 if ($installType == 'backdrop') {
257 // Lets check only /modules/.
258 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR
. 'modules', CIVICRM_DIRECTORY_SEPARATOR
) . '/';
260 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
261 $directory = 'modules';
262 $errorTitle = ts("Oops! Please correct your install location");
263 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
264 errorDisplayPage($errorTitle, $errorMsg);
268 // Exit with error if CiviCRM has already been installed.
269 if ($alreadyInstalled) {
270 $errorTitle = ts("Oops! CiviCRM is already installed");
271 $settings_directory = $cmsPath;
273 if ($installType == 'drupal') {
274 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array(
275 ts('[your Drupal root directory]'),
280 if ($installType == 'backdrop') {
281 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR
, array(
282 ts('[your Backdrop root directory]'),
287 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, ts('Installation Guide'), NULL, NULL, "wiki");
288 $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));
289 errorDisplayPage($errorTitle, $errorMsg, FALSE);
292 $versionFile = $crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'civicrm-version.php';
293 if (file_exists($versionFile)) {
294 require_once $versionFile;
295 $civicrm_version = civicrmVersion();
298 $civicrm_version = 'unknown';
301 if ($installType == 'drupal') {
302 // Ensure that they have downloaded the correct version of CiviCRM
303 if ($civicrm_version['cms'] != 'Drupal' && $civicrm_version['cms'] != 'Drupal6') {
304 $errorTitle = ts("Oops! Incorrect CiviCRM version");
305 $errorMsg = ts("This installer can only be used for the Drupal version of CiviCRM.");
306 errorDisplayPage($errorTitle, $errorMsg);
309 define('DRUPAL_ROOT', $cmsPath);
310 $drupalVersionFiles = array(
312 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'modules', 'system', 'system.module')),
314 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'includes', 'bootstrap.inc')),
316 foreach ($drupalVersionFiles as $drupalVersionFile) {
317 if (file_exists($drupalVersionFile)) {
318 require_once $drupalVersionFile;
322 if (!defined('VERSION') or version_compare(VERSION
, '6.0') < 0) {
323 $errorTitle = ts("Oops! Incorrect Drupal version");
324 $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)));
325 errorDisplayPage($errorTitle, $errorMsg);
328 elseif ($installType == 'backdrop') {
329 // Ensure that they have downloaded the correct version of CiviCRM
330 if ($civicrm_version['cms'] != 'Backdrop') {
331 $errorTitle = ts("Oops! Incorrect CiviCRM version");
332 $errorMsg = ts("This installer can only be used for the Backdrop version of CiviCRM.");
333 errorDisplayPage($errorTitle, $errorMsg);
336 define('BACKDROP_ROOT', $cmsPath);
338 $backdropVersionFiles = array(
340 implode(CIVICRM_DIRECTORY_SEPARATOR
, array($cmsPath, 'core', 'includes', 'bootstrap.inc')),
342 foreach ($backdropVersionFiles as $backdropVersionFile) {
343 if (file_exists($backdropVersionFile)) {
344 require_once $backdropVersionFile;
347 if (!defined('BACKDROP_VERSION') or version_compare(BACKDROP_VERSION
, '1.0') < 0) {
348 $errorTitle = ts("Oops! Incorrect Backdrop version");
349 $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)));
350 errorDisplayPage($errorTitle, $errorMsg);
353 elseif ($installType == 'wordpress') {
355 $civicrm_version['cms'] = 'WordPress';
357 // Ensure that they have downloaded the correct version of CiviCRM
358 if ($civicrm_version['cms'] != 'WordPress') {
359 $errorTitle = ts("Oops! Incorrect CiviCRM version");
360 $errorMsg = ts("This installer can only be used for the WordPress version of CiviCRM.");
361 errorDisplayPage($errorTitle, $errorMsg);
365 // Check requirements
366 $req = new InstallRequirements();
369 if ($req->hasErrors()) {
370 $hasErrorOtherThanDatabase = TRUE;
373 if ($databaseConfig) {
374 $dbReq = new InstallRequirements();
375 $dbReq->checkdatabase($databaseConfig, 'CiviCRM');
376 if ($installType == 'drupal') {
377 $dbReq->checkdatabase($drupalConfig, 'Drupal');
379 if ($installType == 'backdrop') {
380 $dbReq->checkdatabase($backdropConfig, 'Backdrop');
385 if (isset($_POST['go']) && !$req->hasErrors() && !$dbReq->hasErrors()) {
386 // Confirm before reinstalling
387 if (!isset($_POST['force_reinstall']) && $alreadyInstalled) {
388 include $installDirPath . 'template.html';
391 $inst = new Installer();
392 $inst->install($_POST);
395 // Show the config form
398 include $installDirPath . 'template.html';
402 * This class checks requirements
403 * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array
405 * $description[0] - The test category
406 * $description[1] - The test title
407 * $description[2] - The test error to show, if it goes wrong
409 class InstallRequirements
{
410 var $errors, $warnings, $tests;
412 // @see CRM_Upgrade_Form::MINIMUM_THREAD_STACK
413 const MINIMUM_THREAD_STACK
= 192;
416 * Just check that the database configuration is okay.
417 * @param $databaseConfig
420 public function checkdatabase($databaseConfig, $dbName) {
421 if ($this->requireFunction('mysql_connect',
423 ts("PHP Configuration"),
425 ts("MySQL support not included in PHP."),
429 $this->requireMySQLServer($databaseConfig['server'],
431 ts("MySQL %1 Configuration", array(1 => $dbName)),
432 ts("Does the server exist?"),
433 ts("Can't find the a MySQL server on '%1'.", array(1 => $databaseConfig['server'])),
434 $databaseConfig['server'],
437 if ($this->requireMysqlConnection($databaseConfig['server'],
438 $databaseConfig['username'],
439 $databaseConfig['password'],
441 ts("MySQL %1 Configuration", array(1 => $dbName)),
442 ts("Are the access credentials correct?"),
443 ts("That username/password doesn't work"),
447 @$this->requireMySQLVersion("5.1",
449 ts("MySQL %1 Configuration", array(1 => $dbName)),
450 ts("MySQL version at least %1", array(1 => '5.1')),
451 ts("MySQL version %1 or higher is required, you are running MySQL %2.", array(1 => '5.1', 2 => mysql_get_server_info())),
452 ts("MySQL %1", array(1 => mysql_get_server_info())),
455 $this->requireMySQLAutoIncrementIncrementOne($databaseConfig['server'],
456 $databaseConfig['username'],
457 $databaseConfig['password'],
459 ts("MySQL %1 Configuration", array(1 => $dbName)),
460 ts("Is auto_increment_increment set to 1"),
461 ts("An auto_increment_increment value greater than 1 is not currently supported. Please see issue CRM-7923 for further details and potential workaround."),
464 $testDetails = array(
465 ts("MySQL %1 Configuration", array(1 => $dbName)),
466 ts("Is the provided database name valid?"),
467 ts("The database name provided is not valid. Please use only 0-9, a-z, A-Z and _ as characters in the name."),
469 if (!CRM_Core_DAO
::requireValidDBName($databaseConfig['database'])) {
470 $this->error($testDetails);
474 $this->testing($testDetails);
476 $this->requireMySQLThreadStack($databaseConfig['server'],
477 $databaseConfig['username'],
478 $databaseConfig['password'],
479 $databaseConfig['database'],
480 self
::MINIMUM_THREAD_STACK
,
482 ts("MySQL %1 Configuration", array(1 => $dbName)),
483 ts("Does MySQL thread_stack meet minimum (%1k)", array(1 => self
::MINIMUM_THREAD_STACK
)),
485 // "The MySQL thread_stack does not meet minimum " . CRM_Upgrade_Form::MINIMUM_THREAD_STACK . "k. Please update thread_stack in my.cnf.",
489 $onlyRequire = ($dbName == 'Drupal' ||
$dbName == 'Backdrop') ?
TRUE : FALSE;
490 $this->requireDatabaseOrCreatePermissions(
491 $databaseConfig['server'],
492 $databaseConfig['username'],
493 $databaseConfig['password'],
494 $databaseConfig['database'],
496 ts("MySQL %1 Configuration", array(1 => $dbName)),
497 ts("Can I access/create the database?"),
498 ts("I can't create new databases and the database '%1' doesn't exist.", array(1 => $databaseConfig['database'])),
502 if ($dbName != 'Drupal' && $dbName != 'Backdrop') {
503 $this->requireMySQLInnoDB($databaseConfig['server'],
504 $databaseConfig['username'],
505 $databaseConfig['password'],
506 $databaseConfig['database'],
508 ts("MySQL %1 Configuration", array(1 => $dbName)),
509 ts("Can I access/create InnoDB tables in the database?"),
510 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."),
513 $this->requireMySQLTempTables($databaseConfig['server'],
514 $databaseConfig['username'],
515 $databaseConfig['password'],
516 $databaseConfig['database'],
518 ts("MySQL %1 Configuration", array(1 => $dbName)),
519 ts('Can I create temporary tables in the database?'),
520 ts('Unable to create temporary tables. This MySQL user is missing the CREATE TEMPORARY TABLES privilege.'),
523 $this->requireMySQLLockTables($databaseConfig['server'],
524 $databaseConfig['username'],
525 $databaseConfig['password'],
526 $databaseConfig['database'],
528 ts("MySQL %1 Configuration", array(1 => $dbName)),
529 ts('Can I create lock tables in the database?'),
530 ts('Unable to lock tables. This MySQL user is missing the LOCK TABLES privilege.'),
533 $this->requireMySQLTrigger($databaseConfig['server'],
534 $databaseConfig['username'],
535 $databaseConfig['password'],
536 $databaseConfig['database'],
538 ts("MySQL %1 Configuration", array(1 => $dbName)),
539 ts('Can I create triggers in the database?'),
540 ts('Unable to create triggers. This MySQL user is missing the CREATE TRIGGERS privilege.'),
548 * Check everything except the database.
550 public function check() {
551 global $crmPath, $installType;
553 $this->errors
= NULL;
555 $this->requirePHPVersion('5.3.4', array(
556 ts("PHP Configuration"),
557 ts("PHP5 installed"),
559 ts("PHP version %1", array(1 => phpversion())),
562 // Check that we can identify the root folder successfully
563 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. 'README.txt',
565 ts("File permissions"),
566 ts("Does the webserver know where files are stored?"),
567 ts("The webserver isn't letting me identify where files are stored."),
573 // CRM-6485: make sure the path does not contain PATH_SEPARATOR, as we don’t know how to escape it
574 $this->requireNoPathSeparator(
576 ts("File permissions"),
577 ts('Does the CiviCRM path contain PATH_SEPARATOR?'),
578 ts('The path %1 contains PATH_SEPARATOR (the %2 character).', array(1 => $this->getBaseDir(), 2 => PATH_SEPARATOR
)),
583 $requiredDirectories = array('CRM', 'packages', 'templates', 'js', 'api', 'i', 'sql');
584 foreach ($requiredDirectories as $dir) {
585 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR
. $dir,
587 ts("File permissions"),
588 ts("Folder '%1' exists?", array(1 => $dir)),
589 ts("There is no '%1' folder.", array(1 => $dir)),
594 $configIDSiniDir = NULL;
596 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
597 if ($installType == 'drupal') {
599 // make sure that we can write to sites/default and files/
600 $writableDirectories = array(
601 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
602 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
603 $siteDir . CIVICRM_DIRECTORY_SEPARATOR
.
605 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
606 'sites' . CIVICRM_DIRECTORY_SEPARATOR
.
610 elseif ($installType == 'backdrop') {
612 // make sure that we can write to sites/default and files/
613 $writableDirectories = array(
614 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
619 elseif ($installType == 'wordpress') {
620 // make sure that we can write to uploads/civicrm/
621 $upload_dir = wp_upload_dir();
622 $files_dirname = $upload_dir['basedir'] . DIRECTORY_SEPARATOR
. 'civicrm';
623 if (!file_exists($files_dirname)) {
624 wp_mkdir_p($files_dirname);
626 $writableDirectories = array($files_dirname);
629 foreach ($writableDirectories as $dir) {
630 $dirName = CIVICRM_WINDOWS ?
$dir : CIVICRM_DIRECTORY_SEPARATOR
. $dir;
631 $testDetails = array(
632 ts("File permissions"),
633 ts("Is the %1 folder writeable?", array(1 => $dir)),
636 $this->requireWriteable($dirName, $testDetails, TRUE);
639 //check for Config.IDS.ini, file may exist in re-install
640 $configIDSiniDir = array($cmsPath, 'sites', $siteDir, 'files', 'civicrm', 'upload', 'Config.IDS.ini');
642 if (is_array($configIDSiniDir) && !empty($configIDSiniDir)) {
643 $configIDSiniFile = implode(CIVICRM_DIRECTORY_SEPARATOR
, $configIDSiniDir);
644 if (file_exists($configIDSiniFile)) {
645 unlink($configIDSiniFile);
649 // Check for rewriting
650 if (isset($_SERVER['SERVER_SOFTWARE'])) {
651 $webserver = strip_tags(trim($_SERVER['SERVER_SOFTWARE']));
653 elseif (isset($_SERVER['SERVER_SIGNATURE'])) {
654 $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE']));
657 if ($webserver == '') {
658 $webserver = ts("I can't tell what webserver you are running");
661 // Check for $_SERVER configuration
662 $this->requireServerVariables(array('SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'), array(
663 ts("Webserver config"),
664 ts("Recognised webserver"),
665 ts("You seem to be using an unsupported webserver. The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set."),
668 // Check for MySQL support
669 $this->requireFunction('mysql_connect', array(
670 ts("PHP Configuration"),
672 ts("MySQL support not included in PHP."),
675 // Check for JSON support
676 $this->requireFunction('json_encode', array(
677 ts("PHP Configuration"),
679 ts("JSON support not included in PHP."),
682 // Check for xcache_isset and emit warning if exists
683 $this->checkXCache(array(
684 ts("PHP Configuration"),
685 ts("XCache compatibility"),
686 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."),
689 // Check memory allocation
690 $this->requireMemory(32 * 1024 * 1024,
693 ts("PHP Configuration"),
694 ts("Memory allocated (PHP config option 'memory_limit')"),
695 ts("CiviCRM needs a minimum of %1 MB allocated to PHP, but recommends %2 MB.", array(1 => 32, 2 => 64)),
696 ini_get("memory_limit"),
700 return $this->errors
;
705 * @param $recommended
706 * @param $testDetails
708 public function requireMemory($min, $recommended, $testDetails) {
709 $this->testing($testDetails);
710 $mem = $this->getPHPMemory();
712 if ($mem < $min && $mem > 0) {
713 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
714 $this->error($testDetails);
716 elseif ($mem < $recommended && $mem > 0) {
717 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
718 $this->warning($testDetails);
721 $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));
722 $this->warning($testDetails);
729 public function getPHPMemory() {
730 $memString = ini_get("memory_limit");
732 switch (strtolower(substr($memString, -1))) {
734 return round(substr($memString, 0, -1) * 1024);
737 return round(substr($memString, 0, -1) * 1024 * 1024);
740 return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
743 return round($memString);
747 public function listErrors() {
749 echo "<p>" . ts("The following problems are preventing me from installing CiviCRM:") . "</p>";
750 foreach ($this->errors
as $error) {
751 echo "<li>" . htmlentities($error) . "</li>";
757 * @param null $section
759 public function showTable($section = NULL) {
761 $tests = $this->tests
[$section];
762 echo "<table class=\"testResults\" width=\"100%\">";
763 foreach ($tests as $test => $result) {
764 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
769 foreach ($this->tests
as $section => $tests) {
770 echo "<h3>$section</h3>";
771 echo "<table class=\"testResults\" width=\"100%\">";
773 foreach ($tests as $test => $result) {
774 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
782 * @param string $funcName
783 * @param $testDetails
787 public function requireFunction($funcName, $testDetails) {
788 $this->testing($testDetails);
790 if (!function_exists($funcName)) {
791 $this->error($testDetails);
800 * @param $testDetails
802 public function checkXCache($testDetails) {
803 if (function_exists('xcache_isset') &&
804 ini_get('xcache.size') > 0
806 $this->testing($testDetails);
807 $this->warning($testDetails);
813 * @param $testDetails
814 * @param null $maxVersion
816 public function requirePHPVersion($minVersion, $testDetails, $maxVersion = NULL) {
818 $this->testing($testDetails);
820 $phpVersion = phpversion();
821 $aboveMinVersion = version_compare($phpVersion, $minVersion) >= 0;
822 $belowMaxVersion = $maxVersion ?
version_compare($phpVersion, $maxVersion) < 0 : TRUE;
824 if ($aboveMinVersion && $belowMaxVersion) {
825 if (version_compare(phpversion(), CRM_Upgrade_Incremental_General
::MIN_RECOMMENDED_PHP_VER
) < 0) {
826 $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(
828 2 => CRM_Upgrade_Incremental_General
::MIN_RECOMMENDED_PHP_VER
,
830 $this->warning($testDetails);
835 if (!$testDetails[2]) {
836 if (!$aboveMinVersion) {
837 $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));
840 $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));
844 $this->error($testDetails);
848 * @param string $filename
849 * @param $testDetails
850 * @param bool $absolute
852 public function requireFile($filename, $testDetails, $absolute = FALSE) {
853 $this->testing($testDetails);
855 $filename = $this->getBaseDir() . $filename;
857 if (!file_exists($filename)) {
858 $testDetails[2] .= " (" . ts("file '%1' not found", array(1 => $filename)) . ')';
859 $this->error($testDetails);
864 * @param $testDetails
866 public function requireNoPathSeparator($testDetails) {
867 $this->testing($testDetails);
868 if (substr_count($this->getBaseDir(), PATH_SEPARATOR
)) {
869 $this->error($testDetails);
874 * @param string $filename
875 * @param $testDetails
877 public function requireNoFile($filename, $testDetails) {
878 $this->testing($testDetails);
879 $filename = $this->getBaseDir() . $filename;
880 if (file_exists($filename)) {
881 $testDetails[2] .= " (" . ts("file '%1' found", array(1 => $filename)) . ")";
882 $this->error($testDetails);
887 * @param string $filename
888 * @param $testDetails
890 public function moveFileOutOfTheWay($filename, $testDetails) {
891 $this->testing($testDetails);
892 $filename = $this->getBaseDir() . $filename;
893 if (file_exists($filename)) {
894 if (file_exists("$filename.bak")) {
897 rename($filename, "$filename.bak");
902 * @param string $filename
903 * @param $testDetails
904 * @param bool $absolute
906 public function requireWriteable($filename, $testDetails, $absolute = FALSE) {
907 $this->testing($testDetails);
909 $filename = $this->getBaseDir() . $filename;
912 if (!is_writable($filename)) {
914 if (function_exists('posix_getpwuid')) {
915 $user = posix_getpwuid(posix_geteuid());
916 $name = '- ' . $user['name'] . ' -';
919 if (!isset($testDetails[2])) {
920 $testDetails[2] = NULL;
922 $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";
923 $this->error($testDetails);
928 * @param string $moduleName
929 * @param $testDetails
931 public function requireApacheModule($moduleName, $testDetails) {
932 $this->testing($testDetails);
933 if (!in_array($moduleName, apache_get_modules())) {
934 $this->error($testDetails);
940 * @param string $username
942 * @param $testDetails
944 public function requireMysqlConnection($server, $username, $password, $testDetails) {
945 $this->testing($testDetails);
946 $conn = @mysql_connect
($server, $username, $password);
952 $testDetails[2] .= ": " . mysql_error();
953 $this->error($testDetails);
959 * @param $testDetails
961 public function requireMySQLServer($server, $testDetails) {
962 $this->testing($testDetails);
963 $conn = @mysql_connect
($server, NULL, NULL);
965 if ($conn ||
mysql_errno() < 2000) {
969 $testDetails[2] .= ": " . mysql_error();
970 $this->error($testDetails);
976 * @param $testDetails
978 public function requireMySQLVersion($version, $testDetails) {
979 $this->testing($testDetails);
981 if (!mysql_get_server_info()) {
982 $testDetails[2] = ts('Cannot determine the version of MySQL installed. Please ensure at least version %1 is installed.', array(1 => $version));
983 $this->warning($testDetails);
986 list($majorRequested, $minorRequested) = explode('.', $version);
987 list($majorHas, $minorHas) = explode('.', mysql_get_server_info());
989 if (($majorHas > $majorRequested) ||
($majorHas == $majorRequested && $minorHas >= $minorRequested)) {
993 $testDetails[2] .= "{$majorHas}.{$minorHas}.";
994 $this->error($testDetails);
1001 * @param string $username
1004 * @param $testDetails
1006 public function requireMySQLInnoDB($server, $username, $password, $database, $testDetails) {
1007 $this->testing($testDetails);
1008 $conn = @mysql_connect
($server, $username, $password);
1010 $testDetails[2] .= ' ' . ts("Could not determine if MySQL has InnoDB support. Assuming no.");
1011 $this->error($testDetails);
1015 $innodb_support = FALSE;
1016 $result = mysql_query("SHOW ENGINES", $conn);
1017 while ($values = mysql_fetch_array($result)) {
1018 if ($values['Engine'] == 'InnoDB') {
1019 if (strtolower($values['Support']) == 'yes' ||
1020 strtolower($values['Support']) == 'default'
1022 $innodb_support = TRUE;
1026 if ($innodb_support) {
1027 $testDetails[3] = ts('MySQL server does have InnoDB support');
1030 $testDetails[2] .= ' ' . ts('Could not determine if MySQL has InnoDB support. Assuming no');
1036 * @param string $username
1039 * @param $testDetails
1041 public function requireMySQLTempTables($server, $username, $password, $database, $testDetails) {
1042 $this->testing($testDetails);
1043 $conn = @mysql_connect
($server, $username, $password);
1045 $testDetails[2] = ts('Could not login to the database.');
1046 $this->error($testDetails);
1050 if (!@mysql_select_db
($database, $conn)) {
1051 $testDetails[2] = ts('Could not select the database.');
1052 $this->error($testDetails);
1056 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
1058 $testDetails[2] = ts('Could not create a temp table.');
1059 $this->error($testDetails);
1061 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1066 * @param string $username
1069 * @param $testDetails
1071 public function requireMySQLTrigger($server, $username, $password, $database, $testDetails) {
1072 $this->testing($testDetails);
1073 $conn = @mysql_connect
($server, $username, $password);
1075 $testDetails[2] = ts('Could not login to the database.');
1076 $this->error($testDetails);
1080 if (!@mysql_select_db
($database, $conn)) {
1081 $testDetails[2] = ts('Could not select the database.');
1082 $this->error($testDetails);
1086 $result = mysql_query('CREATE TABLE civicrm_install_temp_table_test (test text)', $conn);
1088 $testDetails[2] = ts('Could not create a table in the database.');
1089 $this->error($testDetails);
1092 $result = mysql_query('CREATE TRIGGER civicrm_install_temp_table_test_trigger BEFORE INSERT ON civicrm_install_temp_table_test FOR EACH ROW BEGIN END');
1094 mysql_query('DROP TABLE civicrm_install_temp_table_test');
1095 $testDetails[2] = ts('Could not create a database trigger.');
1096 $this->error($testDetails);
1099 mysql_query('DROP TRIGGER civicrm_install_temp_table_test_trigger');
1100 mysql_query('DROP TABLE civicrm_install_temp_table_test');
1106 * @param string $username
1109 * @param $testDetails
1111 public function requireMySQLLockTables($server, $username, $password, $database, $testDetails) {
1112 $this->testing($testDetails);
1113 $conn = @mysql_connect
($server, $username, $password);
1115 $testDetails[2] = ts('Could not connect to the database server.');
1116 $this->error($testDetails);
1120 if (!@mysql_select_db
($database, $conn)) {
1121 $testDetails[2] = ts('Could not select the database.');
1122 $this->error($testDetails);
1126 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
1128 $testDetails[2] = ts('Could not create a table in the database.');
1129 $this->error($testDetails);
1133 $result = mysql_query('LOCK TABLES civicrm_install_temp_table_test WRITE', $conn);
1135 $testDetails[2] = ts('Could not obtain a write lock for the database table.');
1136 $this->error($testDetails);
1137 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1141 $result = mysql_query('UNLOCK TABLES', $conn);
1143 $testDetails[2] = ts('Could not release the lock for the database table.');
1144 $this->error($testDetails);
1145 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1149 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1154 * @param string $username
1156 * @param $testDetails
1158 public function requireMySQLAutoIncrementIncrementOne($server, $username, $password, $testDetails) {
1159 $this->testing($testDetails);
1160 $conn = @mysql_connect
($server, $username, $password);
1162 $testDetails[2] = ts('Could not connect to the database server.');
1163 $this->error($testDetails);
1167 $result = mysql_query("SHOW variables like 'auto_increment_increment'", $conn);
1169 $testDetails[2] = ts('Could not query database server variables.');
1170 $this->error($testDetails);
1174 $values = mysql_fetch_row($result);
1175 if ($values[1] == 1) {
1176 $testDetails[3] = ts('MySQL server auto_increment_increment is 1');
1179 $this->error($testDetails);
1186 * @param string $username
1189 * @param $minValueKB
1190 * @param $testDetails
1192 public function requireMySQLThreadStack($server, $username, $password, $database, $minValueKB, $testDetails) {
1193 $this->testing($testDetails);
1194 $conn = @mysql_connect
($server, $username, $password);
1196 $testDetails[2] = ts('Could not connect to the database server.');
1197 $this->error($testDetails);
1201 if (!@mysql_select_db
($database, $conn)) {
1202 $testDetails[2] = ts('Could not select the database.');
1203 $this->error($testDetails);
1207 $result = mysql_query("SHOW VARIABLES LIKE 'thread_stack'", $conn); // bytes => kb
1209 $testDetails[2] = ts('Could not get information about the thread_stack of the database.');
1210 $this->error($testDetails);
1213 $values = mysql_fetch_row($result);
1214 if ($values[1] < (1024 * $minValueKB)) {
1215 $testDetails[2] = ts('MySQL "thread_stack" is %1 kb', array(1 => ($values[1] / 1024)));
1216 $this->error($testDetails);
1223 * @param string $username
1226 * @param $testDetails
1227 * @param bool $onlyRequire
1229 public function requireDatabaseOrCreatePermissions(
1235 $onlyRequire = FALSE
1237 $this->testing($testDetails);
1238 $conn = @mysql_connect
($server, $username, $password);
1241 if (@mysql_select_db
($database)) {
1242 $okay = "Database '$database' exists";
1244 elseif ($onlyRequire) {
1245 $testDetails[2] = ts("The database: '%1' does not exist.", array(1 => $database));
1246 $this->error($testDetails);
1250 $query = sprintf("CREATE DATABASE %s", mysql_real_escape_string($database));
1251 if (@mysql_query
($query)) {
1252 $okay = ts("Able to create a new database.");
1255 $testDetails[2] .= " (" . ts("user '%1' doesn't have CREATE DATABASE permissions.", array(1 => $username)) . ")";
1256 $this->error($testDetails);
1262 $testDetails[3] = $okay;
1263 $this->testing($testDetails);
1269 * @param $errorMessage
1271 public function requireServerVariables($varNames, $errorMessage) {
1272 //$this->testing($testDetails);
1273 foreach ($varNames as $varName) {
1274 if (!$_SERVER[$varName]) {
1275 $missing[] = '$_SERVER[' . $varName . ']';
1278 if (!isset($missing)) {
1282 $testDetails[2] = " (" . ts('the following PHP variables are missing: %1', array(1 => implode(", ", $missing))) . ")";
1283 $this->error($testDetails);
1288 * @param $testDetails
1292 public function isRunningApache($testDetails) {
1293 $this->testing($testDetails);
1294 if (function_exists('apache_get_modules') ||
stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) {
1298 $this->warning($testDetails);
1305 public function getBaseDir() {
1306 return dirname($_SERVER['SCRIPT_FILENAME']) . CIVICRM_DIRECTORY_SEPARATOR
;
1310 * @param $testDetails
1312 public function testing($testDetails) {
1313 if (!$testDetails) {
1317 $section = $testDetails[0];
1318 $test = $testDetails[1];
1320 $message = ts("OK");
1321 if (isset($testDetails[3])) {
1322 $message .= " ($testDetails[3])";
1325 $this->tests
[$section][$test] = array("good", $message);
1329 * @param $testDetails
1331 public function error($testDetails) {
1332 $section = $testDetails[0];
1333 $test = $testDetails[1];
1335 $this->tests
[$section][$test] = array("error", $testDetails[2]);
1336 $this->errors
[] = $testDetails;
1340 * @param $testDetails
1342 public function warning($testDetails) {
1343 $section = $testDetails[0];
1344 $test = $testDetails[1];
1346 $this->tests
[$section][$test] = array("warning", $testDetails[2]);
1347 $this->warnings
[] = $testDetails;
1353 public function hasErrors() {
1354 return count($this->errors
);
1360 public function hasWarnings() {
1361 return count($this->warnings
);
1369 class Installer
extends InstallRequirements
{
1376 public function createDatabaseIfNotExists($server, $username, $password, $database) {
1377 $conn = @mysql_connect
($server, $username, $password);
1379 if (@mysql_select_db
($database)) {
1380 // skip if database already present
1383 $query = sprintf("CREATE DATABASE %s", mysql_real_escape_string($database));
1384 if (@mysql_query
($query)) {
1387 $errorTitle = ts("Oops! Could not create database %1", array(1 => $database));
1388 $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.");
1389 errorDisplayPage($errorTitle, $errorMsg);
1398 public function install($config) {
1399 global $installDirPath;
1401 // create database if does not exists
1402 $this->createDatabaseIfNotExists($config['mysql']['server'],
1403 $config['mysql']['username'],
1404 $config['mysql']['password'],
1405 $config['mysql']['database']
1408 global $installDirPath;
1411 require_once $installDirPath . 'civicrm.php';
1412 civicrm_main($config);
1414 if (!$this->errors
) {
1415 global $installType, $installURLPath;
1417 $registerSiteURL = "https://civicrm.org/register-site";
1418 $commonOutputMessage
1419 = "<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>"
1420 . "<li>" . ts("We have integrated KCFinder with CKEditor and TinyMCE. This allows a user to upload images. All uploaded images are public.") . "</li>";
1425 $installType == 'drupal' &&
1426 version_compare(VERSION
, '7.0-rc1') >= 0
1432 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1433 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1434 $output .= '<head>';
1435 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1436 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1437 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1438 $output .= '</head>';
1439 $output .= '<body>';
1440 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1443 $drupalURL = civicrm_cms_base();
1444 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/people/permissions";
1445 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1447 $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>";
1448 $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>";
1449 $output .= $commonOutputMessage;
1451 // automatically enable CiviCRM module once it is installed successfully.
1452 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1453 global $cmsPath, $crmPath;
1455 // relative / abosolute paths are not working for drupal, hence using chdir()
1458 // Force the re-initialisation of the config singleton on the next call
1459 // since so far, we had used the Config object without loading the DB.
1460 $c = CRM_Core_Config
::singleton(FALSE);
1463 include_once "./includes/bootstrap.inc";
1464 include_once "./includes/unicode.inc";
1466 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1468 // prevent session information from being saved.
1469 drupal_save_session(FALSE);
1471 // Force the current user to anonymous.
1472 $original_user = $GLOBALS['user'];
1473 $GLOBALS['user'] = drupal_anonymous_user();
1475 // explicitly setting error reporting, since we cannot handle drupal related notices
1478 // rebuild modules, so that civicrm is added
1479 system_rebuild_module_data();
1481 // now enable civicrm module.
1482 module_enable(array('civicrm', 'civicrmtheme'));
1484 // clear block, page, theme, and hook caches
1485 drupal_flush_all_caches();
1487 //add basic drupal permissions
1488 civicrm_install_set_drupal_perms();
1490 // restore the user.
1491 $GLOBALS['user'] = $original_user;
1492 drupal_save_session(TRUE);
1494 //change the default language to one chosen
1495 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1496 civicrm_api3('Setting', 'create', array(
1497 'domain_id' => 'current_domain',
1498 'lcMessages' => $config['seedLanguage'],
1504 $output .= '</div>';
1505 $output .= '</body>';
1506 $output .= '</html>';
1510 $installType == 'backdrop'
1516 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1517 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1518 $output .= '<head>';
1519 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1520 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1521 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1522 $output .= '</head>';
1523 $output .= '<body>';
1524 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1527 $backdropURL = civicrm_cms_base();
1528 $backdropPermissionsURL = "{$backdropURL}index.php?q=admin/config/people/permissions";
1529 $backdropURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1531 $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>";
1532 $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>";
1533 $output .= $commonOutputMessage;
1535 // automatically enable CiviCRM module once it is installed successfully.
1536 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1537 global $cmsPath, $crmPath;
1539 // relative / abosolute paths are not working for drupal, hence using chdir()
1542 // Force the re-initialisation of the config singleton on the next call
1543 // since so far, we had used the Config object without loading the DB.
1544 $c = CRM_Core_Config
::singleton(FALSE);
1547 include_once "./core/includes/bootstrap.inc";
1548 include_once "./core/includes/unicode.inc";
1550 backdrop_bootstrap(BACKDROP_BOOTSTRAP_FULL
);
1552 // prevent session information from being saved.
1553 backdrop_save_session(FALSE);
1555 // Force the current user to anonymous.
1556 $original_user = $GLOBALS['user'];
1557 $GLOBALS['user'] = backdrop_anonymous_user();
1559 // explicitly setting error reporting, since we cannot handle drupal related notices
1562 // rebuild modules, so that civicrm is added
1563 system_rebuild_module_data();
1565 // now enable civicrm module.
1566 module_enable(array('civicrm', 'civicrmtheme'));
1568 // clear block, page, theme, and hook caches
1569 backdrop_flush_all_caches();
1571 //add basic backdrop permissions
1572 civicrm_install_set_backdrop_perms();
1574 // restore the user.
1575 $GLOBALS['user'] = $original_user;
1576 backdrop_save_session(TRUE);
1578 //change the default language to one chosen
1579 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1580 civicrm_api3('Setting', 'create', array(
1581 'domain_id' => 'current_domain',
1582 'lcMessages' => $config['seedLanguage'],
1588 $output .= '</div>';
1589 $output .= '</body>';
1590 $output .= '</html>';
1593 elseif ($installType == 'drupal' && version_compare(VERSION
, '6.0') >= 0) {
1597 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1598 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1599 $output .= '<head>';
1600 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1601 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1602 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1603 $output .= '</head>';
1604 $output .= '<body>';
1605 $output .= '<div style="padding: 1em;"><p class="good">' . ts("CiviCRM has been successfully installed") . '</p>';
1608 $drupalURL = civicrm_cms_base();
1609 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/user/permissions";
1610 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1612 $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>";
1613 $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>";
1614 $output .= $commonOutputMessage;
1616 // explicitly setting error reporting, since we cannot handle drupal related notices
1619 // automatically enable CiviCRM module once it is installed successfully.
1620 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1621 global $cmsPath, $crmPath;
1623 // relative / abosolute paths are not working for drupal, hence using chdir()
1626 // Force the re-initialisation of the config singleton on the next call
1627 // since so far, we had used the Config object without loading the DB.
1628 $c = CRM_Core_Config
::singleton(FALSE);
1631 include_once "./includes/bootstrap.inc";
1632 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL
);
1634 // rebuild modules, so that civicrm is added
1635 module_rebuild_cache();
1637 // now enable civicrm module.
1638 module_enable(array('civicrm'));
1640 // clear block, page, theme, and hook caches
1641 drupal_flush_all_caches();
1643 //add basic drupal permissions
1644 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)');
1648 elseif ($installType == 'wordpress') {
1649 echo '<h1>' . ts('CiviCRM Installed') . '</h1>';
1650 echo '<div style="padding: 1em;"><p style="background-color: #0C0; border: 1px #070 solid; color: white;">' . ts("CiviCRM has been successfully installed") . '</p>';
1653 $cmsURL = civicrm_cms_base();
1654 $cmsURL .= "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/configtask&reset=1";
1655 $wpPermissionsURL = "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/access/wp-permissions&reset=1";
1657 $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>";
1658 $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>";
1659 $output .= $commonOutputMessage;
1664 $c = CRM_Core_Config
::singleton(FALSE);
1666 $wpInstallRedirect = admin_url("?page=CiviCRM&q=civicrm&reset=1");
1668 window.location = '$wpInstallRedirect';
1673 return $this->errors
;
1678 function civicrm_install_set_drupal_perms() {
1679 if (!function_exists('db_select')) {
1680 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)');
1684 'access all custom data',
1685 'access uploaded files',
1686 'make online contributions',
1690 'register for events',
1692 'view event participants',
1693 'access CiviMail subscribe/unsubscribe pages',
1696 // Adding a permission that has not yet been assigned to a module by
1697 // a hook_permission implementation results in a database error.
1699 $allPerms = array_keys(module_invoke_all('permission'));
1700 foreach (array_diff($perms, $allPerms) as $perm) {
1702 'Cannot grant the %perm permission because it does not yet exist.',
1703 array('%perm' => $perm),
1707 $perms = array_intersect($perms, $allPerms);
1708 user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID
, $perms);
1709 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID
, $perms);
1713 function civicrm_install_set_backdrop_perms() {
1715 'access all custom data',
1716 'access uploaded files',
1717 'make online contributions',
1721 'register for events',
1723 'view event participants',
1724 'access CiviMail subscribe/unsubscribe pages',
1727 // Adding a permission that has not yet been assigned to a module by
1728 // a hook_permission implementation results in a database error.
1730 $allPerms = array_keys(module_invoke_all('permission'));
1731 foreach (array_diff($perms, $allPerms) as $perm) {
1733 'Cannot grant the %perm permission because it does not yet exist.',
1734 array('%perm' => $perm),
1738 $perms = array_intersect($perms, $allPerms);
1739 user_role_grant_permissions(BACKDROP_AUTHENTICATED_ROLE
, $perms);
1740 user_role_grant_permissions(BACKDROP_ANONYMOUS_ROLE
, $perms);
1749 function getSiteDir($cmsPath, $str) {
1750 static $siteDir = '';
1756 $sites = CIVICRM_DIRECTORY_SEPARATOR
. 'sites' . CIVICRM_DIRECTORY_SEPARATOR
;
1757 $modules = CIVICRM_DIRECTORY_SEPARATOR
. 'modules' . CIVICRM_DIRECTORY_SEPARATOR
;
1758 preg_match("/" . preg_quote($sites, CIVICRM_DIRECTORY_SEPARATOR
) .
1759 "([\-a-zA-Z0-9_.]+)" .
1760 preg_quote($modules, CIVICRM_DIRECTORY_SEPARATOR
) . "/",
1761 $_SERVER['SCRIPT_FILENAME'], $matches
1763 $siteDir = isset($matches[1]) ?
$matches[1] : 'default';
1765 if (strtolower($siteDir) == 'all') {
1766 // For this case - use drupal's way of finding out multi-site directory
1767 $uri = explode(CIVICRM_DIRECTORY_SEPARATOR
, $_SERVER['SCRIPT_FILENAME']);
1768 $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
1769 for ($i = count($uri) - 1; $i > 0; $i--) {
1770 for ($j = count($server); $j > 0; $j--) {
1771 $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
1772 if (file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR
.
1773 'sites' . CIVICRM_DIRECTORY_SEPARATOR
. $dir
1780 $siteDir = 'default';
1787 * @param $errorTitle
1791 function errorDisplayPage($errorTitle, $errorMsg, $showRefer = TRUE) {
1793 $docLink = CRM_Utils_System
::docURL2('Installation and Upgrades', FALSE, 'Installation Guide', NULL, NULL, "wiki");
1795 if (function_exists('ts')) {
1796 $errorMsg .= '<p>' . ts("<a %1>Refer to the online documentation for more information</a>", array(1 => "href='$docLink'")) . '</p>';
1799 $errorMsg .= '<p>' . sprintf("<a %s>Refer to the online documentation for more information</a>", "href='$docLink'") . '</p>';
1803 include 'error.html';