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