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