drupal-civicrm/sites/all/modules/civicrm/api/v3/System.php

430 lines
14 KiB
PHP
Raw Normal View History

2018-01-14 15:10:16 +02:00
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
* This api exposes CiviCRM system functionality.
*
* Includes caching, logging, and checking system functionality.
*
* @package CiviCRM_APIv3
*/
/**
* Flush all system caches.
*
* @param array $params
* Input parameters.
* - triggers: bool, whether to drop/create SQL triggers; default: FALSE
* - session: bool, whether to reset the CiviCRM session data; default: FALSE
*
* @return array
*/
function civicrm_api3_system_flush($params) {
CRM_Core_Invoke::rebuildMenuAndCaches(
CRM_Utils_Array::value('triggers', $params, FALSE),
CRM_Utils_Array::value('session', $params, FALSE)
);
return civicrm_api3_create_success();
}
/**
* Adjust Metadata for Flush action.
*
* The metadata is used for setting defaults, documentation & validation.
*
* @param array $params
* Array of parameters determined by getfields.
*/
function _civicrm_api3_system_flush_spec(&$params) {
$params['triggers'] = array(
'title' => 'Triggers',
'description' => 'rebuild triggers (boolean)',
'type' => CRM_Utils_Type::T_BOOLEAN,
);
$params['session'] = array(
'title' => 'Sessions',
'description' => 'refresh sessions (boolean)',
'type' => CRM_Utils_Type::T_BOOLEAN,
);
}
/**
* System.Check API specification (optional).
*
* This is used for documentation and validation.
*
* @param array $spec
* Description of fields supported by this API call.
*
* @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
*/
function _civicrm_api3_system_check_spec(&$spec) {
$spec['id'] = array(
'title' => 'ID',
'description' => 'Not a real identifier - do not use',
'type' => CRM_Utils_Type::T_INT,
);
$spec['name'] = array(
'title' => 'Name',
'description' => 'Unique identifier',
'type' => CRM_Utils_Type::T_STRING,
);
$spec['title'] = array(
'title' => 'Title',
'description' => 'Short title text',
'type' => CRM_Utils_Type::T_STRING,
);
$spec['message'] = array(
'title' => 'Message',
'description' => 'Long description html',
'type' => CRM_Utils_Type::T_STRING,
);
$spec['help'] = array(
'title' => 'Help',
'description' => 'Optional extra help (html string)',
'type' => CRM_Utils_Type::T_STRING,
);
$spec['severity'] = array(
'title' => 'Severity',
'description' => 'Psr\Log\LogLevel string',
'type' => CRM_Utils_Type::T_STRING,
'options' => array_combine(CRM_Utils_Check::getSeverityList(), CRM_Utils_Check::getSeverityList()),
);
$spec['severity_id'] = array(
'title' => 'Severity ID',
'description' => 'Integer representation of Psr\Log\LogLevel',
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Utils_Check::getSeverityList(),
);
$spec['is_visible'] = array(
'title' => 'is visible',
'description' => '0 if message has been hidden by the user',
'type' => CRM_Utils_Type::T_BOOLEAN,
);
$spec['hidden_until'] = array(
'title' => 'Hidden_until',
'description' => 'When will hidden message be visible again?',
'type' => CRM_Utils_Type::T_DATE,
);
}
/**
* System Check API.
*
* @param array $params
*
* @return array
* API result descriptor; return items are alert codes/messages
* @see civicrm_api3_create_success
* @see civicrm_api3_create_error
* @throws API_Exception
*/
function civicrm_api3_system_check($params) {
// array(array('name'=> $, 'severity'=>$, ...))
$id = 1;
$returnValues = $fields = array();
_civicrm_api3_system_check_spec($fields);
// array(CRM_Utils_Check_Message)
$messages = CRM_Utils_Check::checkAll();
foreach ($messages as $msg) {
$returnValues[] = $msg->toArray() + array('id' => $id++);
}
return _civicrm_api3_basic_array_get('systemCheck', $params, $returnValues, "id", array_keys($fields));
}
/**
* Log entry to system log table.
*
* @param array $params
*
* @return array
*/
function civicrm_api3_system_log($params) {
$log = new CRM_Utils_SystemLogger();
// This part means fields with separate db storage are accepted as params which kind of seems more intuitive to me
// 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?
if (!isset($params['context'])) {
$params['context'] = array();
}
$specialFields = array('contact_id', 'hostname');
foreach ($specialFields as $specialField) {
if (isset($params[$specialField]) && !isset($params['context'])) {
$params['context'][$specialField] = $params[$specialField];
}
}
$returnValues = $log->log($params['level'], $params['message'], $params['context']);
return civicrm_api3_create_success($returnValues, $params, 'System', 'Log');
}
/**
* Metadata for log function.
*
* @param array $params
*/
function _civicrm_api3_system_log_spec(&$params) {
$params['level'] = array(
'title' => 'Log Level',
'description' => 'Log level as described in PSR3 (info, debug, warning etc)',
'type' => CRM_Utils_Type::T_STRING,
'api.required' => TRUE,
);
$params['message'] = array(
'title' => 'Log Message',
'description' => 'Standardised message string, you can also ',
'type' => CRM_Utils_Type::T_STRING,
'api.required' => TRUE,
);
$params['context'] = array(
'title' => 'Log Context',
'description' => 'An array of additional data to store.',
'type' => CRM_Utils_Type::T_LONGTEXT,
'api.default' => array(),
);
$params['contact_id'] = array(
'title' => 'Log Contact ID',
'description' => 'Optional ID of relevant contact',
'type' => CRM_Utils_Type::T_INT,
);
$params['hostname'] = array(
'title' => 'Log Hostname',
'description' => 'Optional name of host',
'type' => CRM_Utils_Type::T_STRING,
);
}
/**
* System.Get API.
*
* @param array $params
*
* @return array
*/
function civicrm_api3_system_get($params) {
$config = CRM_Core_Config::singleton();
$returnValues = array(
array(
'version' => CRM_Utils_System::version(), // deprecated in favor of civi.version
'uf' => CIVICRM_UF, // deprecated in favor of cms.type
'php' => array(
'version' => phpversion(),
'time' => time(),
'tz' => date_default_timezone_get(),
'sapi' => php_sapi_name(),
'extensions' => get_loaded_extensions(),
'ini' => _civicrm_api3_system_get_redacted_ini(),
),
'mysql' => array(
'version' => CRM_Core_DAO::singleValueQuery('SELECT @@version'),
'time' => CRM_Core_DAO::singleValueQuery('SELECT unix_timestamp()'),
'vars' => _civicrm_api3_system_get_redacted_mysql(),
),
'cms' => array(
'version' => $config->userSystem->getVersion(),
'type' => CIVICRM_UF,
'modules' => CRM_Core_Module::collectStatuses($config->userSystem->getModules()),
),
'civi' => array(
'version' => CRM_Utils_System::version(),
'dev' => (bool) CRM_Utils_System::isDevelopment(),
'components' => array_keys(CRM_Core_Component::getEnabledComponents()),
'extensions' => preg_grep(
'/^uninstalled$/',
CRM_Extension_System::singleton()->getManager()->getStatuses(),
PREG_GREP_INVERT
),
'multidomain' => CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_domain') > 1,
'settings' => _civicrm_api3_system_get_redacted_settings(),
'exampleUrl' => CRM_Utils_System::url('civicrm/example', NULL, TRUE, NULL, FALSE),
),
'http' => array(
'software' => CRM_Utils_Array::value('SERVER_SOFTWARE', $_SERVER),
'forwarded' => !empty($_SERVER['HTTP_X_FORWARDED_FOR']) || !empty($_SERVER['X_FORWARDED_PROTO']),
'port' => (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443) ? 'Standard' : 'Nonstandard',
),
'os' => array(
'type' => php_uname('s'),
'release' => php_uname('r'),
'version' => php_uname('v'),
'machine' => php_uname('m'),
),
),
);
return civicrm_api3_create_success($returnValues, $params, 'System', 'get');
}
/**
* Generate a sanitized/anonymized/redacted dump of the PHP configuration.
*
* Some INI fields contain site-identifying information (SII) -- e.g. URLs,
* hostnames, file paths, IP addresses, passwords, or free-form comments
* could be used to identify a site or gain access to its resources.
*
* A number of INI fields have been examined to determine whether they
* contain SII. Approved fields are put in a whitelist; all other fields
* are redacted.
*
* Redaction hides the substance of a field but does not completely omit
* all information. Consider the field 'mail.log' - setting this field
* has a functional effect (it enables or disables the logging behavior)
* and also points to particular file. Empty values (FALSE/NULL/0/"")
* will pass through redaction, but all other values will be replaced
* by a string (eg "REDACTED"). This roughly indicates whether the
* option is enabled/disabled without giving away its content.
*
* @return array
*/
function _civicrm_api3_system_get_redacted_ini() {
static $whitelist = NULL;
if ($whitelist === NULL) {
$whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/ini-whitelist.txt');
}
$inis = ini_get_all(NULL, FALSE);
$result = array();
foreach ($inis as $k => $v) {
if (empty($v) || in_array($k, $whitelist)) {
$result[$k] = $v;
}
else {
$result[$k] = 'REDACTED';
}
}
return $result;
}
/**
* Generate ae sanitized/anonymized/redacted dump of MySQL configuration.
*
* @return array
* @see _civicrm_api3_system_get_redacted_ini
*/
function _civicrm_api3_system_get_redacted_mysql() {
static $whitelist = NULL;
if ($whitelist === NULL) {
$whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/mysql-whitelist.txt');
}
$inis = ini_get_all(NULL, FALSE);
$result = array();
$dao = CRM_Core_DAO::executeQuery('SHOW VARIABLES');
while ($dao->fetch()) {
if (empty($dao->Variable_name) || in_array($dao->Variable_name, $whitelist)) {
$result[$dao->Variable_name] = $dao->Value;
}
else {
$result[$dao->Variable_name] = 'REDACTED';
}
}
return $result;
}
/**
* Get redacted settings.
*
* @return array
* @throws CiviCRM_API3_Exception
*/
function _civicrm_api3_system_get_redacted_settings() {
static $whitelist = NULL;
if ($whitelist === NULL) {
$whitelist = _civicrm_api3_system_get_whitelist(__DIR__ . '/System/setting-whitelist.txt');
}
$apiResult = civicrm_api3('Setting', 'get', array());
$result = array();
foreach ($apiResult['values'] as $settings) {
foreach ($settings as $key => $value) {
if (in_array($key, $whitelist)) {
$result[$key] = $value;
}
}
}
return $result;
}
/**
* Read a whitelist.
*
* @param string $whitelistFile
* Name of a file. Each line is a field name. Comments begin with "#".
* @return array
*/
function _civicrm_api3_system_get_whitelist($whitelistFile) {
$whitelist = array_filter(
explode("\n", file_get_contents($whitelistFile)),
function ($k) {
return !empty($k) && !preg_match('/^\s*#/', $k);
}
);
return $whitelist;
}
/**
* Update log table structures.
*
* This updates the engine type if defined in the hook and changes the field type
* for log_conn_id to reflect CRM-18193.
*/
function civicrm_api3_system_updatelogtables() {
$schema = new CRM_Logging_Schema();
$schema->updateLogTableSchema();
return civicrm_api3_create_success(1);
}
/**
* Update indexes.
*
* This adds any indexes that exist in the schema but not the database.
*/
function civicrm_api3_system_updateindexes() {
CRM_Core_BAO_SchemaHandler::createMissingIndices(CRM_Core_BAO_SchemaHandler::getMissingIndices(TRUE));
return civicrm_api3_create_success(1);
}
/**
* Creates missing log tables.
*
* CRM-20838 - This adds any missing log tables into the database.
*/
function civicrm_api3_system_createmissinglogtables() {
$schema = new CRM_Logging_Schema();
$missingLogTables = $schema->getMissingLogTables();
if (!empty($missingLogTables)) {
foreach ($missingLogTables as $tableName) {
$schema->fixSchemaDifferencesFor($tableName, NULL, FALSE);
}
}
return civicrm_api3_create_success(1);
}