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