3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
13 * This api exposes CiviCRM system functionality.
15 * Includes caching, logging, and checking system functionality.
17 * @package CiviCRM_APIv3
21 * Flush all system caches.
23 * @param array $params
25 * - triggers: bool, whether to drop/create SQL triggers; default: FALSE
26 * - session: bool, whether to reset the CiviCRM session data; default: FALSE
30 function civicrm_api3_system_flush($params) {
31 CRM_Core_Invoke
::rebuildMenuAndCaches(
32 CRM_Utils_Array
::value('triggers', $params, FALSE),
33 CRM_Utils_Array
::value('session', $params, FALSE)
35 return civicrm_api3_create_success();
39 * Adjust Metadata for Flush action.
41 * The metadata is used for setting defaults, documentation & validation.
43 * @param array $params
44 * Array of parameters determined by getfields.
46 function _civicrm_api3_system_flush_spec(&$params) {
47 $params['triggers'] = [
48 'title' => 'Triggers',
49 'description' => 'rebuild triggers (boolean)',
50 'type' => CRM_Utils_Type
::T_BOOLEAN
,
52 $params['session'] = [
53 'title' => 'Sessions',
54 'description' => 'refresh sessions (boolean)',
55 'type' => CRM_Utils_Type
::T_BOOLEAN
,
60 * System.Check API specification (optional).
62 * This is used for documentation and validation.
65 * Description of fields supported by this API call.
67 * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
69 function _civicrm_api3_system_check_spec(&$spec) {
72 'description' => 'Not a real identifier - do not use',
73 'type' => CRM_Utils_Type
::T_INT
,
77 'description' => 'Unique identifier',
78 'type' => CRM_Utils_Type
::T_STRING
,
82 'description' => 'Short title text',
83 'type' => CRM_Utils_Type
::T_STRING
,
87 'description' => 'Long description html',
88 'type' => CRM_Utils_Type
::T_STRING
,
92 'description' => 'Optional extra help (html string)',
93 'type' => CRM_Utils_Type
::T_STRING
,
96 'title' => 'Severity',
97 'description' => 'Psr\Log\LogLevel string',
98 'type' => CRM_Utils_Type
::T_STRING
,
99 'options' => array_combine(CRM_Utils_Check
::getSeverityList(), CRM_Utils_Check
::getSeverityList()),
101 $spec['severity_id'] = [
102 'title' => 'Severity ID',
103 'description' => 'Integer representation of Psr\Log\LogLevel',
104 'type' => CRM_Utils_Type
::T_INT
,
105 'options' => CRM_Utils_Check
::getSeverityList(),
107 $spec['is_visible'] = [
108 'title' => 'is visible',
109 'description' => '0 if message has been hidden by the user',
110 'type' => CRM_Utils_Type
::T_BOOLEAN
,
112 $spec['hidden_until'] = [
113 'title' => 'Hidden_until',
114 'description' => 'When will hidden message be visible again?',
115 'type' => CRM_Utils_Type
::T_DATE
,
122 * @param array $params
125 * API result descriptor; return items are alert codes/messages
126 * @see civicrm_api3_create_success
127 * @see civicrm_api3_create_error
128 * @throws API_Exception
130 function civicrm_api3_system_check($params) {
131 // array(array('name'=> $, 'severity'=>$, ...))
133 $returnValues = $fields = [];
134 _civicrm_api3_system_check_spec($fields);
136 // array(CRM_Utils_Check_Message)
137 $messages = CRM_Utils_Check
::checkAll();
139 foreach ($messages as $msg) {
140 $returnValues[] = $msg->toArray() +
['id' => $id++
];
143 return _civicrm_api3_basic_array_get('systemCheck', $params, $returnValues, "id", array_keys($fields));
147 * Log entry to system log table.
149 * @param array $params
153 function civicrm_api3_system_log($params) {
154 $log = new CRM_Utils_SystemLogger();
155 // This part means fields with separate db storage are accepted as params which kind of seems more intuitive to me
156 // 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?
157 if (!isset($params['context'])) {
158 $params['context'] = [];
160 $specialFields = ['contact_id', 'hostname'];
161 foreach ($specialFields as $specialField) {
162 if (isset($params[$specialField]) && !isset($params['context'])) {
163 $params['context'][$specialField] = $params[$specialField];
166 $returnValues = $log->log($params['level'], $params['message'], $params['context']);
167 return civicrm_api3_create_success($returnValues, $params, 'System', 'Log');
171 * Metadata for log function.
173 * @param array $params
175 function _civicrm_api3_system_log_spec(&$params) {
177 'title' => 'Log Level',
178 'description' => 'Log level as described in PSR3 (info, debug, warning etc)',
179 'type' => CRM_Utils_Type
::T_STRING
,
180 'api.required' => TRUE,
182 $params['message'] = [
183 'title' => 'Log Message',
184 'description' => 'Standardised message string, you can also ',
185 'type' => CRM_Utils_Type
::T_STRING
,
186 'api.required' => TRUE,
188 $params['context'] = [
189 'title' => 'Log Context',
190 'description' => 'An array of additional data to store.',
191 'type' => CRM_Utils_Type
::T_LONGTEXT
,
194 $params['contact_id'] = [
195 'title' => 'Log Contact ID',
196 'description' => 'Optional ID of relevant contact',
197 'type' => CRM_Utils_Type
::T_INT
,
199 $params['hostname'] = [
200 'title' => 'Log Hostname',
201 'description' => 'Optional name of host',
202 'type' => CRM_Utils_Type
::T_STRING
,
209 * @param array $params
213 function civicrm_api3_system_get($params) {
214 $config = CRM_Core_Config
::singleton();
217 // deprecated in favor of civi.version
218 'version' => CRM_Utils_System
::version(),
219 // deprecated in favor of cms.type
222 'version' => phpversion(),
224 'tz' => date_default_timezone_get(),
225 'sapi' => php_sapi_name(),
226 'extensions' => get_loaded_extensions(),
227 'ini' => _civicrm_api3_system_get_redacted_ini(),
230 'version' => CRM_Core_DAO
::singleValueQuery('SELECT @@version'),
231 'time' => CRM_Core_DAO
::singleValueQuery('SELECT unix_timestamp()'),
232 'vars' => _civicrm_api3_system_get_redacted_mysql(),
235 'version' => $config->userSystem
->getVersion(),
236 'type' => CIVICRM_UF
,
237 'modules' => CRM_Core_Module
::collectStatuses($config->userSystem
->getModules()),
240 'version' => CRM_Utils_System
::version(),
241 'dev' => (bool) CRM_Utils_System
::isDevelopment(),
242 'components' => array_keys(CRM_Core_Component
::getEnabledComponents()),
243 'extensions' => preg_grep('/^uninstalled$/', CRM_Extension_System
::singleton()->getManager()->getStatuses(), PREG_GREP_INVERT
),
244 'multidomain' => CRM_Core_DAO
::singleValueQuery('SELECT count(*) FROM civicrm_domain') > 1,
245 'settings' => _civicrm_api3_system_get_redacted_settings(),
246 'exampleUrl' => CRM_Utils_System
::url('civicrm/example', NULL, TRUE, NULL, FALSE),
249 'software' => CRM_Utils_Array
::value('SERVER_SOFTWARE', $_SERVER),
250 'forwarded' => !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ||
!empty($_SERVER['X_FORWARDED_PROTO']),
251 'port' => (empty($_SERVER['SERVER_PORT']) ||
$_SERVER['SERVER_PORT'] == 80 ||
$_SERVER['SERVER_PORT'] == 443) ?
'Standard' : 'Nonstandard',
254 'type' => php_uname('s'),
255 'release' => php_uname('r'),
256 'version' => php_uname('v'),
257 'machine' => php_uname('m'),
262 return civicrm_api3_create_success($returnValues, $params, 'System', 'get');
266 * Generate a sanitized/anonymized/redacted dump of the PHP configuration.
268 * Some INI fields contain site-identifying information (SII) -- e.g. URLs,
269 * hostnames, file paths, IP addresses, passwords, or free-form comments
270 * could be used to identify a site or gain access to its resources.
272 * A number of INI fields have been examined to determine whether they
273 * contain SII. Approved fields are put in a whitelist; all other fields
276 * Redaction hides the substance of a field but does not completely omit
277 * all information. Consider the field 'mail.log' - setting this field
278 * has a functional effect (it enables or disables the logging behavior)
279 * and also points to particular file. Empty values (FALSE/NULL/0/"")
280 * will pass through redaction, but all other values will be replaced
281 * by a string (eg "REDACTED"). This roughly indicates whether the
282 * option is enabled/disabled without giving away its content.
286 function _civicrm_api3_system_get_redacted_ini() {
287 static $whitelist = NULL;
288 if ($whitelist === NULL) {
289 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__
. '/System/ini-whitelist.txt');
292 $inis = ini_get_all(NULL, FALSE);
294 foreach ($inis as $k => $v) {
295 if (empty($v) ||
in_array($k, $whitelist)) {
299 $result[$k] = 'REDACTED';
307 * Generate ae sanitized/anonymized/redacted dump of MySQL configuration.
310 * @see _civicrm_api3_system_get_redacted_ini
312 function _civicrm_api3_system_get_redacted_mysql() {
313 static $whitelist = NULL;
314 if ($whitelist === NULL) {
315 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__
. '/System/mysql-whitelist.txt');
318 $inis = ini_get_all(NULL, FALSE);
320 $dao = CRM_Core_DAO
::executeQuery('SHOW VARIABLES');
321 while ($dao->fetch()) {
322 if (empty($dao->Variable_name
) ||
in_array($dao->Variable_name
, $whitelist)) {
323 $result[$dao->Variable_name
] = $dao->Value
;
326 $result[$dao->Variable_name
] = 'REDACTED';
334 * Get redacted settings.
337 * @throws CiviCRM_API3_Exception
339 function _civicrm_api3_system_get_redacted_settings() {
340 static $whitelist = NULL;
341 if ($whitelist === NULL) {
342 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__
. '/System/setting-whitelist.txt');
345 $apiResult = civicrm_api3('Setting', 'get', []);
347 foreach ($apiResult['values'] as $settings) {
348 foreach ($settings as $key => $value) {
349 if (in_array($key, $whitelist)) {
350 $result[$key] = $value;
361 * @param string $whitelistFile
362 * Name of a file. Each line is a field name. Comments begin with "#".
365 function _civicrm_api3_system_get_whitelist($whitelistFile) {
366 $whitelist = array_filter(
367 explode("\n", file_get_contents($whitelistFile)),
369 return !empty($k) && !preg_match('/^\s*#/', $k);
376 * Update log table structures.
378 * This updates the engine type if defined in the hook and changes the field type
379 * for log_conn_id to reflect CRM-18193.
381 function civicrm_api3_system_updatelogtables($params) {
382 $schema = new CRM_Logging_Schema();
383 $updatedTablesCount = $schema->updateLogTableSchema($params);
384 return civicrm_api3_create_success($updatedTablesCount);
388 * Update log table structures.
390 * This updates the engine type if defined in the hook and changes the field type
391 * for log_conn_id to reflect CRM-18193.
393 * @param array $params
397 * @throws \API_Exception
399 function civicrm_api3_system_utf8conversion($params) {
400 if (CRM_Core_BAO_SchemaHandler
::migrateUtf8mb4($params['is_revert'])) {
401 return civicrm_api3_create_success(1);
403 throw new API_Exception('Conversion failed');
407 * Metadata for conversion function.
409 * @param array $params
411 function _civicrm_api3_system_utf8conversion_spec(&$params) {
412 $params['is_revert'] = [
413 'title' => ts('Revert back from UTF8MB4 to UTF8?'),
414 'type' => CRM_Utils_Type
::T_BOOLEAN
,
415 'api.default' => FALSE,
420 * Adjust Metadata for Flush action.
422 * The metadata is used for setting defaults, documentation & validation.
424 * @param array $params
425 * Array of parameters determined by getfields.
427 function _civicrm_api3_system_updatelogtables_spec(&$params) {
428 $params['updateChangedEngineConfig'] = [
429 'title' => 'Update Engine Config if changed?',
430 'description' => 'By default, we only update if the ENGINE has changed, set this to TRUE to update if the ENGINE_CONFIG has changed.',
431 'type' => CRM_Utils_Type
::T_BOOLEAN
,
432 'api.default' => FALSE,
434 $params['forceEngineMigration'] = [
435 'title' => 'Force storage engine to upgrade to InnoDB?',
436 'description' => 'Older versions of CiviCRM used the ARCHIVE engine by default. Set this to TRUE to migrate the engine to the new default.',
437 'type' => CRM_Utils_Type
::T_BOOLEAN
,
438 'api.default' => FALSE,
445 * This adds any indexes that exist in the schema but not the database.
447 * @param array $params
451 function civicrm_api3_system_updateindexes(array $params):array {
452 $tables = empty($params['tables']) ?
FALSE : (array) $params['tables'];
453 CRM_Core_BAO_SchemaHandler
::createMissingIndices(CRM_Core_BAO_SchemaHandler
::getMissingIndices(TRUE, $tables));
454 return civicrm_api3_create_success(1);
458 * Declare metadata for api System.getmissingindices
460 * @param array $params
462 function _civicrm_api3_system_updateindexes_spec(array &$params) {
463 $params['tables'] = [
464 'type' => CRM_Utils_Type
::T_STRING
,
465 'api.default' => FALSE,
466 'title' => ts('Optional tables filter'),
471 * Get an array of indices that should be defined but are not.
473 * @param array $params
477 function civicrm_api3_system_getmissingindices($params) {
478 $tables = empty($params['tables']) ?
FALSE : (array) $params['tables'];
479 $indices = CRM_Core_BAO_SchemaHandler
::getMissingIndices(FALSE, $tables);
480 return civicrm_api3_create_success($indices);
484 * Declare metadata for api System.getmissingindices
486 * @param array $params
488 function _civicrm_api3_system_getmissingindices_spec(&$params) {
489 $params['tables'] = [
490 'type' => CRM_Utils_Type
::T_STRING
,
491 'api.default' => FALSE,
492 'title' => ts('Optional tables filter'),
497 * Creates missing log tables.
499 * CRM-20838 - This adds any missing log tables into the database.
501 function civicrm_api3_system_createmissinglogtables() {
502 $schema = new CRM_Logging_Schema();
503 $missingLogTables = $schema->getMissingLogTables();
504 if (!empty($missingLogTables)) {
505 foreach ($missingLogTables as $tableName) {
506 $schema->fixSchemaDifferencesFor($tableName);
509 return civicrm_api3_create_success(1);
513 * Rebuild Multilingual Schema
516 function civicrm_api3_system_rebuildmultilingualschema() {
517 $domain = new CRM_Core_DAO_Domain();
520 if ($domain->locales
) {
521 $locales = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $domain->locales
);
522 CRM_Core_I18n_Schema
::rebuildMultilingualSchema($locales);
523 return civicrm_api3_create_success(1);
526 throw new API_Exception('Cannot call rebuild Multilingual schema on non Multilingual database');