3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
29 * This api exposes CiviCRM system functionality.
31 * Includes caching, logging, and checking system functionality.
33 * @package CiviCRM_APIv3
37 * Flush all system caches.
39 * @param array $params
41 * - triggers: bool, whether to drop/create SQL triggers; default: FALSE
42 * - session: bool, whether to reset the CiviCRM session data; default: FALSE
46 function 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)
51 return civicrm_api3_create_success();
55 * Adjust Metadata for Flush action.
57 * The metadata is used for setting defaults, documentation & validation.
59 * @param array $params
60 * Array of parameters determined by getfields.
62 function _civicrm_api3_system_flush_spec(&$params) {
63 $params['triggers'] = [
64 'title' => 'Triggers',
65 'description' => 'rebuild triggers (boolean)',
66 'type' => CRM_Utils_Type
::T_BOOLEAN
,
68 $params['session'] = [
69 'title' => 'Sessions',
70 'description' => 'refresh sessions (boolean)',
71 'type' => CRM_Utils_Type
::T_BOOLEAN
,
76 * System.Check API specification (optional).
78 * This is used for documentation and validation.
81 * Description of fields supported by this API call.
83 * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
85 function _civicrm_api3_system_check_spec(&$spec) {
88 'description' => 'Not a real identifier - do not use',
89 'type' => CRM_Utils_Type
::T_INT
,
93 'description' => 'Unique identifier',
94 'type' => CRM_Utils_Type
::T_STRING
,
98 'description' => 'Short title text',
99 'type' => CRM_Utils_Type
::T_STRING
,
102 'title' => 'Message',
103 'description' => 'Long description html',
104 'type' => CRM_Utils_Type
::T_STRING
,
108 'description' => 'Optional extra help (html string)',
109 'type' => CRM_Utils_Type
::T_STRING
,
111 $spec['severity'] = [
112 'title' => 'Severity',
113 'description' => 'Psr\Log\LogLevel string',
114 'type' => CRM_Utils_Type
::T_STRING
,
115 'options' => array_combine(CRM_Utils_Check
::getSeverityList(), CRM_Utils_Check
::getSeverityList()),
117 $spec['severity_id'] = [
118 'title' => 'Severity ID',
119 'description' => 'Integer representation of Psr\Log\LogLevel',
120 'type' => CRM_Utils_Type
::T_INT
,
121 'options' => CRM_Utils_Check
::getSeverityList(),
123 $spec['is_visible'] = [
124 'title' => 'is visible',
125 'description' => '0 if message has been hidden by the user',
126 'type' => CRM_Utils_Type
::T_BOOLEAN
,
128 $spec['hidden_until'] = [
129 'title' => 'Hidden_until',
130 'description' => 'When will hidden message be visible again?',
131 'type' => CRM_Utils_Type
::T_DATE
,
138 * @param array $params
141 * API result descriptor; return items are alert codes/messages
142 * @see civicrm_api3_create_success
143 * @see civicrm_api3_create_error
144 * @throws API_Exception
146 function civicrm_api3_system_check($params) {
147 // array(array('name'=> $, 'severity'=>$, ...))
149 $returnValues = $fields = [];
150 _civicrm_api3_system_check_spec($fields);
152 // array(CRM_Utils_Check_Message)
153 $messages = CRM_Utils_Check
::checkAll();
155 foreach ($messages as $msg) {
156 $returnValues[] = $msg->toArray() +
['id' => $id++
];
159 return _civicrm_api3_basic_array_get('systemCheck', $params, $returnValues, "id", array_keys($fields));
163 * Log entry to system log table.
165 * @param array $params
169 function civicrm_api3_system_log($params) {
170 $log = new CRM_Utils_SystemLogger();
171 // This part means fields with separate db storage are accepted as params which kind of seems more intuitive to me
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?
173 if (!isset($params['context'])) {
174 $params['context'] = [];
176 $specialFields = ['contact_id', 'hostname'];
177 foreach ($specialFields as $specialField) {
178 if (isset($params[$specialField]) && !isset($params['context'])) {
179 $params['context'][$specialField] = $params[$specialField];
182 $returnValues = $log->log($params['level'], $params['message'], $params['context']);
183 return civicrm_api3_create_success($returnValues, $params, 'System', 'Log');
187 * Metadata for log function.
189 * @param array $params
191 function _civicrm_api3_system_log_spec(&$params) {
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,
198 $params['message'] = [
199 'title' => 'Log Message',
200 'description' => 'Standardised message string, you can also ',
201 'type' => CRM_Utils_Type
::T_STRING
,
202 'api.required' => TRUE,
204 $params['context'] = [
205 'title' => 'Log Context',
206 'description' => 'An array of additional data to store.',
207 'type' => CRM_Utils_Type
::T_LONGTEXT
,
210 $params['contact_id'] = [
211 'title' => 'Log Contact ID',
212 'description' => 'Optional ID of relevant contact',
213 'type' => CRM_Utils_Type
::T_INT
,
215 $params['hostname'] = [
216 'title' => 'Log Hostname',
217 'description' => 'Optional name of host',
218 'type' => CRM_Utils_Type
::T_STRING
,
225 * @param array $params
229 function civicrm_api3_system_get($params) {
230 $config = CRM_Core_Config
::singleton();
233 // deprecated in favor of civi.version
234 'version' => CRM_Utils_System
::version(),
235 // deprecated in favor of cms.type
238 'version' => phpversion(),
240 'tz' => date_default_timezone_get(),
241 'sapi' => php_sapi_name(),
242 'extensions' => get_loaded_extensions(),
243 'ini' => _civicrm_api3_system_get_redacted_ini(),
246 'version' => CRM_Core_DAO
::singleValueQuery('SELECT @@version'),
247 'time' => CRM_Core_DAO
::singleValueQuery('SELECT unix_timestamp()'),
248 'vars' => _civicrm_api3_system_get_redacted_mysql(),
251 'version' => $config->userSystem
->getVersion(),
252 'type' => CIVICRM_UF
,
253 'modules' => CRM_Core_Module
::collectStatuses($config->userSystem
->getModules()),
256 'version' => CRM_Utils_System
::version(),
257 'dev' => (bool) CRM_Utils_System
::isDevelopment(),
258 'components' => array_keys(CRM_Core_Component
::getEnabledComponents()),
259 'extensions' => preg_grep('/^uninstalled$/', CRM_Extension_System
::singleton()->getManager()->getStatuses(), PREG_GREP_INVERT
),
260 'multidomain' => CRM_Core_DAO
::singleValueQuery('SELECT count(*) FROM civicrm_domain') > 1,
261 'settings' => _civicrm_api3_system_get_redacted_settings(),
262 'exampleUrl' => CRM_Utils_System
::url('civicrm/example', NULL, TRUE, NULL, FALSE),
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',
270 'type' => php_uname('s'),
271 'release' => php_uname('r'),
272 'version' => php_uname('v'),
273 'machine' => php_uname('m'),
278 return civicrm_api3_create_success($returnValues, $params, 'System', 'get');
282 * Generate a sanitized/anonymized/redacted dump of the PHP configuration.
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.
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
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.
302 function _civicrm_api3_system_get_redacted_ini() {
303 static $whitelist = NULL;
304 if ($whitelist === NULL) {
305 $whitelist = _civicrm_api3_system_get_whitelist(__DIR__
. '/System/ini-whitelist.txt');
308 $inis = ini_get_all(NULL, FALSE);
310 foreach ($inis as $k => $v) {
311 if (empty($v) ||
in_array($k, $whitelist)) {
315 $result[$k] = 'REDACTED';
323 * Generate ae sanitized/anonymized/redacted dump of MySQL configuration.
326 * @see _civicrm_api3_system_get_redacted_ini
328 function _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');
334 $inis = ini_get_all(NULL, FALSE);
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
;
342 $result[$dao->Variable_name
] = 'REDACTED';
350 * Get redacted settings.
353 * @throws CiviCRM_API3_Exception
355 function _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');
361 $apiResult = civicrm_api3('Setting', 'get', []);
363 foreach ($apiResult['values'] as $settings) {
364 foreach ($settings as $key => $value) {
365 if (in_array($key, $whitelist)) {
366 $result[$key] = $value;
377 * @param string $whitelistFile
378 * Name of a file. Each line is a field name. Comments begin with "#".
381 function _civicrm_api3_system_get_whitelist($whitelistFile) {
382 $whitelist = array_filter(
383 explode("\n", file_get_contents($whitelistFile)),
385 return !empty($k) && !preg_match('/^\s*#/', $k);
392 * Update log table structures.
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.
397 function civicrm_api3_system_updatelogtables($params) {
398 $schema = new CRM_Logging_Schema();
399 $updatedTablesCount = $schema->updateLogTableSchema($params);
400 return civicrm_api3_create_success($updatedTablesCount);
404 * Adjust Metadata for Flush action.
406 * The metadata is used for setting defaults, documentation & validation.
408 * @param array $params
409 * Array of parameters determined by getfields.
411 function _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
,
416 'api.default' => FALSE,
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
,
422 'api.default' => FALSE,
429 * This adds any indexes that exist in the schema but not the database.
431 function civicrm_api3_system_updateindexes() {
432 CRM_Core_BAO_SchemaHandler
::createMissingIndices(CRM_Core_BAO_SchemaHandler
::getMissingIndices(TRUE));
433 return civicrm_api3_create_success(1);
437 * Creates missing log tables.
439 * CRM-20838 - This adds any missing log tables into the database.
441 function civicrm_api3_system_createmissinglogtables() {
442 $schema = new CRM_Logging_Schema();
443 $missingLogTables = $schema->getMissingLogTables();
444 if (!empty($missingLogTables)) {
445 foreach ($missingLogTables as $tableName) {
446 $schema->fixSchemaDifferencesFor($tableName);
449 return civicrm_api3_create_success(1);
453 * Rebuild Multilingual Schema
456 function civicrm_api3_system_rebuildmultilingualschema() {
457 $domain = new CRM_Core_DAO_Domain();
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);
466 throw new API_Exception('Cannot call rebuild Multilingual schema on non Multilingual database');