Merge pull request #14981 from eileenmcnaughton/load_extract
[civicrm-core.git] / api / v3 / System.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28/**
b081365f 29 * This api exposes CiviCRM system functionality.
6a488035 30 *
b081365f 31 * Includes caching, logging, and checking system functionality.
6a488035 32 *
b081365f 33 * @package CiviCRM_APIv3
6a488035
TO
34 */
35
36/**
9d32e6f7 37 * Flush all system caches.
6a488035 38 *
cf470720
TO
39 * @param array $params
40 * Input parameters.
c28e1768
CW
41 * - triggers: bool, whether to drop/create SQL triggers; default: FALSE
42 * - session: bool, whether to reset the CiviCRM session data; default: FALSE
6a488035 43 *
c23f45d3 44 * @return array
6a488035
TO
45 */
46function civicrm_api3_system_flush($params) {
47 CRM_Core_Invoke::rebuildMenuAndCaches(
48 CRM_Utils_Array::value('triggers', $params, FALSE),
49 CRM_Utils_Array::value('session', $params, FALSE)
50 );
51 return civicrm_api3_create_success();
52}
53
11e09c59 54/**
9d32e6f7 55 * Adjust Metadata for Flush action.
6a488035 56 *
0aa0303c
EM
57 * The metadata is used for setting defaults, documentation & validation.
58 *
cf470720 59 * @param array $params
b081365f 60 * Array of parameters determined by getfields.
6a488035 61 */
9b873358 62function _civicrm_api3_system_flush_spec(&$params) {
cf8f0fff 63 $params['triggers'] = [
b2ed8e73
CW
64 'title' => 'Triggers',
65 'description' => 'rebuild triggers (boolean)',
66 'type' => CRM_Utils_Type::T_BOOLEAN,
cf8f0fff
CW
67 ];
68 $params['session'] = [
b2ed8e73
CW
69 'title' => 'Sessions',
70 'description' => 'refresh sessions (boolean)',
71 'type' => CRM_Utils_Type::T_BOOLEAN,
cf8f0fff 72 ];
9ef501da 73}
6a488035 74
9ef501da 75/**
9d32e6f7
EM
76 * System.Check API specification (optional).
77 *
9ef501da
TO
78 * This is used for documentation and validation.
79 *
cf470720
TO
80 * @param array $spec
81 * Description of fields supported by this API call.
9d32e6f7 82 *
9ef501da
TO
83 * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
84 */
85function _civicrm_api3_system_check_spec(&$spec) {
cf8f0fff 86 $spec['id'] = [
e5e4a5b2
CW
87 'title' => 'ID',
88 'description' => 'Not a real identifier - do not use',
89 'type' => CRM_Utils_Type::T_INT,
cf8f0fff
CW
90 ];
91 $spec['name'] = [
e5e4a5b2
CW
92 'title' => 'Name',
93 'description' => 'Unique identifier',
94 'type' => CRM_Utils_Type::T_STRING,
cf8f0fff
CW
95 ];
96 $spec['title'] = [
e5e4a5b2
CW
97 'title' => 'Title',
98 'description' => 'Short title text',
99 'type' => CRM_Utils_Type::T_STRING,
cf8f0fff
CW
100 ];
101 $spec['message'] = [
e5e4a5b2
CW
102 'title' => 'Message',
103 'description' => 'Long description html',
104 'type' => CRM_Utils_Type::T_STRING,
cf8f0fff
CW
105 ];
106 $spec['help'] = [
e5e4a5b2
CW
107 'title' => 'Help',
108 'description' => 'Optional extra help (html string)',
109 'type' => CRM_Utils_Type::T_STRING,
cf8f0fff
CW
110 ];
111 $spec['severity'] = [
e5e4a5b2 112 'title' => 'Severity',
d1fa280a
CW
113 'description' => 'Psr\Log\LogLevel string',
114 'type' => CRM_Utils_Type::T_STRING,
0e1b333f 115 'options' => array_combine(CRM_Utils_Check::getSeverityList(), CRM_Utils_Check::getSeverityList()),
cf8f0fff
CW
116 ];
117 $spec['severity_id'] = [
d1fa280a 118 'title' => 'Severity ID',
e5e4a5b2
CW
119 'description' => 'Integer representation of Psr\Log\LogLevel',
120 'type' => CRM_Utils_Type::T_INT,
0e1b333f 121 'options' => CRM_Utils_Check::getSeverityList(),
cf8f0fff
CW
122 ];
123 $spec['is_visible'] = [
fc8d84da 124 'title' => 'is visible',
e5e4a5b2 125 'description' => '0 if message has been hidden by the user',
a1c17079 126 'type' => CRM_Utils_Type::T_BOOLEAN,
cf8f0fff
CW
127 ];
128 $spec['hidden_until'] = [
e5e4a5b2
CW
129 'title' => 'Hidden_until',
130 'description' => 'When will hidden message be visible again?',
131 'type' => CRM_Utils_Type::T_DATE,
cf8f0fff 132 ];
232624b1 133}
9ef501da
TO
134
135/**
b081365f 136 * System Check API.
9ef501da
TO
137 *
138 * @param array $params
9d32e6f7 139 *
a6c01b45 140 * @return array
72b3a70c 141 * API result descriptor; return items are alert codes/messages
9ef501da
TO
142 * @see civicrm_api3_create_success
143 * @see civicrm_api3_create_error
144 * @throws API_Exception
145 */
146function civicrm_api3_system_check($params) {
e918c16d 147 // array(array('name'=> $, 'severity'=>$, ...))
7c6fb573 148 $id = 1;
cf8f0fff 149 $returnValues = $fields = [];
e5e4a5b2 150 _civicrm_api3_system_check_spec($fields);
e918c16d
NM
151
152 // array(CRM_Utils_Check_Message)
e5e4a5b2 153 $messages = CRM_Utils_Check::checkAll();
e918c16d 154
7c6fb573 155 foreach ($messages as $msg) {
cf8f0fff 156 $returnValues[] = $msg->toArray() + ['id' => $id++];
46a903fb
NM
157 }
158
e5e4a5b2 159 return _civicrm_api3_basic_array_get('systemCheck', $params, $returnValues, "id", array_keys($fields));
e2bef985 160}
161
162/**
9d32e6f7
EM
163 * Log entry to system log table.
164 *
c490a46a 165 * @param array $params
e2bef985 166 *
167 * @return array
168 */
169function civicrm_api3_system_log($params) {
170 $log = new CRM_Utils_SystemLogger();
9d32e6f7 171 // This part means fields with separate db storage are accepted as params which kind of seems more intuitive to me
e2bef985 172 // because I felt like not doing this required a bunch of explanation in the spec function - but perhaps other won't see it as helpful?
22e263ad 173 if (!isset($params['context'])) {
cf8f0fff 174 $params['context'] = [];
e2bef985 175 }
cf8f0fff 176 $specialFields = ['contact_id', 'hostname'];
22e263ad
TO
177 foreach ($specialFields as $specialField) {
178 if (isset($params[$specialField]) && !isset($params['context'])) {
e2bef985 179 $params['context'][$specialField] = $params[$specialField];
180 }
181 }
182 $returnValues = $log->log($params['level'], $params['message'], $params['context']);
183 return civicrm_api3_create_success($returnValues, $params, 'System', 'Log');
184}
185
186/**
d1b0d05e
EM
187 * Metadata for log function.
188 *
c490a46a 189 * @param array $params
e2bef985 190 */
4f8ccea0 191function _civicrm_api3_system_log_spec(&$params) {
cf8f0fff 192 $params['level'] = [
e2bef985 193 'title' => 'Log Level',
194 'description' => 'Log level as described in PSR3 (info, debug, warning etc)',
195 'type' => CRM_Utils_Type::T_STRING,
196 'api.required' => TRUE,
cf8f0fff
CW
197 ];
198 $params['message'] = [
e2bef985 199 'title' => 'Log Message',
200 'description' => 'Standardised message string, you can also ',
201 'type' => CRM_Utils_Type::T_STRING,
202 'api.required' => TRUE,
cf8f0fff
CW
203 ];
204 $params['context'] = [
e2bef985 205 'title' => 'Log Context',
206 'description' => 'An array of additional data to store.',
207 'type' => CRM_Utils_Type::T_LONGTEXT,
cf8f0fff
CW
208 'api.default' => [],
209 ];
210 $params['contact_id'] = [
e2bef985 211 'title' => 'Log Contact ID',
212 'description' => 'Optional ID of relevant contact',
213 'type' => CRM_Utils_Type::T_INT,
cf8f0fff
CW
214 ];
215 $params['hostname'] = [
e2bef985 216 'title' => 'Log Hostname',
217 'description' => 'Optional name of host',
218 'type' => CRM_Utils_Type::T_STRING,
cf8f0fff 219 ];
e2bef985 220}
42bf9336 221
91f1889e 222/**
d1b0d05e 223 * System.Get API.
91f1889e 224 *
24a70b66 225 * @param array $params
d1b0d05e 226 *
24a70b66 227 * @return array
91f1889e
TO
228 */
229function civicrm_api3_system_get($params) {
5bbcc823 230 $config = CRM_Core_Config::singleton();
cf8f0fff
CW
231 $returnValues = [
232 [
7c31ae57
SL
233 // deprecated in favor of civi.version
234 'version' => CRM_Utils_System::version(),
235 // deprecated in favor of cms.type
236 'uf' => CIVICRM_UF,
cf8f0fff 237 'php' => [
5bbcc823 238 'version' => phpversion(),
40278a8e 239 'time' => time(),
5bbcc823 240 'tz' => date_default_timezone_get(),
d7aad22f 241 'sapi' => php_sapi_name(),
5bbcc823
TO
242 'extensions' => get_loaded_extensions(),
243 'ini' => _civicrm_api3_system_get_redacted_ini(),
cf8f0fff
CW
244 ],
245 'mysql' => [
5bbcc823 246 'version' => CRM_Core_DAO::singleValueQuery('SELECT @@version'),
40278a8e 247 'time' => CRM_Core_DAO::singleValueQuery('SELECT unix_timestamp()'),
7163c128 248 'vars' => _civicrm_api3_system_get_redacted_mysql(),
cf8f0fff
CW
249 ],
250 'cms' => [
594260ad 251 'version' => $config->userSystem->getVersion(),
5bbcc823
TO
252 'type' => CIVICRM_UF,
253 'modules' => CRM_Core_Module::collectStatuses($config->userSystem->getModules()),
cf8f0fff
CW
254 ],
255 'civi' => [
5bbcc823
TO
256 'version' => CRM_Utils_System::version(),
257 'dev' => (bool) CRM_Utils_System::isDevelopment(),
258 'components' => array_keys(CRM_Core_Component::getEnabledComponents()),
7237222f 259 'extensions' => preg_grep('/^uninstalled$/', CRM_Extension_System::singleton()->getManager()->getStatuses(), PREG_GREP_INVERT),
41ccb6fc
C
260 'multidomain' => CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_domain') > 1,
261 'settings' => _civicrm_api3_system_get_redacted_settings(),
5bbcc823 262 'exampleUrl' => CRM_Utils_System::url('civicrm/example', NULL, TRUE, NULL, FALSE),
cf8f0fff
CW
263 ],
264 'http' => [
d7aad22f
C
265 'software' => CRM_Utils_Array::value('SERVER_SOFTWARE', $_SERVER),
266 'forwarded' => !empty($_SERVER['HTTP_X_FORWARDED_FOR']) || !empty($_SERVER['X_FORWARDED_PROTO']),
267 'port' => (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443) ? 'Standard' : 'Nonstandard',
cf8f0fff
CW
268 ],
269 'os' => [
d7aad22f
C
270 'type' => php_uname('s'),
271 'release' => php_uname('r'),
272 'version' => php_uname('v'),
273 'machine' => php_uname('m'),
cf8f0fff
CW
274 ],
275 ],
276 ];
5bbcc823 277
91f1889e
TO
278 return civicrm_api3_create_success($returnValues, $params, 'System', 'get');
279}
5bbcc823
TO
280
281/**
282 * Generate a sanitized/anonymized/redacted dump of the PHP configuration.
283 *
284 * Some INI fields contain site-identifying information (SII) -- e.g. URLs,
285 * hostnames, file paths, IP addresses, passwords, or free-form comments
286 * could be used to identify a site or gain access to its resources.
287 *
288 * A number of INI fields have been examined to determine whether they
289 * contain SII. Approved fields are put in a whitelist; all other fields
290 * are redacted.
291 *
292 * Redaction hides the substance of a field but does not completely omit
293 * all information. Consider the field 'mail.log' - setting this field
294 * has a functional effect (it enables or disables the logging behavior)
295 * and also points to particular file. Empty values (FALSE/NULL/0/"")
296 * will pass through redaction, but all other values will be replaced
297 * by a string (eg "REDACTED"). This roughly indicates whether the
298 * option is enabled/disabled without giving away its content.
299 *
300 * @return array
301 */
302function _civicrm_api3_system_get_redacted_ini() {
303 static $whitelist = NULL;
304 if ($whitelist === NULL) {
7163c128 305 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/ini-whitelist.txt');
5bbcc823
TO
306 }
307
308 $inis = ini_get_all(NULL, FALSE);
cf8f0fff 309 $result = [];
5bbcc823
TO
310 foreach ($inis as $k => $v) {
311 if (empty($v) || in_array($k, $whitelist)) {
312 $result[$k] = $v;
313 }
314 else {
315 $result[$k] = 'REDACTED';
316 }
317 }
318
319 return $result;
320}
7163c128
TO
321
322/**
323 * Generate ae sanitized/anonymized/redacted dump of MySQL configuration.
324 *
325 * @return array
326 * @see _civicrm_api3_system_get_redacted_ini
327 */
328function _civicrm_api3_system_get_redacted_mysql() {
329 static $whitelist = NULL;
330 if ($whitelist === NULL) {
331 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/mysql-whitelist.txt');
332 }
333
334 $inis = ini_get_all(NULL, FALSE);
cf8f0fff 335 $result = [];
7163c128
TO
336 $dao = CRM_Core_DAO::executeQuery('SHOW VARIABLES');
337 while ($dao->fetch()) {
338 if (empty($dao->Variable_name) || in_array($dao->Variable_name, $whitelist)) {
339 $result[$dao->Variable_name] = $dao->Value;
340 }
341 else {
342 $result[$dao->Variable_name] = 'REDACTED';
343 }
344 }
345
346 return $result;
347}
348
db01bf2f 349/**
350 * Get redacted settings.
351 *
352 * @return array
353 * @throws CiviCRM_API3_Exception
354 */
41ccb6fc
C
355function _civicrm_api3_system_get_redacted_settings() {
356 static $whitelist = NULL;
357 if ($whitelist === NULL) {
358 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/setting-whitelist.txt');
359 }
360
cf8f0fff
CW
361 $apiResult = civicrm_api3('Setting', 'get', []);
362 $result = [];
41ccb6fc
C
363 foreach ($apiResult['values'] as $settings) {
364 foreach ($settings as $key => $value) {
365 if (in_array($key, $whitelist)) {
366 $result[$key] = $value;
367 }
368 }
369 }
370
371 return $result;
372}
373
7163c128
TO
374/**
375 * Read a whitelist.
376 *
377 * @param string $whitelistFile
378 * Name of a file. Each line is a field name. Comments begin with "#".
379 * @return array
380 */
381function _civicrm_api3_system_get_whitelist($whitelistFile) {
382 $whitelist = array_filter(
383 explode("\n", file_get_contents($whitelistFile)),
384 function ($k) {
385 return !empty($k) && !preg_match('/^\s*#/', $k);
386 }
387 );
388 return $whitelist;
389}
d7ea7150 390
391/**
392 * Update log table structures.
393 *
394 * This updates the engine type if defined in the hook and changes the field type
395 * for log_conn_id to reflect CRM-18193.
396 */
dd05020d 397function civicrm_api3_system_updatelogtables($params) {
d7ea7150 398 $schema = new CRM_Logging_Schema();
dd05020d
MWMC
399 $updatedTablesCount = $schema->updateLogTableSchema($params);
400 return civicrm_api3_create_success($updatedTablesCount);
401}
402
403/**
404 * Adjust Metadata for Flush action.
405 *
406 * The metadata is used for setting defaults, documentation & validation.
407 *
408 * @param array $params
409 * Array of parameters determined by getfields.
410 */
411function _civicrm_api3_system_updatelogtables_spec(&$params) {
412 $params['updateChangedEngineConfig'] = [
413 'title' => 'Update Engine Config if changed?',
414 'description' => 'By default, we only update if the ENGINE has changed, set this to TRUE to update if the ENGINE_CONFIG has changed.',
415 'type' => CRM_Utils_Type::T_BOOLEAN,
e26df891 416 'api.default' => FALSE,
dd05020d 417 ];
204aa6fb
PF
418 $params['forceEngineMigration'] = [
419 'title' => 'Force storage engine to upgrade to InnoDB?',
420 'description' => 'Older versions of CiviCRM used the ARCHIVE engine by default. Set this to TRUE to migrate the engine to the new default.',
421 'type' => CRM_Utils_Type::T_BOOLEAN,
e26df891 422 'api.default' => FALSE,
204aa6fb 423 ];
49186f94
AS
424}
425
426/**
427 * Update indexes.
428 *
429 * This adds any indexes that exist in the schema but not the database.
430 */
431function civicrm_api3_system_updateindexes() {
3d4602c3 432 CRM_Core_BAO_SchemaHandler::createMissingIndices(CRM_Core_BAO_SchemaHandler::getMissingIndices(TRUE));
49186f94 433 return civicrm_api3_create_success(1);
d7ea7150 434}
cb721356
JP
435
436/**
437 * Creates missing log tables.
438 *
439 * CRM-20838 - This adds any missing log tables into the database.
440 */
441function civicrm_api3_system_createmissinglogtables() {
442 $schema = new CRM_Logging_Schema();
443 $missingLogTables = $schema->getMissingLogTables();
444 if (!empty($missingLogTables)) {
445 foreach ($missingLogTables as $tableName) {
fcc20cec 446 $schema->fixSchemaDifferencesFor($tableName);
cb721356
JP
447 }
448 }
449 return civicrm_api3_create_success(1);
450}
7fb9179d
SL
451
452/**
453 * Rebuild Multilingual Schema
454 *
455 */
456function civicrm_api3_system_rebuildmultilingualschema() {
457 $domain = new CRM_Core_DAO_Domain();
458 $domain->find(TRUE);
459
460 if ($domain->locales) {
461 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
462 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales);
463 return civicrm_api3_create_success(1);
464 }
465 else {
466 throw new API_Exception('Cannot call rebuild Multilingual schema on non Multilingual database');
467 }
468}