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