*
* Generated from xml/schema/CRM/Contact/Group.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:49027c63bf6fd142e79220b39f84056d)
+ * (GenCodeChecksum:e40e779ac8e9bec5ea4d6c55f6f3b863)
*/
/**
'type' => CRM_Utils_Type::T_STRING,
'title' => ts('Group Title'),
'description' => ts('Name of Group.'),
- 'required' => TRUE,
'maxlength' => 255,
'size' => CRM_Utils_Type::HUGE,
'where' => 'civicrm_group.title',
* @throws \CiviCRM_API3_Exception
*/
public static function bulkSave($bulkParams, $defaults = []) {
- $addedColumns = $sql = $tables = $customFields = [];
+ $addedColumns = $sql = $customFields = [];
foreach ($bulkParams as $index => $fieldParams) {
$params = array_merge($defaults, $fieldParams);
$customField = self::createCustomFieldRecord($params);
if (!isset($params['custom_group_id'])) {
$params['custom_group_id'] = civicrm_api3('CustomField', 'getvalue', ['id' => $customField->id, 'return' => 'custom_group_id']);
}
- if (!isset($params['table_name'])) {
- if (!isset($tables[$params['custom_group_id']])) {
- $tables[$params['custom_group_id']] = civicrm_api3('CustomGroup', 'getvalue', [
- 'id' => $params['custom_group_id'],
- 'return' => 'table_name',
- ]);
- }
- $params['table_name'] = $tables[$params['custom_group_id']];
- }
- $sql[$params['table_name']][] = $fieldSQL;
- $addedColumns[$params['table_name']][] = $customField->name;
+ $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customField->custom_group_id, 'table_name');
+ $sql[$tableName][] = $fieldSQL;
+ $addedColumns[$tableName][] = $customField->name;
$customFields[$index] = $customField;
}
$logging->fixSchemaDifferencesFor($tableName, ['ADD' => $addedColumns[$tableName]]);
}
- Civi::service('sql_triggers')->rebuild($params['table_name'], TRUE);
+ Civi::service('sql_triggers')->rebuild($tableName, TRUE);
}
CRM_Utils_System::flushCache();
foreach ($customFields as $index => $customField) {
return $sql;
}
- /**
- * @deprecated
- *
- * @param array $params
- * @param bool $indexExist
- * @param bool $triggerRebuild
- *
- * @return bool
- */
- public static function alterFieldSQL($params, $indexExist = FALSE, $triggerRebuild = TRUE) {
- CRM_Core_Error::deprecatedFunctionWarning('function no longer in use / supported');
- // lets suppress the required flag, since that can cause sql issue
- $params['required'] = FALSE;
-
- $sql = self::buildFieldChangeSql($params, $indexExist);
-
- // CRM-7007: do not i18n-rewrite this query
- CRM_Core_DAO::executeQuery($sql, [], TRUE, NULL, FALSE, FALSE);
-
- $config = CRM_Core_Config::singleton();
- if ($config->logging) {
- // CRM-16717 not sure why this was originally limited to add.
- // For example custom tables can have field length changes - which need to flow through to logging.
- // Are there any modifies we DON'T was to call this function for (& shouldn't it be clever enough to cope?)
- if ($params['operation'] == 'add' || $params['operation'] == 'modify') {
- $logging = new CRM_Logging_Schema();
- $logging->fixSchemaDifferencesFor($params['table_name'], [trim(strtoupper($params['operation'])) => [$params['name']]]);
- }
- }
-
- if ($triggerRebuild) {
- Civi::service('sql_triggers')->rebuild($params['table_name'], TRUE);
- }
-
- return TRUE;
- }
-
/**
* Delete a CiviCRM-table.
*
'description' => "text COMMENT 'Optional description.'",
],
'civicrm_group' => [
- 'title' => "varchar(255) NOT NULL COMMENT 'Name of Group.'",
+ 'title' => "varchar(255) COMMENT 'Name of Group.'",
'frontend_title' => "varchar(255) DEFAULT NULL COMMENT 'Alternative public title for this Group.'",
'frontend_description' => "text DEFAULT NULL COMMENT 'Alternative public description of the group.'",
],
'civicrm_group' => [
'title' => [
'type' => "Text",
- 'required' => "true",
],
'frontend_title' => [
'type' => "Text",
*
* @param array $tables
* Array of tables to inspect.
+ * @param int $limit
+ * Limit result to x
+ * @param int $offset
+ * Offset result to y
*
* @return array
*/
- public function getAllChangesForConnection($tables) {
- $params = [1 => [$this->log_conn_id, 'String']];
+ public function getAllChangesForConnection($tables, $limit = 0, $offset = 0) {
+ $params = [
+ 1 => [$this->log_conn_id, 'String'],
+ 2 => [$limit, 'Integer'],
+ 3 => [$offset, 'Integer'],
+ ];
+
foreach ($tables as $table) {
if (empty($sql)) {
$sql = " SELECT '{$table}' as table_name, id FROM {$this->db}.log_{$table} WHERE log_conn_id = %1";
$sql .= " UNION SELECT '{$table}' as table_name, id FROM {$this->db}.log_{$table} WHERE log_conn_id = %1";
}
}
+ if ($limit) {
+ $sql .= " LIMIT %2";
+ }
+ if ($offset) {
+ $sql .= " OFFSET %3";
+ }
$diffs = [];
$dao = CRM_Core_DAO::executeQuery($sql, $params);
while ($dao->fetch()) {
if (empty($this->log_date)) {
- $this->log_date = CRM_Core_DAO::singleValueQuery("SELECT log_date FROM {$this->db}.log_{$table} WHERE log_conn_id = %1 LIMIT 1", $params);
+ // look for available table in above query instead of looking for last table. this will avoid multiple loops
+ $this->log_date = CRM_Core_DAO::singleValueQuery("SELECT log_date FROM {$this->db}.log_{$dao->table_name} WHERE log_conn_id = %1 LIMIT 1", $params);
}
$diffs = array_merge($diffs, $this->diffsInTableForId($dao->table_name, $dao->id));
}
return $diffs;
}
+ /**
+ * Get count of all changes made in the connection.
+ *
+ * @param array $tables
+ * Array of tables to inspect.
+ *
+ * @return array
+ */
+ public function getCountOfAllContactChangesForConnection($tables) {
+ $count = 0;
+ $params = [1 => [$this->log_conn_id, 'String']];
+ foreach ($tables as $table) {
+ if (empty($sql)) {
+ $sql = " SELECT '{$table}' as table_name, id FROM {$this->db}.log_{$table} WHERE log_conn_id = %1";
+ }
+ else {
+ $sql .= " UNION SELECT '{$table}' as table_name, id FROM {$this->db}.log_{$table} WHERE log_conn_id = %1";
+ }
+ }
+ $countSQL = " SELECT count(*) as countOfContacts FROM ({$sql}) count";
+ $count = CRM_Core_DAO::singleValueQuery($countSQL, $params);
+ return $count;
+ }
+
/**
* Check that the log record relates to a unique log id.
*
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
class CRM_Logging_ReportDetail extends CRM_Report_Form {
+
+ const ROW_COUNT_LIMIT = 50;
protected $cid;
/**
// populate $rows with only the differences between $changed and $original (skipping certain columns and NULL ↔ empty changes unless raw requested)
$skipped = ['id'];
+ $nRows = $rows = [];
foreach ($this->diffs as $diff) {
$table = $diff['table'];
if (empty($metadata[$table])) {
$to = '';
}
}
-
- $rows[] = ['field' => $field . " (id: {$diff['id']})", 'from' => $from, 'to' => $to];
+ // Rework the results to provide grouping based on the ID
+ // We don't need that field displayed so we will output empty
+ if ($field == 'Modified Date') {
+ $nRows[$diff['id']][] = ['field' => '', 'from' => $from, 'to' => $to];
+ }
+ else {
+ $nRows[$diff['id']][] = ['field' => $field . " (id: {$diff['id']})", 'from' => $from, 'to' => $to];
+ }
}
+ // Transform the output so that we can compact the changes into the proper amount of rows IF trData is holding more than 1 array
+ foreach ($nRows as $trData) {
+ if (count($trData) > 1) {
+ $keys = array_intersect(...array_map('array_keys', $trData));
+ $mergedRes = array_combine($keys, array_map(function ($key) use ($trData) {
+ // If more than 1 entry is found, we are assigning them as subarrays, then the tpls will be responsible for concatenating the results
+ return array_column($trData, $key);
+ }, $keys));
+ $rows[] = $mergedRes;
+ }
+ else {
+ // We always need the first row of that array
+ $rows[] = $trData[0];
+ }
+ }
return $rows;
}
* Calculate all the contact related diffs for the change.
*/
protected function calculateContactDiffs() {
+ $this->_rowsFound = $this->getCountOfAllContactChangesForConnection();
+ // Apply some limits before asking for all contact changes
+ $this->getLimit();
$this->diffs = $this->getAllContactChangesForConnection();
}
}
$this->setDiffer();
try {
- return $this->differ->getAllChangesForConnection($this->tables);
+ return $this->differ->getAllChangesForConnection($this->tables, $this->dblimit, $this->dboffset);
+ }
+ catch (CRM_Core_Exception $e) {
+ CRM_Core_Error::statusBounce($e->getMessage());
+ }
+ }
+
+ /**
+ * Get an count of contacts with changes.
+ *
+ * @return mixed
+ */
+ public function getCountOfAllContactChangesForConnection() {
+ if (empty($this->log_conn_id)) {
+ return [];
+ }
+ $this->setDiffer();
+ try {
+ return $this->differ->getCountOfAllContactChangesForConnection($this->tables);
}
catch (CRM_Core_Exception $e) {
- CRM_Core_Error::statusBounce(ts($e->getMessage()));
+ CRM_Core_Error::statusBounce($e->getMessage());
}
}
$this->altered_name = CRM_Utils_Request::retrieve('alteredName', 'String');
$this->altered_by = CRM_Utils_Request::retrieve('alteredBy', 'String');
$this->altered_by_id = CRM_Utils_Request::retrieve('alteredById', 'Integer');
+ $this->layout = CRM_Utils_Request::retrieve('layout', 'String');
+ }
+
+ /**
+ * Override to set limit
+ * @param int $rowCount
+ */
+ public function limit($rowCount = self::ROW_COUNT_LIMIT) {
+ parent::limit($rowCount);
+ }
+
+ /**
+ * Override to set pager with limit
+ * @param int $rowCount
+ */
+ public function setPager($rowCount = self::ROW_COUNT_LIMIT) {
+ // We should not be rendering the pager in overlay mode
+ if (!isset($this->layout)) {
+ $this->_dashBoardRowCount = $rowCount;
+ $this->_limit = TRUE;
+ parent::setPager($rowCount);
+ }
+ }
+
+ /**
+ * This is a function similar to limit, in fact we copied it as-is and removed
+ * some `set` statements
+ *
+ */
+ public function getLimit($rowCount = self::ROW_COUNT_LIMIT) {
+ if ($this->addPaging) {
+
+ $pageId = CRM_Utils_Request::retrieve('crmPID', 'Integer');
+
+ // @todo all http vars should be extracted in the preProcess
+ // - not randomly in the class
+ if (!$pageId && !empty($_POST)) {
+ if (isset($_POST['PagerBottomButton']) && isset($_POST['crmPID_B'])) {
+ $pageId = max((int) $_POST['crmPID_B'], 1);
+ }
+ elseif (isset($_POST['PagerTopButton']) && isset($_POST['crmPID'])) {
+ $pageId = max((int) $_POST['crmPID'], 1);
+ }
+ unset($_POST['crmPID_B'], $_POST['crmPID']);
+ }
+
+ $pageId = $pageId ? $pageId : 1;
+ $offset = ($pageId - 1) * $rowCount;
+
+ $offset = CRM_Utils_Type::escape($offset, 'Int');
+ $rowCount = CRM_Utils_Type::escape($rowCount, 'Int');
+ $this->_limit = " LIMIT $offset, $rowCount";
+ $this->dblimit = $rowCount;
+ $this->dboffset = $offset;
+ }
}
}
'civicrm_mail_settings', 'is_contact_creation_disabled_if_no_match', "TINYINT DEFAULT 0 NOT NULL COMMENT 'If this option is enabled, CiviCRM will not create new contacts when filing emails'");
}
+ public function upgrade_5_31_beta2($rev) {
+ $this->addTask('Restore null-ity of "civicrm_group.title" field', 'groupTitleRestore');
+ $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+ }
+
public static function enableEwaySingleExtension(CRM_Queue_TaskContext $ctx) {
$eWAYPaymentProcessorType = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_payment_processor_type WHERE class_name = 'Payment_eWAY'");
if ($eWAYPaymentProcessorType) {
return TRUE;
}
+ /**
+ * The prior task grouptitlefieldExpand went a bit too far in making the `title` NOT NULL.
+ *
+ * @link https://lab.civicrm.org/dev/translation/-/issues/58
+ * @param \CRM_Queue_TaskContext $ctx
+ * @return bool
+ */
+ public static function groupTitleRestore(CRM_Queue_TaskContext $ctx) {
+ $locales = CRM_Core_I18n::getMultilingual();
+ $queries = [];
+ if ($locales) {
+ foreach ($locales as $locale) {
+ $queries[] = "ALTER TABLE civicrm_group CHANGE `title_{$locale}` `title_{$locale}` varchar(255) DEFAULT NULL COMMENT 'Name of Group.'";
+ }
+ }
+ else {
+ $queries[] = "ALTER TABLE civicrm_group CHANGE `title` `title` varchar(255) DEFAULT NULL COMMENT 'Name of Group.'";
+ }
+ foreach ($queries as $query) {
+ CRM_Core_DAO::executeQuery($query, [], TRUE, NULL, FALSE, FALSE);
+ }
+ return TRUE;
+ }
+
}
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Upgrade logic for FiveThirtyThree */
+class CRM_Upgrade_Incremental_php_FiveThirtyThree extends CRM_Upgrade_Incremental_Base {
+
+ /**
+ * Compute any messages which should be displayed beforeupgrade.
+ *
+ * Note: This function is called iteratively for each upcoming
+ * revision to the database.
+ *
+ * @param string $preUpgradeMessage
+ * @param string $rev
+ * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
+ * @param null $currentVer
+ */
+ public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
+ // Example: Generate a pre-upgrade message.
+ // if ($rev == '5.12.34') {
+ // $preUpgradeMessage .= '<p>' . ts('A new permission, "%1", has been added. This permission is now used to control access to the Manage Tags screen.', array(1 => ts('manage tags'))) . '</p>';
+ // }
+ }
+
+ /**
+ * Compute any messages which should be displayed after upgrade.
+ *
+ * @param string $postUpgradeMessage
+ * alterable.
+ * @param string $rev
+ * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
+ */
+ public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
+ // Example: Generate a post-upgrade message.
+ // if ($rev == '5.12.34') {
+ // $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
+ // }
+ }
+
+ /*
+ * Important! All upgrade functions MUST add a 'runSql' task.
+ * Uncomment and use the following template for a new upgrade version
+ * (change the x in the function name):
+ */
+
+ // /**
+ // * Upgrade function.
+ // *
+ // * @param string $rev
+ // */
+ // public function upgrade_5_0_x($rev) {
+ // $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+ // $this->addTask('Do the foo change', 'taskFoo', ...);
+ // // Additional tasks here...
+ // // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
+ // // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
+ // }
+
+ // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
+ // return TRUE;
+ // }
+
+}
--- /dev/null
+{* file to handle db changes in 5.31.beta2 during upgrade *}
--- /dev/null
+{* file to handle db changes in 5.32.beta1 during upgrade *}
--- /dev/null
+{* file to handle db changes in 5.33.alpha1 during upgrade *}
$host = $db_config['server'];
}
if (empty($db_config['ssl_params'])) {
- $conn = @mysqli_connect($host, $db_config['username'], $db_config['password'], $db_config['database'], !empty($db_config['port']) ? $db_config['port'] : NULL);
+ $conn = @mysqli_connect($host, $db_config['username'], $db_config['password'], $db_config['database'], !empty($db_config['port']) ? $db_config['port'] : NULL, $db_config['socket'] ?? NULL);
}
else {
$conn = NULL;
$db_config['ssl_params']['capath'] ?? NULL,
$db_config['ssl_params']['cipher'] ?? NULL
);
- if (@mysqli_real_connect($init, $host, $db_config['username'], $db_config['password'], $db_config['database'], (!empty($db_config['port']) ? $db_config['port'] : NULL), NULL, MYSQLI_CLIENT_SSL)) {
+ if (@mysqli_real_connect($init, $host, $db_config['username'], $db_config['password'], $db_config['database'], (!empty($db_config['port']) ? $db_config['port'] : NULL), $db_config['socket'] ?? NULL, MYSQLI_CLIENT_SSL)) {
$conn = $init;
}
}
}
],
"description": "Composer plugin for downloading additional files within any composer package.",
- "time": "2020-11-02T05:26:23+00:00"
+ "time": "2020-11-02T04:00:42+00:00"
},
{
"name": "cweagans/composer-patches",
- "version": "1.6.5",
+ "version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/cweagans/composer-patches.git",
- "reference": "2ec4f00ff5fb64de584c8c4aea53bf9053ecb0b3"
+ "reference": "ae02121445ad75f4eaff800cc532b5e6233e2ddf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/2ec4f00ff5fb64de584c8c4aea53bf9053ecb0b3",
- "reference": "2ec4f00ff5fb64de584c8c4aea53bf9053ecb0b3",
+ "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/ae02121445ad75f4eaff800cc532b5e6233e2ddf",
+ "reference": "ae02121445ad75f4eaff800cc532b5e6233e2ddf",
"shasum": ""
},
"require": {
- "composer-plugin-api": "^1.0",
+ "composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3.0"
},
"require-dev": {
- "composer/composer": "~1.0",
+ "composer/composer": "~1.0 || ~2.0",
"phpunit/phpunit": "~4.6"
},
"type": "composer-plugin",
}
],
"description": "Provides a way to patch Composer packages.",
- "time": "2018-05-11T18:00:16+00:00"
+ "time": "2020-09-30T17:56:20+00:00"
},
{
"name": "dflydev/apache-mime-types",
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-04-12T14:33:46+00:00"
},
{
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-04-13T09:33:40+00:00"
},
{
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-03-15T09:38:08+00:00"
},
{
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-04-12T16:54:01+00:00"
},
{
"polyfill",
"portable"
],
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-05-12T16:14:59+00:00"
},
{
"portable",
"shim"
],
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-05-12T16:47:27+00:00"
},
{
"portable",
"shim"
],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
"time": "2020-05-12T16:47:27+00:00"
},
{
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
"time": "2020-04-12T14:33:46+00:00"
},
{
<p>Some (but not all) OAuth2 tokens are based on <a href="https://en.wikipedia.org/wiki/JSON_Web_Token">JWT</a>. If a token is based on JWT, then we can examine its content to learn more about what the token signifies. This may help with debugging token-access issues.</p>
- <h3>Token ID</h3>
+ <div af-api4-ctrl="tokens" af-api4="['OAuthSysToken', 'get', {'where': [['id', '=', routeParams.id]]}]"></div>
- <input ng-model="routeParams.id" type="text"/>
-
- <div class="btn-group">
- <a class="btn btn-default"
- af-api4-action="['OAuthSysToken', 'get', {where: [['id', '=', data.tokenId]]}]"
- af-api4-start-msg="ts('Fetching...')"
- af-api4-success-msg="ts('Fetched')"
- af-api4-success="data.token = response"
- >{{ts('Inspect')}}</a>
+ <div ng-if="tokens.result.length == 0">
+ No tokens found.
</div>
+ <div ng-repeat="token in tokens.result">
+
+ <h3>Token Record</h3>
- <div ng-if="!!data.token">
+ <pre>{{token|json}}</pre>
<h3>Access Token: Raw</h3>
- <pre>{{data.token[0].access_token}}</pre>
+ <pre>{{token.access_token}}</pre>
<h3>Access Token: JWT Payload</h3>
- <pre>{{data.token[0].access_token|unvalidatedJwtDecode|json}}</pre>
+ (This will only display meaningful data if the token is based on JWT.)
+
+ <pre>{{token.access_token|unvalidatedJwtDecode|json}}</pre>
</div>
* https://github.com/civicrm/civicrm-joomla
* https://github.com/civicrm/civicrm-wordpress
+## CiviCRM 5.32.0
+
+Released December 2, 2020
+
+- **[Synopsis](release-notes/5.32.0.md#synopsis)**
+- **[Features](release-notes/5.32.0.md#features)**
+- **[Bugs resolved](release-notes/5.32.0.md#bugs)**
+- **[Miscellany](release-notes/5.32.0.md#misc)**
+- **[Credits](release-notes/5.32.0.md#credits)**
+- **[Feedback](release-notes/5.32.0.md#feedback)**
+
## CiviCRM 5.31.0
Released November 4, 2020
--- /dev/null
+# CiviCRM 5.32.0
+
+Released December 2, 2020
+
+- **[Synopsis](#synopsis)**
+- **[Features](#features)**
+- **[Bugs resolved](#bugs)**
+- **[Miscellany](#misc)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?* | |
+|:--------------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities? | |
+| Change the database schema? | |
+| Alter the API? | |
+| Require attention to configuration options? | |
+| Fix problems installing or upgrading to a previous version? | |
+| Introduce features? | |
+| Fix bugs? | |
+
+## <a name="features"></a>Features
+
+### Core CiviCRM
+
+- **crm- Missing Summary ([18913](https://github.com/civicrm/civicrm-core/pull/18913))**
+
+- **CRM-5048 Missing Summary ([18859](https://github.com/civicrm/civicrm-core/pull/18859))**
+
+- **CRM-9362 Missing Summary ([18411](https://github.com/civicrm/civicrm-core/pull/18411))**
+
+- **CRM- Missing Summary ([115](https://github.com/civicrm/civicrm-backdrop/pull/115))**
+
+## <a name="bugs"></a>Bugs resolved
+
+### Core CiviCRM
+
+- **get log date from tables available in query with data instead of last table ([18868](https://github.com/civicrm/civicrm-core/pull/18868))**
+
+- **Adds performance improvement when browsing the report logs ([18851](https://github.com/civicrm/civicrm-core/pull/18851))**
+
+- **Schema handler fixes ([18932](https://github.com/civicrm/civicrm-core/pull/18932))**
+
+- **5.31.0 - Set version. Update notes. ([18933](https://github.com/civicrm/civicrm-core/pull/18933))**
+
+- **5.31 ([18931](https://github.com/civicrm/civicrm-core/pull/18931))**
+
+- **closes financial/#156: Set contribution status to refunded even if cancelled_payment_id is set ([18930](https://github.com/civicrm/civicrm-core/pull/18930))**
+
+- **dev/core#2166 - E_NOTICE when deleting mail account ([18927](https://github.com/civicrm/civicrm-core/pull/18927))**
+
+- **dev/mail#2141 - MailSettings - Add button+API for testing a connection ([18911](https://github.com/civicrm/civicrm-core/pull/18911))**
+
+- **5.31 to master ([18923](https://github.com/civicrm/civicrm-core/pull/18923))**
+
+- **Add UI metadata for payment_processor_id on financialTrxn ([18917](https://github.com/civicrm/civicrm-core/pull/18917))**
+
+- **dev/core#2139 fix defaulting for multi-select custom fields ([18907](https://github.com/civicrm/civicrm-core/pull/18907))**
+
+- **Search ext: Fix validation and saving on search admin screen ([18919](https://github.com/civicrm/civicrm-core/pull/18919))**
+
+- **dev/core#2141 - Add "oauth-client" extension (hidden) ([18914](https://github.com/civicrm/civicrm-core/pull/18914))**
+
+- **dev/core#2148 - Incorrect use of ts, quotes, escape in log call ([18864](https://github.com/civicrm/civicrm-core/pull/18864))**
+
+- **Use standard names for entity paths and add a few more paths ([18915](https://github.com/civicrm/civicrm-core/pull/18915))**
+
+- **CRM_Core_Error::formatFooException - Don't bomb on 'Error' ([18910](https://github.com/civicrm/civicrm-core/pull/18910))**
+
+- **Search ext: Add links to search admin and improve links in displays ([18909](https://github.com/civicrm/civicrm-core/pull/18909))**
+
+- **dev/core#2141 - composer.json - Require league/oauth2-{client,google} ([18908](https://github.com/civicrm/civicrm-core/pull/18908))**
+
+- **5.31 ([18904](https://github.com/civicrm/civicrm-core/pull/18904))**
+
+- **dev/core#2043 Remove instance of pass-by-ref ([18802](https://github.com/civicrm/civicrm-core/pull/18802))**
+
+- **Move call to update related pledges on contribution cancel to extension ([18894](https://github.com/civicrm/civicrm-core/pull/18894))**
+
+- **Remove IPN reference to _relatedObjects, deprecate property ([18895](https://github.com/civicrm/civicrm-core/pull/18895))**
+
+- **[Ref] Simplify params ([18896](https://github.com/civicrm/civicrm-core/pull/18896))**
+
+- **[REF] Simplify use of shared code. ([18900](https://github.com/civicrm/civicrm-core/pull/18900))**
+
+- **Remove deprecated code ([18903](https://github.com/civicrm/civicrm-core/pull/18903))**
+
+- **Add postProcess hook to MessageTemplates ([18807](https://github.com/civicrm/civicrm-core/pull/18807))**
+
+- **[REF] Remove silly if ([18897](https://github.com/civicrm/civicrm-core/pull/18897))**
+
+- **dev/core#2141 - Add hook_civicrm_alterMailStore ([18902](https://github.com/civicrm/civicrm-core/pull/18902))**
+
+- **[Ref] Move sending the email back out of the recur function ([18852](https://github.com/civicrm/civicrm-core/pull/18852))**
+
+- **5.31 to master ([18893](https://github.com/civicrm/civicrm-core/pull/18893))**
+
+- **dev/core#927 Move handling of participant.cancel from BaseIPN to contributioncancelactions ([18881](https://github.com/civicrm/civicrm-core/pull/18881))**
+
+- **[Ref] Use direct version of participant id ([18882](https://github.com/civicrm/civicrm-core/pull/18882))**
+
+- **Hack away at false negative test fails ([18892](https://github.com/civicrm/civicrm-core/pull/18892))**
+
+- **5.31 ([18891](https://github.com/civicrm/civicrm-core/pull/18891))**
+
+- **Add entity paths to schema & APIv4 ([18887](https://github.com/civicrm/civicrm-core/pull/18887))**
+
+- **Lotsa new features for the Search Kit extension ([18876](https://github.com/civicrm/civicrm-core/pull/18876))**
+
+- **Deprecate hook_civicrm_crudLink ([18888](https://github.com/civicrm/civicrm-core/pull/18888))**
+
+- **dev/core#2141 - "Add Mail Account" - Allow hookable listing of setup links ([18885](https://github.com/civicrm/civicrm-core/pull/18885))**
+
+- **(NFC) Fix typo in Money valueFormat depretation warning ([18886](https://github.com/civicrm/civicrm-core/pull/18886))**
+
+- **/dev/core#2152: Merge contacts keep case roles ([18884](https://github.com/civicrm/civicrm-core/pull/18884))**
+
+- **Remove always-true & otherwise silly if ([18883](https://github.com/civicrm/civicrm-core/pull/18883))**
+
+- **Fix extension generated DAO files to pass civilint ([18879](https://github.com/civicrm/civicrm-core/pull/18879))**
+
+- **Merge branch 5.31 into master ([18875](https://github.com/civicrm/civicrm-core/pull/18875))**
+
+- **Participant Calculate/Fees: fix ts usage, simplify wording ([18874](https://github.com/civicrm/civicrm-core/pull/18874))**
+
+- **dev/core#1879 Fix inconsistent ability to view event information ([18712](https://github.com/civicrm/civicrm-core/pull/18712))**
+
+- **Show only Active SMS provider List on Mass SMS form ([18867](https://github.com/civicrm/civicrm-core/pull/18867))**
+
+- **dev/core#2150 Re-enact the recapture validation by validating the res… ([18872](https://github.com/civicrm/civicrm-core/pull/18872))**
+
+- **APIv4 - Add `$result->single()` helper ([18871](https://github.com/civicrm/civicrm-core/pull/18871))**
+
+- **ClassLoader - Fix autoloading of `API_Exception` ([18870](https://github.com/civicrm/civicrm-core/pull/18870))**
+
+- **Refactor entityParams in Order.Create API so it is easier to understand/modify ([18306](https://github.com/civicrm/civicrm-core/pull/18306))**
+
+- **(core/dev#2104) Add gender column for target contact to activity report ([18840](https://github.com/civicrm/civicrm-core/pull/18840))**
+
+- **dev/core#927 Move cancelling of related memberships to extension from BaseIPN ([18853](https://github.com/civicrm/civicrm-core/pull/18853))**
+
+- **Move filtering of unpermitted options for reports/ search select to financialacl extension ([18849](https://github.com/civicrm/civicrm-core/pull/18849))**
+
+- **dev/core#2146 - Long unicode contact names get truncated badly causing a crash ([18862](https://github.com/civicrm/civicrm-core/pull/18862))**
+
+- **APIv4 - Fix type coersion of non-string input ([18860](https://github.com/civicrm/civicrm-core/pull/18860))**
+
+- **Remove meaningless legacy code ([18856](https://github.com/civicrm/civicrm-core/pull/18856))**
+
+- **5.31 ([18861](https://github.com/civicrm/civicrm-core/pull/18861))**
+
+- **Fix campaign_id handling for batch entry ([18792](https://github.com/civicrm/civicrm-core/pull/18792))**
+
+- **Set id after save for the mailing component in the postProcess ([18808](https://github.com/civicrm/civicrm-core/pull/18808))**
+
+- **Move CRM_Member_BAO_MembershipType::getPermissionedMembershipTypes to financial acl extension ([18848](https://github.com/civicrm/civicrm-core/pull/18848))**
+
+- **backdrop#116 Override sessionStart function and use backdrop function… ([18745](https://github.com/civicrm/civicrm-core/pull/18745))**
+
+- **Get phone_type by name. dev/core#2138 ([18842](https://github.com/civicrm/civicrm-core/pull/18842))**
+
+- **dev/user-interface#34 Replace <th> with <td> on ContributionPage configuration Amount tab ([18850](https://github.com/civicrm/civicrm-core/pull/18850))**
+
+- **dev/financial#152 [REF] Clean up interaction with contribution recur object ([18835](https://github.com/civicrm/civicrm-core/pull/18835))**
+
+- **dev/core#927 preliminary cleanup ([18813](https://github.com/civicrm/civicrm-core/pull/18813))**
+
+- **dev/core#2029 exclude ornery test ([18846](https://github.com/civicrm/civicrm-core/pull/18846))**
+
+- **[REF] Determine values where they are needed rather than passing them around (in tested function) ([18837](https://github.com/civicrm/civicrm-core/pull/18837))**
+
+- **5.31 to master ([18847](https://github.com/civicrm/civicrm-core/pull/18847))**
+
+- **dev/core#2140 Fix site path for Drupal 8 and 9 ([18843](https://github.com/civicrm/civicrm-core/pull/18843))**
+
+- **5.31 ([18839](https://github.com/civicrm/civicrm-core/pull/18839))**
+
+- **5.31 ([18836](https://github.com/civicrm/civicrm-core/pull/18836))**
+
+- **[REF] Minor extraction ([18829](https://github.com/civicrm/civicrm-core/pull/18829))**
+
+- **Remove a few lines of deprecated code ([18826](https://github.com/civicrm/civicrm-core/pull/18826))**
+
+- **(core/dev#2104) Add birth date column for target contact to activity … ([18827](https://github.com/civicrm/civicrm-core/pull/18827))**
+
+- **[REF] Include contributioncancelactions extension in dismaker and reg… ([18825](https://github.com/civicrm/civicrm-core/pull/18825))**
+
+- **dev/core#927 Remove code to update recur on cancel & fail where there is no recur ([18814](https://github.com/civicrm/civicrm-core/pull/18814))**
+
+- **[REF] Extract handling for loading contribution recur object. ([18746](https://github.com/civicrm/civicrm-core/pull/18746))**
+
+- **5.31 ([18818](https://github.com/civicrm/civicrm-core/pull/18818))**
+
+- **(NFC) dev/core#2029 - Make assertions in PrevNextTest more skimmable ([18822](https://github.com/civicrm/civicrm-core/pull/18822))**
+
+- **dev/core#2115 Move some more financialacl code to a hook within the extension ([18740](https://github.com/civicrm/civicrm-core/pull/18740))**
+
+- **dev/financial#152 move code only relevant to repeattransaction into that function ([18815](https://github.com/civicrm/civicrm-core/pull/18815))**
+
+- **dev/core#927 Enable contribution cancel actions extension ([18812](https://github.com/civicrm/civicrm-core/pull/18812))**
+
+- **Rationalise date formatting ([18805](https://github.com/civicrm/civicrm-core/pull/18805))**
+
+- **SavedSearch: add UI_name index to upgrade script ([18811](https://github.com/civicrm/civicrm-core/pull/18811))**
+
+- **dev/core#927 add first test on cancel ([18786](https://github.com/civicrm/civicrm-core/pull/18786))**
+
+- **Update CRM_Utils_Constant::value to support env variables ([18806](https://github.com/civicrm/civicrm-core/pull/18806))**
+
+- **Declare support for cancelRecurring in manual processor ([18804](https://github.com/civicrm/civicrm-core/pull/18804))**
+
+- **Remove always-true IF ([18803](https://github.com/civicrm/civicrm-core/pull/18803))**
+
+- **dev/core#927 Add shell extension to move contribution cancel actions into ([18784](https://github.com/civicrm/civicrm-core/pull/18784))**
+
+- **SavedSearch - Add name and label columns ([18809](https://github.com/civicrm/civicrm-core/pull/18809))**
+
+- **Display public title and description on profiles and unsubscribe/subs… ([18645](https://github.com/civicrm/civicrm-core/pull/18645))**
+
+- **Remove always true if ([18801](https://github.com/civicrm/civicrm-core/pull/18801))**
+
+- **Add test for recurring links and clean up method of retrieving recurring ([18790](https://github.com/civicrm/civicrm-core/pull/18790))**
+
+- **Replace BAO calls with api calls in test class ([18798](https://github.com/civicrm/civicrm-core/pull/18798))**
+
+- **Switch to calling api ([18797](https://github.com/civicrm/civicrm-core/pull/18797))**
+
+- **Switch to calling the api ([18796](https://github.com/civicrm/civicrm-core/pull/18796))**
+
+- **unit test for #18306 - order create api test for contribution ([18785](https://github.com/civicrm/civicrm-core/pull/18785))**
+
+- **Fix sendconfirmation api to override receipt params ([18789](https://github.com/civicrm/civicrm-core/pull/18789))**
+
+- **[Test] - Fix some tests to call API not BAO ([18795](https://github.com/civicrm/civicrm-core/pull/18795))**
+
+- **Remove instances of variable variables ([18791](https://github.com/civicrm/civicrm-core/pull/18791))**
+
+- **[Ref] Minor code extraction ([18739](https://github.com/civicrm/civicrm-core/pull/18739))**
+
+- **5.31 ([18788](https://github.com/civicrm/civicrm-core/pull/18788))**
+
+- **dev/core#2034 Fix paypal standard cancel url ([18540](https://github.com/civicrm/civicrm-core/pull/18540))**
+
+- **dev/core#2066 Use shared function to set the next url ([18773](https://github.com/civicrm/civicrm-core/pull/18773))**
+
+- **dev/core#2066 Further cleanup on search actions ([18783](https://github.com/civicrm/civicrm-core/pull/18783))**
+
+- **Contribution confirmation page should not display the name of payment processor type ([17568](https://github.com/civicrm/civicrm-core/pull/17568))**
+
+- **Fix pluralize function for words like 'display' ([18778](https://github.com/civicrm/civicrm-core/pull/18778))**
+
+- **5.31 ([18777](https://github.com/civicrm/civicrm-core/pull/18777))**
+
+- **[REF] Search ext: Reorganize code into modules ([18775](https://github.com/civicrm/civicrm-core/pull/18775))**
+
+- **class.api.php: In remote api calls, allow referer and useragent to be set. ([18400](https://github.com/civicrm/civicrm-core/pull/18400))**
+
+- **5.31 to master ([18774](https://github.com/civicrm/civicrm-core/pull/18774))**
+
+- **Test for event#43 ([18761](https://github.com/civicrm/civicrm-core/pull/18761))**
+
+- **5.31 ([18770](https://github.com/civicrm/civicrm-core/pull/18770))**
+
+- **dev/core#2066 Extract getSelectedIDs ([18768](https://github.com/civicrm/civicrm-core/pull/18768))**
+
+- **dev/core#2066 Use shared function to set the next url ([18767](https://github.com/civicrm/civicrm-core/pull/18767))**
+
+- **Allow custom fields of type Autocomplete-Select to be multivalued ([18449](https://github.com/civicrm/civicrm-core/pull/18449))**
+
+- **5.31 ([18764](https://github.com/civicrm/civicrm-core/pull/18764))**
+
+- **dev/drupal#137 - Alternate PR - On drupal status report need different check when civi is already installed ([18581](https://github.com/civicrm/civicrm-core/pull/18581))**
+
+- **Typo in call to fixSchemaDifferencesForAll ([18762](https://github.com/civicrm/civicrm-core/pull/18762))**
+
+- **5.31 ([18757](https://github.com/civicrm/civicrm-core/pull/18757))**
+
+- **Angular Loader: Allow modules to specify permissions to add client-side ([18754](https://github.com/civicrm/civicrm-core/pull/18754))**
+
+- **5.31 to master ([18756](https://github.com/civicrm/civicrm-core/pull/18756))**
+
+- **Extract setNextUrl ([18750](https://github.com/civicrm/civicrm-core/pull/18750))**
+
+- **crmMailing - Only load Angular settings if they're needed ([18749](https://github.com/civicrm/civicrm-core/pull/18749))**
+
+- **AngularLoader: Support 'settingsFactory' callbacks in angular modules. ([18731](https://github.com/civicrm/civicrm-core/pull/18731))**
+
+- **[REF] Replace long if block with early return ([18747](https://github.com/civicrm/civicrm-core/pull/18747))**
+
+- **dev/financial#152 simplify passed parameters ([18744](https://github.com/civicrm/civicrm-core/pull/18744))**
+
+- **More accurate language around social media sharing ([18743](https://github.com/civicrm/civicrm-core/pull/18743))**
+
+- **Fix main contact uf url on merge screen ([18742](https://github.com/civicrm/civicrm-core/pull/18742))**
+
+- **dev/core#2115 remove reference to financialACLs in bounce ([18738](https://github.com/civicrm/civicrm-core/pull/18738))**
+
+- **dev/financial#152 simplify interaction with membership, deprecate function ([18735](https://github.com/civicrm/civicrm-core/pull/18735))**
+
+- **dev/financial#152 simplify passed parameters ([18736](https://github.com/civicrm/civicrm-core/pull/18736))**
+
+- **dev/core#2079 Eliminate unused query on CRM_Core_BAO_CustomQuery::_construct ([18668](https://github.com/civicrm/civicrm-core/pull/18668))**
+
+- **[REF] Separate export form classes out & simplify task handling ([18589](https://github.com/civicrm/civicrm-core/pull/18589))**
+
+- **dev/core#2047 Fix merge code so that deleted contacts are not left without a primary address ([18555](https://github.com/civicrm/civicrm-core/pull/18555))**
+
+- **dev/financial#152 remove unused parameter ([18737](https://github.com/civicrm/civicrm-core/pull/18737))**
+
+- **[REF] Minor simplification - don't use a variable for table name ([18651](https://github.com/civicrm/civicrm-core/pull/18651))**
+
+- **dev/financial#152 Pass contribution directly to completeOrder ([18728](https://github.com/civicrm/civicrm-core/pull/18728))**
+
+- **dev/financial#152 [REF] Extract getMembershipID ([18733](https://github.com/civicrm/civicrm-core/pull/18733))**
+
+- **dev/financial#152 Remove unreachable code ([18734](https://github.com/civicrm/civicrm-core/pull/18734))**
+
+- **[Test] Ensure all APIv4 entities have basic info ([18727](https://github.com/civicrm/civicrm-core/pull/18727))**
+
+- **dev/financial#152 Remove unused parameters from BaseIPN->failed signature ([18732](https://github.com/civicrm/civicrm-core/pull/18732))**
+
+- **dev/financial#152 Remove unused parameters from BaseIPN->cancelled signature ([18730](https://github.com/civicrm/civicrm-core/pull/18730))**
+
+- **dev/financial#152 Clean up & test contributionPageID handling ([18729](https://github.com/civicrm/civicrm-core/pull/18729))**
+
+- **dev/core#2110 - Warning "Non-static method CRM_Contact_Page_AJAX::pdfFormat() should not be called statically" when changing the page format on print/merge document ([18726](https://github.com/civicrm/civicrm-core/pull/18726))**
+
+- **dev/financial#152 [REF] Parse ids before sending to single function (minor simplification) ([18631](https://github.com/civicrm/civicrm-core/pull/18631))**
+
+- **dev/financial#152 [REF] Parse ids before sending to recur function (minor simplification) ([18629](https://github.com/civicrm/civicrm-core/pull/18629))**
+
+- **dev/cloud-native#16 Migrate Contribution Page widget extern url to us… ([17969](https://github.com/civicrm/civicrm-core/pull/17969))**
+
+- **5.31 ([18725](https://github.com/civicrm/civicrm-core/pull/18725))**
+
+- **dev/core#1428 Add test for Activity::update() ([18720](https://github.com/civicrm/civicrm-core/pull/18720))**
+
+- **dev/financial#11 Expand unit test to ensure that the correct currency… ([18715](https://github.com/civicrm/civicrm-core/pull/18715))**
+
+- **Financial#111: Contribution tokens always display amount with default… ([18714](https://github.com/civicrm/civicrm-core/pull/18714))**
+
+- **[REF] Upgrade DomPDF to v0.8.6 ([18688](https://github.com/civicrm/civicrm-core/pull/18688))**
+
+- **Protect against undefined index query in heartbeat callback ([220](https://github.com/civicrm/civicrm-wordpress/pull/220))**
+
+- **(dev/joomla#14) Joomla 4.0 compatibility fixes ([52](https://github.com/civicrm/civicrm-joomla/pull/52))**
+
+- **dev/core#2150 Update checking of response function to work with v2 api ([311](https://github.com/civicrm/civicrm-packages/pull/311))**
+
+## <a name="misc"></a>Miscellany
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following code authors:
+
+AGH Strategies - Alice Frumin, Andrew Hunt; Agileware - Francis Whittle, Justin Freeman, Pengyi Zhang; Andrew Thompson; Christian Wach; Circle Interactive - Pradeep Nayak; CiviCoop - Jaap Jansma; CiviCRM - Coleman Watts, Tim Otten; CiviDesk - Sunil Pawar, Yashodha Chaku; CiviFirst - John Kirk; CompuCorp - Debarshi Bhaumik; Coop SymbioTIC - Mathieu Lutfy; Dave D; Diego Muñio; Freeform Solutions - Herb van den Dool; Fuzion - Jitendra Purohit; iXiam - Luciano Spiegel, Vangelis Pantazis; JMA Consulting - Monish Deb, Seamus Lee; John Kingsnorth; masetto; Megaphone Technology Consulting - Jon Goldberg; mglaman; MJW Consulting - Matthew Wire; Nicol Wistreich; Progressive Technology Project - Jamie McClelland; Richard van Oosterhout; Squiffle Consulting - Aidan Saunders; Wikimedia Foundation - Eileen McNaughton
+
+Most authors also reviewed code for this release; in addition, the following
+reviewers contributed their comments:
+
+AGH Strategies - Alice Frumin; Agileware - Justin Freeman; Andrew Thompson; Artful Robot - Rich Lott; Australian Greens - John Twyman; Circle Interactive - Pradeep Nayak; civibot[bot]; civicrm-builder; CiviCRM - Coleman Watts, Tim Otten; CiviDesk - Sunil Pawar, Yashodha Chaku; Coop SymbioTIC - Mathieu Lutfy; Dave D; Diego Muñio; Freeform Solutions - Herb van den Dool; Fuzion - Jitendra Purohit, Luke Stewart; Greenpeace Central and Eastern Europe - Patrick Figel; iXiam - Vangelis Pantazis; JMA Consulting - Joe Murray, Monish Deb, Seamus Lee; jvos; Lighthouse Consulting and Design - Brian Shaughnessy; masetto; maxtsero; Megaphone Technology Consulting - Jon Goldberg; mglaman; MJCO - Mikey O'Toole; MJW Consulting - Matthew Wire; Nicol Wistreich; Semper IT - Karin Gerritsen; Tadpole Collective - Kevin Cristiano; Wikimedia Foundation - Eileen McNaughton
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Alice Frumin and Andrew Hunt. If you'd like
+to provide feedback on them, please log in to https://chat.civicrm.org/civicrm
+and contact `@agh1`.
<p><?php echo ts('By default, CiviCRM uses the same database as your website. You may install on a separate database if you need more fine-grained control over permissions, replication, hardware capacity, etc.'); ?></p>
<p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@localhost/civicrm')); ?></p>
<p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@127.0.0.1:3306/otherdb')); ?></p>
+ <p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@unix(/var/lib/mysql/mysql.sock)/otherdb')); ?></p>
</div>
</td>
</tr>
_corereqadapter_addMessages($e, 'system', $systemMsgs);
\Civi\Setup::log()->info(sprintf('[%s] Run Requirements::checkDatabase()', basename(__FILE__)));
- list ($host, $port) = \Civi\Setup\DbUtil::decodeHostPort($model->db['server']);
+ list ($host, $port, $socket) = \Civi\Setup\DbUtil::decodeHostPort($model->db['server']);
$dbMsgs = $r->checkDatabase(array(
'host' => $host,
'port' => $port,
+ 'socket' => $socket,
'username' => $model->db['username'],
'password' => $model->db['password'],
'database' => $model->db['database'],
// Compute DSN.
global $databases;
$ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($databases['default']['default']);
+ // @todo Does Backdrop support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
$model->db = $model->cmsDb = array(
'server' => \Civi\Setup\DbUtil::encodeHostPort($databases['default']['default']['host'], $databases['default']['default']['port'] ?: NULL),
'username' => $databases['default']['default']['username'],
// Compute DSN.
global $databases;
$ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($databases['default']['default']);
+ // @todo Does Drupal support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
$model->db = $model->cmsDb = array(
'server' => \Civi\Setup\DbUtil::encodeHostPort($databases['default']['default']['host'], $databases['default']['default']['port'] ?: NULL),
'username' => $databases['default']['default']['username'],
// Compute DSN.
$connectionOptions = \Drupal::database()->getConnectionOptions();
$ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($connectionOptions);
+ // @todo Does Drupal support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
$model->db = $model->cmsDb = array(
'server' => \Civi\Setup\DbUtil::encodeHostPort($connectionOptions['host'], $connectionOptions['port'] ?: NULL),
'username' => $connectionOptions['username'],
$model->templateCompilePath = implode(DIRECTORY_SEPARATOR, [$uploadDir['basedir'], 'civicrm', 'templates_c']);
// Compute DSN.
+ list(/*$host*/, /*$port*/, $socket) = Civi\Setup\DbUtil::decodeHostPort(DB_HOST);
$model->db = $model->cmsDb = array(
- 'server' => DB_HOST,
+ 'server' => $socket ? sprintf('unix(%s)', $socket) : DB_HOST,
'username' => DB_USER,
'password' => DB_PASSWORD,
'database' => DB_NAME,
*/
public static function parseDsn($dsn) {
$parsed = parse_url($dsn);
+ // parse_url parses 'mysql://admin:secret@unix(/var/lib/mysql/mysql.sock)/otherdb' like:
+ // [
+ // 'host' => 'unix(',
+ // 'path' => '/var/lib/mysql/mysql.sock)/otherdb',
+ // ...
+ // ]
+ if ($parsed['host'] == 'unix(') {
+ preg_match('/(unix\(.*\))(\/(.+)?)?$/', $dsn, $matches);
+ $server = $matches[1];
+ $database = $matches[3] ?? NULL;
+ }
+ else {
+ $server = self::encodeHostPort($parsed['host'], $parsed['port'] ?? NULL);
+ $database = $parsed['path'] ? ltrim($parsed['path'], '/') : NULL;
+ }
+
return array(
- 'server' => self::encodeHostPort($parsed['host'], $parsed['port'] ?? NULL),
+ 'server' => $server,
'username' => $parsed['user'] ?: NULL,
'password' => $parsed['pass'] ?: NULL,
- 'database' => $parsed['path'] ? ltrim($parsed['path'], '/') : NULL,
+ 'database' => $database,
'ssl_params' => self::parseSSL($parsed['query'] ?? NULL),
);
}
* @return \mysqli
*/
public static function softConnect($db) {
- list($host, $port) = self::decodeHostPort($db['server']);
+ list($host, $port, $socket) = self::decodeHostPort($db['server']);
if (empty($db['ssl_params'])) {
- $conn = @mysqli_connect($host, $db['username'], $db['password'], $db['database'], $port);
+ $conn = @mysqli_connect($host, $db['username'], $db['password'], $db['database'], $port, $socket);
}
else {
$conn = NULL;
$db['ssl_params']['capath'] ?? NULL,
$db['ssl_params']['cipher'] ?? NULL
);
- // @todo socket parameter, but if you're using sockets do you need SSL?
- if (@mysqli_real_connect($init, $host, $db['username'], $db['password'], $db['database'], $port, NULL, MYSQLI_CLIENT_SSL)) {
+ if (@mysqli_real_connect($init, $host, $db['username'], $db['password'], $db['database'], $port, $socket, MYSQLI_CLIENT_SSL)) {
$conn = $init;
}
}
* Ex: '127.0.0.1:123'
* Ex: '[1234:abcd]'
* Ex: '[1234:abcd]:123'
+ * Ex: 'localhost:/path/to/socket.sock
+ * Ex: 'unix(/path/to/socket.sock)
* @return array
- * Combination: [0 => string $host, 1 => numeric|NULL $port].
- * Ex: ['localhost', NULL].
- * Ex: ['127.0.0.1', 3306]
+ * Combination: [0 => string $host, 1 => numeric|NULL $port, 2 => string|NULL].
+ * Ex: ['localhost', NULL, NULL].
+ * Ex: ['127.0.0.1', 3306, NULL]
*/
public static function decodeHostPort($host) {
- $hostParts = explode(':', $host);
- if (count($hostParts) > 1 && strrpos($host, ']') !== strlen($host) - 1) {
- $port = array_pop($hostParts);
- $host = implode(':', $hostParts);
+ $port = NULL;
+ $socket = NULL;
+ if (preg_match('/^unix\(([^)]+)\)$/', $host, $matches) === 1) {
+ $host = 'localhost';
+ $socket = $matches[1];
}
else {
- $port = NULL;
+ $hostParts = explode(':', $host);
+ if (count($hostParts) > 1 && strrpos($host, ']') !== strlen($host) - 1) {
+ $portOrSocket = array_pop($hostParts);
+ if (substr($portOrSocket, /*start*/ 0, /*length*/ 1) == '/') {
+ $socket = $portOrSocket;
+ }
+ else {
+ $port = $portOrSocket;
+ }
+ $host = implode(':', $hostParts);
+ }
}
- return array($host, $port);
+ return array($host, $port, $socket);
}
/**
LOCK TABLES `civicrm_domain` WRITE;
/*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */;
-INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.32.alpha1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
+INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.33.alpha1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
/*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
UNLOCK TABLES;
VALUES
( @domainID, CONCAT('civicrm/report/instance/', @instanceID,'&reset=1'), 'Mailing Detail Report', 'Mailing Detail Report', 'administer CiviMail', 'OR', @reportlastID, '1', NULL, @instanceID+2 );
UPDATE civicrm_report_instance SET navigation_id = LAST_INSERT_ID() WHERE id = @instanceID;
-UPDATE civicrm_domain SET version = '5.32.alpha1';
+UPDATE civicrm_domain SET version = '5.33.alpha1';
<div class="block-crm crm-container">
<form method="post" id="id_fulltext_search">
<div style="margin-bottom: 8px;">
- <input type="text" name="text" id='text' value="" class="crm-form-text" style="width: 10em;" /> <button type="submit" name="submit" id="fulltext_submit" class="crm-button crm-form-submit" onclick='submitForm();'>{ts}Go{/ts}</button>
+ <input type="text" name="text" id='text' value="" class="crm-form-text" />
<input type="hidden" name="qfKey" value="{crmKey name='CRM_Contact_Controller_Search' addSequence=1}" />
</div>
<select class="form-select" id="fulltext_table" name="fulltext_table">
<option value="Membership">{ts}Memberships{/ts}</option>
{/if}
</select> {help id="id-fullText" file="CRM/Contact/Form/Search/Custom/FullText.hlp"}
+ <div class="crm-submit-buttons"><button type="submit" name="submit" id="fulltext_submit" class="crm-button crm-form-submit" onclick='submitForm();'>{ts}Search{/ts}</button></div>
</form>
</div>
<a title="{$row.$fieldHover|escape}" href="{$row.$fieldLink}" {$row.$fieldClass}>
{/if}
- {if $row.$field eq 'Subtotal'}
+ {if is_array($row.$field)}
+ {foreach from=$row.$field item=fieldrow key=fieldid}
+ <div class="crm-report-{$field}-row-{$fieldid}">{$fieldrow}</div>
+ {/foreach}
+ {elseif $row.$field eq 'Subtotal'}
{$row.$field}
{elseif $header.type & 4 OR $header.type & 256}
{if $header.group_by eq 'MONTH' or $header.group_by eq 'QUARTER'}
<a title="{$row.$fieldHover|escape}" href="{$row.$fieldLink}" {if $row.$fieldClass} class="{$row.$fieldClass}"{/if}>
{/if}
- {if $row.$field eq 'Subtotal'}
+ {if is_array($row.$field)}
+ {foreach from=$row.$field item=fieldrow key=fieldid}
+ <div class="crm-report-{$field}-row-{$fieldid}">{$fieldrow}</div>
+ {/foreach}
+ {elseif $row.$field eq 'Subtotal'}
{$row.$field}
{elseif $header.type & 4 OR $header.type & 256}
{if $header.group_by eq 'MONTH' or $header.group_by eq 'QUARTER'}
<title>Group Title</title>
<length>255</length>
<localizable>true</localizable>
- <required>true</required>
<comment>Name of Group.</comment>
<add>1.1</add>
<html>
<?xml version="1.0" encoding="iso-8859-1" ?>
<version>
- <version_no>5.32.alpha1</version_no>
+ <version_no>5.33.alpha1</version_no>
</version>