'case_id',
'campaign_id',
];
+ // Q. What does the code below achieve? case_id and campaign_id are already
+ // in the array, defined above, and this code adds them in again if their
+ // component is enabled? @fixme remove case_id and campaign_id from the array above?
foreach (['case_id' => 'CiviCase', 'campaign_id' => 'CiviCampaign'] as $attr => $component) {
if (in_array($component, self::activityComponents())) {
$activityParams['return'][] = $attr;
// Eventually this second iteration should just handle the target contacts. It's a bit muddled at
// the moment as the bulk activity stuff needs unravelling & test coverage.
+ $caseIds = [];
foreach ($result as $id => $activity) {
$isBulkActivity = (!$bulkActivityTypeID || ($bulkActivityTypeID === $activity['activity_type_id']));
foreach ($mappingParams as $apiKey => $expectedName) {
// fetch case subject for case ID found
if (!empty($activity['case_id'])) {
- $activities[$id]['case_subject'] = civicrm_api3('Case', 'getvalue', [
- 'return' => 'subject',
- 'id' => reset($activity['case_id']),
- ]);
+ // Store cases; we'll look them up in one query below. We convert
+ // to int here so we can trust it for SQL.
+ $caseIds[$id] = (int) current($activity['case_id']);
}
}
else {
$activities[$id]['is_recurring_activity'] = CRM_Core_BAO_RecurringEntity::getParentFor($id, 'civicrm_activity');
}
+ // Look up any case subjects we need in a single query and add them in the relevant activities under 'case_subject'
+ if ($caseIds) {
+ $subjects = CRM_Core_DAO::executeQuery('SELECT id, subject FROM civicrm_case WHERE id IN (' . implode(',', array_unique($caseIds)) . ')')
+ ->fetchMap('id', 'subject');
+ foreach ($caseIds as $activityId => $caseId) {
+ $result[$activityId]['case_subject'] = $subjects[$caseId];
+ }
+ }
+
return $activities;
}
// Format params and add links.
$contactActivities = [];
+ // View-only activity types
+ $viewOnlyCaseActivityTypeIDs = array_flip(CRM_Activity_BAO_Activity::getViewOnlyActivityTypeIDs());
+
if (!empty($activities)) {
$activityStatus = CRM_Core_PseudoConstant::activityStatus();
}
$mask = CRM_Core_Action::mask($permissions);
+ $userID = CRM_Core_Session::getLoggedInContactID();
foreach ($activities as $activityId => $values) {
$activity = ['source_contact_name' => '', 'target_contact_name' => ''];
$accessMailingReport = TRUE;
}
- $actionLinks = CRM_Activity_Selector_Activity::actionLinks(
- CRM_Utils_Array::value('activity_type_id', $values),
- CRM_Utils_Array::value('source_record_id', $values),
- $accessMailingReport,
- CRM_Utils_Array::value('activity_id', $values)
- );
+ // Get action links.
+
+ // If this is a case activity, then we hand off to Case's actionLinks instead.
+ if (!empty($values['case_id']) && Civi::settings()->get('civicaseShowCaseActivities')) {
+ // This activity belongs to a case.
+ $caseId = current($values['case_id']);
+
+ $activity['subject'] = $values['subject'];
+
+ // Get the view and edit (update) links:
+ $caseActionLinks =
+ $actionLinks = array_intersect_key(
+ CRM_Case_Selector_Search::actionLinks(),
+ array_fill_keys([CRM_Core_Action::VIEW, CRM_Core_Action::UPDATE], NULL));
+
+ // Create a Manage Case link (using ADVANCED as can't use two VIEW ones)
+ $actionLinks[CRM_Core_Action::ADVANCED] = [
+ "name" => 'Manage Case',
+ "url" => 'civicrm/contact/view/case',
+ 'qs' => 'reset=1&id=%%caseid%%&cid=%%cid%%&action=view&context=&selectedChild=case',
+ "title" => ts('Manage Case %1', [1 => $caseId]),
+ 'class' => 'no-popup',
+ ];
+
+ $caseLinkValues = [
+ 'aid' => $activityId,
+ 'caseid' => $caseId,
+ 'cid' => current(CRM_Case_BAO_Case::getCaseClients($caseId) ?? []),
+ // Unlike other 'context' params, this 'ctx' param is appended raw to the URL.
+ 'cxt' => '',
+ ];
+
+ $caseActivityPermissions = CRM_Core_Action::VIEW | CRM_Core_Action::ADVANCED;
+ // Allow Edit link if:
+ // 1. Activity type is NOT view-only type. CRM-5871
+ // 2. User has edit permission.
+ if (!isset($viewOnlyCaseActivityTypeIDs[$values['activity_type_id']])
+ && CRM_Case_BAO_Case::checkPermission($activityId, 'edit', $values['activity_type_id'], $userID)) {
+ // We're allowed to edit.
+ $caseActivityPermissions |= CRM_Core_Action::UPDATE;
+ }
- $actionMask = array_sum(array_keys($actionLinks)) & $mask;
-
- $activity['links'] = CRM_Core_Action::formLink($actionLinks,
- $actionMask,
- [
- 'id' => $values['activity_id'],
- 'cid' => $params['contact_id'],
- 'cxt' => $context,
- 'caseid' => CRM_Utils_Array::value('case_id', $values),
- ],
- ts('more'),
- FALSE,
- 'activity.tab.row',
- 'Activity',
- $values['activity_id']
- );
+ $activity['links'] = CRM_Core_Action::formLink($actionLinks,
+ $caseActivityPermissions,
+ $caseLinkValues,
+ ts('more'),
+ FALSE,
+ 'activity.tab.row',
+ 'Activity',
+ $values['activity_id']
+ );
+ }
+ else {
+ // Non-case activity
+ $actionLinks = CRM_Activity_Selector_Activity::actionLinks(
+ CRM_Utils_Array::value('activity_type_id', $values),
+ CRM_Utils_Array::value('source_record_id', $values),
+ $accessMailingReport,
+ CRM_Utils_Array::value('activity_id', $values)
+ );
+ $actionMask = array_sum(array_keys($actionLinks)) & $mask;
+
+ $activity['links'] = CRM_Core_Action::formLink($actionLinks,
+ $actionMask,
+ [
+ 'id' => $values['activity_id'],
+ 'cid' => $params['contact_id'],
+ 'cxt' => $context,
+ 'caseid' => NULL,
+ ],
+ ts('more'),
+ FALSE,
+ 'activity.tab.row',
+ 'Activity',
+ $values['activity_id']
+ );
+ }
if ($values['is_recurring_activity']) {
$activity['is_recurring_activity'] = CRM_Core_BAO_RecurringEntity::getPositionAndCount($values['activity_id'], 'civicrm_activity');
],
'source_contact_id' => [
'type' => 'entityRef',
- 'label' => ts('Added By'),
+ 'label' => ts('Added by'),
'required' => FALSE,
],
'target_contact_id' => [
parent::preProcess();
// Get the contact read only fields to display.
- $readOnlyFields = array_merge(['sort_name' => ts('Added By'), 'target_sort_name' => ts('With Contact')],
+ $readOnlyFields = array_merge(['sort_name' => ts('Added by'), 'target_sort_name' => ts('With Contact')],
CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'contact_autocomplete_options',
TRUE, NULL, FALSE, 'name', TRUE
'id' => $row['activity_id'],
'cid' => $this->_contactId,
'cxt' => $this->_context,
- 'caseid' => CRM_Utils_Array::value('case_id', $row),
+ 'caseid' => isset($row['case_id']) ? current($row['case_id']) : NULL,
],
ts('more'),
FALSE,
'direction' => CRM_Utils_Sort::DONTCARE,
],
[
- 'name' => ts('Added By'),
+ 'name' => ts('Added by'),
'sort' => 'source_contact_name',
'direction' => CRM_Utils_Sort::DONTCARE,
],
'direction' => CRM_Utils_Sort::DONTCARE,
],
[
- 'name' => ts('Added By'),
+ 'name' => ts('Added by'),
'sort' => 'source_contact',
'direction' => CRM_Utils_Sort::DONTCARE,
],
*/
class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
- private $basicTokens;
- private $customFieldTokens;
+ use CRM_Core_TokenTrait;
/**
- * Mapping from tokenName to api return field
- * Use lists since we might need multiple fields
- *
- * @var array
+ * @return string
*/
- private static $fieldMapping = [
- 'activity_id' => ['id'],
- 'activity_type' => ['activity_type_id'],
- 'status' => ['status_id'],
- 'campaign' => ['campaign_id'],
- ];
+ private function getEntityName(): string {
+ return 'activity';
+ }
/**
- * CRM_Activity_Tokens constructor.
+ * @return string
*/
- public function __construct() {
- parent::__construct('activity', array_merge(
- $this->getBasicTokens(),
- $this->getCustomFieldTokens()
- ));
+ private function getEntityTableName(): string {
+ return 'civicrm_activity';
}
/**
- * @inheritDoc
+ * @return string
*/
- public function checkActive(\Civi\Token\TokenProcessor $processor) {
- return in_array('activityId', $processor->context['schema']) ||
- (!empty($processor->context['actionMapping'])
- && $processor->context['actionMapping']->getEntity() === 'civicrm_activity');
+ private function getEntityContextSchema(): string {
+ return 'activityId';
}
/**
- * @inheritDoc
+ * Mapping from tokenName to api return field
+ * Use lists since we might need multiple fields
+ *
+ * @var array
*/
- public function getActiveTokens(\Civi\Token\Event\TokenValueEvent $e) {
- $messageTokens = $e->getTokenProcessor()->getMessageTokens();
- if (!isset($messageTokens[$this->entity])) {
- return NULL;
- }
-
- $activeTokens = [];
- // if message token contains '_\d+_', then treat as '_N_'
- foreach ($messageTokens[$this->entity] as $msgToken) {
- if (array_key_exists($msgToken, $this->tokenNames)) {
- $activeTokens[] = $msgToken;
- }
- else {
- $altToken = preg_replace('/_\d+_/', '_N_', $msgToken);
- if (array_key_exists($altToken, $this->tokenNames)) {
- $activeTokens[] = $msgToken;
- }
- }
- }
- return array_unique($activeTokens);
- }
+ private static $fieldMapping = [
+ 'activity_id' => ['id'],
+ 'activity_type' => ['activity_type_id'],
+ 'status' => ['status_id'],
+ 'campaign' => ['campaign_id'],
+ ];
/**
* @inheritDoc
*/
public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent $e) {
- if ($e->mapping->getEntity() !== 'civicrm_activity') {
+ if ($e->mapping->getEntity() !== $this->getEntityTableName()) {
return;
}
$e->query->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
}
- /**
- * Find the fields that we need to get to construct the tokens requested.
- * @param array $tokens list of tokens
- * @return array list of fields needed to generate those tokens
- */
- public function getReturnFields($tokens) {
- // Make sure we always return something
- $fields = ['id'];
-
- foreach (array_intersect($tokens,
- array_merge(array_keys(self::getBasicTokens()), array_keys(self::getCustomFieldTokens()))
- ) as $token) {
- if (isset(self::$fieldMapping[$token])) {
- $fields = array_merge($fields, self::$fieldMapping[$token]);
- }
- else {
- $fields[] = $token;
- }
- }
- return array_unique($fields);
- }
-
/**
* @inheritDoc
*/
public function prefetch(\Civi\Token\Event\TokenValueEvent $e) {
- // Find all the activity IDs
- $activityIds
+ // Find all the entity IDs
+ $entityIds
= $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
- + $e->getTokenProcessor()->getContextValues('activityId');
+ + $e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());
- if (!$activityIds) {
- return;
+ if (!$entityIds) {
+ return NULL;
}
// Get data on all activities for basic and customfield tokens
$activities = civicrm_api3('Activity', 'get', [
- 'id' => ['IN' => $activityIds],
+ 'id' => ['IN' => $entityIds],
'options' => ['limit' => 0],
'return' => self::getReturnFields($this->activeTokens),
]);
];
// Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
- $activityId = isset($row->context['actionSearchResult']->entityID)
- ? $row->context['actionSearchResult']->entityID
- : $row->context['activityId'];
+ $activityId = $row->context['actionSearchResult']->entityID ?? $row->context[$this->getEntityContextSchema()];
$activity = (object) $prefetch['activity'][$activityId];
return $this->basicTokens;
}
- /**
- * Get the tokens for custom fields
- * @return array token name => token label
- */
- protected function getCustomFieldTokens() {
- if (!isset($this->customFieldTokens)) {
- $this->customFieldTokens = \CRM_Utils_Token::getCustomFieldTokens('Activity');
- }
- return $this->customFieldTokens;
- }
-
}
* Build the form object.
*/
public function buildQuickForm() {
- $filter = $this->getSettingPageFilter();
- $settings = civicrm_api3('Setting', 'getfields', [])['values'];
- foreach ($settings as $key => $setting) {
- if (isset($setting['settings_pages'][$filter])) {
- $this->_settings[$key] = $setting;
- }
- }
-
$this->addFieldsDefinedInSettingsMetadata();
// @todo look at sharing the code below in the settings trait.
/** @var \Civi\API\Kernel $apiKernel */
$apiKernel = \Civi::service('civi_api_kernel');
- $apiRequest = \Civi\API\Request::create($fields['api_entity'], $fields['api_action'], ['version' => 3], NULL);
+ $apiRequest = \Civi\API\Request::create($fields['api_entity'], $fields['api_action'], ['version' => 3]);
try {
$apiKernel->resolve($apiRequest);
}
* This class generates form components for the display preferences.
*/
class CRM_Admin_Form_Preferences_Contribute extends CRM_Admin_Form_Preferences {
- protected $_settings = [
- 'cvv_backoffice_required' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'update_contribution_on_membership_type_change' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'acl_financial_type' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'always_post_to_accounts_receivable' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'deferred_revenue_enabled' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'default_invoice_page' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- 'invoicing' => CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME,
- ];
/**
* Our standards for settings are to have a setting per value with defined metadata.
* Unfortunately the 'contribution_invoice_settings' has been added in non-compliance.
* We use this array to hack-handle.
*
- * I think the best way forwards would be to covert to multiple individual settings.
+ * These are now stored as individual settings but this form still does weird & wonderful things.
+ *
+ * Note the 'real' settings on this form are added via metadata definition - ie
+ * 'settings_pages' => ['contribute' => ['weight' => 1]], in their metadata.
*
* @var array
*/
/**
* Build the form object.
+ *
+ * @throws \CiviCRM_API3_Exception
+ * @throws \CRM_Core_Exception
*/
public function buildQuickForm() {
parent::buildQuickForm();
- $config = CRM_Core_Config::singleton();
$this->invoiceSettings = [
'invoice_prefix' => [
'html_type' => 'text',
'weight' => 1,
'description' => ts('Enter prefix to be display on PDF for invoice'),
],
- 'credit_notes_prefix' => [
- 'html_type' => 'text',
- 'title' => ts('Credit Notes Prefix'),
- 'weight' => 2,
- 'description' => ts('Enter prefix to be display on PDF for credit notes.'),
- ],
'due_date' => [
'html_type' => 'text',
'title' => ts('Due Date'),
'civicaseAllowMultipleClients' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'civicaseNaturalActivityTypeSort' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'civicaseActivityRevisions' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+ 'civicaseShowCaseActivities' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
];
/**
'Subject' => $subject,
];
- $mailer = Mail::factory($mailerName, $params);
+ $mailer = CRM_Utils_Mail::_createMailer($mailerName, $params);
$errorScope = CRM_Core_TemporaryErrorScope::ignoreException();
$result = $mailer->send($toEmail, $headers, $message);
* Add fields in the metadata to the template.
*
* @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
protected function addFieldsDefinedInSettingsMetadata() {
+ $this->addSettingsToFormFromMetadata();
$settingMetaData = $this->getSettingsMetaData();
$descriptions = [];
foreach ($settingMetaData as $setting => $props) {
}
//Load input as readonly whose values are overridden in civicrm.settings.php.
- if (Civi::settings()->getMandatory($setting)) {
+ if (Civi::settings()->getMandatory($setting) !== NULL) {
$props['html_attributes']['readonly'] = TRUE;
$this->includesReadOnlyFields = TRUE;
}
$this->$add($setting, $props['title'], $props['entity_reference_options']);
}
elseif ($add === 'addYesNo' && ($props['type'] === 'Boolean')) {
- $this->addRadio($setting, $props['title'], [1 => 'Yes', 0 => 'No'], NULL, ' ');
+ $this->addRadio($setting, $props['title'], [1 => 'Yes', 0 => 'No'], CRM_Utils_Array::value('html_attributes', $props), ' ');
}
elseif ($add === 'add') {
$this->add($props['html_type'], $setting, $props['title'], $options);
return array_intersect($order, $settingValueKeys);
}
+ /**
+ * Add settings to form if the metadata designates they should be on the page.
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+ protected function addSettingsToFormFromMetadata() {
+ $filter = $this->getSettingPageFilter();
+ $settings = civicrm_api3('Setting', 'getfields', [])['values'];
+ foreach ($settings as $key => $setting) {
+ if (isset($setting['settings_pages'][$filter])) {
+ $this->_settings[$key] = $setting;
+ }
+ }
+ }
+
}
try {
// Call multiple
if (empty($this->urlPath[3])) {
- $calls = CRM_Utils_Request::retrieve('calls', 'String', CRM_Core_DAO::$_nullObject, TRUE, NULL, 'POST', TRUE);
+ $calls = CRM_Utils_Request::retrieve('calls', 'String', CRM_Core_DAO::$_nullObject, TRUE, NULL, 'POST');
$calls = json_decode($calls, TRUE);
$response = [];
foreach ($calls as $index => $call) {
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
+
/**
* This class contains the functions for Case Management.
*/
*
* @param int $activityId
*
- * @return int, case ID
+ * @return int|null, case ID
*/
public static function getCaseIdByActivityId($activityId) {
$originalId = CRM_Core_DAO::singleValueQuery(
// store the submitted values in an array
$params = $this->controller->exportValues($this->_name);
- $xmlProcessor = new CRM_Case_XMLProcessor_Report();
- $contents = $xmlProcessor->run($this->_clientID,
- $this->_caseID,
- $this->_activitySetName,
- $params
+ // this is either a 1 or a 2, but the url expects a 1 or 0
+ $all = ($params['include_activities'] == 1) ? 1 : 0;
+
+ // similar but comes from a checkbox that's either 1 or not present
+ $is_redact = empty($params['is_redact']) ? 0 : 1;
+
+ $asn = rawurlencode($this->_activitySetName);
+
+ CRM_Utils_System::redirect(
+ CRM_Utils_System::url(
+ 'civicrm/case/report/print',
+ "caseID={$this->_caseID}&cid={$this->_clientID}&asn={$asn}&redact={$is_redact}&all={$all}"
+ )
);
- $this->set('report', $contents);
}
}
'translatedName' => ts('CiviCase'),
'title' => ts('CiviCase Engine'),
'search' => 1,
- 'showActivitiesInCore' => 0,
+ 'showActivitiesInCore' => Civi::settings()->get('civicaseShowCaseActivities') ?? 0,
];
}
foreach ($activitySetsXML->ActivitySet as $activitySetXML) {
if ((string ) $activitySetXML->name == $activitySetName) {
$activityTypes = array();
- $allActivityTypes = &$this->allActivityTypes();
+ $allActivityTypes = CRM_Case_PseudoConstant::caseActivityType(TRUE, TRUE);
foreach ($activitySetXML->ActivityTypes as $activityTypesXML) {
foreach ($activityTypesXML as $activityTypeXML) {
$activityTypeName = (string ) $activityTypeXML->name;
$case = $form->caseInfo($clientID, $caseID);
$template->assign_by_ref('case', $case);
- if ($params['include_activities'] == 1) {
+ if (CRM_Utils_Array::value('include_activities', $params) == 1) {
$template->assign('includeActivities', 'All');
}
else {
$location = ['location' => ["{$locName}" => $address]];
$returnProperties = array_merge($returnProperties, $location);
$params[] = ['location_type', '=', [1 => $fv['location_type_id']], 0, 0];
+ $primaryLocationOnly = FALSE;
}
else {
$returnProperties = array_merge($returnProperties, $address);
+ $primaryLocationOnly = TRUE;
}
$rows = [];
//get the total number of contacts to fetch from database.
$numberofContacts = count($this->_contactIds);
$query = new CRM_Contact_BAO_Query($params, $returnProperties);
- $details = $query->apiQuery($params, $returnProperties, NULL, NULL, 0, $numberofContacts);
+ $details = $query->apiQuery($params, $returnProperties, NULL, NULL, 0, $numberofContacts, TRUE, FALSE, TRUE, CRM_Contact_BAO_Query::MODE_CONTACTS, NULL, $primaryLocationOnly);
$messageToken = CRM_Utils_Token::getTokens($mailingFormat);
* Function to get email address of a contact.
*/
public static function getContactEmail() {
- if (!empty($_REQUEST['contact_id'])) {
- $contactID = CRM_Utils_Type::escape($_REQUEST['contact_id'], 'Positive');
- if (!CRM_Contact_BAO_Contact_Permission::allow($contactID, CRM_Core_Permission::EDIT)) {
- return;
+ $queryStrings = [];
+ $name = CRM_Utils_Array::value('name', $_GET);
+ if ($name) {
+ $name = CRM_Utils_Type::escape($name, 'String');
+ $wildCard = Civi::settings()->get('includeWildCardInName') ? '%' : '';
+ foreach (['cc.sort_name', 'ce.email'] as $column) {
+ $queryStrings[] = "{$column} LIKE '{$wildCard}{$name}%'";
}
- list($displayName,
- $userEmail
- ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactID);
+ $result = [];
+ $rowCount = Civi::settings()->get('search_autocomplete_count');
- CRM_Utils_System::setHttpHeader('Content-Type', 'text/plain');
- if ($userEmail) {
- echo $userEmail;
- }
- }
- else {
- $noemail = CRM_Utils_Array::value('noemail', $_GET);
- $queryString = NULL;
- $name = CRM_Utils_Array::value('name', $_GET);
- if ($name) {
- $name = CRM_Utils_Type::escape($name, 'String');
- if ($noemail) {
- $queryString = " cc.sort_name LIKE '%$name%'";
- }
- else {
- $queryString = " ( cc.sort_name LIKE '%$name%' OR ce.email LIKE '%$name%' ) ";
- }
- }
- else {
- $cid = CRM_Utils_Array::value('cid', $_GET);
- if ($cid) {
- //check cid for integer
- $contIDS = explode(',', $cid);
- foreach ($contIDS as $contID) {
- CRM_Utils_Type::escape($contID, 'Integer');
- }
- $queryString = " cc.id IN ( $cid )";
- }
+ // add acl clause here
+ list($aclFrom, $aclWhere) = CRM_Contact_BAO_Contact_Permission::cacheClause('cc');
+ if ($aclWhere) {
+ $aclWhere = "AND {$aclWhere}";
}
-
- if ($queryString) {
- $result = [];
- $offset = CRM_Utils_Array::value('offset', $_GET, 0);
- $rowCount = Civi::settings()->get('search_autocomplete_count');
-
- $offset = CRM_Utils_Type::escape($offset, 'Int');
-
- // add acl clause here
- list($aclFrom, $aclWhere) = CRM_Contact_BAO_Contact_Permission::cacheClause('cc');
- if ($aclWhere) {
- $aclWhere = " AND $aclWhere";
- }
- if ($noemail) {
- $query = "
-SELECT sort_name name, cc.id
-FROM civicrm_contact cc
- {$aclFrom}
-WHERE cc.is_deceased = 0 AND {$queryString}
- {$aclWhere}
-LIMIT {$offset}, {$rowCount}
-";
-
- // send query to hook to be modified if needed
- CRM_Utils_Hook::contactListQuery($query,
- $name,
- CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
- CRM_Utils_Request::retrieve('cid', 'Positive')
- );
-
- $dao = CRM_Core_DAO::executeQuery($query);
- while ($dao->fetch()) {
- $result[] = [
- 'id' => $dao->id,
- 'text' => $dao->name,
- ];
- }
- }
- else {
- $query = "
+ foreach ($queryStrings as &$queryString) {
+ $queryString = "(
SELECT sort_name name, ce.email, cc.id
FROM civicrm_email ce INNER JOIN civicrm_contact cc ON cc.id = ce.contact_id
{$aclFrom}
WHERE ce.on_hold = 0 AND cc.is_deceased = 0 AND cc.do_not_email = 0 AND {$queryString}
{$aclWhere}
-LIMIT {$offset}, {$rowCount}
-";
+LIMIT {$rowCount}
+)";
+ }
+ $query = implode(' UNION ', $queryStrings) . " LIMIT {$rowCount}";
- // send query to hook to be modified if needed
- CRM_Utils_Hook::contactListQuery($query,
- $name,
- CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
- CRM_Utils_Request::retrieve('cid', 'Positive')
- );
-
- $dao = CRM_Core_DAO::executeQuery($query);
-
- while ($dao->fetch()) {
- //working here
- $result[] = [
- 'text' => '"' . $dao->name . '" <' . $dao->email . '>',
- 'id' => (CRM_Utils_Array::value('id', $_GET)) ? "{$dao->id}::{$dao->email}" : '"' . $dao->name . '" <' . $dao->email . '>',
- ];
- }
- }
- CRM_Utils_JSON::output($result);
+ // send query to hook to be modified if needed
+ CRM_Utils_Hook::contactListQuery($query,
+ $name,
+ CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
+ CRM_Utils_Request::retrieve('cid', 'Positive')
+ );
+
+ $dao = CRM_Core_DAO::executeQuery($query);
+
+ while ($dao->fetch()) {
+ //working here
+ $result[] = [
+ 'text' => '"' . $dao->name . '" <' . $dao->email . '>',
+ 'id' => (CRM_Utils_Array::value('id', $_GET)) ? "{$dao->id}::{$dao->email}" : '"' . $dao->name . '" <' . $dao->email . '>',
+ ];
}
+ CRM_Utils_JSON::output($result);
}
CRM_Utils_System::civiExit();
}
* Run the page.
*
* This method is called after the page is created.
+ *
+ * @throws \CRM_Core_Exception
*/
public function run() {
// get the emails for this contact
- $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+ $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
$params = ['id' => $contactId];
* Run the page.
*
* This method is called after the page is created.
+ *
+ * @throws \CRM_Core_Exception
*/
public function run() {
// get the emails for this contact
- $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+ $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
$locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', ['labelColumn' => 'display_name']);
* Run the page.
*
* This method is called after the page is created.
+ *
+ * @throws \CRM_Core_Exception
*/
public function run() {
// get the emails for this contact
- $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+ $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
$locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', ['labelColumn' => 'display_name']);
$phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
* Run the page.
*
* This method is called after the page is created.
+ *
+ * @throws \CRM_Core_Exception
*/
public function run() {
// get the emails for this contact
- $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+ $contactId = CRM_Utils_Request::retrieveValue('cid', 'Positive');
$websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
$setPrevContribution = TRUE;
// CRM-13964 partial payment
if (!empty($params['partial_payment_total']) && !empty($params['partial_amount_to_pay'])) {
+ CRM_Core_Error::deprecatedFunctionWarning('partial_amount params are deprecated from Contribution.create - use Payment.create');
$partialAmtTotal = $params['partial_payment_total'];
$partialAmtPay = $params['partial_amount_to_pay'];
$params['total_amount'] = $partialAmtTotal;
if ($contributionStatus == 'Partially paid'
&& !empty($params['partial_payment_total']) && !empty($params['partial_amount_to_pay'])
) {
+ CRM_Core_Error::deprecatedFunctionWarning('partial_amount params are deprecated from Contribution.create - use Payment.create');
$partialAmtPay = CRM_Utils_Rule::cleanMoney($params['partial_amount_to_pay']);
$partialAmtTotal = CRM_Utils_Rule::cleanMoney($params['partial_payment_total']);
[
'id' => $resultDAO->id,
'contribution_id' => $contributionId,
- ]
+ ],
+ ts('more'),
+ FALSE,
+ 'Payment.edit.action',
+ 'Payment',
+ $resultDAO->id
);
}
return '';
}
- /**
- * Function to add payments for contribution for Partially Paid status
- *
- * @deprecated this is known to be flawed and possibly buggy.
- *
- * Replace with Order.create->Payment.create flow.
- *
- * @param array $contribution
- *
- * @throws \CiviCRM_API3_Exception
- */
- public static function addPayments($contribution) {
- // get financial trxn which is a payment
- $ftSql = "SELECT ft.id, ft.total_amount
- FROM civicrm_financial_trxn ft
- INNER JOIN civicrm_entity_financial_trxn eft ON eft.financial_trxn_id = ft.id AND eft.entity_table = 'civicrm_contribution'
- WHERE eft.entity_id = %1 AND ft.is_payment = 1 ORDER BY ft.id DESC LIMIT 1";
-
- $ftDao = CRM_Core_DAO::executeQuery($ftSql, [
- 1 => [
- $contribution->id,
- 'Integer',
- ],
- ]);
- $ftDao->fetch();
-
- // store financial item Proportionaly.
- $trxnParams = [
- 'total_amount' => $ftDao->total_amount,
- 'contribution_id' => $contribution->id,
- ];
- self::assignProportionalLineItems($trxnParams, $ftDao->id, $contribution->total_amount);
- }
-
/**
* Function use to store line item proportionally in in entity financial trxn table
*
}
$this->_processors = [];
foreach ($this->_paymentProcessors as $id => $processor) {
- // @todo review this. The inclusion of this IF was to address test processors being incorrectly loaded.
- // However the function $this->getValidProcessors() is expected to only return the processors relevant
- // to the mode (using the actual id - ie. the id of the test processor for the test processor).
- // for some reason there was a need to filter here per commit history - but this indicates a problem
- // somewhere else.
- if ($processor['is_test'] == ($this->_mode == 'test')) {
- $this->_processors[$id] = $processor['name'];
- if (!empty($processor['description'])) {
- $this->_processors[$id] .= ' : ' . $processor['description'];
- }
- if ($processor['is_recur']) {
- $this->_recurPaymentProcessors[$id] = $this->_processors[$id];
- }
+ $this->_processors[$id] = $processor['name'];
+ if (!empty($processor['description'])) {
+ $this->_processors[$id] .= ' : ' . $processor['description'];
+ }
+ if ($processor['is_recur']) {
+ $this->_recurPaymentProcessors[$id] = $this->_processors[$id];
}
}
// CRM-21002: pass the default payment processor ID whose credit card type icons should be populated first
/**
* Build the form object.
+ *
+ * @throws \CRM_Core_Exception
*/
public function buildQuickForm() {
if ($this->_view == 'transaction' && ($this->_action & CRM_Core_Action::BROWSE)) {
if ($this->_coid) {
if (CRM_Contribute_BAO_Contribution::isSubscriptionCancelled($this->_coid)) {
- CRM_Core_Error::fatal(ts('The recurring contribution looks to have been cancelled already.'));
+ CRM_Core_Error::statusBounce(ts('The recurring contribution looks to have been cancelled already.'));
}
$this->_paymentProcessorObj = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'obj');
$invoiceDate = date("F j, Y");
$dueDate = date('F j, Y', strtotime($contributionReceiveDate . "+" . $prefixValue['due_date'] . "" . $prefixValue['due_date_period']));
- $lineItem = CRM_Price_BAO_LineItem::getLineItemsByContributionID($contribID);
-
- $resultPayments = civicrm_api3('Payment', 'get', [
- 'sequential' => 1,
- 'contribution_id' => $contribID,
- ]);
- $amountPaid = 0;
- foreach ($resultPayments['values'] as $singlePayment) {
- // Only count payments that have been (status =) completed.
- if ($singlePayment['status_id'] == 1) {
- $amountPaid += $singlePayment['total_amount'];
- }
- }
+ $amountPaid = CRM_Core_BAO_FinancialTrxn::getTotalPayments($contribID, TRUE);
$amountDue = ($input['amount'] - $amountPaid);
// retrieving the subtotal and sum of same tax_rate
$dataArray = [];
$subTotal = 0;
+ $lineItem = CRM_Price_BAO_LineItem::getLineItemsByContributionID($contribID);
foreach ($lineItem as $taxRate) {
if (isset($dataArray[(string) $taxRate['tax_rate']])) {
$dataArray[(string) $taxRate['tax_rate']] = $dataArray[(string) $taxRate['tax_rate']] + CRM_Utils_Array::value('tax_amount', $taxRate);
'Boolean',
CRM_Core_DAO::$_nullArray,
FALSE,
- FALSE,
- 'REQUEST'
+ FALSE
);
if ($config->userSystem->is_drupal &&
$resetSessionTable
}
// Add data for popup link. Normally this is handled by CRM_Core_Form->addSelect
- $isSupportedWidget = in_array($widget, ['Select', 'Radio']);
$canEditOptions = CRM_Core_Permission::check('administer CiviCRM');
if ($field->option_group_id && !$search && $isSelect && $canEditOptions) {
$customFieldAttributes += array(
* @param string $tableName
* @param int $tableID
* @param int $userID
+ *
+ * @throws \CRM_Core_Exception
*/
public static function register(
$contactID,
CRM_Utils_Hook::notePrivacy($noteValues);
- if (!$noteValues['privacy']) {
+ if (empty($noteValues['privacy'])) {
return FALSE;
}
elseif (isset($noteValues['notePrivacy_hidden'])) {
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019 |
+ | Copyright CiviCRM LLC (c) 2004-2020 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
* @throws \CRM_Core_Exception
*/
protected function assignPaymentProcessor($isPayLaterEnabled) {
- $this->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors(
- [ucfirst($this->_mode) . 'Mode'],
- $this->_paymentProcessorIDs
- );
+ $this->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors([ucfirst($this->_mode) . 'Mode'], $this->_paymentProcessorIDs);
if ($isPayLaterEnabled) {
$this->_paymentProcessors[0] = CRM_Financial_BAO_PaymentProcessor::getPayment(0);
}
* obtain the location of given contact-id.
* This method is used by on-behalf-of form to dynamically generate poulate the
* location field values for selected permissioned contact.
+ *
+ * @throws \CRM_Core_Exception
*/
public static function getPermissionedLocation() {
$cid = CRM_Utils_Request::retrieve('cid', 'Integer', CRM_Core_DAO::$_nullObject, TRUE);
* @return bool
*/
protected function supportsLiveMode() {
- return TRUE;
+ return empty($this->_paymentProcessor['is_test']) ? TRUE : FALSE;
}
/**
* @return bool
*/
protected function supportsTestMode() {
- return TRUE;
+ return empty($this->_paymentProcessor['is_test']) ? FALSE : TRUE;
}
/**
return $params;
}
- /**
- * Are back office payments supported.
- *
- * E.g paypal standard won't permit you to enter a credit card associated with someone else's login.
- *
- * @return bool
- */
- protected function supportsLiveMode() {
- return TRUE;
- }
-
/**
* Does this payment processor support refund?
*
return CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', $this->getPaymentInstrumentID());
}
+ /**
+ * Are live payments supported - e.g dummy doesn't support this.
+ *
+ * @return bool
+ */
+ protected function supportsLiveMode() {
+ return TRUE;
+ }
+
+ /**
+ * Are test payments supported.
+ *
+ * @return bool
+ */
+ protected function supportsTestMode() {
+ return TRUE;
+ }
+
/**
* Declare that more than one payment can be processed at once.
*
--- /dev/null
+<?php
+
+trait CRM_Core_TokenTrait {
+
+ private $basicTokens;
+ private $customFieldTokens;
+
+ /**
+ * CRM_Entity_Tokens constructor.
+ */
+ public function __construct() {
+ parent::__construct($this->getEntityName(), array_merge(
+ $this->getBasicTokens(),
+ $this->getCustomFieldTokens()
+ ));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function checkActive(\Civi\Token\TokenProcessor $processor) {
+ return in_array($this->getEntityContextSchema(), $processor->context['schema']) ||
+ (!empty($processor->context['actionMapping'])
+ && $processor->context['actionMapping']->getEntity() === $this->getEntityTableName());
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getActiveTokens(\Civi\Token\Event\TokenValueEvent $e) {
+ $messageTokens = $e->getTokenProcessor()->getMessageTokens();
+ if (!isset($messageTokens[$this->entity])) {
+ return NULL;
+ }
+
+ $activeTokens = [];
+ // if message token contains '_\d+_', then treat as '_N_'
+ foreach ($messageTokens[$this->entity] as $msgToken) {
+ if (array_key_exists($msgToken, $this->tokenNames)) {
+ $activeTokens[] = $msgToken;
+ }
+ else {
+ $altToken = preg_replace('/_\d+_/', '_N_', $msgToken);
+ if (array_key_exists($altToken, $this->tokenNames)) {
+ $activeTokens[] = $msgToken;
+ }
+ }
+ }
+ return array_unique($activeTokens);
+ }
+
+ /**
+ * Find the fields that we need to get to construct the tokens requested.
+ * @param array $tokens list of tokens
+ * @return array list of fields needed to generate those tokens
+ */
+ public function getReturnFields($tokens) {
+ // Make sure we always return something
+ $fields = ['id'];
+
+ foreach (array_intersect($tokens,
+ array_merge(array_keys(self::getBasicTokens()), array_keys(self::getCustomFieldTokens()))
+ ) as $token) {
+ if (isset(self::$fieldMapping[$token])) {
+ $fields = array_merge($fields, self::$fieldMapping[$token]);
+ }
+ else {
+ $fields[] = $token;
+ }
+ }
+ return array_unique($fields);
+ }
+
+ /**
+ * Get the tokens for custom fields
+ * @return array token name => token label
+ */
+ protected function getCustomFieldTokens() {
+ if (!isset($this->customFieldTokens)) {
+ $this->customFieldTokens = \CRM_Utils_Token::getCustomFieldTokens(ucfirst($this->getEntityName()));
+ }
+ return $this->customFieldTokens;
+ }
+
+}
<item>
<path>civicrm/ajax/recipientListing</path>
<page_callback>CRM_Admin_Page_AJAX::recipientListing</page_callback>
- <access_arguments>administer CiviCRM,access CiviCRM</access_arguments>
+ <access_arguments>access CiviEvent,access CiviCRM</access_arguments>
</item>
<item>
<path>civicrm/admin/sms/provider</path>
*
* @return string
* SQL query performing the search
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
public function sql() {
if ($this->params &&
$id = 'entity_id';
}
else {
- CRM_Core_Error::fatal("Unsupported rule_table for civicrm_dedupe_rule.id of {$this->id}");
+ throw new CRM_Core_Exception("Unsupported rule_table for civicrm_dedupe_rule.id of {$this->id}");
}
break;
}
$ruleBao->find();
$ruleFields = [];
while ($ruleBao->fetch()) {
- $ruleFields[] = $ruleBao->rule_field;
+ $field_name = $ruleBao->rule_field;
+ if ($field_name == 'phone_numeric') {
+ $field_name = 'phone';
+ }
+ $ruleFields[] = $field_name;
}
return $ruleFields;
}
$ruleBao->find();
$ruleFields = [];
while ($ruleBao->fetch()) {
- $ruleFields[$ruleBao->rule_field] = $ruleBao->rule_weight;
+ $field_name = $ruleBao->rule_field;
+ if ($field_name == 'phone_numeric') {
+ $field_name = 'phone';
+ }
+ $ruleFields[$field_name] = $ruleBao->rule_weight;
}
return [$ruleFields, $rgBao->threshold];
* @return array
* Array of (cid1, cid2, weight) dupe triples
*
- * @throws Exception
+ * @throws \CRM_Core_Exception
*/
public static function dupes($rgid, $cids = [], $checkPermissions = TRUE) {
$rgBao = new CRM_Dedupe_BAO_RuleGroup();
*
* @return array
* array of (cid1, cid2, weight) dupe triples
- * @throws \CiviCRM_API3_Exception
+ *
+ * @throws \CRM_Core_Exception
*/
public static function dupesInGroup($rgid, $gid, $searchLimit = 0) {
$cids = array_keys(CRM_Contact_BAO_Group::getMember($gid, TRUE, $searchLimit));
$supportedFields = CRM_Dedupe_BAO_RuleGroup::supportedFields($ctype);
if (is_array($supportedFields)) {
foreach ($supportedFields as $table => $fields) {
- if ($table == 'civicrm_address') {
+ if ($table === 'civicrm_address') {
// for matching on civicrm_address fields, we also need the location_type_id
$fields['location_type_id'] = '';
// FIXME: we also need to do some hacking for id and name fields, see CRM-3902’s comments
'id' => $otherId,
'return' => ['created_date'],
])['created_date'];
- if ($otherCreatedDate < $mainCreatedDate) {
+ if ($otherCreatedDate < $mainCreatedDate && !empty($otherCreatedDate)) {
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact SET created_date = %1 WHERE id = %2", [
1 => [$otherCreatedDate, 'String'],
2 => [$mainId, 'Positive'],
return CRM_Core_DAO::singleValueQuery($query, $params);
}
- /**
- * Get the event fee info for given participant ids
- * either from line item table / participant table.
- *
- * @param array $participantIds
- * Participant ids.
- * @param bool $hasLineItems
- * Do fetch from line items.
- *
- * @return array
- */
- public function getFeeDetails($participantIds, $hasLineItems = FALSE) {
- $feeDetails = [];
- if (!is_array($participantIds) || empty($participantIds)) {
- return $feeDetails;
- }
-
- $select = '
-SELECT participant.id as id,
- participant.fee_level as fee_level,
- participant.fee_amount as fee_amount';
- $from = 'FROM civicrm_participant participant';
- if ($hasLineItems) {
- $select .= ' ,
-lineItem.id as lineId,
-lineItem.label as label,
-lineItem.qty as qty,
-lineItem.unit_price as unit_price,
-lineItem.line_total as line_total,
-field.label as field_title,
-field.html_type as html_type,
-field.id as price_field_id,
-value.id as price_field_value_id,
-value.description as description,
-IF( value.count, value.count, 0 ) as participant_count';
- $from .= "
-INNER JOIN civicrm_line_item lineItem ON ( lineItem.entity_table = 'civicrm_participant'
- AND lineItem.entity_id = participant.id )
-INNER JOIN civicrm_price_field field ON ( field.id = lineItem.price_field_id )
-INNER JOIN civicrm_price_field_value value ON ( value.id = lineItem.price_field_value_id )
-";
- }
- $where = 'WHERE participant.id IN ( ' . implode(', ', $participantIds) . ' )';
- $query = "$select $from $where";
-
- $feeInfo = CRM_Core_DAO::executeQuery($query);
- $feeProperties = ['fee_level', 'fee_amount'];
- $lineProperties = [
- 'lineId',
- 'label',
- 'qty',
- 'unit_price',
- 'line_total',
- 'field_title',
- 'html_type',
- 'price_field_id',
- 'participant_count',
- 'price_field_value_id',
- 'description',
- ];
- while ($feeInfo->fetch()) {
- if ($hasLineItems) {
- foreach ($lineProperties as $property) {
- $feeDetails[$feeInfo->id][$feeInfo->lineId][$property] = $feeInfo->$property;
- }
- }
- else {
- foreach ($feeProperties as $property) {
- $feeDetails[$feeInfo->id][$property] = $feeInfo->$property;
- }
- }
- }
-
- return $feeDetails;
- }
-
/**
* Retrieve additional participants display-names and URL to view their participant records.
* (excludes cancelled participants automatically)
*/
public $_action;
- /**
- * Role Id.
- *
- * @var int
- */
- protected $_roleId = NULL;
-
/**
* Event Type Id.
*
*/
protected $participantRecord;
+ /**
+ * Params for creating a payment to add to the contribution.
+ *
+ * @var array
+ */
+ protected $createPaymentParams = [];
+
+ /**
+ * Get params to create payments.
+ *
+ * @return array
+ */
+ public function getCreatePaymentParams(): array {
+ return $this->createPaymentParams;
+ }
+
+ /**
+ * Set params to create payments.
+ *
+ * @param array $createPaymentParams
+ */
+ public function setCreatePaymentParams(array $createPaymentParams) {
+ $this->createPaymentParams = $createPaymentParams;
+ }
+
/**
* Explicitly declare the entity api name.
*/
if ($this->_id) {
// assign participant id to the template
$this->assign('participantId', $this->_id);
- $this->_roleId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Participant', $this->_id, 'role_id');
}
// when fee amount is included in form
// CRM-13964 partial_payment_total
if ($amountOwed > $params['total_amount']) {
// the owed amount
- $contributionParams['partial_payment_total'] = $amountOwed;
- // the actual amount paid
- $contributionParams['partial_amount_to_pay'] = $params['total_amount'];
- $this->assign('balanceAmount', $contributionParams['partial_payment_total'] - $contributionParams['partial_amount_to_pay']);
+ $contributionParams['total_amount'] = $amountOwed;
+ $contributionParams['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
+ $this->assign('balanceAmount', $amountOwed - $params['total_amount']);
+ $this->storePaymentCreateParams($params);
}
}
}
}
foreach ($contributions as $contribution) {
- if ('Partially paid' === CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contribution->contribution_status_id)) {
- CRM_Contribute_BAO_Contribution::addPayments($contribution);
+ if (!empty($this->getCreatePaymentParams())) {
+ civicrm_api3('Payment', 'create', array_merge(['contribution_id' => $contribution->id], $this->getCreatePaymentParams()));
}
}
}
}
}
- $this->assign('totalAmount', $contributionParams['total_amount']);
+ $this->assign('totalAmount', $params['total_amount'] ?? $contributionParams['total_amount']);
$this->assign('isPrimary', 1);
$this->assign('checkNumber', CRM_Utils_Array::value('check_number', $params));
}
if (CRM_Event_BAO_Participant::isPrimaryParticipant($this->_id)) {
$additionalIds = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_id);
$hasLineItems = CRM_Utils_Array::value('priceSetId', $params, FALSE);
- $additionalParticipantDetails = CRM_Event_BAO_Participant::getFeeDetails($additionalIds,
- $hasLineItems
- );
+ $additionalParticipantDetails = $this->getFeeDetails($additionalIds, $hasLineItems);
}
}
else {
return '';
}
+ /**
+ * Store the parameters to create a payment, if approprite, on the form.
+ *
+ * @param array $params
+ * Params as submitted.
+ */
+ protected function storePaymentCreateParams($params) {
+ if ('Completed' === CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $params['contribution_status_id'])) {
+ $this->setCreatePaymentParams([
+ 'total_amount' => $params['total_amount'],
+ 'is_send_contribution_notification' => FALSE,
+ 'payment_instrument_id' => $params['payment_instrument_id'],
+ 'trxn_date' => $params['receive_date'] ?? date('Y-m-d'),
+ 'trxn_id' => $params['trxn_id'],
+ 'pan_truncation' => $params['pan_truncation'] ?? '',
+ 'card_type_id' => $params['card_type_id'] ?? '',
+ 'check_number' => $params['check_number'] ?? '',
+ 'skipCleanMoney' => TRUE,
+ ]);
+ }
+ }
+
+ /**
+ * Get the event fee info for given participant ids
+ * either from line item table / participant table.
+ *
+ * @param array $participantIds
+ * Participant ids.
+ * @param bool $hasLineItems
+ * Do fetch from line items.
+ *
+ * @return array
+ */
+ public function getFeeDetails($participantIds, $hasLineItems = FALSE) {
+ $feeDetails = [];
+ if (!is_array($participantIds) || empty($participantIds)) {
+ return $feeDetails;
+ }
+
+ $select = '
+SELECT participant.id as id,
+ participant.fee_level as fee_level,
+ participant.fee_amount as fee_amount';
+ $from = 'FROM civicrm_participant participant';
+ if ($hasLineItems) {
+ $select .= ' ,
+lineItem.id as lineId,
+lineItem.label as label,
+lineItem.qty as qty,
+lineItem.unit_price as unit_price,
+lineItem.line_total as line_total,
+field.label as field_title,
+field.html_type as html_type,
+field.id as price_field_id,
+value.id as price_field_value_id,
+value.description as description,
+IF( value.count, value.count, 0 ) as participant_count';
+ $from .= "
+INNER JOIN civicrm_line_item lineItem ON ( lineItem.entity_table = 'civicrm_participant'
+ AND lineItem.entity_id = participant.id )
+INNER JOIN civicrm_price_field field ON ( field.id = lineItem.price_field_id )
+INNER JOIN civicrm_price_field_value value ON ( value.id = lineItem.price_field_value_id )
+";
+ }
+ $where = 'WHERE participant.id IN ( ' . implode(', ', $participantIds) . ' )';
+ $query = "$select $from $where";
+
+ $feeInfo = CRM_Core_DAO::executeQuery($query);
+ $feeProperties = ['fee_level', 'fee_amount'];
+ $lineProperties = [
+ 'lineId',
+ 'label',
+ 'qty',
+ 'unit_price',
+ 'line_total',
+ 'field_title',
+ 'html_type',
+ 'price_field_id',
+ 'participant_count',
+ 'price_field_value_id',
+ 'description',
+ ];
+ while ($feeInfo->fetch()) {
+ if ($hasLineItems) {
+ foreach ($lineProperties as $property) {
+ $feeDetails[$feeInfo->id][$feeInfo->lineId][$property] = $feeInfo->$property;
+ }
+ }
+ else {
+ foreach ($feeProperties as $property) {
+ $feeDetails[$feeInfo->id][$property] = $feeInfo->$property;
+ }
+ }
+ }
+
+ return $feeDetails;
+ }
+
}
*
* @param string $key
* Fully-qualified extension name.
+ *
+ * @throws \CRM_Extension_Exception_MissingException
*/
public function getResUrl($key);
*/
public $requires = [];
+ /**
+ * @var array
+ * List of strings (tag-names).
+ */
+ public $tags = [];
+
/**
* Load extension info an XML file.
*
];
}
}
+ elseif ($attr === 'tags') {
+ $this->tags = [];
+ foreach ($val->tag as $tag) {
+ $this->tags[] = (string) $tag;
+ }
+ }
elseif ($attr === 'requires') {
$this->requires = $this->filterRequirements($val);
}
*
* @return string
* url for resources in this extension
+ *
+ * @throws \CRM_Extension_Exception_MissingException
*/
public function keyToUrl($key) {
- if ($key == 'civicrm') {
+ if ($key === 'civicrm') {
// CRM-12130 Workaround: If the domain's config_backend is NULL at the start of the request,
// then the Mapper is wrongly constructed with an empty value for $this->civicrmUrl.
if (empty($this->civicrmUrl)) {
* @param bool $fresh
* whether to forcibly reload extensions list from canonical store.
* @return array
- * array(array('prefix' => $, 'file' => $))
+ * array(array('prefix' => $, 'fullName' => $, 'filePath' => $))
*/
public function getActiveModuleFiles($fresh = FALSE) {
if (!defined('CIVICRM_DSN')) {
return [];
}
+ // The list of module files is cached in two tiers. The tiers are slightly
+ // different:
+ //
+ // 1. The persistent tier (cache) stores
+ // names WITHOUT absolute paths.
+ // 2. The ephemeral/thread-local tier (statics) stores names
+ // WITH absolute paths.
+ // Return static value instead of re-running query
+ if (isset(Civi::$statics[__CLASS__]['moduleExtensions']) && !$fresh) {
+ return Civi::$statics[__CLASS__]['moduleExtensions'];
+ }
+
$moduleExtensions = NULL;
+
+ // Checked if it's stored in the persistent cache.
if ($this->cache && !$fresh) {
$moduleExtensions = $this->cache->get($this->cacheKey . '_moduleFiles');
}
+ // If cache is empty we build it from database.
if (!is_array($moduleExtensions)) {
$compat = CRM_Extension_System::getCompatibilityInfo();
if (!empty($compat[$dao->full_name]['force-uninstall'])) {
continue;
}
- try {
- $moduleExtensions[] = [
- 'prefix' => $dao->file,
- 'filePath' => $this->keyToPath($dao->full_name),
- ];
- }
- catch (CRM_Extension_Exception $e) {
- // Putting a stub here provides more consistency
- // in how getActiveModuleFiles when racing between
- // dirty file-removals and cache-clears.
- CRM_Core_Session::setStatus($e->getMessage(), '', 'error');
- $moduleExtensions[] = [
- 'prefix' => $dao->file,
- 'filePath' => NULL,
- ];
- }
+ $moduleExtensions[] = [
+ 'prefix' => $dao->file,
+ 'fullName' => $dao->full_name,
+ 'filePath' => NULL,
+ ];
}
if ($this->cache) {
$this->cache->set($this->cacheKey . '_moduleFiles', $moduleExtensions);
}
}
+
+ // Since we're not caching the full path we add it now.
+ array_walk($moduleExtensions, function(&$value, $key) {
+ try {
+ if (!$value['filePath']) {
+ $value['filePath'] = $this->keyToPath($value['fullName']);
+ }
+ }
+ catch (CRM_Extension_Exception $e) {
+ // Putting a stub here provides more consistency
+ // in how getActiveModuleFiles when racing between
+ // dirty file-removals and cache-clears.
+ CRM_Core_Session::setStatus($e->getMessage(), '', 'error');
+ $value['filePath'] = NULL;
+ }
+ });
+
+ Civi::$statics[__CLASS__]['moduleExtensions'] = $moduleExtensions;
+
return $moduleExtensions;
}
*
* @return array
* (string $extKey => string $baseUrl)
+ *
+ * @throws \CRM_Extension_Exception_MissingException
*/
public function getActiveModuleUrls() {
// TODO optimization/caching
foreach ($this->getModules() as $module) {
/** @var $module CRM_Core_Module */
if ($module->is_active) {
- $urls[$module->name] = $this->keyToUrl($module->name);
+ try {
+ $urls[$module->name] = $this->keyToUrl($module->name);
+ }
+ catch (CRM_Extension_Exception_MissingException $e) {
+ CRM_Core_Session::setStatus(ts('An enabled extension is missing from the extensions directory') . ':' . $module->name);
+ }
}
}
return $urls;
return $keys;
}
+ /**
+ * Get a list of extensions which match a given tag.
+ *
+ * @param string $tag
+ * Ex: 'foo'
+ * @return array
+ * Array(string $key).
+ * Ex: array("org.foo.bar").
+ */
+ public function getKeysByTag($tag) {
+ $allTags = $this->getAllTags();
+ return $allTags[$tag] ?? [];
+ }
+
+ /**
+ * Get a list of extension tags.
+ *
+ * @return array
+ * Ex: ['form-building' => ['org.civicrm.afform-gui', 'org.civicrm.afform-html']]
+ */
+ public function getAllTags() {
+ $tags = Civi::cache('short')->get('extension_tags', NULL);
+ if ($tags !== NULL) {
+ return $tags;
+ }
+
+ $tags = [];
+ $allInfos = $this->getAllInfos();
+ foreach ($allInfos as $key => $info) {
+ foreach ($info->tags as $tag) {
+ $tags[$tag][] = $key;
+ }
+ }
+ return $tags;
+ }
+
/**
* @return array
* Ex: $result['org.civicrm.foobar'] = new CRM_Extension_Info(...).
$whiteList = ['check_number', 'payment_processor_id', 'fee_amount', 'total_amount', 'contribution_id', 'net_amount', 'card_type_id', 'pan_truncation', 'trxn_result_code', 'payment_instrument_id', 'trxn_id', 'trxn_date'];
$paymentTrxnParams = array_intersect_key($params, array_fill_keys($whiteList, 1));
$paymentTrxnParams['is_payment'] = 1;
+ // Really we should have a DB default.
+ $paymentTrxnParams['fee_amount'] = $paymentTrxnParams['fee_amount'] ?? 0;
if (isset($paymentTrxnParams['payment_processor_id']) && empty($paymentTrxnParams['payment_processor_id'])) {
// Don't pass 0 - ie the Pay Later processor as it is a pseudo-processor.
}
elseif ($contributionStatus === 'Pending' && $params['total_amount'] > 0) {
self::updateContributionStatus($contribution['id'], 'Partially Paid');
+ $participantPayments = civicrm_api3('ParticipantPayment', 'get', [
+ 'contribution_id' => $contribution['id'],
+ 'participant_id.status_id' => ['IN' => ['Pending from pay later', 'Pending from incomplete transaction']],
+ ])['values'];
+ foreach ($participantPayments as $participantPayment) {
+ civicrm_api3('Participant', 'create', ['id' => $participantPayment['participant_id'], 'status_id' => 'Partially paid']);
+ }
}
elseif ($contributionStatus === 'Completed' && ((float) CRM_Core_BAO_FinancialTrxn::getTotalPayments($contribution['id'], TRUE) === 0.0)) {
// If the contribution has previously been completed (fully paid) and now has total payments adding up to 0
* available processors
*/
public static function getPaymentProcessors($capabilities = [], $ids = FALSE) {
- $testProcessors = in_array('TestMode', $capabilities) ? self::getAllPaymentProcessors('test') : [];
if (is_array($ids)) {
+ $testProcessors = in_array('TestMode', $capabilities) ? self::getAllPaymentProcessors('test') : [];
$processors = self::getAllPaymentProcessors('all', FALSE, FALSE);
if (in_array('TestMode', $capabilities)) {
$possibleLiveIDs = array_diff($ids, array_keys($testProcessors));
$domain = new CRM_Core_DAO_Domain();
$domain->find(TRUE);
if (!(CRM_Core_DAO::checkTriggerViewPermission(FALSE)) && $value) {
- throw new API_Exception("In order to use this functionality, the installation's database user must have privileges to create triggers (in MySQL 5.0 – and in MySQL 5.1 if binary logging is enabled – this means the SUPER privilege). This install either does not seem to have the required privilege enabled.");
+ throw new API_Exception(ts("In order to use this functionality, the installation's database user must have privileges to create triggers and views (if binary logging is enabled – this means the SUPER privilege). This install does not have the required privilege(s) enabled."));
}
return TRUE;
}
CRM_Activity_BAO_Activity::deleteActivity($params);
}
self::deleteMembershipPayment($membershipId, $preserveContrib);
+ CRM_Price_BAO_LineItem::deleteLineItems($membershipId, 'civicrm_membership');
$results = $membership->delete();
$transaction->commit();
self::processOverriddenUntilDateMembership($dao1);
}
- $query = $baseQuery . " AND (civicrm_membership.is_override = 0 OR civicrm_membership.is_override IS NULL)
+ $query = $baseQuery . " AND (civicrm_membership.is_override = 0 OR civicrm_membership.is_override IS NULL)
AND civicrm_membership.status_id NOT IN (%1, %2, %3, %4)
AND civicrm_membership.owner_membership_id IS NULL ";
$params = [
*/
protected $groupFilterNotOptimised = TRUE;
+ /**
+ * Store the joins for civicrm_activity_contact
+ *
+ * Activities are retrieved by a union of four queries in order to catch
+ * activities where the contact is the source, target, assignee, or case
+ * contact.
+ *
+ * @var array
+ */
+ protected $activityContactJoin = [];
+
/**
* Class constructor.
*/
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => [
'source_contact_id' => [
- 'title' => ts('Added By'),
+ 'title' => ts('Added by'),
'name' => 'contact_id',
'default' => TRUE,
],
$this->_selectedTables = array_diff($this->_selectedTables, $componentTables);
if (!empty($this->_selectComponent['contribution_civireport'])) {
- $this->_formComponent['contribution_civireport'] = " FROM
+ $this->_formComponent['contribution_civireport'] = <<<HERESQL
+ FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id
- ";
+HERESQL;
}
if (!empty($this->_selectComponent['membership_civireport'])) {
- $this->_formComponent['membership_civireport'] = " FROM
+ $this->_formComponent['membership_civireport'] = <<<HERESQL
+ FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_membership']}.contact_id
- ";
+HERESQL;
}
if (!empty($this->_selectComponent['participant_civireport'])) {
- $this->_formComponent['participant_civireport'] = " FROM
+ $this->_formComponent['participant_civireport'] = <<<HERESQL
+ FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_participant {$this->_aliases['civicrm_participant']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_participant']}.contact_id
- ";
+HERESQL;
}
if (!empty($this->_selectComponent['activity_civireport'])) {
+
+ // First, prepare all the joins to filter activities by contact
$activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
- $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
- $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
- $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
- $this->_formComponent['activity_civireport'] = "FROM
+ $aliasMap = [
+ 'Activity Assignees' => 'civicrm_activity_assignment',
+ 'Activity Targets' => 'civicrm_activity_target',
+ 'Activity Source' => 'civicrm_activity_source',
+ ];
+
+ $this->activityContactJoin['case'] = <<<HERESQL
+ JOIN civicrm_case_activity
+ ON civicrm_case_activity.activity_id = activity_civireport.id
+ JOIN civicrm_case
+ ON civicrm_case_activity.case_id = civicrm_case.id
+ JOIN civicrm_case_contact
+ ON civicrm_case_contact.case_id = civicrm_case.id
+ AND civicrm_case_contact.contact_id IN ([FILTERCONTACTSHERE])
+HERESQL;
+
+ // Collect the joins for civicrm_contact to each of the activity contact joins
+ $contactJoins = [];
+
+ foreach ($activityContacts as $recordTypeId => $label) {
+ if (empty($aliasMap[$label])) {
+ continue;
+ }
+
+ // Inner join on this record type
+ $this->activityContactJoin[$recordTypeId] = <<<HERESQL
+ JOIN civicrm_activity_contact {$aliasMap[$label]}
+ ON activity_civireport.id = {$aliasMap[$label]}.activity_id
+ AND {$aliasMap[$label]}.record_type_id = $recordTypeId
+ AND {$aliasMap[$label]}.contact_id IN ([FILTERCONTACTSHERE])
+HERESQL;
+
+ // Cycle through other record types to add left joins
+ foreach ($activityContacts as $recordTypeIdX => $labelX) {
+ if ($recordTypeIdX == $recordTypeId || empty($aliasMap[$labelX])) {
+ continue;
+ }
+ $this->activityContactJoin[$recordTypeId] .= <<<HERESQL
+ LEFT JOIN civicrm_activity_contact {$aliasMap[$labelX]}
+ ON activity_civireport.id = {$aliasMap[$labelX]}.activity_id
+ AND {$aliasMap[$labelX]}.record_type_id = $recordTypeIdX
+HERESQL;
+ }
+
+ // Add to the joins for case activities
+ $this->activityContactJoin['case'] .= <<<HERESQL
+ LEFT JOIN civicrm_activity_contact {$aliasMap[$label]}
+ ON activity_civireport.id = {$aliasMap[$label]}.activity_id
+ AND {$aliasMap[$label]}.record_type_id = $recordTypeId
+HERESQL;
+
+ // Each activity_contact join gets joined to civicrm_contact
+ $contactJoins[] = <<<HERESQL
+ LEFT JOIN civicrm_contact {$this->_aliases[$aliasMap[$label]]}
+ ON $aliasMap[$label].contact_id = {$this->_aliases[$aliasMap[$label]]}.id
+HERESQL;
+ }
+
+ // civicrm_contact joins into a single string
+ $contactJoins = implode(PHP_EOL, $contactJoins);
+
+ // Now filter out component activities that should be suppressed
+ $compInfo = CRM_Core_Component::getEnabledComponents();
+ $componentsList = [];
+ foreach ($compInfo as $compObj) {
+ if ($compObj->info['showActivitiesInCore']) {
+ $componentsList[] = $compObj->componentID;
+ }
+ }
+ $componentClause = "civicrm_option_value.component_id IS NULL";
+ if (!empty($componentsList)) {
+ $componentsIn = implode(', ', $componentsList);
+ $componentClause = <<<HERESQL
+ ( $componentClause
+ OR civicrm_option_value.component_id IN ($componentsIn) )
+HERESQL;
+ }
+
+ $this->_formComponent['activity_civireport'] = <<<HERESQL
+ FROM
civicrm_activity {$this->_aliases['civicrm_activity']}
- LEFT JOIN civicrm_activity_contact civicrm_activity_target
- ON {$this->_aliases['civicrm_activity']}.id = civicrm_activity_target.activity_id
- AND civicrm_activity_target.record_type_id = {$targetID}
- LEFT JOIN civicrm_activity_contact civicrm_activity_assignment
- ON {$this->_aliases['civicrm_activity']}.id = civicrm_activity_assignment.activity_id
- AND civicrm_activity_assignment.record_type_id = {$assigneeID}
- LEFT JOIN civicrm_activity_contact civicrm_activity_source
- ON {$this->_aliases['civicrm_activity']}.id = civicrm_activity_source.activity_id
- AND civicrm_activity_source.record_type_id = {$sourceID}
- LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_target']}
- ON civicrm_activity_target.contact_id = {$this->_aliases['civicrm_activity_target']}.id
- LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_assignment']}
- ON civicrm_activity_assignment.contact_id = {$this->_aliases['civicrm_activity_assignment']}.id
- LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_source']}
- ON civicrm_activity_source.contact_id = {$this->_aliases['civicrm_activity_source']}.id
- LEFT JOIN civicrm_option_value
- ON ( {$this->_aliases['civicrm_activity']}.activity_type_id = civicrm_option_value.value )
- LEFT JOIN civicrm_option_group
+ [ACTIVITYCONTACTJOINSHERE]
+ $contactJoins
+ JOIN civicrm_option_value
+ ON {$this->_aliases['civicrm_activity']}.activity_type_id = civicrm_option_value.value
+ AND $componentClause
+ JOIN civicrm_option_group
ON civicrm_option_group.id = civicrm_option_value.option_group_id
- LEFT JOIN civicrm_case_activity
- ON civicrm_case_activity.activity_id = {$this->_aliases['civicrm_activity']}.id
- LEFT JOIN civicrm_case
- ON civicrm_case_activity.case_id = civicrm_case.id
- LEFT JOIN civicrm_case_contact
- ON civicrm_case_contact.case_id = civicrm_case.id
- ";
+ AND civicrm_option_group.name = 'activity_type'
+HERESQL;
}
if (!empty($this->_selectComponent['relationship_civireport'])) {
- $this->_formComponent['relationship_civireport'] = "FROM
+ $this->_formComponent['relationship_civireport'] = <<<HERESQL
+ FROM
civicrm_relationship {$this->_aliases['civicrm_relationship']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_relationship']}.contact_id_b
LEFT JOIN civicrm_contact contact_a
ON contact_a.id = {$this->_aliases['civicrm_relationship']}.contact_id_a
- ";
+HERESQL;
}
}
if (!empty($this->_selectComponent[$val]) &&
($val != 'activity_civireport' && $val != 'relationship_civireport')
) {
- $sql = "{$this->_selectComponent[$val]} {$this->_formComponent[$val]}
- WHERE {$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
- ";
+ $sql = <<<HERESQL
+ {$this->_selectComponent[$val]} {$this->_formComponent[$val]}
+ WHERE {$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
+HERESQL;
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
$val = 'relationship_civireport';
$eligibleResult[$val] = $val;
- $sql = "{$this->_selectComponent[$val]},{$this->_aliases['civicrm_contact']}.display_name as contact_b_name, contact_a.id as contact_a_id , contact_a.display_name as contact_a_name {$this->_formComponent[$val]}
- WHERE ({$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
- OR
- contact_a.id IN ( $selectedContacts ) ) AND
- {$this->_aliases['civicrm_relationship']}.is_active = 1 AND
- contact_a.is_deleted = 0 AND
- {$this->_aliases['civicrm_contact']}.is_deleted = 0
- ";
+ $sql = <<<HERESQL
+ {$this->_selectComponent[$val]},{$this->_aliases['civicrm_contact']}.display_name as contact_b_name, contact_a.id as contact_a_id, contact_a.display_name as contact_a_name
+ {$this->_formComponent[$val]}
+ WHERE ({$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
+ OR contact_a.id IN ( $selectedContacts ) )
+ AND {$this->_aliases['civicrm_relationship']}.is_active = 1
+ AND contact_a.is_deleted = 0
+ AND {$this->_aliases['civicrm_contact']}.is_deleted = 0
+HERESQL;
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
}
if (!empty($this->_selectComponent['activity_civireport'])) {
-
- $componentClause = "civicrm_option_value.component_id IS NULL";
- $componentsIn = NULL;
- $compInfo = CRM_Core_Component::getEnabledComponents();
- foreach ($compInfo as $compObj) {
- if ($compObj->info['showActivitiesInCore']) {
- $componentsIn = $componentsIn ? ($componentsIn . ', ' .
- $compObj->componentID) : $compObj->componentID;
- }
- }
- if ($componentsIn) {
- $componentClause = "( $componentClause OR
- civicrm_option_value.component_id IN ($componentsIn) )";
- }
-
$val = 'activity_civireport';
$eligibleResult[$val] = $val;
- $sql = "{$this->_selectComponent[$val]} ,
- {$this->_aliases['civicrm_activity_source']}.display_name as added_by {$this->_formComponent[$val]}
-
- WHERE ( civicrm_activity_source.contact_id IN ($selectedContacts) OR
- civicrm_activity_target.contact_id IN ($selectedContacts) OR
- civicrm_activity_assignment.contact_id IN ($selectedContacts) OR
- civicrm_case_contact.contact_id IN ($selectedContacts) ) AND
- civicrm_option_group.name = 'activity_type' AND
- {$this->_aliases['civicrm_activity']}.is_test = 0 AND
- ($componentClause)
- ORDER BY {$this->_aliases['civicrm_activity']}.activity_date_time desc ";
+ // The activities we want to show are those where the contact is the
+ // target, assignee, source, or the client on a case. Since the vast
+ // majority of activities will not involve the client, it's impractical to
+ // retrieve all activities and use OR clauses in the WHERE. Instead, we
+ // use a union of subqueries for each of the four ways activities might
+ // join to the contact.
+ $unionParts = [];
+ foreach ($this->activityContactJoin as $activityContactJoinClauses) {
+ $fromClauses = str_replace(
+ '[ACTIVITYCONTACTJOINSHERE]',
+ str_replace('[FILTERCONTACTSHERE]', $selectedContacts, $activityContactJoinClauses),
+ $this->_formComponent[$val]
+ );
+ $unionParts[] = <<<HERESQL
+ (
+ {$this->_selectComponent[$val]},
+ {$this->_aliases['civicrm_activity_source']}.display_name as added_by,
+ {$this->_aliases['civicrm_activity']}.activity_date_time as date_time_for_sort
+ $fromClauses
+
+ WHERE {$this->_aliases['civicrm_activity']}.is_test = 0
+ )
+HERESQL;
+ }
+
+ $sql = implode(' UNION ', $unionParts) . ' ORDER BY date_time_for_sort DESC';
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
foreach ($this->_columnHeadersComponent[$val] as $key => $value) {
'description' => [
'title' => ts('Description'),
],
+ 'is_active' => [
+ 'title' => ts('Is active?'),
+ ],
'relationship_id' => [
'title' => ts('Rel ID'),
'name' => 'id',
'title' => ts('Start Date'),
'name' => 'start_date',
],
+ 'end_date' => [
+ 'title' => ts('End Date'),
+ 'name' => 'end_date',
+ ],
],
'grouping' => 'relation-fields',
],
$entryFound = TRUE;
}
+ $rows[$rowNum]['civicrm_relationship_is_active'] = $row['civicrm_relationship_is_active'] ? ts('Yes') : '';
+
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
*/
class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form {
- protected $_charts = array(
+ protected $_charts = [
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
- );
- protected $_customGroupExtends = array('Contribution', 'Contact', 'Individual');
+ ];
+ protected $_customGroupExtends = ['Contribution', 'Contact', 'Individual'];
protected $_customGroupGroupBy = TRUE;
- public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
+ public $_drilldownReport = ['contribute/detail' => 'Link to Detail Report'];
/**
* To what frequency group-by a date column
*
* @var array
*/
- protected $_groupByDateFreq = array(
+ protected $_groupByDateFreq = [
'MONTH' => 'Month',
'YEARWEEK' => 'Week',
'DATE' => 'Day',
'QUARTER' => 'Quarter',
'YEAR' => 'Year',
'FISCALYEAR' => 'Fiscal Year',
- );
+ ];
/**
* This report has been optimised for group filtering.
* Class constructor.
*/
public function __construct() {
- $this->_columns = array(
- 'civicrm_contact' => array(
+ $this->_columns = [
+ 'civicrm_contact' => [
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array_merge(
$this->getBasicContactFields(),
- array(
- 'sort_name' => array(
+ [
+ 'sort_name' => [
'title' => ts('Contact Name'),
'no_repeat' => TRUE,
- ),
- )
+ ],
+ ]
),
- 'filters' => $this->getBasicContactFilters(array('deceased' => NULL)),
+ 'filters' => $this->getBasicContactFilters(['deceased' => NULL]),
'grouping' => 'contact-fields',
- 'group_bys' => array(
- 'id' => array('title' => ts('Contact ID')),
- 'sort_name' => array(
+ 'group_bys' => [
+ 'id' => ['title' => ts('Contact ID')],
+ 'sort_name' => [
'title' => ts('Contact Name'),
- ),
- ),
- ),
- 'civicrm_email' => array(
+ ],
+ ],
+ ],
+ 'civicrm_email' => [
'dao' => 'CRM_Core_DAO_Email',
- 'fields' => array(
- 'email' => array(
+ 'fields' => [
+ 'email' => [
'title' => ts('Email'),
'no_repeat' => TRUE,
- ),
- ),
+ ],
+ ],
'grouping' => 'contact-fields',
- ),
- 'civicrm_line_item' => array(
+ ],
+ 'civicrm_line_item' => [
'dao' => 'CRM_Price_DAO_LineItem',
- ),
- 'civicrm_phone' => array(
+ ],
+ 'civicrm_phone' => [
'dao' => 'CRM_Core_DAO_Phone',
- 'fields' => array(
- 'phone' => array(
+ 'fields' => [
+ 'phone' => [
'title' => ts('Phone'),
'no_repeat' => TRUE,
- ),
- ),
+ ],
+ ],
'grouping' => 'contact-fields',
- ),
- 'civicrm_financial_type' => array(
+ ],
+ 'civicrm_financial_type' => [
'dao' => 'CRM_Financial_DAO_FinancialType',
- 'fields' => array('financial_type' => NULL),
+ 'fields' => ['financial_type' => NULL],
'grouping' => 'contri-fields',
- 'group_bys' => array(
- 'financial_type' => array('title' => ts('Financial Type')),
- ),
- ),
- 'civicrm_contribution' => array(
+ 'group_bys' => [
+ 'financial_type' => ['title' => ts('Financial Type')],
+ ],
+ ],
+ 'civicrm_contribution' => [
'dao' => 'CRM_Contribute_DAO_Contribution',
//'bao' => 'CRM_Contribute_BAO_Contribution',
- 'fields' => array(
- 'contribution_status_id' => array(
+ 'fields' => [
+ 'contribution_status_id' => [
'title' => ts('Contribution Status'),
- ),
- 'contribution_source' => array('title' => ts('Source')),
- 'currency' => array(
+ ],
+ 'contribution_source' => ['title' => ts('Source')],
+ 'currency' => [
'required' => TRUE,
'no_display' => TRUE,
- ),
- 'contribution_page_id' => array(
+ ],
+ 'contribution_page_id' => [
'title' => ts('Contribution Page'),
- ),
- 'total_amount' => array(
+ ],
+ 'total_amount' => [
'title' => ts('Contribution Amount Stats'),
'default' => TRUE,
- 'statistics' => array(
+ 'statistics' => [
'count' => ts('Contributions'),
'sum' => ts('Contribution Aggregate'),
'avg' => ts('Contribution Avg'),
- ),
- ),
- 'non_deductible_amount' => array(
+ ],
+ ],
+ 'non_deductible_amount' => [
'title' => ts('Non-deductible Amount'),
- ),
- ),
+ ],
+ ],
'grouping' => 'contri-fields',
- 'filters' => array(
- 'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
- 'thankyou_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
- 'contribution_status_id' => array(
+ 'filters' => [
+ 'receive_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
+ 'thankyou_date' => ['operatorType' => CRM_Report_Form::OP_DATE],
+ 'contribution_status_id' => [
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'search'),
- 'default' => array(1),
+ 'default' => [1],
'type' => CRM_Utils_Type::T_INT,
- ),
- 'contribution_page_id' => array(
+ ],
+ 'contribution_page_id' => [
'title' => ts('Contribution Page'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionPage(),
'type' => CRM_Utils_Type::T_INT,
- ),
- 'currency' => array(
+ ],
+ 'currency' => [
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
- ),
- 'financial_type_id' => array(
+ ],
+ 'financial_type_id' => [
'title' => ts('Financial Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
'type' => CRM_Utils_Type::T_INT,
- ),
- 'contribution_page_id' => array(
+ ],
+ 'contribution_page_id' => [
'title' => ts('Contribution Page'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionPage(),
'type' => CRM_Utils_Type::T_INT,
- ),
- 'total_amount' => array(
+ ],
+ 'total_amount' => [
'title' => ts('Contribution Amount'),
- ),
- 'non_deductible_amount' => array(
+ ],
+ 'non_deductible_amount' => [
'title' => ts('Non-deductible Amount'),
- ),
- 'total_sum' => array(
+ ],
+ 'total_sum' => [
'title' => ts('Contribution Aggregate'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_total_amount_sum',
'having' => TRUE,
- ),
- 'total_count' => array(
+ ],
+ 'total_count' => [
'title' => ts('Contribution Count'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_total_amount_count',
'having' => TRUE,
- ),
- 'total_avg' => array(
+ ],
+ 'total_avg' => [
'title' => ts('Contribution Avg'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_total_amount_avg',
'having' => TRUE,
- ),
- ),
- 'group_bys' => array(
- 'receive_date' => array(
+ ],
+ ],
+ 'group_bys' => [
+ 'receive_date' => [
'frequency' => TRUE,
'default' => TRUE,
'chart' => TRUE,
- ),
+ ],
'contribution_source' => NULL,
- 'contribution_status_id' => array(
+ 'contribution_status_id' => [
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'search'),
- 'default' => array(1),
+ 'default' => [1],
'type' => CRM_Utils_Type::T_INT,
- ),
- 'contribution_page_id' => array(
+ ],
+ 'contribution_page_id' => [
'title' => ts('Contribution Page'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionPage(),
'type' => CRM_Utils_Type::T_INT,
- ),
- ),
- ),
- 'civicrm_financial_trxn' => array(
+ ],
+ ],
+ ],
+ 'civicrm_financial_trxn' => [
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
- 'fields' => array(
- 'card_type_id' => array(
+ 'fields' => [
+ 'card_type_id' => [
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
- ),
- ),
- 'filters' => array(
- 'card_type_id' => array(
+ ],
+ ],
+ 'filters' => [
+ 'card_type_id' => [
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
- ),
- ),
- ),
- 'civicrm_batch' => array(
+ ],
+ ],
+ ],
+ 'civicrm_batch' => [
'dao' => 'CRM_Batch_DAO_EntityBatch',
'grouping' => 'contri-fields',
- 'fields' => array(
- 'batch_id' => array(
+ 'fields' => [
+ 'batch_id' => [
'name' => 'batch_id',
'title' => ts('Batch Title'),
'dbAlias' => 'GROUP_CONCAT(DISTINCT batch_civireport.batch_id
ORDER BY batch_civireport.batch_id SEPARATOR ",")',
- ),
- ),
- 'filters' => array(
- 'batch_id' => array(
+ ],
+ ],
+ 'filters' => [
+ 'batch_id' => [
'title' => ts('Batch Title'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Batch_BAO_Batch::getBatches(),
'type' => CRM_Utils_Type::T_INT,
- ),
- ),
- 'group_bys' => array(
- 'batch_id' => array('title' => ts('Batch Title')),
- ),
- ),
- 'civicrm_contribution_soft' => array(
+ ],
+ ],
+ 'group_bys' => [
+ 'batch_id' => ['title' => ts('Batch Title')],
+ ],
+ ],
+ 'civicrm_contribution_soft' => [
'dao' => 'CRM_Contribute_DAO_ContributionSoft',
- 'fields' => array(
- 'soft_amount' => array(
+ 'fields' => [
+ 'soft_amount' => [
'title' => ts('Soft Credit Amount Stats'),
'name' => 'amount',
- 'statistics' => array(
+ 'statistics' => [
'count' => ts('Soft Credits'),
'sum' => ts('Soft Credit Aggregate'),
'avg' => ts('Soft Credit Avg'),
- ),
- ),
- ),
+ ],
+ ],
+ ],
'grouping' => 'contri-fields',
- 'filters' => array(
- 'amount' => array(
+ 'filters' => [
+ 'amount' => [
'title' => ts('Soft Credit Amount'),
- ),
- 'soft_credit_type_id' => array(
+ ],
+ 'soft_credit_type_id' => [
'title' => ts('Soft Credit Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('soft_credit_type'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
- ),
- 'soft_sum' => array(
+ ],
+ 'soft_sum' => [
'title' => ts('Soft Credit Aggregate'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_soft_soft_amount_sum',
'having' => TRUE,
- ),
- 'soft_count' => array(
+ ],
+ 'soft_count' => [
'title' => ts('Soft Credits Count'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_soft_soft_amount_count',
'having' => TRUE,
- ),
- 'soft_avg' => array(
+ ],
+ 'soft_avg' => [
'title' => ts('Soft Credit Avg'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_soft_soft_amount_avg',
'having' => TRUE,
- ),
- ),
- ),
- ) + $this->addAddressFields();
+ ],
+ ],
+ ],
+ ] + $this->addAddressFields();
$this->addCampaignFields('civicrm_contribution', TRUE);
* Set select clause.
*/
public function select() {
- $select = array();
- $this->_columnHeaders = array();
+ $select = [];
+ $this->_columnHeaders = [];
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
// just to make sure these values are transferred to rows.
// since we need that for calculation purpose,
// e.g making subtotals look nicer or graphs
- $this->_columnHeaders["{$tableName}_{$fieldName}_interval"] = array('no_display' => TRUE);
- $this->_columnHeaders["{$tableName}_{$fieldName}_subtotal"] = array('no_display' => TRUE);
+ $this->_columnHeaders["{$tableName}_{$fieldName}_interval"] = ['no_display' => TRUE];
+ $this->_columnHeaders["{$tableName}_{$fieldName}_subtotal"] = ['no_display' => TRUE];
}
}
}
public static function formRule($fields, $files, $self) {
// Check for searching combination of display columns and
// grouping criteria
- $ignoreFields = array('total_amount', 'sort_name');
+ $ignoreFields = ['total_amount', 'sort_name'];
$errors = $self->customDataFormRule($fields, $ignoreFields);
if (empty($fields['fields']['total_amount'])) {
- foreach (array(
+ foreach ([
'total_count_value',
'total_sum_value',
'total_avg_value',
- ) as $val) {
+ ] as $val) {
if (!empty($fields[$val])) {
$errors[$val] = ts("Please select the Amount Statistics");
}
*/
public function groupBy() {
$this->_groupBy = "";
- $groupByColumns = array();
+ $groupByColumns = [];
$append = FALSE;
if (!empty($this->_params['group_bys']) &&
is_array($this->_params['group_bys'])
$append = "YEAR({$field['dbAlias']});;";
if (in_array(strtolower($this->_params['group_bys_freq'][$fieldName]),
- array('year')
+ ['year']
)) {
$append = '';
}
) {
$this->_rollup = " WITH ROLLUP";
}
- $groupBy = array();
+ $groupBy = [];
foreach ($groupByColumns as $key => $val) {
if (strpos($val, ';;') !== FALSE) {
$groupBy = array_merge($groupBy, explode(';;', $val));
$softCredit = CRM_Utils_Array::value('soft_amount', $this->_params['fields']);
$onlySoftCredit = $softCredit && !CRM_Utils_Array::value('total_amount', $this->_params['fields']);
- $group = "\nGROUP BY {$this->_aliases['civicrm_contribution']}.currency";
+ if (empty($this->_groupBy)) {
+ $group = "\nGROUP BY {$this->_aliases['civicrm_contribution']}.currency";
+ }
+ else {
+ $group = "\n {$this->_groupBy}, {$this->_aliases['civicrm_contribution']}.currency";
+ }
$this->from('contribution');
if ($softCredit) {
$contriSQL = "SELECT {$contriQuery} {$group} {$this->_having}";
$contriDAO = CRM_Core_DAO::executeQuery($contriSQL);
$this->addToDeveloperTab($contriSQL);
- $totalAmount = $average = $mode = $median = $softTotalAmount = $softAverage = array();
- $count = $softCount = 0;
+ $currencies = $currAmount = $currAverage = $currCount = [];
+ $totalAmount = $average = $mode = $median = [];
+ $softTotalAmount = $softAverage = $averageCount = $averageSoftCount = [];
+ $softCount = $count = 0;
while ($contriDAO->fetch()) {
- $totalAmount[]
- = CRM_Utils_Money::format($contriDAO->civicrm_contribution_total_amount_sum, $contriDAO->currency) .
- " (" . $contriDAO->civicrm_contribution_total_amount_count . ")";
- $average[] = CRM_Utils_Money::format($contriDAO->civicrm_contribution_total_amount_avg, $contriDAO->currency);
+ if (!isset($currAmount[$contriDAO->currency])) {
+ $currAmount[$contriDAO->currency] = 0;
+ }
+ if (!isset($currCount[$contriDAO->currency])) {
+ $currCount[$contriDAO->currency] = 0;
+ }
+ if (!isset($currAverage[$contriDAO->currency])) {
+ $currAverage[$contriDAO->currency] = 0;
+ }
+ if (!isset($averageCount[$contriDAO->currency])) {
+ $averageCount[$contriDAO->currency] = 0;
+ }
+ $currAmount[$contriDAO->currency] += $contriDAO->civicrm_contribution_total_amount_sum;
+ $currCount[$contriDAO->currency] += $contriDAO->civicrm_contribution_total_amount_count;
+ $currAverage[$contriDAO->currency] += $contriDAO->civicrm_contribution_total_amount_avg;
+ $averageCount[$contriDAO->currency]++;
$count += $contriDAO->civicrm_contribution_total_amount_count;
+
+ if (!in_array($contriDAO->currency, $currencies)) {
+ $currencies[] = $contriDAO->currency;
+ }
+ }
+
+ foreach ($currencies as $currency) {
+ $totalAmount[] = CRM_Utils_Money::format($currAmount[$currency], $currency) .
+ " (" . $currCount[$currency] . ")";
+ $average[] = CRM_Utils_Money::format(($currAverage[$currency] / $averageCount[$currency]), $currency);
}
$groupBy = "\n{$group}, {$this->_aliases['civicrm_contribution']}.total_amount";
$mode = $this->calculateMode($modeSQL);
$median = $this->calculateMedian();
+ $currencies = $currSoftAmount = $currSoftAverage = $currSoftCount = [];
if ($softCredit) {
$softDAO = CRM_Core_DAO::executeQuery($softSQL);
$this->addToDeveloperTab($softSQL);
while ($softDAO->fetch()) {
- $softTotalAmount[]
- = CRM_Utils_Money::format($softDAO->civicrm_contribution_soft_soft_amount_sum, $softDAO->currency) .
- " (" . $softDAO->civicrm_contribution_soft_soft_amount_count . ")";
- $softAverage[] = CRM_Utils_Money::format($softDAO->civicrm_contribution_soft_soft_amount_avg, $softDAO->currency);
+ if (!isset($currSoftAmount[$softDAO->currency])) {
+ $currSoftAmount[$softDAO->currency] = 0;
+ }
+ if (!isset($currSoftCount[$softDAO->currency])) {
+ $currSoftCount[$softDAO->currency] = 0;
+ }
+ if (!isset($currSoftAverage[$softDAO->currency])) {
+ $currSoftAverage[$softDAO->currency] = 0;
+ }
+ if (!isset($averageSoftCount[$softDAO->currency])) {
+ $averageSoftCount[$softDAO->currency] = 0;
+ }
+ $currSoftAmount[$softDAO->currency] += $softDAO->civicrm_contribution_soft_soft_amount_sum;
+ $currSoftCount[$softDAO->currency] += $softDAO->civicrm_contribution_soft_soft_amount_count;
+ $currSoftAverage[$softDAO->currency] += $softDAO->civicrm_contribution_soft_soft_amount_avg;
+ $averageSoftCount[$softDAO->currency]++;
$softCount += $softDAO->civicrm_contribution_soft_soft_amount_count;
+
+ if (!in_array($softDAO->currency, $currencies)) {
+ $currencies[] = $softDAO->currency;
+ }
+ }
+
+ foreach ($currencies as $currency) {
+ $softTotalAmount[] = CRM_Utils_Money::format($currSoftAmount[$currency], $currency) .
+ " (" . $currSoftCount[$currency] . ")";
+ $softAverage[] = CRM_Utils_Money::format(($currSoftAverage[$currency] / $averageSoftCount[$currency]), $currency);
}
}
if (!$onlySoftCredit) {
- $statistics['counts']['amount'] = array(
+ $statistics['counts']['amount'] = [
'title' => ts('Total Amount'),
'value' => implode(', ', $totalAmount),
'type' => CRM_Utils_Type::T_STRING,
- );
- $statistics['counts']['count'] = array(
+ ];
+ $statistics['counts']['count'] = [
'title' => ts('Total Contributions'),
'value' => $count,
- );
- $statistics['counts']['avg'] = array(
+ ];
+ $statistics['counts']['avg'] = [
'title' => ts('Average'),
'value' => implode(', ', $average),
'type' => CRM_Utils_Type::T_STRING,
- );
- $statistics['counts']['mode'] = array(
+ ];
+ $statistics['counts']['mode'] = [
'title' => ts('Mode'),
'value' => implode(', ', $mode),
'type' => CRM_Utils_Type::T_STRING,
- );
- $statistics['counts']['median'] = array(
+ ];
+ $statistics['counts']['median'] = [
'title' => ts('Median'),
'value' => implode(', ', $median),
'type' => CRM_Utils_Type::T_STRING,
- );
+ ];
}
if ($softCredit) {
- $statistics['counts']['soft_amount'] = array(
+ $statistics['counts']['soft_amount'] = [
'title' => ts('Total Soft Credit Amount'),
'value' => implode(', ', $softTotalAmount),
'type' => CRM_Utils_Type::T_STRING,
- );
- $statistics['counts']['soft_count'] = array(
+ ];
+ $statistics['counts']['soft_count'] = [
'title' => ts('Total Soft Credits'),
'value' => $softCount,
- );
- $statistics['counts']['soft_avg'] = array(
+ ];
+ $statistics['counts']['soft_avg'] = [
'title' => ts('Average Soft Credit'),
'value' => implode(', ', $softAverage),
'type' => CRM_Utils_Type::T_STRING,
- );
+ ];
}
return $statistics;
}
* @param array $rows
*/
public function buildChart(&$rows) {
- $graphRows = array();
+ $graphRows = [];
if (!empty($this->_params['charts'])) {
if (!empty($this->_params['group_bys']['receive_date'])) {
// build the chart.
$config = CRM_Core_Config::Singleton();
$graphRows['xname'] = $this->_interval;
- $graphRows['yname'] = ts('Amount (%1)', array(1 => $config->defaultCurrency));
+ $graphRows['yname'] = ts('Amount (%1)', [1 => $config->defaultCurrency]);
CRM_Utils_Chart::chart($graphRows, $this->_params['charts'], $this->_interval);
$this->assign('chartType', $this->_params['charts']);
}
$contriDAO = CRM_Core_DAO::executeQuery($contriSQL);
CRM_Core_DAO::reenableFullGroupByMode();
$this->addToDeveloperTab($contriSQL);
- $contriFields = array(
+ $contriFields = [
'civicrm_contribution_total_amount_sum',
'civicrm_contribution_total_amount_avg',
'civicrm_contribution_total_amount_count',
- );
+ ];
$count = 0;
while ($contriDAO->fetch()) {
foreach ($contriFields as $column) {
$dateStart = CRM_Utils_Date::customFormat($row['civicrm_contribution_receive_date_start'], '%Y%m%d');
$endDate = new DateTime($dateStart);
- $dateEnd = array();
+ $dateEnd = [];
list($dateEnd['Y'], $dateEnd['M'], $dateEnd['d']) = explode(':', $endDate->format('Y:m:d'));
if ($contactId = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$pcid = $contactId;
- $fAmt = $row['first_donation_first_donation_amount'];
- $fDate = $row['first_donation_first_donation_date'];
+ $fAmt = $row['first_donation_first_donation_amount'] ?? '';
+ $fDate = $row['first_donation_first_donation_date'] ?? '';
}
else {
if ($pcid == $contactId) {
$pcid = $contactId;
}
else {
- $fAmt = $row['first_donation_first_donation_amount'];
- $fDate = $row['first_donation_first_donation_date'];
+ $fAmt = $row['first_donation_first_donation_amount'] ?? '';
+ $fDate = $row['first_donation_first_donation_date'] ?? '';
$pcid = $contactId;
}
}
* @param string $title
* @param bool|int $action
* @param bool $modal
+ *
+ * @throws \CRM_Core_Exception
*/
public function __construct($title = NULL, $action = CRM_Core_Action::NONE, $modal = TRUE) {
parent::__construct($title, $modal, NULL, FALSE, TRUE);
- $mailingID = CRM_Utils_Request::retrieve('mid', 'String', $this, FALSE, NULL);
+ $mailingID = CRM_Utils_Request::retrieve('mid', 'String', $this);
// also get the text and html file
- $txtFile = CRM_Utils_Request::retrieve('txtFile', 'String',
- CRM_Core_DAO::$_nullObject, FALSE, NULL
- );
+ $txtFile = CRM_Utils_Request::retrieveValue('txtFile', 'String');
$config = CRM_Core_Config::singleton();
if ($txtFile &&
/**
* The recommended PHP version.
*/
- const RECOMMENDED_PHP_VER = '7.2';
+ const RECOMMENDED_PHP_VER = '7.3';
/**
* The previous recommended PHP version.
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Upgrade logic for FiveTwentyFour */
+class CRM_Upgrade_Incremental_php_FiveTwentyFour extends CRM_Upgrade_Incremental_Base {
+
+ /**
+ * Compute any messages which should be displayed beforeupgrade.
+ *
+ * Note: This function is called iteratively for each upcoming
+ * revision to the database.
+ *
+ * @param string $preUpgradeMessage
+ * @param string $rev
+ * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
+ * @param null $currentVer
+ */
+ public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
+ // Example: Generate a pre-upgrade message.
+ // if ($rev == '5.12.34') {
+ // $preUpgradeMessage .= '<p>' . ts('A new permission, "%1", has been added. This permission is now used to control access to the Manage Tags screen.', array(1 => ts('manage tags'))) . '</p>';
+ // }
+ }
+
+ /**
+ * Compute any messages which should be displayed after upgrade.
+ *
+ * @param string $postUpgradeMessage
+ * alterable.
+ * @param string $rev
+ * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
+ */
+ public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
+ // Example: Generate a post-upgrade message.
+ // if ($rev == '5.12.34') {
+ // $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
+ // }
+ }
+
+ /*
+ * Important! All upgrade functions MUST add a 'runSql' task.
+ * Uncomment and use the following template for a new upgrade version
+ * (change the x in the function name):
+ */
+
+ // /**
+ // * Upgrade function.
+ // *
+ // * @param string $rev
+ // */
+ // public function upgrade_5_0_x($rev) {
+ // $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+ // $this->addTask('Do the foo change', 'taskFoo', ...);
+ // // Additional tasks here...
+ // // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
+ // // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
+ // }
+
+ // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
+ // return TRUE;
+ // }
+
+}
--- /dev/null
+{* file to handle db changes in 5.24.alpha1 during upgrade *}
else {
$mailer = Mail::factory($driver, $params);
}
+
+ // Previously, CiviCRM bundled patches to change the behavior of 3 specific drivers. Use wrapper/filters to avoid patching.
+ $mailer = new CRM_Utils_Mail_FilteredPearMailer($driver, $params, $mailer);
+ if (in_array($driver, ['smtp', 'mail', 'sendmail'])) {
+ $mailer->addFilter('2000_log', ['CRM_Utils_Mail_Logger', 'filter']);
+ $mailer->addFilter('2100_validate', function ($mailer, &$recipients, &$headers, &$body) {
+ if (!is_array($headers)) {
+ return PEAR::raiseError('$headers must be an array');
+ }
+ });
+ }
CRM_Utils_Hook::alterMailer($mailer, $driver, $params);
return $mailer;
}
// * All other mailers require that all be recipients be listed in the $to array AND that
// the Bcc must not be present in $header as otherwise it will be shown to all recipients
// ref: https://pear.php.net/bugs/bug.php?id=8047, full thread and answer [2011-04-19 20:48 UTC]
- if (get_class($mailer) != "Mail_mail") {
+ // TODO: Refactor this quirk-handler as another filter in FilteredPearMailer. But that would merit review of impact on universe.
+ $driver = ($mailer instanceof CRM_Utils_Mail_FilteredPearMailer) ? $mailer->getDriver() : NULL;
+ $isPhpMail = (get_class($mailer) === "Mail_mail" || $driver === 'mail');
+ if (!$isPhpMail) {
// get emails from headers, since these are
// combination of name and email addresses.
if (!empty($headers['Cc'])) {
* @param $to
* @param $headers
* @param $message
+ * @deprecated
*/
public static function logger(&$to, &$headers, &$message) {
- if (is_array($to)) {
- $toString = implode(', ', $to);
- $fileName = $to[0];
- }
- else {
- $toString = $fileName = $to;
- }
- $content = "To: " . $toString . "\n";
- foreach ($headers as $key => $val) {
- $content .= "$key: $val\n";
- }
- $content .= "\n" . $message . "\n";
-
- if (is_numeric(CIVICRM_MAIL_LOG)) {
- $config = CRM_Core_Config::singleton();
- // create the directory if not there
- $dirName = $config->configAndLogDir . 'mail' . DIRECTORY_SEPARATOR;
- CRM_Utils_File::createDir($dirName);
- $fileName = md5(uniqid(CRM_Utils_String::munge($fileName))) . '.txt';
- file_put_contents($dirName . $fileName,
- $content
- );
- }
- else {
- file_put_contents(CIVICRM_MAIL_LOG, $content, FILE_APPEND);
- }
+ CRM_Utils_Mail_Logger::log($to, $headers, $message);
}
/**
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * The filtered-mailer is a utility to wrap an existing PEAR Mail class
+ * and apply extra filters. It is primarily intended for resolving
+ * quirks in the standard implementations.
+ *
+ * This wrapper acts a bit like a chameleon, passing-through properties
+ * from the underlying object. Consequently, internal properties are
+ * prefixed with `_` to avoid conflict.
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+class CRM_Utils_Mail_FilteredPearMailer extends Mail {
+
+ /**
+ * @var string
+ * Ex: 'smtp' or 'sendmail'
+ */
+ protected $_driver;
+
+ /**
+ * @var array
+ */
+ protected $_params;
+
+ /**
+ * @var Mail
+ */
+ protected $_delegate;
+
+ /**
+ * @var callable[]
+ */
+ protected $_filters = [];
+
+ /**
+ * CRM_Utils_Mail_FilteredPearMailer constructor.
+ * @param string $driver
+ * @param array $params
+ * @param Mail $mailer
+ */
+ public function __construct($driver, $params, $mailer) {
+ $this->_driver = $driver;
+ $this->_params = $params;
+ $this->_delegate = $mailer;
+ }
+
+ public function send($recipients, $headers, $body) {
+ $filterArgs = [$this, &$recipients, &$headers, &$body];
+ foreach ($this->_filters as $filter) {
+ $result = call_user_func_array($filter, $filterArgs);
+ if ($result !== NULL) {
+ return $result;
+ }
+ }
+
+ return $this->_delegate->send($recipients, $headers, $body);
+ }
+
+ /**
+ * @param string $id
+ * Unique ID for this filter. Filters are sorted by ID.
+ * Suggestion: '{nnnn}_{name}', where '{nnnn}' is a number.
+ * Filters are sorted and executed in order.
+ * @param callable $func
+ * function(FilteredPearMailer $mailer, mixed $recipients, array $headers, string $body).
+ * The return value should generally be null/void. However, if you wish to
+ * short-circuit execution of the filters, then return a concrete value.
+ * @return static
+ */
+ public function addFilter($id, $func) {
+ $this->_filters[$id] = $func;
+ ksort($this->_filters);
+ return $this;
+ }
+
+ /**
+ * @return string
+ * Ex: 'smtp', 'sendmail', 'mail'.
+ */
+ public function getDriver() {
+ return $this->_driver;
+ }
+
+ public function &__get($name) {
+ return $this->_delegate->{$name};
+ }
+
+ public function __set($name, $value) {
+ return $this->_delegate->{$name} = $value;
+ }
+
+ public function __isset($name) {
+ return isset($this->_delegate->{$name});
+ }
+
+ public function __unset($name) {
+ unset($this->_delegate->{$name});
+ }
+
+}
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * An attachment to PEAR Mail which logs emails to files based on
+ * the CIVICRM_MAIL_LOG configuration.
+ *
+ * (Produced by refactoring; specifically, extracting log-related functions
+ * from CRM_Utils_Mail.)
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+class CRM_Utils_Mail_Logger {
+
+ /**
+ * @param CRM_Utils_Mail_FilteredPearMailer $mailer
+ * @param mixed $recipients
+ * @param array $headers
+ * @param string $body
+ * @return mixed
+ * Normally returns null/void. But if the filter process is to be
+ * short-circuited, then returns a concrete value.
+ */
+ public static function filter($mailer, &$recipients, &$headers, &$body) {
+ if (defined('CIVICRM_MAIL_LOG')) {
+ static::log($recipients, $headers, $body);
+ if (!defined('CIVICRM_MAIL_LOG_AND_SEND') && !defined('CIVICRM_MAIL_LOG_AND SEND')) {
+ return TRUE;
+ }
+ }
+ }
+
+ /**
+ * @param $to
+ * @param $headers
+ * @param $message
+ */
+ public static function log(&$to, &$headers, &$message) {
+ if (is_array($to)) {
+ $toString = implode(', ', $to);
+ $fileName = $to[0];
+ }
+ else {
+ $toString = $fileName = $to;
+ }
+ $content = "To: " . $toString . "\n";
+ foreach ($headers as $key => $val) {
+ $content .= "$key: $val\n";
+ }
+ $content .= "\n" . $message . "\n";
+
+ if (is_numeric(CIVICRM_MAIL_LOG)) {
+ $config = CRM_Core_Config::singleton();
+ // create the directory if not there
+ $dirName = $config->configAndLogDir . 'mail' . DIRECTORY_SEPARATOR;
+ CRM_Utils_File::createDir($dirName);
+ $fileName = md5(uniqid(CRM_Utils_String::munge($fileName))) . '.txt';
+ file_put_contents($dirName . $fileName,
+ $content
+ );
+ }
+ else {
+ file_put_contents(CIVICRM_MAIL_LOG, $content, FILE_APPEND);
+ }
+ }
+
+}
/**
* Tests if two currency values are equal, taking into account the currency's
- * precision, so that if the difference between the two values is less than
- * one more order of magnitude for the precision, then the values are
- * considered as equal. So, if the currency has precision of 2 decimal
- * points, a difference of more than 0.001 will cause the values to be
- * considered as different. Anything less than 0.001 will be considered as
- * equal.
+ * precision, so that the two values are compared as integers after rounding.
*
* Eg.
*
- * 1.2312 == 1.2319 with a currency precision of 2 decimal points
- * 1.2310 != 1.2320 with a currency precision of 2 decimal points
- * 1.3000 != 1.2000 with a currency precision of 2 decimal points
+ * 1.231 == 1.232 with a currency precision of 2 decimal points
+ * 1.234 != 1.236 with a currency precision of 2 decimal points
+ * 1.300 != 1.200 with a currency precision of 2 decimal points
*
* @param $value1
* @param $value2
* @return bool
*/
public static function equals($value1, $value2, $currency) {
- $precision = 1 / pow(10, self::getCurrencyPrecision($currency) + 1);
- $difference = self::subtractCurrencies($value1, $value2, $currency);
+ $precision = pow(10, self::getCurrencyPrecision($currency));
- if (abs($difference) > $precision) {
- return FALSE;
- }
-
- return TRUE;
+ return (int) round($value1 * $precision) == (int) round($value2 * $precision);
}
/**
break;
}
- if (isset($value) &&
- (CRM_Utils_Type::validate($value, $type, $abort, $name) === NULL)
- ) {
- $value = NULL;
+ if (isset($value)) {
+ $value = CRM_Utils_Type::validate($value, $type, $abort, $name);
}
if (!isset($value) && $store) {
// This checks for both username uniqueness and validity.
$violations = iterator_to_array($user->validate());
// We only care about violations on the username field; discard the rest.
- $violations = array_filter($violations, function ($v) {
+ $violations = array_values(array_filter($violations, function ($v) {
return $v->getPropertyPath() == 'name';
- });
+ }));
if (count($violations) > 0) {
$errors['cms_name'] = (string) $violations[0]->getMessage();
}
}
// And if we are given an email address, let's check to see if it already exists.
- if (!empty($params[$emailName])) {
- $mail = $params[$emailName];
+ if (!empty($params['mail'])) {
+ $mail = $params['mail'];
$user = entity_create('user');
$user->setEmail($mail);
// This checks for both email uniqueness.
$violations = iterator_to_array($user->validate());
// We only care about violations on the email field; discard the rest.
- $violations = array_filter($violations, function ($v) {
+ $violations = array_values(array_filter($violations, function ($v) {
return $v->getPropertyPath() == 'mail';
- });
+ }));
if (count($violations) > 0) {
$errors[$emailName] = (string) $violations[0]->getMessage();
}
}
/**
- * @deprecated
* @param string $entity
- * Type of entities to deal with.
+ * Name of entity: e.g. Contact, Activity, Event
* @param string $action
- * Create, get, delete or some special action name.
+ * Name of action: e.g. create, get, delete
* @param array $params
* Array to be passed to API function.
- * @param mixed $extra
- * Unused/deprecated.
+ *
* @return array|int
+ * @throws \API_Exception
* @see runSafe
+ * @deprecated
*/
- public function run($entity, $action, $params, $extra = NULL) {
- return $this->runSafe($entity, $action, $params, $extra);
+ public function run($entity, $action, $params) {
+ return $this->runSafe($entity, $action, $params);
}
/**
* normal format.
*
* @param string $entity
- * Type of entities to deal with.
+ * Name of entity: e.g. Contact, Activity, Event
* @param string $action
- * Create, get, delete or some special action name.
+ * Name of action: e.g. create, get, delete
* @param array $params
* Array to be passed to API function.
- * @param mixed $extra
- * Unused/deprecated.
*
* @return array|int
* @throws \API_Exception
*/
- public function runSafe($entity, $action, $params, $extra = NULL) {
- $apiRequest = Request::create($entity, $action, $params, $extra);
-
+ public function runSafe($entity, $action, $params) {
+ $apiRequest = [];
try {
+ $apiRequest = Request::create($entity, $action, $params);
$apiResponse = $this->runRequest($apiRequest);
return $this->formatResult($apiRequest, $apiResponse);
}
catch (\Exception $e) {
- $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, NULL, $apiRequest, $this));
+ if ($apiRequest) {
+ $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, NULL, $apiRequest, $this));
+ }
if ($e instanceof \PEAR_Exception) {
$err = $this->formatPearException($e, $apiRequest);
* Create, get, delete or some special action name.
* @param array $params
* Array to be passed to function.
- * @param mixed $extra
- * Unused/deprecated.
*
* @return bool
* TRUE if authorization would succeed.
* @throws \Exception
*/
- public function runAuthorize($entity, $action, $params, $extra = NULL) {
+ public function runAuthorize($entity, $action, $params) {
$apiProvider = NULL;
- $apiRequest = Request::create($entity, $action, $params, $extra);
+ $apiRequest = Request::create($entity, $action, $params);
try {
$this->boot($apiRequest);
* API action name.
* @param array $params
* API parameters.
- * @param mixed $extra
- * Who knows? ...
*
- * @throws \API_Exception
- * @return array
- * the request descriptor; keys:
- * - version: int
- * - entity: string
- * - action: string
- * - params: array (string $key => mixed $value) [deprecated in v4]
- * - extra: unspecified
- * - fields: NULL|array (string $key => array $fieldSpec)
- * - options: \CRM_Utils_OptionBag derived from params [v4-only]
- * - data: \CRM_Utils_OptionBag derived from params [v4-only]
- * - chains: unspecified derived from params [v4-only]
+ * @throws \Civi\API\Exception\NotImplementedException
+ * @return \Civi\Api4\Generic\AbstractAction|array
*/
- public static function create($entity, $action, $params, $extra = NULL) {
- $version = \CRM_Utils_Array::value('version', $params);
- switch ($version) {
- default:
- $apiRequest = [];
- $apiRequest['id'] = self::$nextId++;
- $apiRequest['version'] = (int) $version;
- $apiRequest['params'] = $params;
- $apiRequest['extra'] = $extra;
- $apiRequest['fields'] = NULL;
- $apiRequest['entity'] = self::normalizeEntityName($entity, $apiRequest['version']);
- $apiRequest['action'] = self::normalizeActionName($action, $apiRequest['version']);
- return $apiRequest;
+ public static function create(string $entity, string $action, array $params) {
+ switch ($params['version'] ?? NULL) {
+ case 3:
+ return [
+ 'id' => self::$nextId++,
+ 'version' => 3,
+ 'params' => $params,
+ 'fields' => NULL,
+ 'entity' => self::normalizeEntityName($entity),
+ 'action' => self::normalizeActionName($action),
+ ];
case 4:
- $callable = ["Civi\\Api4\\$entity", $action];
- if (!is_callable($callable)) {
- throw new Exception\NotImplementedException("API ($entity, $action) does not exist (join the API team and implement it!)");
+ // For custom pseudo-entities
+ if (strpos($entity, 'Custom_') === 0) {
+ $apiRequest = \Civi\Api4\CustomValue::$action(substr($entity, 7));
+ }
+ else {
+ $callable = ["\\Civi\\Api4\\$entity", $action];
+ if (!is_callable($callable)) {
+ throw new \Civi\API\Exception\NotImplementedException("API ($entity, $action) does not exist (join the API team and implement it!)");
+ }
+ $apiRequest = call_user_func($callable);
}
- $apiCall = call_user_func($callable);
- $apiRequest['id'] = self::$nextId++;
- unset($params['version']);
foreach ($params as $name => $param) {
$setter = 'set' . ucfirst($name);
- $apiCall->$setter($param);
+ $apiRequest->$setter($param);
}
- return $apiCall;
- }
+ return $apiRequest;
+ default:
+ throw new \Civi\API\Exception\NotImplementedException("Unknown api version");
+ }
}
/**
* APIv1-v3 munges entity/action names, and accepts any mixture of case and underscores.
*
* @param string $entity
- * @param int $version
* @return string
*/
- public static function normalizeEntityName($entity, $version) {
+ public static function normalizeEntityName($entity) {
return \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity));
}
* @param $version
* @return string
*/
- public static function normalizeActionName($action, $version) {
+ public static function normalizeActionName($action) {
return strtolower(\CRM_Utils_String::munge($action));
}
foreach ($newparams as $entityparams) {
$subParams = array_merge($genericParams, $entityparams);
_civicrm_api_replace_variables($subParams, $result['values'][$idIndex], $separator);
- $result['values'][$idIndex][$field][] = $apiKernel->run($subEntity, $subaction, $subParams);
+ $result['values'][$idIndex][$field][] = $apiKernel->runSafe($subEntity, $subaction, $subParams);
if ($result['is_error'] === 1) {
throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
}
$subParams = array_merge($subParams, $newparams);
_civicrm_api_replace_variables($subParams, $result['values'][$idIndex], $separator);
- $result['values'][$idIndex][$field] = $apiKernel->run($subEntity, $subaction, $subParams);
+ $result['values'][$idIndex][$field] = $apiKernel->runSafe($subEntity, $subaction, $subParams);
if (!empty($result['is_error'])) {
throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
}
'id' => $entityId,
];
- $result = $self->kernel->run($entity, $self->getDelegatedAction($action), $params);
+ $result = $self->kernel->runSafe($entity, $self->getDelegatedAction($action), $params);
if ($result['is_error'] || empty($result['values'])) {
$exception = new \Civi\API\Exception\UnauthorizedException("Authorization failed on ($entity,$entityId)", [
'cause' => $result,
use Civi\API\Exception\NotImplementedException;
use Civi\Api4\Generic\BasicGetAction;
-use Civi\Api4\Utils\ActionUtil;
use Civi\Api4\Utils\ReflectionUtils;
/**
private function loadAction($actionName, $method = NULL) {
try {
if (!isset($this->_actions[$actionName]) && (!$this->_actionsToGet || in_array($actionName, $this->_actionsToGet))) {
- $action = ActionUtil::getAction($this->getEntityName(), $actionName);
+ $action = \Civi\API\Request::create($this->getEntityName(), $actionName, ['version' => 4]);
if (is_object($action)) {
$this->_actions[$actionName] = ['name' => $actionName];
if ($this->_isFieldSelected('description', 'comment', 'see')) {
namespace Civi\Api4\Generic;
use Civi\Api4\Utils\ReflectionUtils;
-use Civi\Api4\Utils\ActionUtil;
/**
* Base class for all api actions.
*/
public function entityFields() {
if (!$this->_entityFields) {
- $getFields = ActionUtil::getAction($this->getEntityName(), 'getFields');
+ $getFields = \Civi\API\Request::create($this->getEntityName(), 'getFields', [
+ 'version' => 4,
+ 'checkPermissions' => $this->checkPermissions,
+ 'action' => $this->getActionName(),
+ 'includeCustom' => FALSE,
+ ]);
$result = new Result();
- if (method_exists($this, 'getBaoName')) {
- $getFields->setIncludeCustom(FALSE);
- }
- $getFields
- ->setCheckPermissions($this->checkPermissions)
- ->setAction($this->getActionName())
- ->_run($result);
+ $getFields->_run($result);
$this->_entityFields = (array) $result->indexBy('name');
}
return $this->_entityFields;
namespace Civi\Api4\Generic;
use Civi\API\Exception\NotImplementedException;
-use Civi\Api4\Utils\ActionUtil;
/**
* Lists information about fields for the $ENTITY entity.
*/
public function _run(Result $result) {
try {
- $actionClass = ActionUtil::getAction($this->getEntityName(), $this->getAction());
+ $actionClass = \Civi\API\Request::create($this->getEntityName(), $this->getAction(), ['version' => 4]);
}
catch (NotImplementedException $e) {
}
return $this;
}
+ /**
+ * @param bool $includeCustom
+ * @return $this
+ */
+ public function setIncludeCustom(bool $includeCustom) {
+ // Be forgiving if the param doesn't exist and don't throw an exception
+ if (property_exists($this, 'includeCustom')) {
+ $this->includeCustom = $includeCustom;
+ }
+ return $this;
+ }
+
public function fields() {
return [
[
namespace Civi\Api4\Generic;
-use Civi\Api4\Utils\ActionUtil;
-
/**
* Replaces an existing set of $ENTITIES with a new one.
*
$idField = $this->getSelect()[0];
$toDelete = array_diff_key(array_column($items, NULL, $idField), array_flip(array_filter(\CRM_Utils_Array::collect($idField, $this->records))));
- $saveAction = ActionUtil::getAction($this->getEntityName(), 'save');
+ $saveAction = \Civi\API\Request::create($this->getEntityName(), 'save', ['version' => 4]);
$saveAction
->setCheckPermissions($this->getCheckPermissions())
->setReload($this->reload)
namespace Civi\Api4\Generic;
use Civi\API\Exception\NotImplementedException;
-use Civi\Api4\Utils\ActionUtil;
/**
* $ACTION one or more $ENTITIES.
}
if ($this->reload) {
/** @var BasicGetAction $get */
- $get = ActionUtil::getAction($this->getEntityName(), 'get');
+ $get = \Civi\API\Request::create($this->getEntityName(), 'get', ['version' => 4]);
$get
->setCheckPermissions($this->getCheckPermissions())
->addWhere($this->getIdField(), 'IN', (array) $result->column($this->getIdField()));
/**
* @inheritDoc
- * @method $this setIncludeCustom(bool $value)
* @method bool getIncludeCustom()
*/
class DAOGetFieldsAction extends BasicGetFieldsAction {
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019 |
+ | Copyright CiviCRM LLC (c) 2004-2020 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
/**
*
* @package CRM
- * @copyright CiviCRM LLC (c) 2004-2019
+ * @copyright CiviCRM LLC (c) 2004-2020
* $Id$
*
*/
+++ /dev/null
-<?php
-
-/*
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC. All rights reserved. |
- | |
- | This work is published under the GNU AGPLv3 license with some |
- | permitted exceptions and without any warranty. For full license |
- | and copyright information, see https://civicrm.org/licensing |
- +--------------------------------------------------------------------+
- */
-
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
-namespace Civi\Api4\Utils;
-
-class ActionUtil {
-
- /**
- * @param $entityName
- * @param $actionName
- * @return \Civi\Api4\Generic\AbstractAction
- * @throws \Civi\API\Exception\NotImplementedException
- */
- public static function getAction($entityName, $actionName) {
- // For custom pseudo-entities
- if (strpos($entityName, 'Custom_') === 0) {
- return \Civi\Api4\CustomValue::$actionName(substr($entityName, 7));
- }
- else {
- $callable = ["\\Civi\\Api4\\$entityName", $actionName];
- if (!is_callable($callable)) {
- throw new \Civi\API\Exception\NotImplementedException("API ($entityName, $actionName) does not exist (join the API team and implement it!)");
- }
- return call_user_func($callable);
- }
- }
-
-}
*/
public static function codeGen() {
if (!isset(self::$singletons['codeGen'])) {
- $civiRoot = dirname(__DIR__);
+ $civiRoot = str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__));
$codeGen = new \CRM_Core_CodeGen_Main("$civiRoot/CRM/Core/DAO", "$civiRoot/sql", $civiRoot, "$civiRoot/templates", NULL, "UnitTests", NULL, "$civiRoot/xml/schema/Schema.xml", NULL);
$codeGen->init();
self::$singletons['codeGen'] = $codeGen;
* For civicrm_contact_add api function call.
*
* @return int
- * id of Household created
- * @throws \CRM_Core_Exception
+ * id of contact created
*
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
private function _contactCreate($params) {
$result = civicrm_api3('contact', 'create', $params);
if (!empty($result['is_error']) || empty($result['id'])) {
throw new \CRM_Core_Exception('Could not create test contact, with message: ' . \CRM_Utils_Array::value('error_message', $result) . "\nBacktrace:" . \CRM_Utils_Array::value('trace', $result));
}
- return $result['id'];
+ return (int) $result['id'];
}
/**
<span>
<a class="action-item crm-hover-button" ng-href="#/caseType/{{caseType.id}}">{{ts('Edit')}}</a>
- <span class="btn-slide crm-hover-button" ng-show="!caseType.is_reserved || (!caseType.is_active || caseType.is_forked)">
+ <!-- The variables used in ng-show below can take on any of the values from the set {0, 1, "0", "1", undefined}, so use explicit ==1 or !=1 to cover all possibilities properly. -->
+ <span class="more-panel btn-slide crm-hover-button" ng-show="caseType.is_reserved!=1 || (caseType.is_active!=1 || caseType.is_forked==1)">
{{ts('more')}}
<ul class="panel" style="display: none;">
- <li ng-hide="caseType.is_active">
+ <li class="panel-item-enable" ng-hide="caseType.is_active==1">
<a class="action-item crm-hover-button" ng-click="toggleCaseType(caseType)">
{{ts('Enable')}}
</a>
</li>
- <li ng-show="caseType.is_active && !caseType.is_reserved">
+ <li class="panel-item-disable" ng-show="caseType.is_active==1 && caseType.is_reserved!=1">
<a class="action-item crm-hover-button"
crm-confirm="{type: 'disable', obj: caseType}"
on-yes="toggleCaseType(caseType)">
{{ts('Disable')}}
</a>
</li>
- <li ng-show="caseType.is_forked">
+ <li class="panel-item-revert" ng-show="caseType.is_forked==1">
<a class="action-item crm-hover-button"
crm-confirm="{type: 'revert', obj: caseType}"
on-yes="revertCaseType(caseType)">
{{ts('Revert')}}
</a>
</li>
- <li ng-show="!caseType.is_reserved">
+ <li class="panel-item-delete" ng-show="caseType.is_reserved!=1">
<a class="action-item crm-hover-button"
crm-confirm="{type: 'delete', obj: caseType}"
on-yes="deleteCaseType(caseType)">
*
* @return array|int
*/
-function civicrm_api(string $entity = NULL, string $action, array $params, $extra = NULL) {
+function civicrm_api(string $entity, string $action, array $params, $extra = NULL) {
return \Civi::service('civi_api_kernel')->runSafe($entity, $action, $params, $extra);
}
* @throws \Civi\API\Exception\NotImplementedException
*/
function civicrm_api4(string $entity, string $action, array $params = [], $index = NULL) {
- $apiCall = \Civi\Api4\Utils\ActionUtil::getAction($entity, $action);
$indexField = $index && is_string($index) && !CRM_Utils_Rule::integer($index) ? $index : NULL;
$removeIndexField = FALSE;
$params['select'][] = $indexField;
$removeIndexField = TRUE;
}
- foreach ($params as $name => $param) {
- $setter = 'set' . ucfirst($name);
- $apiCall->$setter($param);
- }
+ $apiCall = \Civi\API\Request::create($entity, $action, ['version' => 4] + $params);
if ($index && is_array($index)) {
$indexCol = reset($index);
}
elseif (is_string($moveFile)) {
// CRM-17432 Do not use rename() since it will break file permissions.
- // Also avoid move_uplaoded_file() because the API can use options.move-file.
- copy($moveFile, $path);
+ // Also avoid move_uploaded_file() because the API can use options.move-file.
+ if (!copy($moveFile, $path)) {
+ throw new API_Exception("Cannot copy uploaded file $moveFile to $path");
+ }
unlink($moveFile);
}
if (empty($params['contact_type']) && $contactID) {
$params['contact_type'] = CRM_Contact_BAO_Contact::getContactType($contactID);
+ if (!$params['contact_type']) {
+ throw new API_Exception('Contact id ' . $contactID . ' not found.');
+ }
}
if (!isset($params['contact_sub_type']) && $contactID) {
*
* @return array
* API result array
+ *
+ * @throws \CiviCRM_API3_Exception
+ * @throws \CRM_Core_Exception
*/
function civicrm_api3_participant_create($params) {
// Check that event id is not an template - should be done @ BAO layer.
}
}
- if (is_array($params) && !empty($params['debug'])) {
+ if (is_array($params) && $entity && !empty($params['debug'])) {
if (is_string($action) && $action !== 'getfields') {
$apiFields = civicrm_api($entity, 'getfields', ['version' => 3, 'action' => $action] + $params);
}
},
"require": {
"php": "~7.0",
+ "cache/integration-tests": "~0.16.0",
"dompdf/dompdf" : "0.8.*",
"electrolinux/phpquery": "^0.9.6",
"symfony/config": "^2.8.50 || ~3.0",
"pear/validate_finance_creditcard": "dev-master",
"civicrm/civicrm-cxn-rpc": "~0.19.01.08",
"pear/auth_sasl": "1.1.0",
- "pear/net_smtp": "1.6.*",
+ "pear/net_smtp": "1.9.*",
"pear/net_socket": "1.0.*",
"pear/mail": "^1.4",
"civicrm/civicrm-setup": "~0.4.0",
"tplaner/when": "~3.0.0",
"xkerman/restricted-unserialize": "~1.1"
},
- "require-dev": {
- "cache/integration-tests": "dev-master"
- },
"scripts": {
"post-install-cmd": [
"bash tools/scripts/composer/dompdf-cleanup.sh",
}
},
"patches": {
+ "cache/integration-tests": {
+ "Allow adding tests": "https://github.com/php-cache/integration-tests/commit/05f97174c09364dc10c084a38ba0cfd5124f4cec.patch",
+ "Support PHPUnit 6+": "https://github.com/php-cache/integration-tests/commit/1ec7362962185df91d3d749bc3fa7e7b99cb9fc7.patch",
+ "Add tests for binary data round trip": "https://github.com/php-cache/integration-tests/commit/89cd7068e83aa776774bfc44f6bcba858c085616.patch"
+ },
+ "pear/net_smtp": {
+ "Add in CiviCRM custom error message for CRM-8744": "https://raw.githubusercontent.com/civicrm/civicrm-core/a6a0ff13d2a155ad962529595dceaef728116f96/tools/scripts/composer/patches/net-smtp-patch.patch"
+ },
"phpoffice/common": {
- "Fix handling of libxml_disable_entity_loader": "tools/scripts/composer/patches/phpoffice-common-xml-entity-fix.patch"
+ "Fix handling of libxml_disable_entity_loader": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/phpoffice-common-xml-entity-fix.patch"
},
"phpoffice/phpword": {
- "Fix handling of libxml_disable_entity_loader": "tools/scripts/composer/patches/phpword-libxml-fix-global-handling.patch"
+ "Fix handling of libxml_disable_entity_loader": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/phpword-libxml-fix-global-handling.patch"
},
"zetacomponents/mail": {
- "CiviCRM Custom Patches for ZetaCompoents mail": "tools/scripts/composer/patches/civicrm-custom-patches-zetacompoents-mail.patch"
+ "CiviCRM Custom Patches for ZetaCompoents mail": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/civicrm-custom-patches-zetacompoents-mail.patch"
}
}
}
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "6b2ec4d9dc608f8b2e0def4af6d7bafb",
+ "content-hash": "705221f636824b774ef9fb35f3bfc987",
"packages": [
+ {
+ "name": "cache/integration-tests",
+ "version": "0.16.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-cache/integration-tests.git",
+ "reference": "a8d9538a44ed5a70d551f9b87f534c98dfe6b0ee"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-cache/integration-tests/zipball/a8d9538a44ed5a70d551f9b87f534c98dfe6b0ee",
+ "reference": "a8d9538a44ed5a70d551f9b87f534c98dfe6b0ee",
+ "shasum": ""
+ },
+ "require": {
+ "cache/tag-interop": "^1.0",
+ "php": "^5.4|^7",
+ "psr/cache": "~1.0"
+ },
+ "require-dev": {
+ "cache/cache": "dev-master",
+ "illuminate/cache": "^5.0",
+ "madewithlove/illuminate-psr-cache-bridge": "^1.0",
+ "phpunit/phpunit": "^4.0|^5.0",
+ "symfony/cache": "^3.1",
+ "tedivm/stash": "dev-master"
+ },
+ "type": "library",
+ "extra": {
+ "patches_applied": {
+ "Allow adding tests": "https://github.com/php-cache/integration-tests/commit/05f97174c09364dc10c084a38ba0cfd5124f4cec.patch",
+ "Support PHPUnit 6+": "https://github.com/php-cache/integration-tests/commit/1ec7362962185df91d3d749bc3fa7e7b99cb9fc7.patch",
+ "Add tests for binary data round trip": "https://github.com/php-cache/integration-tests/commit/89cd7068e83aa776774bfc44f6bcba858c085616.patch"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Cache\\IntegrationTests\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Aaron Scherer",
+ "email": "aequasi@gmail.com",
+ "homepage": "https://github.com/aequasi"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ }
+ ],
+ "description": "Integration tests for PSR-6 and PSR-16 cache implementations",
+ "homepage": "https://github.com/php-cache/integration-tests",
+ "keywords": [
+ "cache",
+ "psr16",
+ "psr6",
+ "test"
+ ],
+ "time": "2017-02-02T14:29:50+00:00"
+ },
+ {
+ "name": "cache/tag-interop",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-cache/tag-interop.git",
+ "reference": "c7496dd81530f538af27b4f2713cde97bc292832"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-cache/tag-interop/zipball/c7496dd81530f538af27b4f2713cde97bc292832",
+ "reference": "c7496dd81530f538af27b4f2713cde97bc292832",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5 || ^7.0",
+ "psr/cache": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Cache\\TagInterop\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com",
+ "homepage": "https://github.com/nicolas-grekas"
+ }
+ ],
+ "description": "Framework interoperable interfaces for tags",
+ "homepage": "http://www.php-cache.com/en/latest/",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr6",
+ "tag"
+ ],
+ "time": "2017-03-13T09:14:27+00:00"
+ },
{
"name": "civicrm/civicrm-cxn-rpc",
"version": "v0.19.01.08",
},
{
"name": "pear/net_smtp",
- "version": "1.6.3",
+ "version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/pear/Net_SMTP.git",
- "reference": "7b6240761adf6ee245098e238a25d5c35650d82c"
+ "reference": "f7fbc5808bfeba87c38e02ea4acc5243ffc9524e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pear/Net_SMTP/zipball/7b6240761adf6ee245098e238a25d5c35650d82c",
- "reference": "7b6240761adf6ee245098e238a25d5c35650d82c",
+ "url": "https://api.github.com/repos/pear/Net_SMTP/zipball/f7fbc5808bfeba87c38e02ea4acc5243ffc9524e",
+ "reference": "f7fbc5808bfeba87c38e02ea4acc5243ffc9524e",
"shasum": ""
},
"require": {
- "pear/net_socket": "*",
- "pear/pear_exception": "*",
- "php": ">=4.0.5"
+ "pear/net_socket": "@stable",
+ "pear/pear-core-minimal": "@stable",
+ "php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "*"
"pear/auth_sasl": "Install optionally via your project's composer.json"
},
"type": "library",
+ "extra": {
+ "patches_applied": {
+ "Add in CiviCRM custom error message for CRM-8744": "https://raw.githubusercontent.com/civicrm/civicrm-core/a6a0ff13d2a155ad962529595dceaef728116f96/tools/scripts/composer/patches/net-smtp-patch.patch"
+ }
+ },
"autoload": {
"psr-0": {
"Net": "./"
"./"
],
"license": [
- "PHP License"
+ "BSD-2-Clause"
],
"authors": [
{
"name": "Jon Parise",
"email": "jon@php.net",
- "homepage": "http://www.indelible.org",
+ "homepage": "https://www.indelible.org",
"role": "Lead"
},
{
}
],
"description": "An implementation of the SMTP protocol",
- "homepage": "http://pear.github.io/Net_SMTP/",
+ "homepage": "https://pear.github.io/Net_SMTP/",
"keywords": [
"email",
"mail",
"smtp"
],
- "time": "2015-08-02T17:20:17+00:00"
+ "time": "2019-11-30T23:40:31+00:00"
},
{
"name": "pear/net_socket",
"type": "library",
"extra": {
"patches_applied": {
- "Fix handling of libxml_disable_entity_loader": "tools/scripts/composer/patches/phpoffice-common-xml-entity-fix.patch"
+ "Fix handling of libxml_disable_entity_loader": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/phpoffice-common-xml-entity-fix.patch"
}
},
"autoload": {
"dev-develop": "0.16-dev"
},
"patches_applied": {
- "Fix handling of libxml_disable_entity_loader": "tools/scripts/composer/patches/phpword-libxml-fix-global-handling.patch"
+ "Fix handling of libxml_disable_entity_loader": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/phpword-libxml-fix-global-handling.patch"
}
},
"autoload": {
],
"time": "2017-06-05T06:30:30+00:00"
},
+ {
+ "name": "psr/cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "time": "2016-08-06T20:24:11+00:00"
+ },
{
"name": "psr/http-message",
"version": "1.0.1",
"type": "library",
"extra": {
"patches_applied": {
- "CiviCRM Custom Patches for ZetaCompoents mail": "tools/scripts/composer/patches/civicrm-custom-patches-zetacompoents-mail.patch"
+ "CiviCRM Custom Patches for ZetaCompoents mail": "https://raw.githubusercontent.com/civicrm/civicrm-core/9d93748a36c7c5d44422911db1c98fb2f7067b34/tools/scripts/composer/patches/civicrm-custom-patches-zetacompoents-mail.patch"
}
},
"autoload": {
"time": "2020-01-17T11:18:01+00:00"
}
],
- "packages-dev": [
- {
- "name": "cache/integration-tests",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "https://github.com/php-cache/integration-tests.git",
- "reference": "b97328797ab199f0ac933e39842a86ab732f21f9"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-cache/integration-tests/zipball/b97328797ab199f0ac933e39842a86ab732f21f9",
- "reference": "b97328797ab199f0ac933e39842a86ab732f21f9",
- "shasum": ""
- },
- "require": {
- "cache/tag-interop": "^1.0",
- "php": "^5.4|^7",
- "psr/cache": "~1.0"
- },
- "conflict": {
- "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
- },
- "require-dev": {
- "cache/cache": "^1.0",
- "illuminate/cache": "^5.4|^5.5|^5.6",
- "mockery/mockery": "^1.0",
- "phpunit/phpunit": "^4.8.35|^5.4.3",
- "symfony/cache": "^3.1|^4.0|^5.0",
- "tedivm/stash": "^0.14"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Cache\\IntegrationTests\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Aaron Scherer",
- "email": "aequasi@gmail.com",
- "homepage": "https://github.com/aequasi"
- },
- {
- "name": "Tobias Nyholm",
- "email": "tobias.nyholm@gmail.com",
- "homepage": "https://github.com/nyholm"
- }
- ],
- "description": "Integration tests for PSR-6 and PSR-16 cache implementations",
- "homepage": "https://github.com/php-cache/integration-tests",
- "keywords": [
- "cache",
- "psr16",
- "psr6",
- "test"
- ],
- "time": "2019-05-28T15:23:38+00:00"
- },
- {
- "name": "cache/tag-interop",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-cache/tag-interop.git",
- "reference": "c7496dd81530f538af27b4f2713cde97bc292832"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-cache/tag-interop/zipball/c7496dd81530f538af27b4f2713cde97bc292832",
- "reference": "c7496dd81530f538af27b4f2713cde97bc292832",
- "shasum": ""
- },
- "require": {
- "php": "^5.5 || ^7.0",
- "psr/cache": "^1.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Cache\\TagInterop\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Tobias Nyholm",
- "email": "tobias.nyholm@gmail.com",
- "homepage": "https://github.com/Nyholm"
- },
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com",
- "homepage": "https://github.com/nicolas-grekas"
- }
- ],
- "description": "Framework interoperable interfaces for tags",
- "homepage": "http://www.php-cache.com/en/latest/",
- "keywords": [
- "cache",
- "psr",
- "psr6",
- "tag"
- ],
- "time": "2017-03-13T09:14:27+00:00"
- },
- {
- "name": "psr/cache",
- "version": "1.0.1",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/cache.git",
- "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
- "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Psr\\Cache\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interface for caching libraries",
- "keywords": [
- "cache",
- "psr",
- "psr-6"
- ],
- "time": "2016-08-06T20:24:11+00:00"
- }
- ],
+ "packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
- "pear/validate_finance_creditcard": 20,
- "cache/integration-tests": 20
+ "pear/validate_finance_creditcard": 20
},
"prefer-stable": false,
"prefer-lowest": false,
return $(this).each(function() {
$(this)
.removeClass('crm-ajax-select')
+ .off('.crmSelect2')
.select2('destroy');
});
}
};
}
+ // Use description as title for each option
+ $el.on('select2-loaded.crmSelect2', function() {
+ $('.crm-select2-row-description', '#select2-drop').each(function() {
+ $(this).closest('.select2-result-label').attr('title', $(this).text());
+ });
+ });
+
// Defaults for single-selects
if ($el.is('select:not([multiple])')) {
settings.minimumResultsForSearch = 10;
'</div>' +
'<div class="crm-select2-row-description">';
$.each(row.description || [], function(k, text) {
- markup += '<p>' + _.escape(text) + '</p>';
+ markup += '<p>' + _.escape(text) + '</p> ';
});
markup += '</div></div></div>';
return markup;
return (yiq >= 128) ? 'black' : 'white';
};
- // based on https://github.com/janl/mustache.js/blob/master/mustache.js
- // If you feel the need to use this function, consider whether assembling HTML
- // via DOM might be a cleaner approach rather than using string concatenation.
- CRM.utils.escapeHtml = function(string) {
- var entityMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '/': '/',
- '`': '`',
- '=': '='
- };
- return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
- return entityMap[s];
- });
- }
-
// CVE-2015-9251 - Prevent auto-execution of scripts when no explicit dataType was provided
$.ajaxPrefilter(function(s) {
if (s.crossDomain) {
// https://civicrm.org/licensing
/* global CRM, ts */
/*jshint loopfunc: true */
-(function($) {
+(function($, _) {
'use strict';
// Constructor for dashboard object.
$.fn.dashboard = function(options) {
});
CRM.alert(
ts('You can re-add it by clicking the "Configure Your Dashboard" button.'),
- ts('"%1" Removed', {1: CRM.utils.escapeHtml(widget.title)}),
+ ts('"%1" Removed', {1: _.escape(widget.title)}),
'success'
);
};
function widgetHTML() {
var html = '';
html += '<div class="widget-wrapper">';
- html += ' <div class="widget-controls"><h3 class="widget-header">' + CRM.utils.escapeHtml(widget.title) + '</h3></div>';
+ html += ' <div class="widget-controls"><h3 class="widget-header">' + _.escape(widget.title) + '</h3></div>';
html += ' <div class="widget-content"></div>';
html += '</div>';
return html;
// id, url, fullscreenUrl, title, name, cacheMinutes
}
};
-})(jQuery);
+})(jQuery, CRM._);
# CiviCRM 5.21.1
-Released January 10, 2019
+Released January 10, 2020
- **[Synopsis](#synopsis)**
- **[Bugs resolved](#bugs)**
'description' => ts('Enable tracking of activity revisions embedded within the "civicrm_activity" table. Alternatively, see "Administer => System Settings => Misc => Logging".'),
'help_text' => '',
],
+ 'civicaseShowCaseActivities' => [
+ 'group_name' => 'CiviCRM Preferences',
+ 'group' => 'core',
+ 'name' => 'civicaseShowCaseActivities',
+ 'type' => 'Boolean',
+ 'quick_form_type' => 'YesNo',
+ 'default' => FALSE,
+ 'html_type' => 'radio',
+ 'add' => '5.24',
+ 'title' => ts('Include case activities in general activity views.'),
+ 'is_domain' => 1,
+ 'is_contact' => 0,
+ 'description' => ts('e.g. the Contact form\'s Activity tab listing. Without this ticked, activities that belong to a case are hidden (default behavior). Warning: enabling this option means that all case activities relating to a contact will be listed which could result in users without "access all cases and activities" permission being able to see see the summarized details (date, subject, assignees, status etc.). Such users will still be prevented from managing the case and viewing/editing the activity.'),
+ 'help_text' => '',
+ ],
];
'is_contact' => 0,
'description' => ts('Is the CVV code required for back office credit card transactions'),
'help_text' => 'If set it back-office credit card transactions will required a cvv code. Leave as required unless you have a very strong reason to change',
+ 'settings_pages' => ['contribute' => ['weight' => 10]],
],
'contribution_invoice_settings' => [
// @todo our standard is to have a setting per item not to hide settings in an array with
'on_change' => [
'CRM_Invoicing_Utils::onToggle',
],
+ 'settings_pages' => ['contribute' => ['weight' => 90]],
],
'credit_notes_prefix' => [
'group_name' => 'Contribute Preferences',
'description' => ts('Prefix to be prepended to credit note ids'),
'default' => 'CN_',
'help_text' => ts('The credit note ID is generated when a contribution is set to Refunded, Cancelled or Chargeback. It is visible on invoices, if invoices are enabled'),
+ 'settings_pages' => ['contribute' => ['weight' => 80]],
],
'invoice_prefix' => [
'html_type' => 'text',
'is_contact' => 0,
'help_text' => NULL,
'help' => ['id' => 'acl_financial_type'],
+ 'settings_pages' => ['contribute' => ['weight' => 30]],
],
'deferred_revenue_enabled' => [
'group_name' => 'Contribute Preferences',
'is_domain' => 1,
'is_contact' => 0,
'help_text' => NULL,
+ 'settings_pages' => ['contribute' => ['weight' => 50]],
],
'default_invoice_page' => [
'group_name' => 'Contribute Preferences',
'is_domain' => 1,
'is_contact' => 0,
'help_text' => NULL,
+ 'settings_pages' => ['contribute' => ['weight' => 70]],
],
'always_post_to_accounts_receivable' => [
'group_name' => 'Contribute Preferences',
'is_domain' => 1,
'is_contact' => 0,
'help_text' => NULL,
+ 'settings_pages' => ['contribute' => ['weight' => 40]],
],
'update_contribution_on_membership_type_change' => [
'group_name' => 'Contribute Preferences',
'is_contact' => 0,
'description' => ts('Enabling this setting will update related contribution of membership(s) except if the membership is paid for with a recurring contribution.'),
'help_text' => NULL,
+ 'settings_pages' => ['contribute' => ['weight' => 20]],
],
];
LOCK TABLES `civicrm_domain` WRITE;
/*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */;
-INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.23.beta1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
+INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.24.alpha1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
/*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
UNLOCK TABLES;
{/if}
<table class="crm-info-panel">
<tr>
- <td class="label">{ts}Added By{/ts}</td><td class="view-value">{$values.source_contact}</td>
+ <td class="label">{ts}Added by{/ts}</td><td class="view-value">{$values.source_contact}</td>
</tr>
{if $values.target_contact_value}
<tr>
<tr class="columnheader">
<td>{ts}Type{/ts}</td>
<td>{ts}Subject{/ts}</td>
- <td>{ts}Added By{/ts}</td>
+ <td>{ts}Added by{/ts}</td>
<td>{ts}With{/ts}</td>
<td>{ts}Assigned to{/ts}</td>
<td>{ts}Date{/ts}</td>
<tr class="columnheader">
<th>{ts}Type{/ts}</th>
<th>{ts}Subject{/ts}</th>
- <th>{ts}Added By{/ts}</th>
+ <th>{ts}Added by{/ts}</th>
<th>{ts}With{/ts}</th>
<th>{ts}Date{/ts}</th>
<th>{ts}Status{/ts}</th>
<tr>
<th data-data="activity_type" class="crm-contact-activity-activity_type">{ts}Type{/ts}</th>
<th data-data="subject" cell-class="crmf-subject crm-editable" class="crm-contact-activity_subject">{ts}Subject{/ts}</th>
- <th data-data="source_contact_name" class="crm-contact-activity-source_contact">{ts}Added By{/ts}</th>
+ <th data-data="source_contact_name" class="crm-contact-activity-source_contact">{ts}Added by{/ts}</th>
<th data-data="target_contact_name" data-orderable="false" class="crm-contact-activity-target_contact">{ts}With{/ts}</th>
<th data-data="assignee_contact_name" data-orderable="false" class="crm-contact-activity-assignee_contact">{ts}Assigned{/ts}</th>
<th data-data="activity_date_time" class="crm-contact-activity-activity_date_time">{ts}Date{/ts}</th>
<span class="description">{ts}Enable embedded tracking to activity revisions within the "civicrm_activity" table. Alternatively, see "Administer => System Settings => Misc => Logging".{/ts}</span>
</td>
</tr>
+ <tr class="crm-case-form-block-civicaseShowCaseActivities">
+ <td class="label">{$form.civicaseShowCaseActivities.label}</td>
+ <td>{$form.civicaseShowCaseActivities.html}<br />
+ <span class="description">{$civicaseShowCaseActivities_description}</span>
+ </td>
+ </tr>
</table>
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
</div>
{else}
<tr class="crm-localization-form-block-description">
<td>
- <span class="description">{ts}In order to use this functionality, the installation's database user must have privileges to create triggers and views (in MySQL 5.0 – and in MySQL 5.1 if binary logging is enabled – this means the SUPER privilege). This install either does not seem to have the required privilege enabled.{/ts} {ts}(Multilingual support currently cannot be enabled on installations with enabled logging.){/ts}</span><br /><br />
+ <span class="description">{ts}In order to use this functionality, the installation's database user must have privileges to create triggers and views (if binary logging is enabled – this means the SUPER privilege). This install does not have the required privilege(s) enabled.{/ts} {ts}(Multilingual support currently cannot be enabled on installations with enabled logging.){/ts}</span><br /><br />
<span class="description font-red">{$warning}</span></td>
</tr>
{/if}
<div id="crm-container" class="crm-container">
<h1>{$pageTitle}</h1>
<div id="report-date">{$reportDate}</div>
-<h2>{ts}Case Summary{/ts}</h2>
-<table class="report-layout">
+{if $case}
+ <h2>{ts}Case Summary{/ts}</h2>
+ <table class="report-layout">
<tr>
<th class="reports-header">{ts}Client{/ts}</th>
<th class="reports-header">{ts}Case Type{/ts}</th>
- <th class="reports-header">{ts}Status{/ts}</th>
- <th class="reports-header">{ts}Start Date{/ts}</th>
+ <th class="reports-header">{ts}Status{/ts}</th>
+ <th class="reports-header">{ts}Start Date{/ts}</th>
<th class="reports-header">{ts}Case ID{/ts}</th>
</tr>
<tr>
- <td class="crm-case-report-clientName">{$case.clientName}</td>
- <td class="crm-case-report-caseType">{$case.caseType}</td>
- <td class="crm-case-report-status">{$case.status}</td>
- <td class="crm-case-report-start_date">{$case.start_date}</td>
- <td class="crm-case-report-{$caseId}">{$caseId}</td>
+ <td class="crm-case-report-clientName">{$case.clientName}</td>
+ <td class="crm-case-report-caseType">{$case.caseType}</td>
+ <td class="crm-case-report-status">{$case.status}</td>
+ <td class="crm-case-report-start_date">{$case.start_date}</td>
+ <td class="crm-case-report-{$caseId}">{$caseId}</td>
</tr>
-</table>
-<h2>{ts}Case Roles{/ts}</h2>
-<table class ="report-layout">
+ </table>
+{/if}
+
+{if $caseRelationships}
+ <h2>{ts}Case Roles{/ts}</h2>
+ <table class ="report-layout">
<tr>
<th class="reports-header">{ts}Case Role{/ts}</th>
<th class="reports-header">{ts}Name{/ts}</th>
- <th class="reports-header">{ts}Phone{/ts}</th>
- <th class="reports-header">{ts}Email{/ts}</th>
+ <th class="reports-header">{ts}Phone{/ts}</th>
+ <th class="reports-header">{ts}Email{/ts}</th>
</tr>
{foreach from=$caseRelationships item=row key=relId}
- <tr>
- <td class="crm-case-report-caserelationships-relation">{$row.relation}</td>
- <td class="crm-case-report-caserelationships-name">{$row.name}</td>
- <td class="crm-case-report-caserelationships-phone">{$row.phone}</td>
- <td class="crm-case-report-caserelationships-email">{$row.email}</td>
- </tr>
+ <tr>
+ <td class="crm-case-report-caserelationships-relation">{$row.relation}</td>
+ <td class="crm-case-report-caserelationships-name">{$row.name}</td>
+ <td class="crm-case-report-caserelationships-phone">{$row.phone}</td>
+ <td class="crm-case-report-caserelationships-email">{$row.email}</td>
+ </tr>
{/foreach}
{foreach from=$caseRoles item=relName key=relTypeID}
- {if $relTypeID neq 'client'}
- <tr>
- <td>{$relName}</td>
- <td>{ts}(not assigned){/ts}</td>
- <td></td>
- <td></td>
- </tr>
- {else}
- <tr>
- <td class="crm-case-report-caseroles-role">{$relName.role}</td>
- <td class="crm-case-report-caseroles-sort_name">{$relName.sort_name}</td>
- <td class="crm-case-report-caseroles-phone">{$relName.phone}</td>
- <td class="crm-case-report-caseroles-email">{$relName.email}</td>
- </tr>
- {/if}
- {/foreach}
-</table>
-<br />
-
+ {if $relTypeID neq 'client'}
+ <tr>
+ <td>{$relName}</td>
+ <td>{ts}(not assigned){/ts}</td>
+ <td></td>
+ <td></td>
+ </tr>
+ {else}
+ <tr>
+ <td class="crm-case-report-caseroles-role">{$relName.role}</td>
+ <td class="crm-case-report-caseroles-sort_name">{$relName.sort_name}</td>
+ <td class="crm-case-report-caseroles-phone">{$relName.phone}</td>
+ <td class="crm-case-report-caseroles-email">{$relName.email}</td>
+ </tr>
+ {/if}
+ {/foreach}
+ </table>
+ <br />
+{/if}
{if $otherRelationships}
<table class ="report-layout">
<tr>
{/foreach}
{/if}
-<h2>{ts}Case Activities{/ts}</h2>
-{foreach from=$activities item=activity key=key}
- <table class ="report-layout">
- {foreach from=$activity item=field name=fieldloop}
- <tr class="crm-case-report-activity-{$field.label}">
- <th scope="row" class="label">{$field.label|escape}</th>
- {if $field.label eq 'Activity Type' or $field.label eq 'Status'}
- <td class="bold">{$field.value|escape}</td>
- {elseif $field.label eq 'Details' or $field.label eq 'Subject'}
- <td>{$field.value}</td>
- {else}
- <td>{$field.value|escape}</td>
- {/if}
- </tr>
- {/foreach}
- </table>
- <br />
-{/foreach}
+{if $activities}
+ <h2>{ts}Case Activities{/ts}</h2>
+ {foreach from=$activities item=activity key=key}
+ <table class ="report-layout">
+ {foreach from=$activity item=field name=fieldloop}
+ <tr class="crm-case-report-activity-{$field.label}">
+ <th scope="row" class="label">{$field.label|escape}</th>
+ {if $field.label eq 'Activity Type' or $field.label eq 'Status'}
+ <td class="bold">{$field.value|escape}</td>
+ {elseif $field.label eq 'Details' or $field.label eq 'Subject'}
+ <td>{$field.value}</td>
+ {else}
+ <td>{$field.value|escape}</td>
+ {/if}
+ </tr>
+ {/foreach}
+ </table>
+ <br />
+ {/foreach}
+{/if}
</div>
</body>
</html>
-
-
-
-
-
<th>{ts}Type{/ts}</th>
<th>{ts}Subject{/ts}</th>
<th>{ts}Details{/ts}</th>
- <th class='link'>{ts}Added By{/ts}</th>
+ <th class='link'>{ts}Added by{/ts}</th>
<th class='link'>{ts}With{/ts}</th>
<th class='link'>{ts}Assignee{/ts}</th>
{if $allowFileSearch}<th>{ts}File{/ts}</th>{/if}
{/literal}
</script>
{/if}
-
-{* jQuery validate *}
-{* disabled because originally this caused problems with some credit cards.
-Likely it no longer has an problems but allowing conditional
- inclusion by extensions / payment processors for now in order to add in a conservative way *}
-{if $isJsValidate}
- {include file="CRM/Form/validate.tpl"}
-{/if}
+{include file="CRM/Form/validate.tpl"}
<td class="label">{ts}Financial Type{/ts}</td>
<td>{$financial_type}{if $is_test} {ts}(test){/ts} {/if}</td>
</tr>
+ <tr>
+ <td class="label">{ts}Source{/ts}</td>
+ <td>{$source}</td>
+ </tr>
+ <tr>
+ <td class="label">{ts}Received{/ts}</td>
+ <td>{if $receive_date}{$receive_date|crmDate}{else}({ts}not available{/ts}){/if}</td>
+ </tr>
{if $displayLineItems}
<tr>
<td class="label">{ts}Contribution Amount{/ts}</td>
<td>{$revenue_recognition_date|crmDate:"%B, %Y"}</td>
</tr>
{/if}
- <tr>
- <td class="label">{ts}Received{/ts}</td>
- <td>{if $receive_date}{$receive_date|crmDate}{else}({ts}not available{/ts}){/if}</td>
- </tr>
{if $to_financial_account }
<tr>
<td class="label">{ts}Received Into{/ts}</td>
<td>{$check_number}</td>
</tr>
{/if}
- <tr>
- <td class="label">{ts}Source{/ts}</td>
- <td>{$source}</td>
- </tr>
{if $campaign}
<tr>
</script>
{/literal}
+{include file="CRM/Form/validate.tpl"}
"url": {/literal}'{crmURL p="civicrm/ajax/grouplist" h=0 q="snippet=4"}'{literal},
"data": function (d) {
- var groupTypes = ($('.crm-group-search-form-block #group_type_search_1').prop('checked')) ? '1' : '';
- if (groupTypes) {
- groupTypes = ($('.crm-group-search-form-block #group_type_search_2').prop('checked')) ? groupTypes + ',2' : groupTypes;
- } else {
- groupTypes = ($('.crm-group-search-form-block #group_type_search_2').prop('checked')) ? '2' : '';
- }
+ var groupTypes = '';
+ $('input[id*="group_type_search_"]:checked').each(function(e) {
+ groupTypes += $(this).attr('id').replace(/group_type_search_/, groupTypes == '' ? '' : ',');
+ });
var groupStatus = ($('.crm-group-search-form-block #group_status_1').prop('checked')) ? 1 : '';
if (groupStatus) {
<thead>
<tr>
<th data-data="subject" class="crm-mailing-contact-subject">{ts}Subject{/ts}</th>
- <th data-data="creator_name" class="crm-mailing-contact_created">{ts}Added By{/ts}</th>
+ <th data-data="creator_name" class="crm-mailing-contact_created">{ts}Added by{/ts}</th>
<th data-data="recipients" data-orderable="false" class="crm-contact-activity_contact">{ts}Recipients{/ts}</th>
<th data-data="start_date" class="crm-mailing-contact-date">{ts}Date{/ts}</th>
<th data-data="openstats" data-orderable="false" class="crm-mailing_openstats">{ts}Opens/ Clicks{/ts}</th>
* Display calculated amount.
*/
function display(totalfee) {
+ // totalfee is monetary, round it to 2 decimal points so it can
+ // go as a float - CRM-13491
+ totalfee = Math.round(totalfee*100)/100;
+ var totalFormattedFee = CRM.formatMoney(totalfee);
+ cj('#pricevalue').html(totalFormattedFee);
- // totalfee is monetary, round it to 2 decimal points so it can
- // go as a float - CRM-13491
- totalfee = Math.round(totalfee*100)/100;
- var totalEventFee = formatMoney( totalfee, 2, separator, thousandMarker);
- document.getElementById('pricevalue').innerHTML = "<b>"+symbol+"</b> "+totalEventFee;
+ cj('#total_amount').val( totalfee );
+ cj('#pricevalue').data('raw-total', totalfee).trigger('change');
- cj('#total_amount').val( totalfee );
- cj('#pricevalue').data('raw-total', totalfee).trigger('change');
-
- ( totalfee < 0 ) ? cj('table#pricelabel').addClass('disabled') : cj('table#pricelabel').removeClass('disabled');
- if (typeof skipPaymentMethod == 'function') {
- // Advice to anyone who, like me, feels hatred towards this if construct ... if you remove the if you
- // get an error on participant 2 of a event that requires approval & permits multiple registrants.
- skipPaymentMethod();
- }
-}
+ if (totalfee < 0) {
+ cj('table#pricelabel').addClass('disabled');
+ }
+ else {
+ cj('table#pricelabel').removeClass('disabled');
+ }
-//money formatting/localization
-function formatMoney (amount, c, d, t) {
-var n = amount,
- c = isNaN(c = Math.abs(c)) ? 2 : c,
- d = d == undefined ? "," : d,
- t = t == undefined ? "." : t, s = n < 0 ? "-" : "",
- i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
- j = (j = i.length) > 3 ? j % 3 : 0;
- return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
+ if (typeof skipPaymentMethod == 'function') {
+ // Advice to anyone who, like me, feels hatred towards this if construct ... if you remove the if you
+ // get an error on participant 2 of a event that requires approval & permits multiple registrants.
+ skipPaymentMethod();
+ }
}
{/literal}
</tr>
{/if}
</table>
- {if $parent_tags|@count > 0}
- <table class="form-layout-compressed">
- <tr><td><label>{ts}Remove Parent?{/ts}</label></td></tr>
- {foreach from=$parent_tags item=ctag key=tag_id}
- {assign var="element_name" value="remove_parent_tag_"|cat:$tag_id}
- <tr><td> {$form.$element_name.html} {$form.$element_name.label}</td></tr>
- {/foreach}
- </table><br />
- {/if}
{else}
<div class="status">{ts 1=$delName}Are you sure you want to delete <b>%1</b>?{/ts}<br />{ts}This tag will be removed from any currently tagged contacts, and users will no longer be able to assign contacts to this tag.{/ts}</div>
{/if}
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2018 |
+ | Copyright CiviCRM LLC (c) 2004-2020 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
<extension key='test.extension.manager.moduletest' type='module'>
<file>moduletest</file>
<name>test_extension_manager_moduletest</name>
+ <tags>
+ <tag>mock</tag>
+ </tags>
</extension>
<isRecur>0</isRecur>
<paymentType>1</paymentType>
</typeInfo>
+ <tags>
+ <tag>mock</tag>
+ </tags>
</extension>
$httpBackend = _$httpBackend_;
$q = _$q_;
$rootScope = _$rootScope_;
+ $rootScope.ts = CRM.ts(null);
$timeout = _$timeout_;
}));
});
});
});
+
+ // Test show/hide for the various dropdown actions
+ describe('showandtell', function() {
+ var templateCache;
+ var template;
+
+ // $templateCache is populated by the nghtml2js plugin. See karma.conf.js
+ // I'm not sure why it can't be injected higher up in the hierarchy. It doesn't seem to work?
+ beforeEach(inject(function($templateCache) {
+ scope = $rootScope.$new();
+ templateCache = $templateCache;
+ template = templateCache.get('~/crmCaseType/list.html');
+ }));
+
+ // Helper function which we call repeatedly. It can't be in beforeEach
+ // because then the timing is wrong because we need different caseTypes
+ // in each test, which happens of course after beforeEach.
+ var compileTemplate = function(scope) {
+ var element = $compile(template)(scope);
+ scope.$digest();
+ return element;
+ };
+
+ // This is the workhorse function that does the actual test, called
+ // repeatedly for each case type variation from the `it()` below.
+ var doTest = function(inputCaseType, expected) {
+ // Mock up our case types based on input, merging some static info
+ // with the variable input.
+ var caseType = {
+ id: 1,
+ title: 'Housing Support',
+ name: 'housing_support'
+ };
+ // PhantomJS at the moment doesn't support ES6, so do a loop.
+ for (var memberVar in inputCaseType) {
+ caseType[memberVar] = inputCaseType[memberVar];
+ }
+ scope.caseTypes = {
+ 1: caseType
+ };
+
+ // Render the template in the context of our scope now that the scope
+ // contains our mock case types.
+ var element = compileTemplate(scope);
+ //console.debug(element);
+
+ //
+ // Now verify the expected values
+ //
+
+ // Useful variable for displaying the inputs that caused failure
+ // in readable form.
+ var inputStr = JSON.stringify(inputCaseType);
+
+ expect(element.find('span.more-panel').hasClass('ng-hide')).toBe(expected.more_hidden, 'More link should be ' +
+ (expected.more_hidden ? 'hidden' : 'visible') +
+ ' for ' + inputStr);
+
+ expect(element.find('li.panel-item-enable').hasClass('ng-hide')).toBe(expected.enable_hidden, 'Enable should be ' +
+ (expected.enable_hidden ? 'hidden' : 'visible') +
+ ' for ' + inputStr);
+
+ expect(element.find('li.panel-item-disable').hasClass('ng-hide')).toBe(expected.disable_hidden, 'Disable should be ' +
+ (expected.disable_hidden ? 'hidden' : 'visible') +
+ ' for ' + inputStr);
+
+ expect(element.find('li.panel-item-revert').hasClass('ng-hide')).toBe(expected.revert_hidden, 'Revert should be ' +
+ (expected.revert_hidden ? 'hidden' : 'visible') +
+ ' for ' + inputStr);
+
+ expect(element.find('li.panel-item-delete').hasClass('ng-hide')).toBe(expected.delete_hidden, 'Delete should be ' +
+ (expected.delete_hidden ? 'hidden' : 'visible') +
+ ' for ' + inputStr);
+ };
+
+ // Test show/hide for the various dropdown actions
+ //
+ // There's 625 assertions.
+ // Three variables: [is_active, is_forked, is_reserved],
+ // each with 5 possible values: [0, 1, "0", "1", undefined].
+ // Then, multiply that by 5 because there are 5 UI elements
+ // to be checked.
+ // So 125 possible input tuples, with 5 things to check in each test.
+ it('to be or not to be', function() {
+ var caseTypeSimulations = [
+ [
+ // input case type
+ {"is_active": "1", "is_reserved": "0"},
+ {
+ // should more link be hidden
+ "more_hidden": false,
+ // should enable choice be hidden
+ "enable_hidden": true,
+ // should disable choice be hidden
+ "disable_hidden": false,
+ // should revert choice be hidden
+ "revert_hidden": true,
+ // should delete choice be hidden
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":1,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":1,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"1","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"1","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_reserved":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":1,"is_forked":0},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":1,"is_forked":"0"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":1},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"1","is_forked":0},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"1","is_forked":"0"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_reserved":"1"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":1,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":1,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":1,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"1","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"1","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_reserved":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":1,"is_forked":0},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":1,"is_forked":"0"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":1},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"1","is_forked":0},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"1","is_forked":"0"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_reserved":"1"},
+ {
+ "more_hidden": true,
+ "enable_hidden": true,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_active":"1","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_active":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": true,
+ "disable_hidden": false,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":0,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":0,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":0,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":0,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":1,"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":1,"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":1,"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":1,"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":"0","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":"0","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":"0","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":"0","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_reserved":"1","is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":"1","is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":"1","is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":"1","is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_reserved":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": true
+ }
+ ],
+
+ [
+ {"is_forked":0},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_forked":1},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_forked":"0"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {"is_forked":"1"},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": false,
+ "delete_hidden": false
+ }
+ ],
+
+ [
+ {},
+ {
+ "more_hidden": false,
+ "enable_hidden": false,
+ "disable_hidden": true,
+ "revert_hidden": true,
+ "delete_hidden": false
+ }
+ ],
+ ];
+ caseTypeSimulations.forEach(function(simulation) {
+ doTest(simulation[0], simulation[1]);
+ });
+ });
+ });
});
+
});
/**
* Test getActivities BAO method for getting count.
+ *
*/
public function testGetActivitiesCountForAdminDashboard() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->setUpForActivityDashboardTests();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
+
$activityCount = CRM_Activity_BAO_Activity::getActivitiesCount($this->_params);
$this->assertEquals(8, $activityCount);
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activityCount = CRM_Activity_BAO_Activity::getActivitiesCount($this->_params);
+ $this->assertEquals(9, $activityCount);
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method for getting count
+ *
*/
public function testGetActivitiesCountforNonAdminDashboard() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$params = [
'contact_id' => 9,
];
//since we are loading activities from dataset, we know total number of activities for this contact
- // 5 activities ( 2 scheduled, 3 Completed ), note that dashboard shows only scheduled activities
+ // 5 activities ( 2 scheduled, 3 Completed, 1 Scheduled Case activity ),
+ // note that dashboard shows only scheduled activities
$this->assertEquals(2, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $this->assertEquals(3, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method for getting count
+ *
*/
public function testGetActivitiesCountforContactSummary() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$params = [
'contact_id' => 9,
];
//since we are loading activities from dataset, we know total number of activities for this contact
- // 5 activities, Contact Summary should show all activities
+ // 5 activities
$this->assertEquals(5, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $this->assertEquals(6, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesForAdminDashboard() {
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->setUpForActivityDashboardTests();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
+
$activitiesNew = CRM_Activity_BAO_Activity::getActivities($this->_params);
// $this->assertEquals($activities, $activitiesDeprecatedFn);
$this->assertEquals($value['status_id'], 1, 'Verify all activities are scheduled.');
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activitiesNew = CRM_Activity_BAO_Activity::getActivities($this->_params);
+ $this->assertEquals(9, count($activitiesNew));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activitiesNew, 'subject')),
+ "failed to find scheduled case Meeting activity");
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesforNonAdminDashboard() {
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$contactID = 9;
$params = [
}
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activities = CRM_Activity_BAO_Activity::getActivities($params);
+ $this->assertEquals(3, count($activities));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activities, 'subject')),
+ "failed to find scheduled case Meeting activity");
+
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesForContactSummary() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$contactID = 9;
$params = [
$this->assertArrayHasKey($contactID, $value['assignee_contact_name']);
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activities = CRM_Activity_BAO_Activity::getActivities($params);
+ $this->assertEquals(6, count($activities));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activities, 'subject')),
+ "failed to find scheduled case Meeting activity");
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesforContactSummaryWithActivities() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
// parameters for different test cases, check each array key for the specific test-case
$mut->stop();
}
+ /**
+ * Adds a case with one activity.
+ *
+ */
+ protected function addCaseWithActivity() {
+ // case is not enabled by default do that now.
+ $enableResult = CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
+ $this->assertTrue($enableResult, 'Cannot enable CiviCase in line ' . __LINE__);
+
+ // We need a minimal case setup.
+ $case_type_id = civicrm_api3('CaseType', 'get', ['return' => 'id', 'name' => 'test_case_type'])['id'] ?? NULL;
+ if (!$case_type_id) {
+ $params = [
+ 'name' => 'test_case_type',
+ 'title' => 'test_case_type',
+ "is_active" => "1",
+ "definition" => [
+ "activityTypes" => [
+ ["name" => "Open Case", "max_instances" => "1"],
+ ["name" => "Meeting"],
+ ],
+ "activitySets" => [
+ [
+ "name" => "standard_timeline",
+ "label" => "Standard Timeline",
+ "timeline" => "1",
+ "activityTypes" => [
+ [
+ "name" => "Open Case",
+ "status" => "Completed",
+ "label" => "Open Case",
+ "default_assignee_type" => "1",
+ ],
+ ],
+ ],
+ ],
+ "timelineActivityTypes" => [
+ [
+ "name" => "Open Case",
+ "status" => "Completed",
+ "label" => "Open Case",
+ "default_assignee_type" => "1",
+ ],
+ ],
+ "caseRoles" => [
+ [
+ "name" => "Case Coordinator",
+ "creator" => "1",
+ "manager" => "1",
+ ],
+ ],
+ ],
+ ];
+ $case_type_id = $this->callAPISuccess('CaseType', 'create', $params)['id'];
+ }
+
+ // Create a case with Contact #3 as the client.
+ $case_id = civicrm_api3('case', 'get', ['subject' => 'test case 1'])['id'] ?? NULL;
+ if (!$case_id) {
+ // Create case
+ $params = [
+ 'subject' => 'test case 1',
+ 'contact_id' => 3,
+ 'status_id' => 'Open',
+ 'case_type_id' => $case_type_id,
+ 'creator_id' => 3,
+ ];
+ $case_id = $this->callAPISuccess('case', 'create', $params)['id'];
+ }
+
+ // Create a scheduled 'Meeting' activity that belongs to this case, but is
+ // assigned to contact #9
+ $activity_id = $this->callAPISuccess('Activity', 'create', [
+ 'activity_type_id' => 'Meeting',
+ 'status_id' => 'Scheduled',
+ 'case_id' => $case_id,
+ 'source_contact_id' => 3,
+ 'assignee_id' => [9],
+ 'subject' => 'test meeting activity',
+ ])['id'] ?? NULL;
+ }
+
+ /**
+ * Change setting, and the cache of it.
+ */
+ protected function setShowCaseActivitiesInCore(bool $val) {
+ Civi::settings()->set('civicaseShowCaseActivities', $val ? 1 : 0);
+ CRM_Core_Component::getEnabledComponents();
+ Civi::$statics['CRM_Core_Component']['info']['CiviCase']->info['showActivitiesInCore'] = $val;
+ }
+
}
'name' => 'source_contact',
'sort' => 'source_contact',
'direction' => 4,
- 'title' => 'Added By',
+ 'title' => 'Added by',
],
5 => [
'name' => 'activity_status',
}
}
+ /**
+ * This is similar to testGetCaseReport but test with a timeline that
+ * does have Meeting in it.
+ */
+ public function testGetCaseReportWithMeetingInTimeline() {
+ $client_id = $this->individualCreate([
+ 'first_name' => 'Casey',
+ 'middle_name' => '',
+ 'last_name' => 'Reportee',
+ 'prefix_id' => NULL,
+ 'suffix_id' => NULL,
+ ]);
+ $caseObj = $this->createCase($client_id, $this->_loggedInUser);
+ $case_id = $caseObj->id;
+
+ // Now update the timeline so it has Meeting in it.
+ $this->addMeetingToTimeline();
+
+ // Add a meeting activity to the case.
+ $meetingTypeId = $this->callAPISuccess('OptionValue', 'getsingle', [
+ 'return' => ["value"],
+ 'option_group_id' => 'activity_type',
+ 'name' => 'Meeting',
+ ]);
+ $this->callAPISuccess('activity', 'create', [
+ 'case_id' => $case_id,
+ 'activity_type_id' => $meetingTypeId['value'],
+ 'activity_date_time' => '20191114123456',
+ 'subject' => 'Test Meeting',
+ 'source_contact_id' => $this->_loggedInUser,
+ 'target_contact_id' => $client_id,
+ ]);
+
+ $caseReportParams = [
+ 'is_redact' => FALSE,
+ 'include_activities' => 1,
+ ];
+
+ // run the thing we're testing and get the output vars
+ $template = CRM_Case_XMLProcessor_Report::populateCaseReportTemplate($client_id, $case_id, 'standard_timeline', $caseReportParams, $this->report);
+ $assigned_vars = $template->get_template_vars();
+
+ // We don't want to run all the data in the dataprovider but we know
+ // in this case it should be the same as the second one in the
+ // dataprovider so we can reuse it.
+ $expected = $this->caseReportDataProvider()[1][1];
+ $this->updateExpectedBecauseDataProviderEvaluatesBeforeEverything($expected, $client_id, $case_id);
+
+ foreach ($expected as $key => $value) {
+ // does the assigned template var match the expected value?
+ $this->assertEquals($value, $assigned_vars[$key], "$key does not match" . print_r($assigned_vars[$key], TRUE));
+ }
+ }
+
/**
* Data provider for testGetCaseReport
* @return array
[
// activity set name
'standard_timeline',
- // some expected assigned vars of CRM_Core_Smarty template
+ // Some expected assigned vars of CRM_Core_Smarty template.
+ // In particular we shouldn't have meeting in the output since it's
+ // not in the timeline.
[
'case' => [
'clientName' => 'Casey Reportee',
[
// activity set name is blank here, meaning don't filter the activities
'',
- // some expected assigned vars of CRM_Core_Smarty template
+ // Some expected assigned vars of CRM_Core_Smarty template.
+ // In particular now we will have Meeting in the output.
[
'case' => [
'clientName' => 'Casey Reportee',
$this->callAPISuccess('CaseType', 'create', $caseType);
}
+ /**
+ * Add Meeting to the standard timeline.
+ */
+ private function addMeetingToTimeline() {
+ $caseType = $this->callAPISuccess('CaseType', 'getsingle', ['id' => $this->caseTypeId]);
+ $activityTypes = $caseType['definition']['activitySets'][0]['activityTypes'];
+ // Make a copy of the second activity type and change the type.
+ $activityType = $activityTypes[1];
+ $activityType['name'] = 'Meeting';
+ $activityType['label'] = 'Meeting';
+
+ $activityTypes[] = $activityType;
+ $caseType['definition']['activitySets'][0]['activityTypes'] = $activityTypes;
+ $this->callAPISuccess('CaseType', 'create', $caseType);
+ }
+
}
$this->assertEquals(2, $financialTrxn->N, 'Mismatch count for is payment flag.');
}
- /**
- * addPayments() method (add and edit modes of participant).
- *
- * Add Payments is part of an old, flawed, code flow.
- */
- public function testAddPayments() {
- $contribution = $this->addParticipantWithContribution();
- // Delete existing financial_trxns. This is because we are testing a code flow we
- // want to deprecate & remove & the test relies on bad data asa starting point.
- // End goal is the Order.create->Payment.create flow.
- CRM_Core_DAO::executeQuery('DELETE FROM civicrm_entity_financial_trxn WHERE entity_table = "civicrm_financial_item"');
- CRM_Contribute_BAO_Contribution::addPayments($contribution);
- $this->checkItemValues($contribution);
- }
-
/**
* checks db values for financial item
*/
$this->assertEquals('20191020000000', $formatted[$this->getCustomFieldName('date')]);
}
+ /**
+ * Test phone is included if it is part of dedupe rule.
+ *
+ * @throws \CRM_Core_Exception
+ */
+ public function testPhoneMatchOnContact() {
+ // Update existing unsupervised rule, change to general.
+ $unsupervisedRuleGroup = $this->callApiSuccess('RuleGroup', 'getsingle', [
+ 'used' => 'Unsupervised',
+ 'contact_type' => 'Individual',
+ ]);
+ $this->callApiSuccess('RuleGroup', 'create', [
+ 'id' => $unsupervisedRuleGroup['id'],
+ 'used' => 'General',
+ ]);
+
+ // Create new unsupervised rule with Phone field.
+ $ruleGroup = $this->callAPISuccess('RuleGroup', 'create', [
+ 'contact_type' => 'Individual',
+ 'threshold' => 10,
+ 'used' => 'Unsupervised',
+ 'name' => 'MatchingPhone',
+ 'title' => 'Matching Phone',
+ 'is_reserved' => 0,
+ ]);
+ $this->callAPISuccess('Rule', 'create', [
+ 'dedupe_rule_group_id' => $ruleGroup['id'],
+ 'rule_table' => 'civicrm_phone',
+ 'rule_weight' => 10,
+ 'rule_field' => 'phone_numeric',
+ ]);
+ $fields = CRM_Contribute_BAO_Contribution::importableFields();
+ $this->assertTrue(array_key_exists('phone', $fields));
+ }
+
/**
* Run the import parser.
*
--- /dev/null
+<?php
+
+/**
+ * @group headless
+ */
+class CRM_Core_FormTest extends CiviUnitTestCase {
+
+ /**
+ * Simulate opening various forms. All we're looking to do here is
+ * see if any warnings or notices come up, the equivalent of red boxes
+ * on the screen, but which are hidden when using popup forms.
+ * So no assertions required.
+ *
+ * @param string $classname
+ * @dataProvider formClassList
+ */
+ public function testOpeningForms(string $classname) {
+ $form = $this->getFormObject($classname);
+ $form->preProcess();
+ $form->buildQuickForm();
+ $form->setDefaultValues();
+ $form->assign('action', CRM_Core_Action::UPDATE);
+ $form->getTemplate()->fetch($form->getTemplateFileName());
+ }
+
+ /**
+ * Dataprovider for testOpeningForms().
+ * TODO: Add more forms! Use a descriptive array key so when it fails
+ * it will make it clearer what form it is, although you'll see the class
+ * anyway.
+ */
+ public function formClassList() {
+ return [
+ 'Add New Tag' => ['CRM_Tag_Form_Edit'],
+ ];
+ }
+
+}
/**
* Clean up after the test.
+ *
+ * @throws \CRM_Core_Exception
*/
public function tearDown() {
/**
* Test duplicate contact retrieval with 2 email fields.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testUnsupervisedWithTwoEmailFields() {
$this->setupForGroupDedupe();
* Test that a rule set to is_reserved = 0 works.
*
* There is a different search used dependent on this variable.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testCustomRule() {
$this->setupForGroupDedupe();
/**
* Test a custom rule with a non-default field.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testCustomRuleWithAddress() {
$this->setupForGroupDedupe();
/**
* Test rule from Richard
+ *
+ * @throws \CRM_Core_Exception
*/
public function testRuleThreeContactFieldsEqualWeightWIthThresholdtheTotalSumOfAllWeight() {
$this->setupForGroupDedupe();
]);
}
$foundDupes = CRM_Dedupe_Finder::dupesInGroup($ruleGroup['id'], $this->groupID);
- $this->assertEquals(1, count($foundDupes));
+ $this->assertCount(1, $foundDupes);
}
/**
* Test a custom rule with a non-default field.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testInclusiveRule() {
$this->setupForGroupDedupe();
]);
}
$foundDupes = CRM_Dedupe_Finder::dupesInGroup($ruleGroup['id'], $this->groupID);
- $this->assertEquals(4, count($foundDupes));
+ $this->assertCount(4, $foundDupes);
CRM_Dedupe_Finder::dupes($ruleGroup['id']);
}
/**
* Test dupesByParams function.
+ *
+ * @throws \CRM_Core_Exception
*/
public function testDupesByParams() {
// make dupe checks based on based on following contact sets:
/**
* Set up a group of dedupable contacts.
+ *
+ * @throws \CRM_Core_Exception
*/
protected function setupForGroupDedupe() {
$params = [
$event = $this->eventCreate($eventParams);
}
- $contactID = $this->individualCreate();
+ $this->ids['contact']['event'] = (int) $this->individualCreate();
/** @var CRM_Event_Form_Participant $form */
$form = $this->getFormObject('CRM_Event_Form_Participant');
$form->_single = TRUE;
- $form->_contactID = $form->_contactId = $contactID;
+ $form->_contactID = $form->_contactId = $this->ids['contact']['event'];
$form->setCustomDataTypes();
$form->_eventId = $event['id'];
if (!empty($eventParams['is_monetary'])) {
* @param bool $isQuickConfig
*
* @throws \CRM_Core_Exception
- * @throws \CiviCRM_API3_Exception
*/
public function testSubmitPartialPayment($isQuickConfig) {
$mut = new CiviMailUtils($this, TRUE);
'hidden_custom' => '1',
'hidden_custom_group_count' => ['' => 1],
'custom_4_-1' => '',
- 'contact_id' => $form->_contactID,
+ 'contact_id' => $this->getContactID(),
'event_id' => $this->getEventID(),
'campaign_id' => '',
'register_date' => '2020-01-31 00:50:00',
'MAX_FILE_SIZE' => '33554432',
];
$form->submit($submitParams);
+ $this->assertPartialPaymentResult($isQuickConfig, $mut);
+ }
+
+ /**
+ * Test submitting a partially paid event registration, recording a pending contribution.
+ *
+ * This tests
+ *
+ * @dataProvider getBooleanDataProvider
+ *
+ * @param bool $isQuickConfig
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
+ public function testSubmitPendingPartiallyPaidAddPayment($isQuickConfig) {
+ $mut = new CiviMailUtils($this, TRUE);
+ $form = $this->getForm(['is_monetary' => 1]);
+ $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
+ $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
+ $submitParams = $this->getRecordContributionParams('Partially paid', $form);
+ $form->submit($submitParams);
+ $this->callAPISuccess('Payment', 'create', [
+ 'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
+ 'total_amount' => 20,
+ 'check_number' => 879,
+ 'payment_instrument_id' => $paymentInstrumentID,
+ ]);
+ $this->assertPartialPaymentResult($isQuickConfig, $mut);
+ }
+
+ /**
+ * Test submitting a partially paid event registration, recording a pending contribution.
+ *
+ * This tests
+ *
+ * @dataProvider getBooleanDataProvider
+ *
+ * @param bool $isQuickConfig
+ *
+ * @throws \CRM_Core_Exception
+ */
+ public function testSubmitPendingAddPayment($isQuickConfig) {
+ $mut = new CiviMailUtils($this, TRUE);
+ $form = $this->getForm(['is_monetary' => 1]);
+ $this->callAPISuccess('PriceSet', 'create', ['is_quick_config' => $isQuickConfig, 'id' => $this->getPriceSetID()]);
+ $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
+ $submitParams = $this->getRecordContributionParams('Pending from pay later', 'Pending');
+ // Create the pending contribution for the full amount to be paid.
+ $submitParams['total_amount'] = 1550.55;
+ $form->submit($submitParams);
+ $this->callAPISuccess('Payment', 'create', [
+ 'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
+ 'total_amount' => 20,
+ 'check_number' => 879,
+ 'payment_instrument_id' => $paymentInstrumentID,
+ ]);
+ $this->assertPartialPaymentResult($isQuickConfig, $mut, FALSE);
+ }
+
+ /**
+ * @param bool $isQuickConfig
+ * @param \CiviMailUtils $mut
+ * @param bool $isAmountPaidOnForm
+ * Was the amount paid entered on the form (if so this should be on the receipt)
+ */
+ protected function assertPartialPaymentResult($isQuickConfig, CiviMailUtils $mut, $isAmountPaidOnForm = TRUE) {
+ $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
$contribution = $this->callAPISuccessGetSingle('Contribution', []);
$expected = [
- 'contact_id' => $form->_contactID,
+ 'contact_id' => $this->getContactID(),
'total_amount' => '1550.55',
'fee_amount' => '0.00',
- 'net_amount' => '20.00',
+ 'net_amount' => '1550.55',
'contribution_source' => 'I wrote this',
'amount_level' => '',
'is_template' => '0',
$participant = $this->callAPISuccessGetSingle('Participant', []);
$this->assertAttributesEquals([
- 'contact_id' => $form->_contactID,
+ 'contact_id' => $this->getContactID(),
'event_title' => 'Annual CiviCRM meet',
'participant_fee_level' => [0 => 'big - 1'],
'participant_fee_amount' => '1550.55',
'tax_amount' => '0.00',
], $lineItem);
- $financialTrxn = $this->callAPISuccessGetSingle('FinancialTrxn', ['is_payment' => 0]);
- $this->assertAttributesEquals([
- 'to_financial_account_id' => '7',
- 'total_amount' => '1550.55',
- 'fee_amount' => '0.00',
- 'net_amount' => '1550.55',
- 'currency' => 'USD',
- 'status_id' => '1',
- 'payment_instrument_id' => $paymentInstrumentID,
- 'check_number' => '879',
- ], $financialTrxn);
-
$payment = $this->callAPISuccessGetSingle('FinancialTrxn', ['is_payment' => 1]);
$this->assertAttributesEquals([
'to_financial_account_id' => 6,
$financialItem = $this->callAPISuccessGetSingle('FinancialItem', []);
$this->assertAttributesEquals([
'description' => 'big',
- 'contact_id' => $form->_contactID,
+ 'contact_id' => $this->getContactID(),
'amount' => 1550.55,
'currency' => 'USD',
- 'status_id' => 2,
+ 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialItem', 'status_id', 'Unpaid'),
'entity_table' => 'civicrm_line_item',
'entity_id' => $lineItem['id'],
'financial_account_id' => 4,
'Annual CiviCRM meet',
'Registered Email',
$isQuickConfig ? $this->formatMoneyInput(1550.55) . ' big - 1' : 'Price Field - big',
- 'Total Paid: $ 20.00',
+ $isAmountPaidOnForm ? 'Total Paid: $ 20.00' : ' ',
'Balance: $ 1,530.55',
'Financial Type: Event Fee',
'Paid By: Check',
return (int) $this->_ids['price_field_value'][1];
}
+ /**
+ * Get the parameters for recording a contribution.
+ *
+ * @param string $participantStatus
+ * @param string $contributionStatus
+ *
+ * @return array
+ */
+ protected function getRecordContributionParams($participantStatus, $contributionStatus): array {
+ $submitParams = [
+ 'hidden_feeblock' => '1',
+ 'hidden_eventFullMsg' => '',
+ 'priceSetId' => $this->getPriceSetID(),
+ $this->getPriceFieldKey() => $this->getPriceFieldValueID(),
+ 'check_number' => '879',
+ 'record_contribution' => '1',
+ 'financial_type_id' => '4',
+ 'receive_date' => '2020-01-31 00:51:00',
+ 'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
+ 'trxn_id' => '',
+ 'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contributionStatus),
+ 'total_amount' => '20',
+ 'send_receipt' => '1',
+ 'from_email_address' => $this->getFromEmailAddress(),
+ 'receipt_text' => 'Contact the Development Department if you need to make any changes to your registration.',
+ 'hidden_custom' => '1',
+ 'hidden_custom_group_count' => ['' => 1],
+ 'custom_4_-1' => '',
+ 'contact_id' => $this->getContactID(),
+ 'event_id' => $this->getEventID(),
+ 'campaign_id' => '',
+ 'register_date' => '2020-01-31 00:50:00',
+ 'role_id' => [0 => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
+ 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'status_id', $participantStatus),
+ 'source' => 'I wrote this',
+ 'note' => 'I wrote a note',
+ 'MAX_FILE_SIZE' => '33554432',
+ ];
+ return $submitParams;
+ }
+
/**
* Get the id of the created event.
*
return $this->ids['event']['event'];
}
+ /**
+ * Get created contact ID.
+ *
+ * @return int
+ */
+ protected function getContactID(): int {
+ return $this->ids['contact']['event'];
+ }
+
}
}
}
+ public function testGetKeysByTag() {
+ $this->assertEquals([], $this->mapper->getKeysByTag('big-rock-candy-mountain'));
+ $this->assertEquals(['test.foo.bar'], $this->mapper->getKeysByTag('wakka'));
+ }
+
/**
* @param CRM_Utils_Cache_Interface $cache
* @param null $cacheKey
$basedir = rtrim($this->createTempDir('ext-'), '/');
mkdir("$basedir/weird");
mkdir("$basedir/weird/foobar");
- file_put_contents("$basedir/weird/foobar/info.xml", "<extension key='test.foo.bar' type='report'><file>oddball</file></extension>");
+ file_put_contents("$basedir/weird/foobar/info.xml", "<extension key='test.foo.bar' type='report'><file>oddball</file><tags><tag>wakka</tag></tags></extension>");
// not needed for now // file_put_contents("$basedir/weird/bar/oddball.php", "<?php\n");
$c = new CRM_Extension_Container_Basic($basedir . $appendPathGarbage, 'http://example/basedir' . $appendPathGarbage, $cache, $cacheKey);
return [$basedir, $c];
$liveProcessorID = $testProcessorID + 1;
$processors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors(['BackOffice', 'TestMode']);
- $this->markTestIncomplete('Not working yet :-(');
$this->assertEquals([$testProcessorID, 0], array_keys($processors), 'Only the test processor and the manual processor should be returned');
$processors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors(['BackOffice', 'TestMode'], [$liveProcessorID]);
$processors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors(['BackOffice', 'LiveMode'], [$liveProcessorID]);
$this->assertEquals([$liveProcessorID], array_keys($processors), 'Only the Live processor should be returned');
-
}
}
$this->assertDBNull('CRM_Member_BAO_Membership', $contactId, 'id',
'contact_id', 'Database check for deleted membership.'
);
+ $this->assertDBNull('CRM_Price_BAO_LineItem', $membershipId, 'id',
+ 'entity_id', 'Database check for deleted line item.'
+ );
$this->contactDelete($contactId);
}
--- /dev/null
+<?php
+
+/**
+ * Class CRM_Utils_Mail_FilteredPearMailerTest
+ * @group headless
+ */
+class CRM_Utils_Mail_FilteredPearMailerTest extends CiviUnitTestCase {
+
+ public function testFilter() {
+ $mock = new class() extends \Mail {
+ public $buf = [];
+
+ public function send($recipients, $headers, $body) {
+ $this->buf['recipients'] = $recipients;
+ $this->buf['headers'] = $headers;
+ $this->buf['body'] = $body;
+ return 'all the fruits in the basket';
+ }
+
+ };
+
+ $fm = new CRM_Utils_Mail_FilteredPearMailer('mock', [], $mock);
+ $fm->addFilter('1000_apple', function ($mailer, &$recipients, &$headers, &$body) {
+ $body .= ' with apples!';
+ });
+ $fm->addFilter('1000_banana', function ($mailer, &$recipients, &$headers, &$body) {
+ $headers['Banana'] = 'Cavendish';
+ });
+ $r = $fm->send(['recip'], ['Subject' => 'Fruit loops'], 'body');
+
+ $this->assertEquals('Fruit loops', $mock->buf['headers']['Subject']);
+ $this->assertEquals('Cavendish', $mock->buf['headers']['Banana']);
+ $this->assertEquals('body with apples!', $mock->buf['body']);
+ $this->assertEquals('all the fruits in the basket', $r);
+ }
+
+ public function testFilter_shortCircuit() {
+ $mock = new class() extends \Mail {
+
+ public function send($recipients, $headers, $body) {
+ return 'all the fruits in the basket';
+ }
+
+ };
+
+ $fm = new CRM_Utils_Mail_FilteredPearMailer('mock', [], $mock);
+ $fm->addFilter('1000_short_circuit', function ($mailer, &$recipients, &$headers, &$body) {
+ return 'the triumph of veggies over fruits';
+ });
+ $r = $fm->send(['recip'], ['Subject' => 'Fruit loops'], 'body');
+ $this->assertEquals('the triumph of veggies over fruits', $r);
+ }
+
+}
public function testEquals() {
$testValue = 0.01;
- for ($i = 0; $i <= 10; $i++) {
- $equalValues = CRM_Utils_Money::equals($testValue, $testValue + ($i * 0.0001), 'USD');
- $this->assertTrue($equalValues);
+ for ($i = 0; $i < 10; $i++) {
+ $equalValues = CRM_Utils_Money::equals($testValue, $testValue + ($i * 0.0005), 'USD');
+ $this->assertTrue($equalValues, 'Currency - USD' . $testValue . ' is equal to USD' . ($testValue + ($i * 0.0005)));
}
- $this->assertFalse(CRM_Utils_Money::equals($testValue, $testValue + 0.001000000001, 'USD'));
+ $this->assertFalse(CRM_Utils_Money::equals($testValue + 0.004, $testValue + 0.006, 'USD'), 'Currency - USD' . ($testValue + 0.004) . ' is different to USD' . ($testValue + 0.006));
}
/**
+++ /dev/null
-<?php
-/*
- +--------------------------------------------------------------------+
- | CiviCRM version 5 |
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2018 |
- +--------------------------------------------------------------------+
- | This file is a part of CiviCRM. |
- | |
- | CiviCRM is free software; you can copy, modify, and distribute it |
- | under the terms of the GNU Affero General Public License |
- | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
- | |
- | CiviCRM is distributed in the hope that it will be useful, but |
- | WITHOUT ANY WARRANTY; without even the implied warranty of |
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
- | See the GNU Affero General Public License for more details. |
- | |
- | You should have received a copy of the GNU Affero General Public |
- | License and the CiviCRM Licensing Exception along |
- | with this program; if not, contact CiviCRM LLC |
- | at info[AT]civicrm[DOT]org. If you have questions about the |
- | GNU Affero General Public License or the licensing of CiviCRM, |
- | see the CiviCRM license FAQ at http://civicrm.org/licensing |
- +--------------------------------------------------------------------+
- */
-
-/**
- * Trait ACL_Permission_Trait.
- *
- * Trait for working with ACLs in tests
- */
-trait CRMTraits_ACL_PermissionTrait {
-
- protected $allowedContactId = 0;
- protected $allowedContacts = [];
-
- /**
- * All results returned.
- *
- * @implements CRM_Utils_Hook::aclWhereClause
- *
- * @param string $type
- * @param array $tables
- * @param array $whereTables
- * @param int $contactID
- * @param string $where
- */
- public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
- $where = " (1) ";
- }
-
- /**
- * All but first results returned.
- *
- * @implements CRM_Utils_Hook::aclWhereClause
- *
- * @param string $type
- * @param array $tables
- * @param array $whereTables
- * @param int $contactID
- * @param string $where
- */
- public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
- $where = " contact_a.id > 1";
- }
-
- /**
- * Only specified contact returned.
- *
- * @implements CRM_Utils_Hook::aclWhereClause
- *
- * @param string $type
- * @param array $tables
- * @param array $whereTables
- * @param int $contactID
- * @param string $where
- */
- public function aclWhereOnlyOne($type, &$tables, &$whereTables, &$contactID, &$where) {
- $where = " contact_a.id = " . $this->allowedContactId;
- }
-
-}
public function testOnPrepare($onPrepare, $inputApiCall, $expectResult) {
$this->dispatcher->addListener(Events::PREPARE, [$this, $onPrepare]);
$this->kernel->registerApiProvider($this->createWidgetFrobnicateProvider());
- $result = call_user_func_array([$this->kernel, 'run'], $inputApiCall);
+ $result = call_user_func_array([$this->kernel, 'runSafe'], $inputApiCall);
$this->assertEquals($expectResult, $result['values']);
}
public function testNormalEvents() {
$this->kernel->registerApiProvider($this->createWidgetFrobnicateProvider());
- $result = $this->kernel->run('Widget', 'frobnicate', [
+ $result = $this->kernel->runSafe('Widget', 'frobnicate', [
'version' => self::MOCK_VERSION,
]);
});
$this->kernel->registerApiProvider($this->createWidgetFrobnicateProvider());
- $result = $this->kernel->run('Widget', 'frobnicate', [
+ $result = $this->kernel->runSafe('Widget', 'frobnicate', [
'version' => self::MOCK_VERSION,
]);
*/
public function testCreateRequest_EntityActionMunging($input, $expected) {
list ($inEntity, $inAction, $inVersion) = $input;
- $apiRequest = Request::create($inEntity, $inAction, ['version' => $inVersion], NULL);
+ $apiRequest = Request::create($inEntity, $inAction, ['version' => $inVersion]);
$this->assertEquals($expected, [$apiRequest['entity'], $apiRequest['action'], $apiRequest['version']]);
}
$params['version'] = 3;
$params['debug'] = 1;
$params['check_permissions'] = 1;
- $result = $this->kernel->run($entity, $action, $params);
+ $result = $this->kernel->runSafe($entity, $action, $params);
$this->assertFalse((bool) $result['is_error'], print_r([
'$entity' => $entity,
'$action' => $action,
$params['version'] = 3;
$params['debug'] = 1;
$params['check_permissions'] = 1;
- $result = $this->kernel->run($entity, $action, $params);
+ $result = $this->kernel->runSafe($entity, $action, $params);
$this->assertTrue((bool) $result['is_error'], print_r([
'$entity' => $entity,
'$action' => $action,
'check_permissions' => 1,
];
// run with permission check
- $result = $this->kernel->run('FakeFile', 'create', $params);
+ $result = $this->kernel->runSafe('FakeFile', 'create', $params);
$this->assertTrue((bool) $result['is_error'], 'Undelegated entity with check_permissions = 1 should fail');
$this->assertRegExp('/Unrecognized target entity table \(civicrm_membership\)/', $result['error_message']);
// repeat without permission check
$params['check_permissions'] = 0;
- $result = $this->kernel->run('FakeFile', 'create', $params);
+ $result = $this->kernel->runSafe('FakeFile', 'create', $params);
$this->assertFalse((bool) $result['is_error'], 'Undelegated entity with check_permissions = 0 should succeed');
}
0 => ['id' => 1, 'provider' => 'cosmo spacely'],
1 => ['id' => 5, 'provider' => 'george jetson'],
],
- // This is silly:
- 'undefined_fields' => ['entity_id', 'entity_table', 'widget_id', 'api.has_parent'],
],
],
],
$dispatcher->addSubscriber(new WhitelistSubscriber($whitelist));
$dispatcher->addSubscriber(new ChainSubscriber());
- $apiRequest['params']['debug'] = 1;
$apiRequest['params']['check_permissions'] = 'whitelist';
- $result = $kernel->run($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
+ $result = $kernel->runSafe($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
if ($expectSuccess) {
$this->assertAPISuccess($result);
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019 |
+ | Copyright CiviCRM LLC (c) 2004-2020 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
public function testExtensionGet() {
$result = $this->callAPISuccess('extension', 'get', ['options' => ['limit' => 0]]);
$testExtensionResult = $this->callAPISuccess('extension', 'get', ['key' => 'test.extension.manager.paymenttest']);
- $this->assertNotNull($result['values'][$testExtensionResult['id']]['typeInfo']);
+ $ext = $result['values'][$testExtensionResult['id']];
+ $this->assertNotNull($ext['typeInfo']);
+ $this->assertEquals(['mock'], $ext['tags']);
$this->assertTrue($result['count'] >= 6);
}
* TRUE or FALSE depending on the outcome of the authorization check
*/
public function runPermissionCheck($entity, $action, $params, $throws = FALSE) {
+ $params['version'] = 3;
$dispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$dispatcher->addSubscriber(new \Civi\API\Subscriber\PermissionCheck());
$kernel = new \Civi\API\Kernel($dispatcher);
- $apiRequest = \Civi\API\Request::create($entity, $action, $params, NULL);
+ $apiRequest = \Civi\API\Request::create($entity, $action, $params);
try {
$kernel->authorize(NULL, $apiRequest);
return TRUE;
});
$kernel->registerApiProvider($provider);
- $r1 = $kernel->run('Widget', 'get', $params);
+ $r1 = $kernel->runSafe('Widget', 'get', $params);
$this->assertEquals(count($resultIds), $r1['count']);
$this->assertEquals($resultIds, array_keys($r1['values']));
$this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('snack_id', $r1['values'])));
$this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('id', $r1['values'])));
- $r2 = $kernel->run('Widget', 'get', $params + ['sequential' => 1]);
+ $r2 = $kernel->runSafe('Widget', 'get', $params + ['sequential' => 1]);
$this->assertEquals(count($resultIds), $r2['count']);
$this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('snack_id', $r2['values'])));
$this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('id', $r2['values'])));
- $r3 = $kernel->run('Widget', 'get', $params + ['options' => ['offset' => 1, 'limit' => 2]]);
+ $r3 = $kernel->runSafe('Widget', 'get', $params + ['options' => ['offset' => 1, 'limit' => 2]]);
$slice = array_slice($resultIds, 1, 2);
$this->assertEquals(count($slice), $r3['count']);
$this->assertEquals($slice, array_values(CRM_Utils_Array::collect('snack_id', $r3['values'])));
});
$kernel->registerApiProvider($provider);
- $r1 = $kernel->run('Widget', 'get', [
+ $r1 = $kernel->runSafe('Widget', 'get', [
'version' => 3,
'snack_id' => 'b',
'return' => 'fruit',
$this->assertAPISuccess($r1);
$this->assertEquals(['b' => ['id' => 'b', 'fruit' => 'grape']], $r1['values']);
- $r2 = $kernel->run('Widget', 'get', [
+ $r2 = $kernel->runSafe('Widget', 'get', [
'version' => 3,
'snack_id' => 'b',
'return' => ['fruit', 'cheese'],
$this->assertAPISuccess($r2);
$this->assertEquals(['b' => ['id' => 'b', 'fruit' => 'grape', 'cheese' => 'cheddar']], $r2['values']);
- $r3 = $kernel->run('Widget', 'get', [
+ $r3 = $kernel->runSafe('Widget', 'get', [
'version' => 3,
'cheese' => 'cheddar',
'return' => ['fruit'],
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019 |
+ | Copyright CiviCRM LLC (c) 2004-2020 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
/**
*
* @package CRM
- * @copyright CiviCRM LLC (c) 2004-2019
+ * @copyright CiviCRM LLC (c) 2004-2020
* $Id$
*
*/
# Remove debug_print_backtrace(), which can leak system details. Put backtrace in log.
simple_replace vendor/dompdf/dompdf/lib/html5lib/TreeBuilder.php 'debug_print_backtrace();' 'CRM_Core_Error::backtrace("backTrace", TRUE);'
-
-if ! grep -q 'CRM-21395' vendor/dompdf/dompdf/src/Dompdf.php; then
- patch vendor/dompdf/dompdf/src/Dompdf.php < tools/scripts/composer/patches/dompdf_no_block_level_parent_fix.patch
-fi
done
}
-
-##############################################################################
-# Add in CiviCRM custom error message for CRM-8744.
-if ! grep -q 'CRM-8744' vendor/pear/net_smtp/Net/SMTP.php; then
- patch vendor/pear/net_smtp/Net/SMTP.php < tools/scripts/composer/patches/net-smtp-patch.txt
-fi
-if ! grep -q '@STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT' vendor/pear/net_smtp/Net/SMTP.php; then
- patch vendor/pear/net_smtp/Net/SMTP.php < tools/scripts/composer/patches/net-smtp-tls-patch.txt
-fi
-if ! grep -q 'function __construct' vendor/pear/net_smtp/Net/SMTP.php; then
- patch vendor/pear/net_smtp/Net/SMTP.php < tools/scripts/composer/patches/net-smtp-php7-patch.txt
-fi
-if grep -q '&Auth_SASL::factory' vendor/pear/net_smtp/Net/SMTP.php; then
- patch vendor/pear/net_smtp/Net/SMTP.php < tools/scripts/composer/patches/net-smtp-ref-patch.txt
-fi
-
safe_delete vendor/pear/net_smtp/{README.rst,examples,phpdoc.sh,tests}
+++ /dev/null
-diff --git a/tests/tutorial_examples.php b/tests/tutorial_examples.php
-index 3acadc3..06f1e71 100644
---- a/tests/tutorial_examples.php
-+++ b/tests/tutorial_examples.php
-@@ -1,5 +1,4 @@
- <?php
--declare(encoding="latin1");
- /**
- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
- * @version //autogentag//
-diff --git a/src/parser/interfaces/part_parser.php b/src/parser/interfaces/part_parser.php
-index a81378b..6c59e5a 100644
---- a/src/parser/interfaces/part_parser.php
-+++ b/src/parser/interfaces/part_parser.php
-@@ -168,7 +168,11 @@ abstract class ezcMailPartParser
- break;
-
- case 'text':
-- if ( ezcMailPartParser::$parseTextAttachmentsAsFiles === true )
-+ // dev/core#940 Ensure that emails are not processed as .unknown attachments by checking
-+ // for Filename or name in the content-disposition and content-type headers.
-+ if ( (ezcMailPartParser::$parseTextAttachmentsAsFiles === true) &&
-+ (preg_match('/\s*filename="?([^;"]*);?/i', $headers['Content-Disposition']) ||
-+ preg_match( '/\s*name="?([^;"]*);?/i' , $headers['Content-Type']) ) )
- {
- $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers );
- }
+++ /dev/null
-From 226061647fc7e30f99855c8b481a88f5d78f455b Mon Sep 17 00:00:00 2001
-From: Ed Preston <epreston@prestonsoft.com>
-Date: Mon, 9 Oct 2017 20:29:46 +1100
-Subject: [PATCH] Fix: Uncaught Dompdf\Exception: No block-level parent found.
- Not good
-
-Fatal error: Uncaught Dompdf\Exception: No block-level parent found.
-Not good
----
- src/Dompdf.php | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/src/Dompdf.php b/src/Dompdf.php
-index 40329063..bfb1c2b1 100644
---- a/src/Dompdf.php
-+++ b/src/Dompdf.php
-@@ -490,6 +490,16 @@ public function loadHtml($str, $encoding = 'UTF-8')
- $doc->loadHTML($str);
- $doc->encoding = $encoding;
-
-+ // Remove #text children nodes in nodes that shouldn't have #CRM-21395
-+ $tag_names = array("html", "table", "tbody", "thead", "tfoot", "tr");
-+ foreach ($tag_names as $tag_name) {
-+ $nodes = $doc->getElementsByTagName($tag_name);
-+
-+ foreach ($nodes as $node) {
-+ self::removeTextNodes($node);
-+ }
-+ }
-+
- // If some text is before the doctype, we are in quirksmode
- if (preg_match("/^(.+)<!doctype/i", ltrim($str), $matches)) {
- $quirksmode = true;
+++ /dev/null
---- SMTP.php 2017-01-15 05:19:55.000000000 +1100
-+++ SMTP.php.new 2017-05-20 09:01:52.832373840 +1000
-@@ -368,8 +368,10 @@
- return true;
- }
-
-- return PEAR::raiseError('Invalid response code received from server',
-- $this->_code, PEAR_ERROR_RETURN);
-+ // CRM-8744
-+ $errorMessage = 'Invalid response code received from SMTP server while sending email. This is often caused by a misconfiguration in Outbound Email settings. Please verify the settings at Administer CiviCRM >> Global Settings >> Outbound Email (SMTP).';
-+ return PEAR::raiseError($errorMessage, $this->_code, PEAR_ERROR_RETURN);
-+
- }
-
- /**
+++ /dev/null
---- SMTP.php 2017-05-20 11:50:53.716664059 +1000
-+++ SMTP.php.new 2017-05-20 12:38:36.271530119 +1000
-@@ -167,7 +167,7 @@
- * @access public
- * @since 1.0
- */
-- function Net_SMTP($host = null, $port = null, $localhost = null,
-+ function __construct($host = null, $port = null, $localhost = null,
- $pipelining = false, $timeout = 0, $socket_options = null)
- {
- if (isset($host)) {
+++ /dev/null
---- SMTP.php 2017-06-15 20:08:34.696988543 -0700
-+++ SMTP.php.new 2017-06-15 20:08:25.951703778 -0700
-@@ -732,7 +732,8 @@
- }
-
- $challenge = base64_decode($this->_arguments[0]);
-- $digest = &Auth_SASL::factory('digest-md5');
-+ // CRM-8597
-+ $digest = Auth_SASL::factory('digest-md5');
- $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge,
- $this->host, "smtp",
- $authz));
-@@ -784,7 +785,8 @@
- }
-
- $challenge = base64_decode($this->_arguments[0]);
-- $cram = &Auth_SASL::factory('cram-md5');
-+ // CRM-8597
-+ $cram = Auth_SASL::factory('cram-md5');
- $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
-
- if (PEAR::isError($error = $this->_put($auth_str))) {
+++ /dev/null
-diff --git a/Net/SMTP.php b/Net/SMTP.php
-index 28eae8c..8f4e92b 100644
---- a/Net/SMTP.php
-+++ b/Net/SMTP.php
-@@ -602,7 +602,17 @@
- if (PEAR::isError($result = $this->_parseResponse(220))) {
- return $result;
- }
-- if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) {
-+ if (isset($this->_socket_options['ssl']['crypto_method'])) {
-+ $crypto_method = $this->_socket_options['ssl']['crypto_method'];
-+ } else {
-+ /* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist
-+ * and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is
-+ * inconsistent across PHP versions. */
-+ $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT
-+ | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
-+ | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
-+ }
-+ if (PEAR::isError($result = $this->_socket->enableCrypto(true, $crypto_method))) {
- return $result;
- } elseif ($result !== true) {
- return PEAR::raiseError('STARTTLS failed');
index ee1ecef..ae6e2e8 100644
--- a/Mail/mail.php
+++ b/Mail/mail.php
-@@ -114,6 +114,14 @@ class Mail_mail extends Mail {
- */
- public function send($recipients, $headers, $body)
- {
-+ if (defined('CIVICRM_MAIL_LOG')) {
-+ CRM_Utils_Mail::logger($recipients, $headers, $body);
-+ // Note: "CIVICRM_MAIL_LOG_AND SEND" (space not underscore) was a typo that existed for some years, so kept here for compatibility, but it should not be used.
-+ if (!defined('CIVICRM_MAIL_LOG_AND_SEND') && !defined('CIVICRM_MAIL_LOG_AND SEND')) {
-+ return true;
-+ }
-+ }
-+
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
@@ -145,7 +153,12 @@ class Mail_mail extends Mail {
if (is_a($headerElements, 'PEAR_Error')) {
return $headerElements;
// We only use mail()'s optional fifth parameter if the additional
// parameters have been provided and we're not running in safe mode.
-diff --git a/Mail/sendmail.php b/Mail/sendmail.php
-index 7e8f804..e0300a0 100644
---- a/Mail/sendmail.php
-+++ b/Mail/sendmail.php
-@@ -132,6 +132,14 @@ class Mail_sendmail extends Mail {
- */
- public function send($recipients, $headers, $body)
- {
-+ if (defined('CIVICRM_MAIL_LOG')) {
-+ CRM_Utils_Mail::logger($recipients, $headers, $body);
-+ // Note: "CIVICRM_MAIL_LOG_AND SEND" (space not underscore) was a typo that existed for some years, so kept here for compatibility, but it should not be used.
-+ if (!defined('CIVICRM_MAIL_LOG_AND_SEND') && !defined('CIVICRM_MAIL_LOG_AND SEND')) {
-+ return true;
-+ }
-+ }
-+
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-diff --git a/Mail/smtp.php b/Mail/smtp.php
-index 5e698fe..5f057e2 100644
---- a/Mail/smtp.php
-+++ b/Mail/smtp.php
-@@ -255,6 +255,14 @@ class Mail_smtp extends Mail {
- */
- public function send($recipients, $headers, $body)
- {
-+ if (defined('CIVICRM_MAIL_LOG')) {
-+ CRM_Utils_Mail::logger($recipients, $headers, $body);
-+ // Note: "CIVICRM_MAIL_LOG_AND SEND" (space not underscore) was a typo that existed for some years, so kept here for compatibility, but it should not be used.
-+ if (!defined('CIVICRM_MAIL_LOG_AND_SEND') && !defined('CIVICRM_MAIL_LOG_AND SEND')) {
-+ return true;
-+ }
-+ }
-+
- $result = $this->send_or_fail($recipients, $headers, $body);
-
- /* If persistent connections are disabled, destroy our SMTP object. */
+++ /dev/null
---- src/Common/XMLReader.php 2019-02-24 13:35:42.895637978 +1100
-+++ src/Common/XMLReader.php 2019-02-24 11:41:29.462449569 +1100
-@@ -71,10 +71,11 @@
- */
- public function getDomFromString($content)
- {
-- libxml_disable_entity_loader(true);
-+ $originalLibXMLEntityValue = libxml_disable_entity_loader(true);
- $this->dom = new \DOMDocument();
- $this->dom->loadXML($content);
--
-+ libxml_disable_entity_loader($originalLibXMLEntityValue);
-+
- return $this->dom;
- }
-
+++ /dev/null
-From 27ee4bef48def2e3b966b6d5ff8cc8c56b1fac2c Mon Sep 17 00:00:00 2001
-From: Seamus Lee <seamuslee001@gmail.com>
-Date: Sun, 24 Feb 2019 09:06:51 +1100
-Subject: [PATCH] Ensure that entity_loader disable variable is re-set back to
- the original setting
-
----
- src/PhpWord/Shared/Html.php | 2 ++
- src/PhpWord/TemplateProcessor.php | 2 ++
- 3 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php
-index 89881822ca..f2710ea168 100644
---- a/src/PhpWord/Shared/Html.php
-+++ b/src/PhpWord/Shared/Html.php
-@@ -72,7 +72,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit
- }
-
- // Load DOM
-- libxml_disable_entity_loader(true);
-+ $orignalLibEntityLoader = libxml_disable_entity_loader(true);
- $dom = new \DOMDocument();
- $dom->preserveWhiteSpace = $preserveWhiteSpace;
- $dom->loadXML($html);
-@@ -80,6 +80,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit
- $node = $dom->getElementsByTagName('body');
-
- self::parseNode($node->item(0), $element);
-+ libxml_disable_entity_loader($orignalLibEntityLoader);
- }
-
- /**
-diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php
-index 0f685bc45b..7efc0f1ac8 100644
---- a/src/PhpWord/TemplateProcessor.php
-+++ b/src/PhpWord/TemplateProcessor.php
-@@ -170,7 +170,7 @@ protected function readPartWithRels($fileName)
- */
- protected function transformSingleXml($xml, $xsltProcessor)
- {
-- libxml_disable_entity_loader(true);
-+ $orignalLibEntityLoader = libxml_disable_entity_loader(true);
- $domDocument = new \DOMDocument();
- if (false === $domDocument->loadXML($xml)) {
- throw new Exception('Could not load the given XML document.');
-@@ -180,6 +180,7 @@ protected function transformSingleXml($xml, $xsltProcessor)
- if (false === $transformedXml) {
- throw new Exception('Could not transform the given XML document.');
- }
-+ libxml_disable_entity_loader($orignalLibEntityLoader);
-
- return $transformedXml;
- }
<?xml version="1.0" encoding="iso-8859-1" ?>
<version>
- <version_no>5.23.beta1</version_no>
+ <version_no>5.24.alpha1</version_no>
</version>