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