diff options
Diffstat (limited to 'www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils')
5 files changed, 367 insertions, 0 deletions
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ActionUtil.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ActionUtil.php new file mode 100644 index 00000000..628bc6fa --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ActionUtil.php @@ -0,0 +1,27 @@ +<?php + +namespace Civi\Api4\Utils; + +class ActionUtil { + + /** + * @param $entityName + * @param $actionName + * @return \Civi\Api4\Generic\AbstractAction + * @throws \Civi\API\Exception\NotImplementedException + */ + public static function getAction($entityName, $actionName) { + // For custom pseudo-entities + if (strpos($entityName, 'Custom_') === 0) { + return \Civi\Api4\CustomValue::$actionName(substr($entityName, 7)); + } + else { + $callable = ["\\Civi\\Api4\\$entityName", $actionName]; + if (!is_callable($callable)) { + throw new \Civi\API\Exception\NotImplementedException("API ($entityName, $actionName) does not exist (join the API team and implement it!)"); + } + return call_user_func($callable); + } + } + +} diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ArrayInsertionUtil.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ArrayInsertionUtil.php new file mode 100644 index 00000000..54e3944b --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ArrayInsertionUtil.php @@ -0,0 +1,73 @@ +<?php + +namespace Civi\Api4\Utils; + +use CRM_Utils_Array as UtilsArray; + +class ArrayInsertionUtil { + /** + * If the values to be inserted contain a key _parent_id they will only be + * inserted if the parent node ID matches their ID + * + * @param $array + * The array to insert the value in + * @param array $parts + * Path to insertion point with structure: + * [[ name => is_multiple ], ..] + * @param mixed $values + * The value to be inserted + */ + public static function insert(&$array, $parts, $values) { + $key = key($parts); + $isMulti = array_shift($parts); + if (!isset($array[$key])) { + $array[$key] = $isMulti ? [] : NULL; + } + if (empty($parts)) { + $values = self::filterValues($array, $isMulti, $values); + $array[$key] = $values; + } + else { + if ($isMulti) { + foreach ($array[$key] as &$subArray) { + self::insert($subArray, $parts, $values); + } + } + else { + self::insert($array[$key], $parts, $values); + } + } + } + + /** + * @param $parentArray + * @param $isMulti + * @param $values + * + * @return array|mixed + */ + private static function filterValues($parentArray, $isMulti, $values) { + $parentID = UtilsArray::value('id', $parentArray); + + if ($parentID) { + $values = array_filter($values, function ($value) use ($parentID) { + return UtilsArray::value('_parent_id', $value) == $parentID; + }); + } + + $unsets = ['_parent_id', '_base_id']; + array_walk($values, function (&$value) use ($unsets) { + foreach ($unsets as $unset) { + if (isset($value[$unset])) { + unset($value[$unset]); + } + } + }); + + if (!$isMulti) { + $values = array_shift($values); + } + return $values; + } + +} diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/CoreUtil.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/CoreUtil.php new file mode 100644 index 00000000..b43e62ca --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/CoreUtil.php @@ -0,0 +1,42 @@ +<?php + +namespace Civi\Api4\Utils; + +use Civi\Api4\CustomGroup; + +require_once 'api/v3/utils.php'; + +class CoreUtil { + + /** + * todo this class should not rely on api3 code + * + * @param $entityName + * + * @return \CRM_Core_DAO|string + * The DAO name for use in static calls. Return doc block is hacked to allow + * auto-completion of static methods + */ + public static function getDAOFromApiName($entityName) { + if ($entityName === 'CustomValue' || strpos($entityName, 'Custom_') === 0) { + return 'CRM_Contact_BAO_Contact'; + } + return \_civicrm_api3_get_DAO($entityName); + } + + /** + * Get table name of given Custom group + * + * @param string $customGroupName + * + * @return string + */ + public static function getCustomTableByName($customGroupName) { + return CustomGroup::get() + ->addSelect('table_name') + ->addWhere('name', '=', $customGroupName) + ->execute() + ->first()['table_name']; + } + +} diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/FormattingUtil.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/FormattingUtil.php new file mode 100644 index 00000000..3a7cdae5 --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/FormattingUtil.php @@ -0,0 +1,106 @@ +<?php + +namespace Civi\Api4\Utils; + +use CRM_Utils_Array as UtilsArray; + +require_once 'api/v3/utils.php'; + +class FormattingUtil { + + /** + * Massage values into the format the BAO expects for a write operation + * + * @param $params + * @param $entity + * @param $fields + * @throws \API_Exception + */ + public static function formatWriteParams(&$params, $entity, $fields) { + foreach ($fields as $name => $field) { + if (!empty($params[$name])) { + $value =& $params[$name]; + // Hack for null values -- see comment below + if ($value === 'null') { + $value = 'Null'; + } + FormattingUtil::formatValue($value, $field, $entity); + // Ensure we have an array for serialized fields + if (!empty($field['serialize'] && !is_array($value))) { + $value = (array) $value; + } + } + /* + * Because of the wacky way that database values are saved we need to format + * some of the values here. In this strange world the string 'null' is used to + * unset values. Hence if we encounter true null we change it to string 'null'. + * + * If we encounter the string 'null' then we assume the user actually wants to + * set the value to string null. However since the string null is reserved for + * unsetting values we must change it. Another quirk of the DB_DataObject is + * that it allows 'Null' to be set, but any other variation of string 'null' + * will be converted to true null, e.g. 'nuLL', 'NUlL' etc. so we change it to + * 'Null'. + */ + elseif (array_key_exists($name, $params) && $params[$name] === NULL) { + $params[$name] = 'null'; + } + + if (strstr($entity, 'Custom_')) { + if ($name == 'entity_id') { + $params['entityID'] = $params['entity_id']; + unset($params['entity_id']); + } + elseif (!empty($field['custom_field_id'])) { + $params['custom_' . $field['custom_field_id']] = $params[$name]; + unset($params[$name]); + } + } + } + } + + /** + * Transform raw api input to appropriate format for use in a SQL query. + * + * This is used by read AND write actions (Get, Create, Update, Replace) + * + * @param $value + * @param $fieldSpec + * @throws \API_Exception + */ + public static function formatValue(&$value, $fieldSpec, $entity) { + if (is_array($value)) { + foreach ($value as &$val) { + self::formatValue($val, $fieldSpec, $entity); + } + return; + } + $fk = UtilsArray::value('fk_entity', $fieldSpec); + if ($fieldSpec['name'] == 'id') { + $fk = $entity; + } + $dataType = UtilsArray::value('data_type', $fieldSpec); + + if ($fk === 'Domain' && $value === 'current_domain') { + $value = \CRM_Core_Config::domainID(); + } + + if ($fk === 'Contact' && !is_numeric($value)) { + $value = \_civicrm_api3_resolve_contactID($value); + if ('unknown-user' === $value) { + throw new \API_Exception("\"{$fieldSpec['name']}\" \"{$value}\" cannot be resolved to a contact ID", 2002, ['error_field' => $fieldSpec['name'], "type" => "integer"]); + } + } + + switch ($dataType) { + case 'Timestamp': + $value = date('Y-m-d H:i:s', strtotime($value)); + break; + + case 'Date': + $value = date('Ymd', strtotime($value)); + break; + } + } + +} diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ReflectionUtils.php b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ReflectionUtils.php new file mode 100644 index 00000000..76662647 --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ext/api4/Civi/Api4/Utils/ReflectionUtils.php @@ -0,0 +1,119 @@ +<?php +/* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2015 | + +--------------------------------------------------------------------+ + | 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 | + +--------------------------------------------------------------------+ + */ + +namespace Civi\Api4\Utils; + +/** + * Just another place to put static functions... + */ +class ReflectionUtils { + /** + * @param \Reflector|\ReflectionClass $reflection + * @param string $type + * If we are not reflecting the class itself, specify "Method", "Property", etc. + * + * @return array + */ + public static function getCodeDocs($reflection, $type = NULL) { + $docs = self::parseDocBlock($reflection->getDocComment()); + + // Recurse into parent functions + if (isset($docs['inheritDoc']) || isset($docs['inheritdoc'])) { + unset($docs['inheritDoc'], $docs['inheritdoc']); + $newReflection = NULL; + try { + if ($type) { + $name = $reflection->getName(); + $reflectionClass = $reflection->getDeclaringClass()->getParentClass(); + if ($reflectionClass) { + $getItem = "get$type"; + $newReflection = $reflectionClass->$getItem($name); + } + } + else { + $newReflection = $reflection->getParentClass(); + } + } + catch (\ReflectionException $e) {} + if ($newReflection) { + // Mix in + $additionalDocs = self::getCodeDocs($newReflection, $type); + if (!empty($docs['comment']) && !empty($additionalDocs['comment'])) { + $docs['comment'] .= "\n\n" . $additionalDocs['comment']; + } + $docs += $additionalDocs; + } + } + return $docs; + } + + /** + * @param string $comment + * @return array + */ + public static function parseDocBlock($comment) { + $info = []; + foreach (preg_split("/((\r?\n)|(\r\n?))/", $comment) as $num => $line) { + if (!$num || strpos($line, '*/') !== FALSE) { + continue; + } + $line = ltrim(trim($line), '* '); + if (strpos($line, '@') === 0) { + $words = explode(' ', $line); + $key = substr($words[0], 1); + if ($key == 'var') { + $info['type'] = explode('|', $words[1]); + } + elseif ($key == 'options') { + $val = str_replace(', ', ',', implode(' ', array_slice($words, 1))); + $info['options'] = explode(',', $val); + } + else { + // Unrecognized annotation, but we'll duly add it to the info array + $val = implode(' ', array_slice($words, 1)); + $info[$key] = strlen($val) ? $val : TRUE; + } + } + elseif ($num == 1) { + $info['description'] = $line; + } + elseif (!$line) { + if (isset($info['comment'])) { + $info['comment'] .= "\n"; + } + } + else { + $info['comment'] = isset($info['comment']) ? "{$info['comment']}\n$line" : $line; + } + } + if (isset($info['comment'])) { + $info['comment'] = trim($info['comment']); + } + return $info; + } + +} |