Switches api v3 and v4 to use that method so they are upgrade-safe by default.
return $result;
}
+ /**
+ * Returns all usable fields, indexed by name.
+ *
+ * This function differs from fields() in that it indexes by name rather than unique_name.
+ *
+ * It excludes fields not added yet by pending upgrades.
+ * This avoids problems with trying to SELECT a field that exists in code but has not yet been added to the db.
+ *
+ * @param bool $checkPermissions
+ * Filter by field permissions.
+ * @return array
+ */
+ public static function getSupportedFields($checkPermissions = FALSE) {
+ $fields = array_column((array) static::fields(), NULL, 'name');
+
+ // Exclude fields yet not added by pending upgrades
+ $dbVer = \CRM_Core_BAO_Domain::version();
+ if ($fields && version_compare($dbVer, \CRM_Utils_System::version()) < 0) {
+ $fields = array_filter($fields, function($field) use ($dbVer) {
+ $add = $field['add'] ?? '1.0.0';
+ if (substr_count($add, '.') < 2) {
+ $add .= '.alpha1';
+ }
+ return version_compare($dbVer, $add, '>=');
+ });
+ }
+
+ // Exclude fields the user does not have permission for
+ if ($checkPermissions) {
+ $fields = array_filter($fields, function($field) {
+ return empty($field['permission']) || CRM_Core_Permission::check($field['permission']);
+ });
+ }
+
+ return $fields;
+ }
+
/**
* Get/set an associative array of table columns
*
private function getDAOFields($entityName) {
$bao = CoreUtil::getBAOFromApiName($entityName);
- return $bao::fields();
+ return $bao::getSupportedFields();
}
}
* return the DAO name to manipulate this function
* eg. "civicrm_api3_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
*
- * @return mixed|string
+ * @return CRM_Core_DAO|string
*/
function _civicrm_api3_get_DAO($name) {
if (strpos($name, 'civicrm_api3') !== FALSE) {
if (empty($dao)) {
return [];
}
- $d = new $dao();
- $fields = $d->fields();
+ $fields = $dao::fields();
+ $supportedFields = $dao::getSupportedFields();
- foreach ($fields as $name => &$field) {
+ foreach ($fields as $name => $field) {
// Denote as core field
- $field['is_core_field'] = TRUE;
+ $fields[$name]['is_core_field'] = TRUE;
// Set html attributes for text fields
if (isset($field['html'])) {
- $field['html'] += (array) $d::makeAttribute($field);
+ $fields[$name]['html'] += (array) $dao::makeAttribute($field);
+ }
+ // Delete field if not supported by current db schema (prevents errors when there are pending db updates)
+ if (!isset($supportedFields[$field['name']])) {
+ unset($fields[$name]);
}
}
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.27.alpha1';
+UPDATE civicrm_domain SET version = '5.28.alpha1';
$this->fail('String not altered');
}
+ public function testSupportedFields() {
+ // Hack a different db version which will trigger getSupportedFields to filter out newer fields
+ \CRM_Core_DAO::$_dbColumnValueCache['CRM_Core_DAO_Domain']['id'][1]['version'] = '5.26.0';
+
+ $customGroupFields = CRM_Core_DAO_CustomGroup::getSupportedFields();
+ // 'icon' was added in 5.28
+ $this->assertArrayNotHasKey('icon', $customGroupFields);
+
+ // Remove domain version override:
+ \CRM_Core_DAO::$_dbColumnValueCache = NULL;
+
+ $activityFields = CRM_Activity_DAO_Activity::getSupportedFields();
+ // Fields should be indexed by name not unique_name (which is "activity_id")
+ $this->assertEquals('id', $activityFields['id']['name']);
+
+ $customGroupFields = CRM_Core_DAO_CustomGroup::getSupportedFields();
+ $this->assertArrayHasKey('icon', $customGroupFields);
+
+ \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'view all contacts'];
+ $contactFields = CRM_Contact_DAO_Contact::getSupportedFields();
+ $this->assertArrayHasKey('api_key', $contactFields);
+
+ $permissionedContactFields = CRM_Contact_DAO_Contact::getSupportedFields(TRUE);
+ $this->assertArrayNotHasKey('api_key', $permissionedContactFields);
+ }
+
}