-
Notifications
You must be signed in to change notification settings - Fork 3
/
provision_civicrm.inc
386 lines (331 loc) · 13.3 KB
/
provision_civicrm.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
<?php
/**
* @file
* Hookup with drush
* Common functions used by install and verify.
*/
/**
* Expose the service type this extension defines to provision.
*
* @return
* An array with the service type the key, and the default implementation the value.
*/
function provision_civicrm_provision_services() {
provision_civicrm_provision_register_autoload();
return array(
'civicrm' => NULL,
'civicrm_db' => NULL,
);
}
/**
* Wrapper to initialize CiviCRM, depending on the CMS.
*
* Returns FALSE if this is not a CiviCRM site (ex: hostmaster).
*/
function provision_civicrm_initialize() {
if (drush_drupal_major_version() >= 8 && \Drupal::hasService('civicrm')) {
\Drupal::service('civicrm')->initialize();
return TRUE;
}
elseif (function_exists('civicrm_initialize')) {
civicrm_initialize();
return TRUE;
}
return FALSE;
}
/**
* Get the default CiviCRM locale.
* This is inspired from CRM_Core_Smarty::getLocale().
*/
function _provision_civicrm_get_default_locale() {
global $tsLocale;
$config = CRM_Core_Config::singleton();
if (!empty($config->lcMessages)) {
return $config->lcMessages;
}
return 'en_US';
}
/**
* Get an array of civicrm related options
*
* @param $op
* A string describing the task being run, for debugging purposes
*/
function _provision_civicrm_drush_options($op = 'unknown') {
drush_log(dt("CiviCRM: In @op: Fetching CiviCRM Drush options", array('@op' => $op)));
$civi_opts = array(
'civicrm_cron_username' => '',
'civicrm_cron_password' => '',
'civicrm_sitekey' => '',
);
foreach ($civi_opts as $opt => $val) {
$civi_opts[$opt] = drush_get_option($opt, NULL);
}
return $civi_opts;
}
/**
* Check we are in an Aegir site context, and that CiviCRM is available in the platform.
*
* @param Boolean $load_if_missing Recommended in most cases. See do#2364871.
* @see _provision_civicrm_get_package_path();
*/
function _provision_civicrm_is_site_context($load_if_missing = FALSE) {
if (d()->type == 'site') {
$crmpath = _provision_civicrm_get_package_path($load_if_missing);
return ($crmpath ? TRUE : FALSE);
}
elseif (d()->type == 'wpsite') {
// Requires hosting_wordpress in Aegir.
if (function_exists('civicrm_initialize')) {
return TRUE;
}
}
return FALSE;
}
/**
* Get the path where the CiviCRM module is installed
* Ex: /var/aegir/platforms/[...]/sites/all/modules/civicrm
*
* NB: if CiviCRM was not detected, verify the platform.
*
* @param Boolean $load_if_missing Recommended in most cases. See do#2364871.
*/
function _provision_civicrm_get_package_path($load_if_missing = FALSE) {
// Issue#2942572 For D8 and D9, we only support having CiviCRM in /vendor
// Aegir package info functions are not CiviCRM-friendly. This is simpler.
$drupal_core_version = drush_drupal_major_version();
if (function_exists('provision_get_drupal_core_version')) {
$v = provision_get_drupal_core_version();
if ($v) {
$drupal_core_version = $v;
}
}
if (drush_drupal_major_version() >= 8 || version_compare($drupal_core_version, 9, '>=')) {
$root = d()->root;
// If Drupal lives under a 'web' subdirectory (which is usually the case with composer),
// we remove the prefix, since the vendor directory is outside 'web'.
$root = preg_replace('#web/?$#', '', $root);
$crmpath = $root . '/vendor/civicrm/civicrm-core/';
if (is_dir($crmpath)) {
drush_log(dt('CiviCRM: civicrm is in @path', array('@path' => $crmpath)));
return $crmpath;
}
}
$module = _provision_civicrm_get_package_info();
if ($module) {
// Get the parent directory of the module, which is in civicrm/drupal/civicrm.module
$crmpath = dirname(dirname($module['filename']));
drush_log(dt('CiviCRM: civicrm is in @path', array('@path' => $crmpath)));
// do#2364871 Workaround a BOA 2.3 issue
// When civicrm is in an install profile, the civicrm drush module does not get loaded.
if ($load_if_missing && ! function_exists('_civicrm_get_crmpath')) {
drush_log(dt('CiviCRM: loading file: civicrm.drush.inc.'));
require_once($crmpath . '/drupal/drush/civicrm.drush.inc');
}
return $crmpath;
}
return FALSE;
}
/**
* Get the CiviCRM module base information (filename, basename, version, etc)
*/
function _provision_civicrm_get_package_info() {
$module = NULL;
// Check if the CiviCRM code base is present in the platform
// Note: after putting the code there, you need to verify
// the platform.
$packages = drush_get_option('packages', array('modules' => NULL));
$profile = drush_get_option('profile', NULL);
if (isset($packages['modules']) && isset($packages['modules']['civicrm'])) {
drush_log(dt('CiviCRM: found civicrm in packages'));
$module = $packages['modules']['civicrm'];
}
elseif (isset($packages['sites-all']) && isset($packages['sites-all']['modules']) && isset($packages['sites-all']['modules']['civicrm'])) {
$module = $packages['sites-all']['modules']['civicrm'];
drush_log(dt('CiviCRM: found civicrm in packages of sites-all modules'));
}
elseif (isset($packages['base']) && isset($packages['base']['modules']) && isset($packages['base']['modules']['civicrm'])) {
$module = $packages['base']['modules']['civicrm'];
drush_log(dt('CiviCRM: found civicrm in packages of base modules'));
}
elseif ($profile && isset($packages['profiles'][$profile]['modules']) && isset($packages['profiles'][$profile]['modules']['civicrm'])) {
$module = $packages['profiles'][$profile]['modules']['civicrm'];
drush_log(dt('CiviCRM: found civicrm in packages of @profile profile modules', array('@profile' => $profile)));
}
else {
// drush_log(dt('CiviCRM: civicrm not found in packages ' . print_r($packages, 1)));
}
return $module;
}
/**
* CiviCRM verify operations (used by both verify and deploy)
*/
function _provision_civicrm_regenerate_settings($url = NULL) {
drush_log(dt("CiviCRM: starting provision_civicrm_regenerate_settings()."));
// Make sure to write the civicrm options
$civi_opts = _provision_civicrm_drush_options('post verify');
foreach ($civi_opts as $opt => $val) {
drush_set_option($opt, $val, 'site');
}
// Since we do not have an upgrade path for existing site key (before it
// was added to the frontend), be nice about an empty sitekey.
if (d()->civicrm_sitekey) {
drush_log('CiviCRM: found a site key from the front-end.', 'ok');
drush_set_option('civicrm_sitekey', d()->civicrm_sitekey);
}
else {
drush_log('CiviCRM: no site key found from the front-end.');
}
// @todo FIXME pass the civicrm_sitekey if set in the frontend
provision_file()->chmod(d()->site_path, 0755);
_provision_civicrm_run_cv_command('php:script ' . dirname(__DIR__) . '/cv/regenerate-settings.php ' . escapeshellarg($url));
provision_file()->chmod(d()->site_path, 0555);
drush_log(dt("CiviCRM: Generated config civicrm.settings.php file"), 'ok');
drush_log(dt("CiviCRM: leaving provision_civicrm_regenerate_settings()."));
}
function provision_civicrm_verify_common() {
drush_log(dt("CiviCRM: in provision_civicrm_verify_common()."));
// Set file acls on civicrm.settings.php, if necessary
if (function_exists('provisionacl_set_acl')) {
$group = d()->client_name;
$file = d()->site_path . '/' . 'civicrm.settings.php';
drush_log(dt('CiviCRM: Attempting to set acls for @group on @file', array('@group' => $group, '@file' => $file)));
// Check the group
if (!provision_posix_groupname($group)) {
drush_log(dt('CiviCRM: not setting acls on @file for non-existent group @group', array('@file' => $file, '@group' => $group)), 'warning');
}
// Check the file
else if (! file_exists($file)) {
drush_log(dt('@file not found, acls not configured', array('@file' => $file)), 'warning');
}
else {
provisionacl_set_acl('group', $group, 'r--', array($file), TRUE);
}
}
drush_log(dt("CiviCRM: leaving provision_civicrm_verify_common()."));
return TRUE;
}
/**
* Check whether to set the upgrade mode
*/
function _provision_civicrm_check_upgrade_mode() {
drush_log(dt("CiviCRM: in _provision_civicrm_check_upgrade_mode()"));
// Sets the civicrm upgrade mode of the code/db version do not match
$codeVer = _provision_civicrm_codebase_version();
$dbVer = _provision_civicrm_database_version();
if (version_compare($codeVer, $dbVer) != 0) {
if (! defined('CIVICRM_UPGRADE_ACTIVE')) {
define('CIVICRM_UPGRADE_ACTIVE', 1);
drush_log(dt('CiviCRM: upgrade mode enabled.'));
return TRUE;
}
}
drush_log(dt("CiviCRM: leaving _provision_civicrm_check_upgrade_mode()"));
return FALSE;
}
/**
* Helper function to get the CiviCRM version of the code base.
*
* Avoiding any CMS or Aegir methods, because:
* - using pm_parse_version() to parse the version, because it does not
* like versions such as '8.x-5.0.beta1'.
* - Drupal7 has $packages['modules']['civicrm']['info']['version'],
* but Drupal8 only has $packages['modules']['civicrm']['version'] (which D7 also has).
* - Sometimes the platform info is outdated unless we remember to run verify.
* - CiviCRM has a somewhat stable interface to fetch this info.
*/
function _provision_civicrm_codebase_version() {
static $codeVer = 0;
if ($codeVer) {
return $codeVer;
}
$crmPath = _provision_civicrm_get_package_path();
$vendorPath = $crmPath . '/vendor/';
if (drush_drupal_major_version() >= 8) {
$root = d()->root;
// If Drupal lives under a 'web' subdirectory (which is usually the case with composer),
// we remove the prefix, since the vendor directory is outside 'web'.
// Duplicates code from _provision_civicrm_get_package_path().
$root = preg_replace('#web/?$#', '', $root);
$vendorPath = $root . '/vendor/';
}
if ($crmPath) {
$xmlPath = $crmPath . '/xml/version.xml';
drush_log(dt('CiviCRM: version xmlPath !path', ['!path' => $xmlPath]), 'ok');
$codeVer = system('grep version_no ' . escapeshellarg($xmlPath) . ' | sed "s/.*>\(.*\)<.*/\1/"');
}
drush_log(dt('CiviCRM: code version is !ver', ['!ver' => $codeVer]), 'ok');
return $codeVer;
}
/**
* Helper function to get the CiviCRM version of the DB
*/
function _provision_civicrm_database_version() {
static $dbVer = 0;
if ($dbVer) {
return $dbVer;
}
$command = 'cd ' . escapeshellarg(d()->site_path) . ' && echo "select version from civicrm_domain limit 1" | cv sql | tail -1';
drush_log(dt("CiviCRM: running: %command", ['%command' => $command]), 'ok');
$dbVer = system($command, $retval);
if ($retval) {
drush_log(dt("CiviCRM: command failed {$retval} (the ConfigAndLog should have more details): %output", ['%output' => $dbVer]), 'warning');
return NULL;
}
drush_log(dt('CiviCRM: db version is !ver', ['!ver' => $dbVer]), 'ok');
return $dbVer;
}
/**
* Run a command by invoking a shell instead of running it in the
* same process as Aegir, because it makes error handling more difficult.
*
* You must call escapeshellarg() before calling this function, if there are any args in the $command.
*
* Errors are logged as warnings to avoid an Aegir rollback (because those errors
* should not happen, and if they do, we want to be able to debug).
*/
function _provision_civicrm_run_drush_command($command) {
$command = 'cd ' . escapeshellarg(d()->site_path) . ' && drush --quiet cc drush && drush --quiet @' . escapeshellarg(d()->uri) . ' ' . $command;
drush_log(dt("CiviCRM: running: %command", ['%command' => $command]), 'ok');
$json = system($command, $retval);
// This assumes we are always using --out=json for CiviCRM
$output = json_decode($json, TRUE);
if ($retval == 1 && $json == 'Do you really want to continue? (y/n): y') {
// Not seeing any error.. shrug
drush_log(dt("CiviCRM: command success: %output", ['%output' => $json]), 'ok');
}
elseif ($retval || (is_array($output) && !empty($output['is_error']))) {
drush_log(dt("CiviCRM: command failed {$retval} (the ConfigAndLog should have more details): %output", ['%output' => $json]), 'warning');
}
elseif (!preg_match('/is_error.:0/', $json)) {
drush_log(dt("CiviCRM: command may have failed: %output", ['%output' => $json]), 'warning');
}
else {
drush_log(dt("CiviCRM: command success: %output", ['%output' => $json]), 'ok');
}
return $json;
}
/**
* Run a command by invoking a shell instead of running it in the
* same process as Aegir, because it makes error handling more difficult.
*
* You must call escapeshellarg() before calling this function, if there are any args in the $command.
*
* Errors are logged as warnings to avoid an Aegir rollback (because those errors
* should not happen, and if they do, we want to be able to debug).
*/
function _provision_civicrm_run_cv_command($command) {
// Always non-interactive (cv -n)
$command = 'cd ' . escapeshellarg(d()->site_path) . ' && cv -n ' . $command;
drush_log(dt("CiviCRM: running: %command", ['%command' => $command]), 'ok');
$json = system($command, $retval);
// Output is always json
$output = json_decode($json, TRUE);
if ($retval || (is_array($output) && !empty($output['is_error']))) {
drush_log(dt("CiviCRM: command failed {$retval} (the ConfigAndLog should have more details): %output", ['%output' => $json]), 'warning');
}
else {
drush_log(dt("CiviCRM: command success: %output", ['%output' => $json]), 'ok');
}
return $output;
}