}
// CRM-11516
if ($this->_gName == 'payment_instrument' && $this->_id) {
- $defaults['financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($this->_id, 'civicrm_option_value', 'financial_account_id');
+ $defaults['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($this->_id, NULL, 'civicrm_option_value');
}
if (empty($this->_id) || !CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'color')) {
$defaults['color'] = '#ffffff';
$defaults[$testName] = $testDAO->{$field['name']};
}
}
- $defaults['financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($dao->id, 'civicrm_payment_processor', 'financial_account_id');
+ $defaults['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($dao->id, NULL, 'civicrm_payment_processor');
return $defaults;
}
* @param string $text
* @return string
*/
- private static function formatDocBlock($text) {
+ public static function formatDocBlock($text) {
+ // Normalize #leading spaces.
+ $lines = explode("\n", $text);
+ $lines = preg_replace('/^ +\*/', ' *', $lines);
+ $text = implode("\n", $lines);
+
// Get rid of comment stars
$text = str_replace(array("\n * ", "\n *\n", "\n */\n", "/**\n"), array("\n", "\n\n", '', ''), $text);
// retrieve financial account name for the payment method page
if ($gName = "payment_instrument") {
foreach ($optionValue as $key => $option) {
- $optionValue[$key]['financial_account'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($key, 'civicrm_option_value');
+ $optionValue[$key]['financial_account'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($key, NULL, 'civicrm_option_value', 'financial_account_id.name');
}
}
$this->assign('rows', $optionValue);
'PaymentProcessor',
$dao->id
);
- $paymentProcessor[$dao->id]['financialAccount'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($dao->id, 'civicrm_payment_processor');
+ $paymentProcessor[$dao->id]['financialAccount'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($dao->id, NULL, 'civicrm_payment_processor', 'financial_account_id.name');
}
$this->assign('rows', $paymentProcessor);
}
$result = array();
- list($name, $address) = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID);
-
- $receiptFrom = "$name <$address>";
+ // CRM-20308 get receiptFrom defaults see https://issues.civicrm.org/jira/browse/CRM-20308
+ $receiptFrom = self::getReceiptFrom($activityId);
$recordedActivityParams = array();
AS SELECT ca.case_id, a.id, a.activity_date_time, a.status_id, a.activity_type_id
FROM civicrm_case_activity ca
INNER JOIN civicrm_activity a ON ca.activity_id=a.id
- WHERE a.activity_date_time =
+ WHERE a.activity_date_time =
(SELECT b.activity_date_time FROM civicrm_case_activity bca
INNER JOIN civicrm_activity b ON bca.activity_id=b.id
WHERE b.activity_date_time <= DATE_ADD( NOW(), INTERVAL 14 DAY )
AS SELECT ca.case_id, a.id, a.activity_date_time, a.status_id, a.activity_type_id
FROM civicrm_case_activity ca
INNER JOIN civicrm_activity a ON ca.activity_id=a.id
- WHERE a.activity_date_time =
+ WHERE a.activity_date_time =
(SELECT b.activity_date_time FROM civicrm_case_activity bca
INNER JOIN civicrm_activity b ON bca.activity_id=b.id
WHERE b.activity_date_time >= DATE_SUB( NOW(), INTERVAL 14 DAY )
return $clauses;
}
+ /**
+ * CRM-20308: Method to get the contact id to use as from contact for email copy
+ * 1. Activity Added by Contact's email address
+ * 2. System Default From Address
+ * 3. Default Organization Contact email address
+ * 4. Logged in user
+ *
+ * @param int $activityID
+ *
+ * @return mixed $emailFromContactId
+ * @see https://issues.civicrm.org/jira/browse/CRM-20308
+ */
+ public static function getReceiptFrom($activityID) {
+ $name = $address = NULL;
+
+ if (!empty($activityID)) {
+ // There is always a 'Added by' contact for a activity,
+ // so we can safely use ActivityContact.Getvalue API
+ $sourceContactId = civicrm_api3('ActivityContact', 'getvalue', array(
+ 'activity_id' => $activityID,
+ 'record_type_id' => 'Activity Source',
+ 'return' => 'contact_id',
+ ));
+ list($name, $address) = CRM_Contact_BAO_Contact_Location::getEmailDetails($sourceContactId);
+ }
+
+ // If 'From' email address not found for Source Activity Contact then
+ // fetch the email from domain or logged in user.
+ if (empty($address)) {
+ list($name, $address) = CRM_Core_BAO_Domain::getDefaultReceiptFrom();
+ }
+
+ return "$name <$address>";
+ }
+
}
);
}
elseif (!empty($params['payment_processor'])) {
- $params['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($params['payment_processor'], 'civicrm_payment_processor', 'financial_account_id');
+ $params['to_financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($params['payment_processor'], NULL, 'civicrm_payment_processor');
$params['payment_instrument_id'] = civicrm_api3('PaymentProcessor', 'getvalue', array(
'id' => $params['payment_processor'],
'return' => 'payment_instrument_id',
* @param CRM_Core_Transaction $transaction
* @param int $recur
* @param CRM_Contribute_BAO_Contribution $contribution
- * @param bool $isRecurring
- * Duplication of param needs review. Only used by AuthorizeNetIPN
- * @param int $isFirstOrLastRecurringPayment
- * Deprecated param only used by AuthorizeNetIPN.
*
* @return array
*/
- public static function completeOrder(&$input, &$ids, $objects, $transaction, $recur, $contribution, $isRecurring, $isFirstOrLastRecurringPayment) {
+ public static function completeOrder(&$input, &$ids, $objects, $transaction, $recur, $contribution) {
$primaryContributionID = isset($contribution->id) ? $contribution->id : $objects['first_contribution']->id;
// The previous details are used when calculating line items so keep it before any code that 'does something'
if (!empty($contribution->id)) {
}
$dao->free();
- $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
- $membershipParams['membership_type_id'],
- $primaryContributionID
- );
- $dates = array_fill_keys(array('join_date', 'start_date', 'end_date'), NULL);
- if ($currentMembership) {
- /*
- * Fixed FOR CRM-4433
- * In BAO/Membership.php(renewMembership function), we skip the extend membership date and status
- * when Contribution mode is notify and membership is for renewal )
- */
- CRM_Member_BAO_Membership::fixMembershipStatusBeforeRenew($currentMembership, $changeDate);
-
- // @todo - we should pass membership_type_id instead of null here but not
- // adding as not sure of testing
- $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($membershipParams['id'],
- $changeDate, NULL, $membershipParams['num_terms']
- );
-
- $dates['join_date'] = $currentMembership['join_date'];
+ if (CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'contribution_status_id', CRM_Utils_Array::value('contribution_status_id', $input)) === 'Pending') {
+ $membershipParams['num_terms'] = 0;
}
+ else {
+ $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
+ $membershipParams['membership_type_id'],
+ $primaryContributionID
+ );
+ // @todo remove all this stuff in favour of letting the api call further down handle in
+ // (it is a duplication of what the api does).
+ $dates = array_fill_keys(array('join_date', 'start_date', 'end_date'), NULL);
+ if ($currentMembership) {
+ /*
+ * Fixed FOR CRM-4433
+ * In BAO/Membership.php(renewMembership function), we skip the extend membership date and status
+ * when Contribution mode is notify and membership is for renewal )
+ */
+ CRM_Member_BAO_Membership::fixMembershipStatusBeforeRenew($currentMembership, $changeDate);
+
+ // @todo - we should pass membership_type_id instead of null here but not
+ // adding as not sure of testing
+ $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($membershipParams['id'],
+ $changeDate, NULL, $membershipParams['num_terms']
+ );
+
+ $dates['join_date'] = $currentMembership['join_date'];
+ }
- //get the status for membership.
- $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($dates['start_date'],
- $dates['end_date'],
- $dates['join_date'],
- 'today',
- TRUE,
- $membershipParams['membership_type_id'],
- $membershipParams
- );
+ //get the status for membership.
+ $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($dates['start_date'],
+ $dates['end_date'],
+ $dates['join_date'],
+ 'today',
+ TRUE,
+ $membershipParams['membership_type_id'],
+ $membershipParams
+ );
- $membershipParams['status_id'] = CRM_Utils_Array::value('id', $calcStatus, 'New');
- //we might be renewing membership,
- //so make status override false.
- $membershipParams['is_override'] = FALSE;
+ unset($dates['end_date']);
+ $membershipParams['status_id'] = CRM_Utils_Array::value('id', $calcStatus, 'New');
+ //we might be renewing membership,
+ //so make status override false.
+ $membershipParams['is_override'] = FALSE;
+ }
//CRM-17723 - reset static $relatedContactIds array()
+ // @todo move it to Civi Statics.
$var = TRUE;
CRM_Member_BAO_Membership::createRelatedMemberships($var, $var, TRUE);
civicrm_api3('Membership', 'create', $membershipParams);
}
CRM_Core_Error::debug_log_message("Success: Database updated");
- if ($isRecurring) {
- CRM_Contribute_BAO_ContributionRecur::sendRecurringStartOrEndNotification($ids, $recur,
- $isFirstOrLastRecurringPayment);
- }
return $contributionResult;
}
$balanceTrxnParams['to_financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($contribution['financial_type_id'], 'Accounts Receivable Account is');
}
elseif (!empty($params['payment_processor'])) {
- $balanceTrxnParams['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($contribution['payment_processor'], 'civicrm_payment_processor', 'financial_account_id');
+ $balanceTrxnParams['to_financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($contribution['payment_processor'], NULL, 'civicrm_payment_processor');
}
elseif (!empty($params['payment_instrument_id'])) {
$balanceTrxnParams['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($contribution['payment_instrument_id']);
return $result;
}
- /**
- * @param int $financialTypeId
- *
- * @return array
- */
- public function getFinancialAccounts($financialTypeId) {
- $financialAccounts = array();
- CRM_Core_PseudoConstant::populate($financialAccounts,
- 'CRM_Financial_DAO_EntityFinancialAccount',
- $all = TRUE,
- $retrieve = 'financial_account_id',
- $filter = NULL,
- " entity_id = {$financialTypeId} ", NULL, 'account_relationship');
- return $financialAccounts;
- }
-
- /**
- * @param int $financialTypeId
- * @param int $relationTypeId
- *
- * @return mixed
- */
- public function getFinancialAccount($financialTypeId, $relationTypeId) {
- $financialAccounts = $this->getFinancialAccounts($financialTypeId);
- return CRM_Utils_Array::value($relationTypeId, $financialAccounts);
- }
-
public function preProcessPledge() {
//get the payment values associated with given pledge payment id OR check for payments due.
$this->_pledgeValues = array();
*
* @param int $entityId
* @param string $accountRelationType
- *
+ * @param string $entityTable
+ * @param string $returnField
* @return int
*/
- public static function getRelationalFinancialAccount($entityId, $accountRelationType) {
- $result = civicrm_api3('EntityFinancialAccount', 'get', array(
- 'return' => array("financial_account_id"),
- 'account_relationship.name' => $accountRelationType,
- 'entity_table' => 'civicrm_financial_type',
+ public static function getRelationalFinancialAccount($entityId, $accountRelationType, $entityTable = 'civicrm_financial_type', $returnField = 'financial_account_id') {
+ $params = array(
+ 'return' => array($returnField),
+ 'entity_table' => $entityTable,
'entity_id' => $entityId,
- ));
+ );
+ if ($accountRelationType) {
+ $params['account_relationship.name'] = $accountRelationType;
+ }
+ $result = civicrm_api3('EntityFinancialAccount', 'get', $params);
if (!$result['count']) {
return NULL;
}
- return $result['values'][$result['id']]['financial_account_id'];
+ return $result['values'][$result['id']][$returnField];
}
/**
$contribution->financial_type_id = $objects['contributionType']->id;
$contribution->contribution_page_id = $ids['contributionPage'];
$contribution->contribution_recur_id = $ids['contributionRecur'];
- $contribution->receive_date = $now;
+ $contribution->receive_date = $input['receive_date'];
$contribution->currency = $objects['contribution']->currency;
$contribution->payment_instrument_id = $objects['contribution']->payment_instrument_id;
$contribution->amount_level = $objects['contribution']->amount_level;
$this->checkMD5($paymentProcessorObject, $input);
+ $isFirstOrLastRecurringPayment = FALSE;
if ($input['response_code'] == 1) {
// Approved
if ($first) {
$recur->start_date = $now;
$recur->trxn_id = $recur->processor_id;
- $this->_isFirstOrLastRecurringPayment = CRM_Core_Payment::RECURRING_PAYMENT_START;
+ $isFirstOrLastRecurringPayment = CRM_Core_Payment::RECURRING_PAYMENT_START;
}
$statusName = 'In Progress';
if (($recur->installments > 0) &&
// this is the last payment
$statusName = 'Completed';
$recur->end_date = $now;
- $this->_isFirstOrLastRecurringPayment = CRM_Core_Payment::RECURRING_PAYMENT_END;
+ $isFirstOrLastRecurringPayment = CRM_Core_Payment::RECURRING_PAYMENT_END;
}
$recur->modified_date = $now;
$recur->contribution_status_id = array_search($statusName, $contributionStatus);
}
$this->completeTransaction($input, $ids, $objects, $transaction, $recur);
+
+ // Only Authorize.net does this so it is on the a.net class. If there is a need for other processors
+ // to do this we should make it available via the api, e.g as a parameter, changing the nuance
+ // from isSentReceipt to an array of which receipts to send.
+ // Note that there is site-by-site opinions on which notifications are good to send.
+ if ($isFirstOrLastRecurringPayment) {
+ CRM_Contribute_BAO_ContributionRecur::sendRecurringStartOrEndNotification($ids, $recur,
+ $isFirstOrLastRecurringPayment);
+ }
+
}
/**
$input['response_reason_text'] = $this->retrieve('x_response_reason_text', 'String', FALSE);
$input['subscription_paynum'] = $this->retrieve('x_subscription_paynum', 'Integer', FALSE, 0);
$input['trxn_id'] = $this->retrieve('x_trans_id', 'String', FALSE);
+ $input['trxn_id'] = $this->retrieve('x_trans_id', 'String', FALSE);
+ $input['receive_date'] = $this->retrieve('receive_date', 'String', FALSE, 'now');
if ($input['trxn_id']) {
$input['is_test'] = 0;
}
/**
+ * @deprecated
+ *
* Jumbled up function.
*
* The purpose of this function is to transition a pending transaction to Completed including updating any
* @param bool $recur
*/
public function completeTransaction(&$input, &$ids, &$objects, &$transaction, $recur = FALSE) {
- $isRecurring = $this->_isRecurring;
- $isFirstOrLastRecurringPayment = $this->_isFirstOrLastRecurringPayment;
$contribution = &$objects['contribution'];
- CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects, $transaction, $recur, $contribution,
- $isRecurring, $isFirstOrLastRecurringPayment);
+ CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects, $transaction, $recur, $contribution);
}
/**
CRM_Core_Session::setStatus(ts('Unbalanced transactions may be created if you delete the account of type: %1.', array(1 => $relationValues[$financialType->account_relationship])));
}
- /**
- * Get Financial Account Name.
- *
- * @param int $entityId
- *
- * @param string $entityTable
- *
- * @param string $columnName
- * Column to fetch.
- *
- * @return null|string
- */
- public static function getFinancialAccount($entityId, $entityTable, $columnName = 'name') {
- $join = $columnName == 'name' ? 'LEFT JOIN civicrm_financial_account ON civicrm_entity_financial_account.financial_account_id = civicrm_financial_account.id' : NULL;
- $query = "
-SELECT {$columnName}
-FROM civicrm_entity_financial_account
-{$join}
-WHERE entity_table = %1
-AND entity_id = %2";
-
- $params = array(
- 1 => array($entityTable, 'String'),
- 2 => array($entityId, 'Integer'),
- );
- return CRM_Core_DAO::singleValueQuery($query, $params);
- }
-
/**
* Financial Account for payment instrument.
*
);
}
+ /**
+ * Build a description of available hooks.
+ *
+ * @param \Civi\Core\CiviEventInspector $inspector
+ */
+ public static function eventDefs($inspector) {
+ $event = \Civi\Core\Event\GenericHookEvent::create(array(
+ 'inspector' => $inspector,
+ ));
+ Civi::dispatcher()->dispatch('hook_civicrm_eventDefs', $event);
+ }
+
/**
* This hook is called while preparing a profile form.
*
);
}
+ /**
+ * @param \Civi\Core\Event\GenericHookEvent $e
+ * @see \CRM_Utils_Hook::eventDefs
+ */
+ public static function hookEventDefs($e) {
+ $e->inspector->addEventClass(self::AUTHORIZE, 'Civi\API\Event\AuthorizeEvent');
+ $e->inspector->addEventClass(self::EXCEPTION, 'Civi\API\Event\ExceptionEvent');
+ $e->inspector->addEventClass(self::PREPARE, 'Civi\API\Event\PrepareEvent');
+ $e->inspector->addEventClass(self::RESOLVE, 'Civi\API\Event\ResolveEvent');
+ $e->inspector->addEventClass(self::RESPOND, 'Civi\API\Event\RespondEvent');
+ }
+
}
--- /dev/null
+<?php
+namespace Civi\Core;
+
+/**
+ * Class CiviEventInspector
+ *
+ * The event inspector is a development tool which provides metadata about events.
+ * It can be used for code-generators and documentation-generators.
+ *
+ * @code
+ * $i = new CiviEventInspector();
+ * print_r(CRM_Utils_Array::collect('name', $i->getAll()));
+ * @endCode
+ *
+ * An event definition includes these fields:
+ * - type: string, required. Ex: 'hook' or 'object'
+ * - name: string, required. Ex: 'hook_civicrm_post' or 'civi.dao.postInsert'
+ * - class: string, required. Ex: 'Civi\Core\Event\GenericHookEvent'.
+ * - signature: string, required FOR HOOKS. Ex: '$first, &$second'.
+ * - fields: array, required FOR HOOKS. List of hook parameters.
+ * - stub: ReflectionMethod, optional. An example function with docblocks/inputs.
+ *
+ * Note: The inspector is only designed for use in developer workflows, such
+ * as code-generation and inspection. It should be not called by regular
+ * runtime logic.
+ */
+class CiviEventInspector {
+
+ /**
+ * Register the default hooks defined by 'CRM_Utils_Hook'.
+ *
+ * @param \Civi\Core\Event\GenericHookEvent $e
+ * @see \CRM_Utils_Hook::eventDefs()
+ */
+ public static function findBuiltInEvents(\Civi\Core\Event\GenericHookEvent $e) {
+ $skipList = array('singleton');
+ $e->inspector->addStaticStubs('CRM_Utils_Hook', 'hook_civicrm_',
+ function ($eventDef, $method) use ($skipList) {
+ return in_array($method->name, $skipList) ? NULL : $eventDef;
+ });
+ }
+
+ /**
+ * @var array
+ * Array(string $name => array $eventDef).
+ *
+ * Ex: $eventDefs['hook_civicrm_foo']['description_html'] = 'Hello world';
+ */
+ protected $eventDefs;
+
+ /**
+ * Perform a scan to identify/describe all events.
+ *
+ * @param bool $force
+ * @return CiviEventInspector
+ */
+ public function build($force = FALSE) {
+ if ($force || $this->eventDefs === NULL) {
+ $this->eventDefs = array();
+ \CRM_Utils_Hook::eventDefs($this);
+ ksort($this->eventDefs);
+ }
+ return $this;
+ }
+
+ /**
+ * Get a list of all events.
+ *
+ * @return array
+ * Array(string $name => array $eventDef).
+ * Ex: $result['hook_civicrm_foo']['description_html'] = 'Hello world';
+ */
+ public function getAll() {
+ $this->build();
+ return $this->eventDefs;
+ }
+
+ /**
+ * Find any events that match a pattern.
+ *
+ * @param string $regex
+ * @return array
+ * Array(string $name => array $eventDef).
+ * Ex: $result['hook_civicrm_foo']['description_html'] = 'Hello world';
+ */
+ public function find($regex) {
+ $this->build();
+ return array_filter($this->eventDefs, function ($e) use ($regex) {
+ return preg_match($regex, $e['name']);
+ });
+ }
+
+ /**
+ * Get the definition of one event.
+ *
+ * @param string $name
+ * Ex: 'hook_civicrm_alterSettingsMetaData'.
+ * @return array
+ * Ex: $result['description_html'] = 'Hello world';
+ */
+ public function get($name) {
+ $this->build();
+ return $this->eventDefs[$name];
+ }
+
+ /**
+ * @param $eventDef
+ * @return bool
+ * TRUE if valid.
+ */
+ public function validate($eventDef) {
+ if (!is_array($eventDef) || empty($eventDef['name']) || !isset($eventDef['type'])) {
+ return FALSE;
+ }
+
+ if (!in_array($eventDef['type'], array('hook', 'object'))) {
+ return FALSE;
+ }
+
+ if ($eventDef['type'] === 'hook') {
+ if (!isset($eventDef['signature']) || !is_array($eventDef['fields'])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Add a new event definition.
+ *
+ * @param array $eventDef
+ * @return CiviEventInspector
+ */
+ public function add($eventDef) {
+ $name = isset($eventDef['name']) ? $eventDef['name'] : NULL;
+
+ if (!isset($eventDef['type'])) {
+ $eventDef['type'] = preg_match('/^hook_/', $eventDef['name']) ? 'hook' : 'object';
+ }
+
+ if ($eventDef['type'] === 'hook' && empty($eventDef['signature'])) {
+ $eventDef['signature'] = implode(', ', array_map(
+ function ($field) {
+ $sigil = $field['ref'] ? '&$' : '$';
+ return $sigil . $field['name'];
+ },
+ $eventDef['fields']
+ ));
+ }
+
+ if (TRUE !== $this->validate($eventDef)) {
+ throw new \CRM_Core_Exception("Failed to register event ($name). Invalid definition.");
+ }
+
+ $this->eventDefs[$name] = $eventDef;
+ return $this;
+ }
+
+ /**
+ * Scan a Symfony event class for metadata, and add it.
+ *
+ * @param string $event
+ * Ex: 'civi.api.authorize'.
+ * @param string $className
+ * Ex: 'Civi\API\Event\AuthorizeEvent'.
+ * @return CiviEventInspector
+ */
+ public function addEventClass($event, $className) {
+ $this->add(array(
+ 'name' => $event,
+ 'class' => $className,
+ ));
+ return $this;
+ }
+
+ /**
+ * Scan a class for hook stubs, and add all of them.
+ *
+ * @param string $className
+ * The name of a class which contains static stub functions.
+ * Ex: 'CRM_Utils_Hook'.
+ * @param string $prefix
+ * A prefix to apply to all hook names.
+ * Ex: 'hook_civicrm_'.
+ * @param null|callable $filter
+ * An optional function to filter/rewrite the metadata for each hook.
+ * @return CiviEventInspector
+ */
+ public function addStaticStubs($className, $prefix, $filter = NULL) {
+ $class = new \ReflectionClass($className);
+
+ foreach ($class->getMethods(\ReflectionMethod::IS_STATIC) as $method) {
+ if (!isset($method->name)) {
+ continue;
+ }
+
+ $eventDef = array(
+ 'name' => $prefix . $method->name,
+ 'description_html' => $method->getDocComment() ? \CRM_Admin_Page_APIExplorer::formatDocBlock($method->getDocComment()) : '',
+ 'fields' => array(),
+ 'class' => 'Civi\Core\Event\GenericHookEvent',
+ 'stub' => $method,
+ );
+
+ foreach ($method->getParameters() as $parameter) {
+ $eventDef['fields'][$parameter->getName()] = array(
+ 'name' => $parameter->getName(),
+ 'ref' => (bool) $parameter->isPassedByReference(),
+ // WISHLIST: 'type' => 'mixed',
+ );
+ }
+
+ if ($filter !== NULL) {
+ $eventDef = $filter($eventDef, $method);
+ if ($eventDef === NULL) {
+ continue;
+ }
+ }
+
+ $this->add($eventDef);
+ }
+
+ return $this;
+ }
+
+}
$dispatcher->addListener('hook_civicrm_post::Case', array('\Civi\CCase\Events', 'fireCaseChange'));
$dispatcher->addListener('hook_civicrm_caseChange', array('\Civi\CCase\Events', 'delegateToXmlListeners'));
$dispatcher->addListener('hook_civicrm_caseChange', array('\Civi\CCase\SequenceListener', 'onCaseChange_static'));
+ $dispatcher->addListener('hook_civicrm_eventDefs', array('\Civi\Core\CiviEventInspector', 'findBuiltInEvents'));
+ // TODO We need a better code-convention for metadata about non-hook events.
+ $dispatcher->addListener('hook_civicrm_eventDefs', array('\Civi\API\Events', 'hookEventDefs'));
+ $dispatcher->addListener('hook_civicrm_eventDefs', array('\Civi\Core\Event\SystemInstallEvent', 'hookEventDefs'));
$dispatcher->addListener('civi.dao.postInsert', array('\CRM_Core_BAO_RecurringEntity', 'triggerInsert'));
$dispatcher->addListener('civi.dao.postUpdate', array('\CRM_Core_BAO_RecurringEntity', 'triggerUpdate'));
$dispatcher->addListener('civi.dao.postDelete', array('\CRM_Core_BAO_RecurringEntity', 'triggerDelete'));
*/
const EVENT_NAME = 'civi.core.install';
+ /**
+ * @param \Civi\Core\Event\GenericHookEvent $e
+ * @see \CRM_Utils_Hook::eventDefs
+ */
+ public static function hookEventDefs($e) {
+ $e->inspector->addEventClass(self::EVENT_NAME, __CLASS__);
+ }
+
}
$input['pan_truncation'] = CRM_Utils_Array::value('pan_truncation', $params);
$transaction = new CRM_Core_Transaction();
return CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects, $transaction, !empty
- ($contribution->contribution_recur_id), $contribution,
- FALSE, FALSE);
+ ($contribution->contribution_recur_id), $contribution);
}
/**
}
}
+ /**
+ * CRM-20308: Test from email address when a 'copy of Activity' event occur
+ */
+ public function testEmailAddressOfActivityCopy() {
+ // Case 1: assert the 'From' Email Address of source Actvity Contact ID
+ // create activity with source contact ID which has email address
+ $assigneeContactId = $this->individualCreate();
+ $sourceContactParams = array(
+ 'first_name' => 'liz',
+ 'last_name' => 'hurleey',
+ 'email' => substr(sha1(rand()), 0, 7) . '@testemail.com',
+ );
+ $sourceContactID = $this->individualCreate($sourceContactParams);
+ $sourceDisplayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $sourceContactID, 'display_name');
+
+ // create an activity using API
+ $params = array(
+ 'source_contact_id' => $sourceContactID,
+ 'subject' => 'Scheduling Meeting ' . substr(sha1(rand()), 0, 4),
+ 'activity_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Meeting'),
+ 'assignee_contact_id' => array($assigneeContactId),
+ 'activity_date_time' => date('Ymd'),
+ );
+ $activity = $this->callAPISuccess('Activity', 'create', $params);
+
+ // Check that from address is in "Source-Display-Name <source-email>"
+ $formAddress = CRM_Case_BAO_Case::getReceiptFrom($activity['id']);
+ $expectedFromAddress = sprintf("%s <%s>", $sourceDisplayName, $sourceContactParams['email']);
+ $this->assertEquals($expectedFromAddress, $formAddress);
+ // ----------------------- End of Case 1 ---------------------------
+
+ // Case 2: System Default From Address
+ // but first erase the email address of existing source contact ID
+ $withoutEmailParams = array(
+ 'email' => '',
+ );
+ $sourceContactID = $this->individualCreate($withoutEmailParams);
+ $params = array(
+ 'source_contact_id' => $sourceContactID,
+ 'subject' => 'Scheduling Meeting ' . substr(sha1(rand()), 0, 4),
+ 'activity_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Meeting'),
+ 'activity_date_time' => date('Ymd'),
+ );
+ $activity = $this->callAPISuccess('Activity', 'create', $params);
+ // fetch domain info
+ $domainInfo = $this->callAPISuccess('Domain', 'getsingle', array('id' => CRM_Core_Config::domainID()));
+
+ $formAddress = CRM_Case_BAO_Case::getReceiptFrom($activity['id']);
+ if (!empty($domainInfo['from_email'])) {
+ $expectedFromAddress = sprintf("%s <%s>", $domainInfo['from_name'], $domainInfo['from_email']);
+ }
+ // Case 3: fetch default Organization Contact email address
+ elseif (!empty($domainInfo['domain_email'])) {
+ $expectedFromAddress = sprintf("%s <%s>", $domainInfo['name'], $domainInfo['domain_email']);
+ }
+ // TODO: due to unknown reason the following assertion fails on
+ // test.civicrm.org test build but works fine on local
+ // $this->assertEquals($expectedFromAddress, $formAddress);
+ // ----------------------- End of Case 2 ---------------------------
+
+ // TODO: Case 4 about checking the $formAddress on basis of logged contact ID respectively needs,
+ // to change the domain setting, which isn't straight forward in test environment
+ }
+
}
));
$this->assertEquals(2, $contribution['count']);
$this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
+ $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contribution['values'][1]['receive_date'])));
}
+ /**
+ * Test IPN response updates contribution_recur & contribution for first & second contribution
+ */
+ public function testIPNPaymentRecurSuccessSuppliedReceiveDate() {
+ $this->setupRecurringPaymentProcessorTransaction();
+ $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
+ $IPN->main();
+ $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID));
+ $this->assertEquals(1, $contribution['contribution_status_id']);
+ $this->assertEquals('6511143069', $contribution['trxn_id']);
+ // source gets set by processor
+ $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
+ $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID));
+ $this->assertEquals(5, $contributionRecur['contribution_status_id']);
+ $IPN = new CRM_Core_Payment_AuthorizeNetIPN(array_merge(array('receive_date' => '1 July 2010'), $this->getRecurSubsequentTransaction()));
+ $IPN->main();
+ $contribution = $this->callAPISuccess('contribution', 'get', array(
+ 'contribution_recur_id' => $this->_contributionRecurID,
+ 'sequential' => 1,
+ ));
+ $this->assertEquals(2, $contribution['count']);
+ $this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
+ $this->assertEquals('2010-07-01', date('Y-m-d', strtotime($contribution['values'][1]['receive_date'])));
+ }
+
+
/**
* Test IPN response updates contribution_recur & contribution for first & second contribution
*/
}
/**
- * Check method getFinancialAccount()
+ * Check method retrieve()
*/
public function testRetrieve() {
list($financialAccount, $financialType, $financialAccountType) = $this->createFinancialAccount(
$this->assertEquals($financialAccountType['financial_account_id'], $financialAccount->id, 'Verify Financial Account Id.');
}
- /**
- * Check method getFinancialAccount()
- */
- public function testGetFinancialAccount() {
- list($financialAccount, $financialType, $financialAccountType) = $this->createFinancialAccount(
- 'Asset'
- );
- $params = array(
- 'financial_account_id' => $financialAccount->id,
- 'payment_processor_type_id' => 1,
- 'domain_id' => 1,
- 'billing_mode' => 1,
- 'name' => 'paymentProcessor',
- );
- $processor = CRM_Financial_BAO_PaymentProcessor::create($params);
-
- $account = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount(
- $processor->id,
- 'civicrm_payment_processor'
- );
- $this->assertEquals($account, $financialAccount->name, 'Verify Financial Account Name');
- }
-
/**
* Check method getInstrumentFinancialAccount()
*/
--- /dev/null
+<?php
+namespace Civi\Core;
+
+/**
+ * Class CiviEventInspectorTest
+ * @group headless
+ */
+class CiviEventInspectorTest extends \CiviUnitTestCase {
+
+ public function testGet() {
+ $inspector = new CiviEventInspector();
+ $eventDef = $inspector->get('hook_civicrm_alterSettingsMetaData');
+ $this->assertEquals('hook_civicrm_alterSettingsMetaData', $eventDef['name']);
+ $this->assertEquals(array('settingsMetaData', 'domainID', 'profile'), array_keys($eventDef['fields']));
+ $this->assertEquals('hook', $eventDef['type']);
+ $this->assertNotEmpty($eventDef['description_html']);
+ $this->assertTrue($eventDef['fields']['settingsMetaData']['ref']);
+ $this->assertFalse($eventDef['fields']['domainID']['ref']);
+ $this->assertEquals('&$settingsMetaData, $domainID, $profile', $eventDef['signature']);
+ $this->assertTrue($inspector->validate($eventDef));
+ $this->assertTrue($eventDef['stub'] instanceof \ReflectionMethod);
+ $this->assertTrue($eventDef['stub']->isStatic());
+ }
+
+ public function testGetAll() {
+ $inspector = new CiviEventInspector();
+ $all = $inspector->getAll();
+ $this->assertTrue(count($all) > 1);
+ $this->assertTrue(isset($all['hook_civicrm_alterSettingsMetaData']));
+ foreach ($all as $name => $eventDef) {
+ $this->assertEquals($name, $eventDef['name']);
+ $this->assertTrue($inspector->validate($eventDef));
+ if (isset($eventDef['stub'])) {
+ $this->assertTrue($eventDef['stub'] instanceof \ReflectionMethod);
+ $this->assertTrue($eventDef['stub']->isStatic());
+ }
+ }
+ }
+
+ public function testFind() {
+ $inspector = new CiviEventInspector();
+
+ $result_a = $inspector->find('/^hook_civicrm_post/');
+ $this->assertTrue(is_array($result_a['hook_civicrm_post']));
+ $this->assertFalse(isset($result_a['hook_civicrm_pre']));
+
+ $result_b = $inspector->find('/^hook_civicrm_pre/');
+ $this->assertTrue(is_array($result_b['hook_civicrm_pre']));
+ $this->assertFalse(isset($result_b['hook_civicrm_post']));
+ }
+
+}
public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
}
+ /**
+ * @implements CRM_Utils_Hook::selectWhereClause
+ *
+ * @param string $entity
+ * @param array $clauses
+ */
+ public function selectWhereClauseHook($entity, &$clauses) {
+ if ($entity == 'Event') {
+ $clauses['event_type_id'][] = "IN (2, 3, 4)";
+ }
+ }
+
}
$this->quickCleanUpFinancialEntities();
}
+ /**
+ * CRM-20008 Tests repeattransaction creates pending membership.
+ */
+ public function testRepeatTransactionPendingMembership() {
+ list($originalContribution, $membership) = $this->setUpAutoRenewMembership();
+ $this->callAPISuccess('membership', 'create', array(
+ 'id' => $membership['id'],
+ 'end_date' => 'yesterday',
+ 'status_id' => 'Expired',
+ ));
+ $repeatedContribution = $this->callAPISuccess('contribution', 'repeattransaction', array(
+ 'contribution_recur_id' => $originalContribution['values'][1]['contribution_recur_id'],
+ 'contribution_status_id' => 'Pending',
+ 'trxn_id' => uniqid(),
+ ));
+ $membershipStatusId = $this->callAPISuccess('membership', 'getvalue', array(
+ 'id' => $membership['id'],
+ 'return' => 'status_id',
+ ));
+
+ // Let's see if the membership payments got created while we're at it.
+ $membershipPayments = $this->callAPISuccess('MembershipPayment', 'get', array(
+ 'memberhip_id' => $membership['id'],
+ ));
+ $this->assertEquals(2, $membershipPayments['count']);
+
+ $this->assertEquals('Expired', CRM_Core_PseudoConstant::getLabel('CRM_Member_BAO_Membership', 'status_id', $membershipStatusId));
+ $this->callAPISuccess('Contribution', 'completetransaction', array('id' => $repeatedContribution['id']));
+ $membership = $this->callAPISuccessGetSingle('membership', array(
+ 'id' => $membership['id'],
+ 'return' => 'status_id, end_date',
+ ));
+ $this->assertEquals('New', CRM_Core_PseudoConstant::getLabel('CRM_Member_BAO_Membership', 'status_id', $membership['status_id']));
+ $this->assertEquals(date('Y-m-d', strtotime('yesterday + 1 month')), $membership['end_date']);
+
+ $this->quickCleanUpFinancialEntities();
+ $this->contactDelete($originalContribution['values'][1]['contact_id']);
+ }
+
/**
* Test sending a mail via the API.
*/
$this->assertEquals($result['values'][$this->_eventIds[1]]['event_title'], 'Annual CiviCRM meet 2');
}
+ /**
+ * Test getLocationEvents() function invokes selectWhereClause() hook
+ */
+ public function testGetEventWithPermissionHook() {
+ $address = $this->callAPISuccess('address', 'create', array(
+ 'contact_id' => 'null',
+ 'location_type_id' => 1,
+ 'street_address' => '1234567',
+ ));
+ $params = array(
+ 'address_id' => $address['id'],
+ );
+ $result = $this->callAPISuccess('loc_block', 'create', $params);
+ $params = array(
+ 'id' => $this->_events[1]['id'],
+ 'loc_block_id' => $result['id'],
+ );
+ $this->callAPISuccess('Event', 'create', $params);
+ $result = CRM_Event_BAO_Event::getLocationEvents();
+ $this->assertEquals(1, count($result));
+
+ $this->hookClass->setHook('civicrm_selectWhereClause', array($this, 'selectWhereClauseHook'));
+ $result = CRM_Event_BAO_Event::getLocationEvents();
+ $this->assertEquals(0, count($result));
+ }
+
public function testGetEventByEventTitle() {
$params = array(