tests/phpunit/CiviTest/civicrm.settings.php
tools/stats/config.php
authors.txt
-drupal/
+/drupal/
+/drupal-8/
WordPress
joomla
packages/
/**
* Access Control Cache.
*/
-class CRM_ACL_BAO_Cache extends CRM_ACL_DAO_Cache {
+class CRM_ACL_BAO_Cache extends CRM_ACL_DAO_ACLCache {
public static $_cache = NULL;
*/
public static function store($id, &$cache) {
foreach ($cache as $aclID => $data) {
- $dao = new CRM_ACL_DAO_Cache();
+ $dao = new CRM_ACL_BAO_Cache();
if ($id) {
$dao->contact_id = $id;
}
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2019
*
- * Generated from xml/schema/CRM/ACL/Cache.xml
+ * Generated from xml/schema/CRM/ACL/ACLCache.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:6180a43e0d4bd8f2008286be6683d0ba)
+ * (GenCodeChecksum:a7bccfc35714fdcf0fdb6f4cd24842bd)
*/
/**
- * Database access object for the Cache entity.
+ * Database access object for the ACLCache entity.
*/
-class CRM_ACL_DAO_Cache extends CRM_Core_DAO {
+class CRM_ACL_DAO_ACLCache extends CRM_Core_DAO {
/**
* Static instance to hold the table name.
'required' => TRUE,
'where' => 'civicrm_acl_cache.id',
'table_name' => 'civicrm_acl_cache',
- 'entity' => 'Cache',
- 'bao' => 'CRM_ACL_BAO_Cache',
+ 'entity' => 'ACLCache',
+ 'bao' => 'CRM_ACL_DAO_ACLCache',
'localizable' => 0,
],
'contact_id' => [
'description' => ts('Foreign Key to Contact'),
'where' => 'civicrm_acl_cache.contact_id',
'table_name' => 'civicrm_acl_cache',
- 'entity' => 'Cache',
- 'bao' => 'CRM_ACL_BAO_Cache',
+ 'entity' => 'ACLCache',
+ 'bao' => 'CRM_ACL_DAO_ACLCache',
'localizable' => 0,
'FKClassName' => 'CRM_Contact_DAO_Contact',
],
'required' => TRUE,
'where' => 'civicrm_acl_cache.acl_id',
'table_name' => 'civicrm_acl_cache',
- 'entity' => 'Cache',
- 'bao' => 'CRM_ACL_BAO_Cache',
+ 'entity' => 'ACLCache',
+ 'bao' => 'CRM_ACL_DAO_ACLCache',
'localizable' => 0,
'FKClassName' => 'CRM_ACL_DAO_ACL',
],
'required' => FALSE,
'where' => 'civicrm_acl_cache.modified_date',
'table_name' => 'civicrm_acl_cache',
- 'entity' => 'Cache',
- 'bao' => 'CRM_ACL_BAO_Cache',
+ 'entity' => 'ACLCache',
+ 'bao' => 'CRM_ACL_DAO_ACLCache',
'localizable' => 0,
],
];
return civicrm_api3('Activity', 'getcount', $activityParams);
}
+ /**
+ * @param int $userID
+ * @param string $subject
+ * @param string $html
+ * @param string $text
+ * @param string $additionalDetails
+ * @param int $campaignID
+ * @param array $attachments
+ *
+ * @return int
+ * The created activity ID
+ * @throws \CRM_Core_Exception
+ */
+ public static function createEmailActivity($userID, $subject, $html, $text, $additionalDetails, $campaignID, $attachments) {
+ $activityTypeID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Email');
+
+ // CRM-6265: save both text and HTML parts in details (if present)
+ if ($html and $text) {
+ $details = "-ALTERNATIVE ITEM 0-\n$html$additionalDetails\n-ALTERNATIVE ITEM 1-\n$text$additionalDetails\n-ALTERNATIVE END-\n";
+ }
+ else {
+ $details = $html ? $html : $text;
+ $details .= $additionalDetails;
+ }
+
+ $activityParams = [
+ 'source_contact_id' => $userID,
+ 'activity_type_id' => $activityTypeID,
+ 'activity_date_time' => date('YmdHis'),
+ 'subject' => $subject,
+ 'details' => $details,
+ // FIXME: check for name Completed and get ID from that lookup
+ 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'status_id', 'Completed'),
+ 'campaign_id' => $campaignID,
+ ];
+
+ // CRM-5916: strip [case #…] before saving the activity (if present in subject)
+ $activityParams['subject'] = preg_replace('/\[case #([0-9a-h]{7})\] /', '', $activityParams['subject']);
+
+ // add the attachments to activity params here
+ if ($attachments) {
+ // first process them
+ $activityParams = array_merge($activityParams, $attachments);
+ }
+
+ $activity = self::create($activityParams);
+
+ return $activity->id;
+ }
+
/**
* Send the message to all the contacts.
*
*
* @return array
* ( sent, activityId) if any email is sent and activityId
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public static function sendEmail(
&$contactDetails,
}
//create the meta level record first ( email activity )
- $activityTypeID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Email');
+ $activityID = self::createEmailActivity($userID, $subject, $html, $text, $additionalDetails, $campaignId, $attachments);
- // CRM-6265: save both text and HTML parts in details (if present)
- if ($html and $text) {
- $details = "-ALTERNATIVE ITEM 0-\n$html$additionalDetails\n-ALTERNATIVE ITEM 1-\n$text$additionalDetails\n-ALTERNATIVE END-\n";
- }
- else {
- $details = $html ? $html : $text;
- $details .= $additionalDetails;
- }
-
- $activityParams = [
- 'source_contact_id' => $userID,
- 'activity_type_id' => $activityTypeID,
- 'activity_date_time' => date('YmdHis'),
- 'subject' => $subject,
- 'details' => $details,
- // FIXME: check for name Completed and get ID from that lookup
- 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'status_id', 'Completed'),
- 'campaign_id' => $campaignId,
- ];
-
- // CRM-5916: strip [case #…] before saving the activity (if present in subject)
- $activityParams['subject'] = preg_replace('/\[case #([0-9a-h]{7})\] /', '', $activityParams['subject']);
-
- // add the attachments to activity params here
- if ($attachments) {
- // first process them
- $activityParams = array_merge($activityParams,
- $attachments
- );
- }
-
- $activity = self::create($activityParams);
-
- // get the set of attachments from where they are stored
- $attachments = CRM_Core_BAO_File::getEntityFile('civicrm_activity',
- $activity->id
- );
$returnProperties = [];
if (isset($messageToken['contact'])) {
foreach ($messageToken['contact'] as $key => $value) {
$tokenText,
$tokenHtml,
$emailAddress,
- $activity->id,
- $attachments,
+ $activityID,
+ // get the set of attachments from where they are stored
+ CRM_Core_BAO_File::getEntityFile('civicrm_activity', $activityID),
$cc,
$bcc
)
}
}
- return [$sent, $activity->id];
+ return [$sent, $activityID];
}
/**
else {
foreach ($value as $clientRole) {
$relClient = [];
- $relClient['relation'] = 'Client';
+ $relClient['relation'] = ts('Client');
$relClient['name'] = $clientRole['sort_name'];
$relClient['phone'] = $clientRole['phone'];
$relClient['email'] = $clientRole['email'];
list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
- $fixUrl = CRM_Utils_System::url("civicrm/admin/domain", 'action=update&reset=1');
- CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid email address in <a href="%1">Administer CiviCRM » Communications » Organization Address and Contact Info</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
+ $fixUrl = CRM_Utils_System::url("civicrm/admin/options/from_email_address", 'action=update&reset=1');
+ CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM » System Settings » Option Groups » From Email Address</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
}
if (!$toEmail) {
CRM_Core_Error::statusBounce(ts('Cannot send a test email because your user record does not have a valid email address.'));
$aid = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Export Accounting Batch');
$activityParams = ['source_record_id' => $values['id'], 'activity_type_id' => $aid];
$exportActivity = CRM_Activity_BAO_Activity::retrieve($activityParams, $val);
- $fid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_EntityFile', $exportActivity->id, 'file_id', 'entity_id');
- $fileHash = CRM_Core_BAO_File::generateFileHash($exportActivity->id, $fid);
- $tokens = array_merge(['eid' => $exportActivity->id, 'fid' => $fid, 'fcs' => $fileHash], $tokens);
+ if ($exportActivity) {
+ $fid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_EntityFile', $exportActivity->id, 'file_id', 'entity_id');
+ $fileHash = CRM_Core_BAO_File::generateFileHash($exportActivity->id, $fid);
+ $tokens = array_merge(['eid' => $exportActivity->id, 'fid' => $fid, 'fcs' => $fileHash], $tokens);
+ }
+ else {
+ CRM_Utils_Array::remove($newLinks, 'export', 'download');
+ }
}
$values['action'] = CRM_Core_Action::formLink(
$newLinks,
$completeStatus = CRM_Contribute_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
$specialFields = [
- 'join_date' => date('Y-m-d'),
+ 'membership_join_date' => date('Y-m-d'),
'receive_date' => $currentDate,
'contribution_status_id' => $completeStatus,
];
}
else {
$dateTypes = [
- 'join_date' => 'joinDate',
+ 'membership_join_date' => 'joinDate',
'membership_start_date' => 'startDate',
'membership_end_date' => 'endDate',
];
$tags = CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', ['onlyActive' => FALSE]);
if (!empty($value)) {
- $val = explode(',', $value);
+ if (is_array($value)) {
+ // Search tag(s) are part of a tag set
+ $val = array_keys($value);
+ }
+ else {
+ // Search tag(s) are part of the tag tree
+ $val = explode(',', $value);
+ }
foreach ($val as $v) {
if ($v) {
$names[] = $tags[$v];
* @param CRM_Activity_BAO_Activity $activity
*/
public static function endPostProcess(&$form, &$params, $activity) {
-
$groupingValues = CRM_Core_OptionGroup::values('case_status', FALSE, TRUE, FALSE, NULL, 'value');
// Set case end_date if we're closing the case. Clear end_date if we're (re)opening it.
// End case-specific relationships (roles)
foreach ($params['target_contact_id'] as $cid) {
$rels = CRM_Case_BAO_Case::getCaseRoles($cid, $params['case_id']);
- // FIXME: Is there an existing function to close a relationship?
- $query = 'UPDATE civicrm_relationship SET end_date=%2 WHERE id=%1';
foreach ($rels as $relId => $relData) {
- $relParams = [
- 1 => [$relId, 'Integer'],
- 2 => [$params['end_date'], 'Timestamp'],
+ $relationshipParams = [
+ 'id' => $relId,
+ 'end_date' => $params['end_date'],
];
- CRM_Core_DAO::executeQuery($query, $relParams);
+ // @todo we can't switch directly to api because there is too much business logic and it breaks closing cases with organisations as client relationships
+ //civicrm_api3('Relationship', 'create', $relationshipParams);
+ CRM_Contact_BAO_Relationship::add($relationshipParams);
}
}
}
// Reopen case-specific relationships (roles)
foreach ($params['target_contact_id'] as $cid) {
$rels = CRM_Case_BAO_Case::getCaseRoles($cid, $params['case_id'], NULL, FALSE);
- // FIXME: Is there an existing function?
- $query = 'UPDATE civicrm_relationship SET end_date=NULL WHERE id=%1';
foreach ($rels as $relId => $relData) {
- $relParams = [1 => [$relId, 'Integer']];
- CRM_Core_DAO::executeQuery($query, $relParams);
+ $relationshipParams = [
+ 'id' => $relId,
+ 'end_date' => 'null',
+ ];
+ // @todo we can't switch directly to api because there is too much business logic and it breaks closing cases with organisations as client relationships
+ //civicrm_api3('Relationship', 'create', $relationshipParams);
+ CRM_Contact_BAO_Relationship::add($relationshipParams);
}
}
}
foreach ($xml->CaseRoles as $caseRoleXML) {
foreach ($caseRoleXML->RelationshipType as $relationshipTypeXML) {
if ((int ) $relationshipTypeXML->creator == 1) {
- if (!$this->createRelationships((string ) $relationshipTypeXML->name,
+ if (!$this->createRelationships($this->locateNameOrLabel($relationshipTypeXML),
$params
)
) {
return $default;
}
+ /**
+ * At some point name and label got mixed up for case roles.
+ * Check for higher priority tag <machineName> first which represents name, then fall back to the <name> tag which somehow became label.
+ * We do this to avoid requiring people to update their xml files which can be stored in external files.
+ *
+ * Note this is different than doing something like comparing the <name> tag against name in the database and then falling back to comparing label in the database, which is subject to an edge case where you would get the wrong one (where the label of one relationship type is the same as the name of another). Here there are two tags with explicit single meanings.
+ *
+ * @param SimpleXMLElement $xml
+ *
+ * @return string
+ */
+ public function locateNameOrLabel($xml) {
+ /* While it's unlikely, it's possible somebody is using '0' as their machineName, so we should let them.
+ * Specifically if machineName is:
+ * missing - use name
+ * null - use name
+ * blank - use name
+ * the string '0' - use machineName
+ * the number 0 - use machineName (but can't really have number 0 in simplexml unless cast to number)
+ * the word 'null' - use machineName and best not to think about it
+ */
+ if (isset($xml->machineName)) {
+ $machineName = (string) $xml->machineName;
+ if ($machineName !== '') {
+ return $machineName;
+ }
+ }
+ return (string) $xml->name;
+ }
+
}
*
*/
public static function buildOnBehalfForm(&$form, $contactType, $countryID, $stateID, $title) {
-
- $config = CRM_Core_Config::singleton();
-
$form->assign('contact_type', $contactType);
$form->assign('fieldSetTitle', $title);
$form->assign('contactEditMode', TRUE);
);
}
- $addressSequence = $config->addressSequence();
+ $addressSequence = CRM_Utils_Address::sequence(\Civi::settings()->get('address_format'));
$form->assign('addressSequence', array_fill_keys($addressSequence, 1));
//Primary Phone
self::filterCountryFromValuesIfStateExists($formValues);
// We shouldn't have to whitelist fields to not hack but here we are, for now.
- $nonLegacyDateFields = ['participant_register_date_relative', 'receive_date_relative'];
+ $nonLegacyDateFields = [
+ 'participant_register_date_relative',
+ 'receive_date_relative',
+ 'pledge_end_date_relative',
+ 'pledge_create_date_relative',
+ 'pledge_start_date_relative',
+ 'pledge_payment_scheduled_date_relative',
+ 'membership_join_date_relative',
+ 'membership_start_date_relative',
+ 'membership_end_date_relative',
+ ];
// Handle relative dates first
foreach (array_keys($formValues) as $id) {
if (
$this->buildRelativeDateQuery($values);
return;
}
+ // @todo also handle _low, _high generically here with if ($query->buildDateRangeQuery($values)) {return}
// do not process custom fields or prefixed contact ids or component params
if (CRM_Core_BAO_CustomField::getKeyID($values[0]) ||
* @param string $dateFormat
*/
public function dateQueryBuilder(
- &$values, $tableName, $fieldName,
+ $values, $tableName, $fieldName,
$dbFieldName, $fieldTitle,
$appendTimeStamp = TRUE,
$dateFormat = 'YmdHis'
return isset($this->_fields[$realField]);
}
+ /**
+ * Get the specifications for the field, if available.
+ *
+ * @param string $fieldName
+ * Fieldname as displayed on the form.
+ *
+ * @return array
+ */
+ public function getFieldSpec($fieldName) {
+ if (isset($this->_fields[$fieldName])) {
+ return $this->_fields[$fieldName];
+ }
+ $lowFieldName = str_replace('_low', '', $fieldName);
+ if (isset($this->_fields[$lowFieldName])) {
+ return array_merge($this->_fields[$lowFieldName], ['field_name' => $lowFieldName]);
+ }
+ $highFieldName = str_replace('_high', '', $fieldName);
+ if (isset($this->_fields[$highFieldName])) {
+ return array_merge($this->_fields[$highFieldName], ['field_name' => $highFieldName]);
+ }
+ return [];
+ }
+
+ public function buildWhereForDate() {
+
+ }
+
+ /**
+ * Is the field a relative date field.
+ *
+ * @param string $fieldName
+ *
+ * @return bool
+ */
+ protected function isADateRangeField($fieldName) {
+ if (substr($fieldName, -4, 4) !== '_low' && substr($fieldName, -5, 5) !== '_high') {
+ return FALSE;
+ }
+ return !empty($this->getFieldSpec($fieldName));
+ }
+
/**
* @param $values
*/
}
}
+ /**
+ * Build the query for a date field if it is a _high or _low field.
+ *
+ * @param $values
+ *
+ * @return bool
+ */
+ public function buildDateRangeQuery($values) {
+ if ($this->isADateRangeField($values[0])) {
+ $fieldSpec = $this->getFieldSpec($values[0]);
+ $title = empty($fieldSpec['unique_title']) ? $fieldSpec['title'] : $fieldSpec['unique_title'];
+ $this->dateQueryBuilder($values, $fieldSpec['table_name'], $fieldSpec['field_name'], $fieldSpec['name'], $title);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
/**
* Add the address table into the query.
*
$hook = 'edit';
}
+ // @todo pre hook is called from add - remove it from here
CRM_Utils_Hook::pre($hook, 'Relationship', $relationshipId, $params);
if (!$relationshipId) {
if ($params['id']) {
$hook = 'edit';
}
- //@todo hook are called from create and add - remove one
CRM_Utils_Hook::pre($hook, 'Relationship', $params['id'], $params);
$relationshipTypes = CRM_Utils_Array::value('relationship_type_id', $params);
-
// explode the string with _ to get the relationship type id
// and to know which contact has to be inserted in
// contact_id_a and which one in contact_id_b
- list($type) = explode('_', $relationshipTypes);
+ list($relationshipTypeID) = explode('_', $relationshipTypes);
+
+ $relationship = new CRM_Contact_BAO_Relationship();
+ if (!empty($params['id'])) {
+ $relationship->id = $params['id'];
+ // Only load the relationship if we're missing required params
+ $requiredParams = ['contact_id_a', 'contact_id_b', 'relationship_type_id'];
+ foreach ($requiredParams as $requiredKey) {
+ if (!isset($params[$requiredKey])) {
+ $relationship->find(TRUE);
+ break;
+ }
+ }
+
+ }
+ $relationship->copyValues($params);
+ // @todo we could probably set $params['relationship_type_id'] above but it's unclear
+ // what that would do with the code below this. So for now be conservative and set it manually.
+ if (!empty($relationshipTypeID)) {
+ $relationship->relationship_type_id = $relationshipTypeID;
+ }
+
+ $params['contact_id_a'] = $relationship->contact_id_a;
+ $params['contact_id_b'] = $relationship->contact_id_b;
// check if the relationship type is Head of Household then update the
// household's primary contact with this contact.
- if ($type == 6) {
- CRM_Contact_BAO_Household::updatePrimaryContact($params['contact_id_b'], $params['contact_id_a']);
+ try {
+ $headOfHouseHoldID = civicrm_api3('RelationshipType', 'getvalue', [
+ 'return' => "id",
+ 'name_a_b' => "Head of Household for",
+ ]);
+ if ($relationshipTypeID == $headOfHouseHoldID) {
+ CRM_Contact_BAO_Household::updatePrimaryContact($relationship->contact_id_b, $relationship->contact_id_a);
+ }
}
- if (!empty($params['id']) && self::isCurrentEmployerNeedingToBeCleared($params, $params['id'], $type)) {
- CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($params['contact_id_a']);
+ catch (Exception $e) {
+ // No "Head of Household" relationship found so we skip specific processing
}
- $relationship = new CRM_Contact_BAO_Relationship();
- //@todo this code needs to be updated for the possibility that not all fields are set
- // by using $relationship->copyValues($params);
- // (update)
- $relationship->contact_id_b = $params['contact_id_b'];
- $relationship->contact_id_a = $params['contact_id_a'];
- $relationship->relationship_type_id = $type;
- $relationship->id = $params['id'];
+ if (!empty($params['id']) && self::isCurrentEmployerNeedingToBeCleared($relationship->toArray(), $params['id'], $relationshipTypeID)) {
+ CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($relationship->contact_id_a);
+ }
$dateFields = ['end_date', 'start_date'];
* @param bool $active
*
* @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = TRUE) {
// Check the end date and set the status of the relationship
$mainRelatedContactId = reset($relatedContacts);
foreach ($details['memberships'] as $membershipId => $membershipValues) {
+ $membershipInherittedFromContactID = NULL;
+ if (!empty($membershipValues['owner_membership_id'])) {
+ // Use get not getsingle so that we get e-notice noise but not a fatal is the membership has already been deleted.
+ $inheritedFromMembership = civicrm_api3('Membership', 'get', ['id' => $membershipValues['owner_membership_id'], 'sequential' => 1])['values'][0];
+ $membershipInherittedFromContactID = (int) $inheritedFromMembership['contact_id'];
+ }
$relTypeIds = [];
if ($action & CRM_Core_Action::DELETE) {
// @todo don't return relTypeId here - but it seems to be used later in a cryptic way (hint cryptic is not a complement).
if (!empty($membershipValues['status_id']) && $membershipValues['status_id'] == $pendingStatusId) {
$membershipValues['skipStatusCal'] = TRUE;
}
-
- // check whether we have some related memberships still available
- $query = "
-SELECT count(*)
- FROM civicrm_membership
- LEFT JOIN civicrm_membership_status ON (civicrm_membership_status.id = civicrm_membership.status_id)
- WHERE membership_type_id = {$membershipValues['membership_type_id']} AND owner_membership_id = {$membershipValues['owner_membership_id']}
- AND is_current_member = 1";
- $result = CRM_Core_DAO::singleValueQuery($query);
- if ($result < CRM_Utils_Array::value('max_related', $membershipValues, PHP_INT_MAX)) {
- CRM_Member_BAO_Membership::create($membershipValues);
+ // As long as the membership itself was not created by inheritance from the same contact
+ // that stands to inherit the membership we add an inherited membership.
+ if ($membershipInherittedFromContactID !== (int) $membershipValues['contact_id']) {
+ $membershipValues = self::addInheritedMembership($membershipValues);
}
}
}
return [implode(',', $relTypeIds), $isDeletable];
}
+ /**
+ * Add an inherited membership, provided max related not exceeded.
+ *
+ * @param array $membershipValues
+ *
+ * @return array
+ * @throws \CRM_Core_Exception
+ */
+ protected static function addInheritedMembership($membershipValues) {
+ $query = "
+SELECT count(*)
+ FROM civicrm_membership
+ LEFT JOIN civicrm_membership_status ON (civicrm_membership_status.id = civicrm_membership.status_id)
+ WHERE membership_type_id = {$membershipValues['membership_type_id']}
+ AND owner_membership_id = {$membershipValues['owner_membership_id']}
+ AND is_current_member = 1";
+ $result = CRM_Core_DAO::singleValueQuery($query);
+ if ($result < CRM_Utils_Array::value('max_related', $membershipValues, PHP_INT_MAX)) {
+ CRM_Member_BAO_Membership::create($membershipValues);
+ }
+ return $membershipValues;
+ }
+
}
// This is required only until all fields are converted to datepicker fields as the new format is truer to the
// form format and simply saves (e.g) custom_3_relative => "this.year"
$relativeDates = ['relative_dates' => []];
- $specialDateFields = ['event_relative', 'case_from_relative', 'case_to_relative', 'participant_relative'];
+ $specialDateFields = [
+ 'event_relative',
+ 'case_from_relative',
+ 'case_to_relative',
+ 'participant_relative',
+ 'log_date_relative',
+ 'birth_date_relative',
+ 'deceased_date_relative',
+ 'mailing_date_relative',
+ 'relation_date_relative',
+ 'relation_start_date_relative',
+ 'relation_end_date_relative',
+ 'relation_action_date_relative',
+ ];
foreach ($formValues as $id => $value) {
- if ((preg_match('/_date$/', $id) || in_array($id, $specialDateFields)) && !empty($value)) {
+ if (in_array($id, $specialDateFields) && !empty($value)) {
$entityName = strstr($id, '_date', TRUE);
if (empty($entityName)) {
$entityName = strstr($id, '_relative', TRUE);
*
* Generated from xml/schema/CRM/Contact/Contact.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:bd37bd31a0ac8ba4fd5f411fddef080b)
+ * (GenCodeChecksum:ee3bf9f2d1faed5a4de439ecf0537ac6)
*/
/**
'type' => CRM_Utils_Type::T_INT,
'title' => ts('Communication Style'),
'description' => ts('Communication style (e.g. formal vs. familiar) to use with this contact. FK to communication styles in civicrm_option_value.'),
+ 'import' => TRUE,
'where' => 'civicrm_contact.communication_style_id',
+ 'headerPattern' => '/style/i',
'export' => TRUE,
'table_name' => 'civicrm_contact',
'entity' => 'Contact',
'localizable' => FALSE,
'sig' => 'civicrm_contact::0::is_deleted::sort_name::id',
],
+ 'index_created_date' => [
+ 'name' => 'index_created_date',
+ 'field' => [
+ 0 => 'created_date',
+ ],
+ 'localizable' => FALSE,
+ 'sig' => 'civicrm_contact::0::created_date',
+ ],
+ 'index_modified_date' => [
+ 'name' => 'index_modified_date',
+ 'field' => [
+ 0 => 'modified_date',
+ ],
+ 'localizable' => FALSE,
+ 'sig' => 'civicrm_contact::0::modified_date',
+ ],
];
return ($localize && !empty($indices)) ? CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices;
}
$displayName = CRM_Contact_BAO_Contact::displayName($this->_contactId);
if ($defaults['is_deceased']) {
- $displayName .= ' <span class="crm-contact-deceased">(deceased)</span>';
+ $displayName .= ' <span class="crm-contact-deceased">(' . ts('deceased') . ')</span>';
}
$displayName = ts('Edit %1', [1 => $displayName]);
CRM_Core_Session::singleton()->pushUserContext($browseUrl);
}
- $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid, json_decode($this->criteria, TRUE));
+ $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid, json_decode($this->criteria, TRUE), TRUE, $this->limit);
$join = CRM_Dedupe_Merger::getJoinOnDedupeTable();
$where = "de.id IS NULL";
}
if ($this->next && $this->_mergeId) {
- $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid, json_decode($this->criteria, TRUE));
+ $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid, json_decode($this->criteria, TRUE), TRUE, $this->limit);
$join = CRM_Dedupe_Merger::getJoinOnDedupeTable();
$where = "de.id IS NULL";
else {
$savedMapping = $this->get('savedMapping');
- list($mappingName, $mappingContactType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $mappingRelation, $mappingOperator, $mappingValue, $mappingWebsiteType) = CRM_Core_BAO_Mapping::getMappingFields($savedMapping, TRUE);
+ list($mappingName) = CRM_Core_BAO_Mapping::getMappingFields($savedMapping, TRUE);
//get loaded Mapping Fields
$mappingName = CRM_Utils_Array::value(1, $mappingName);
- $mappingLocation = CRM_Utils_Array::value(1, $mappingLocation);
- $mappingRelation = CRM_Utils_Array::value(1, $mappingRelation);
- $mappingWebsiteType = CRM_Utils_Array::value(1, $mappingWebsiteType);
$this->assign('loadedMapping', $savedMapping);
$this->set('loadedMapping', $savedMapping);
$processor->setMappingID($savedMappingID);
$processor->setFormName($formName);
$processor->setMetadata($this->getContactImportMetadata());
+ $processor->setContactTypeByConstant($this->get('contactType'));
+ $processor->setContactSubType($this->get('contactSubType'));
for ($i = 0; $i < $this->_columnCount; $i++) {
$sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);
if ($this->get('savedMapping')) {
- list($defaults, $js) = $this->loadSavedMapping($processor, $mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns);
+ list($defaults, $js) = $this->loadSavedMapping($processor, $mappingName, $i, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns);
}
else {
$js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
elseif (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'im') {
$updateMappingFields->im_provider_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
}
- $updateMappingFields->location_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
+ $updateMappingFields->location_type_id = isset($mapperKeys[$i][2]) && is_numeric($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
}
}
else {
* @param \CRM_Import_ImportProcessor $processor
* @param $mappingName
* @param int $i
- * @param $mappingRelation
- * @param $mappingWebsiteType
- * @param $mappingLocation
* @param array $defaults
* @param string $js
* @param bool $hasColumnNames
* @return array
* @throws \CiviCRM_API3_Exception
*/
- public function loadSavedMapping($processor, $mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns) {
- $jsSet = FALSE;
+ public function loadSavedMapping($processor, $mappingName, $i, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns) {
$formName = $processor->getFormName();
if (isset($mappingName[$i])) {
if ($mappingName[$i] != ts('- do not import -')) {
-
- if (isset($mappingRelation[$i])) {
- // relationship mapping
- switch ($this->get('contactType')) {
- case CRM_Import_Parser::CONTACT_INDIVIDUAL:
- $contactType = 'Individual';
- break;
-
- case CRM_Import_Parser::CONTACT_HOUSEHOLD:
- $contactType = 'Household';
- break;
-
- case CRM_Import_Parser::CONTACT_ORGANIZATION:
- $contactType = 'Organization';
- }
- //CRM-5125
- $contactSubType = NULL;
- if ($this->get('contactSubType')) {
- $contactSubType = $this->get('contactSubType');
- }
-
- $relations = CRM_Contact_BAO_Relationship::getContactRelationshipType(NULL, NULL, NULL, $contactType,
- FALSE, 'label', TRUE, $contactSubType
- );
-
- foreach ($relations as $key => $var) {
- if ($key == $mappingRelation[$i]) {
- $relation = $key;
- break;
- }
- }
-
- $contactDetails = strtolower(str_replace(" ", "_", $mappingName[$i]));
- $websiteTypeId = isset($mappingWebsiteType[$i]) ? $mappingWebsiteType[$i] : NULL;
- $locationId = isset($mappingLocation[$i]) ? $mappingLocation[$i] : 0;
- $phoneType = $processor->getPhoneTypeID($i);
- $imProvider = $processor->getIMProviderID($i);
-
- if ($websiteTypeId) {
- $defaults["mapper[$i]"] = [$relation, $contactDetails, $websiteTypeId];
- if (!$websiteTypeId) {
- $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
- }
- }
- else {
- // default for IM/phone when mapping with relation is true
- $typeId = NULL;
- if (isset($phoneType)) {
- $typeId = $phoneType;
- }
- elseif (isset($imProvider)) {
- $typeId = $imProvider;
- }
- $defaults["mapper[$i]"] = [$relation, $contactDetails, $locationId, $typeId];
- if (!$locationId) {
- $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
- }
- }
- // fix for edge cases, CRM-4954
- if ($contactDetails == 'image_url') {
- $contactDetails = str_replace('url', 'URL', $contactDetails);
- }
-
- if (!$contactDetails) {
- $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
- }
-
- if ((!$phoneType) && (!$imProvider)) {
- $js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
- }
- //$js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
- $jsSet = TRUE;
- }
- else {
- $mappingHeader = array_keys((array) $this->_mapperFields, $mappingName[$i]);
- $websiteTypeId = isset($mappingWebsiteType[$i]) ? $mappingWebsiteType[$i] : NULL;
- $locationId = isset($mappingLocation[$i]) ? $mappingLocation[$i] : 0;
- $phoneType = $processor->getPhoneTypeID($i);
- $imProvider = $processor->getIMProviderID($i);
-
- if ($websiteTypeId) {
- $defaults["mapper[$i]"] = [$mappingHeader[0], $websiteTypeId];
- }
- else {
- if (!$locationId) {
- $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
- }
- //default for IM/phone without related contact
- $typeId = NULL;
- if (isset($phoneType)) {
- $typeId = $phoneType;
- }
- elseif (isset($imProvider)) {
- $typeId = $imProvider;
- }
- $defaults["mapper[$i]"] = [$mappingHeader[0] ?? '', $locationId, $typeId];
- }
-
- if ((!$phoneType) && (!$imProvider)) {
- $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
- }
-
- $js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
-
- $jsSet = TRUE;
- }
+ $defaults["mapper[$i]"] = $processor->getSavedQuickformDefaultsForColumn($i);
+ $js .= $processor->getQuickFormJSForField($i);
}
else {
$defaults["mapper[$i]"] = [];
- }
- if (!$jsSet) {
for ($k = 1; $k < 4; $k++) {
$js .= "{$formName}['mapper[$i][$k]'].style.display = 'none';\n";
}
if (!array_key_exists($blockFieldName, $values)) {
continue;
}
+ $blockIndex = $values['location_type_id'] . (!empty($values['phone_type_id']) ? '_' . $values['phone_type_id'] : '');
// block present in value array.
if (!array_key_exists($blockFieldName, $params) || !is_array($params[$blockFieldName])) {
}
_civicrm_api3_store_values($fields[$block], $values,
- $params[$blockFieldName][$values['location_type_id']]
+ $params[$blockFieldName][$blockIndex]
);
- $this->fillPrimary($params[$blockFieldName][$values['location_type_id']], $values, $block, CRM_Utils_Array::value('id', $params));
+ $this->fillPrimary($params[$blockFieldName][$blockIndex], $values, $block, CRM_Utils_Array::value('id', $params));
if (empty($params['id']) && (count($params[$blockFieldName]) == 1)) {
- $params[$blockFieldName][$values['location_type_id']]['is_primary'] = TRUE;
+ $params[$blockFieldName][$blockIndex]['is_primary'] = TRUE;
}
// we only process single block at a time.
$gid = CRM_Utils_Request::retrieve('gid', 'Positive');
$rgid = CRM_Utils_Request::retrieve('rgid', 'Positive');
+ $limit = CRM_Utils_Request::retrieveValue('limit', 'Positive', 0);
$null = NULL;
$criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $null, FALSE, '{}');
$selected = CRM_Utils_Request::retrieveValue('selected', 'Boolean');
}
$whereClause = $orderByClause = '';
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE));
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE), TRUE, $limit);
$searchRows = [];
'reset' => 1,
'rgid' => $rgid,
'gid' => $gid,
- 'limit' => $limit,
+ 'limit' => (int) $limit,
'criteria' => $criteria,
];
$this->assign('urlQuery', CRM_Utils_System::makeQueryString($urlQry));
$this->assign('isSelected', $this->isSelected());
$criteria = json_decode($criteria, TRUE);
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria);
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria, TRUE, $limit);
$this->assign('cacheKey', $cacheKeyString);
if ($context == 'search') {
}
elseif ($action & CRM_Core_Action::MAP) {
// do a batch merge if requested
- $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', 75, 2, $criteria);
+ $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', 75, 2, $criteria, TRUE, NULL, $limit);
$skippedCount = CRM_Utils_Request::retrieve('skipped', 'Positive', $this, FALSE, 0);
$skippedCount = $skippedCount + count($result['skipped']);
];
$criteria = json_decode($criteria, TRUE);
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria);
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria, TRUE, $limit);
if ($mode == 'aggressive' && !CRM_Core_Permission::check('force merge duplicate contacts')) {
CRM_Core_Session::setStatus(ts('You do not have permission to force merge duplicate contact records'), ts('Permission Denied'), 'error');
for ($i = 1; $i <= ceil($total / self::BATCHLIMIT); $i++) {
$task = new CRM_Queue_Task(
['CRM_Contact_Page_DedupeMerge', 'callBatchMerge'],
- [$rgid, $gid, $mode, self::BATCHLIMIT, $onlyProcessSelected, $criteria],
+ [$rgid, $gid, $mode, self::BATCHLIMIT, $onlyProcessSelected, $criteria, $limit],
"Processed " . $i * self::BATCHLIMIT . " pair of duplicates out of " . $total
);
* @param int $batchLimit
* @param int $isSelected
* @param array $criteria
+ * @param int $searchLimit
*
* @return int
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
- public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $batchLimit, $isSelected, $criteria) {
- CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $batchLimit, $isSelected, $criteria, TRUE, FALSE);
+ public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $batchLimit, $isSelected, $criteria, $searchLimit) {
+ CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $batchLimit, $isSelected, $criteria, TRUE, FALSE, $searchLimit);
return CRM_Queue_Task::TASK_SUCCESS;
}
// set page title
$title = "{$contactImage} {$displayName}";
if ($contactDetails[$contactId]['isDeceased']) {
- $title .= ' <span class="crm-contact-deceased">(deceased)</span>';
+ $title .= ' <span class="crm-contact-deceased">(' . ts('deceased') . ')</span>';
}
if ($isDeleted) {
$title = "<del>{$title}</del>";
* @return array
*/
protected static function cancel($processContributionObject, $memberships, $contributionId, $membershipStatuses, $updateResult, $participant, $oldStatus, $pledgePayment, $pledgeID, $pledgePaymentIDs, $contributionStatusId) {
+ // @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
$processContribution = FALSE;
$participantStatuses = CRM_Event_PseudoConstant::participantStatus();
if (is_array($memberships)) {
return [TRUE, $isARefund];
}
+ /**
+ * It is possible to override the membership id that is updated from the payment processor.
+ *
+ * Historically Paypal does this & it still does if it determines data is messed up - see
+ * https://lab.civicrm.org/dev/membership/issues/13
+ *
+ * Read the comment block on repeattransaction for more information
+ * about how things should work.
+ *
+ * @param int $contributionID
+ * @param array $input
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+ protected static function handleMembershipIDOverride($contributionID, $input) {
+ if (!empty($input['membership_id'])) {
+ Civi::log()->debug('The related membership id has been overridden - this may impact data - see https://github.com/civicrm/civicrm-core/pull/15053');
+ civicrm_api3('MembershipPayment', 'create', ['contribution_id' => $contributionID, 'membership_id' => $input['membership_id']]);
+ }
+ }
+
/**
* @inheritDoc
*/
/**
* Repeat a transaction as part of a recurring series.
*
- * Only call this via the api as it is being refactored. The intention is that the repeatTransaction function
- * (possibly living on the ContributionRecur BAO) would be called first to create a pending contribution with a
- * subsequent call to the contribution.completetransaction api.
- *
- * The completeTransaction functionality has historically been overloaded to both complete and repeat payments.
+ * The ideal flow is
+ * 1) Processor calls contribution.repeattransaction with contribution_status_id = Pending
+ * 2) The repeattransaction loads the 'template contribution' and calls a hook to allow altering of it .
+ * 3) Repeat transaction calls order.create to create the pending contribution with correct line items
+ * and associated entities.
+ * 4) The calling code calls Payment.create which in turn calls CompleteOrder (if completing)
+ * which updates the various entities and sends appropriate emails.
+ *
+ * Gaps in the above (@todo)
+ * 1) many processors still call repeattransaction with contribution_status_id = Completed
+ * 2) repeattransaction code is current munged into completeTransaction code for historical bad coding reasons
+ * 3) Repeat transaction duplicates rather than calls Order.create
+ * 4) Use of payment.create still limited - completetransaction is more common.
+ * 5) the template transaction is tricky - historically we used the first contribution
+ * linked to a recurring contribution. More recently that was changed to be the most recent.
+ * Ideally it would be an actual template - not a contribution used as a template which
+ * would give more appropriate flexibility. Note line_items have an entity so that table
+ * could be used for the line item template - the difficulty is the custom fields...
+ * 6) the determination of the membership to be linked is tricksy. The prioritised method is
+ * to load the membership(s) referred to via line items in the template transactions. Any other
+ * method is likely to lead to incorrect line items & related entities being created (as the line_item
+ * link is a required part of 'correct data'). However there are 3 other methods to determine it
+ * - membership_payment record
+ * - civicrm_membership.contribution_recur_id
+ * - input override.
+ * Passing in an input override WILL ensure the membership is extended to prevent regressions
+ * of historical processors since this has been handled 'forever' - specifically for paypal.
+ * albeit by an even nastier mechanism than the current input override.
+ * The count is out on how correct related entities wind up in this case.
*
* @param CRM_Contribute_BAO_Contribution $contribution
* @param array $input
$createContribution = civicrm_api3('Contribution', 'create', $contributionParams);
$contribution->id = $createContribution['id'];
CRM_Contribute_BAO_ContributionRecur::copyCustomValues($contributionParams['contribution_recur_id'], $contribution->id);
+ self::handleMembershipIDOverride($contribution->id, $input);
return TRUE;
}
}
return FALSE;
}
- /**
- * Function to record additional payment for partial and refund contributions.
- *
- * @param int $contributionId
- * is the invoice contribution id (got created after processing participant payment).
- * @param array $trxnsData
- * to take user provided input of transaction details.
- * @param string $paymentType
- * 'owed' for purpose of recording partial payments, 'refund' for purpose of recording refund payments.
- * @param int $participantId
- * @param bool $updateStatus
- *
- * @return int
- *
- * @throws \CRM_Core_Exception
- * @throws \CiviCRM_API3_Exception
- */
- public static function recordAdditionalPayment($contributionId, $trxnsData, $paymentType = 'owed', $participantId = NULL, $updateStatus = TRUE) {
-
- if ($paymentType == 'owed') {
- $financialTrxn = CRM_Financial_BAO_Payment::recordPayment($contributionId, $trxnsData, $participantId);
- if (!empty($financialTrxn)) {
- self::recordPaymentActivity($contributionId, $participantId, $financialTrxn->total_amount, $financialTrxn->currency, $financialTrxn->trxn_date);
- return $financialTrxn->id;
- }
- }
- elseif ($paymentType == 'refund') {
- $trxnsData['total_amount'] = -$trxnsData['total_amount'];
- $trxnsData['participant_id'] = $participantId;
- $trxnsData['contribution_id'] = $contributionId;
- return civicrm_api3('Payment', 'create', $trxnsData)['id'];
- }
- }
-
/**
* @param int $targetCid
* @param $activityType
$recur->cancel_date = date('YmdHis');
$recur->save();
+ // @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
$dao = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recurId);
if ($dao && $dao->recur_id) {
$details = CRM_Utils_Array::value('details', $activityParams);
public $_action = NULL;
+ /**
+ * Pre process form.
+ *
+ * @throws \CRM_Core_Exception
+ */
public function preProcess() {
$this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this, TRUE);
$this->_paymentType = 'owed';
}
else {
- CRM_Core_Error::fatal(ts('No payment information found for this record'));
+ throw new CRM_Core_Exception(ts('No payment information found for this record'));
}
if (!empty($this->_mode) && $this->_paymentType == 'refund') {
- CRM_Core_Error::fatal(ts('Credit card payment is not for Refund payments use'));
+ throw new CRM_Core_Exception(ts('Credit card payment is not for Refund payments use'));
}
list($this->_contributorDisplayName, $this->_contributorEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
* Is this function being called from a datatable selector.
*
* If so we don't want to show the buttons.
+ *
+ * @throws \CRM_Core_Exception
*/
protected function isBeingCalledFromSelectorContext() {
return CRM_Utils_Request::retrieve('selector', 'Positive');
$this->processCreditCard();
}
- $defaults = [];
- $contribution = civicrm_api3('Contribution', 'getsingle', [
- 'return' => ["contribution_status_id"],
- 'id' => $this->_contributionId,
- ]);
- $contributionStatusId = CRM_Utils_Array::value('contribution_status_id', $contribution);
- $paymentID = CRM_Contribute_BAO_Contribution::recordAdditionalPayment($this->_contributionId, $this->_params, $this->_paymentType, $participantId);
- // Fetch the contribution & do proportional line item assignment
- $params = ['id' => $this->_contributionId];
- $contribution = CRM_Contribute_BAO_Contribution::retrieve($params, $defaults, $params);
- // @todo - this line needs to be moved to the Payment.create api - it's not form layer appropriate.
- // testing required.
- CRM_Contribute_BAO_Contribution::addPayments([$contribution], $contributionStatusId);
+ $trxnsData = $this->_params;
+ if ($this->_paymentType == 'refund') {
+ $trxnsData['total_amount'] = -$trxnsData['total_amount'];
+ }
+ $trxnsData['participant_id'] = $participantId;
+ $trxnsData['contribution_id'] = $this->_contributionId;
+ // From the
+ $trxnsData['is_send_contribution_notification'] = FALSE;
+ $paymentID = civicrm_api3('Payment', 'create', $trxnsData)['id'];
+
if ($this->_contributionId && CRM_Core_Permission::access('CiviMember')) {
$membershipPaymentCount = civicrm_api3('MembershipPayment', 'getCount', ['contribution_id' => $this->_contributionId]);
if ($membershipPaymentCount) {
$membershipTypeIDs = (array) $membershipParams['selectMembership'];
$membershipTypes = CRM_Member_BAO_Membership::buildMembershipTypeValues($this, $membershipTypeIDs);
$membershipType = empty($membershipTypes) ? [] : reset($membershipTypes);
- $isPending = $this->getIsPending();
$this->assign('membership_name', CRM_Utils_Array::value('name', $membershipType));
$this->_values['membership_name'] = CRM_Utils_Array::value('name', $membershipType);
$this->postProcessMembership($membershipParams, $contactID,
$this, $premiumParams, $customFieldsFormatted, $fieldTypes, $membershipType, $membershipTypeIDs, $isPaidMembership, $this->_membershipId, $isProcessSeparateMembershipTransaction, $financialTypeID,
- $membershipLineItems, $isPending);
+ $membershipLineItems);
$this->assign('membership_assign', TRUE);
$this->set('membershipTypeID', $membershipParams['selectMembership']);
* @param int $financialTypeID
* @param array $unprocessedLineItems
* Line items for payment options chosen on the form.
- * @param bool $isPending
*
* @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ * @throws \Civi\Payment\Exception\PaymentProcessorException
*/
protected function postProcessMembership(
$membershipParams, $contactID, &$form, $premiumParams,
$customFieldsFormatted = NULL, $includeFieldTypes = NULL, $membershipDetails, $membershipTypeIDs, $isPaidMembership, $membershipID,
- $isProcessSeparateMembershipTransaction, $financialTypeID, $unprocessedLineItems, $isPending) {
+ $isProcessSeparateMembershipTransaction, $financialTypeID, $unprocessedLineItems) {
$membershipContribution = NULL;
$isTest = CRM_Utils_Array::value('is_test', $membershipParams, FALSE);
}
$i++;
$numTerms = CRM_Utils_Array::value($memType, $typesTerms, 1);
- if (!empty($membershipContribution)) {
- $pendingStatus = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
- $pending = ($membershipContribution->contribution_status_id == $pendingStatus) ? TRUE : FALSE;
- }
- else {
- $pending = $isPending;
- }
$contributionRecurID = isset($form->_params['contributionRecurID']) ? $form->_params['contributionRecurID'] : NULL;
$membershipSource = NULL;
}
}
+ // @todo Move this into CRM_Member_BAO_Membership::processMembership
+ if (!empty($membershipContribution)) {
+ $pending = ($membershipContribution->contribution_status_id == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus())) ? TRUE : FALSE;
+ }
+ else {
+ $pending = $this->getIsPending();
+ }
list($membership, $renewalMode, $dates) = CRM_Member_BAO_Membership::processMembership(
$contactID, $memType, $isTest,
date('YmdHis'), CRM_Utils_Array::value('cms_contactID', $membershipParams),
if (substr($name, 0, 7) == 'country') {
// make sure its different from the default country
// iso code
- $defaultCountry = $config->defaultContactCountry();
+ $defaultCountry = CRM_Core_BAO_Country::defaultContactCountry();
// full name
- $defaultCountryName = $config->defaultContactCountryName();
+ $defaultCountryName = CRM_Core_BAO_Country::defaultContactCountryName();
if ($defaultCountry) {
if ($value == $defaultCountry ||
* Array of address sequence.
*/
public static function addressSequence() {
- $config = CRM_Core_Config::singleton();
- $addressSequence = $config->addressSequence();
+ $addressSequence = CRM_Utils_Address::sequence(\Civi::settings()->get('address_format'));
$countryState = $cityPostal = FALSE;
foreach ($addressSequence as $key => $field) {
if (!$value) {
$config = CRM_Core_Config::singleton();
if ($config->defaultContactCountry) {
- $value = $config->defaultContactCountry();
+ $value = CRM_Core_BAO_Country::defaultContactCountry();
}
}
}
'contact_id' => $contactID,
'is_active' => 1,
'dashboard_id.is_active' => 1,
+ 'dashboard_id.domain_id' => CRM_Core_Config::domainID(),
'options' => ['sort' => 'weight', 'limit' => 0],
'return' => [
'id',
// If empty, then initialize default dashlets for this user.
if (!$results['count']) {
// They may just have disabled all their dashlets. Check if any records exist for this contact.
- if (!civicrm_api3('DashboardContact', 'getcount', ['contact_id' => $contactID])) {
+ if (!civicrm_api3('DashboardContact', 'getcount', ['contact_id' => $contactID, 'dashboard_id.domain_id' => CRM_Core_Config::domainID()])) {
$dashlets = self::initializeDashlets();
}
}
$dashlet = new CRM_Core_DAO_Dashboard();
if (!$dashboardID) {
- // check url is same as exiting entries, if yes just update existing
+
+ // Assign domain before search to allow identical dashlets in different domains.
+ if (empty($params['domain_id'])) {
+ $dashlet->domain_id = CRM_Core_Config::domainID();
+ }
+
+ // Try and find an existing dashlet - it will be updated if found.
if (!empty($params['name'])) {
$dashlet->name = CRM_Utils_Array::value('name', $params);
$dashlet->find(TRUE);
$dashlet->url = CRM_Utils_Array::value('url', $params);
$dashlet->find(TRUE);
}
- if (empty($params['domain_id'])) {
- $dashlet->domain_id = CRM_Core_Config::domainID();
- }
+
}
else {
$dashlet->id = $dashboardID;
* @throws \CiviCRM_API3_Exception
*/
public static function refillCache($rgid, $gid, $criteria, $checkPermissions, $searchLimit = 0) {
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions);
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions, $searchLimit);
// 1. Clear cache if any
$sql = "DELETE FROM civicrm_prevnext_cache WHERE cachekey LIKE %1";
// would chain to a delete. Limiting to getfields for 'get' limits us to declared fields,
// although we might wish to revisit later to allow joins.
$validFieldsForRetrieval = civicrm_api3('Contact', 'getfields', ['action' => 'get'])['values'];
- if (!empty($criteria)) {
+ $filteredCriteria = isset($criteria['contact']) ? array_intersect_key($criteria['contact'], $validFieldsForRetrieval) : [];
+
+ if (!empty($criteria) || !empty($searchLimit)) {
$contacts = civicrm_api3('Contact', 'get', array_merge([
- 'options' => ['limit' => 0],
+ 'options' => ['limit' => $searchLimit],
'return' => 'id',
'check_permissions' => TRUE,
- ], array_intersect_key($criteria['contact'], $validFieldsForRetrieval)));
+ 'contact_type' => civicrm_api3('RuleGroup', 'getvalue', ['id' => $rgid, 'return' => 'contact_type']),
+ ], $filteredCriteria));
$contactIDs = array_keys($contacts['values']);
+
+ if (empty($contactIDs)) {
+ // If there is criteria but no contacts were found then we should return now
+ // since we have no contacts to match.
+ return [];
+ }
}
- $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIDs, $checkPermissions, $searchLimit);
+ $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIDs, $checkPermissions);
}
if (!empty($foundDupes)) {
2 => [$table_name, 'String'],
3 => [$constraint_name, 'String'],
];
- $dao = CRM_Core_DAO::executeQuery($query, $params);
+ $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
if ($dao->fetch()) {
return TRUE;
*/
public static function safeRemoveFK($table_name, $constraint_name) {
if (self::checkFKExists($table_name, $constraint_name)) {
- CRM_Core_DAO::executeQuery("ALTER TABLE {$table_name} DROP FOREIGN KEY {$constraint_name}", []);
+ CRM_Core_DAO::executeQuery("ALTER TABLE {$table_name} DROP FOREIGN KEY {$constraint_name}", [], TRUE, NULL, FALSE, FALSE);
return TRUE;
}
return FALSE;
* @deprecated
*/
public function addressSequence() {
+ CRM_Core_Error::deprecatedFunctionWarning('CRM_Utils_Address::sequence(Civi::settings()->get(\'address_format\')');
return CRM_Utils_Address::sequence(Civi::settings()->get('address_format'));
}
* @deprecated
*/
public function defaultContactCountry() {
+ CRM_Core_Error::deprecatedFunctionWarning('CRM_Core_BAO_Country::defaultContactCountry');
return CRM_Core_BAO_Country::defaultContactCountry();
}
* @deprecated
*/
public function defaultContactCountryName() {
+ CRM_Core_Error::deprecatedFunctionWarning('CRM_Core_BAO_Country::defaultContactCountryName');
return CRM_Core_BAO_Country::defaultContactCountryName();
}
'class' => 'CRM_Core_DAO_StatusPreference',
'table' => 'civicrm_status_pref',
],
- 'CRM_ACL_DAO_Cache' => [
- 'name' => 'Cache',
- 'class' => 'CRM_ACL_DAO_Cache',
+ 'CRM_ACL_DAO_ACLCache' => [
+ 'name' => 'ACLCache',
+ 'class' => 'CRM_ACL_DAO_ACLCache',
'table' => 'civicrm_acl_cache',
],
'CRM_Contact_DAO_Group' => [
*
* Generated from xml/schema/CRM/Core/Cache.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:97df4edaa4829ea30a151dbb95ff754d)
+ * (GenCodeChecksum:4d3ccecb7d91aa67b8c78c3c39933ae8)
*/
/**
public static $_log = FALSE;
/**
+ * Unique table ID
+ *
* @var int
*/
public $id;
'id' => [
'name' => 'id',
'type' => CRM_Utils_Type::T_INT,
+ 'title' => ts('Cache ID'),
+ 'description' => ts('Unique table ID'),
'required' => TRUE,
'where' => 'civicrm_cache.id',
'table_name' => 'civicrm_cache',
'component_id' => [
'name' => 'component_id',
'type' => CRM_Utils_Type::T_INT,
+ 'title' => ts('Component ID'),
'description' => ts('Component that this menu item belongs to'),
'where' => 'civicrm_cache.component_id',
'table_name' => 'civicrm_cache',
*
* Generated from xml/schema/CRM/Core/Dashboard.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:2b085baa3414de05ee5c52a4d7d4f81f)
+ * (GenCodeChecksum:6fd1bfbecace855a159025ad31e37fb0)
*/
/**
$template = CRM_Core_Smarty::singleton();
$template->assign($vars);
$content = $template->fetch('CRM/common/fatal.tpl');
+
if ($config->backtrace) {
$content = self::formatHtmlException($exception) . $content;
}
- if ($config->userFramework == 'Joomla' &&
- class_exists('JError')
- ) {
- JError::raiseError('CiviCRM-001', $content);
- }
- else {
- echo CRM_Utils_System::theme($content);
- }
+
+ echo CRM_Utils_System::theme($content);
// fin
self::abend(CRM_Core_Error::FATAL_ERROR);
$entityBlock = ['contact_id' => $cid];
$location = CRM_Core_BAO_Location::getValues($entityBlock);
- $config = CRM_Core_Config::singleton();
- $addressSequence = array_flip($config->addressSequence());
+ $addressSequence = array_flip(CRM_Utils_Address::sequence(\Civi::settings()->get('address_format')));
$profileFields = CRM_Core_BAO_UFGroup::getFields($ufId, FALSE, CRM_Core_Action::VIEW, NULL, NULL, FALSE,
NULL, FALSE, NULL, CRM_Core_Permission::CREATE, NULL
* @param array $input
*
* @return bool
+ * @throws \CiviCRM_API3_Exception
*/
public function failed(&$objects, &$transaction, $input = []) {
$contribution = &$objects['contribution'];
'labelColumn' => 'name',
'flip' => 1,
]);
+ $contribution->contribution_status_id = $contributionStatuses['Failed'];
$contribution->receive_date = CRM_Utils_Date::isoToMysql($contribution->receive_date);
$contribution->receipt_date = CRM_Utils_Date::isoToMysql($contribution->receipt_date);
$contribution->thankyou_date = CRM_Utils_Date::isoToMysql($contribution->thankyou_date);
- $contribution->contribution_status_id = $contributionStatuses['Failed'];
$contribution->save();
// Add line items for recurring payments.
if (empty($input['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'])) {
if (!empty($memberships)) {
- // if transaction is failed then set "Cancelled" as membership status
- $membershipStatuses = CRM_Core_PseudoConstant::get('CRM_Member_DAO_Membership', 'status_id', [
- 'labelColumn' => 'name',
- 'flip' => 1,
- ]);
foreach ($memberships as $membership) {
- if ($membership) {
- $membership->status_id = $membershipStatuses['Cancelled'];
- $membership->save();
-
- //update related Memberships.
- $params = ['status_id' => $membershipStatuses['Cancelled']];
- CRM_Member_BAO_Membership::updateRelatedMemberships($membership->id, $params);
- }
+ // @fixme Should we cancel only Pending memberships? per cancelled()
+ $this->cancelMembership($membership, $membership->status_id, FALSE);
}
}
if ($participant) {
- $participantParams['id'] = $participant->id;
- $participantParams['status_id'] = 'Cancelled';
- civicrm_api3('Participant', 'create', $participantParams);
+ $this->cancelParticipant($participant->id);
}
}
$transaction->commit();
- CRM_Core_Error::debug_log_message("Setting contribution status to failed");
- //echo "Success: Setting contribution status to failed<p>";
+ Civi::log()->debug("Setting contribution status to Failed");
return TRUE;
}
*/
public function pending(&$objects, &$transaction) {
$transaction->commit();
- CRM_Core_Error::debug_log_message("returning since contribution status is pending");
+ Civi::log()->debug("Returning since contribution status is Pending");
echo "Success: Returning since contribution status is pending<p>";
return TRUE;
}
* @param array $input
*
* @return bool
+ * @throws \CiviCRM_API3_Exception
*/
public function cancelled(&$objects, &$transaction, $input = []) {
$contribution = &$objects['contribution'];
- $memberships = &$objects['membership'];
- if (is_numeric($memberships)) {
- $memberships = [$objects['membership']];
+ $memberships = [];
+ if (!empty($objects['membership'])) {
+ $memberships = &$objects['membership'];
+ if (is_numeric($memberships)) {
+ $memberships = [$objects['membership']];
+ }
}
- $participant = &$objects['participant'];
$addLineItems = FALSE;
if (empty($contribution->id)) {
$addLineItems = TRUE;
}
+ $participant = &$objects['participant'];
+
+ // CRM-15546
$contributionStatuses = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'contribution_status_id', [
'labelColumn' => 'name',
'flip' => 1,
]);
$contribution->contribution_status_id = $contributionStatuses['Cancelled'];
- $contribution->cancel_date = self::$_now;
- $contribution->cancel_reason = CRM_Utils_Array::value('reasonCode', $input);
$contribution->receive_date = CRM_Utils_Date::isoToMysql($contribution->receive_date);
$contribution->receipt_date = CRM_Utils_Date::isoToMysql($contribution->receipt_date);
$contribution->thankyou_date = CRM_Utils_Date::isoToMysql($contribution->thankyou_date);
+ $contribution->cancel_date = self::$_now;
+ $contribution->cancel_reason = CRM_Utils_Array::value('reasonCode', $input);
$contribution->save();
- //add lineitems for recurring payments
+ // Add line items for recurring payments.
if (!empty($objects['contributionRecur']) && $objects['contributionRecur']->id && $addLineItems) {
CRM_Contribute_BAO_ContributionRecur::addRecurLineItems($objects['contributionRecur']->id, $contribution);
}
if (empty($input['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'])) {
if (!empty($memberships)) {
- $membershipStatuses = CRM_Core_PseudoConstant::get('CRM_Member_DAO_Membership', 'status_id', [
- 'labelColumn' => 'name',
- 'flip' => 1,
- ]);
- // Cancel only Pending memberships
- // CRM-18688
- $pendingStatusId = $membershipStatuses['Pending'];
foreach ($memberships as $membership) {
- if ($membership && ($membership->status_id == $pendingStatusId)) {
- $membership->status_id = $membershipStatuses['Cancelled'];
- $membership->save();
-
- //update related Memberships.
- $params = ['status_id' => $membershipStatuses['Cancelled']];
- CRM_Member_BAO_Membership::updateRelatedMemberships($membership->id, $params);
+ if ($membership) {
+ $this->cancelMembership($membership, $membership->status_id);
}
}
}
if ($participant) {
- $participantParams['id'] = $participant->id;
- $participantParams['status_id'] = 'Cancelled';
- civicrm_api3('Participant', 'create', $participantParams);
+ $this->cancelParticipant($participant->id);
}
}
$transaction->commit();
- CRM_Core_Error::debug_log_message("Setting contribution status to cancelled");
- //echo "Success: Setting contribution status to cancelled<p>";
+ Civi::log()->debug("Setting contribution status to Cancelled");
return TRUE;
}
*/
public function unhandled(&$objects, &$transaction) {
$transaction->rollback();
- CRM_Core_Error::debug_log_message("returning since contribution status: is not handled");
+ Civi::log()->debug("Returning since contribution status is not handled");
echo "Failure: contribution status is not handled<p>";
return FALSE;
}
+ /**
+ * Logic to cancel a participant record when the related contribution changes to failed/cancelled.
+ * @todo This is part of a bigger refactor for dev/core/issues/927 - "duplicate" functionality exists in CRM_Contribute_BAO_Contribution::cancel()
+ *
+ * @param $participantID
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+ private function cancelParticipant($participantID) {
+ // @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
+ $participantParams['id'] = $participantID;
+ $participantParams['status_id'] = 'Cancelled';
+ civicrm_api3('Participant', 'create', $participantParams);
+ }
+
+ /**
+ * Logic to cancel a membership record when the related contribution changes to failed/cancelled.
+ * @todo This is part of a bigger refactor for dev/core/issues/927 - "duplicate" functionality exists in CRM_Contribute_BAO_Contribution::cancel()
+ * @param \CRM_Member_BAO_Membership $membership
+ * @param int $membershipStatusID
+ * @param boolean $onlyCancelPendingMembership
+ * Do we only cancel pending memberships? OR memberships in any status? (see CRM-18688)
+ * @fixme Historically failed() cancelled membership in any status, cancelled() cancelled only pending memberships so we retain that behaviour for now.
+ *
+ */
+ private function cancelMembership($membership, $membershipStatusID, $onlyCancelPendingMembership = TRUE) {
+ // @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
+ // Cancel only Pending memberships
+ $pendingMembershipStatusId = CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Pending');
+ if (($membershipStatusID == $pendingMembershipStatusId) || ($onlyCancelPendingMembership == FALSE)) {
+ $cancelledMembershipStatusId = CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Cancelled');
+
+ $membership->status_id = $cancelledMembershipStatusId;
+ $membership->save();
+
+ $params = ['status_id' => $cancelledMembershipStatusId];
+ CRM_Member_BAO_Membership::updateRelatedMemberships($membership->id, $params);
+
+ // @todo Convert the above to API
+ // $membershipParams = [
+ // 'id' => $membership->id,
+ // 'status_id' => $cancelledMembershipStatusId,
+ // ];
+ // civicrm_api3('Membership', 'create', $membershipParams);
+ // CRM_Member_BAO_Membership::updateRelatedMemberships($membershipParams['id'], ['status_id' => $cancelledMembershipStatusId]);
+ }
+
+ }
+
/**
* @deprecated
*
* @param array $objects
* @param CRM_Core_Transaction $transaction
* @param bool $recur
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public function completeTransaction(&$input, &$ids, &$objects, &$transaction, $recur = FALSE) {
$contribution = &$objects['contribution'];
* is because the function is also used to generate pdfs
*
* @return array
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public function sendMail(&$input, &$ids, &$objects, &$values, $recur = FALSE, $returnMessageText = FALSE) {
return CRM_Contribute_BAO_Contribution::sendMail($input, $ids, $objects['contribution']->id, $values,
$input['component'] = $component;
$ids['contact'] = $this->retrieve('contactID', 'Integer', TRUE);
- $ids['contribution'] = $this->retrieve('contributionID', 'Integer', TRUE);
+ $contributionID = $ids['contribution'] = $this->retrieve('contributionID', 'Integer', TRUE);
+ $membershipID = $this->retrieve('membershipID', 'Integer', FALSE);
+ $contributionRecurID = $this->retrieve('contributionRecurID', 'Integer', FALSE);
$this->getInput($input, $ids);
}
else {
// get the optional ids
- $ids['membership'] = $this->retrieve('membershipID', 'Integer', FALSE);
- $ids['contributionRecur'] = $this->retrieve('contributionRecurID', 'Integer', FALSE);
+ $ids['membership'] = $membershipID;
+ $ids['contributionRecur'] = $contributionRecurID;
$ids['contributionPage'] = $this->retrieve('contributionPageID', 'Integer', FALSE);
$ids['related_contact'] = $this->retrieve('relatedContactID', 'Integer', FALSE);
$ids['onbehalf_dupe_alert'] = $this->retrieve('onBehalfDupeAlert', 'Integer', FALSE);
}
- $paymentProcessorID = self::getPayPalPaymentProcessorID($input, $ids);
+ $paymentProcessorID = $this->getPayPalPaymentProcessorID($input, $ids);
Civi::log()->debug('PayPalIPN: Received (ContactID: ' . $ids['contact'] . '; trxn_id: ' . $input['trxn_id'] . ').');
+ if ($this->retrieve('membershipID', 'Integer', FALSE)) {
+ $templateContribution = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecurID);
+ $membershipPayment = civicrm_api3('MembershipPayment', 'get', [
+ 'contribution_id' => $templateContribution['id'],
+ 'membership_id' => $membershipID,
+ ]);
+ $lineItems = civicrm_api3('LineItem', 'get', [
+ 'contribution_id' => $templateContribution['id'],
+ 'entity_id' => $membershipID,
+ 'entity_table' => 'civicrm_membership',
+ ]);
+ Civi::log()->debug('PayPalIPN: Received payment for membership ' . (int) $membershipID
+ . '. Original contribution was ' . (int) $contributionID . '. The template for this contribution is '
+ . $templateContribution['id'] . ' it is linked to ' . $membershipPayment['count']
+ . 'payments for this membership. It has ' . $lineItems['count'] . ' line items linked to this membership.'
+ . ' it is expected the original contribution will be linked by both entities to the membership.'
+ );
+ if (empty($membershipPayment['count']) && empty($lineItems['count'])) {
+ Civi::log()->debug('PayPalIPN: Will attempt to compensate');
+ $input['membership_id'] = $this->retrieve('membershipID', 'Integer', FALSE);
+ }
+ if ($contributionRecurID) {
+ $recurLinks = civicrm_api3('ContributionRecur', 'get', [
+ 'membership_id' => $membershipID,
+ 'contribution_recur_id' => $contributionRecurID,
+ ]);
+ Civi::log()->debug('PayPalIPN: Membership should be linked to contribution recur record ' . $contributionRecurID
+ . ' ' . $recurLinks['count'] . 'links found'
+ );
+ }
+ }
if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) {
return;
}
* @throws \Civi\Payment\Exception\PaymentProcessorException
*/
public function doExpressCheckout(&$params) {
- $statuses = CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id');
if (!empty($params['is_recur'])) {
return $this->createRecurringPayments($params);
}
}
/* Success */
-
$params['trxn_id'] = $result['transactionid'];
$params['gross_amount'] = $result['amt'];
$params['fee_amount'] = $result['feeamt'];
$params['pending_reason'] = $result['pendingreason'];
if (!empty($params['is_recur'])) {
// See comment block.
- $params['payment_status_id'] = array_search('Pending', $statuses);
+ $params['payment_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
}
else {
- $params['payment_status_id'] = array_search('Completed', $statuses);
+ $params['payment_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
}
return $params;
}
/**
* Given a permission string or array, check for access requirements
- * @param string|array $permissions
- * The permission to check as an array or string -see examples.
- *
- * @param int $contactId
- * Contact id to check permissions for. Defaults to current logged-in user.
*
- * Ex 1
+ * Ex 1: Must have 'access CiviCRM'
+ * (string) 'access CiviCRM'
*
- * Must have 'access CiviCRM'
- * (string) 'access CiviCRM'
+ * Ex 2: Must have 'access CiviCRM' and 'access Ajax API'
+ * ['access CiviCRM', 'access Ajax API']
*
+ * Ex 3: Must have 'access CiviCRM' or 'access Ajax API'
+ * [
+ * ['access CiviCRM', 'access Ajax API'],
+ * ],
*
- * Ex 2 Must have 'access CiviCRM' and 'access Ajax API'
- * array('access CiviCRM', 'access Ajax API')
+ * Ex 4: Must have 'access CiviCRM' or 'access Ajax API' AND 'access CiviEvent'
+ * [
+ * ['access CiviCRM', 'access Ajax API'],
+ * 'access CiviEvent',
+ * ],
*
- * Ex 3 Must have 'access CiviCRM' or 'access Ajax API'
- * array(
- * array('access CiviCRM', 'access Ajax API'),
- * ),
+ * Note that in permissions.php this is keyed by the action eg.
+ * (access Civi || access AJAX) && (access CiviEvent || access CiviContribute)
+ * 'myaction' => [
+ * ['access CiviCRM', 'access Ajax API'],
+ * ['access CiviEvent', 'access CiviContribute']
+ * ],
*
- * Ex 4 Must have 'access CiviCRM' or 'access Ajax API' AND 'access CiviEvent'
- * array(
- * array('access CiviCRM', 'access Ajax API'),
- * 'access CiviEvent',
- * ),
+ * @param string|array $permissions
+ * The permission to check as an array or string -see examples.
*
- * Note that in permissions.php this is keyed by the action eg.
- * (access Civi || access AJAX) && (access CiviEvent || access CiviContribute)
- * 'myaction' => array(
- * array('access CiviCRM', 'access Ajax API'),
- * array('access CiviEvent', 'access CiviContribute')
- * ),
+ * @param int $contactId
+ * Contact id to check permissions for. Defaults to current logged-in user.
*
* @return bool
- * true if yes, else false
+ * true if contact has permission(s), else false
*/
public static function check($permissions, $contactId = NULL) {
$permissions = (array) $permissions;
- $userId = NULL;
- if ($contactId) {
- $userId = CRM_Core_BAO_UFMatch::getUFId($contactId);
- }
+ $userId = CRM_Core_BAO_UFMatch::getUFId($contactId);
/** @var CRM_Core_Permission_Temp $tempPerm */
$tempPerm = CRM_Core_Config::singleton()->userPermissionTemp;
'duplicatecheck' => [
'access CiviCRM',
],
+ 'merge' => ['merge duplicate contacts'],
+ ];
+
+ $permissions['dedupe'] = [
+ 'getduplicates' => ['access CiviCRM'],
+ 'getstatistics' => ['access CiviCRM'],
];
// CRM-16963 - Permissions for country.
'edit all events',
],
];
+ // Exception refers to dedupe_exception.
+ $permissions['exception'] = [
+ 'default' => ['merge duplicate contacts'],
+ ];
+ $permissions['job'] = [
+ 'process_batch_merge' => ['merge duplicate contacts'],
+ ];
// Loc block is only used for events
$permissions['loc_block'] = $permissions['event'];
self::populate(self::$country, 'CRM_Core_DAO_Country', TRUE, 'name', 'is_active', $whereClause);
// if default country is set, percolate it to the top
- if ($config->defaultContactCountry()) {
+ if (CRM_Core_BAO_Country::defaultContactCountry()) {
$countryIsoCodes = self::countryIsoCode();
- $defaultID = array_search($config->defaultContactCountry(), $countryIsoCodes);
+ $defaultID = array_search(CRM_Core_BAO_Country::defaultContactCountry(), $countryIsoCodes);
if ($defaultID !== FALSE) {
$default[$defaultID] = CRM_Utils_Array::value($defaultID, self::$country);
self::$country = $default + self::$country;
* @param bool $checkPermissions
* Respect logged in user permissions.
*
- * @param int $searchLimit
- * Limit for the number of contacts to be used for comparison.
- * The search methodology finds all matches for the searchedContacts so this limits
- * the number of searched contacts, not the matches found.
- *
* @return array
* Array of (cid1, cid2, weight) dupe triples
*
- * @throws CiviCRM_API3_Exception
* @throws Exception
*/
- public static function dupes($rgid, $cids = [], $checkPermissions = TRUE, $searchLimit = 0) {
+ public static function dupes($rgid, $cids = [], $checkPermissions = TRUE) {
$rgBao = new CRM_Dedupe_BAO_RuleGroup();
$rgBao->id = $rgid;
$rgBao->contactIds = $cids;
if (!$rgBao->find(TRUE)) {
- CRM_Core_Error::fatal("Dedupe rule not found for selected contacts");
- }
- if (empty($rgBao->contactIds) && !empty($searchLimit)) {
- $limitedContacts = civicrm_api3('Contact', 'get', [
- 'return' => 'id',
- 'contact_type' => $rgBao->contact_type,
- 'options' => ['limit' => $searchLimit],
- ]);
- $rgBao->contactIds = array_keys($limitedContacts['values']);
+ throw new CRM_Core_Exception('Dedupe rule not found for selected contacts');
}
$rgBao->fillTable();
*
* @return array
* matching contact ids
+ * @throws \CRM_Core_Exception
*/
public static function dupesByParams(
$params,
$rgBao->contact_type = $ctype;
$rgBao->used = $used;
if (!$rgBao->find(TRUE)) {
- CRM_Core_Error::fatal("$used rule for $ctype does not exist");
+ throw new CRM_Core_Exception("$used rule for $ctype does not exist");
}
}
*
* @return array
* array of (cid1, cid2, weight) dupe triples
+ * @throws \CiviCRM_API3_Exception
*/
public static function dupesInGroup($rgid, $gid, $searchLimit = 0) {
$cids = array_keys(CRM_Contact_BAO_Group::getMember($gid, TRUE, $searchLimit));
*
* @return array
* valid $params array for dedupe
+ * @throws \CRM_Core_Exception
*/
public static function formatParams($fields, $ctype) {
$flat = [];
}
}
}
- if ($table == 'civicrm_phone') {
+ if ($table === 'civicrm_phone') {
$fixes = [
'phone' => 'phone_numeric',
];
* -dstName
* -weight
* -canMerge
- *
- * @throws CRM_Core_Exception
*/
public static function parseAndStoreDupePairs($foundDupes, $cacheKeyString) {
$cids = [];
* If not set explicitly this is calculated but it is preferred that it be set
* per comments on isSelected above.
*
+ * @param int $searchLimit
+ * Limit on number of contacts to search for duplicates for.
+ * This means that if the limit is 1000 then only duplicates for the first 1000 contacts
+ * matching criteria will be found and batchMerged (the number of merges could be less than or greater than 100)
+ *
* @return array|bool
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
- public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = [], $checkPermissions = TRUE, $reloadCacheIfEmpty = NULL) {
+ public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = [], $checkPermissions = TRUE, $reloadCacheIfEmpty = NULL, $searchLimit = 0) {
$redirectForPerformance = ($batchLimit > 1) ? TRUE : FALSE;
-
+ if ($mode === 'aggressive' && $checkPermissions && !CRM_Core_Permission::check('force merge duplicate contacts')) {
+ throw new CRM_Core_Exception(ts('Insufficient permissions for aggressive mode batch merge'));
+ }
if (!isset($reloadCacheIfEmpty)) {
$reloadCacheIfEmpty = (!$redirectForPerformance && $isSelected == 2);
}
$dupePairs = self::getDuplicatePairs($rgid, $gid, $reloadCacheIfEmpty, $batchLimit, $isSelected, ($mode == 'aggressive'), $criteria, $checkPermissions);
$cacheParams = [
- 'cache_key_string' => self::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions),
+ 'cache_key_string' => self::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions, $searchLimit),
// @todo stop passing these parameters in & instead calculate them in the merge function based
// on the 'real' params like $isRespectExclusions $batchLimit and $isSelected.
'join' => self::getJoinOnDedupeTable(),
* @param int $searchLimit
* Limit to searching for matches against this many contacts.
*
+ * @param int $isForceNewSearch
+ * Should a new search be forced, bypassing any cache retrieval.
+ *
* @return array
* Array of matches meeting the criteria.
*
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
- public static function getDuplicatePairs($rule_group_id, $group_id, $reloadCacheIfEmpty, $batchLimit, $isSelected, $includeConflicts = TRUE, $criteria = [], $checkPermissions = TRUE, $searchLimit = 0) {
- $dupePairs = self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions);
+ public static function getDuplicatePairs($rule_group_id, $group_id, $reloadCacheIfEmpty, $batchLimit, $isSelected, $includeConflicts = TRUE, $criteria = [], $checkPermissions = TRUE, $searchLimit = 0, $isForceNewSearch = 0) {
+ $dupePairs = $isForceNewSearch ? [] : self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions, $searchLimit);
if (empty($dupePairs) && $reloadCacheIfEmpty) {
// If we haven't found any dupes, probably cache is empty.
// Try filling cache and give another try. We don't need to specify include conflicts here are there will not be any
// until we have done some processing.
CRM_Core_BAO_PrevNextCache::refillCache($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit);
- return self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, FALSE, $criteria, $checkPermissions);
+ return self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, FALSE, $criteria, $checkPermissions, $searchLimit);
}
return $dupePairs;
}
* @param array $criteria
* Additional criteria to narrow down the merge group.
* Currently we are only supporting the key 'contact' within it.
- *
* @param bool $checkPermissions
* Respect the users permissions.
+ * @param int $searchLimit
+ * Number of contacts to seek dupes for (we need this because if
+ * we change it the results won't be refreshed otherwise. Changing the limit
+ * from 100 to 1000 SHOULD result in a new dedupe search).
*
* @return string
*/
- public static function getMergeCacheKeyString($rule_group_id, $group_id, $criteria = [], $checkPermissions = TRUE) {
+ public static function getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit) {
$contactType = CRM_Dedupe_BAO_RuleGroup::getContactTypeForRuleGroup($rule_group_id);
$cacheKeyString = "merge_{$contactType}";
$cacheKeyString .= $rule_group_id ? "_{$rule_group_id}" : '_0';
$cacheKeyString .= $group_id ? "_{$group_id}" : '_0';
+ $cacheKeyString .= '_' . (int) $searchLimit;
$cacheKeyString .= !empty($criteria) ? md5(serialize($criteria)) : '_0';
if ($checkPermissions) {
$contactID = CRM_Core_Session::getLoggedInContactID();
* @param bool $includeConflicts
* @param array $criteria
* @param int $checkPermissions
+ * @param int $searchLimit
*
* @return array
*/
- protected static function getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions) {
+ protected static function getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions, $searchLimit = 0) {
return CRM_Core_BAO_PrevNextCache::retrieve(
- self::getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions),
+ self::getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit),
self::getJoinOnDedupeTable(),
self::getWhereString($isSelected),
0, $batchLimit,
* @return CRM_Event_DAO_Event
*/
public static function add(&$params) {
- CRM_Utils_System::flushCache();
$financialTypeId = NULL;
if (!empty($params['id'])) {
CRM_Utils_Hook::pre('edit', 'Event', $params['id'], $params);
$params['created_id'] = $session->get('userID');
}
$params['created_date'] = date('YmdHis');
+
+ // Clone from template
+ if (!empty($params['template_id'])) {
+ $copy = self::copy($params['template_id']);
+ $params['id'] = $copy->id;
+ unset($params['template_id']);
+ }
}
$event = self::add($params);
$blockCopyOfCustomValue = (!empty($params['custom']));
+ /** @var \CRM_Event_DAO_Event $copyEvent */
$copyEvent = CRM_Core_DAO::copyGeneric('CRM_Event_DAO_Event',
['id' => $id],
// since the location is sharable, lets use the same loc_block_id.
$config = CRM_Core_Config::singleton();
$default_country = new CRM_Core_DAO_Country();
- $default_country->iso_code = $config->defaultContactCountry();
+ $default_country->iso_code = CRM_Core_BAO_Country::defaultContactCountry();
$default_country->find(TRUE);
$defaults["billing_country_id-{$this->_bltID}"] = $default_country->id;
$queryFields['country']['context'] = 'country';
$queryFields['world_region']['context'] = 'country';
$queryFields['state_province']['context'] = 'province';
+ $queryFields['contact_id'] = ['title' => ts('Contact ID'), 'type' => CRM_Utils_Type::T_INT];
$this->queryFields = $queryFields;
}
// create activity.
$subject .= ' ' . ts('Batch') . '[' . $values['title'] . ']';
- $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, FALSE, FALSE, 'name');
$activityParams = [
- 'activity_type_id' => array_search('Export Accounting Batch', $activityTypes),
+ 'activity_type_id' => 'Export Accounting Batch',
'subject' => $subject,
- 'status_id' => 2,
+ 'status_id' => 'Completed',
'activity_date_time' => date('YmdHis'),
'source_contact_id' => $session->get('userID'),
'source_record_id' => $values['id'],
'upload_date' => date('YmdHis'),
],
];
-
- CRM_Activity_BAO_Activity::create($activityParams);
+ civicrm_api3('Activity', 'create', $activityParams);
}
/**
civicrm_api3('Contribution', 'completetransaction', [
'id' => $contribution['id'],
'is_post_payment_create' => TRUE,
+ 'is_email_receipt' => $params['is_send_contribution_notification'],
]);
// Get the trxn
$trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
* @param $updateStatus
* - deprecate this param
*
- * @todo - make this protected once recordAdditionalPayment no longer calls it.
- *
* @return CRM_Financial_DAO_FinancialTrxn
*/
protected static function recordRefundPayment($contributionId, $trxnData, $updateStatus) {
],
]);
- if ($this->_context == 'standalone') {
- $this->addEntityRef('contact_id', ts('Applicant'), ['create' => TRUE], TRUE);
+ $contactField = $this->addEntityRef('contact_id', ts('Applicant'), ['create' => TRUE], TRUE);
+ if ($this->_context != 'standalone') {
+ $contactField->freeze();
}
}
* @return string
*/
public function getContactSubType(): string {
- return $this->contactSubType;
+ return $this->contactSubType ?? '';
}
/**
}
/**
+ * Get the contact type for the import.
+ *
* @return string
*/
public function getContactType(): string {
}
/**
+ * Set mapping fields.
+ *
+ * We do a little cleanup here too.
+ *
+ * We ensure that column numbers are set and that the fields are ordered by them.
+ *
+ * This would mean the fields could be loaded unsorted.
+ *
* @param array $mappingFields
*/
public function setMappingFields(array $mappingFields) {
+ $i = 0;
+ foreach ($mappingFields as &$mappingField) {
+ if (!isset($mappingField['column_number'])) {
+ $mappingField['column_number'] = $i;
+ }
+ if ($mappingField['column_number'] > $i) {
+ $i = $mappingField['column_number'];
+ }
+ $i++;
+ }
$this->mappingFields = $this->rekeyBySortedColumnNumbers($mappingFields);
}
return !empty($this->getValidRelationships()[$key]) ? TRUE : FALSE;
}
+ /**
+ * Get the relevant js for quickform.
+ *
+ * @param int $column
+ *
+ * @return string
+ * @throws \CiviCRM_API3_Exception
+ */
+ public function getQuickFormJSForField($column) {
+ $columnNumbersToHide = [];
+ if ($this->getRelationshipKey($column)) {
+ if (!$this->getWebsiteTypeID($column) && !$this->getLocationTypeID($column)) {
+ $columnNumbersToHide[] = 2;
+ }
+ if (!$this->getFieldName($column)) {
+ $columnNumbersToHide[] = 1;
+ }
+ if (!$this->getPhoneOrIMTypeID($column)) {
+ $columnNumbersToHide[] = 3;
+ }
+ }
+ else {
+ if (!$this->getLocationTypeID($column) && !$this->getWebsiteTypeID($column)) {
+ $columnNumbersToHide[] = 1;
+ }
+ if (!$this->getPhoneOrIMTypeID($column)) {
+ $columnNumbersToHide[] = 2;
+ }
+ $columnNumbersToHide[] = 3;
+ }
+
+ $jsClauses = [];
+ foreach ($columnNumbersToHide as $columnNumber) {
+ $jsClauses[] = $this->getFormName() . "['mapper[$column][" . $columnNumber . "]'].style.display = 'none';";
+ }
+ return empty($jsClauses) ? '' : implode("\n", $jsClauses) . "\n";
+ }
+
+ /**
+ * Get the defaults for the column from the saved mapping.
+ *
+ * @param int $column
+ *
+ * @return array
+ * @throws \CiviCRM_API3_Exception
+ */
+ public function getSavedQuickformDefaultsForColumn($column) {
+ if ($this->getValidRelationshipKey($column)) {
+ if ($this->getWebsiteTypeID($column)) {
+ return [$this->getValidRelationshipKey($column), $this->getFieldName($column), $this->getWebsiteTypeID($column)];
+ }
+ return [$this->getValidRelationshipKey($column), $this->getFieldName($column), $this->getLocationTypeID($column), $this->getPhoneOrIMTypeID($column)];
+ }
+ if ($this->getWebsiteTypeID($column)) {
+ return [$this->getFieldName($column), $this->getWebsiteTypeID($column)];
+ }
+ return [(string) $this->getFieldName($column), $this->getLocationTypeID($column), $this->getPhoneOrIMTypeID($column)];
+ }
+
}
CRM_Core_DAO::getAttribute('CRM_Mailing_DAO_Mailing', 'title')
);
- CRM_Core_Form_Date::buildDateRange($this, 'mailing', 1, '_from', '_to', ts('From'), FALSE);
+ $dateFieldLabel = ($parent->_sms) ? ts('SMS Date') : ts('Mailing Date');
+ $this->addDatePickerRange('mailing', $dateFieldLabel);
$this->add('text', 'sort_name', ts('Created or Sent by'),
CRM_Core_DAO::getAttribute('CRM_Contact_DAO_Contact', 'sort_name')
public function postProcess() {
$params = $this->controller->exportValues($this->_name);
- CRM_Contact_BAO_Query::fixDateValues($params["mailing_relative"], $params['mailing_from'], $params['mailing_to']);
+ if (!empty($params['mailing_relative'])) {
+ list($params['mailing_low'], $params['mailing_high']) = CRM_Utils_Date::getFromTo($params['mailing_relative'], $params['mailing_low'], $params['mailing_high']);
+ unset($params['mailing_relative']);
+ }
+ elseif (!empty($params['mailing_high'])) {
+ $params['mailing_high'] .= ' ' . '23:59:59';
+ }
$parent = $this->controller->getParent();
if (!empty($params)) {
$fields = [
'mailing_name',
- 'mailing_from',
- 'mailing_to',
+ 'mailing_low',
+ 'mailing_high',
'sort_name',
'campaign_id',
'mailing_status',
if (isset($params[$field]) &&
!CRM_Utils_System::isNull($params[$field])
) {
- if (in_array($field, [
- 'mailing_from',
- 'mailing_to',
- ]) && !$params["mailing_relative"]) {
- $time = ($field == 'mailing_to') ? '235959' : NULL;
- $parent->set($field, CRM_Utils_Date::processDate($params[$field], $time));
- }
- else {
- $parent->set($field, $params[$field]);
- }
+ $parent->set($field, $params[$field]);
}
else {
$parent->set($field, NULL);
}
$dateClause1 = $dateClause2 = [];
- $from = $this->_parent->get('mailing_from');
+ $from = $this->_parent->get('mailing_low');
if (!CRM_Utils_System::isNull($from)) {
if ($this->_parent->get('unscheduled')) {
$dateClause1[] = 'civicrm_mailing.created_date >= %2';
$params[2] = [$from, 'String'];
}
- $to = $this->_parent->get('mailing_to');
+ $to = $this->_parent->get('mailing_high');
if (!CRM_Utils_System::isNull($to)) {
if ($this->_parent->get('unscheduled')) {
$dateClause1[] = ' civicrm_mailing.created_date <= %3 ';
* (reference ) an assoc array of name/value pairs.
* @param array $ids
* Deprecated parameter The array that holds all the db ids.
- * @param bool $skipRedirect
- *
- * @throws CRM_Core_Exception
*
* @return CRM_Member_BAO_Membership|CRM_Core_Error
+ * @throws \CiviCRM_API3_Exception
+ *
+ * @throws CRM_Core_Exception
*/
- public static function create(&$params, &$ids = [], $skipRedirect = FALSE) {
+ public static function create(&$params, &$ids = []) {
// always calculate status if is_override/skipStatusCal is not true.
// giving respect to is_override during import. CRM-4012
$memParams['contribution_recur_id'] = $contributionRecurID;
}
// @todo stop passing $ids - it is empty
- $membership = self::create($memParams, $ids, FALSE);
+ $membership = self::create($memParams, $ids);
return array($membership, $renewalMode, $dates);
}
// Relevant tests in api_v3_ContributionPageTest.
$memParams['line_item'] = $lineItems;
// @todo stop passing $ids (membership and userId may be set by this point)
- $membership = self::create($memParams, $ids, FALSE);
+ $membership = self::create($memParams, $ids);
// not sure why this statement is here, seems quite odd :( - Lobo: 12/26/2010
// related to: http://forum.civicrm.org/index.php/topic,11416.msg49072.html#msg49072
}
//add join date
- if (!empty($query->_returnProperties['join_date'])) {
- $query->_select['join_date'] = "civicrm_membership.join_date as join_date";
- $query->_element['join_date'] = 1;
+ if (!empty($query->_returnProperties['membership_join_date'])) {
+ $query->_select['membership_join_date'] = "civicrm_membership.join_date as membership_join_date";
+ $query->_element['membership_join_date'] = 1;
}
//add source
* @param CRM_Contact_BAO_Query $query
*/
public static function whereClauseSingle(&$values, &$query) {
+ if ($query->buildDateRangeQuery($values)) {
+ // @todo - move this to Contact_Query in or near the call to
+ // $this->buildRelativeDateQuery($values);
+ return;
+ }
list($name, $op, $value, $grouping) = $values;
switch ($name) {
case 'member_join_date_low':
case 'member_join_date_high':
+ Civi::log()->warning(
+ 'member_join_date field is deprecated please use membership_join_date field instead',
+ ['civi.tag' => 'deprecated']
+ );
+ $fldName = str_replace(['_low', '_high'], '', $name);
$query->dateQueryBuilder($values,
- 'civicrm_membership', 'member_join_date', 'join_date',
+ 'civicrm_membership', $fldName, 'join_date',
'Member Since'
);
return;
case 'membership_start_date':
case 'member_start_date_low':
case 'member_start_date_high':
+ Civi::log()->warning(
+ 'member_start_date field is deprecated please use membership_start_date field instead',
+ ['civi.tag' => 'deprecated']
+ );
$fldName = str_replace(['_low', '_high'], '', $name);
$query->dateQueryBuilder($values,
'civicrm_membership', $fldName, 'start_date',
case 'membership_end_date':
case 'member_end_date_low':
case 'member_end_date_high':
+ Civi::log()->warning(
+ 'member_end_date field is deprecated please use membership_end_date field instead',
+ ['civi.tag' => 'deprecated']
+ );
$fldName = str_replace(['_low', '_high'], '', $name);
$query->dateQueryBuilder($values,
'civicrm_membership', $fldName, 'end_date',
$query->_qill[$grouping][] = $value ? ts("Membership Status Is Overriden") : ts("Membership Status Is NOT Overriden");
$query->_tables['civicrm_membership'] = $query->_whereTables['civicrm_membership'] = 1;
return;
+
}
}
'membership_type' => 1,
'member_is_test' => 1,
'member_is_pay_later' => 1,
- 'join_date' => 1,
+ 'membership_join_date' => 1,
'membership_start_date' => 1,
'membership_end_date' => 1,
'membership_source' => 1,
return $properties;
}
+ /**
+ * Get the metadata for fields to be included on the grant search form.
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+ public static function getSearchFieldMetadata() {
+ $fields = [
+ 'membership_join_date',
+ 'membership_start_date',
+ 'membership_end_date',
+ ];
+ $metadata = civicrm_api3('Membership', 'getfields', [])['values'];
+ return array_intersect_key($metadata, array_flip($fields));
+ }
+
/**
* Build the search form.
*
* @param CRM_Core_Form $form
*/
public static function buildSearchForm(&$form) {
+ $form->addSearchFieldMetadata(['Membership' => self::getSearchFieldMetadata()]);
+ $form->addFormFieldsFromMetadata();
$membershipStatus = CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label', FALSE, FALSE);
$form->add('select', 'membership_status_id', ts('Membership Status'), $membershipStatus, FALSE, [
'id' => 'membership_status_id',
$form->addElement('text', 'member_source', ts('Source'));
$form->add('number', 'membership_id', ts('Membership ID'), ['class' => 'four', 'min' => 1]);
- CRM_Core_Form_Date::buildDateRange($form, 'member_join_date', 1, '_low', '_high', ts('From'), FALSE);
- $form->addElement('hidden', 'member_join_date_range_error');
-
- CRM_Core_Form_Date::buildDateRange($form, 'member_start_date', 1, '_low', '_high', ts('From'), FALSE);
- $form->addElement('hidden', 'member_start_date_range_error');
-
- CRM_Core_Form_Date::buildDateRange($form, 'member_end_date', 1, '_low', '_high', ts('From'), FALSE);
- $form->addElement('hidden', 'member_end_date_range_error');
-
- $form->addFormRule(['CRM_Member_BAO_Query', 'formRule'], $form);
-
$form->addYesNo('membership_is_current_member', ts('Current Member?'), TRUE);
$form->addYesNo('member_is_primary', ts('Primary Member?'), TRUE);
$form->addYesNo('member_pay_later', ts('Pay Later?'), TRUE);
}
}
- /**
- * Custom form rules.
- *
- * @param array $fields
- * @param array $files
- * @param CRM_Core_Form $form
- *
- * @return bool|array
- */
- public static function formRule($fields, $files, $form) {
- $errors = [];
-
- if ((empty($fields['member_join_date_low']) || empty($fields['member_join_date_high'])) && (empty($fields['member_start_date_low']) || empty($fields['member_start_date_high'])) && (empty($fields['member_end_date_low']) || empty($fields['member_end_date_high']))) {
- return TRUE;
- }
-
- CRM_Utils_Rule::validDateRange($fields, 'member_join_date', $errors, ts('Member Since'));
- CRM_Utils_Rule::validDateRange($fields, 'member_start_date', $errors, ts('Start Date'));
- CRM_Utils_Rule::validDateRange($fields, 'member_end_date', $errors, ts('End Date'));
-
- return empty($errors) ? TRUE : $errors;
- }
-
}
*
* Generated from xml/schema/CRM/Member/Membership.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:40f3b0813c1e13fab544ae1f8fa2ebb3)
+ * (GenCodeChecksum:97d01bc13256a1dd315a86fb5faea1dc)
*/
/**
'labelColumn' => 'name',
],
],
- 'join_date' => [
+ 'membership_join_date' => [
'name' => 'join_date',
'type' => CRM_Utils_Type::T_DATE,
'title' => ts('Member Since'),
$lineItem = [$this->_priceSetId => []];
+ // BEGIN Fix for dev/core/issues/860
+ // Prepare fee block and call buildAmount hook - based on CRM_Price_BAO_PriceSet::buildPriceSet().
+ CRM_Price_BAO_PriceSet::applyACLFinancialTypeStatusToFeeBlock($this->_priceSet['fields']);
+ CRM_Utils_Hook::buildAmount('membership', $this, $this->_priceSet['fields']);
+ // END Fix for dev/core/issues/860
+
CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'],
$formValues, $lineItem[$this->_priceSetId], NULL, $this->_priceSetId);
$membershipSource = $this->_params['membership_source'];
}
- $isPending = ($this->_params['contribution_status_id'] == 2) ? TRUE : FALSE;
-
+ // @todo Move this into CRM_Member_BAO_Membership::processMembership
+ $pending = ($this->_params['contribution_status_id'] == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus())) ? TRUE : FALSE;
list($membership) = CRM_Member_BAO_Membership::processMembership(
$this->_contactID, $this->_params['membership_type_id'][1], $isTestMembership,
$renewalDate, NULL, $customFieldsFormatted, $numRenewTerms, $this->_membershipId,
- $isPending,
+ $pending,
$contributionRecurID, $membershipSource, $this->_params['is_pay_later'], CRM_Utils_Array::value('campaign_id',
$this->_params)
);
}
if ($this->_force) {
+ $this->addSearchFieldMetadata(['Membership' => CRM_Member_BAO_Query::getSearchFieldMetadata()]);
+ $this->addFormFieldsFromMetadata();
$this->postProcess();
$this->set('force', 0);
}
}
$this->_done = TRUE;
-
- $this->_formValues = $this->controller->exportValues($this->_name);
+ $this->setFormValues();
$this->fixFormValues();
$controller->run();
}
- /**
- * Set default values.
- *
- * @todo - can this function override be removed?
- *
- * @return array
- */
- public function setDefaultValues() {
- return $this->_defaults;
- }
-
/**
* If this search has been forced then see if there are any get values, and if so over-ride the post values.
*
// extend CRM_Event_Form_Task_BatchTest::testSubmit with a data provider to test
// handling of custom data, specifically checkbox fields.
$dates = [
- 'join_date',
+ 'membership_join_date',
'membership_start_date',
'membership_end_date',
];
'contact_type',
'sort_name',
'membership_type',
- 'join_date',
+ 'membership_join_date',
'membership_start_date',
'membership_end_date',
'membership_source',
],
[
'name' => ts('Member Since'),
- 'sort' => 'join_date',
+ 'sort' => 'membership_join_date',
'direction' => CRM_Utils_Sort::DESCENDING,
],
[
$query->_tables['civicrm_pledge'] = $query->_whereTables['civicrm_pledge'] = 1;
}
+ if (!empty($query->_returnProperties['pledge_end_date'])) {
+ $query->_select['pledge_end_date'] = 'civicrm_pledge.end_date as pledge_end_date';
+ $query->_element['pledge_end_date'] = 1;
+ $query->_tables['civicrm_pledge'] = $query->_whereTables['civicrm_pledge'] = 1;
+ }
+
if (!empty($query->_returnProperties['pledge_start_date'])) {
$query->_select['pledge_start_date'] = 'civicrm_pledge.start_date as pledge_start_date';
$query->_element['pledge_start_date'] = 1;
}
/**
- * @param $values
- * @param $query
+ * Get where clause for field.
+ *
+ * @todo most of this could be replaced by using metadata.
+ *
+ * @param array $values
+ * @param \CRM_Contact_BAO_Query $query
+ *
+ * @throws \CRM_Core_Exception
*/
public static function whereClauseSingle(&$values, &$query) {
+ if ($query->buildDateRangeQuery($values)) {
+ // @todo - move this to Contact_Query in or near the call to
+ // $this->buildRelativeDateQuery($values);
+ return;
+ }
list($name, $op, $value, $grouping, $wildcard) = $values;
switch ($name) {
- case 'pledge_create_date_low':
- case 'pledge_create_date_high':
- // process to / from date
- $query->dateQueryBuilder($values,
- 'civicrm_pledge', 'pledge_create_date', 'create_date', 'Pledge Made'
- );
- case 'pledge_start_date_low':
- case 'pledge_start_date_high':
- // process to / from date
- $query->dateQueryBuilder($values,
- 'civicrm_pledge', 'pledge_start_date', 'start_date', 'Pledge Start Date'
- );
- return;
-
- case 'pledge_end_date_low':
- case 'pledge_end_date_high':
- // process to / from date
- $query->dateQueryBuilder($values,
- 'civicrm_pledge', 'pledge_end_date', 'end_date', 'Pledge End Date'
- );
- return;
-
- case 'pledge_payment_date_low':
- case 'pledge_payment_date_high':
- // process to / from date
- $query->dateQueryBuilder($values,
- 'civicrm_pledge_payment', 'pledge_payment_date', 'scheduled_date', 'Payment Scheduled'
- );
- return;
-
case 'pledge_amount':
case 'pledge_amount_low':
case 'pledge_amount_high':
public static function getSearchFieldMetadata() {
$fields = [
'pledge_status_id',
+ 'pledge_start_date',
+ 'pledge_end_date',
+ 'pledge_create_date',
];
$metadata = civicrm_api3('Pledge', 'getfields', [])['values'];
return array_intersect_key($metadata, array_flip($fields));
}
+ /**
+ * Get the metadata for fields to be included on the grant search form.
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+ public static function getPledgePaymentSearchFieldMetadata() {
+ $fields = [
+ 'pledge_payment_scheduled_date',
+ ];
+ $metadata = civicrm_api3('PledgePayment', 'getfields', [])['values'];
+ return array_intersect_key($metadata, array_flip($fields));
+ }
+
/**
* Build the search for for pledges.
*
public static function buildSearchForm(&$form) {
// pledge related dates
$form->addSearchFieldMetadata(['Pledge' => self::getSearchFieldMetadata()]);
+ $form->addSearchFieldMetadata(['PledgePayment' => self::getPledgePaymentSearchFieldMetadata()]);
$form->addFormFieldsFromMetadata();
- CRM_Core_Form_Date::buildDateRange($form, 'pledge_start_date', 1, '_low', '_high', ts('From'), FALSE);
- CRM_Core_Form_Date::buildDateRange($form, 'pledge_end_date', 1, '_low', '_high', ts('From'), FALSE);
- CRM_Core_Form_Date::buildDateRange($form, 'pledge_create_date', 1, '_low', '_high', ts('From'), FALSE);
-
- // pledge payment related dates
- CRM_Core_Form_Date::buildDateRange($form, 'pledge_payment_date', 1, '_low', '_high', ts('From'), FALSE);
$form->addYesNo('pledge_test', ts('Pledge is a Test?'), TRUE);
$form->add('text', 'pledge_amount_low', ts('From'), ['size' => 8, 'maxlength' => 8]);
*
* Generated from xml/schema/CRM/Pledge/Pledge.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:5e5bb725caa46ae10f0c5d039a03c675)
+ * (GenCodeChecksum:a25cc68d8392b1d60d7179ca484b604a)
*/
/**
'type' => 'Text',
],
],
- 'start_date' => [
+ 'pledge_start_date' => [
'name' => 'start_date',
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
'title' => ts('Pledge Start Date'),
'description' => ts('The date the first scheduled pledge occurs.'),
'required' => TRUE,
'where' => 'civicrm_pledge.start_date',
+ 'export' => TRUE,
'table_name' => 'civicrm_pledge',
'entity' => 'Pledge',
'bao' => 'CRM_Pledge_BAO_Pledge',
'localizable' => 0,
+ 'unique_title' => ts('Payments Start Date'),
'html' => [
'type' => 'Select Date',
],
'type' => 'Select Date',
],
],
- 'end_date' => [
+ 'pledge_end_date' => [
'name' => 'end_date',
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
'title' => ts('Pledge End Date'),
'description' => ts('Date this pledge finished successfully (total pledge payments equal to or greater than pledged amount).'),
'where' => 'civicrm_pledge.end_date',
+ 'export' => TRUE,
'table_name' => 'civicrm_pledge',
'entity' => 'Pledge',
'bao' => 'CRM_Pledge_BAO_Pledge',
'localizable' => 0,
+ 'unique_title' => ts('Payments Ended Date'),
'html' => [
'type' => 'Select Date',
],
*
* Generated from xml/schema/CRM/Pledge/PledgePayment.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:7dfb4f8000b79fa8b1abab1de3712fc1)
+ * (GenCodeChecksum:563e2926d00b9fe0c4919bfd9a0a05e7)
*/
/**
'entity' => 'PledgePayment',
'bao' => 'CRM_Pledge_BAO_PledgePayment',
'localizable' => 0,
+ 'unique_title' => ts('Payment Scheduled'),
'html' => [
'type' => 'Select Date',
'formatType' => 'activityDate',
}
if ($this->_force) {
+ // pledge related dates
+ $this->addSearchFieldMetadata(['Pledge' => CRM_Pledge_BAO_Query::getSearchFieldMetadata()]);
+ $this->addSearchFieldMetadata(['PledgePayment' => CRM_Pledge_BAO_Query::getPledgePaymentSearchFieldMetadata()]);
+ $this->addFormFieldsFromMetadata();
$this->postProcess();
$this->set('force', 0);
}
$this->_done = TRUE;
- $this->_formValues = $this->controller->exportValues($this->_name);
+ $this->setFormValues();
$this->fixFormValues();
$this->addFormRule(['CRM_Pledge_Form_Search', 'formRule']);
}
- /**
- * Set the default form values.
- *
- *
- * @return array
- * the default array reference
- */
- public function setDefaultValues() {
- $defaults = [];
- $defaults = $this->_formValues;
- return $defaults;
- }
-
public function fixFormValues() {
if (!$this->_force) {
return;
]);
unset($updateFinancialItemInfoValues['financialTrxn']);
}
- elseif (!empty($updateFinancialItemInfoValues['link-financial-trxn']) && $newFinancialItem->amount != 0) {
+ elseif ($trxn && $newFinancialItem->amount != 0) {
civicrm_api3('EntityFinancialTrxn', 'create', [
'entity_id' => $newFinancialItem->id,
'entity_table' => 'civicrm_financial_item',
'financial_trxn_id' => $trxn->id,
'amount' => $newFinancialItem->amount,
]);
- unset($updateFinancialItemInfoValues['link-financial-trxn']);
}
}
}
- // @todo - it may be that trxn_id is always empty - flush out scenarios. Add tests.
- $trxnId = !empty($trxn->id) ? ['id' => $trxn->id] : [];
- $lineItemObj->addFinancialItemsOnLineItemsChange(array_merge($requiredChanges['line_items_to_add'], $requiredChanges['line_items_to_resurrect']), $entityID, $entityTable, $contributionId, $trxnId);
+ $lineItemObj->addFinancialItemsOnLineItemsChange(array_merge($requiredChanges['line_items_to_add'], $requiredChanges['line_items_to_resurrect']), $entityID, $entityTable, $contributionId, $trxn->id ?? NULL);
// update participant fee_amount column
$lineItemObj->updateEntityRecordOnChangeFeeSelection($params, $entityID, $entity);
if ($amountChangeOnTextLineItem !== (float) 0) {
// calculate the amount difference, considered as financial item amount
$updateFinancialItemInfoValues['amount'] = $amountChangeOnTextLineItem;
- // add a flag, later used to link financial trxn and this new financial item
- $updateFinancialItemInfoValues['link-financial-trxn'] = TRUE;
if ($previousLineItems[$updateFinancialItemInfoValues['entity_id']]['tax_amount']) {
$updateFinancialItemInfoValues['tax']['amount'] = $lineItemsToUpdate[$updateFinancialItemInfoValues['entity_id']]['tax_amount'] - $previousLineItems[$updateFinancialItemInfoValues['entity_id']]['tax_amount'];
$updateFinancialItemInfoValues['tax']['description'] = $this->getSalesTaxTerm();
* @param int $entityID
* @param string $entityTable
* @param int $contributionID
- * @param bool $isCreateAdditionalFinancialTrxn
+ * @param bool $trxnID
* Is there a change to the total balance requiring additional transactions to be created.
*/
- protected function addFinancialItemsOnLineItemsChange($lineItemsToAdd, $entityID, $entityTable, $contributionID, $isCreateAdditionalFinancialTrxn) {
+ protected function addFinancialItemsOnLineItemsChange($lineItemsToAdd, $entityID, $entityTable, $contributionID, $trxnID) {
$updatedContribution = new CRM_Contribute_BAO_Contribution();
$updatedContribution->id = $contributionID;
$updatedContribution->find(TRUE);
+ $trxnArray = $trxnID ? ['id' => $trxnID] : NULL;
foreach ($lineItemsToAdd as $priceFieldValueID => $lineParams) {
$lineParams = array_merge($lineParams, [
'entity_id' => $entityID,
'contribution_id' => $contributionID,
]);
- $this->addFinancialItemsOnLineItemChange($isCreateAdditionalFinancialTrxn, $lineParams, $updatedContribution);
+ $financialTypeChangeTrxnID = $this->addFinancialItemsOnLineItemChange($trxnID, $lineParams, $updatedContribution);
+ $lineObj = CRM_Price_BAO_LineItem::retrieve($lineParams);
+ // insert financial items
+ // ensure entity_financial_trxn table has a linking of it.
+ CRM_Financial_BAO_FinancialItem::add($lineObj, $updatedContribution, NULL, $trxnArray);
+ if (isset($lineObj->tax_amount)) {
+ CRM_Financial_BAO_FinancialItem::add($lineObj, $updatedContribution, TRUE, $trxnArray);
+ }
}
}
$tempFinancialTrxnID = NULL;
// don't add financial item for cancelled line item
if ($lineParams['qty'] == 0) {
- return;
+ return NULL;
}
elseif ($isCreateAdditionalFinancialTrxn) {
// This routine & the return below is super uncomfortable.
- // I have refactored to here but don't understand how this would be hit
- // and it is how it would be a good thing, given the odd return below which
- // does not seem consistent with what is going on.
- // I'm tempted to add an e-deprecated into it to confirm my suspicion it only exists to
- // cause mental anguish.
+ // I have refactored to here and it is hit from
+ // testSubmitUnpaidPriceChangeWhileStillPending
+ // but I'm still skeptical it's not covered elsewhere.
// original comment : add financial item if ONLY financial type is changed
if ($lineParams['financial_type_id'] != $updatedContribution->financial_type_id) {
$changedFinancialTypeID = (int) $lineParams['financial_type_id'];
'currency' => $updatedContribution->currency,
];
$adjustedTrxn = CRM_Core_BAO_FinancialTrxn::create($adjustedTrxnValues);
- $tempFinancialTrxnID = ['id' => $adjustedTrxn->id];
+ return $adjustedTrxn->id;
}
}
- $lineObj = CRM_Price_BAO_LineItem::retrieve($lineParams);
- // insert financial items
- // ensure entity_financial_trxn table has a linking of it.
- CRM_Financial_BAO_FinancialItem::add($lineObj, $updatedContribution, NULL, $tempFinancialTrxnID);
- if (isset($lineObj->tax_amount)) {
- CRM_Financial_BAO_FinancialItem::add($lineObj, $updatedContribution, TRUE, $tempFinancialTrxnID);
- }
}
/**
else {
$feeBlock = &$form->_priceSet['fields'];
}
- if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
- foreach ($feeBlock as $key => $value) {
- foreach ($value['options'] as $k => $options) {
- if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
- unset($feeBlock[$key]['options'][$k]);
- }
- }
- if (empty($feeBlock[$key]['options'])) {
- unset($feeBlock[$key]);
- }
- }
- }
- // call the hook.
+
+ self::applyACLFinancialTypeStatusToFeeBlock($feeBlock);
+ // Call the buildAmount hook.
CRM_Utils_Hook::buildAmount($component, $form, $feeBlock);
// CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
}
}
+ /**
+ * Apply ACLs on Financial Type to the price options in a fee block.
+ *
+ * @param array $feeBlock
+ * Fee block: array of price fields.
+ *
+ * @return void
+ */
+ public static function applyACLFinancialTypeStatusToFeeBlock(&$feeBlock) {
+ if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
+ foreach ($feeBlock as $key => $value) {
+ foreach ($value['options'] as $k => $options) {
+ if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
+ unset($feeBlock[$key]['options'][$k]);
+ }
+ }
+ if (empty($feeBlock[$key]['options'])) {
+ unset($feeBlock[$key]);
+ }
+ }
+ }
+ }
+
/**
* Check the current Membership having end date null.
*
'source' => ['title' => ts('Membership Source')],
],
'filters' => [
- 'join_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
+ 'membership_join_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'membership_start_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'membership_end_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'owner_membership_id' => [
'source' => ['title' => ts('Source')],
],
'filters' => [
- 'join_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
+ 'membership_join_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'membership_start_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'membership_end_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
'owner_membership_id' => [
implode(",", $this->_params['status_id_value']);
}
$url = CRM_Report_Utils_Report::getNextUrl('member/detail',
- "reset=1&force=1&join_date_from={$dateStart}&join_date_to={$dateEnd}{$typeUrl}{$statusUrl}",
+ "reset=1&force=1&membership_join_date_from={$dateStart}&membership_join_date_to={$dateEnd}{$typeUrl}{$statusUrl}",
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$row['civicrm_membership_join_date_start'] = CRM_Utils_Date::format($row['civicrm_membership_join_date_start']);
'membership_type_id' => ['title' => ts('Membership Type')],
],
'filters' => [
- 'join_date' => ['type' => CRM_Utils_Type::T_DATE],
+ 'membership_join_date' => ['type' => CRM_Utils_Type::T_DATE],
],
],
'civicrm_address' => [
*/
public function datePickerConversion($fields) {
$fieldPossibilities = $relativeFieldNames = [];
- foreach ($fields as $field) {
- $fieldPossibilities[] = $field;
- $fieldPossibilities[] = $field . '_high';
- $fieldPossibilities[] = $field . '_low';
- }
$relativeDateMappings = [
'activity_date_time' => 'activity',
'participant_register_date' => 'participant',
'receive_date' => 'contribution',
'contribution_cancel_date' => 'contribution_cancel',
+ 'membership_join_date' => 'member_join',
+ 'membership_start_date' => 'member_start',
+ 'membership_end_date' => 'member_end',
+ 'pledge_payment_scheduled_date' => 'pledge_payment',
+ 'pledge_create_date' => 'pledge_create',
+ 'pledge_end_date' => 'pledge_end',
+ 'pledge_start_date' => 'pledge_start',
];
foreach ($fields as $field) {
foreach ($this->getSearchesWithField($field) as $savedSearch) {
+ // Only populate field possibilities as we go to convert each field
+ $fieldPossibilities[] = $field;
+ $fieldPossibilities[] = $field . '_high';
+ $fieldPossibilities[] = $field . '_low';
$formValues = $savedSearch['form_values'];
$isRelative = $hasRelative = FALSE;
$relativeFieldName = $field . '_relative';
['old' => 'is_override', 'new' => 'member_is_override'],
],
]);
+ $this->addTask('Remove Foreign Key from civicrm_dashboard on domain_id if exists', 'removeDomainIDFK');
+ $this->addTask('Remove Index on domain_id that might have been randomly added in the same format as FK', 'dropIndex', 'civicrm_dashboard', 'FK_civicrm_dashboard_domain_id');
+ $this->addTask('Re-Create Foreign key between civicrm_dashboard and civicrm_domain correctly', 'recreateDashboardFK');
+ $this->addTask('Update smart groups to rename filters on pledge_payment_date to pledge_payment_scheduled_date', 'updateSmartGroups', [
+ 'renameField' => [
+ ['old' => 'pledge_payment_date_relative', 'new' => 'pledge_payment_scheduled_date_relative'],
+ ['old' => 'pledge_payment_date_high', 'new' => 'pledge_payment_scheduled_date_high'],
+ ['old' => 'pledge_payment_date_low', 'new' => 'pledge_payment_scheduled_date_low'],
+ ['old' => 'member_join_date_relative', 'new' => 'membership_join_date_relative'],
+ ['old' => 'member_join_date_high', 'new' => 'membership_join_date_high'],
+ ['old' => 'member_join_date_low', 'new' => 'membership_join_date_low'],
+ ['old' => 'member_start_date_relative', 'new' => 'membership_start_date_relative'],
+ ['old' => 'member_start_date_high', 'new' => 'membership_start_date_high'],
+ ['old' => 'member_start_date_low', 'new' => 'membership_start_date_low'],
+ ['old' => 'member_end_date_relative', 'new' => 'membership_end_date_relative'],
+ ['old' => 'member_end_date_high', 'new' => 'membership_end_date_high'],
+ ['old' => 'member_end_date_low', 'new' => 'membership_end_date_low'],
+ ],
+ ]);
+ $this->addTask('Update smart groups where jcalendar fields have been converted to datepicker', 'updateSmartGroups', [
+ 'datepickerConversion' => [
+ 'pledge_payment_scheduled_date',
+ 'pledge_create_date',
+ 'pledge_end_date',
+ 'pledge_start_date',
+ 'membership_join_date',
+ 'membership_end_date',
+ 'membership_start_date',
+ ],
+ ]);
+ $this->addTask('Update civicrm_mapping_field and civicrm_uf_field for change in join_date name', 'updateJoinDateMappingUF');
+ $this->addTask('Update civicrm_report_instances for change in filter from join_date to membership_join_date', 'joinDateReportUpdate');
+ }
+
+ public static function removeDomainIDFK() {
+ CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_dashboard', 'FK_civicrm_dashboard_domain_id');
+ return TRUE;
+ }
+
+ public static function recreateDashboardFK() {
+ $sql = CRM_Core_BAO_SchemaHandler::buildForeignKeySQL([
+ 'fk_table_name' => 'civicrm_domain',
+ 'fk_field_name' => 'id',
+ 'name' => 'domain_id',
+ 'fk_attributes' => ' ON DELETE CASCADE',
+ ], "\n", " ADD ", 'civicrm_dashboard');
+ CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_dashboard " . $sql, [], TRUE, NULL, FALSE, FALSE);
+ return TRUE;
+ }
+
+ public static function updateJoinDateMappingUF() {
+ CRM_Core_DAO::executeQuery("UPDATE civicrm_mapping_field SET name = 'membership_join_date' WHERE name = 'join_date' AND contact_type = 'Membership'");
+ CRM_Core_DAO::executeQuery("UPDATE civicrm_uf_field SET field_name = 'membership_join_date' WHERE field_name = 'join_date' AND field_type = 'Membership'");
+ return TRUE;
+ }
+
+ public static function joinDateReportUpdate() {
+ $report_templates = ['member/contributionDetail', 'member/Detail', 'member/Summary'];
+ $substitutions = [
+ 'join_date_relative' => 'membership_join_date_relative',
+ 'join_date_from' => 'membership_join_date_from',
+ 'join_date_to' => 'membership_join_date_to',
+ ];
+ foreach ($report_templates as $report_template) {
+ $reports = civicrm_api3('ReportInstance', 'get', [
+ 'report_id' => $report_template,
+ 'options' => ['limit' => 0],
+ ])['values'];
+ foreach ($reports as $report) {
+ if (!is_array($report['form_values'])) {
+ $form_values = unserialize($report['form_values']);
+ }
+ else {
+ $form_values = $report['form_values'];
+ }
+ foreach ($form_values as $key => $value) {
+ if (array_key_exists($key, $substitutions)) {
+ $form_values[$substitutions[$key]] = $value;
+ unset($form_values[$key]);
+ }
+ }
+ $form_values = serialize($form_values);
+ CRM_Core_DAO::executeQuery("UPDATE civicrm_report_instance SET form_values = %1 WHERE id = %2", [
+ 1 => [$form_values, 'String'],
+ 2 => [$report['id'], 'Positive'],
+ ]);
+ }
+ }
+ return TRUE;
}
// public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
*/
public static function decode($js) {
$js = trim($js);
- if ($js[0] === "'" || $js[0] === '"') {
+ $first = substr($js, 0, 1);
+ $last = substr($js, -1);
+ if ($last === $first && ($first === "'" || $first === '"')) {
// Use a temp placeholder for escaped backslashes
return str_replace(['\\\\', "\\'", '\\"', '\\&', '\\/', '**backslash**'], ['**backslash**', "'", '"', '&', '/', '\\'], substr($js, 1, -1));
}
- if ($js[0] === '{' || $js[0] === '[') {
+ if (($first === '{' && $last === '}') || ($first === '[' && $last === ']')) {
$obj = self::getRawProps($js);
foreach ($obj as $idx => $item) {
$obj[$idx] = self::decode($item);
* @method static array synchronizeUsers() Create CRM contacts for all existing CMS users.
* @method static appendCoreResources(\Civi\Core\Event\GenericHookEvent $e) Callback for hook_civicrm_coreResourceList.
* @method static alterAssetUrl(\Civi\Core\Event\GenericHookEvent $e) Callback for hook_civicrm_getAssetUrl.
- * @method static sendResponse(\Psr\Http\Message\ResponseInterface $response) function to handle RepsoseInterface for delivering HTTP Responses.
*/
class CRM_Utils_System {
}
}
- /**
- * Output code from error function.
- * @param string $content
- */
- public function outputError($content) {
- if (class_exists('JErrorPage')) {
- $error = new Exception($content);
- JErrorPage::render($error);
- }
- elseif (class_exists('JError')) {
- JError::raiseError('CiviCRM-001', $content);
- }
- else {
- parent::outputError($content);
- }
- }
-
/**
* @inheritDoc
*/
* @param array $params
*
* @return array
+ * @throws \API_Exception
+ * @throws \Civi\API\Exception\UnauthorizedException
*/
function civicrm_api3_batch_create($params) {
return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, 'Batch');
$params['entity_table']['api.default'] = "civicrm_batch";
$params['entity_table']['type'] = CRM_Utils_Type::T_STRING;
$params['entity_table']['title'] = 'Batch Entity Table - remove?';
-
- $params['modified_date']['api.default'] = "now";
+ $params['created_id']['api.default'] = 'user_contact_id';
+ $params['created_date']['api.default'] = 'now';
+ $params['modified_id']['api.default'] = 'user_contact_id';
+ $params['modified_date']['api.default'] = 'now';
$params['status_id']['api.required'] = 1;
$params['title']['api.required'] = 1;
$params['status_id']['api.required'] = 1;
*
* @return array
* Array of deleted values.
+ * @throws \API_Exception
+ * @throws \Civi\API\Exception\UnauthorizedException
*/
function civicrm_api3_batch_delete($params) {
return _civicrm_api3_basic_delete(_civicrm_api3_get_BAO(__FUNCTION__), $params);
'fee_amount',
'financial_type_id',
'contribution_status_id',
+ 'membership_id',
];
$input = array_intersect_key($params, array_fill_keys($passThroughParams, NULL));
$params['rule_group_id'],
CRM_Utils_Array::value('group_id', $params),
CRM_Utils_Array::value('criteria', $params, []),
- CRM_Utils_Array::value('check_permissions', $params, [])
+ !empty($params['check_permissions']),
+ CRM_Utils_Array::value('search_limit', $params, 0)
));
return civicrm_api3_create_success($stats);
}
'title' => ts('Criteria'),
'description' => ts('Dedupe search criteria, as parsable by v3 Contact.get api'),
];
+ $spec['search_limit'] = [
+ 'title' => ts('Number of contacts to look for matches for.'),
+ 'type' => CRM_Utils_Type::T_INT,
+ 'api.default' => (int) Civi::settings()->get('dedupe_default_limit'),
+ ];
}
*/
function civicrm_api3_dedupe_getduplicates($params) {
$options = _civicrm_api3_get_options_from_params($params);
- $dupePairs = CRM_Dedupe_Merger::getDuplicatePairs($params['rule_group_id'], NULL, TRUE, $options['limit'], FALSE, TRUE, $params['criteria'], CRM_Utils_Array::value('check_permissions', $params), CRM_Utils_Array::value('search_limit', $params, 0));
+ $dupePairs = CRM_Dedupe_Merger::getDuplicatePairs($params['rule_group_id'], NULL, TRUE, $options['limit'], FALSE, TRUE, $params['criteria'], CRM_Utils_Array::value('check_permissions', $params), CRM_Utils_Array::value('search_limit', $params, 0), CRM_Utils_Array::value('is_force_new_search', $params));
return civicrm_api3_create_success($dupePairs);
}
'type' => CRM_Utils_Type::T_INT,
'api.default' => (int) Civi::settings()->get('dedupe_default_limit'),
];
+ $spec['is_force_new_search'] = [
+ 'title' => ts('Force a new search, refreshing any cached search'),
+ 'type' => CRM_Utils_Type::T_BOOLEAN,
+ ];
}
*
* @return array
* API result Array.
+ * @throws \CRM_Core_Exception
+ * @throws \API_Exception
*/
function civicrm_api3_event_create($params) {
// Required fields for creating an event
]);
}
- // Clone event from template
- if (!empty($params['template_id']) && empty($params['id'])) {
- $copy = CRM_Event_BAO_Event::copy($params['template_id']);
- $params['id'] = $copy->id;
- unset($params['template_id']);
- }
-
_civicrm_api3_event_create_legacy_support_42($params);
return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params, 'Event');
}
$gid = CRM_Utils_Array::value('gid', $params);
$mode = CRM_Utils_Array::value('mode', $params, 'safe');
- $result = CRM_Dedupe_Merger::batchMerge($rule_group_id, $gid, $mode, 1, 2, CRM_Utils_Array::value('criteria', $params, []), CRM_Utils_Array::value('check_permissions', $params));
+ $result = CRM_Dedupe_Merger::batchMerge($rule_group_id, $gid, $mode, 1, 2, CRM_Utils_Array::value('criteria', $params, []), CRM_Utils_Array::value('check_permissions', $params), NULL, $params['search_limit']);
return civicrm_api3_create_success($result, $params);
}
'description' => 'let the api decide which contact to retain and which to delete?',
'type' => CRM_Utils_Type::T_BOOLEAN,
];
+ $params['search_limit'] = [
+ 'title' => ts('Number of contacts to look for matches for.'),
+ 'type' => CRM_Utils_Type::T_INT,
+ 'api.default' => (int) Civi::settings()->get('dedupe_default_limit'),
+ ];
+
}
/**
return $results;
}
+/**
+ * Adjust Metadata for Get action.
+ *
+ * The metadata is used for setting defaults, documentation & validation.
+ *
+ * @param array $params
+ * Array of parameters determined by getfields.
+ */
+function _civicrm_api3_membership_type_get_spec(&$params) {
+ $params['domain_id']['api.default'] = CRM_Core_Config::domainID();
+}
+
/**
* Adjust input for getlist action.
*
'title' => ts('Cancel Date'),
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
],
+ 'is_send_contribution_notification' => [
+ 'title' => ts('Send out notifications based on contribution status change?'),
+ 'description' => ts('Most commonly this equates to emails relating to the contribution, event, etcwhen a payment completes a contribution'),
+ 'type' => CRM_Utils_Type::T_BOOLEAN,
+ 'api.default' => TRUE,
+ ],
];
}
COMPOSER=$(pickcmd composer composer.phar)
$COMPOSER install
- if has_commands bower karma ; then
+ if has_commands karma ; then
## dev dependencies have been installed globally; don't force developer to redownload
npm install --production
else
npm install
fi
-
- BOWER=$(pickcmd node_modules/bower/bin/bower bower)
- if [ -f "$BOWER" ]; then
- NODE=$(pickcmd node nodejs)
- BOWER="$NODE $BOWER"
- fi
- # Without the force flag, bower may not check for new versions or verify that installed software matches version specified in bower.json
- # With the force flag, bower will ignore all caches and download all deps.
- if [ -n "$OFFLINE" ]; then
- BOWER_OPT=
- elif [ ! -f "bower_components/.setupsh.ts" ]; then
- ## First run -- or cleanup from failed run
- BOWER_OPT=-f
- elif [ "bower.json" -nt "bower_components/.setupsh.ts" ]; then
- ## Bower.json has changed since last run
- BOWER_OPT=-f
- fi
- [ -f "bower_components/.setupsh.ts" ] && rm -f "bower_components/.setupsh.ts"
- $BOWER install $BOWER_OPT
- touch bower_components/.setupsh.ts
popd
fi
+++ /dev/null
-{
- "name": "civicrm",
- "description": "CiviCRM",
- "version": "5.0.0",
- "license": "AGPL-3.0",
- "private": true,
- "dependencies": {
- "angular": "~1.5.0",
- "angular-file-upload": ">=1.1.5 <=1.1.6",
- "angular-jquery-dialog-service": "totten/angular-jquery-dialog-service#civicrm",
- "angular-mocks": "~1.5.0",
- "angular-route": "~1.5.0",
- "angular-ui-sortable": "0.12.x",
- "angular-ui-utils": "0.1.x",
- "angular-unsavedChanges": "~0.1.1",
- "qunit": "~1.10",
- "d3": "3.4.11",
- "d3-3.5.x": "d3#~3.5.17",
- "dc-2.1.x": "dc.js#~2.1.8",
- "crossfilter-1.3.x": "crossfilter2#~1.3.11",
- "jquery": "civicrm/jquery#1.12.4-civicrm-1.2",
- "jquery-ui": "~1.12",
- "lodash-compat": "~3.0",
- "google-code-prettify": "~1.0",
- "select2": "colemanw/select2#v3.5-civicrm-1.0",
- "jquery-validation": "~1.13",
- "datatables": "~1.10",
- "jstree": "~3",
- "ckeditor": "~4.9",
- "font-awesome": "~4",
- "angular-bootstrap": "^2.5.0",
- "angular-sanitize": "~1.5.0",
- "smartmenus": "~1.1",
- "phantomjs-polyfill": "^0.0.2",
- "es6-promise": "^4.2.4",
- "angular-xeditable": "^0.9.0",
- "checklist-model": "~1",
- "css-color-names": "~1"
- },
- "resolutions": {
- "angular": "~1.5.11",
- "jquery": "1.12.4-civicrm-1.2"
- }
-}
"cweagans/composer-patches": "~1.0",
"pear/log": "1.13.1",
"katzien/php-mime-type": "2.1.0",
+ "civicrm/composer-downloads-plugin": "^2.0",
"league/csv": "^9.2"
},
"require-dev": {
]
},
"extra": {
+ "downloads": {
+ "*": {
+ "path": "bower_components/{$id}"
+ },
+ "angular": {
+ "url": "https://github.com/angular/bower-angular/archive/v1.5.11.zip"
+ },
+ "angular-bootstrap": {
+ "url": "https://github.com/angular-ui/bootstrap-bower/archive/2.5.0.zip"
+ },
+ "angular-file-upload": {
+ "url": "https://github.com/nervgh/angular-file-upload/archive/v1.1.6.zip",
+ "ignore": ["examples"]
+ },
+ "angular-jquery-dialog-service": {
+ "url": "https://github.com/totten/angular-jquery-dialog-service/archive/v0.8.0-civicrm-1.0.zip"
+ },
+ "angular-mocks": {
+ "url": "https://github.com/angular/bower-angular-mocks/archive/v1.5.11.zip"
+ },
+ "angular-route": {
+ "url": "https://github.com/angular/bower-angular-route/archive/v1.5.11.zip"
+ },
+ "angular-sanitize": {
+ "url": "https://github.com/angular/bower-angular-sanitize/archive/v1.5.11.zip"
+ },
+ "angular-ui-sortable": {
+ "url": "https://github.com/angular-ui/ui-sortable/archive/v0.12.11.zip"
+ },
+ "angular-ui-utils": {
+ "url": "https://github.com/angular-ui/ui-utils/archive/v0.1.1.zip"
+ },
+ "angular-unsavedChanges": {
+ "url": "https://github.com/facultymatt/angular-unsavedChanges/archive/v0.1.1.zip",
+ "ignore": [".*", "node_modules", "bower_components", "test", "tests"]
+ },
+ "angular-xeditable": {
+ "url": "https://github.com/vitalets/angular-xeditable/archive/0.9.0.zip",
+ "ignore": [".*", "node_modules", "bower_components", "playground", "test", "libs", "docs", "zip", "src", "starter", "Gruntfile.js", "index.html", "jsdoc.conf.json", "package.json"]
+ },
+ "checklist-model": {
+ "url": "https://github.com/vitalets/checklist-model/archive/1.0.0.zip",
+ "ignore": [".*", "node_modules", "docs", "Gruntfile.js", "index.html", "package.json", "test"]
+ },
+ "ckeditor": {
+ "url": "https://github.com/ckeditor/ckeditor-releases/archive/4.9.2.zip"
+ },
+ "crossfilter-1.3.x": {
+ "url": "https://github.com/crossfilter/crossfilter/archive/1.3.14.zip",
+ "ignore": [".*", "node_modules", "bower_components", "src", "lib", "test", "component.json", "package.json", "index.js", "Makefile"]
+ },
+ "crossfilter2": {
+ "url": "https://github.com/crossfilter/crossfilter/archive/1.4.7.zip",
+ "ignore": [".*", "node_modules", "bower_components", "package.json", "index.js", "src", "component.json", "media", "test", "tests"]
+ },
+ "css-color-names": {
+ "url": "https://github.com/bahamas10/css-color-names/archive/v1.0.1.zip"
+ },
+ "d3": {
+ "url": "https://github.com/mbostock-bower/d3-bower/archive/v3.4.11.zip",
+ "ignore": [".DS_Store", ".git", ".gitignore", ".npmignore", ".travis.yml", "Makefile", "bin", "component.json", "index.js", "lib", "node_modules", "package.json", "src", "test"]
+ },
+ "d3-3.5.x": {
+ "url": "https://github.com/mbostock-bower/d3-bower/archive/v3.5.17.zip"
+ },
+ "datatables": {
+ "url": "https://github.com/DataTables/DataTables/archive/1.10.19.zip",
+ "ignore": ["/.*", "examples", "media/unit_testing", "composer.json", "dataTables.jquery.json", "package.json"]
+ },
+ "dc-2.1.x": {
+ "url": "https://github.com/NickQiZhu/dc.js/archive/2.1.10.zip",
+ "ignore": [".*", "style", "web", "*.json", "regression", "scripts", "spec", "src", "docs", "grunt", "Gruntfile.js", "Changelog.md", "welcome.md", "class-hierarchy.dot", "index.js", "CONTRIBUTING.md", "LICENSE_BANNER", "AUTHORS"]
+ },
+ "es6-promise": {
+ "url": "https://github.com/components/es6-promise/archive/v4.2.4.zip"
+ },
+ "font-awesome": {
+ "url": "https://github.com/FortAwesome/Font-Awesome/archive/v4.7.0.zip",
+ "ignore": ["*/.*", "*.json", "src", "*.yml", "Gemfile", "Gemfile.lock", "*.md"]
+ },
+ "google-code-prettify": {
+ "url": "https://github.com/tcollard/google-code-prettify/archive/v1.0.5.zip",
+ "ignore": ["closure-compiler", "js-modules", "tests", "yui-compressor", "Makefile"]
+ },
+ "jquery": {
+ "url": "https://github.com/civicrm/jquery/archive/1.12.4-civicrm-1.2.zip"
+ },
+ "jquery-ui": {
+ "url": "https://github.com/components/jqueryui/archive/1.12.1.zip"
+ },
+ "jquery-validation": {
+ "url": "https://github.com/jquery-validation/jquery-validation/archive/1.13.1.zip",
+ "ignore": [".*", "node_modules", "bower_components", "test", "demo", "lib"]
+ },
+ "jstree": {
+ "url": "https://github.com/vakata/jstree/archive/3.3.8.zip",
+ "ignore": [".*", "docs", "demo", "libs", "node_modules", "test", "libs", "jstree.jquery.json", "gruntfile.js", "package.json", "bower.json", "component.json", "LICENCE-MIT", "README.md"]
+ },
+ "lodash-compat": {
+ "url": "https://github.com/lodash/lodash-compat/archive/3.0.1.zip",
+ "ignore": [".*", "*.log", "*.md", "component.json", "package.json", "node_modules"]
+ },
+ "phantomjs-polyfill": {
+ "url": "https://github.com/conversocial/phantomjs-polyfill/archive/v0.0.2.zip"
+ },
+ "qunit": {
+ "url": "https://github.com/jquery/qunit/archive/v1.10.0.zip"
+ },
+ "select2": {
+ "url": "https://github.com/colemanw/select2/archive/v3.5-civicrm-1.0.zip"
+ },
+ "smartmenus": {
+ "url": "https://github.com/vadikom/smartmenus/archive/1.1.0.zip",
+ "ignore": [".gitignore", "Gruntfile.js"]
+ }
+ },
"patches": {
"phpoffice/common": {
"Fix handling of libxml_disable_entity_loader": "tools/scripts/composer/patches/phpoffice-common-xml-entity-fix.patch"
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ffdac3f93564fe6edb467d3ac43c4869",
+ "content-hash": "195f60bb40e72b390be3211fcc870a38",
"packages": [
{
"name": "civicrm/civicrm-cxn-rpc",
"description": "CiviCRM installation library",
"time": "2018-01-23T06:26:55+00:00"
},
+ {
+ "name": "civicrm/composer-downloads-plugin",
+ "version": "v2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/civicrm/composer-downloads-plugin.git",
+ "reference": "869b7a12f57b2d912f0ea77d5c33c1518b8de27d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/civicrm/composer-downloads-plugin/zipball/869b7a12f57b2d912f0ea77d5c33c1518b8de27d",
+ "reference": "869b7a12f57b2d912f0ea77d5c33c1518b8de27d",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.1",
+ "php": ">=5.6",
+ "togos/gitignore": "~1.1.1"
+ },
+ "require-dev": {
+ "composer/composer": "~1.0",
+ "friendsofphp/php-cs-fixer": "^2.3",
+ "phpunit/phpunit": "^5.7",
+ "totten/process-helper": "^1.0.1"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "LastCall\\DownloadsPlugin\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "LastCall\\DownloadsPlugin\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Rob Bayliss",
+ "email": "rob@lastcallmedia.com"
+ },
+ {
+ "name": "Tim Otten",
+ "email": "totten@civicrm.org"
+ }
+ ],
+ "description": "Composer plugin for downloading additional files within any composer package.",
+ "time": "2019-08-22T10:56:51+00:00"
+ },
{
"name": "cweagans/composer-patches",
"version": "1.6.5",
],
"time": "2018-10-16T17:24:05+00:00"
},
+ {
+ "name": "togos/gitignore",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/TOGoS/PHPGitIgnore.git",
+ "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/TOGoS/PHPGitIgnore/zipball/32bc0830e4123f670adcbf5ddda5bef362f4f4d4",
+ "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2"
+ },
+ "require-dev": {
+ "togos/simpler-test": "1.1.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "TOGoS_GitIgnore_": "src/main/php/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Parser for .gitignore (and sparse-checkout, and anything else using the same format) files",
+ "time": "2019-04-19T19:16:58+00:00"
+ },
{
"name": "totten/ca-config",
"version": "v17.05.0",
DM_REF_BACKDROP=1.x-${DM_REF_CORE}
DM_REF_DRUPAL=7.x-${DM_REF_CORE}
DM_REF_DRUPAL6=6.x-${DM_REF_CORE}
+DM_REF_DRUPAL8=${DM_REF_CORE}
DM_REF_JOOMLA=${DM_REF_CORE}
DM_REF_WORDPRESS=${DM_REF_CORE}
DM_REF_PACKAGES=${DM_REF_CORE}
echo "Current directory is : $THIS_DIR";
exit 1
else
- export DM_SOURCEDIR DM_GENFILESDIR DM_TMPDIR DM_TARGETDIR DM_PHP DM_RSYNC DM_ZIP DM_VERSION DM_REF_CORE DM_REF_DRUPAL DM_REF_DRUPAL6 DM_REF_JOOMLA DM_REF_WORDPRESS DM_REF_PACKAGES
+ export DM_SOURCEDIR DM_GENFILESDIR DM_TMPDIR DM_TARGETDIR DM_PHP DM_RSYNC DM_ZIP DM_VERSION DM_REF_CORE DM_REF_DRUPAL DM_REF_DRUPAL6 DM_REF_DRUPAL8 DM_REF_JOOMLA DM_REF_WORDPRESS DM_REF_PACKAGES
if [ ! -d "$DM_SOURCEDIR" ]; then
echo; echo "ERROR! " DM_SOURCEDIR "directory not found!"; echo "(if you get empty directory name, it might mean that one of necessary variables is not set)"; echo;
fi
dm_git_checkout "$DM_SOURCEDIR/drupal" "$DM_REF_DRUPAL"
GENCODE_CMS=Drupal
fi
+if [ -d "$DM_SOURCEDIR/drupal-8" ]; then
+ dm_git_checkout "$DM_SOURCEDIR/drupal-8" "$DM_REF_DRUPAL8"
+fi
-## Get latest dependencies
+## Get fresh dependencies
+[ -d "$DM_SOURCEDIR/vendor" ] && rm -rf $DM_SOURCEDIR/vendor
+[ -d "$DM_SOURCEDIR/bower_components" ] && rm -rf $DM_SOURCEDIR/bower_components
dm_generate_vendor "$DM_SOURCEDIR"
-## if we already have a bower_compoents dir empty it.
-if [ -d "$DM_SOURCEDIR/bower_components" ]; then
- rm -rf $DM_SOURCEDIR/bower_components/*
-fi
-dm_generate_bower "$DM_SOURCEDIR"
# Before anything - regenerate DAOs
done
dm_install_files "$repo" "$to" {agpl-3.0,agpl-3.0.exception,gpl,CONTRIBUTORS}.txt
- dm_install_files "$repo" "$to" composer.json composer.lock bower.json package.json Civi.php README.md release-notes.md extension-compatibility.json
+ dm_install_files "$repo" "$to" composer.json composer.lock package.json Civi.php README.md release-notes.md extension-compatibility.json
mkdir -p "$to/sql"
pushd "$repo" >> /dev/null
dm_preg_edit '/^Version: [0-9\.]+/m' "Version: $DM_VERSION" "$to/civicrm.php"
}
-
-## Generate the "bower_components" folder.
-## usage: dm_generate_bower <repo_path>
-function dm_generate_bower() {
- local repo="$1"
- pushd "$repo"
- ${DM_NPM:-npm} install
- ${DM_NODE:-node} node_modules/bower/bin/bower install
- popd
-}
-
## Generate the composer "vendor" folder
## usage: dm_generate_vendor <repo_path>
function dm_generate_vendor() {
DM_REF_BACKDROP="$DM_REF_BACKDROP" \
DM_REF_DRUPAL6="$DM_REF_DRUPAL6" \
DM_REF_DRUPAL="$DM_REF_DRUPAL" \
+ DM_REF_DRUPAL8="$DM_REF_DRUPAL8" \
DM_REF_JOOMLA="$DM_REF_JOOMLA" \
DM_REF_WORDPRESS="$DM_REF_WORDPRESS" \
DM_REF_PACKAGES="$DM_REF_PACKAGES" \
'civicrm-core' => repo("$DM_SOURCEDIR", getenv('DM_REF_CORE')),
'civicrm-drupal@6.x' => repo("$DM_SOURCEDIR/drupal", getenv('DM_REF_DRUPAL6')),
'civicrm-drupal@7.x' => repo("$DM_SOURCEDIR/drupal", getenv('DM_REF_DRUPAL')),
- //'civicrm-drupal@8.x' => repo("$DM_SOURCEDIR/drupal", getenv('DM_REF_DRUPAL8')),
+ 'civicrm-drupal-8' => repo("$DM_SOURCEDIR/drupal-8", getenv('DM_REF_DRUPAL8')),
'civicrm-joomla' => repo("$DM_SOURCEDIR/joomla", getenv('DM_REF_JOOMLA')),
'civicrm-packages' => repo("$DM_SOURCEDIR/packages", getenv('DM_REF_PACKAGES')),
'civicrm-wordpress' => repo("$DM_SOURCEDIR/WordPress", getenv('DM_REF_WORDPRESS')),
- **[Credits](release-notes/5.17.0.md#credits)**
- **[Feedback](release-notes/5.17.0.md#feedback)**
+## CiviCRM 5.16.4
+
+Released September 3, 2019
+
+- **[Synopsis](release-notes/5.16.4.md#synopsis)**
+- **[Bugs resolved](release-notes/5.16.4.md#bugs)**
+- **[Credits](release-notes/5.16.4.md#credits)**
+- **[Feedback](release-notes/5.16.4.md#feedback)**
+
## CiviCRM 5.16.3
Released August 22, 2019
--- /dev/null
+# CiviCRM 5.16.4
+
+Released September 3, 2019
+
+- **[Synopsis](#synopsis)**
+- **[Bugs resolved](#bugs)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?* | |
+|:--------------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities? | no |
+| Change the database schema? | no |
+| Alter the API? | no |
+| **Require attention to configuration options?** | **yes** |
+| Fix problems installing or upgrading to a previous version? | no |
+| Introduce features? | no |
+| **Fix bugs?** | **yes** |
+
+## <a name="bugs"></a>Bugs resolved
+
+- **_Smart Groups_: Relative date filters saved incorrectly ([dev/core#1226](https://lab.civicrm.org/dev/core/issues/1226):
+ [#15201](https://github.com/civicrm/civicrm-core/pull/15201), [#15169](https://github.com/civicrm/civicrm-core/pull/15169))**
+
+ On 5.16.0 - 5.16.3, if you saved a smart-group with a relative date
+ filter, it would incorrectly save the configuration.
+
+ If you recently created or modified a smart-group with a date-filter, please update it.
+ For discussion of cleanup tips, please use [dev/core#1226](https://lab.civicrm.org/dev/core/issues/1226).
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following authors and reviewers:
+
+Wikimedia Foundation - Eileen McNaughton; Pradeep Nayak; CiviCRM - Tim
+Otten; Australian Greens - Seamus Lee;
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Tim Otten and Andrew Hunt. If you'd like to
+provide feedback on them, please login to https://chat.civicrm.org/civicrm and
+contact `@agh1`.
| *Does this version...?* | |
|:--------------------------------------------------------------- |:-------:|
-| Fix security vulnerabilities? | |
-| Change the database schema? | **yes** |
-| Alter the API? | **yes** |
-| Require attention to configuration options? | |
-| Fix problems installing or upgrading to a previous version? | **yes** |
-| Introduce features? | **yes** |
-| Fix bugs? | **yes** |
+| Fix security vulnerabilities? | no |
+| **Change the database schema?** | **yes** |
+| **Alter the API?** | **yes** |
+| Require attention to configuration options? | no |
+| **Fix problems installing or upgrading to a previous version?** | **yes** |
+| **Introduce features?** | **yes** |
+| **Fix bugs?** | **yes** |
## <a name="features"></a>Features
Fixes a call to `languageNegotiationURL` that was causing cv to fail on Drupal
8 sites.
-- **Error when upgrading to 5.16.0
+- **Fail more gracefully when attempting to install on PHP 5.x
([dev/drupal#79](https://lab.civicrm.org/dev/drupal/issues/79):
- [15082](https://github.com/civicrm/civicrm-core/pull/15082))**
+ [15082](https://github.com/civicrm/civicrm-core/pull/15082) and
+ [15089](https://github.com/civicrm/civicrm-core/pull/15089))**
Raises the `MINIMUM_PHP_VERSION` from 5.6 to 7.0 in the metadata because when
upgrading via drush or Drupal web UI to Civi 5.16+ on PHP 5.6, the Civi
- class-loader fails to initialize.
+ class-loader fails to initialize. The installer is also updated to check the
+ PHP version before proceeding with the class loader.
- **Migrate CivicrmHelper::parseUrl() to CRM_Utils_System_Drupal8::parseUrl().
([14696](https://github.com/civicrm/civicrm-core/pull/14696))**
- **[NFC] comment fixes, function mis-casing fix
([14906](https://github.com/civicrm/civicrm-core/pull/14906))**
+- **[NFC] comment
+ fixes([15197](https://github.com/civicrm/civicrm-core/pull/15197))**
+
## <a name="credits"></a>Credits
This release was developed by the following code authors:
LOCK TABLES `civicrm_uf_field` WRITE;
/*!40000 ALTER TABLE `civicrm_uf_field` DISABLE KEYS */;
-INSERT INTO `civicrm_uf_field` (`id`, `uf_group_id`, `field_name`, `is_active`, `is_view`, `is_required`, `weight`, `help_post`, `help_pre`, `visibility`, `in_selector`, `is_searchable`, `location_type_id`, `phone_type_id`, `website_type_id`, `label`, `field_type`, `is_reserved`, `is_multi_summary`) VALUES (1,1,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(2,1,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(3,1,'street_address',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',0,0),(4,1,'city',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',0,0),(5,1,'postal_code',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(6,1,'country',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(7,1,'state_province',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(8,2,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(9,2,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(10,2,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(11,3,'participant_status',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Participant Status','Participant',1,0),(12,4,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(13,4,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(14,4,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(15,5,'organization_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(16,5,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(17,6,'household_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Household Name','Household',0,0),(18,6,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(19,7,'phone',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,1,NULL,'Home Phone','Contact',0,0),(20,7,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,2,NULL,'Home Mobile','Contact',0,0),(21,7,'street_address',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Address','Contact',0,0),(22,7,'city',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'City','Contact',0,0),(23,7,'state_province',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'State','Contact',0,0),(24,7,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Postal Code','Contact',0,0),(25,7,'email',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Email','Contact',0,0),(26,7,'group',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Groups','Contact',0,0),(27,7,'tag',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Tags','Contact',0,0),(28,7,'gender_id',1,0,1,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Gender','Individual',0,0),(29,7,'birth_date',1,0,1,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Date of Birth','Individual',0,0),(30,8,'street_address',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',1,0),(31,8,'city',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',1,0),(32,8,'postal_code',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(33,8,'country',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(34,8,'state_province',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(35,9,'organization_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(36,9,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,3,1,NULL,'Phone (Main) ','Contact',0,0),(37,9,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Email (Main) ','Contact',0,0),(38,9,'street_address',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Street Address','Contact',0,0),(39,9,'city',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'City','Contact',0,0),(40,9,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Postal Code','Contact',0,0),(41,9,'country',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Country','Contact',0,0),(42,9,'state_province',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'State/Province','Contact',0,0),(43,10,'financial_type',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Contribution',1,0),(44,10,'total_amount',1,0,0,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Contribution',1,0),(45,10,'contribution_status_id',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Status','Contribution',1,0),(46,10,'receive_date',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Contribution',1,0),(47,10,'contribution_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Contribution',0,0),(48,10,'payment_instrument',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Contribution',0,0),(49,10,'contribution_check_number',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Contribution',0,0),(50,10,'send_receipt',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Contribution',0,0),(51,10,'invoice_id',1,0,0,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Invoice ID','Contribution',0,0),(52,10,'soft_credit',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Contribution',0,0),(53,10,'soft_credit_type',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Contribution',0,0),(54,11,'membership_type',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Membership Type','Membership',1,0),(55,11,'join_date',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Member Since','Membership',1,0),(56,11,'membership_start_date',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Start Date','Membership',1,0),(57,11,'membership_end_date',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'End Date','Membership',1,0),(58,11,'membership_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Membership',0,0),(59,11,'send_receipt',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Membership',0,0),(60,11,'financial_type',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Membership',1,0),(61,11,'total_amount',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Membership',1,0),(62,11,'receive_date',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Membership',1,0),(63,11,'payment_instrument',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Membership',0,0),(64,11,'contribution_check_number',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Membership',0,0),(65,11,'contribution_status_id',1,0,1,12,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Status','Membership',1,0),(66,11,'soft_credit',1,0,0,13,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Membership',0,0),(67,11,'soft_credit_type',1,0,0,14,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Membership',0,0),(68,12,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(69,12,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(70,12,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(71,13,'prefix_id',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Individual Prefix','Individual',1,0),(72,13,'first_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',1,0),(73,13,'last_name',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',1,0),(74,13,'email',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Email Address','Contact',1,0);
+INSERT INTO `civicrm_uf_field` (`id`, `uf_group_id`, `field_name`, `is_active`, `is_view`, `is_required`, `weight`, `help_post`, `help_pre`, `visibility`, `in_selector`, `is_searchable`, `location_type_id`, `phone_type_id`, `website_type_id`, `label`, `field_type`, `is_reserved`, `is_multi_summary`) VALUES (1,1,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(2,1,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(3,1,'street_address',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',0,0),(4,1,'city',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',0,0),(5,1,'postal_code',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(6,1,'country',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(7,1,'state_province',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(8,2,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(9,2,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(10,2,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(11,3,'participant_status',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Participant Status','Participant',1,0),(12,4,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(13,4,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(14,4,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(15,5,'organization_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(16,5,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(17,6,'household_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Household Name','Household',0,0),(18,6,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(19,7,'phone',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,1,NULL,'Home Phone','Contact',0,0),(20,7,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,2,NULL,'Home Mobile','Contact',0,0),(21,7,'street_address',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Address','Contact',0,0),(22,7,'city',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'City','Contact',0,0),(23,7,'state_province',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'State','Contact',0,0),(24,7,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Postal Code','Contact',0,0),(25,7,'email',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Email','Contact',0,0),(26,7,'group',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Groups','Contact',0,0),(27,7,'tag',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Tags','Contact',0,0),(28,7,'gender_id',1,0,1,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Gender','Individual',0,0),(29,7,'birth_date',1,0,1,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Date of Birth','Individual',0,0),(30,8,'street_address',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',1,0),(31,8,'city',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',1,0),(32,8,'postal_code',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(33,8,'country',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(34,8,'state_province',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(35,9,'organization_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(36,9,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,3,1,NULL,'Phone (Main) ','Contact',0,0),(37,9,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Email (Main) ','Contact',0,0),(38,9,'street_address',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Street Address','Contact',0,0),(39,9,'city',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'City','Contact',0,0),(40,9,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Postal Code','Contact',0,0),(41,9,'country',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Country','Contact',0,0),(42,9,'state_province',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'State/Province','Contact',0,0),(43,10,'financial_type',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Contribution',1,0),(44,10,'total_amount',1,0,0,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Contribution',1,0),(45,10,'contribution_status_id',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Status','Contribution',1,0),(46,10,'receive_date',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Contribution',1,0),(47,10,'contribution_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Contribution',0,0),(48,10,'payment_instrument',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Contribution',0,0),(49,10,'contribution_check_number',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Contribution',0,0),(50,10,'send_receipt',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Contribution',0,0),(51,10,'invoice_id',1,0,0,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Invoice ID','Contribution',0,0),(52,10,'soft_credit',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Contribution',0,0),(53,10,'soft_credit_type',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Contribution',0,0),(54,11,'membership_type',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Membership Type','Membership',1,0),(55,11,'membership_join_date',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Member Since','Membership',1,0),(56,11,'membership_start_date',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Start Date','Membership',1,0),(57,11,'membership_end_date',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'End Date','Membership',1,0),(58,11,'membership_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Membership',0,0),(59,11,'send_receipt',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Membership',0,0),(60,11,'financial_type',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Membership',1,0),(61,11,'total_amount',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Membership',1,0),(62,11,'receive_date',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Membership',1,0),(63,11,'payment_instrument',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Membership',0,0),(64,11,'contribution_check_number',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Membership',0,0),(65,11,'contribution_status_id',1,0,1,12,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Status','Membership',1,0),(66,11,'soft_credit',1,0,0,13,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Membership',0,0),(67,11,'soft_credit_type',1,0,0,14,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Membership',0,0),(68,12,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(69,12,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(70,12,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(71,13,'prefix_id',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Individual Prefix','Individual',1,0),(72,13,'first_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',1,0),(73,13,'last_name',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',1,0),(74,13,'email',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Email Address','Contact',1,0);
/*!40000 ALTER TABLE `civicrm_uf_field` ENABLE KEYS */;
UNLOCK TABLES;
{else}
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
<table class="form-layout-compressed">
- {if $context eq 'standalone'}
<tr class="crm-grant-form-block-contact_id">
<td class="label">{$form.contact_id.label}</td>
<td>{$form.contact_id.html}</td>
</tr>
- {/if}
<tr class="crm-grant-form-block-status_id">
<td class="label">{$form.status_id.label}</td>
<td>{$form.status_id.html}</td>
+--------------------------------------------------------------------+
*}
<div class="crm-block crm-form-block crm-search-form-block">
-<table class="form-layout">
+ <table class="form-layout">
<tr>
- <td>{$form.mailing_name.label} {help id="id-mailing_name"}<br />
- {$form.mailing_name.html|crmAddClass:big}
- </td>
- </tr>
- <tr>
- <td>
- <label>{if $sms eq 1}{ts}SMS Date{/ts}{else}{ts}Mailing Date{/ts}{/if}</label>
- </td>
+ <td>{$form.mailing_name.label} {help id="id-mailing_name"}<br />
+ {$form.mailing_name.html|crmAddClass:big}
+ </td>
</tr>
<tr>
- {include file="CRM/Core/DateRange.tpl" fieldName="mailing" from='_from' to='_to'}
+ {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="mailing" colspan='2'}
</tr>
<tr>
- <td colspan="1">{$form.sort_name.label} {help id="id-create_sort_name"}<br />
- {$form.sort_name.html|crmAddClass:big}
- <br/><br/>
- <div class="crm-search-form-block-is_archive">
- {$form.is_archived.label} {help id="is_archived"}<br/>
- {$form.is_archived.html}
- </div>
- </td>
- {if $form.mailing_status}
- <td width="100%"><label>{if $sms eq 1}{ts}SMS Status{/ts}{else}{ts}Mailing Status{/ts}{/if}</label><br />
+ <td colspan="1">{$form.sort_name.label} {help id="id-create_sort_name"}<br />
+ {$form.sort_name.html|crmAddClass:big}
+ <br/><br/>
+ <div class="crm-search-form-block-is_archive">
+ {$form.is_archived.label} {help id="is_archived"}<br/>
+ {$form.is_archived.html}
+ </div>
+ </td>
+ {if $form.mailing_status}
+ <td width="100%"><label>{if $sms eq 1}{ts}SMS Status{/ts}{else}{ts}Mailing Status{/ts}{/if}</label><br />
<div class="listing-box" style="height: auto">
{foreach from=$form.mailing_status item="mailing_status_val"}
- <div class="{cycle values="odd-row,even-row"}">
- {$mailing_status_val.html}
- </div>
+ <div class="{cycle values="odd-row,even-row"}">
+ {$mailing_status_val.html}
+ </div>
{/foreach}
<div class="{cycle values="odd-row,even-row"}">
{$form.status_unscheduled.html}
</div>
- </div><br />
- </td>
- {/if}
+ </div><br />
+ </td>
+ {/if}
</tr>
{* language *}
{if $form.language}
<tr>
<td>{$form.language.label} {help id="id-language"}<br />
- {$form.language.html|crmAddClass:big}
+ {$form.language.html|crmAddClass:big}
</td>
</tr>
{/if}
{* campaign in mailing search *}
{include file="CRM/Campaign/Form/addCampaignToComponent.tpl"
- campaignContext="componentSearch" campaignTrClass='' campaignTdClass=''}
+ campaignContext="componentSearch" campaignTrClass='' campaignTdClass=''}
<tr>
- <td>{$form.buttons.html}</td><td colspan="2"></td>
+ <td>{$form.buttons.html}</td><td colspan="2"></td>
</tr>
-</table>
+ </table>
</div>
{literal}
</tr>
<tr>
- <td>
- {$form.member_source.label}
- <br />{$form.member_source.html}
- <p>
- {$form.member_test.label} {help id="is-test" file="CRM/Contact/Form/Search/Advanced"} {$form.member_test.html}
- </p>
+ <td>{$form.member_source.label}<br />
+ {$form.member_source.html}
</td>
<td>
- <p>
- {$form.membership_is_current_member.label}
+ {$form.membership_is_current_member.label}<br />
{$form.membership_is_current_member.html}
- </p>
- <p>
- {$form.member_is_primary.label}
- {help id="id-member_is_primary" file="CRM/Member/Form/Search.hlp"}
- {$form.member_is_primary.html}
- </p>
- <p>
- {$form.member_pay_later.label} {$form.member_pay_later.html}
- </p>
- <p>
- {if $form.member_auto_renew}
- <label>{$form.member_auto_renew.label}</label>
- {help id="id-member_auto_renew" file="CRM/Member/Form/Search.hlp"}
- <br/>
- {$form.member_auto_renew.html}
- {/if}
- </p>
- <p>
- {$form.member_is_override.label}
- {help id="id-member_is_override" file="CRM/Member/Form/Search.hlp"}
- {$form.member_is_override.html}
- </p>
</td>
</tr>
-
+<tr>
+ <td>{$form.member_test.label} {help id="is-test" file="CRM/Contact/Form/Search/Advanced"} {$form.member_test.html}
+ </td>
+ <td>
+ {$form.member_is_primary.label} {help id="id-member_is_primary" file="CRM/Member/Form/Search.hlp"} {$form.member_is_primary.html}
+ </td>
+</tr>
<tr><td><label>{$form.membership_id.label}</label> {$form.membership_id.html}</td>
+ <td>{$form.member_pay_later.label} {$form.member_pay_later.html}</td>
</tr>
-
-<tr><td><label>{ts}Member Since{/ts}</label></td></tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="member_join_date" from='_low' to='_high'}
+ <td>
+ {if $form.member_auto_renew}
+ <label>{$form.member_auto_renew.label}</label>
+ {help id="id-member_auto_renew" file="CRM/Member/Form/Search.hlp"}
+ <br/>
+ {$form.member_auto_renew.html}
+ {/if}
+ </td>
+ <td>{$form.member_is_override.label}{help id="id-member_is_override" file="CRM/Member/Form/Search.hlp"}{$form.member_is_override.html}</td>
</tr>
-
-<tr><td><label>{ts}Start Date{/ts}</label></td></tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="member_start_date" from='_low' to='_high'}
+ {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="membership_join_date" colspan='2'}
+</tr>
+<tr>
+ {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="membership_start_date" colspan='2'}
</tr>
-
-<tr><td><label>{ts}End Date{/ts}</label></td></tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="member_end_date" from='_low' to='_high'}
+ {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="membership_end_date" colspan='2'}
</tr>
{* campaign in membership search *}
{$row.membership_type}{if $row.is_test} ({ts}test{/ts}){/if}
{if $row.owner_membership_id}<br />({ts}by relationship{/ts}){/if}
</td>
- <td class="crm-membership-join_date">{$row.join_date|truncate:10:''|crmDate}</td>
+ <td class="crm-membership-join_date">{$row.membership_join_date|truncate:10:''|crmDate}</td>
<td class="crm-membership-start_date">{$row.membership_start_date|truncate:10:''|crmDate}</td>
<td class="crm-membership-end_date">{$row.membership_end_date|truncate:10:''|crmDate}</td>
<td class="crm-membership-source">{$row.membership_source}</td>
*}
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="pledge_payment_date" from='_low' to='_high' label="<label>Payment Scheduled</label>"}
+{include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="pledge_payment_scheduled_date" colspan="2"}
</tr>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="pledge_create_date" from='_low' to='_high' label="<label>Pledge Made</label>"}
+{include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="pledge_create_date" colspan="2"}
</tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="pledge_start_date" from='_low' to='_high' label="<label>Payments Start Date</label>"}
+{include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="pledge_start_date" colspan="2"}
</tr>
<tr>
-{include file="CRM/Core/DateRange.tpl" fieldName="pledge_end_date" from='_low' to='_high' label="<label>Payments Ended Date</label>"}
+{include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="pledge_end_date" colspan="2"}
</tr>
<tr>
<td>
*}
{assign var='hideTotal' value=$quickConfig+$noCalcValueDisplay}
+
<div id="pricesetTotal" class="crm-section section-pricesetTotal">
- <div class="label
-{if $hideTotal}, hiddenElement{/if}" id="pricelabel">
- {if ( $extends eq 'Contribution' ) || ( $extends eq 'Membership' )}
- <span id='amount_sum_label'>{ts}Total Amount{/ts}{else}{ts}Total Fee(s){/ts}</span>
- {if $isAdditionalParticipants} {ts}for this participant{/ts}{/if}
+ <div id="pricelabel" class="label {if $hideTotal}hiddenElement{/if}">
+ {if ($extends eq 'Contribution') || ($extends eq 'Membership')}
+ <span id='amount_sum_label'>{ts}Total Amount{/ts}</span>
+ {else}
+ <span id='amount_sum_label'>{ts}Total Fee(s){/ts}{if $isAdditionalParticipants} {ts}for this participant{/ts}{/if}</span>
{/if}
</div>
- <div class="content calc-value" {if $hideTotal}style="display:none;"{/if} id="pricevalue" ></div>
+ <div class="content calc-value" {if $hideTotal}style="display:none;"{/if} id="pricevalue"></div>
</div>
<script type="text/javascript">
var symbol = '{/literal}{$currencySymbol}{literal}';
var optionSep = '|';
+// Recalculate the total fees based on user selection
cj("#priceset [price]").each(function () {
+ var elementType = cj(this).attr('type');
+ if (this.tagName == 'SELECT') {
+ elementType = 'select-one';
+ }
- var elementType = cj(this).attr('type');
- if ( this.tagName == 'SELECT' ) {
- elementType = 'select-one';
- }
-
- switch(elementType) {
- case 'checkbox':
- //event driven calculation of element.
- cj(this).click(function(){
- calculateCheckboxLineItemValue(this);
- display(calculateTotalFee());
- });
+ switch(elementType) {
+ case 'checkbox':
+ cj(this).click(function(){
calculateCheckboxLineItemValue(this);
+ display(calculateTotalFee());
+ });
+ calculateCheckboxLineItemValue(this);
break;
case 'radio':
- //event driven calculation of element.
cj(this).click( function(){
calculateRadioLineItemValue(this);
display(calculateTotalFee());
calculateRadioLineItemValue(this);
break;
- case 'text':
-
- //event driven calculation of element.
- cj(this).bind( 'keyup', function() {
- calculateText(this);
- }).bind( 'blur' , function() {
+ case 'text':
+ cj(this).bind( 'keyup', function() {
+ calculateText(this);
+ }).bind( 'blur' , function() {
+ calculateText(this);
+ });
+ //default calculation of element.
calculateText(this);
- });
- //default calculation of element.
- calculateText(this);
-
- break;
-
- case 'select-one':
- calculateSelectLineItemValue(this);
+ break;
- //event driven calculation of element.
- cj(this).change( function() {
+ case 'select-one':
calculateSelectLineItemValue(this);
- display(calculateTotalFee());
- });
-
-
- break;
+ cj(this).change(function() {
+ calculateSelectLineItemValue(this);
+ display(calculateTotalFee());
+ });
+ break;
}
+
display(calculateTotalFee());
});
{/if}
{include file="CRM/Report/Form/ErrorMessage.tpl"}
</div>
+
+
+{if $outputMode == 'print'}
+ <script type="text/javascript">
+ window.print();
+ </script>
+{/if}
\ No newline at end of file
+--------------------------------------------------------------------+
*}
{* error.tpl: Display page for fatal errors. Provides complete HTML doc.*}
-{if $config->userFramework != 'Joomla' and $config->userFramework != 'WordPress'}
+{if $config->userFramework != 'WordPress'}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
}
</script>
{/literal}
-{if $config->userFramework != 'Joomla' and $config->userFramework != 'WordPress'}
+{if $config->userFramework != 'WordPress'}
</body>
</html>
{/if}
*/
class CRM_Batch_BAO_BatchTest extends CiviUnitTestCase {
+ /**
+ * Cleanup after test.
+ *
+ * @throws \CRM_Core_Exception
+ */
+ public function tearDown() {
+ parent::tearDown();
+ $this->quickCleanup(['civicrm_batch']);
+ }
+
/**
* This test checks that a batch search
* by payment method works.
* card and one with payment method check. After performing a
* search by payment method for checks, it makes sure that the
* results are only contributions made by check.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testGetBatchFinancialItems() {
$this->assertEquals(count($result), 1, 'In line' . __LINE__);
}
+ /**
+ * Test testExportFinancialBatch.
+ */
+ public function testExportFinancialBatch() {
+ $this->createLoggedInUser();
+ $batchParams = ['title' => 'Test Batch'];
+ $batchParams['status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Batch_BAO_Batch', 'status_id', 'Exported');
+ $batch = $this->callAPISuccess('Batch', 'create', $batchParams);
+ CRM_Batch_BAO_Batch::exportFinancialBatch([$batch['id']], 'CSV', NULL);
+ }
+
}
'field' => [
1 => [
'membership_type' => [0 => $this->_orgContactID, 1 => $this->_membershipTypeID],
- 'join_date' => '2013-07-22',
+ 'membership_join_date' => '2013-07-22',
'membership_start_date' => NULL,
'membership_end_date' => NULL,
'membership_source' => NULL,
],
2 => [
'membership_type' => [0 => $this->_orgContactID, 1 => $this->_membershipTypeID],
- 'join_date' => '2013-07-03',
+ 'membership_join_date' => '2013-07-03',
'membership_start_date' => '2013-02-03',
'membership_end_date' => NULL,
'membership_source' => NULL,
// no join date, coded end date
3 => [
'membership_type' => [0 => $this->_orgContactID, 1 => $this->_membershipTypeID],
- 'join_date' => NULL,
+ 'membership_join_date' => NULL,
'membership_start_date' => NULL,
'membership_end_date' => '2013-12-01',
'membership_source' => NULL,
$this->assertEquals($expectedContact, $activity['assignee_contact_id'], 'Activity is not assigned to expected contact');
}
+ /**
+ * Test that locateNameOrLabel does the right things.
+ *
+ * @dataProvider xmlDataProvider
+ */
+ public function testLocateNameOrLabel($xmlString, $expected) {
+ $xmlObj = new SimpleXMLElement($xmlString);
+ $this->assertEquals($expected, $this->process->locateNameOrLabel($xmlObj));
+ }
+
+ /**
+ * Data provider for testLocateNameOrLabel
+ * @return array
+ */
+ public function xmlDataProvider() {
+ return [
+ ['<RelationshipType><name>Senior Services Coordinator</name><creator>1</creator><manager>1</manager></RelationshipType>', 'Senior Services Coordinator'],
+ ['<RelationshipType><name>Senior Services Coordinator</name></RelationshipType>', 'Senior Services Coordinator'],
+ ['<RelationshipType><name>Lion Tamer's Obituary Writer</name></RelationshipType>', "Lion Tamer's Obituary Writer"],
+ ['<RelationshipType><machineName>BP1234</machineName><name>Banana Peeler</name></RelationshipType>', 'BP1234'],
+ ['<RelationshipType><machineName>BP1234</machineName><name>Banana Peeler</name><creator>1</creator><manager>1</manager></RelationshipType>', 'BP1234'],
+ ['<RelationshipType><machineName>0</machineName><name>Assistant Level 0</name></RelationshipType>', '0'],
+ ['<RelationshipType><machineName></machineName><name>Banana Peeler</name></RelationshipType>', 'Banana Peeler'],
+ // hopefully nobody would do this
+ ['<RelationshipType><machineName>null</machineName><name>Annulled Relationship</name></RelationshipType>', 'null'],
+ ];
+ }
+
}
]);
$this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
-
+ $this->callAPISuccessGetCount('Membership', ['contact_id' => $organisationID], 1);
// Disable the relationship & check the membership is removed.
$relationshipOne['is_active'] = 0;
$this->callAPISuccess('Relationship', 'create', array_merge($relationshipOne, ['is_active' => 0]));
*/
}
+ /**
+ * Test CRM_Contact_BAO_Relationship::add() function directly.
+ *
+ * In general it's preferred to use the Relationship-create api since it does
+ * checks and such before calling add(). There are already some good tests
+ * for the api, but since it does some more business logic after too the
+ * tests might not be checking exactly the same thing.
+ */
+ public function testBAOAdd() {
+ // add a new type
+ $relationship_type_id_1 = $this->relationshipTypeCreate([
+ 'name_a_b' => 'Food poison tester is',
+ 'name_b_a' => 'Food poison tester for',
+ 'contact_type_a' => 'Individual',
+ 'contact_type_b' => 'Individual',
+ ]);
+
+ // add some people
+ $contact_id_1 = $this->individualCreate();
+ $contact_id_2 = $this->individualCreate([], 1);
+
+ // create new relationship (using BAO)
+ $params = [
+ 'relationship_type_id' => $relationship_type_id_1,
+ 'contact_id_a' => $contact_id_1,
+ 'contact_id_b' => $contact_id_2,
+ ];
+ $relationshipObj = CRM_Contact_BAO_Relationship::add($params);
+ $this->assertEquals($relationshipObj->relationship_type_id, $relationship_type_id_1);
+ $this->assertEquals($relationshipObj->contact_id_a, $contact_id_1);
+ $this->assertEquals($relationshipObj->contact_id_b, $contact_id_2);
+ $this->assertEquals($relationshipObj->is_active, 1);
+
+ // demonstrate PR 15103 - should fail before the patch and pass after
+ $today = date('Ymd');
+ $params = [
+ 'id' => $relationshipObj->id,
+ 'end_date' => $today,
+ ];
+ $relationshipObj = CRM_Contact_BAO_Relationship::add($params);
+ $this->assertEquals($relationshipObj->relationship_type_id, $relationship_type_id_1);
+ $this->assertEquals($relationshipObj->contact_id_a, $contact_id_1);
+ $this->assertEquals($relationshipObj->contact_id_b, $contact_id_2);
+ $this->assertEquals($relationshipObj->is_active, 1);
+ $this->assertEquals($relationshipObj->end_date, $today);
+ }
+
}
$this->checkArrayEquals($result['relative_dates'], $expectedResult);
}
+ /**
+ * Test if change log relative dates are stored correctly
+ * in civicrm_saved_search table.
+ */
+ public function testRelativeDateChangeLog() {
+ $savedSearch = new CRM_Contact_BAO_SavedSearch();
+ $formValues = [
+ 'operator' => 'AND',
+ 'log_date_relative' => 'this.month',
+ 'radio_ts' => 'ts_all',
+ ];
+ $queryParams = [];
+ CRM_Contact_BAO_SavedSearch::saveRelativeDates($queryParams, $formValues);
+ CRM_Contact_BAO_SavedSearch::saveSkippedElement($queryParams, $formValues);
+ $savedSearch->form_values = serialize($queryParams);
+ $savedSearch->save();
+
+ $result = CRM_Contact_BAO_SavedSearch::getFormValues(CRM_Core_DAO::singleValueQuery('SELECT LAST_INSERT_ID()'));
+ $expectedResult = [
+ 'log' => 'this.month',
+ ];
+ $this->checkArrayEquals($result['relative_dates'], $expectedResult);
+ }
+
/**
* Test relative dates
*
*
* @param array $fieldSpec
* @param string $expectedJS
+ * @param array $expectedDefaults
*
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
- public function testLoadSavedMapping($fieldSpec, $expectedJS) {
+ public function testLoadSavedMapping($fieldSpec, $expectedJS, $expectedDefaults) {
$this->setUpMapFieldForm();
$mapping = $this->callAPISuccess('Mapping', 'create', ['name' => 'my test']);
$this->callAPISuccess('MappingField', 'create', array_merge(['mapping_id' => $mapping['id']], $fieldSpec));
$result = $this->loadSavedMapping($this->form, $mapping['id'], $fieldSpec['column_number']);
$this->assertEquals($expectedJS, $result['js']);
+ $this->assertEquals($expectedDefaults, $result['defaults']);
}
/**
"document.forms.MapField['mapper[1][1]'].style.display = 'none';
document.forms.MapField['mapper[1][2]'].style.display = 'none';
document.forms.MapField['mapper[1][3]'].style.display = 'none';\n",
+ ['mapper[1]' => ['first_name', 0, NULL]],
],
[
['name' => 'Phone', 'contact_type' => 'Individual', 'column_number' => 8, 'phone_type_id' => 1, 'location_type_id' => 2],
"document.forms.MapField['mapper[8][3]'].style.display = 'none';\n",
+ ['mapper[8]' => ['phone', 2, 1]],
],
[
- ['name' => 'Phone', 'contact_type' => 'Individual', 'column_number' => 0, 'im_provider_id' => 1, 'location_type_id' => 2],
+ ['name' => 'IM Screen Name', 'contact_type' => 'Individual', 'column_number' => 0, 'im_provider_id' => 1, 'location_type_id' => 2],
"document.forms.MapField['mapper[0][3]'].style.display = 'none';\n",
+ ['mapper[0]' => ['im', 2, 1]],
+ ],
+ [
+ ['name' => 'Website', 'contact_type' => 'Individual', 'column_number' => 0, 'website_type_id' => 1],
+ "document.forms.MapField['mapper[0][2]'].style.display = 'none';
+document.forms.MapField['mapper[0][3]'].style.display = 'none';\n",
+ ['mapper[0]' => ['url', 1]],
+ ],
+ [
+ // Yes, the relationship mapping really does use url whereas non relationship uses website because... legacy
+ ['name' => 'Url', 'contact_type' => 'Individual', 'column_number' => 0, 'website_type_id' => 1, 'relationship_type_id' => 1, 'relationship_direction' => 'a_b'],
+ "document.forms.MapField['mapper[0][3]'].style.display = 'none';\n",
+ ['mapper[0]' => ['1_a_b', 'url', 1]],
+ ],
+ [
+ ['name' => 'Phone', 'contact_type' => 'Individual', 'column_number' => 0, 'phone_type_id' => 1, 'relationship_type_id' => 1, 'relationship_direction' => 'b_a'],
+ '',
+ ['mapper[0]' => ['1_b_a', 'phone', 'Primary', 1]],
],
];
}
* @throws \CiviCRM_API3_Exception
*/
protected function loadSavedMapping($form, $mappingID, $columnNumber) {
- list($mappingName, $mappingContactType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $mappingRelation, $mappingOperator, $mappingValue, $mappingWebsiteType) = CRM_Core_BAO_Mapping::getMappingFields($mappingID, TRUE);
+ list($mappingName) = CRM_Core_BAO_Mapping::getMappingFields($mappingID, TRUE);
//get loaded Mapping Fields
$mappingName = CRM_Utils_Array::value(1, $mappingName);
- $mappingLocation = CRM_Utils_Array::value(1, $mappingLocation);
- $mappingPhoneType = CRM_Utils_Array::value(1, $mappingPhoneType);
- $mappingImProvider = CRM_Utils_Array::value(1, $mappingImProvider);
- $mappingRelation = CRM_Utils_Array::value(1, $mappingRelation);
- $mappingWebsiteType = CRM_Utils_Array::value(1, $mappingWebsiteType);
$defaults = [];
$js = '';
$processor->setMappingID($mappingID);
$processor->setFormName('document.forms.MapField');
$processor->setMetadata($this->getContactImportMetadata());
+ $processor->setContactTypeByConstant(CRM_Import_Parser::CONTACT_INDIVIDUAL);
- $return = $form->loadSavedMapping($processor, $mappingName, $columnNumber, $mappingRelation, $mappingWebsiteType, $mappingLocation, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns);
+ $return = $form->loadSavedMapping($processor, $mappingName, $columnNumber, $defaults, $js, $hasColumnNames, $dataPatterns, $columnPatterns);
return ['defaults' => $return[0], 'js' => $return[1]];
}
$this->callAPISuccess('Contact', 'delete', ['id' => $contact['id']]);
}
+ /**
+ * Test importing 2 phones of different types.
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
+ public function testImportTwoPhonesDifferentTypes() {
+ $processor = new CRM_Import_ImportProcessor();
+ $processor->setContactType('Individual');
+ $processor->setMappingFields(
+ [
+ ['name' => 'first_name'],
+ ['name' => 'last_name'],
+ ['name' => 'email'],
+ ['name' => 'phone', 'location_type_id' => 1, 'phone_type_id' => 2],
+ ['name' => 'phone', 'location_type_id' => 1, 'phone_type_id' => 1],
+ ]
+ );
+ $importer = $processor->getImporterObject();
+ $fields = ['First Name', 'new last name', 'bob@example.com', '1234', '5678'];
+ $importer->import(CRM_Import_Parser::DUPLICATE_UPDATE, $fields);
+ $contact = $this->callAPISuccessGetSingle('Contact', ['last_name' => 'new last name']);
+ $phones = $this->callAPISuccess('Phone', 'get', ['contact_id' => $contact['id']])['values'];
+ $this->assertCount(2, $phones);
+ }
+
/**
* Test that the import parser adds the address to the primary location.
*
'field_type' => 'Participant',
],
[
- 'field_name' => 'join_date',
+ 'field_name' => 'membership_join_date',
'field_type' => 'Membership',
],
[
$this->assertEquals('participant_role', $fields['Participant']['participant_role']['name']);
// already used
- $this->assertFalse(isset($fields['Membership']['join_date']));
+ $this->assertFalse(isset($fields['Membership']['membership_join_date']));
$this->assertEquals('end_date', $fields['Membership']['membership_end_date']['name']);
// already used
$this->assertEquals('participant_note', $fields['Participant']['participant_note']['name']);
$this->assertEquals('participant_role', $fields['Participant']['participant_role']['name']);
- $this->assertEquals('join_date', $fields['Membership']['join_date']['name']);
+ $this->assertEquals('join_date', $fields['Membership']['membership_join_date']['name']);
$this->assertEquals('end_date', $fields['Membership']['membership_end_date']['name']);
$this->assertEquals('activity_date_time', $fields['Activity']['activity_date_time']['name']);
$this->assertEquals('Participant', $fields['participant_note']['field_type']);
$this->assertEquals('Participant', $fields['participant_role']['field_type']);
- $this->assertEquals('Membership', $fields['join_date']['field_type']);
+ $this->assertEquals('Membership', $fields['membership_join_date']['field_type']);
$this->assertEquals('Membership', $fields['membership_end_date']['field_type']);
$this->assertEquals('Activity', $fields['activity_date_time']['field_type']);
/**
* Test IPN response updates contribution_recur & contribution for first & second contribution.
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public function testIPNPaymentMembershipRecurSuccess() {
$durationUnit = 'year';
$this->assertEquals(1, $contribution['contribution_status_id']);
$this->assertEquals('8XA571746W2698126', $contribution['trxn_id']);
// source gets set by processor
- $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
+ $this->assertTrue(substr($contribution['contribution_source'], 0, 20) === "Online Contribution:");
$contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', ['id' => $this->_contributionRecurID]);
$this->assertEquals(5, $contributionRecur['contribution_status_id']);
$paypalIPN = new CRM_Core_Payment_PaypalIPN($this->getPaypalRecurSubsequentTransaction());
'entity_table' => 'civicrm_membership',
]);
$this->callAPISuccessGetSingle('membership_payment', ['contribution_id' => $contribution['values'][1]['id']]);
+ }
+ /**
+ * Test IPN that we can force membership when the membership payment has been deleted.
+ *
+ * https://lab.civicrm.org/dev/membership/issues/13
+ *
+ * In this scenario the membership payment record was deleted (or not created) for the first contribution but we
+ * 'recover' by using the input membership id.
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
+ public function testIPNPaymentInputMembershipRecurSuccess() {
+ $durationUnit = 'year';
+ $this->setupMembershipRecurringPaymentProcessorTransaction(['duration_unit' => $durationUnit, 'frequency_unit' => $durationUnit]);
+ $membershipPayment = $this->callAPISuccessGetSingle('membership_payment', []);
+ $paypalIPN = new CRM_Core_Payment_PayPalIPN(array_merge($this->getPaypalRecurTransaction(), ['membershipID' => $membershipPayment['membership_id']]));
+ $paypalIPN->main();
+ $membershipEndDate = $this->callAPISuccessGetValue('membership', ['return' => 'end_date']);
+ CRM_Core_DAO::executeQuery('DELETE FROM civicrm_membership_payment WHERE id = ' . $membershipPayment['id']);
+ CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item SET entity_table = 'civicrm_contribution' WHERE entity_table = 'civicrm_membership'");
+
+ $paypalIPN = new CRM_Core_Payment_PaypalIPN(array_merge($this->getPaypalRecurSubsequentTransaction(), ['membershipID' => $membershipPayment['membership_id']]));
+ $paypalIPN->main();
+ $renewedMembershipEndDate = $this->membershipRenewalDate($durationUnit, $membershipEndDate);
+ $this->assertEquals($renewedMembershipEndDate, $this->callAPISuccessGetValue('membership', ['return' => 'end_date']));
+ $contribution = $this->callAPISuccess('contribution', 'get', [
+ 'contribution_recur_id' => $this->_contributionRecurID,
+ 'sequential' => 1,
+ ]);
+ $this->assertEquals(2, $contribution['count']);
+ $this->assertEquals('secondone', $contribution['values'][1]['trxn_id']);
+ $this->callAPISuccessGetCount('line_item', [
+ 'entity_id' => $this->ids['membership'],
+ 'entity_table' => 'civicrm_membership',
+ ], 1);
+ $this->callAPISuccessGetSingle('line_item', [
+ 'contribution_id' => $contribution['values'][1]['id'],
+ 'entity_table' => 'civicrm_membership',
+ ]);
+ $this->callAPISuccessGetSingle('membership_payment', ['contribution_id' => $contribution['values'][1]['id']]);
}
/**
'sic_code' => 'Sic Code',
'user_unique_id' => 'Unique ID (OpenID)',
'sort_name' => 'Sort Name',
+ 'communication_style_id' => 'Communication Style',
],
'civicrm_email' =>
[
protected $_contactIds = [];
+ /**
+ * Contacts created for the test.
+ *
+ * Overlaps contactIds....
+ *
+ * @var array
+ */
+ protected $contacts = [];
+
/**
* Tear down.
*
'civicrm_contact',
'civicrm_group_contact',
'civicrm_group',
+ 'civicrm_prevnext_cache',
]);
parent::tearDown();
}
// Retrieve pairs from prev next cache table
$select = ['pn.is_selected' => 'is_selected'];
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId);
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId, [], TRUE, 0);
$pnDupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, NULL, NULL, 0, 0, $select);
$this->assertEquals(count($foundDupes), count($pnDupePairs), 'Check number of dupe pairs in prev next cache.');
// Retrieve pairs from prev next cache table
$select = ['pn.is_selected' => 'is_selected'];
- $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId);
+ $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId, [], TRUE, 0);
$pnDupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, NULL, NULL, 0, 0, $select);
$this->assertEquals(count($foundDupes), count($pnDupePairs), 'Check number of dupe pairs in prev next cache.');
], $pairs);
}
+ /**
+ * Test results are returned when criteria are passed in.
+ */
+ public function testGetMatchesCriteriaMatched() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ 'criteria' => ['contact' => ['id' => ['>' => 1]]],
+ ])['values'];
+ $this->assertCount(2, $pairs);
+ }
+
+ /**
+ * Test results are returned when criteria are passed in & limit is respected.
+ */
+ public function testGetMatchesCriteriaMatchedWithLimit() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ 'criteria' => ['contact' => ['id' => ['>' => 1]]],
+ 'options' => ['limit' => 1],
+ ])['values'];
+ $this->assertCount(1, $pairs);
+ }
+
+ /**
+ * Test results are returned when criteria are passed in & limit is respected.
+ */
+ public function testGetMatchesCriteriaMatchedWithSearchLimit() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ 'criteria' => ['contact' => ['id' => ['>' => 1]]],
+ 'search_limit' => 1,
+ ])['values'];
+ $this->assertCount(1, $pairs);
+ }
+
+ /**
+ * Test getting matches where there are no criteria.
+ */
+ public function testGetMatchesNoCriteria() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ ])['values'];
+ $this->assertCount(2, $pairs);
+ }
+
+ /**
+ * Test getting matches with a limit in play.
+ */
+ public function testGetMatchesNoCriteriaButLimit() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ 'options' => ['limit' => 1],
+ ])['values'];
+ $this->assertCount(1, $pairs);
+ }
+
+ /**
+ * Test that if criteria are passed and there are no matching contacts no matches are returned.
+ */
+ public function testGetMatchesCriteriaNotMatched() {
+ $this->setupMatchData();
+ $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+ 'rule_group_id' => 1,
+ 'criteria' => ['contact' => ['id' => ['>' => 100000]]],
+ ])['values'];
+ $this->assertCount(0, $pairs);
+ }
+
/**
* Test function that gets organization pairs.
*
}
}
+ /**
+ * dev-financial-40: Test that partial payment entries in entity-financial-trxn table to ensure that reverse transaction is entered
+ */
+ public function testPartialPaymentEntries() {
+ $this->registerParticipantAndPay($this->_expensiveFee);
+ $priceSetParams['price_' . $this->priceSetFieldID] = $this->veryExpensiveFeeValueID;
+ $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant');
+ CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
+ $actualResults = $this->callAPISuccess('EntityFinancialTrxn', 'get', ['sequential' => 1, 'entity_table' => 'civicrm_financial_item'])['values'];
+ $this->assertCount(3, $actualResults);
+ $expectedResults = [
+ [
+ 'id' => 2,
+ 'amount' => 100.0,
+ 'entity_id' => 1,
+ 'financial_trxn_id' => 1,
+ 'entity_table' => 'civicrm_financial_item',
+ ],
+ [
+ 'id' => 4,
+ // ensure that reverse entry is entered in the EntityFinancialTrxn table on fee change to greater amount
+ 'amount' => -100.0,
+ 'entity_id' => 2,
+ 'financial_trxn_id' => 2,
+ 'entity_table' => 'civicrm_financial_item',
+ ],
+ [
+ 'id' => 5,
+ 'amount' => 120.00,
+ 'entity_id' => 3,
+ 'financial_trxn_id' => 2,
+ 'entity_table' => 'civicrm_financial_item',
+ ],
+ ];
+ foreach ($expectedResults as $key => $expectedResult) {
+ $this->checkArrayEquals($expectedResult, $actualResults[$key]);
+ }
+ }
+
+ /**
+ * dev-financial-40: Test that refund payment entries in entity-financial-trxn table to ensure that reverse transaction is entered on fee change to lesser amount
+ */
+ public function testRefundPaymentEntries() {
+ $this->registerParticipantAndPay($this->_expensiveFee);
+ $priceSetParams['price_' . $this->priceSetFieldID] = $this->cheapFeeValueID;
+ $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->participantID, 'participant');
+ CRM_Price_BAO_LineItem::changeFeeSelections($priceSetParams, $this->_participantId, 'participant', $this->_contributionId, $this->_feeBlock, $lineItem);
+ $actualResults = $this->callAPISuccess('EntityFinancialTrxn', 'get', ['sequential' => 1, 'entity_table' => 'civicrm_financial_item', 'return' => ['amount', 'entity_id']])['values'];
+ $expectedResults = [
+ [
+ 'id' => 2,
+ 'amount' => 100.00,
+ 'entity_id' => 1,
+ ],
+ [
+ 'id' => 4,
+ // ensure that reverse entry is entered in the EntityFinancialTrxn table
+ 'amount' => -100.00,
+ 'entity_id' => 2,
+ ],
+ [
+ 'id' => 5,
+ 'amount' => 80.00,
+ 'entity_id' => 3,
+ ],
+ ];
+ foreach ($expectedResults as $key => $expectedResult) {
+ $this->checkArrayEquals($expectedResult, $actualResults[$key]);
+ }
+ }
+
}
'financial_type_id' => 1,
'contribution_status_id' => 2,
'payment_instrument_id' => 1,
+ 'receive_date' => date('Y-m-d'),
]);
$participants = $this->callAPISuccess('Participant', 'get', []);
$this->assertEquals(1, $participants['count']);
$this->doExportTest(['fields' => $mappedFields, 'ids' => [$this->contactIDs[0]]]);
foreach ($this->csv->getRecords() as $row) {
- $id = $row['contact_id'];
+ $id = $row['Contact ID'];
$this->assertEquals('AIM', $row['Billing-IM Provider']);
$this->assertEquals('AIM', $row['Whare Kai-IM Provider']);
$this->assertEquals('BillingJabber' . $id, $row['Billing-IM Screen Name-Jabber']);
$this->doExportTest(['fields' => $fields]);
foreach ($this->csv as $row) {
- $this->assertEquals('Méin' . $row['contact_id'] . 'city', $row['Main-City']);
- $this->assertEquals('Billing' . $row['contact_id'] . 'street_address', $row['Billing-Street Address']);
- $this->assertEquals('Whare Kai' . $row['contact_id'] . 'postal_code', $row['Whare Kai-Postal Code']);
+ $contactID = (int) $row['Contact ID'];
+ $this->assertEquals('Méin' . $contactID . 'city', $row['Main-City']);
+ $this->assertEquals('Billing' . $contactID . 'street_address', $row['Billing-Street Address']);
+ $this->assertEquals('Whare Kai' . $contactID . 'postal_code', $row['Whare Kai-Postal Code']);
foreach ($relationships as $relatedContactID => $relationship) {
- $value = ((int) $row['contact_id'] === $this->contactIDs[0]) ? 'Méin' . $relatedContactID . 'city' : '';
+ $value = ($contactID === $this->contactIDs[0]) ? 'Méin' . $relatedContactID . 'city' : '';
$this->assertEquals($value, $row[$relationship['label'] . '-Main-City'], 'checking ' . $relationship['label'] . '-Main-City');
}
}
$this->assertEquals([
- 'contact_id' => 'contact_id varchar(255)',
+ 'contact_id' => 'contact_id varchar(16)',
'billing_city' => 'billing_city varchar(64)',
'billing_street_address' => 'billing_street_address varchar(96)',
'billing_postal_code' => 'billing_postal_code varchar(64)',
'membership_type' => 1,
'member_is_test' => 1,
'member_is_pay_later' => 1,
- 'join_date' => 1,
+ 'membership_join_date' => 1,
'membership_start_date' => 1,
'membership_end_date' => 1,
'membership_source' => 1,
*/
protected function getCaseHeaderDefinition() {
return [
- 81 => 'contact_id',
+ 81 => 'Contact ID',
82 => 'Case ID',
83 => 'case_activity_subject',
84 => 'Case Subject',
82 => 'Total Pledged',
83 => 'Total Paid',
84 => 'Pledge Made',
- 85 => 'pledge_start_date',
+ 85 => 'Pledge Start Date',
86 => 'Next Payment Date',
87 => 'Next Payment Amount',
88 => 'Pledge Status',
'case_activity_medium_id' => 'case_activity_medium_id varchar(255)',
'case_activity_details' => 'case_activity_details text',
'case_activity_is_auto' => 'case_activity_is_auto text',
- 'contact_id' => 'contact_id varchar(255)',
+ 'contact_id' => 'contact_id varchar(16)',
'case_id' => 'case_id varchar(16)',
'case_activity_subject' => 'case_activity_subject text',
'case_status' => 'case_status text',
'pledge_amount' => 'pledge_amount varchar(32)',
'pledge_total_paid' => 'pledge_total_paid text',
'pledge_create_date' => 'pledge_create_date varchar(32)',
- 'pledge_start_date' => 'pledge_start_date text',
+ 'pledge_start_date' => 'pledge_start_date varchar(32)',
'pledge_next_pay_date' => 'pledge_next_pay_date text',
'pledge_next_pay_amount' => 'pledge_next_pay_amount text',
'pledge_status' => 'pledge_status varchar(255)',
'membership_type' => 'membership_type varchar(128)',
'member_is_test' => 'member_is_test varchar(16)',
'member_is_pay_later' => 'member_is_pay_later varchar(16)',
- 'join_date' => 'join_date varchar(32)',
+ 'membership_join_date' => 'membership_join_date varchar(32)',
'membership_start_date' => 'membership_start_date varchar(32)',
'membership_end_date' => 'membership_end_date varchar(32)',
'membership_source' => 'membership_source varchar(128)',
/**
* Renew membership with change in membership type.
+ *
+ * @fixme Note that this test fails when today is August 29 2019 (and maybe other years?):
+ * Verify correct end date is calculated after membership renewal
+ * Failed asserting that two strings are equal.
+ * Expected-'2021-03-01'
+ * Actual+'2021-02-28'
+ * /home/jenkins/bknix-dfl/build/core-15165-73etc/web/sites/all/modules/civicrm/tests/phpunit/CRM/Member/BAO/MembershipTest.php:609
*/
public function testRenewMembership() {
$contactId = $this->individualCreate();
$this->assertEquals(1, $contributionResultAfterRelationshipDelete['count'], "Contribution has been wrongly deleted.");
}
+ /**
+ * dev/core/issues/860:
+ * Test creating two memberships via price set in the back end with a discount,
+ * checking that the line items have correct amounts.
+ */
+ public function testTwoMembershipsViaPriceSetInBackendWithDiscount() {
+ // Register buildAmount hook to apply discount.
+ $this->hookClass->setHook('civicrm_buildAmount', [$this, 'buildAmountMembershipDiscount']);
+
+ // Create two memberships for individual $this->_individualId, via a price set in the back end.
+ $this->createTwoMembershipsViaPriceSetInBackEnd($this->_individualId);
+ $contribution = $this->callAPISuccessGetSingle('Contribution', [
+ 'contact_id' => $this->_individualId,
+ ]);
+ // Note: we can't check for the contribution total being discounted, because the total is set
+ // when the contribution is created via $form->testSubmit(), but buildAmount isn't called
+ // until testSubmit() runs. Fixing that might involve making testSubmit() more sophisticated,
+ // or just hacking total_amount for this case.
+
+ $lineItemResult = $this->callAPISuccess('LineItem', 'get', [
+ 'contribution_id' => $contribution['id'],
+ ]);
+ $this->assertEquals(2, $lineItemResult['count']);
+ $discountedItems = 0;
+ foreach ($lineItemResult['values'] as $lineItem) {
+ if (CRM_Utils_String::startsWith($lineItem['label'], 'Long Haired Goat')) {
+ $this->assertEquals(15.0, $lineItem['line_total']);
+ $this->assertEquals('Long Haired Goat - one leg free!', $lineItem['label']);
+ $discountedItems++;
+ }
+ }
+ $this->assertEquals(1, $discountedItems);
+ }
+
+ /**
+ * Implements hook_civicrm_buildAmount() for testTwoMembershipsViaPriceSetInBackendWithDiscount().
+ */
+ public function buildAmountMembershipDiscount($pageType, &$form, &$amount) {
+ foreach ($amount as $id => $priceField) {
+ if (is_array($priceField['options'])) {
+ foreach ($priceField['options'] as $optionId => $option) {
+ if ($option['membership_type_id'] == 15) {
+ // Long Haired Goat membership discount.
+ $amount[$id]['options'][$optionId]['amount'] = $option['amount'] * 0.75;
+ $amount[$id]['options'][$optionId]['label'] = $option['label'] . ' - one leg free!';
+ }
+ }
+ }
+ }
+ }
+
/**
* Get a membership form object.
*
'contact_type' => '<a href="/index.php?q=civicrm/profile/view&reset=1&gid=7&id=' . $this->_contactID . '&snippet=4" class="crm-summary-link"><div class="icon crm-icon Individual-icon"></div></a>',
'sort_name' => 'Anderson, Anthony',
'membership_type' => 'General',
- 'join_date' => date('Y-m-d'),
+ 'membership_join_date' => date('Y-m-d'),
'membership_start_date' => date('Y-m-d'),
'membership_end_date' => $membership['end_date'],
'membership_source' => 'Payment',
$this->assertEquals(TRUE, $hasRelative);
}
+ /**
+ * Test Multiple Relative Date conversions
+ */
+ public function testSmartGroupMultipleRelatvieDateConversions() {
+ $this->callAPISuccess('SavedSearch', 'create', [
+ 'form_values' => [
+ ['membership_join_date_low', '=', '20190903000000'],
+ ['membership_join_date_high', '=', '20190903235959'],
+ ['membership_start_date_low', '=' , '20190901000000'],
+ ['membership_start_date_high', '=', '20190907235959'],
+ ['membership_end_date_low', '=', '20190901000000'],
+ ['membership_end_date_high', '=', '20190907235959'],
+ 'relative_dates' => [
+ 'member_join' => 'this.day',
+ 'member_start' => 'this.week',
+ 'member_end' => 'this.week',
+ ],
+ ],
+ ]);
+ $smartGroupConversionObject = new CRM_Upgrade_Incremental_SmartGroups();
+ $smartGroupConversionObject->updateGroups([
+ 'datepickerConversion' => [
+ 'membership_join_date',
+ 'membership_start_date',
+ 'membership_end_date',
+ ],
+ ]);
+ $savedSearch = $this->callAPISuccessGetSingle('SavedSearch', []);
+ $this->assertContains('6', array_keys($savedSearch['form_values']));
+ $this->assertEquals('membership_join_date_relative', $savedSearch['form_values'][6][0]);
+ $this->assertEquals('this.day', $savedSearch['form_values'][6][2]);
+ $this->assertContains('7', array_keys($savedSearch['form_values']));
+ $this->assertEquals('membership_start_date_relative', $savedSearch['form_values'][7][0]);
+ $this->assertEquals('this.week', $savedSearch['form_values'][7][2]);
+ $this->assertContains('8', array_keys($savedSearch['form_values']));
+ $this->assertEquals('membership_end_date_relative', $savedSearch['form_values'][8][0]);
+ $this->assertEquals('this.week', $savedSearch['form_values'][8][2]);
+ }
+
/**
* Test conversion of on hold group.
*/
return [
['{a: \'Apple\', \'b\': "Banana", c: [1, 2, 3]}', ['a' => 'Apple', 'b' => 'Banana', 'c' => [1, 2, 3]]],
['true', TRUE],
+ [' ', NULL],
['false', FALSE],
['null', NULL],
['"true"', 'true'],
["{ }", []],
[" [ ]", []],
[" [ 2 ]", [2]],
+ [
+ '{a: "parse error no closing bracket"',
+ NULL,
+ ],
[
'{a: ["foo", \'bar\'], "b": {a: [\'foo\', "bar"], b: {\'a\': ["foo", "bar"], b: {}}}}',
['a' => ['foo', 'bar'], 'b' => ['a' => ['foo', 'bar'], 'b' => ['a' => ['foo', 'bar'], 'b' => []]]],
if (!isset($params['target_contact_id'])) {
$params['target_contact_id'] = $this->individualCreate(array(
'first_name' => 'Julia',
- 'Last_name' => 'Anderson',
+ 'last_name' => 'Anderson',
'prefix' => 'Ms.',
'email' => 'julia_anderson@civicrm.org',
'contact_type' => 'Individual',
'return' => ['content'],
]);
$this->assertEquals($expectedContent, $getResult2['values'][$fileId]['content']);
+ // Do this again even though we just tested above to demonstrate that these fields should be returned even if you only ask to return 'content'.
foreach (['id', 'entity_table', 'entity_id', 'url'] as $field) {
- $this->assertEquals($createResult['values'][$fileId][$field], $getResult['values'][$fileId][$field], "Expect field $field to match");
+ if ($field == 'url') {
+ $this->assertEquals(substr($createResult['values'][$fileId][$field], 0, -15), substr($getResult2['values'][$fileId][$field], 0, -15));
+ $this->assertEquals(substr($createResult['values'][$fileId][$field], -3), substr($getResult2['values'][$fileId][$field], -3));
+ $this->assertApproxEquals(substr($createResult['values'][$fileId][$field], -14, 10), substr($getResult2['values'][$fileId][$field], -14, 10), 2);
+ }
+ else {
+ $this->assertEquals($createResult['values'][$fileId][$field], $getResult2['values'][$fileId][$field], "Expect field $field to match");
+ }
}
}
* @throws \Exception
*/
public function testCaseStatusByCaseType() {
- $this->markTestIncomplete('Cannot figure out why this passes locally but fails on Jenkins.');
$statusName = md5(mt_rand());
$template = $this->callAPISuccess('CaseType', 'getsingle', ['id' => $this->caseTypeId]);
unset($template['id']);
]);
$eventResult = $this->callAPISuccess('Event', 'getsingle', ['id' => $eventResult['id']]);
foreach ($templateParams as $param => $value) {
- $this->assertEquals($value, $eventResult[$param]);
+ $this->assertEquals($value, $eventResult[$param], print_r($eventResult, 1));
}
}
/**
* Test civicrm_group_nesting_get.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGet() {
$params = [
/**
* Test civicrm_group_nesting_get with just one param (child_group_id).
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGetWithChildGroupId() {
$params = [
/**
* Test civicrm_group_nesting_get with just one param (parent_group_id).
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGetWithParentGroupId() {
$params = [
* Test civicrm_group_nesting_get for no records results.
*
* Success expected. (these tests are of marginal value as are in syntax conformance,
- * don't copy & paste
+ * don't copy & paste.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGetEmptyResults() {
$params = [
* Test civicrm_group_nesting_create.
*
* @throws \Exception
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testCreate() {
$params = [
/**
* Test civicrm_group_nesting_remove.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testDelete() {
$params = [
* Test civicrm_group_nesting_remove with empty parameter array.
*
* Error expected.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testDeleteWithEmptyParams() {
$this->callAPIFailure('group_nesting', 'delete', []);
/**
* Test civicrm_group_organization_get with valid params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationGet() {
/**
* Test civicrm_group_organization_get with group_id.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationGetWithGroupId() {
$createParams = [
/**
* Test civicrm_group_organization_get with empty params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationGetWithEmptyParams() {
$params = [];
/**
* Test civicrm_group_organization_get with wrong params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationGetWithWrongParams() {
$params = 'groupOrg';
/**
* Test civicrm_group_organization_get invalid keys.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationGetWithInvalidKeys() {
$params = [
/**
* Check with valid params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationCreate() {
$params = [
/**
* CRM-13841 - Load Group Org before save
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationCreateTwice() {
$params = [
/**
* Check with empty params array.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationCreateWithEmptyParams() {
$params = [];
/**
* Check with invalid params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationCreateParamsNotArray() {
$params = 'group_org';
/**
* Check with invalid params keys.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationCreateWithInvalidKeys() {
$params = [
/**
* Test civicrm_group_organization_remove with params not an array.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationDeleteParamsNotArray() {
$params = 'delete';
/**
* Test civicrm_group_organization_remove with empty params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationDeleteWithEmptyParams() {
$params = [];
/**
* Test civicrm_group_organization_remove with valid params.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationDelete() {
$paramsC = [
/**
* Test civicrm_group_organization_remove with invalid params key.
+ *
+ * @dataProvider versionThreeAndFour
*/
public function testGroupOrganizationDeleteWithInvalidKey() {
$paramsDelete = [
* @param $dataSet
*/
public function testBatchMergeWorksCheckPermissionsTrue($dataSet) {
- CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM'];
+ CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM', 'merge duplicate contacts', 'force merge duplicate contacts'];
foreach ($dataSet['contacts'] as $params) {
$this->callAPISuccess('Contact', 'create', $params);
}
'start_date' => '2010-12-20',
'end_date' => '',
'membership_end_date' => '0',
- 'join_date' => '2010-12-20',
+ 'membership_join_date' => '2010-12-20',
'membership_start_date' => '2010-12-20',
];
$fields = civicrm_api3('Membership', 'getfields', ['action' => 'get']);
$this->assertEquals('2010-12-20', $params['start_date']);
$this->assertEquals('20101220000000', $params['membership_start_date']);
$this->assertEquals('', $params['end_date']);
- $this->assertEquals('20101220000000', $params['join_date'], 'join_date not set in line ' . __LINE__);
+ $this->assertEquals('20101220000000', $params['membership_join_date'], 'join_date not set in line ' . __LINE__);
}
public function test_civicrm_api3_validate_fields_event() {
public function test_civicrm_api3_validate_fields_exception() {
$params = [
- 'join_date' => 'abc',
+ 'membership_join_date' => 'abc',
];
try {
$fields = civicrm_api3('Membership', 'getfields', ['action' => 'get']);
_civicrm_api3_validate_fields('Membership', 'get', $params, $fields['values']);
}
catch (Exception$expected) {
- $this->assertEquals('join_date is not a valid date: abc', $expected->getMessage());
+ $this->assertEquals('membership_join_date is not a valid date: abc', $expected->getMessage());
}
}
<table>
<base>CRM/ACL</base>
- <class>Cache</class>
+ <class>ACLCache</class>
<name>civicrm_acl_cache</name>
<comment>Cache for acls and contacts</comment>
<add>1.6</add>
<optionGroupName>communication_style</optionGroupName>
</pseudoconstant>
<export>true</export>
+ <import>true</import>
+ <headerPattern>/style/i</headerPattern>
<comment>Communication style (e.g. formal vs. familiar) to use with this contact. FK to communication styles in civicrm_option_value.</comment>
<add>4.4</add>
<html>
<default>NULL</default>
<add>4.3</add>
</field>
+ <index>
+ <name>index_created_date</name>
+ <fieldName>created_date</fieldName>
+ <add>5.18</add>
+ </index>
<field>
<name>modified_date</name>
<type>timestamp</type>
<default>CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP</default>
<add>4.3</add>
</field>
+ <index>
+ <name>index_modified_date</name>
+ <fieldName>modified_date</fieldName>
+ <add>5.18</add>
+ </index>
</table>
<add>2.1</add>
<field>
<name>id</name>
+ <title>Cache ID</title>
<type>int unsigned</type>
<required>true</required>
+ <comment>Unique table ID</comment>
<add>2.1</add>
</field>
<primaryKey>
</primaryKey>
<field>
<name>group_name</name>
+ <title>Group Name</title>
<type>varchar</type>
<length>32</length>
<required>true</required>
</field>
<field>
<name>path</name>
+ <title>Path</title>
<type>varchar</type>
<length>255</length>
<comment>Unique path name for cache element</comment>
</index>
<field>
<name>data</name>
+ <title>Data</title>
<type>longtext</type>
<comment>data associated with this path</comment>
<add>2.1</add>
</field>
<field>
<name>component_id</name>
+ <title>Component ID</title>
<type>int unsigned</type>
<comment>Component that this menu item belongs to</comment>
<add>2.1</add>
</foreignKey>
<field>
<name>created_date</name>
+ <title>Created Date</title>
<type>timestamp</type>
<default>CURRENT_TIMESTAMP</default>
<comment>When was the cache item created</comment>
</field>
<field>
<name>expired_date</name>
+ <title>Expired Date</title>
<type>timestamp</type>
<default>NULL</default>
<required>false</required>
<table>civicrm_domain</table>
<key>id</key>
<add>3.1</add>
+ <onDelete>CASCADE</onDelete>
</foreignKey>
<field>
<name>name</name>
<type>Select Date</type>
<formatType>activityDate</formatType>
</html>
+ <uniqueName>membership_join_date</uniqueName>
</field>
<field>
<name>start_date</name>
<type>datetime</type>
<title>Pledge Start Date</title>
<required>true</required>
+ <export>true</export>
<comment>The date the first scheduled pledge occurs.</comment>
<add>2.1</add>
<html>
- <type>Select Date</type>
- </html>
+ <type>Select Date</type>
+ </html>
+ <uniqueName>pledge_start_date</uniqueName>
+ <uniqueTitle>Payments Start Date</uniqueTitle>
</field>
<field>
<name>create_date</name>
<title>Pledge Made</title>
<required>true</required>
<import>true</import>
+ <export>true</export>
<comment>When this pledge record was created.</comment>
<add>2.1</add>
<html>
<comment>When a pledge acknowledgement message was sent to the contributor.</comment>
<add>2.1</add>
<html>
- <type>Select Date</type>
+ <type>Select Date</type>
</html>
</field>
<field>
<comment>Date this pledge was cancelled by contributor.</comment>
<add>2.1</add>
<html>
- <type>Select Date</type>
+ <type>Select Date</type>
</html>
</field>
<field>
<name>end_date</name>
<type>datetime</type>
<title>Pledge End Date</title>
+ <export>true</export>
<comment>Date this pledge finished successfully (total pledge payments equal to or greater than pledged amount).</comment>
<add>2.1</add>
<html>
- <type>Select Date</type>
+ <type>Select Date</type>
</html>
+ <uniqueName>pledge_end_date</uniqueName>
+ <uniqueTitle>Payments Ended Date</uniqueTitle>
</field>
<field>
<name>max_reminders</name>
<default>1</default>
<comment>The maximum number of payment reminders to send for any given payment.</comment>
<html>
- <type>Text</type>
- </html>
+ <type>Text</type>
+ </html>
<add>2.1</add>
</field>
<field>
<comment>Send initial reminder this many days prior to the payment due date.</comment>
<add>2.1</add>
<html>
- <type>Select</type>
- </html>
+ <type>Select</type>
+ </html>
</field>
<field>
<name>additional_reminder_day</name>
<comment>Send additional reminder this many days after last one sent, up to maximum number of reminders.</comment>
<add>2.1</add>
<html>
- <type>Text</type>
- </html>
+ <type>Text</type>
+ </html>
</field>
<field>
<name>status_id</name>
<uniqueName>pledge_payment_scheduled_amount</uniqueName>
<title>Scheduled Amount</title>
<import>true</import>
+ <export>true</export>
<type>decimal</type>
<required>true</required>
<comment>Pledged amount for this payment (the actual contribution amount might be different).</comment>
<uniqueName>pledge_payment_scheduled_date</uniqueName>
<title>Scheduled Date</title>
<import>true</import>
+ <export>true</export>
<type>datetime</type>
<required>true</required>
<comment>The date the pledge payment is supposed to happen.</comment>
<type>Select Date</type>
<formatType>activityDate</formatType>
</html>
+ <uniqueTitle>Payment Scheduled</uniqueTitle>
</field>
<field>
<name>reminder_date</name>
( 10, 'soft_credit', 0, 0, 10, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Soft Credit{/ts}', 'Contribution', NULL, NULL ),
( 10, 'soft_credit_type', 0, 0, 11, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Soft Credit Type{/ts}', 'Contribution', NULL, NULL ),
( 11, 'membership_type', 1, 1, 1, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Membership Type{/ts}', 'Membership', NULL, NULL ),
- ( 11, 'join_date', 1, 1, 2, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Member Since{/ts}', 'Membership', NULL, NULL ),
+ ( 11, 'membership_join_date', 1, 1, 2, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Member Since{/ts}', 'Membership', NULL, NULL ),
( 11, 'membership_start_date', 0, 1, 3, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Start Date{/ts}', 'Membership', NULL, NULL ),
( 11, 'membership_end_date', 0, 1, 4, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}End Date{/ts}', 'Membership', NULL, NULL ),
( 11, 'membership_source', 0, 0, 5, 'User and User Admin Only', 0, 0, NULL, '{ts escape="sql"}Source{/ts}', 'Membership', NULL, NULL ),