commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / install / index.php
1 <?php
2
3 /**
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/. Please check
7 * http://www.silverstripe.com/licensing for licensing details.
8 *
9 * Copyright (c) 2006-7, SilverStripe Limited - www.silverstripe.com
10 * All rights reserved.
11 *
12 * Changes and modifications (c) 2007-2015 by CiviCRM LLC
13 *
14 */
15
16 /**
17 * CiviCRM Installer
18 */
19
20 ini_set('max_execution_time', 3000);
21
22 if (stristr(PHP_OS, 'WIN')) {
23 define('CIVICRM_DIRECTORY_SEPARATOR', '/');
24 define('CIVICRM_WINDOWS', 1);
25 }
26 else {
27 define('CIVICRM_DIRECTORY_SEPARATOR', DIRECTORY_SEPARATOR);
28 define('CIVICRM_WINDOWS', 0);
29 }
30
31 // set installation type - drupal
32 if (!session_id()) {
33 session_start();
34 }
35
36 // unset civicrm session if any
37 if (array_key_exists('CiviCRM', $_SESSION)) {
38 unset($_SESSION['CiviCRM']);
39 }
40
41 if (isset($_GET['civicrm_install_type'])) {
42 $_SESSION['civicrm_install_type'] = $_GET['civicrm_install_type'];
43 }
44 else {
45 if (!isset($_SESSION['civicrm_install_type'])) {
46 $_SESSION['civicrm_install_type'] = "drupal";
47 }
48 }
49
50 global $installType;
51 global $crmPath;
52 global $pkgPath;
53 global $installDirPath;
54 global $installURLPath;
55
56 $installType = strtolower($_SESSION['civicrm_install_type']);
57
58 if ($installType == 'drupal') {
59 $crmPath = dirname(dirname($_SERVER['SCRIPT_FILENAME']));
60 $installDirPath = $installURLPath = '';
61 }
62 elseif ($installType == 'wordpress') {
63 $crmPath = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR;
64 $installDirPath = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR;
65 $installURLPath = WP_PLUGIN_URL . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR;
66 }
67 else {
68 $errorTitle = "Oops! Unsupported installation mode";
69 $errorMsg = sprintf('%s: unknown installation mode. Please refer to the online documentation for more information.', $installType);
70 errorDisplayPage($errorTitle, $errorMsg, FALSE);
71 }
72
73 $pkgPath = $crmPath . DIRECTORY_SEPARATOR . 'packages';
74
75 require_once $crmPath . '/CRM/Core/ClassLoader.php';
76 CRM_Core_ClassLoader::singleton()->register();
77
78 // Load civicrm database config
79 if (isset($_POST['mysql'])) {
80 $databaseConfig = $_POST['mysql'];
81 }
82 else {
83 $databaseConfig = array(
84 "server" => "localhost",
85 "username" => "civicrm",
86 "password" => "",
87 "database" => "civicrm",
88 );
89 }
90
91 if ($installType == 'drupal') {
92 // Load drupal database config
93 if (isset($_POST['drupal'])) {
94 $drupalConfig = $_POST['drupal'];
95 }
96 else {
97 $drupalConfig = array(
98 "server" => "localhost",
99 "username" => "drupal",
100 "password" => "",
101 "database" => "drupal",
102 );
103 }
104 }
105
106 $loadGenerated = 0;
107 if (isset($_POST['loadGenerated'])) {
108 $loadGenerated = 1;
109 }
110
111 require_once dirname(__FILE__) . CIVICRM_DIRECTORY_SEPARATOR . 'langs.php';
112 foreach ($langs as $locale => $_) {
113 if ($locale == 'en_US') {
114 continue;
115 }
116 if (!file_exists(implode(CIVICRM_DIRECTORY_SEPARATOR, array($crmPath, 'sql', "civicrm_data.$locale.mysql")))) {
117 unset($langs[$locale]);
118 }
119 }
120
121 // Set the locale (required by CRM_Core_Config)
122 // This is mostly sympbolic, since nothing we do during the install
123 // really requires CIVICRM_UF to be defined.
124 $installTypeToUF = array(
125 'wordpress' => 'WordPress',
126 'drupal' => 'Drupal',
127 );
128
129 $uf = (isset($installTypeToUF[$installType]) ? $installTypeToUF[$installType] : 'Drupal');
130 define('CIVICRM_UF', $uf);
131
132 global $tsLocale;
133
134 $tsLocale = 'en_US';
135 $seedLanguage = 'en_US';
136
137 // CRM-16801 This validates that seedLanguage is valid by looking in $langs.
138 // NB: the variable is initial a $_REQUEST for the initial page reload,
139 // then becomes a $_POST when the installation form is submitted.
140 if (isset($_REQUEST['seedLanguage']) and isset($langs[$_REQUEST['seedLanguage']])) {
141 $seedLanguage = $_REQUEST['seedLanguage'];
142 $tsLocale = $_REQUEST['seedLanguage'];
143 }
144
145 $config = CRM_Core_Config::singleton(FALSE);
146 $GLOBALS['civicrm_default_error_scope'] = NULL;
147
148 // The translation files are in the parent directory (l10n)
149 $config->gettextResourceDir = '..' . DIRECTORY_SEPARATOR . $config->gettextResourceDir;
150 $i18n = CRM_Core_I18n::singleton();
151
152 global $cmsPath;
153 if ($installType == 'drupal') {
154 //CRM-6840 -don't force to install in sites/all/modules/
155 $object = new CRM_Utils_System_Drupal();
156 $cmsPath = $object->cmsRootPath();
157
158 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
159 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR .
160 'sites' . CIVICRM_DIRECTORY_SEPARATOR .
161 $siteDir . CIVICRM_DIRECTORY_SEPARATOR .
162 'civicrm.settings.php'
163 );
164 }
165 elseif ($installType == 'wordpress') {
166 $cmsPath = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'civicrm';
167 $alreadyInstalled = file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR .
168 'civicrm.settings.php'
169 );
170 }
171
172 if ($installType == 'drupal') {
173 // Lets check only /modules/.
174 $pattern = '/' . preg_quote(CIVICRM_DIRECTORY_SEPARATOR . 'modules', CIVICRM_DIRECTORY_SEPARATOR) . '/';
175
176 if (!preg_match($pattern, str_replace("\\", "/", $_SERVER['SCRIPT_FILENAME']))) {
177 $directory = implode(CIVICRM_DIRECTORY_SEPARATOR, array('sites', 'all', 'modules'));
178 $errorTitle = ts("Oops! Please correct your install location");
179 $errorMsg = ts("Please untar (uncompress) your downloaded copy of CiviCRM in the <strong>%1</strong> directory below your Drupal root directory.", array(1 => $directory));
180 errorDisplayPage($errorTitle, $errorMsg);
181 }
182 }
183
184 // Exit with error if CiviCRM has already been installed.
185 if ($alreadyInstalled) {
186 $errorTitle = ts("Oops! CiviCRM is already installed");
187 $settings_directory = $cmsPath;
188
189 if ($installType == 'drupal') {
190 $settings_directory = implode(CIVICRM_DIRECTORY_SEPARATOR, array(
191 ts('[your Drupal root directory]'),
192 'sites',
193 $siteDir,
194 ));
195 }
196
197 $docLink = CRM_Utils_System::docURL2('Installation and Upgrades', FALSE, ts('Installation Guide'), NULL, NULL, "wiki");
198 $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));
199 errorDisplayPage($errorTitle, $errorMsg, FALSE);
200 }
201
202 $versionFile = $crmPath . CIVICRM_DIRECTORY_SEPARATOR . 'civicrm-version.php';
203 if (file_exists($versionFile)) {
204 require_once $versionFile;
205 $civicrm_version = civicrmVersion();
206 }
207 else {
208 $civicrm_version = 'unknown';
209 }
210
211 if ($installType == 'drupal') {
212 // Ensure that they have downloaded the correct version of CiviCRM
213 if ($civicrm_version['cms'] != 'Drupal' && $civicrm_version['cms'] != 'Drupal6') {
214 $errorTitle = ts("Oops! Incorrect CiviCRM version");
215 $errorMsg = ts("This installer can only be used for the Drupal version of CiviCRM.");
216 errorDisplayPage($errorTitle, $errorMsg);
217 }
218
219 define('DRUPAL_ROOT', $cmsPath);
220 $drupalVersionFiles = array(
221 // D6
222 implode(CIVICRM_DIRECTORY_SEPARATOR, array($cmsPath, 'modules', 'system', 'system.module')),
223 // D7
224 implode(CIVICRM_DIRECTORY_SEPARATOR, array($cmsPath, 'includes', 'bootstrap.inc')),
225 );
226 foreach ($drupalVersionFiles as $drupalVersionFile) {
227 if (file_exists($drupalVersionFile)) {
228 require_once $drupalVersionFile;
229 }
230 }
231
232 if (!defined('VERSION') or version_compare(VERSION, '6.0') < 0) {
233 $errorTitle = ts("Oops! Incorrect Drupal version");
234 $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)));
235 errorDisplayPage($errorTitle, $errorMsg);
236 }
237 }
238 elseif ($installType == 'wordpress') {
239 //HACK for now
240 $civicrm_version['cms'] = 'WordPress';
241
242 // Ensure that they have downloaded the correct version of CiviCRM
243 if ($civicrm_version['cms'] != 'WordPress') {
244 $errorTitle = ts("Oops! Incorrect CiviCRM version");
245 $errorMsg = ts("This installer can only be used for the WordPress version of CiviCRM.");
246 errorDisplayPage($errorTitle, $errorMsg);
247 }
248 }
249
250 // Check requirements
251 $req = new InstallRequirements();
252 $req->check();
253
254 if ($req->hasErrors()) {
255 $hasErrorOtherThanDatabase = TRUE;
256 }
257
258 if ($databaseConfig) {
259 $dbReq = new InstallRequirements();
260 $dbReq->checkdatabase($databaseConfig, 'CiviCRM');
261 if ($installType == 'drupal') {
262 $dbReq->checkdatabase($drupalConfig, 'Drupal');
263 }
264 }
265
266 // Actual processor
267 if (isset($_POST['go']) && !$req->hasErrors() && !$dbReq->hasErrors()) {
268 // Confirm before reinstalling
269 if (!isset($_POST['force_reinstall']) && $alreadyInstalled) {
270 include $installDirPath . 'template.html';
271 }
272 else {
273 $inst = new Installer();
274 $inst->install($_POST);
275 }
276
277 // Show the config form
278 }
279 else {
280 include $installDirPath . 'template.html';
281 }
282
283 /**
284 * This class checks requirements
285 * Each of the requireXXX functions takes an argument which gives a user description of the test. It's an array
286 * of 3 parts:
287 * $description[0] - The test category
288 * $description[1] - The test title
289 * $description[2] - The test error to show, if it goes wrong
290 */
291 class InstallRequirements {
292 var $errors, $warnings, $tests;
293
294 // @see CRM_Upgrade_Form::MINIMUM_THREAD_STACK
295 const MINIMUM_THREAD_STACK = 192;
296
297 /**
298 * Just check that the database configuration is okay.
299 * @param $databaseConfig
300 * @param $dbName
301 */
302 public function checkdatabase($databaseConfig, $dbName) {
303 if ($this->requireFunction('mysql_connect',
304 array(
305 ts("PHP Configuration"),
306 ts("MySQL support"),
307 ts("MySQL support not included in PHP."),
308 )
309 )
310 ) {
311 $this->requireMySQLServer($databaseConfig['server'],
312 array(
313 ts("MySQL %1 Configuration", array(1 => $dbName)),
314 ts("Does the server exist?"),
315 ts("Can't find the a MySQL server on '%1'.", array(1 => $databaseConfig['server'])),
316 $databaseConfig['server'],
317 )
318 );
319 if ($this->requireMysqlConnection($databaseConfig['server'],
320 $databaseConfig['username'],
321 $databaseConfig['password'],
322 array(
323 ts("MySQL %1 Configuration", array(1 => $dbName)),
324 ts("Are the access credentials correct?"),
325 ts("That username/password doesn't work"),
326 )
327 )
328 ) {
329 @$this->requireMySQLVersion("5.1",
330 array(
331 ts("MySQL %1 Configuration", array(1 => $dbName)),
332 ts("MySQL version at least %1", array(1 => '5.1')),
333 ts("MySQL version %1 or higher is required, you are running MySQL %2.", array(1 => '5.1', 2 => mysql_get_server_info())),
334 ts("MySQL %1", array(1 => mysql_get_server_info())),
335 )
336 );
337 $this->requireMySQLAutoIncrementIncrementOne($databaseConfig['server'],
338 $databaseConfig['username'],
339 $databaseConfig['password'],
340 array(
341 ts("MySQL %1 Configuration", array(1 => $dbName)),
342 ts("Is auto_increment_increment set to 1"),
343 ts("An auto_increment_increment value greater than 1 is not currently supported. Please see issue CRM-7923 for further details and potential workaround."),
344 )
345 );
346 $testDetails = array(
347 ts("MySQL %1 Configuration", array(1 => $dbName)),
348 ts("Is the provided database name valid?"),
349 ts("The database name provided is not valid. Please use only 0-9, a-z, A-Z and _ as characters in the name."),
350 );
351 if (!CRM_Core_DAO::requireValidDBName($databaseConfig['database'])) {
352 $this->error($testDetails);
353 return FALSE;
354 }
355 else {
356 $this->testing($testDetails);
357 }
358 $this->requireMySQLThreadStack($databaseConfig['server'],
359 $databaseConfig['username'],
360 $databaseConfig['password'],
361 $databaseConfig['database'],
362 self::MINIMUM_THREAD_STACK,
363 array(
364 ts("MySQL %1 Configuration", array(1 => $dbName)),
365 ts("Does MySQL thread_stack meet minimum (%1k)", array(1 => self::MINIMUM_THREAD_STACK)),
366 "",
367 // "The MySQL thread_stack does not meet minimum " . CRM_Upgrade_Form::MINIMUM_THREAD_STACK . "k. Please update thread_stack in my.cnf.",
368 )
369 );
370 }
371 $onlyRequire = ($dbName == 'Drupal') ? TRUE : FALSE;
372 $this->requireDatabaseOrCreatePermissions(
373 $databaseConfig['server'],
374 $databaseConfig['username'],
375 $databaseConfig['password'],
376 $databaseConfig['database'],
377 array(
378 ts("MySQL %1 Configuration", array(1 => $dbName)),
379 ts("Can I access/create the database?"),
380 ts("I can't create new databases and the database '%1' doesn't exist.", array(1 => $databaseConfig['database'])),
381 ),
382 $onlyRequire
383 );
384 if ($dbName != 'Drupal') {
385 $this->requireMySQLInnoDB($databaseConfig['server'],
386 $databaseConfig['username'],
387 $databaseConfig['password'],
388 $databaseConfig['database'],
389 array(
390 ts("MySQL %1 Configuration", array(1 => $dbName)),
391 ts("Can I access/create InnoDB tables in the database?"),
392 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."),
393 )
394 );
395 $this->requireMySQLTempTables($databaseConfig['server'],
396 $databaseConfig['username'],
397 $databaseConfig['password'],
398 $databaseConfig['database'],
399 array(
400 ts("MySQL %1 Configuration", array(1 => $dbName)),
401 ts('Can I create temporary tables in the database?'),
402 ts('Unable to create temporary tables. This MySQL user is missing the CREATE TEMPORARY TABLES privilege.'),
403 )
404 );
405 $this->requireMySQLLockTables($databaseConfig['server'],
406 $databaseConfig['username'],
407 $databaseConfig['password'],
408 $databaseConfig['database'],
409 array(
410 ts("MySQL %1 Configuration", array(1 => $dbName)),
411 ts('Can I create lock tables in the database?'),
412 ts('Unable to lock tables. This MySQL user is missing the LOCK TABLES privilege.'),
413 )
414 );
415 $this->requireMySQLTrigger($databaseConfig['server'],
416 $databaseConfig['username'],
417 $databaseConfig['password'],
418 $databaseConfig['database'],
419 array(
420 ts("MySQL %1 Configuration", array(1 => $dbName)),
421 ts('Can I create triggers in the database?'),
422 ts('Unable to create triggers. This MySQL user is missing the CREATE TRIGGERS privilege.'),
423 )
424 );
425 }
426 }
427 }
428
429 /**
430 * Check everything except the database.
431 */
432 public function check() {
433 global $crmPath, $installType;
434
435 $this->errors = NULL;
436
437 $this->requirePHPVersion('5.3.3', array(
438 ts("PHP Configuration"),
439 ts("PHP5 installed"),
440 NULL,
441 ts("PHP version %1", array(1 => phpversion())),
442 ));
443
444 // Check that we can identify the root folder successfully
445 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR . 'README.txt',
446 array(
447 ts("File permissions"),
448 ts("Does the webserver know where files are stored?"),
449 ts("The webserver isn't letting me identify where files are stored."),
450 $this->getBaseDir(),
451 ),
452 TRUE
453 );
454
455 // CRM-6485: make sure the path does not contain PATH_SEPARATOR, as we don’t know how to escape it
456 $this->requireNoPathSeparator(
457 array(
458 ts("File permissions"),
459 ts('Does the CiviCRM path contain PATH_SEPARATOR?'),
460 ts('The path %1 contains PATH_SEPARATOR (the %2 character).', array(1 => $this->getBaseDir(), 2 => PATH_SEPARATOR)),
461 $this->getBaseDir(),
462 )
463 );
464
465 $requiredDirectories = array('CRM', 'packages', 'templates', 'js', 'api', 'i', 'sql');
466 foreach ($requiredDirectories as $dir) {
467 $this->requireFile($crmPath . CIVICRM_DIRECTORY_SEPARATOR . $dir,
468 array(
469 ts("File permissions"),
470 ts("Folder '%1' exists?", array(1 => $dir)),
471 ts("There is no '%1' folder.", array(1 => $dir)),
472 ), TRUE
473 );
474 }
475
476 $configIDSiniDir = NULL;
477 global $cmsPath;
478 $siteDir = getSiteDir($cmsPath, $_SERVER['SCRIPT_FILENAME']);
479 if ($installType == 'drupal') {
480
481 // make sure that we can write to sites/default and files/
482 $writableDirectories = array(
483 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR .
484 'sites' . CIVICRM_DIRECTORY_SEPARATOR .
485 $siteDir . CIVICRM_DIRECTORY_SEPARATOR .
486 'files',
487 $cmsPath . CIVICRM_DIRECTORY_SEPARATOR .
488 'sites' . CIVICRM_DIRECTORY_SEPARATOR .
489 $siteDir,
490 );
491 }
492 elseif ($installType == 'wordpress') {
493 // make sure that we can write to plugins/civicrm and plugins/files/
494 $writableDirectories = array(WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'files', $cmsPath);
495 }
496
497 foreach ($writableDirectories as $dir) {
498 $dirName = CIVICRM_WINDOWS ? $dir : CIVICRM_DIRECTORY_SEPARATOR . $dir;
499 $testDetails = array(
500 ts("File permissions"),
501 ts("Is the %1 folder writeable?", array(1 => $dir)),
502 NULL,
503 );
504 $this->requireWriteable($dirName, $testDetails, TRUE);
505 }
506
507 //check for Config.IDS.ini, file may exist in re-install
508 $configIDSiniDir = array($cmsPath, 'sites', $siteDir, 'files', 'civicrm', 'upload', 'Config.IDS.ini');
509
510 if (is_array($configIDSiniDir) && !empty($configIDSiniDir)) {
511 $configIDSiniFile = implode(CIVICRM_DIRECTORY_SEPARATOR, $configIDSiniDir);
512 if (file_exists($configIDSiniFile)) {
513 unlink($configIDSiniFile);
514 }
515 }
516
517 // Check for rewriting
518 if (isset($_SERVER['SERVER_SOFTWARE'])) {
519 $webserver = strip_tags(trim($_SERVER['SERVER_SOFTWARE']));
520 }
521 elseif (isset($_SERVER['SERVER_SIGNATURE'])) {
522 $webserver = strip_tags(trim($_SERVER['SERVER_SIGNATURE']));
523 }
524
525 if ($webserver == '') {
526 $webserver = ts("I can't tell what webserver you are running");
527 }
528
529 // Check for $_SERVER configuration
530 $this->requireServerVariables(array('SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'), array(
531 ts("Webserver config"),
532 ts("Recognised webserver"),
533 ts("You seem to be using an unsupported webserver. The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set."),
534 ));
535
536 // Check for MySQL support
537 $this->requireFunction('mysql_connect', array(
538 ts("PHP Configuration"),
539 ts("MySQL support"),
540 ts("MySQL support not included in PHP."),
541 ));
542
543 // Check for JSON support
544 $this->requireFunction('json_encode', array(
545 ts("PHP Configuration"),
546 ts("JSON support"),
547 ts("JSON support not included in PHP."),
548 ));
549
550 // Check for xcache_isset and emit warning if exists
551 $this->checkXCache(array(
552 ts("PHP Configuration"),
553 ts("XCache compatibility"),
554 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."),
555 ));
556
557 // Check memory allocation
558 $this->requireMemory(32 * 1024 * 1024,
559 64 * 1024 * 1024,
560 array(
561 ts("PHP Configuration"),
562 ts("Memory allocated (PHP config option 'memory_limit')"),
563 ts("CiviCRM needs a minimum of %1 MB allocated to PHP, but recommends %2 MB.", array(1 => 32, 2 => 64)),
564 ini_get("memory_limit"),
565 )
566 );
567
568 return $this->errors;
569 }
570
571 /**
572 * @param $min
573 * @param $recommended
574 * @param $testDetails
575 */
576 public function requireMemory($min, $recommended, $testDetails) {
577 $this->testing($testDetails);
578 $mem = $this->getPHPMemory();
579
580 if ($mem < $min && $mem > 0) {
581 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
582 $this->error($testDetails);
583 }
584 elseif ($mem < $recommended && $mem > 0) {
585 $testDetails[2] .= " " . ts("You only have %1 allocated", array(1 => ini_get("memory_limit")));
586 $this->warning($testDetails);
587 }
588 elseif ($mem == 0) {
589 $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));
590 $this->warning($testDetails);
591 }
592 }
593
594 /**
595 * @return float
596 */
597 public function getPHPMemory() {
598 $memString = ini_get("memory_limit");
599
600 switch (strtolower(substr($memString, -1))) {
601 case "k":
602 return round(substr($memString, 0, -1) * 1024);
603
604 case "m":
605 return round(substr($memString, 0, -1) * 1024 * 1024);
606
607 case "g":
608 return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
609
610 default:
611 return round($memString);
612 }
613 }
614
615 public function listErrors() {
616 if ($this->errors) {
617 echo "<p>" . ts("The following problems are preventing me from installing CiviCRM:") . "</p>";
618 foreach ($this->errors as $error) {
619 echo "<li>" . htmlentities($error) . "</li>";
620 }
621 }
622 }
623
624 /**
625 * @param null $section
626 */
627 public function showTable($section = NULL) {
628 if ($section) {
629 $tests = $this->tests[$section];
630 echo "<table class=\"testResults\" width=\"100%\">";
631 foreach ($tests as $test => $result) {
632 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
633 }
634 echo "</table>";
635 }
636 else {
637 foreach ($this->tests as $section => $tests) {
638 echo "<h3>$section</h3>";
639 echo "<table class=\"testResults\" width=\"100%\">";
640
641 foreach ($tests as $test => $result) {
642 echo "<tr class=\"$result[0]\"><td>$test</td><td>" . nl2br(htmlentities($result[1])) . "</td></tr>";
643 }
644 echo "</table>";
645 }
646 }
647 }
648
649 /**
650 * @param string $funcName
651 * @param $testDetails
652 *
653 * @return bool
654 */
655 public function requireFunction($funcName, $testDetails) {
656 $this->testing($testDetails);
657
658 if (!function_exists($funcName)) {
659 $this->error($testDetails);
660 return FALSE;
661 }
662 else {
663 return TRUE;
664 }
665 }
666
667 /**
668 * @param $testDetails
669 */
670 public function checkXCache($testDetails) {
671 if (function_exists('xcache_isset') &&
672 ini_get('xcache.size') > 0
673 ) {
674 $this->testing($testDetails);
675 $this->warning($testDetails);
676 }
677 }
678
679 /**
680 * @param $minVersion
681 * @param $testDetails
682 * @param null $maxVersion
683 */
684 public function requirePHPVersion($minVersion, $testDetails, $maxVersion = NULL) {
685
686 $this->testing($testDetails);
687
688 $phpVersion = phpversion();
689 $aboveMinVersion = version_compare($phpVersion, $minVersion) >= 0;
690 $belowMaxVersion = $maxVersion ? version_compare($phpVersion, $maxVersion) < 0 : TRUE;
691
692 if ($maxVersion && $aboveMinVersion && $belowMaxVersion) {
693 return TRUE;
694 }
695 elseif (!$maxVersion && $aboveMinVersion) {
696 return TRUE;
697 }
698
699 if (!$testDetails[2]) {
700 if (!$aboveMinVersion) {
701 $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));
702 }
703 else {
704 $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));
705 }
706 }
707
708 $this->error($testDetails);
709 }
710
711 /**
712 * @param string $filename
713 * @param $testDetails
714 * @param bool $absolute
715 */
716 public function requireFile($filename, $testDetails, $absolute = FALSE) {
717 $this->testing($testDetails);
718 if (!$absolute) {
719 $filename = $this->getBaseDir() . $filename;
720 }
721 if (!file_exists($filename)) {
722 $testDetails[2] .= " (" . ts("file '%1' not found", array(1 => $filename)) . ')';
723 $this->error($testDetails);
724 }
725 }
726
727 /**
728 * @param $testDetails
729 */
730 public function requireNoPathSeparator($testDetails) {
731 $this->testing($testDetails);
732 if (substr_count($this->getBaseDir(), PATH_SEPARATOR)) {
733 $this->error($testDetails);
734 }
735 }
736
737 /**
738 * @param string $filename
739 * @param $testDetails
740 */
741 public function requireNoFile($filename, $testDetails) {
742 $this->testing($testDetails);
743 $filename = $this->getBaseDir() . $filename;
744 if (file_exists($filename)) {
745 $testDetails[2] .= " (" . ts("file '%1' found", array(1 => $filename)) . ")";
746 $this->error($testDetails);
747 }
748 }
749
750 /**
751 * @param string $filename
752 * @param $testDetails
753 */
754 public function moveFileOutOfTheWay($filename, $testDetails) {
755 $this->testing($testDetails);
756 $filename = $this->getBaseDir() . $filename;
757 if (file_exists($filename)) {
758 if (file_exists("$filename.bak")) {
759 rm("$filename.bak");
760 }
761 rename($filename, "$filename.bak");
762 }
763 }
764
765 /**
766 * @param string $filename
767 * @param $testDetails
768 * @param bool $absolute
769 */
770 public function requireWriteable($filename, $testDetails, $absolute = FALSE) {
771 $this->testing($testDetails);
772 if (!$absolute) {
773 $filename = $this->getBaseDir() . $filename;
774 }
775
776 if (!is_writable($filename)) {
777 $name = NULL;
778 if (function_exists('posix_getpwuid')) {
779 $user = posix_getpwuid(posix_geteuid());
780 $name = '- ' . $user['name'] . ' -';
781 }
782
783 if (!isset($testDetails[2])) {
784 $testDetails[2] = NULL;
785 }
786 $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";
787 $this->error($testDetails);
788 }
789 }
790
791 /**
792 * @param string $moduleName
793 * @param $testDetails
794 */
795 public function requireApacheModule($moduleName, $testDetails) {
796 $this->testing($testDetails);
797 if (!in_array($moduleName, apache_get_modules())) {
798 $this->error($testDetails);
799 }
800 }
801
802 /**
803 * @param $server
804 * @param string $username
805 * @param $password
806 * @param $testDetails
807 */
808 public function requireMysqlConnection($server, $username, $password, $testDetails) {
809 $this->testing($testDetails);
810 $conn = @mysql_connect($server, $username, $password);
811
812 if ($conn) {
813 return TRUE;
814 }
815 else {
816 $testDetails[2] .= ": " . mysql_error();
817 $this->error($testDetails);
818 }
819 }
820
821 /**
822 * @param $server
823 * @param $testDetails
824 */
825 public function requireMySQLServer($server, $testDetails) {
826 $this->testing($testDetails);
827 $conn = @mysql_connect($server, NULL, NULL);
828
829 if ($conn || mysql_errno() < 2000) {
830 return TRUE;
831 }
832 else {
833 $testDetails[2] .= ": " . mysql_error();
834 $this->error($testDetails);
835 }
836 }
837
838 /**
839 * @param $version
840 * @param $testDetails
841 */
842 public function requireMySQLVersion($version, $testDetails) {
843 $this->testing($testDetails);
844
845 if (!mysql_get_server_info()) {
846 $testDetails[2] = ts('Cannot determine the version of MySQL installed. Please ensure at least version %1 is installed.', array(1 => $version));
847 $this->warning($testDetails);
848 }
849 else {
850 list($majorRequested, $minorRequested) = explode('.', $version);
851 list($majorHas, $minorHas) = explode('.', mysql_get_server_info());
852
853 if (($majorHas > $majorRequested) || ($majorHas == $majorRequested && $minorHas >= $minorRequested)) {
854 return TRUE;
855 }
856 else {
857 $testDetails[2] .= "{$majorHas}.{$minorHas}.";
858 $this->error($testDetails);
859 }
860 }
861 }
862
863 /**
864 * @param $server
865 * @param string $username
866 * @param $password
867 * @param $database
868 * @param $testDetails
869 */
870 public function requireMySQLInnoDB($server, $username, $password, $database, $testDetails) {
871 $this->testing($testDetails);
872 $conn = @mysql_connect($server, $username, $password);
873 if (!$conn) {
874 $testDetails[2] .= ' ' . ts("Could not determine if MySQL has InnoDB support. Assuming no.");
875 $this->error($testDetails);
876 return;
877 }
878
879 $innodb_support = FALSE;
880 $result = mysql_query("SHOW ENGINES", $conn);
881 while ($values = mysql_fetch_array($result)) {
882 if ($values['Engine'] == 'InnoDB') {
883 if (strtolower($values['Support']) == 'yes' ||
884 strtolower($values['Support']) == 'default'
885 ) {
886 $innodb_support = TRUE;
887 }
888 }
889 }
890 if ($innodb_support) {
891 $testDetails[3] = ts('MySQL server does have InnoDB support');
892 }
893 else {
894 $testDetails[2] .= ' ' . ts('Could not determine if MySQL has InnoDB support. Assuming no');
895 }
896 }
897
898 /**
899 * @param $server
900 * @param string $username
901 * @param $password
902 * @param $database
903 * @param $testDetails
904 */
905 public function requireMySQLTempTables($server, $username, $password, $database, $testDetails) {
906 $this->testing($testDetails);
907 $conn = @mysql_connect($server, $username, $password);
908 if (!$conn) {
909 $testDetails[2] = ts('Could not login to the database.');
910 $this->error($testDetails);
911 return;
912 }
913
914 if (!@mysql_select_db($database, $conn)) {
915 $testDetails[2] = ts('Could not select the database.');
916 $this->error($testDetails);
917 return;
918 }
919
920 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
921 if (!$result) {
922 $testDetails[2] = ts('Could not create a temp table.');
923 $this->error($testDetails);
924 }
925 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
926 }
927
928 /**
929 * @param $server
930 * @param string $username
931 * @param $password
932 * @param $database
933 * @param $testDetails
934 */
935 public function requireMySQLTrigger($server, $username, $password, $database, $testDetails) {
936 $this->testing($testDetails);
937 $conn = @mysql_connect($server, $username, $password);
938 if (!$conn) {
939 $testDetails[2] = ts('Could not login to the database.');
940 $this->error($testDetails);
941 return;
942 }
943
944 if (!@mysql_select_db($database, $conn)) {
945 $testDetails[2] = ts('Could not select the database.');
946 $this->error($testDetails);
947 return;
948 }
949
950 $result = mysql_query('CREATE TABLE civicrm_install_temp_table_test (test text)', $conn);
951 if (!$result) {
952 $testDetails[2] = ts('Could not create a table in the database.');
953 $this->error($testDetails);
954 }
955
956 $result = mysql_query('CREATE TRIGGER civicrm_install_temp_table_test_trigger BEFORE INSERT ON civicrm_install_temp_table_test FOR EACH ROW BEGIN END');
957 if (!$result) {
958 mysql_query('DROP TABLE civicrm_install_temp_table_test');
959 $testDetails[2] = ts('Could not create a database trigger.');
960 $this->error($testDetails);
961 }
962
963 mysql_query('DROP TRIGGER civicrm_install_temp_table_test_trigger');
964 mysql_query('DROP TABLE civicrm_install_temp_table_test');
965 }
966
967
968 /**
969 * @param $server
970 * @param string $username
971 * @param $password
972 * @param $database
973 * @param $testDetails
974 */
975 public function requireMySQLLockTables($server, $username, $password, $database, $testDetails) {
976 $this->testing($testDetails);
977 $conn = @mysql_connect($server, $username, $password);
978 if (!$conn) {
979 $testDetails[2] = ts('Could not connect to the database server.');
980 $this->error($testDetails);
981 return;
982 }
983
984 if (!@mysql_select_db($database, $conn)) {
985 $testDetails[2] = ts('Could not select the database.');
986 $this->error($testDetails);
987 return;
988 }
989
990 $result = mysql_query('CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)', $conn);
991 if (!$result) {
992 $testDetails[2] = ts('Could not create a table in the database.');
993 $this->error($testDetails);
994 return;
995 }
996
997 $result = mysql_query('LOCK TABLES civicrm_install_temp_table_test WRITE', $conn);
998 if (!$result) {
999 $testDetails[2] = ts('Could not obtain a write lock for the database table.');
1000 $this->error($testDetails);
1001 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1002 return;
1003 }
1004
1005 $result = mysql_query('UNLOCK TABLES', $conn);
1006 if (!$result) {
1007 $testDetails[2] = ts('Could not release the lock for the database table.');
1008 $this->error($testDetails);
1009 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1010 return;
1011 }
1012
1013 $result = mysql_query('DROP TEMPORARY TABLE civicrm_install_temp_table_test');
1014 }
1015
1016 /**
1017 * @param $server
1018 * @param string $username
1019 * @param $password
1020 * @param $testDetails
1021 */
1022 public function requireMySQLAutoIncrementIncrementOne($server, $username, $password, $testDetails) {
1023 $this->testing($testDetails);
1024 $conn = @mysql_connect($server, $username, $password);
1025 if (!$conn) {
1026 $testDetails[2] = ts('Could not connect to the database server.');
1027 $this->error($testDetails);
1028 return;
1029 }
1030
1031 $result = mysql_query("SHOW variables like 'auto_increment_increment'", $conn);
1032 if (!$result) {
1033 $testDetails[2] = ts('Could not query database server variables.');
1034 $this->error($testDetails);
1035 return;
1036 }
1037 else {
1038 $values = mysql_fetch_row($result);
1039 if ($values[1] == 1) {
1040 $testDetails[3] = ts('MySQL server auto_increment_increment is 1');
1041 }
1042 else {
1043 $this->error($testDetails);
1044 }
1045 }
1046 }
1047
1048 /**
1049 * @param $server
1050 * @param string $username
1051 * @param $password
1052 * @param $database
1053 * @param $minValueKB
1054 * @param $testDetails
1055 */
1056 public function requireMySQLThreadStack($server, $username, $password, $database, $minValueKB, $testDetails) {
1057 $this->testing($testDetails);
1058 $conn = @mysql_connect($server, $username, $password);
1059 if (!$conn) {
1060 $testDetails[2] = ts('Could not connect to the database server.');
1061 $this->error($testDetails);
1062 return;
1063 }
1064
1065 if (!@mysql_select_db($database, $conn)) {
1066 $testDetails[2] = ts('Could not select the database.');
1067 $this->error($testDetails);
1068 return;
1069 }
1070
1071 $result = mysql_query("SHOW VARIABLES LIKE 'thread_stack'", $conn); // bytes => kb
1072 if (!$result) {
1073 $testDetails[2] = ts('Could not get information about the thread_stack of the database.');
1074 $this->error($testDetails);
1075 }
1076 else {
1077 $values = mysql_fetch_row($result);
1078 if ($values[1] < (1024 * $minValueKB)) {
1079 $testDetails[2] = ts('MySQL "thread_stack" is %1 kb', array(1 => ($values[1] / 1024)));
1080 $this->error($testDetails);
1081 }
1082 }
1083 }
1084
1085 /**
1086 * @param $server
1087 * @param string $username
1088 * @param $password
1089 * @param $database
1090 * @param $testDetails
1091 * @param bool $onlyRequire
1092 */
1093 public function requireDatabaseOrCreatePermissions(
1094 $server,
1095 $username,
1096 $password,
1097 $database,
1098 $testDetails,
1099 $onlyRequire = FALSE
1100 ) {
1101 $this->testing($testDetails);
1102 $conn = @mysql_connect($server, $username, $password);
1103
1104 $okay = NULL;
1105 if (@mysql_select_db($database)) {
1106 $okay = "Database '$database' exists";
1107 }
1108 elseif ($onlyRequire) {
1109 $testDetails[2] = ts("The database: '%1' does not exist.", array(1 => $database));
1110 $this->error($testDetails);
1111 return;
1112 }
1113 else {
1114 $query = sprintf("CREATE DATABASE %s", mysql_real_escape_string($database));
1115 if (@mysql_query($query)) {
1116 $okay = ts("Able to create a new database.");
1117 }
1118 else {
1119 $testDetails[2] .= " (" . ts("user '%1' doesn't have CREATE DATABASE permissions.", array(1 => $username)) . ")";
1120 $this->error($testDetails);
1121 return;
1122 }
1123 }
1124
1125 if ($okay) {
1126 $testDetails[3] = $okay;
1127 $this->testing($testDetails);
1128 }
1129 }
1130
1131 /**
1132 * @param $varNames
1133 * @param $errorMessage
1134 */
1135 public function requireServerVariables($varNames, $errorMessage) {
1136 //$this->testing($testDetails);
1137 foreach ($varNames as $varName) {
1138 if (!$_SERVER[$varName]) {
1139 $missing[] = '$_SERVER[' . $varName . ']';
1140 }
1141 }
1142 if (!isset($missing)) {
1143 return TRUE;
1144 }
1145 else {
1146 $testDetails[2] = " (" . ts('the following PHP variables are missing: %1', array(1 => implode(", ", $missing))) . ")";
1147 $this->error($testDetails);
1148 }
1149 }
1150
1151 /**
1152 * @param $testDetails
1153 *
1154 * @return bool
1155 */
1156 public function isRunningApache($testDetails) {
1157 $this->testing($testDetails);
1158 if (function_exists('apache_get_modules') || stristr($_SERVER['SERVER_SIGNATURE'], 'Apache')) {
1159 return TRUE;
1160 }
1161
1162 $this->warning($testDetails);
1163 return FALSE;
1164 }
1165
1166 /**
1167 * @return string
1168 */
1169 public function getBaseDir() {
1170 return dirname($_SERVER['SCRIPT_FILENAME']) . CIVICRM_DIRECTORY_SEPARATOR;
1171 }
1172
1173 /**
1174 * @param $testDetails
1175 */
1176 public function testing($testDetails) {
1177 if (!$testDetails) {
1178 return;
1179 }
1180
1181 $section = $testDetails[0];
1182 $test = $testDetails[1];
1183
1184 $message = ts("OK");
1185 if (isset($testDetails[3])) {
1186 $message .= " ($testDetails[3])";
1187 }
1188
1189 $this->tests[$section][$test] = array("good", $message);
1190 }
1191
1192 /**
1193 * @param $testDetails
1194 */
1195 public function error($testDetails) {
1196 $section = $testDetails[0];
1197 $test = $testDetails[1];
1198
1199 $this->tests[$section][$test] = array("error", $testDetails[2]);
1200 $this->errors[] = $testDetails;
1201 }
1202
1203 /**
1204 * @param $testDetails
1205 */
1206 public function warning($testDetails) {
1207 $section = $testDetails[0];
1208 $test = $testDetails[1];
1209
1210 $this->tests[$section][$test] = array("warning", $testDetails[2]);
1211 $this->warnings[] = $testDetails;
1212 }
1213
1214 /**
1215 * @return int
1216 */
1217 public function hasErrors() {
1218 return count($this->errors);
1219 }
1220
1221 /**
1222 * @return int
1223 */
1224 public function hasWarnings() {
1225 return count($this->warnings);
1226 }
1227
1228 }
1229
1230 /**
1231 * Class Installer
1232 */
1233 class Installer extends InstallRequirements {
1234 /**
1235 * @param $server
1236 * @param $username
1237 * @param $password
1238 * @param $database
1239 */
1240 public function createDatabaseIfNotExists($server, $username, $password, $database) {
1241 $conn = @mysql_connect($server, $username, $password);
1242
1243 if (@mysql_select_db($database)) {
1244 // skip if database already present
1245 return;
1246 }
1247 $query = sprintf("CREATE DATABASE %s", mysql_real_escape_string($database));
1248 if (@mysql_query($query)) {
1249 }
1250 else {
1251 $errorTitle = ts("Oops! Could not create database %1", array(1 => $database));
1252 $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.");
1253 errorDisplayPage($errorTitle, $errorMsg);
1254 }
1255 }
1256
1257 /**
1258 * @param $config
1259 *
1260 * @return mixed
1261 */
1262 public function install($config) {
1263 global $installDirPath;
1264
1265 // create database if does not exists
1266 $this->createDatabaseIfNotExists($config['mysql']['server'],
1267 $config['mysql']['username'],
1268 $config['mysql']['password'],
1269 $config['mysql']['database']
1270 );
1271
1272 global $installDirPath;
1273
1274 // Build database
1275 require_once $installDirPath . 'civicrm.php';
1276 civicrm_main($config);
1277
1278 if (!$this->errors) {
1279 global $installType, $installURLPath;
1280
1281 $registerSiteURL = "https://civicrm.org/register-site";
1282 $commonOutputMessage
1283 = "<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>"
1284 . "<li>" . ts("We have integrated KCFinder with CKEditor and TinyMCE. This allows a user to upload images. All uploaded images are public.") . "</li>";
1285
1286 $output = NULL;
1287
1288 if (
1289 $installType == 'drupal' &&
1290 version_compare(VERSION, '7.0-rc1') >= 0
1291 ) {
1292
1293 // clean output
1294 @ob_clean();
1295
1296 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1297 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1298 $output .= '<head>';
1299 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1300 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1301 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1302 $output .= '</head>';
1303 $output .= '<body>';
1304 $output .= '<div style="padding: 1em;"><p class="good">' . ts('CiviCRM has been successfully installed') . '</p>';
1305 $output .= '<ul>';
1306
1307 $drupalURL = civicrm_cms_base();
1308 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/people/permissions";
1309 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1310
1311 $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>";
1312 $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>";
1313 $output .= $commonOutputMessage;
1314
1315 // automatically enable CiviCRM module once it is installed successfully.
1316 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1317 global $cmsPath, $crmPath;
1318
1319 // relative / abosolute paths are not working for drupal, hence using chdir()
1320 chdir($cmsPath);
1321
1322 // Force the re-initialisation of the config singleton on the next call
1323 // since so far, we had used the Config object without loading the DB.
1324 $c = CRM_Core_Config::singleton(FALSE);
1325 $c->free();
1326
1327 include_once "./includes/bootstrap.inc";
1328 include_once "./includes/unicode.inc";
1329
1330 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
1331
1332 // prevent session information from being saved.
1333 drupal_save_session(FALSE);
1334
1335 // Force the current user to anonymous.
1336 $original_user = $GLOBALS['user'];
1337 $GLOBALS['user'] = drupal_anonymous_user();
1338
1339 // explicitly setting error reporting, since we cannot handle drupal related notices
1340 error_reporting(1);
1341
1342 // rebuild modules, so that civicrm is added
1343 system_rebuild_module_data();
1344
1345 // now enable civicrm module.
1346 module_enable(array('civicrm', 'civicrmtheme'));
1347
1348 // clear block, page, theme, and hook caches
1349 drupal_flush_all_caches();
1350
1351 //add basic drupal permissions
1352 civicrm_install_set_drupal_perms();
1353
1354 // restore the user.
1355 $GLOBALS['user'] = $original_user;
1356 drupal_save_session(TRUE);
1357
1358 //change the default language to one chosen
1359 if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
1360 // This ensures that defaults get set, otherwise the user will login
1361 // and most configurations will be empty, not set to en_US defaults.
1362 civicrm_api3('Setting', 'revert');
1363
1364 civicrm_api3('Setting', 'create', array(
1365 'domain_id' => 'current_domain',
1366 'lcMessages' => $config['seedLanguage'],
1367 )
1368 );
1369 }
1370
1371 $output .= '</ul>';
1372 $output .= '</div>';
1373 $output .= '</body>';
1374 $output .= '</html>';
1375 echo $output;
1376 }
1377 elseif ($installType == 'drupal' && version_compare(VERSION, '6.0') >= 0) {
1378 // clean output
1379 @ob_clean();
1380
1381 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
1382 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
1383 $output .= '<head>';
1384 $output .= '<title>' . ts('CiviCRM Installed') . '</title>';
1385 $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
1386 $output .= '<link rel="stylesheet" type="text/css" href="template.css" />';
1387 $output .= '</head>';
1388 $output .= '<body>';
1389 $output .= '<div style="padding: 1em;"><p class="good">' . ts("CiviCRM has been successfully installed") . '</p>';
1390 $output .= '<ul>';
1391
1392 $drupalURL = civicrm_cms_base();
1393 $drupalPermissionsURL = "{$drupalURL}index.php?q=admin/user/permissions";
1394 $drupalURL .= "index.php?q=civicrm/admin/configtask&reset=1";
1395
1396 $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>";
1397 $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>";
1398 $output .= $commonOutputMessage;
1399
1400 // explicitly setting error reporting, since we cannot handle drupal related notices
1401 error_reporting(1);
1402
1403 // automatically enable CiviCRM module once it is installed successfully.
1404 // so we need to Bootstrap Drupal, so that we can call drupal hooks.
1405 global $cmsPath, $crmPath;
1406
1407 // relative / abosolute paths are not working for drupal, hence using chdir()
1408 chdir($cmsPath);
1409
1410 // Force the re-initialisation of the config singleton on the next call
1411 // since so far, we had used the Config object without loading the DB.
1412 $c = CRM_Core_Config::singleton(FALSE);
1413 $c->free();
1414
1415 include_once "./includes/bootstrap.inc";
1416 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
1417
1418 // rebuild modules, so that civicrm is added
1419 module_rebuild_cache();
1420
1421 // now enable civicrm module.
1422 module_enable(array('civicrm'));
1423
1424 // clear block, page, theme, and hook caches
1425 drupal_flush_all_caches();
1426
1427 //add basic drupal permissions
1428 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)');
1429
1430 echo $output;
1431 }
1432 elseif ($installType == 'wordpress') {
1433 echo '<h1>' . ts('CiviCRM Installed') . '</h1>';
1434 echo '<div style="padding: 1em;"><p style="background-color: #0C0; border: 1px #070 solid; color: white;">' . ts("CiviCRM has been successfully installed") . '</p>';
1435 echo '<ul>';
1436
1437 $cmsURL = civicrm_cms_base();
1438 $cmsURL .= "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/configtask&reset=1";
1439 $wpPermissionsURL = "wp-admin/admin.php?page=CiviCRM&q=civicrm/admin/access/wp-permissions&reset=1";
1440
1441 $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>";
1442 $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>";
1443 $output .= $commonOutputMessage;
1444
1445 echo '</ul>';
1446 echo '</div>';
1447
1448 $c = CRM_Core_Config::singleton(FALSE);
1449 $c->free();
1450 }
1451 }
1452
1453 return $this->errors;
1454 }
1455
1456 }
1457
1458 function civicrm_install_set_drupal_perms() {
1459 if (!function_exists('db_select')) {
1460 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)');
1461 }
1462 else {
1463 $perms = array(
1464 'access all custom data',
1465 'access uploaded files',
1466 'make online contributions',
1467 'profile create',
1468 'profile edit',
1469 'profile view',
1470 'register for events',
1471 'view event info',
1472 'view event participants',
1473 'access CiviMail subscribe/unsubscribe pages',
1474 );
1475
1476 // Adding a permission that has not yet been assigned to a module by
1477 // a hook_permission implementation results in a database error.
1478 // CRM-9042
1479 $allPerms = array_keys(module_invoke_all('permission'));
1480 foreach (array_diff($perms, $allPerms) as $perm) {
1481 watchdog('civicrm',
1482 'Cannot grant the %perm permission because it does not yet exist.',
1483 array('%perm' => $perm),
1484 WATCHDOG_ERROR
1485 );
1486 }
1487 $perms = array_intersect($perms, $allPerms);
1488 user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, $perms);
1489 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, $perms);
1490 }
1491 }
1492
1493 /**
1494 * @param $cmsPath
1495 * @param $str
1496 *
1497 * @return string
1498 */
1499 function getSiteDir($cmsPath, $str) {
1500 static $siteDir = '';
1501
1502 if ($siteDir) {
1503 return $siteDir;
1504 }
1505
1506 $sites = CIVICRM_DIRECTORY_SEPARATOR . 'sites' . CIVICRM_DIRECTORY_SEPARATOR;
1507 $modules = CIVICRM_DIRECTORY_SEPARATOR . 'modules' . CIVICRM_DIRECTORY_SEPARATOR;
1508 preg_match("/" . preg_quote($sites, CIVICRM_DIRECTORY_SEPARATOR) .
1509 "([\-a-zA-Z0-9_.]+)" .
1510 preg_quote($modules, CIVICRM_DIRECTORY_SEPARATOR) . "/",
1511 $_SERVER['SCRIPT_FILENAME'], $matches
1512 );
1513 $siteDir = isset($matches[1]) ? $matches[1] : 'default';
1514
1515 if (strtolower($siteDir) == 'all') {
1516 // For this case - use drupal's way of finding out multi-site directory
1517 $uri = explode(CIVICRM_DIRECTORY_SEPARATOR, $_SERVER['SCRIPT_FILENAME']);
1518 $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
1519 for ($i = count($uri) - 1; $i > 0; $i--) {
1520 for ($j = count($server); $j > 0; $j--) {
1521 $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
1522 if (file_exists($cmsPath . CIVICRM_DIRECTORY_SEPARATOR .
1523 'sites' . CIVICRM_DIRECTORY_SEPARATOR . $dir
1524 )) {
1525 $siteDir = $dir;
1526 return $siteDir;
1527 }
1528 }
1529 }
1530 $siteDir = 'default';
1531 }
1532
1533 return $siteDir;
1534 }
1535
1536 /**
1537 * @param $errorTitle
1538 * @param $errorMsg
1539 * @param $showRefer
1540 */
1541 function errorDisplayPage($errorTitle, $errorMsg, $showRefer = TRUE) {
1542 if ($showRefer) {
1543 $docLink = CRM_Utils_System::docURL2('Installation and Upgrades', FALSE, 'Installation Guide', NULL, NULL, "wiki");
1544
1545 if (function_exists('ts')) {
1546 $errorMsg .= '<p>' . ts("<a %1>Refer to the online documentation for more information</a>", array(1 => "href='$docLink'")) . '</p>';
1547 }
1548 else {
1549 $errorMsg .= '<p>' . sprintf("<a %s>Refer to the online documentation for more information</a>", "href='$docLink'") . '</p>';
1550 }
1551 }
1552
1553 include 'error.html';
1554 exit();
1555 }