function validate() { if (CRM_Utils_System::isNull($this->_value)) { return true; } switch ($this->_name) { case 'contact_id': // note: we validate extistence of the contact in API, upon // insert (it would be too costlty to do a db call here) return CRM_Utils_Rule::integer($this->_value); break; case 'receive_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': return CRM_Utils_Rule::date($this->_value); break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': return CRM_Utils_Rule::money($this->_value); break; case 'trxn_id': static $seenTrxnIds = array(); if (in_array($this->_value, $seenTrxnIds)) { return false; } elseif ($this->_value) { $seenTrxnIds[] = $this->_value; return true; } else { $this->_value = null; return true; } break; case 'currency': return CRM_Utils_Rule::currencyCode($this->_value); break; case 'contribution_type': static $contributionTypes = null; if (!$contributionTypes) { $contributionTypes =& CRM_Contribute_PseudoConstant::contributionType(); } if (in_array($this->_value, $contributionTypes)) { return true; } else { return false; } break; case 'payment_instrument': static $paymentInstruments = null; if (!$paymentInstruments) { $paymentInstruments =& CRM_Contribute_PseudoConstant::paymentInstrument(); } if (in_array($this->_value, $paymentInstruments)) { return true; } else { return false; } break; default: break; } // check whether that's a valid custom field id // and if so, check the contents' validity if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($this->_name)) { static $customFields = null; if (!$customFields) { $customFields =& CRM_Core_BAO_CustomField::getFields('Contribution'); } if (!array_key_exists($customFieldID, $customFields)) { return false; } return CRM_Core_BAO_CustomValue::typecheck($customFields[$customFieldID]['data_type'], $this->_value); } return true; }
/** * global validation rules for the form * * @param array $fields posted values of the form * * @return array list of errors to be posted back to the form * @static * @access public */ static function formRule(&$fields, &$files, &$form) { $optionLabel = CRM_Utils_Type::escape($fields['label'], 'String'); $optionValue = CRM_Utils_Type::escape($fields['value'], 'String'); $fieldId = $form->_fid; $optionGroupId = $form->_optionGroupID; $temp = array(); if (empty($form->_id)) { $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND label = %2"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionLabel, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['label'] = ts('There is an entry with the same label.'); } $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND value = %2"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionValue, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['value'] = ts('There is an entry with the same value.'); } } else { //capture duplicate entries while updating Custom Options $optionId = CRM_Utils_Type::escape($fields['optionId'], 'Integer'); //check label duplicates within a custom field $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND id != %2\n AND label = %3"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionId, 'Integer'), 3 => array($optionLabel, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['label'] = ts('There is an entry with the same label.'); } //check value duplicates within a custom field $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND id != %2\n AND value = %3"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionId, 'Integer'), 3 => array($optionValue, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['value'] = ts('There is an entry with the same value.'); } } $query = "\nSELECT data_type \n FROM civicrm_custom_field\n WHERE id = %1"; $params = array(1 => array($fieldId, 'Integer')); $dao =& CRM_Core_DAO::executeQuery($query, $params); if ($dao->fetch()) { switch ($dao->data_type) { case 'Int': if (!CRM_Utils_Rule::integer($fields["value"])) { $errors['value'] = ts('Please enter a valid integer value.'); } break; case 'Float': // case 'Money': if (!CRM_Utils_Rule::numeric($fields["value"])) { $errors['value'] = ts('Please enter a valid number value.'); } break; case 'Money': if (!CRM_Utils_Rule::money($fields["value"])) { $errors['value'] = ts('Please enter a valid value.'); } break; case 'Date': if (!CRM_Utils_Rule::date($fields["value"])) { $errors['value'] = ts('Please enter a valid date using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if (!CRM_Utils_Rule::integer($fields["value"]) && ($fields["value"] != '1' || $fields["value"] != '0')) { $errors['value'] = ts('Please enter 1 or 0 as value.'); } break; case 'Country': if (!empty($fields["value"])) { $params = array(1 => array($fields['value'], 'String')); $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1"; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($fields["value"])) { $params = array(1 => array($fields['value'], 'String')); $query = "\nSELECT count(*) \n FROM civicrm_state_province\n WHERE name = %1\n OR abbreviation = %1"; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['value'] = ts('The invalid value for State/Province data type'); } } break; } } return empty($errors) ? true : $errors; }
/** * global validation rules for the form * * @param array $fields (referance) posted values of the form * * @return array if errors then list of errors to be posted back to the form, * true otherwise * @static * @access public */ static function formRule($fields, $files, $self) { $default = CRM_Utils_Array::value('default_value', $fields); $errors = array(); //validate field label as well as name. $title = $fields['label']; $name = CRM_Utils_String::munge($title, '_', 64); $gId = $self->_gid; // CRM-7564 $query = 'select count(*) from civicrm_custom_field where ( name like %1 OR label like %2 ) and id != %3 and custom_group_id = %4'; $fldCnt = CRM_Core_DAO::singleValueQuery($query, array(1 => array($name, 'String'), 2 => array($title, 'String'), 3 => array((int) $self->_id, 'Integer'), 4 => array($gId, 'Integer'))); if ($fldCnt) { $errors['label'] = ts('Custom field \'%1\' already exists in Database.', array(1 => $title)); } //checks the given custom field name doesnot start with digit if (!empty($title)) { // gives the ascii value $asciiValue = ord($title[0]); if ($asciiValue >= 48 && $asciiValue <= 57) { $errors['label'] = ts("Field's Name should not start with digit"); } } // ensure that the label is not 'id' if (strtolower($title) == 'id') { $errors['label'] = ts("You cannot use 'id' as a field label."); } if (!isset($fields['data_type'][0]) || !isset($fields['data_type'][1])) { $errors['_qf_default'] = ts('Please enter valid - Data and Input Field Type.'); } $dataType = self::$_dataTypeKeys[$fields['data_type'][0]]; if ($default || $dataType == 'ContactReference') { switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($default)) { $errors['default_value'] = ts('Please enter a valid integer as default value.'); } break; case 'Float': if (!CRM_Utils_Rule::numeric($default)) { $errors['default_value'] = ts('Please enter a valid number as default value.'); } break; case 'Money': if (!CRM_Utils_Rule::money($default)) { $errors['default_value'] = ts('Please enter a valid number value.'); } break; case 'Link': if (!CRM_Utils_Rule::url($default)) { $errors['default_value'] = ts('Please enter a valid link.'); } break; case 'Date': if (!CRM_Utils_Rule::date($default)) { $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if ($default != '1' && $default != '0') { $errors['default_value'] = ts('Please enter 1 (for Yes) or 0 (for No) if you want to set a default value.'); } break; case 'Country': if (!empty($default)) { $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1"; $params = array(1 => array($fields['default_value'], 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($default)) { $query = "\nSELECT count(*)\n FROM civicrm_state_province\n WHERE name = %1\n OR abbreviation = %1"; $params = array(1 => array($fields['default_value'], 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('The invalid default value for State/Province data type'); } } break; case 'ContactReference': if ($fields['filter_selected'] == 'Advance' && CRM_Utils_Array::value('filter', $fields)) { if (strpos($fields['filter'], 'entity=') !== FALSE) { $errors['filter'] = ts("Please do not include entity parameter (entity is always 'contact')"); } elseif (strpos($fields['filter'], 'action=') === FALSE) { $errors['filter'] = ts("Please specify 'action' parameter, it should be 'lookup' or 'get'"); } elseif (strpos($fields['filter'], 'action=get') === FALSE && strpos($fields['filter'], 'action=lookup') === FALSE) { $errors['filter'] = ts("Only 'get' and 'lookup' actions are supported."); } } $self->setDefaults(array('filter_selected', $fields['filter_selected'])); break; } } if (self::$_dataTypeKeys[$fields['data_type'][0]] == 'Date') { if (!$fields['date_format']) { $errors['date_format'] = ts('Please select a date format.'); } } /** Check the option values entered * Appropriate values are required for the selected datatype * Incomplete row checking is also required. */ $_flagOption = $_rowError = 0; $_showHide = new CRM_Core_ShowHideBlocks('', ''); $dataType = self::$_dataTypeKeys[$fields['data_type'][0]]; if (isset($fields['data_type'][1])) { $dataField = $fields['data_type'][1]; } $optionFields = array('Select', 'Multi-Select', 'CheckBox', 'Radio', 'AdvMulti-Select'); if (isset($fields['option_type']) && $fields['option_type'] == 1) { //capture duplicate Custom option values if (!empty($fields['option_value'])) { $countValue = count($fields['option_value']); $uniqueCount = count(array_unique($fields['option_value'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] && !empty($fields['option_value'][$nextIndex])) { $errors['option_value[' . $start . ']'] = ts('Duplicate Option values'); $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values'); $_flagOption = 1; } $nextIndex++; } $start++; } } } //capture duplicate Custom Option label if (!empty($fields['option_label'])) { $countValue = count($fields['option_label']); $uniqueCount = count(array_unique($fields['option_label'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] && !empty($fields['option_label'][$nextIndex])) { $errors['option_label[' . $start . ']'] = ts('Duplicate Option label'); $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label'); $_flagOption = 1; } $nextIndex++; } $start++; } } } for ($i = 1; $i <= self::NUM_OPTION; $i++) { if (!$fields['option_label'][$i]) { if ($fields['option_value'][$i]) { $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty'); $_flagOption = 1; } else { $_emptyRow = 1; } } else { if (!strlen(trim($fields['option_value'][$i]))) { if (!$fields['option_value'][$i]) { $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty'); $_flagOption = 1; } } } if ($fields['option_value'][$i] && $dataType != 'String') { if ($dataType == 'Int') { if (!CRM_Utils_Rule::integer($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.'); } } elseif ($dataType == 'Money') { if (!CRM_Utils_Rule::money($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid money value.'); } } else { if (!CRM_Utils_Rule::numeric($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.'); } } } $showBlocks = 'optionField_' . $i; if ($_flagOption) { $_showHide->addShow($showBlocks); $_rowError = 1; } if (!empty($_emptyRow)) { $_showHide->addHide($showBlocks); } else { $_showHide->addShow($showBlocks); } if ($i == self::NUM_OPTION) { $hideBlock = 'additionalOption'; $_showHide->addHide($hideBlock); } $_flagOption = $_emptyRow = 0; } } elseif (isset($dataField) && in_array($dataField, $optionFields) && !in_array($dataType, array('Boolean', 'Country', 'StateProvince'))) { if (!$fields['option_group_id']) { $errors['option_group_id'] = ts('You must select a Multiple Choice Option set if you chose Reuse an existing set.'); } else { $query = "\nSELECT count(*)\nFROM civicrm_custom_field\nWHERE data_type != %1\nAND option_group_id = %2"; $params = array(1 => array(self::$_dataTypeKeys[$fields['data_type'][0]], 'String'), 2 => array($fields['option_group_id'], 'Integer')); $count = CRM_Core_DAO::singleValueQuery($query, $params); if ($count > 0) { $errors['option_group_id'] = ts('The data type of the multiple choice option set you\'ve selected does not match the data type assigned to this field.'); } } } $assignError = new CRM_Core_Page(); if ($_rowError) { $_showHide->addToTemplate(); $assignError->assign('optionRowError', $_rowError); } else { if (isset($fields['data_type'][1])) { switch (self::$_dataToHTML[$fields['data_type'][0]][$fields['data_type'][1]]) { case 'Radio': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; case 'Checkbox': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; case 'Select': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; default: $_fieldError = 0; $assignError->assign('fieldError', $_fieldError); } } for ($idx = 1; $idx <= self::NUM_OPTION; $idx++) { $showBlocks = 'optionField_' . $idx; if (!empty($fields['option_label'][$idx])) { $_showHide->addShow($showBlocks); } else { $_showHide->addHide($showBlocks); } } $_showHide->addToTemplate(); } // we can not set require and view at the same time. if (CRM_Utils_Array::value('is_required', $fields) && CRM_Utils_Array::value('is_view', $fields)) { $errors['is_view'] = ts('Can not set this field Required and View Only at the same time.'); } return empty($errors) ? TRUE : $errors; }
/** * take the input parameter list as specified in the data model and * convert it into the same format that we use in QF and BAO object * * @param array $params * Associative array of property name/value. * pairs to insert in new contact. * @param array $values * The reformatted properties that we can use internally. * ' * * @param bool $create * @param null $onDuplicate * * @return array|CRM_Error */ function _civicrm_api3_deprecated_formatted_param($params, &$values, $create = FALSE, $onDuplicate = NULL) { // copy all the contribution fields as is $fields = CRM_Contribute_DAO_Contribution::fields(); _civicrm_api3_store_values($fields, $params, $values); require_once 'CRM/Core/OptionGroup.php'; $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE); foreach ($params as $key => $value) { // ignore empty values or empty arrays etc if (CRM_Utils_System::isNull($value)) { continue; } // Handling Custom Data if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { $values[$key] = $value; $type = $customFields[$customFieldID]['html_type']; if ($type == 'CheckBox' || $type == 'Multi-Select') { $mulValues = explode(',', $value); $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); $values[$key] = array(); foreach ($mulValues as $v1) { foreach ($customOption as $customValueID => $customLabel) { $customValue = $customLabel['value']; if (strtolower($customLabel['label']) == strtolower(trim($v1)) || strtolower($customValue) == strtolower(trim($v1))) { if ($type == 'CheckBox') { $values[$key][$customValue] = 1; } else { $values[$key][] = $customValue; } } } } } elseif ($type == 'Select' || $type == 'Radio' || $type == 'Autocomplete-Select' && $customFields[$customFieldID]['data_type'] == 'String') { $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); foreach ($customOption as $customFldID => $customValue) { $val = CRM_Utils_Array::value('value', $customValue); $label = CRM_Utils_Array::value('label', $customValue); $label = strtolower($label); $value = strtolower(trim($value)); if ($value == $label || $value == strtolower($val)) { $values[$key] = $val; } } } } switch ($key) { case 'contribution_contact_id': if (!CRM_Utils_Rule::integer($value)) { return civicrm_api3_create_error("contact_id not valid: {$value}"); } $dao = new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = {$value}", $qParams); if (!isset($svq)) { return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } elseif ($svq == 1) { return civicrm_api3_create_error("Invalid Contact ID: contact_id {$value} is a soft-deleted contact."); } $values['contact_id'] = $values['contribution_contact_id']; unset($values['contribution_contact_id']); break; case 'contact_type': // import contribution record according to select contact type require_once 'CRM/Contact/DAO/Contact.php'; $contactType = new CRM_Contact_DAO_Contact(); // when insert mode check contact id or external identifier if (!empty($params['contribution_contact_id']) || !empty($params['external_identifier'])) { if (!empty($params['contribution_contact_id'])) { $contactType->id = CRM_Utils_Array::value('contribution_contact_id', $params); } elseif (!empty($params['external_identifier'])) { $contactType->external_identifier = $params['external_identifier']; } if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { return civicrm_api3_create_error("Contact Type is wrong: {$contactType->contact_type}"); } } } elseif (!empty($params['contribution_id']) || !empty($params['trxn_id']) || !empty($params['invoice_id'])) { // when update mode check contribution id or trxn id or // invoice id $contactId = new CRM_Contribute_DAO_Contribution(); if (!empty($params['contribution_id'])) { $contactId->id = $params['contribution_id']; } elseif (!empty($params['trxn_id'])) { $contactId->trxn_id = $params['trxn_id']; } elseif (!empty($params['invoice_id'])) { $contactId->invoice_id = $params['invoice_id']; } if ($contactId->find(TRUE)) { $contactType->id = $contactId->contact_id; if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { return civicrm_api3_create_error("Contact Type is wrong: {$contactType->contact_type}"); } } } } else { if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE) { return civicrm_api3_create_error("Empty Contribution and Invoice and Transaction ID. Row was skipped."); } else { return civicrm_api3_create_error("Empty Contact and External ID. Row was skipped."); } } break; case 'receive_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': if (!CRM_Utils_Rule::dateTime($value)) { return civicrm_api3_create_error("{$key} not a valid date: {$value}"); } break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': if (!CRM_Utils_Rule::money($value)) { return civicrm_api3_create_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return civicrm_api3_create_error("currency not a valid code: {$value}"); } break; case 'financial_type': require_once 'CRM/Contribute/PseudoConstant.php'; $contriTypes = CRM_Contribute_PseudoConstant::financialType(); foreach ($contriTypes as $val => $type) { if (strtolower($value) == strtolower($type)) { $values['financial_type_id'] = $val; break; } } if (empty($values['financial_type_id'])) { return civicrm_api3_create_error("Financial Type is not valid: {$value}"); } break; case 'payment_instrument': require_once 'CRM/Core/OptionGroup.php'; $values['payment_instrument_id'] = CRM_Core_OptionGroup::getValue('payment_instrument', $value); if (empty($values['payment_instrument_id'])) { return civicrm_api3_create_error("Payment Instrument is not valid: {$value}"); } break; case 'contribution_status_id': require_once 'CRM/Core/OptionGroup.php'; if (!($values['contribution_status_id'] = CRM_Core_OptionGroup::getValue('contribution_status', $value))) { return civicrm_api3_create_error("Contribution Status is not valid: {$value}"); } break; case 'soft_credit': // import contribution record according to select contact type // validate contact id and external identifier. $value[$key] = $mismatchContactType = $softCreditContactIds = ''; if (isset($params[$key]) && is_array($params[$key])) { foreach ($params[$key] as $softKey => $softParam) { $contactId = CRM_Utils_Array::value('contact_id', $softParam); $externalId = CRM_Utils_Array::value('external_identifier', $softParam); $email = CRM_Utils_Array::value('email', $softParam); if ($contactId || $externalId) { require_once 'CRM/Contact/DAO/Contact.php'; $contact = new CRM_Contact_DAO_Contact(); $contact->id = $contactId; $contact->external_identifier = $externalId; $errorMsg = NULL; if (!$contact->find(TRUE)) { $field = $contactId ? ts('Contact ID') : ts('External ID'); $errorMsg = ts("Soft Credit %1 - %2 doesn't exist. Row was skipped.", array(1 => $field, 2 => $contactId ? $contactId : $externalId)); } if ($errorMsg) { return civicrm_api3_create_error($errorMsg, $value[$key]); } // finally get soft credit contact id. $values[$key][$softKey] = $softParam; $values[$key][$softKey]['contact_id'] = $contact->id; } elseif ($email) { if (!CRM_Utils_Rule::email($email)) { return civicrm_api3_create_error("Invalid email address {$email} provided for Soft Credit. Row was skipped"); } // get the contact id from duplicate contact rule, if more than one contact is returned // we should return error, since current interface allows only one-one mapping $emailParams = array('email' => $email, 'contact_type' => $params['contact_type']); $checkDedupe = _civicrm_api3_deprecated_duplicate_formatted_contact($emailParams); if (!$checkDedupe['is_error']) { return civicrm_api3_create_error("Invalid email address(doesn't exist) {$email} for Soft Credit. Row was skipped"); } else { $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); if (count($matchingContactIds) > 1) { return civicrm_api3_create_error("Invalid email address(duplicate) {$email} for Soft Credit. Row was skipped"); } elseif (count($matchingContactIds) == 1) { $contactId = $matchingContactIds[0]; unset($softParam['email']); $values[$key][$softKey] = $softParam + array('contact_id' => $contactId); } } } } } break; case 'pledge_payment': case 'pledge_id': // giving respect to pledge_payment flag. if (empty($params['pledge_payment'])) { continue; } // get total amount of from import fields $totalAmount = CRM_Utils_Array::value('total_amount', $params); $onDuplicate = CRM_Utils_Array::value('onDuplicate', $params); // we need to get contact id $contributionContactID to // retrieve pledge details as well as to validate pledge ID // first need to check for update mode if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE && ($params['contribution_id'] || $params['trxn_id'] || $params['invoice_id'])) { $contribution = new CRM_Contribute_DAO_Contribution(); if ($params['contribution_id']) { $contribution->id = $params['contribution_id']; } elseif ($params['trxn_id']) { $contribution->trxn_id = $params['trxn_id']; } elseif ($params['invoice_id']) { $contribution->invoice_id = $params['invoice_id']; } if ($contribution->find(TRUE)) { $contributionContactID = $contribution->contact_id; if (!$totalAmount) { $totalAmount = $contribution->total_amount; } } else { return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } else { // first get the contact id for given contribution record. if (!empty($params['contribution_contact_id'])) { $contributionContactID = $params['contribution_contact_id']; } elseif (!empty($params['external_identifier'])) { require_once 'CRM/Contact/DAO/Contact.php'; $contact = new CRM_Contact_DAO_Contact(); $contact->external_identifier = $params['external_identifier']; if ($contact->find(TRUE)) { $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id; } else { return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } else { // we need to get contribution contact using de dupe $error = _civicrm_api3_deprecated_check_contact_dedupe($params); if (isset($error['error_message']['params'][0])) { $matchedIDs = explode(',', $error['error_message']['params'][0]); // check if only one contact is found if (count($matchedIDs) > 1) { return civicrm_api3_create_error($error['error_message']['message'], 'pledge_payment'); } else { $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0]; } } else { return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } } if (!empty($params['pledge_id'])) { if (CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $params['pledge_id'], 'contact_id') != $contributionContactID) { return civicrm_api3_create_error('Invalid Pledge ID provided. Contribution row was skipped.', 'pledge_payment'); } $values['pledge_id'] = $params['pledge_id']; } else { // check if there are any pledge related to this contact, with payments pending or in progress require_once 'CRM/Pledge/BAO/Pledge.php'; $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges($contributionContactID); if (empty($pledgeDetails)) { return civicrm_api3_create_error('No open pledges found for this contact. Contribution row was skipped.', 'pledge_payment'); } elseif (count($pledgeDetails) > 1) { return civicrm_api3_create_error('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.', 'pledge_payment'); } // this mean we have only one pending / in progress pledge $values['pledge_id'] = $pledgeDetails[0]; } // we need to check if oldest payment amount equal to contribution amount require_once 'CRM/Pledge/BAO/PledgePayment.php'; $pledgePaymentDetails = CRM_Pledge_BAO_PledgePayment::getOldestPledgePayment($values['pledge_id']); if ($pledgePaymentDetails['amount'] == $totalAmount) { $values['pledge_payment_id'] = $pledgePaymentDetails['id']; } else { return civicrm_api3_create_error('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.', 'pledge_payment'); } break; default: break; } } if (array_key_exists('note', $params)) { $values['note'] = $params['note']; } if ($create) { // CRM_Contribute_BAO_Contribution::add() handles contribution_source // So, if $values contains contribution_source, convert it to source $changes = array('contribution_source' => 'source'); foreach ($changes as $orgVal => $changeVal) { if (isset($values[$orgVal])) { $values[$changeVal] = $values[$orgVal]; unset($values[$orgVal]); } } } return NULL; }
/** * Helper function to validate custom field value * * @params String $fieldName Custom field name (eg: custom_8 ) * @params Mixed $value Field value to be validate * @params Array $fieldDetails Field Details * @params Array $errors Collect validation errors * * @param $fieldName * @param $value * @param $fieldDetails * @param array $errors * * @return Array Validation errors * @todo remove this function - not in use but need to review functionality before * removing as it might be useful in wrapper layer */ function _civicrm_api3_custom_field_validate_field($fieldName, $value, $fieldDetails, &$errors = array()) { return; //see comment block if (!$value) { return $errors; } $dataType = $fieldDetails['data_type']; $htmlType = $fieldDetails['html_type']; switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($value)) { $errors[$fieldName] = 'Invalid integer value for ' . $fieldName; } break; case 'Float': if (!CRM_Utils_Rule::numeric($value)) { $errors[$fieldName] = 'Invalid numeric value for ' . $fieldName; } break; case 'Money': if (!CRM_Utils_Rule::money($value)) { $errors[$fieldName] = 'Invalid numeric value for ' . $fieldName; } break; case 'Link': if (!CRM_Utils_Rule::url($value)) { $errors[$fieldName] = 'Invalid link for ' . $fieldName; } break; case 'Boolean': if ($value != '1' && $value != '0') { $errors[$fieldName] = 'Invalid boolean (use 1 or 0) value for ' . $fieldName; } break; case 'Country': if (empty($value)) { break; } if ($htmlType != 'Multi-Select Country' && is_array($value)) { $errors[$fieldName] = 'Invalid country for ' . $fieldName; break; } if (!is_array($value)) { $value = array($value); } $query = "SELECT count(*) FROM civicrm_country WHERE id IN (" . implode(',', $value) . ")"; if (CRM_Core_DAO::singleValueQuery($query) < count($value)) { $errors[$fieldName] = 'Invalid country(s) for ' . $fieldName; } break; case 'StateProvince': if (empty($value)) { break; } if ($htmlType != 'Multi-Select State/Province' && is_array($value)) { $errors[$fieldName] = 'Invalid State/Province for ' . $fieldName; break; } if (!is_array($value)) { $value = array($value); } $query = "\nSELECT count(*)\n FROM civicrm_state_province\n WHERE id IN ('" . implode("','", $value) . "')"; if (CRM_Core_DAO::singleValueQuery($query) < count($value)) { $errors[$fieldName] = 'Invalid State/Province for ' . $fieldName; } break; case 'ContactReference': //FIX ME break; } if (in_array($htmlType, array('Select', 'Multi-Select', 'CheckBox', 'Radio', 'AdvMulti-Select')) && !isset($errors[$fieldName])) { $options = CRM_Core_OptionGroup::valuesByID($fieldDetails['option_group_id']); if (!is_array($value)) { $value = array($value); } $invalidOptions = array_diff($value, array_keys($options)); if (!empty($invalidOptions)) { $errors[$fieldName] = "Invalid option(s) for field '{$fieldName}': " . implode(',', $invalidOptions); } } return $errors; }
/** * Validate fields being passed into API. * * This function relies on the getFields function working accurately * for the given API. If error mode is set to TRUE then it will also check * foreign keys * * As of writing only date was implemented. * * @param string $entity * @param string $action * @param array $params * -. * @param array $fields * Response from getfields all variables are the same as per civicrm_api. * @param bool $errorMode * ErrorMode do intensive post fail checks?. * * @throws Exception */ function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $errorMode = FALSE) { //CRM-15792 handle datetime for custom fields below code handles chain api call $chainApikeys = array_flip(preg_grep("/^api./", array_keys($params))); if (!empty($chainApikeys) && is_array($chainApikeys)) { foreach ($chainApikeys as $key => $value) { if (is_array($params[$key])) { $chainApiParams = array_intersect_key($fields, $params[$key]); $customFields = array_fill_keys(array_keys($params[$key]), $key); } } } $fields = array_intersect_key($fields, $params); if (!empty($chainApiParams)) { $fields = array_merge($fields, $chainApiParams); } foreach ($fields as $fieldName => $fieldInfo) { switch (CRM_Utils_Array::value('type', $fieldInfo)) { case CRM_Utils_Type::T_INT: //field is of type integer _civicrm_api3_validate_integer($params, $fieldName, $fieldInfo, $entity); break; case CRM_Utils_Type::T_DATE: case CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME: case CRM_Utils_Type::T_TIMESTAMP: //field is of type date or datetime if (!empty($customFields) && array_key_exists($fieldName, $customFields)) { $dateParams =& $params[$customFields[$fieldName]]; } else { $dateParams =& $params; } _civicrm_api3_validate_date($dateParams, $fieldName, $fieldInfo); break; case 32: //blob _civicrm_api3_validate_html($params, $fieldName, $fieldInfo); break; case CRM_Utils_Type::T_STRING: _civicrm_api3_validate_string($params, $fieldName, $fieldInfo, $entity); break; case CRM_Utils_Type::T_MONEY: list($fieldValue, $op) = _civicrm_api3_field_value_check($params, $fieldName); if (strpos($op, 'NULL') !== FALSE || strpos($op, 'EMPTY') !== FALSE) { break; } foreach ((array) $fieldValue as $fieldvalue) { if (!CRM_Utils_Rule::money($fieldvalue) && !empty($fieldvalue)) { throw new Exception($fieldName . " is not a valid amount: " . $params[$fieldName]); } } break; } // intensive checks - usually only called after DB level fail if (!empty($errorMode) && strtolower($action) == 'create') { if (!empty($fieldInfo['FKClassName'])) { if (!empty($fieldValue)) { _civicrm_api3_validate_constraint($params, $fieldName, $fieldInfo); } elseif (!empty($fieldInfo['required'])) { throw new Exception("DB Constraint Violation - possibly {$fieldName} should possibly be marked as mandatory for this API. If so, please raise a bug report"); } } if (!empty($fieldInfo['api.unique'])) { $params['entity'] = $entity; _civicrm_api3_validate_unique_key($params, $fieldName); } } } }
/** * take the input parameter list as specified in the data model and * convert it into the same format that we use in QF and BAO object * * @param array $params Associative array of property name/value * pairs to insert in new contact. * @param array $values The reformatted properties that we can use internally * ' * @return array|CRM_Error * @access public */ function _crm_format_contrib_params(&$params, &$values, $create = false) { // copy all the contribution fields as is $fields =& CRM_Contribute_DAO_Contribution::fields(); _crm_store_values($fields, $params, $values); foreach ($params as $key => $value) { // ignore empty values or empty arrays etc if (CRM_Utils_System::isNull($value)) { continue; } switch ($key) { case 'contribution_contact_id': if (!CRM_Utils_Rule::integer($value)) { return _crm_error("contact_id not valid: {$value}"); } $dao =& new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = {$value}", $qParams); if (!$svq) { return _crm_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } $values['contact_id'] = $values['contribution_contact_id']; unset($values['contribution_contact_id']); break; case 'receive_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': if (!CRM_Utils_Rule::date($value)) { return _crm_error("{$key} not a valid date: {$value}"); } break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': if (!CRM_Utils_Rule::money($value)) { return _crm_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return _crm_error("currency not a valid code: {$value}"); } break; case 'contribution_type': require_once 'CRM/Contribute/PseudoConstant.php'; $values['contribution_type_id'] = CRM_Utils_Array::key(ucfirst($value), CRM_Contribute_PseudoConstant::contributionType()); break; case 'payment_instrument': require_once 'CRM/Core/OptionGroup.php'; $values['payment_instrument_id'] = CRM_Core_OptionGroup::getValue('payment_instrument', $value); break; case 'contribution_status_id': require_once 'CRM/Core/OptionGroup.php'; $values['contribution_status_id'] = CRM_Core_OptionGroup::getValue('contribution_status', $value); break; default: break; } } if (array_key_exists('note', $params)) { $values['note'] = $params['note']; } _crm_format_custom_params($params, $values, 'Contribution'); if ($create) { // CRM_Contribute_BAO_Contribution::add() handles contribution_source // So, if $values contains contribution_source, convert it to source $changes = array('contribution_source' => 'source'); foreach ($changes as $orgVal => $changeVal) { if (isset($values[$orgVal])) { $values[$changeVal] = $values[$orgVal]; unset($values[$orgVal]); } } } return null; }
/** * take the input parameter list as specified in the data model and * convert it into the same format that we use in QF and BAO object * * @param array $params Associative array of property name/value * pairs to insert in new contact. * @param array $values The reformatted properties that we can use internally * ' * * @return array|CRM_Error * @access public */ function _civicrm_pledge_format_params(&$params, &$values, $create = FALSE) { // based on contribution apis - copy all the pledge fields - this function filters out non -valid fields but unfortunately // means we have to put them back where there are 2 names for the field (name in table & unique name) // since there is no clear std to use one or the other. Generally either works ? but not for create date // perhaps we should just copy $params across rather than run it through the 'filter'? // but at least the filter forces anomalies into the open. In several cases it turned out the unique names wouldn't work // even though they are 'generally' what is returned in the GET - implying they should $fields = CRM_Pledge_DAO_Pledge::fields(); _civicrm_store_values($fields, $params, $values); //add back the fields we know of that got dropped by the previous function if ($params['pledge_create_date']) { //pledge_create_date will not be formatted by the format params function so change back to create_date $values['create_date'] = $params['pledge_create_date']; } if ($params['create_date']) { //create_date may have been dropped by the $fields function so retrieve it $values['create_date'] = $params['create_date']; } if (array_key_exists('installment_amount', $params)) { //field has been renamed - don't lose it! Note that this must be called // installment amount not pledge_installment_amount, pledge_original_installment_amount // or original_installment_amount to avoid error // Division by zero in CRM\Pledge\BAO\PledgePayment.php:162 // but we should accept the variant because they are all 'logical assumptions' based on the // 'standards' $values['installment_amount'] = $params['installment_amount']; } if (array_key_exists('original_installment_amount', $params)) { $values['installment_amount'] = $params['original_installment_amount']; } if (array_key_exists('pledge_original_installment_amount', $params)) { $values['installment_amount'] = $params['pledge_original_installment_amount']; } if (array_key_exists('status_id', $params)) { $values['pledge_status_id'] = $params['status_id']; } if ($params['contact_id']) { //this is validity checked further down to make sure the contact exists $values['pledge_contact_id'] = $params['contact_id']; } if (array_key_exists('id', $params)) { //retrieve the id key dropped from params. Note we can't use pledge_id because it //causes an error in CRM_Pledge_BAO_PledgePayment - approx line 302 $values['id'] = $params['id']; } if (array_key_exists('pledge_id', $params)) { //retrieve the id key dropped from params. Note we can't use pledge_id because it //causes an error in CRM_Pledge_BAO_PledgePayment - approx line 302 $values['id'] = $params['pledge_id']; unset($values['pledge_id']); } if (array_key_exists('status_id', $params)) { $values['pledge_status_id'] = $params['status_id']; } if (empty($values['id'])) { //at this point both should be the same so unset both if not set - passing in empty //value causes crash rather creating new - do it before next section as null values ignored in 'switch' unset($values['id']); } if (!empty($params['scheduled_date'])) { //scheduled date is required to set next payment date - defaults to start date $values['scheduled_date'] = $params['scheduled_date']; } elseif (array_key_exists('start_date', $params)) { $values['scheduled_date'] = $params['start_date']; } if (CRM_Utils_Array::value('contribution_type_id', $params)) { $values['contribution_type_id'] = $params['contribution_type_id']; } foreach ($values as $key => $value) { // ignore empty values or empty arrays etc if (CRM_Utils_System::isNull($value)) { continue; } switch ($key) { case 'pledge_contact_id': if (!CRM_Utils_Rule::integer($value)) { return civicrm_create_error("contact_id not valid: {$value}"); } $dao = new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = {$value}", $qParams); if (!$svq) { return civicrm_create_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } $values['contact_id'] = $values['pledge_contact_id']; unset($values['pledge_contact_id']); break; case 'pledge_id': if (!CRM_Utils_Rule::integer($value)) { return civicrm_create_error("contact_id not valid: {$value}"); } $dao = new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_pledge WHERE id = {$value}", $qParams); if (!$svq) { return civicrm_create_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } break; case 'create_date': case 'scheduled_date': case 'start_date': if (!CRM_Utils_Rule::datetime($value)) { return civicrm_create_error("{$key} not a valid date: {$value}"); } break; case 'installment_amount': case 'amount': if (!CRM_Utils_Rule::money($value)) { return civicrm_create_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return civicrm_create_error("currency not a valid code: {$value}"); } break; case 'contribution_type_id': require_once 'CRM/Contribute/PseudoConstant.php'; $typeId = CRM_Contribute_PseudoConstant::contributionType($value); if (!CRM_Utils_Rule::integer($value) || !$typeId) { return civicrm_create_error("contribution type id is not valid: {$value}"); } default: break; } } //format the parameters _civicrm_custom_format_params($params, $values, 'Pledge'); return array(); }
function _civicrm_api3_validate_fields($entity, $action, &$params, $errorMode = NULL) { //skip any entities without working getfields functions $skippedEntities = array('entity', 'mailinggroup', 'customvalue', 'custom_value', 'mailing_group'); if (in_array(strtolower($entity), $skippedEntities) || strtolower($action) == 'getfields') { return; } $fields = civicrm_api($entity, 'getfields', array('version' => 3, 'action' => $action)); $fields = array_intersect_key($fields['values'], $params); foreach ($fields as $fieldname => $fieldInfo) { switch (CRM_Utils_Array::value('type', $fieldInfo)) { case CRM_Utils_Type::T_INT: //field is of type integer _civicrm_api3_validate_integer($params, $fieldname, $fieldInfo); break; case 4: case 12: //field is of type date or datetime _civicrm_api3_validate_date($params, $fieldname, $fieldInfo); break; case 32: //blob _civicrm_api3_validate_html($params, $fieldname, $fieldInfo); break; case CRM_Utils_Type::T_STRING: _civicrm_api3_validate_string($params, $fieldname, $fieldInfo); break; case CRM_Utils_Type::T_MONEY: if (!CRM_Utils_Rule::money($params[$fieldname])) { throw new Exception($fieldname . " is not a valid amount: " . $params[$fieldname]); } } // intensive checks - usually only called after DB level fail if (!empty($errorMode) && strtolower($action) == 'create') { if (CRM_Utils_Array::value('FKClassName', $fieldInfo)) { if (CRM_Utils_Array::value($fieldname, $params)) { _civicrm_api3_validate_constraint($params, $fieldname, $fieldInfo); } elseif (CRM_Utils_Array::value('required', $fieldInfo)) { throw new Exception("DB Constraint Violation - possibly {$fieldname} should possibly be marked as mandatory for this API. If so, please raise a bug report"); } } if (CRM_Utils_Array::value('api.unique', $fieldInfo)) { $params['entity'] = $entity; _civicrm_api3_validate_uniquekey($params, $fieldname, $fieldInfo); } } } }
/** * Validate a formatted contribution parameter list. * * @param array $params Structured parameter list (as in crm_format_params) * * @return bool|CRM_Core_Error * @access public */ function _crm_validate_formatted_contribution(&$params) { static $domainID = null; if (!$domainID) { $config =& CRM_Core_Config::singleton(); $domainID = $config->domainID(); } foreach ($params as $key => $value) { switch ($key) { case 'contact_id': if (!CRM_Utils_Rule::integer($value)) { return _crm_error("contact_id not valid: {$value}"); } $dao =& new CRM_Core_DAO(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE domain_id = {$domainID} AND id = {$value}"); if (!$svq) { return _crm_error("there's no contact with contact_id of {$value}"); } break; case 'receive_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': if (!CRM_Utils_Rule::date($value)) { return _crm_error("{$key} not a valid date: {$value}"); } break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': if (!CRM_Utils_Rule::money($value)) { return _crm_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return _crm_error("currency not a valid code: {$value}"); } break; default: break; } } /* Validate custom data fields */ if (is_array($params['custom'])) { foreach ($params['custom'] as $key => $custom) { if (is_array($custom)) { $valid = CRM_Core_BAO_CustomValue::typecheck($custom['type'], $custom['value']); if (!$valid) { return _crm_error('Invalid value for custom field \'' . $custom['name'] . '\''); } if ($custom['type'] == 'Date') { $params['custom'][$key]['value'] = str_replace('-', '', $params['custom'][$key]['value']); } } } } return true; }
/** * take the input parameter list as specified in the data model and * convert it into the same format that we use in QF and BAO object * * @param array $params Associative array of property name/value * pairs to insert in new contact. * @param array $values The reformatted properties that we can use internally * ' * * @return array|CRM_Error * @access public */ function _civicrm_pledgepayment_format_params(&$params, &$values, $create = FALSE) { // copy all the pledge fields as is require_once 'CRM/Pledge/BAO/PledgePayment.php'; require_once 'CRM/Pledge/DAO/Pledge.php'; $fields = CRM_Pledge_DAO_Pledge::fields(); _civicrm_store_values($fields, $params, $values); foreach ($params as $key => $value) { // ignore empty values or empty arrays etc if (CRM_Utils_System::isNull($value)) { continue; } switch ($key) { case 'pledge_contact_id': if (!CRM_Utils_Rule::integer($value)) { return civicrm_create_error("contact_id not valid: {$value}"); } $dao = new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = {$value}", $qParams); if (!$svq) { return civicrm_create_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } $values['contact_id'] = $values['pledge_contact_id']; unset($values['pledge_contact_id']); break; case 'receive_date': case 'end_date': case 'pledge_create_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': if (!CRM_Utils_Rule::date($value)) { return civicrm_create_error("{$key} not a valid date: {$value}"); } break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': if (!CRM_Utils_Rule::money($value)) { return civicrm_create_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return civicrm_create_error("currency not a valid code: {$value}"); } break; case 'pledge_type': $values['pledge_type_id'] = CRM_Utils_Array::key(ucfirst($value), CRM_Pledge_PseudoConstant::pledgeType()); break; case 'payment_instrument': require_once 'CRM/Core/OptionGroup.php'; $values['payment_instrument_id'] = CRM_Core_OptionGroup::getValue('payment_instrument', $value); break; default: break; } } if (array_key_exists('note', $params)) { $values['note'] = $params['note']; } if (array_key_exists('installment_amount', $params)) { $values['installment_amount'] = $params['installment_amount']; } // testing testing - how do I make it take a create_date? It needs $values['create_date'] set but doesn't seem to like it because $fields calls it $pledge_create_date //ditto scheduled date. I don't know why this is needs to be done because I don't fully understand the code above if (array_key_exists('pledge_create_date', $params)) { $values['create_date'] = $params['pledge_create_date']; } if (array_key_exists('pledge_scheduled_date', $params)) { $values['scheduled_date'] = $params['pledge_scheduled_date']; } if (array_key_exists('pledge_create_date', $params)) { $values['create_date'] = $params['pledge_create_date']; } if (array_key_exists('status_id', $params)) { $values['status_id'] = $params['status_id']; $values['pledge_status_id'] = $params['status_id']; } _civicrm_custom_format_params($params, $values, 'Pledge'); if ($create) { // CRM_pledge_BAO_Pledge::add() handles Pledge_source // So, if $values contains Pledge_source, convert it to source $changes = array('pledge_source' => 'source'); foreach ($changes as $orgVal => $changeVal) { if (isset($values[$orgVal])) { $values[$changeVal] = $values[$orgVal]; unset($values[$orgVal]); } } } return array(); }
/** * Validate fields being passed into API. This function relies on the getFields function working accurately * for the given API. If error mode is set to TRUE then it will also check * foreign keys * * As of writing only date was implemented. * @param string $entity * @param string $action * @param array $params - * @param array $fields response from getfields all variables are the same as per civicrm_api * @param bool $errorMode errorMode do intensive post fail checks? * @throws Exception */ function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $errorMode = False) { $fields = array_intersect_key($fields, $params); foreach ($fields as $fieldName => $fieldInfo) { switch (CRM_Utils_Array::value('type', $fieldInfo)) { case CRM_Utils_Type::T_INT: //field is of type integer _civicrm_api3_validate_integer($params, $fieldName, $fieldInfo, $entity); break; case 4: case 12: case CRM_Utils_Type::T_TIMESTAMP: //field is of type date or datetime _civicrm_api3_validate_date($params, $fieldName, $fieldInfo); break; case 32: //blob _civicrm_api3_validate_html($params, $fieldName, $fieldInfo); break; case CRM_Utils_Type::T_STRING: _civicrm_api3_validate_string($params, $fieldName, $fieldInfo, $entity); break; case CRM_Utils_Type::T_MONEY: if (!CRM_Utils_Rule::money($params[$fieldName]) && !empty($params[$fieldName])) { throw new Exception($fieldName . " is not a valid amount: " . $params[$fieldName]); } } // intensive checks - usually only called after DB level fail if (!empty($errorMode) && strtolower($action) == 'create') { if (!empty($fieldInfo['FKClassName'])) { if (!empty($params[$fieldName])) { _civicrm_api3_validate_constraint($params, $fieldName, $fieldInfo); } elseif (!empty($fieldInfo['required'])) { throw new Exception("DB Constraint Violation - possibly {$fieldName} should possibly be marked as mandatory for this API. If so, please raise a bug report"); } } if (!empty($fieldInfo['api.unique'])) { $params['entity'] = $entity; _civicrm_api3_validate_uniquekey($params, $fieldName, $fieldInfo); } } } }
/** * Validate fields being passed into API. * * This function relies on the getFields function working accurately * for the given API. * * As of writing only date was implemented. * * @param string $entity * @param string $action * @param array $params * -. * @param array $fields * Response from getfields all variables are the same as per civicrm_api. * * @throws Exception */ function _civicrm_api3_validate_fields($entity, $action, &$params, $fields) { //CRM-15792 handle datetime for custom fields below code handles chain api call $chainApikeys = array_flip(preg_grep("/^api./", array_keys($params))); if (!empty($chainApikeys) && is_array($chainApikeys)) { foreach ($chainApikeys as $key => $value) { if (is_array($params[$key])) { $chainApiParams = array_intersect_key($fields, $params[$key]); $customFields = array_fill_keys(array_keys($params[$key]), $key); } } } $fields = array_intersect_key($fields, $params); if (!empty($chainApiParams)) { $fields = array_merge($fields, $chainApiParams); } foreach ($fields as $fieldName => $fieldInfo) { switch (CRM_Utils_Array::value('type', $fieldInfo)) { case CRM_Utils_Type::T_INT: //field is of type integer _civicrm_api3_validate_integer($params, $fieldName, $fieldInfo, $entity); break; case CRM_Utils_Type::T_DATE: case CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME: case CRM_Utils_Type::T_TIMESTAMP: //field is of type date or datetime if (!empty($customFields) && array_key_exists($fieldName, $customFields)) { $dateParams =& $params[$customFields[$fieldName]]; } else { $dateParams =& $params; } _civicrm_api3_validate_date($dateParams, $fieldName, $fieldInfo); break; case CRM_Utils_Type::T_TEXT: //blob _civicrm_api3_validate_html($params, $fieldName, $fieldInfo); break; case CRM_Utils_Type::T_STRING: _civicrm_api3_validate_string($params, $fieldName, $fieldInfo, $entity); break; case CRM_Utils_Type::T_MONEY: list($fieldValue, $op) = _civicrm_api3_field_value_check($params, $fieldName); if (strpos($op, 'NULL') !== FALSE || strpos($op, 'EMPTY') !== FALSE) { break; } foreach ((array) $fieldValue as $fieldvalue) { if (!CRM_Utils_Rule::money($fieldvalue) && !empty($fieldvalue)) { throw new Exception($fieldName . " is not a valid amount: " . $params[$fieldName]); } } break; } } }
/** * take the input parameter list as specified in the data model and * convert it into the same format that we use in QF and BAO object * * @param array $params Associative array of property name/value * pairs to insert in new contact. * @param array $values The reformatted properties that we can use internally * ' * * @return array|CRM_Error * @access public */ function _civicrm_contribute_formatted_param(&$params, &$values, $create = FALSE) { // copy all the contribution fields as is $fields = CRM_Contribute_DAO_Contribution::fields(); _civicrm_store_values($fields, $params, $values); require_once 'CRM/Core/OptionGroup.php'; $customFields = CRM_Core_BAO_CustomField::getFields('Contribution'); foreach ($params as $key => $value) { // ignore empty values or empty arrays etc if (CRM_Utils_System::isNull($value)) { continue; } //Handling Custom Data _civicrm_generic_handle_custom_data($key, $value, $values, $customFields); switch ($key) { case 'contribution_contact_id': if (!CRM_Utils_Rule::integer($value)) { return civicrm_create_error("contact_id not valid: {$value}"); } $dao = new CRM_Core_DAO(); $qParams = array(); $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = {$value}", $qParams); if (!$svq) { return civicrm_create_error("Invalid Contact ID: There is no contact record with contact_id = {$value}."); } $values['contact_id'] = $values['contribution_contact_id']; unset($values['contribution_contact_id']); break; case 'contact_type': //import contribution record according to select contact type require_once 'CRM/Contact/DAO/Contact.php'; $contactType = new CRM_Contact_DAO_Contact(); //when insert mode check contact id or external identifire if ($params['contribution_contact_id'] || $params['external_identifier']) { if ($params['contribution_contact_id']) { $contactType->id = $params['contribution_contact_id']; } elseif ($params['external_identifier']) { $contactType->external_identifier = $params['external_identifier']; } if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { return civicrm_create_error("Contact Type is wrong: {$contactType->contact_type}"); } } } elseif ($params['contribution_id'] || $params['trxn_id'] || $params['invoice_id']) { //when update mode check contribution id or trxn id or //invoice id $contactId = new CRM_Contribute_DAO_Contribution(); if ($params['contribution_id']) { $contactId->id = $params['contribution_id']; } elseif ($params['trxn_id']) { $contactId->trxn_id = $params['trxn_id']; } elseif ($params['invoice_id']) { $contactId->invoice_id = $params['invoice_id']; } if ($contactId->find(TRUE)) { $contactType->id = $contactId->contact_id; if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { return civicrm_create_error("Contact Type is wrong: {$contactType->contact_type}"); } } } } break; case 'receive_date': case 'cancel_date': case 'receipt_date': case 'thankyou_date': if (!CRM_Utils_Rule::date($value)) { return civicrm_create_error("{$key} not a valid date: {$value}"); } break; case 'non_deductible_amount': case 'total_amount': case 'fee_amount': case 'net_amount': if (!CRM_Utils_Rule::money($value)) { return civicrm_create_error("{$key} not a valid amount: {$value}"); } break; case 'currency': if (!CRM_Utils_Rule::currencyCode($value)) { return civicrm_create_error("currency not a valid code: {$value}"); } break; case 'contribution_type': require_once 'CRM/Contribute/PseudoConstant.php'; $contriTypes = CRM_Contribute_PseudoConstant::contributionType(); foreach ($contriTypes as $val => $type) { if (strtolower($value) == strtolower($type)) { $values['contribution_type_id'] = $val; break; } } if (!CRM_Utils_Array::value('contribution_type_id', $values)) { return civicrm_create_error("Contribution Type is not valid: {$value}"); } break; case 'payment_instrument': require_once 'CRM/Core/OptionGroup.php'; $values['payment_instrument_id'] = CRM_Core_OptionGroup::getValue('payment_instrument', $value); if (!CRM_Utils_Array::value('payment_instrument_id', $values)) { return civicrm_create_error("Payment Instrument is not valid: {$value}"); } break; case 'contribution_status_id': require_once 'CRM/Core/OptionGroup.php'; if (!($values['contribution_status_id'] = CRM_Core_OptionGroup::getValue('contribution_status', $value))) { return civicrm_create_error("Contribution Status is not valid: {$value}"); } break; case 'honor_type_id': require_once 'CRM/Core/OptionGroup.php'; $values['honor_type_id'] = CRM_Core_OptionGroup::getValue('honor_type', $value); if (!CRM_Utils_Array::value('honor_type_id', $values)) { return civicrm_create_error("Honor Type is not valid: {$value}"); } break; case 'soft_credit': //import contribution record according to select contact type // validate contact id and external identifier. $contactId = CRM_Utils_Array::value('contact_id', $params['soft_credit']); $externalId = CRM_Utils_Array::value('external_identifier', $params['soft_credit']); if ($contactId || $externalId) { require_once 'CRM/Contact/DAO/Contact.php'; $contact = new CRM_Contact_DAO_Contact(); $contact->id = $contactId; $contact->external_identifier = $externalId; $errorMsg = NULL; if (!$contact->find(TRUE)) { $errorMsg = ts("No match found for specified Soft Credit contact data. Row was skipped."); } elseif ($params['contact_type'] != $contact->contact_type) { $errorMsg = ts("Soft Credit Contact Type is wrong: %1", array(1 => $contact->contact_type)); } if ($errorMsg) { return civicrm_create_error($errorMsg, 'soft_credit'); } // finally get soft credit contact id. $values['soft_credit_to'] = $contact->id; } else { // get the contact id from dupicate contact rule, if more than one contact is returned // we should return error, since current interface allows only one-one mapping $softParams = $params['soft_credit']; $softParams['contact_type'] = $params['contact_type']; $error = _civicrm_duplicate_formatted_contact($softParams); if (isset($error['error_message']['params'][0])) { $matchedIDs = explode(',', $error['error_message']['params'][0]); // check if only one contact is found if (count($matchedIDs) > 1) { return civicrm_create_error($error['error_message']['message'], 'soft_credit'); } else { $values['soft_credit_to'] = $matchedIDs[0]; } } else { return civicrm_create_error('No match found for specified Soft Credit contact data. Row was skipped.', 'soft_credit'); } } break; case 'pledge_payment': case 'pledge_id': //giving respect to pledge_payment flag. if (!CRM_Utils_Array::value('pledge_payment', $params)) { continue; } //get total amount of from import fields $totalAmount = CRM_Utils_Array::value('total_amount', $params); $onDuplicate = CRM_Utils_Array::value('onDuplicate', $params); //we need to get contact id $contributionContactID to //retrieve pledge details as well as to validate pledge ID //first need to check for update mode if ($onDuplicate == CRM_Contribute_Import_Parser::DUPLICATE_UPDATE && ($params['contribution_id'] || $params['trxn_id'] || $params['invoice_id'])) { $contribution = new CRM_Contribute_DAO_Contribution(); if ($params['contribution_id']) { $contribution->id = $params['contribution_id']; } elseif ($params['trxn_id']) { $contribution->trxn_id = $params['trxn_id']; } elseif ($params['invoice_id']) { $contribution->invoice_id = $params['invoice_id']; } if ($contribution->find(TRUE)) { $contributionContactID = $contribution->contact_id; if (!$totalAmount) { $totalAmount = $contribution->total_amount; } } else { return civicrm_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } else { // first get the contact id for given contribution record. if (CRM_Utils_Array::value('contribution_contact_id', $params)) { $contributionContactID = $params['contribution_contact_id']; } elseif (CRM_Utils_Array::value('external_identifier', $params)) { require_once 'CRM/Contact/DAO/Contact.php'; $contact = new CRM_Contact_DAO_Contact(); $contact->external_identifier = $params['external_identifier']; if ($contact->find(TRUE)) { $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id; } else { return civicrm_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } else { // we need to get contribution contact using de dupe $error = civicrm_check_contact_dedupe($params); if (isset($error['error_message']['params'][0])) { $matchedIDs = explode(',', $error['error_message']['params'][0]); // check if only one contact is found if (count($matchedIDs) > 1) { return civicrm_create_error($error['error_message']['message'], 'pledge_payment'); } else { $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0]; } } else { return civicrm_create_error('No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment'); } } } if (CRM_Utils_Array::value('pledge_id', $params)) { if (CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $params['pledge_id'], 'contact_id') != $contributionContactID) { return civicrm_create_error('Invalid Pledge ID provided. Contribution row was skipped.', 'pledge_payment'); } $values['pledge_id'] = $params['pledge_id']; } else { //check if there are any pledge related to this contact, with payments pending or in progress require_once 'CRM/Pledge/BAO/Pledge.php'; $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges($contributionContactID); if (empty($pledgeDetails)) { return civicrm_create_error('No open pledges found for this contact. Contribution row was skipped.', 'pledge_payment'); } elseif (count($pledgeDetails) > 1) { return civicrm_create_error('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.', 'pledge_payment'); } // this mean we have only one pending / in progress pledge $values['pledge_id'] = $pledgeDetails[0]; } //we need to check if oldest payment amount equal to contribution amount require_once 'CRM/Pledge/BAO/PledgePayment.php'; $pledgePaymentDetails = CRM_Pledge_BAO_PledgePayment::getOldestPledgePayment($values['pledge_id']); if ($pledgePaymentDetails['amount'] == $totalAmount) { $values['pledge_payment_id'] = $pledgePaymentDetails['id']; } else { return civicrm_create_error('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.', 'pledge_payment'); } break; default: break; } } if (array_key_exists('note', $params)) { $values['note'] = $params['note']; } if ($create) { // CRM_Contribute_BAO_Contribution::add() handles contribution_source // So, if $values contains contribution_source, convert it to source $changes = array('contribution_source' => 'source'); foreach ($changes as $orgVal => $changeVal) { if (isset($values[$orgVal])) { $values[$changeVal] = $values[$orgVal]; unset($values[$orgVal]); } } } return NULL; }