-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
348 additions
and
429 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
<?php | ||
/*-------------------------------------------------------+ | ||
| SYSTOPIA CUSTOM DATA HELPER | | ||
| Copyright (C) 2018-2021 SYSTOPIA | | ||
| Copyright (C) 2018-2024 SYSTOPIA | | ||
| Author: B. Endres ([email protected]) | | ||
| Source: https://github.com/systopia/Custom-Data-Helper | | ||
+--------------------------------------------------------+ | ||
|
@@ -15,15 +15,15 @@ | |
+--------------------------------------------------------*/ | ||
|
||
class CRM_Committees_CustomData { | ||
const CUSTOM_DATA_HELPER_VERSION = 0.7; | ||
const CUSTOM_DATA_HELPER_LOG_LEVEL = 3; | ||
const CUSTOM_DATA_HELPER_VERSION = '0.12.0'; | ||
const CUSTOM_DATA_HELPER_LOG_LEVEL = 0; | ||
const CUSTOM_DATA_HELPER_LOG_DEBUG = 1; | ||
const CUSTOM_DATA_HELPER_LOG_INFO = 3; | ||
const CUSTOM_DATA_HELPER_LOG_ERROR = 5; | ||
|
||
/** caches custom field data, indexed by group name */ | ||
protected static $custom_group2name = null; | ||
protected static $custom_group2table_name = null; | ||
protected static $custom_group2name = NULL; | ||
protected static $custom_group2table_name = NULL; | ||
protected static $custom_group_cache = []; | ||
protected static $custom_group_spec_cache = []; | ||
protected static $custom_field_cache = []; | ||
|
@@ -35,23 +35,12 @@ public function __construct($ts_domain) { | |
$this->ts_domain = $ts_domain; | ||
} | ||
|
||
/** | ||
* Flush all internal caches | ||
*/ | ||
public static function flushCashes() { | ||
self::$custom_group2name = null; | ||
self::$custom_group2table_name = null; | ||
self::$custom_group_cache = []; | ||
self::$custom_group_spec_cache = []; | ||
self::$custom_field_cache = []; | ||
} | ||
|
||
/** | ||
* Log a message if the log level is high enough | ||
*/ | ||
protected function log($level, $message) { | ||
if ($level >= self::CUSTOM_DATA_HELPER_LOG_LEVEL) { | ||
CRM_Core_Error::debug_log_message("CustomDataHelper {$this->version} ({$this->ts_domain}): {$message}"); | ||
Civi::log()->debug("CustomDataHelper {$this->version} ({$this->ts_domain}): {$message}"); | ||
} | ||
} | ||
|
||
|
@@ -145,10 +134,10 @@ public function syncCustomGroup($source_file) { | |
if (isset($data['extends_entity_column_value'])) { | ||
$force_update = TRUE; // this doesn't get returned by the API, so differences couldn't be detected | ||
if ($data['extends'] == 'Activity') { | ||
$extends_list = array(); | ||
$extends_list = []; | ||
foreach ($data['extends_entity_column_value'] as $activity_type) { | ||
if (!is_numeric($activity_type)) { | ||
$activity_type = CRM_Core_OptionGroup::getValue('activity_type', $activity_type, 'name'); | ||
$activity_type = self::getOptionValue('activity_type', $activity_type, 'name'); | ||
} | ||
if ($activity_type) { | ||
$extends_list[] = $activity_type; | ||
|
@@ -273,15 +262,15 @@ protected function createEntity($entity_type, $data) { | |
} | ||
|
||
// then run query | ||
CRM_Core_Error::debug_log_message("CustomDataHelper ({$this->ts_domain}): CREATE {$entity_type}: " . json_encode($data)); | ||
Civi::log()->debug("CustomDataHelper ({$this->ts_domain}): CREATE {$entity_type}: " . json_encode($data)); | ||
return civicrm_api3($entity_type, 'create', $data); | ||
} | ||
|
||
/** | ||
* create a new entity | ||
*/ | ||
protected function updateEntity($entity_type, $requested_data, $current_data, $required_fields = array(), $force = FALSE) { | ||
$update_query = array(); | ||
protected function updateEntity($entity_type, $requested_data, $current_data, $required_fields = [], $force = FALSE) { | ||
$update_query = []; | ||
|
||
// first: identify fields that need to be updated | ||
foreach ($requested_data as $field => $value) { | ||
|
@@ -339,17 +328,30 @@ protected function translateStrings(&$data) { | |
} | ||
} | ||
|
||
/** | ||
* Flush all internal caches | ||
*/ | ||
public static function flushCashes() { | ||
self::$custom_group2name = null; | ||
self::$custom_group2table_name = null; | ||
self::$custom_group_cache = []; | ||
self::$custom_group_spec_cache = []; | ||
self::$custom_field_cache = []; | ||
} | ||
|
||
/** | ||
* function to replace custom_XX notation with the more | ||
* stable "<custom_group_name>.<custom_field_name>" format | ||
* | ||
* @param $data array key=>value data, keys will be changed | ||
* @param $depth int recursively follow arrays | ||
* @param $data array key=>value data, keys will be changed | ||
* @param $depth int recursively follow arrays | ||
* @param $separator string separator to be used. | ||
* examples are '.' (default) or '__' to avoid drupal form field id issues | ||
*/ | ||
public static function labelCustomFields(&$data, $depth=1) { | ||
if ($depth == 0) return; | ||
public static function labelCustomFields(&$data, $depth=1, $separator = '.') { | ||
if ($depth <= 0) return; | ||
|
||
$custom_fields_used = array(); | ||
$custom_fields_used = []; | ||
foreach ($data as $key => $value) { | ||
if (preg_match('#^custom_(?P<field_id>\d+)$#', $key, $match)) { | ||
$custom_fields_used[] = $match['field_id']; | ||
|
@@ -362,27 +364,39 @@ public static function labelCustomFields(&$data, $depth=1) { | |
// replace names | ||
foreach ($data as $key => &$value) { | ||
if (preg_match('#^custom_(?P<field_id>\d+)$#', $key, $match)) { | ||
$new_key = self::getFieldIdentifier($match['field_id']); | ||
$new_key = self::getFieldIdentifier($match['field_id'], $separator); | ||
$data[$new_key] = $value; | ||
unset($data[$key]); | ||
} | ||
|
||
// recursively look into that array | ||
if (is_array($value) && $depth > 0) { | ||
self::labelCustomFields($value, $depth-1); | ||
self::labelCustomFields($value, $depth-1, $separator); | ||
} | ||
} | ||
} | ||
|
||
public static function getFieldIdentifier($field_id) { | ||
/** | ||
* Function to render a unified field identifier of the compatible | ||
* "<custom_group_name>.<custom_field_name>" | ||
* format | ||
* | ||
* @note This is intended for use with APIv3, since APIv4 already has a similar thing built in | ||
* | ||
* @param $field_id string the field ID | ||
* @param $separator string the separator to used, by default '.' | ||
* | ||
* @see getFieldIdentifier | ||
*/ | ||
public static function getFieldIdentifier($field_id, $separator = '.') { | ||
// just to be on the safe side | ||
self::cacheCustomFields(array($field_id)); | ||
|
||
// get custom field | ||
$custom_field = self::$custom_field_cache[$field_id]; | ||
if ($custom_field) { | ||
$group_name = self::getGroupName($custom_field['custom_group_id']); | ||
return "{$group_name}.{$custom_field['name']}"; | ||
return "{$group_name}{$separator}{$custom_field['name']}"; | ||
} else { | ||
return 'FIELD_NOT_FOUND_' . $field_id; | ||
} | ||
|
@@ -436,7 +450,7 @@ public static function getGroupSpecs($group_id) { | |
*/ | ||
public static function resolveCustomFields(&$data, $customgroups = NULL) { | ||
// first: find out which ones to cache | ||
$customgroups_used = array(); | ||
$customgroups_used = []; | ||
foreach ($data as $key => $value) { | ||
if (preg_match('/^(?P<group_name>\w+)[.](?P<field_name>\w+)$/', $key, $match)) { | ||
if ($match['group_name'] == 'option' || $match['group_name'] == 'options') { | ||
|
@@ -503,7 +517,7 @@ public static function cacheCustomGroups($custom_group_names) { | |
foreach ($custom_group_names as $custom_group_name) { | ||
if (!isset(self::$custom_group_cache[$custom_group_name])) { | ||
// set to empty array to indicate our intentions | ||
self::$custom_group_cache[$custom_group_name] = array(); | ||
self::$custom_group_cache[$custom_group_name] = []; | ||
$fields = civicrm_api3('CustomField', 'get', array( | ||
'custom_group_id' => $custom_group_name, | ||
'option.limit' => 0)); | ||
|
@@ -520,7 +534,7 @@ public static function cacheCustomGroups($custom_group_names) { | |
*/ | ||
public static function cacheCustomFields($custom_field_ids) { | ||
// first: check if they are already cached | ||
$fields_to_load = array(); | ||
$fields_to_load = []; | ||
foreach ($custom_field_ids as $field_id) { | ||
if (!array_key_exists($field_id, self::$custom_field_cache)) { | ||
$fields_to_load[] = $field_id; | ||
|
@@ -546,7 +560,7 @@ public static function cacheCustomFields($custom_field_ids) { | |
*/ | ||
public static function cacheCustomGroupSpecs($custom_group_ids) { | ||
// first: check if they are already cached | ||
$fields_to_load = array(); | ||
$fields_to_load = []; | ||
foreach ($custom_group_ids as $group_id) { | ||
if (!array_key_exists($group_id, self::$custom_group_spec_cache)) { | ||
$groups_to_load[] = $group_id; | ||
|
@@ -569,6 +583,9 @@ public static function cacheCustomGroupSpecs($custom_group_ids) { | |
|
||
/** | ||
* Get a mapping: custom_group_id => custom_group_name | ||
* | ||
* @return array | ||
* mapping custom_group_id => custom_group_name | ||
*/ | ||
public static function getGroup2Name() { | ||
if (self::$custom_group2name === NULL) { | ||
|
@@ -592,8 +609,8 @@ public static function getGroup2TableName() { | |
* Load group data (all groups) | ||
*/ | ||
protected static function loadGroups() { | ||
self::$custom_group2name = array(); | ||
self::$custom_group2table_name = array(); | ||
self::$custom_group2name = []; | ||
self::$custom_group2table_name = []; | ||
$group_search = civicrm_api3('CustomGroup', 'get', array( | ||
'return' => 'name,table_name', | ||
'option.limit' => 0, | ||
|
@@ -628,8 +645,11 @@ public static function getGroupName($custom_group_id) { | |
* | ||
* @todo make it more efficient? | ||
* | ||
* @param array $params the parameter array as used by the API | ||
* @param array $group_names list of group names to process. Default is: all | ||
* @param array $params | ||
* the parameter array as used by the API | ||
* | ||
* @param array $group_names | ||
* list of group names to process. Default is: all | ||
*/ | ||
public static function unREST(&$params, $group_names = NULL) { | ||
if ($group_names == NULL || !is_array($group_names)) { | ||
|
@@ -710,9 +730,14 @@ public static function createSQLJoin($group_name, $table_alias, $join_entity_id) | |
/** | ||
* Get the current field value from CiviCRM's pre-hook structure | ||
* | ||
* @param $params pre-hook data | ||
* @param $field_id custom field ID | ||
* @return mixed the current value | ||
* @param $params array | ||
* pre-hook data | ||
* | ||
* @param $field_id string | ||
* custom field ID | ||
* | ||
* @return mixed | ||
* the current value | ||
*/ | ||
public static function getPreHookCustomDataValue($params, $field_id) { | ||
if ($field_id) { | ||
|
@@ -731,9 +756,14 @@ public static function getPreHookCustomDataValue($params, $field_id) { | |
/** | ||
* Set a field value in CiviCRM's pre-hook structure right in the pre hook data | ||
* | ||
* @param $params pre-hook data | ||
* @param $field_id custom field ID | ||
* @param $value the new value | ||
* @param $params array | ||
* pre-hook data | ||
* | ||
* @param $field_id string | ||
* custom field ID | ||
* | ||
* @param $value mixed | ||
* the new value | ||
*/ | ||
public static function setPreHookCustomDataValue(&$params, $field_id, $value) { | ||
if ($field_id) { | ||
|
@@ -775,4 +805,68 @@ protected static function generatePreHookCustomDataRecord($field_id, $value) { | |
return NULL; | ||
} | ||
} | ||
|
||
/** | ||
* Get CustomField entity (cached) | ||
*/ | ||
public static function getCustomFieldsForGroups($custom_group_names) { | ||
self::cacheCustomGroups($custom_group_names); | ||
$fields = []; | ||
foreach ($custom_group_names as $custom_group_name) { | ||
foreach (self::$custom_group_cache[$custom_group_name] as $field_id => $field) { | ||
if (is_numeric($field_id)) { | ||
$fields[] = $field; | ||
} | ||
} | ||
} | ||
return $fields; | ||
} | ||
|
||
/** | ||
* Get an option value from an option group | ||
* | ||
* This function was specifically introduced as 1:1 replacement | ||
* for the deprecated CRM_Core_OptionGroup::getValue function | ||
* | ||
* @param string $groupName | ||
* name of the group | ||
* | ||
* @param $label | ||
* label/name of the requested option value | ||
* | ||
* @param string $label_field | ||
* field to look in for the label, e.g. 'label' or 'name' | ||
* | ||
* @param string $label_type | ||
* *ignored* | ||
* | ||
* @param string $value_field | ||
* *ignored* | ||
* | ||
* @return string | ||
* value of the OptionValue entity if found | ||
* | ||
* @throws Exception | ||
*/ | ||
public static function getOptionValue($group_name, $label, $label_field = 'label', $label_type = 'String', $value_field = 'value') | ||
{ | ||
if (empty($label) || empty($group_name)) { | ||
return NULL; | ||
} | ||
|
||
// build/run API query | ||
try { | ||
$value = civicrm_api3('OptionValue', 'getvalue', [ | ||
'option_group_id' => $group_name, | ||
$label_field => $label, | ||
'return' => $value_field | ||
]); | ||
} | ||
catch (CRM_Core_Exception $exception) { | ||
return NULL; | ||
} | ||
|
||
// anything else to do here? | ||
return (string) $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.