Skip to content
Snippets Groups Projects
Commit 700cf121 authored by mattwire's avatar mattwire
Browse files

Initial commit

parents
Branches
Tags 0.1
No related merge requests found
<?php
/**
* https://civicrm.org/licensing
*/
/**
* Shared payment IPN functions that should one day be migrated to CiviCRM core
*/
trait CRM_Core_Payment_MJWIPNTrait {
/**********************
* MJW_Core_Payment_MJWIPNTrait: 20190901
* @requires MJW_Payment_Api: 20190901
*********************/
/**
* @var array Payment processor
*/
private $_paymentProcessor;
/**
* Do we send an email receipt for each contribution?
*
* @var int
*/
protected $is_email_receipt = NULL;
/**
* The recurring contribution ID associated with the transaction
* @var int
*/
protected $contribution_recur_id = NULL;
/**
* The IPN event type
* @var string
*/
protected $event_type = NULL;
/**
* Set the value of is_email_receipt to use when a new contribution is received for a recurring contribution
* If not set, we respect the value set on the ContributionRecur entity.
*
* @param int $sendReceipt The value of is_email_receipt
*/
public function setSendEmailReceipt($sendReceipt) {
switch ($sendReceipt) {
case 0:
$this->is_email_receipt = 0;
break;
case 1:
$this->is_email_receipt = 1;
break;
default:
$this->is_email_receipt = 0;
}
}
/**
* Get the value of is_email_receipt to use when a new contribution is received for a recurring contribution
* If not set, we respect the value set on the ContributionRecur entity.
*
* @return int
* @throws \CiviCRM_API3_Exception
*/
public function getSendEmailReceipt() {
if (isset($this->is_email_receipt)) {
return (int) $this->is_email_receipt;
}
if (!empty($this->contribution_recur_id)) {
$this->is_email_receipt = civicrm_api3('ContributionRecur', 'getvalue', [
'return' => "is_email_receipt",
'id' => $this->contribution_recur_id,
]);
}
return (int) $this->is_email_receipt;
}
/**
* Get the payment processor
* The $_GET['processor_id'] value is set by CRM_Core_Payment::handlePaymentMethod.
*/
protected function getPaymentProcessor() {
$paymentProcessorId = (int) CRM_Utils_Array::value('processor_id', $_GET);
if (empty($paymentProcessorId)) {
$this->exception('Failed to get payment processor id');
}
try {
$this->_paymentProcessor = \Civi\Payment\System::singleton()->getById($paymentProcessorId)->getPaymentProcessor();
}
catch(Exception $e) {
$this->exception('Failed to get payment processor');
}
}
/**
* @deprecated Use recordCancelled()
* Mark a contribution as cancelled and update related entities
*
* @param array $params [ 'id' -> contribution_id, 'payment_processor_id' -> payment_processor_id]
*
* @return bool
* @throws \CiviCRM_API3_Exception
*/
protected function canceltransaction($params) {
return $this->incompletetransaction($params, 'cancel');
}
/**
* @deprecated - Use recordFailed()
* Mark a contribution as failed and update related entities
*
* @param array $params [ 'id' -> contribution_id, 'payment_processor_id' -> payment_processor_id]
*
* @return bool
* @throws \CiviCRM_API3_Exception
*/
protected function failtransaction($params) {
return $this->incompletetransaction($params, 'fail');
}
/**
* @deprecated - Use recordXX methods
* Handler for failtransaction and canceltransaction - do not call directly
*
* @param array $params
* @param string $mode
*
* @return bool
* @throws \CiviCRM_API3_Exception
*/
protected function incompletetransaction($params, $mode) {
$requiredParams = ['id', 'payment_processor_id'];
foreach ($requiredParams as $required) {
if (!isset($params[$required])) {
$this->exception('canceltransaction: Missing mandatory parameter: ' . $required);
}
}
if (isset($params['payment_processor_id'])) {
$input['payment_processor_id'] = $params['payment_processor_id'];
}
$contribution = new CRM_Contribute_BAO_Contribution();
$contribution->id = $params['id'];
if (!$contribution->find(TRUE)) {
throw new CiviCRM_API3_Exception('A valid contribution ID is required', 'invalid_data');
}
if (!$contribution->loadRelatedObjects($input, $ids, TRUE)) {
throw new CiviCRM_API3_Exception('failed to load related objects');
}
$input['trxn_id'] = !empty($params['trxn_id']) ? $params['trxn_id'] : $contribution->trxn_id;
if (!empty($params['fee_amount'])) {
$input['fee_amount'] = $params['fee_amount'];
}
$objects['contribution'] = &$contribution;
$objects = array_merge($objects, $contribution->_relatedObjects);
$transaction = new CRM_Core_Transaction();
switch ($mode) {
case 'cancel':
return $this->cancelled($objects, $transaction);
case 'fail':
return $this->failed($objects, $transaction);
default:
throw new CiviCRM_API3_Exception('Unknown incomplete transaction type: ' . $mode);
}
}
protected function recordPending($params) {
// Nothing to do
// @todo Maybe in the future record things like the pending reason if a payment is temporarily held?
}
/**
* Record a completed (successful) contribution
* @param array $params
*
* @throws \CiviCRM_API3_Exception
*/
protected function recordCompleted($params) {
$description = 'recordCompleted';
$this->checkRequiredParams($description, ['contribution_id'], $params);
$contributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
if (!empty($params['contribution_recur_id'])) {
$this->recordRecur($params, $description, $contributionStatusID);
}
else {
$params['id'] = $params['contribution_id'];
$pendingStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
if (civicrm_api3('Contribution', 'getvalue', [
'return' => "contribution_status_id",
'id' => $params['id']
]) == $pendingStatusId) {
civicrm_api3('Contribution', 'completetransaction', $params);
}
}
}
/**
* Record a failed contribution
* @param array $params
*
* @throws \CiviCRM_API3_Exception
*/
protected function recordFailed($params) {
$description = 'recordFailed';
$this->checkRequiredParams($description, ['contribution_id'], $params);
$contributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Failed');
if (!empty($params['contribution_recur_id'])) {
$this->recordRecur($params, $description, $contributionStatusID);
}
else {
$this->recordSingle($params, $description, $contributionStatusID);
}
}
/**
* Record a cancelled contribution
* @param array $params
*
* @throws \CiviCRM_API3_Exception
*/
protected function recordCancelled($params) {
$description = 'recordCancelled';
$this->checkRequiredParams($description, ['contribution_id'], $params);
$contributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Cancelled');
if (!empty($params['contribution_recur_id'])) {
$this->recordRecur($params, $description, $contributionStatusID);
}
else {
$this->recordSingle($params, $description, $contributionStatusID);
}
}
/**
* Record a refunded contribution
* @param array $params
*
* @throws \CiviCRM_API3_Exception
*/
protected function recordRefund($params) {
$this->checkRequiredParams('recordRefund', ['contribution_id', 'total_amount'], $params);
if ($params['total_amount'] > 0) {
$params['total_amount'] = -$params['total_amount'];
}
if (empty($params['trxn_date'])) {
$params['trxn_date'] = date('YmdHis');
}
civicrm_api3('Payment', 'create', $params);
}
/**
* Check that required params are present
*
* @param string $description
* For error logs
* @param array $requiredParams
* Array of params that are required
* @param array $params
* Array of params to check
*/
protected function checkRequiredParams($description, $requiredParams, $params) {
foreach ($requiredParams as $required) {
if (!isset($params[$required])) {
$this->exception("{$description}: Missing mandatory parameter: {$required}");
}
}
}
/**
* Record a contribution against a recur (subscription)
* @param array $params
* @param string $description
* @param int $contributionStatusID
*
* @throws \CiviCRM_API3_Exception
*/
private function recordRecur($params, $description, $contributionStatusID) {
// Process as a payment in a recurring series
// We should have been passed a contribution_id, this either needs updating via completetransaction or repeating via repeattransaction
// If we've already processed it then we'll have a payment with the unique transaction ID
$this->checkRequiredParams($description, ['contribution_id', 'contribution_recur_id', 'payment_processor_transaction_id'], $params);
$matchingContributions = civicrm_api3('Mjwpayment', 'get_contribution', ['trxn_id' => $params['payment_processor_transaction_id']]);
if ($matchingContributions['count'] == 0) {
// This is a new transaction Id in a recurring series, trigger repeattransaction
// @fixme: We may need to consider handling partial payments on the same "invoice/order" (contribution)
// but for now we assume that a new "completed" transaction means a new payment
$repeatParams = [
'contribution_status_id' => $contributionStatusID,
'original_contribution_id' => $params['contribution_id'],
'contribution_recur_id' => $params['contribution_recur_id'],
'trxn_id' => $params['payment_processor_transaction_id'],
'is_email_receipt' => $this->getSendEmailReceipt(),
];
civicrm_api3('Contribution', 'repeattransaction', $repeatParams);
}
}
/**
* Record a change to a single contribution (eg. Failed/Cancelled).
*
* @param array $params
* @param string $description
* @param int $contributionStatusID
*
* @throws \CiviCRM_API3_Exception
*/
private function recordSingle($params, $description, $contributionStatusID) {
$params['id'] = $params['contribution_id'];
$params['contribution_status_id'] = $contributionStatusID;
civicrm_api3('Contribution', 'create', $params);
}
protected function recordSubscriptionCancelled($params = []) {
civicrm_api3('ContributionRecur', 'cancel', ['id' => $this->contribution_recur_id]);
}
/**
* Log and throw an IPN exception
*
* @param string $message
*/
protected function exception($message) {
$errorMessage = $this->getPaymentProcessorLabel() . ' Exception: Event: ' . $this->event_type . ' Error: ' . $message;
Civi::log()->debug($errorMessage);
http_response_code(400);
exit(1);
}
}
<?php
/**
* https://civicrm.org/licensing
*/
/**
* Shared payment functions that should one day be migrated to CiviCRM core
*/
trait CRM_Core_Payment_MJWTrait {
/**********************
* MJW_Core_Payment_MJWTrait: 20190901
*********************/
/**
* @var array params passed for payment
*/
protected $_params = [];
/**
* @var string The unique invoice/order reference from the payment processor
*/
private $paymentProcessorOrderID;
/**
* @var string The unique subscription reference from the payment processor
*/
private $paymentProcessorSubscriptionID;
/**
* Get the billing email address
*
* @param array $params
* @param int $contactId
*
* @return string|NULL
*/
protected function getBillingEmail($params, $contactId) {
$billingLocationId = CRM_Core_BAO_LocationType::getBilling();
$emailAddress = CRM_Utils_Array::value("email-{$billingLocationId}", $params,
CRM_Utils_Array::value('email-Primary', $params,
CRM_Utils_Array::value('email', $params, NULL)));
if (empty($emailAddress) && !empty($contactId)) {
// Try and retrieve an email address from Contact ID
try {
$emailAddress = civicrm_api3('Email', 'getvalue', [
'contact_id' => $contactId,
'return' => ['email'],
]);
}
catch (CiviCRM_API3_Exception $e) {
return NULL;
}
}
return $emailAddress;
}
/**
* Get the billing email address
*
* @param array $params
* @param int $contactId
*
* @return string|NULL
*/
protected function getBillingPhone($params, $contactId) {
$billingLocationId = CRM_Core_BAO_LocationType::getBilling();
$phoneNumber = CRM_Utils_Array::value("phone-{$billingLocationId}", $params,
CRM_Utils_Array::value('phone-Primary', $params,
CRM_Utils_Array::value('phone', $params, NULL)));
if (empty($phoneNumber) && !empty($contactId)) {
// Try and retrieve a phone number from Contact ID
try {
$phoneNumber = civicrm_api3('Phone', 'getvalue', [
'contact_id' => $contactId,
'return' => ['phone'],
]);
}
catch (CiviCRM_API3_Exception $e) {
return NULL;
}
}
return $phoneNumber;
}
/**
* Get the contact id
*
* @param array $params
*
* @return int ContactID
*/
protected function getContactId($params) {
// $params['contact_id'] is preferred.
// contactID is set by: membership payment workflow
// cms_contactID is set by: membership payment workflow when "on behalf of" / related contact is used.
$contactId = CRM_Utils_Array::value('contactID', $params,
CRM_Utils_Array::value('contact_id', $params,
CRM_Utils_Array::value('cms_contactID', $params,
CRM_Utils_Array::value('cid', $params, NULL
))));
if (!empty($contactId)) {
return $contactId;
}
// FIXME: Ref: https://lab.civicrm.org/extensions/stripe/issues/16
// The problem is that when registering for a paid event, civicrm does not pass in the
// contact id to the payment processor (civicrm version 5.3). So, I had to patch your
// getContactId to check the session for a contact id. It's a hack and probably should be fixed in core.
// The code below is exactly what CiviEvent does, but does not pass it through to the next function.
$session = CRM_Core_Session::singleton();
return $session->get('transaction.userID', NULL);
}
/**
* Get the contribution ID
*
* @param $params
*
* @return mixed
*/
protected function getContributionId($params) {
/*
* contributionID is set in the contribution workflow
* We do NOT have a contribution ID for event and membership payments as they are created after payment!
* See: https://github.com/civicrm/civicrm-core/pull/13763 (for events)
*/
return CRM_Utils_Array::value('contributionID', $params);
}
/**
* Get the recurring contribution ID from parameters passed in to cancelSubscription
* Historical the data passed to cancelSubscription is pretty poor and doesn't include much!
*
* @param array $params
*
* @return int|null
*/
protected function getRecurringContributionId($params) {
// Not yet passed, but could be added via core PR
$contributionRecurId = CRM_Utils_Array::value('contribution_recur_id', $params,
CRM_Utils_Array::value('contributionRecurID', $params)); // backend live contribution
if (!empty($contributionRecurId)) {
return $contributionRecurId;
}
// Not yet passed, but could be added via core PR
$contributionId = CRM_Utils_Array::value('contribution_id', $params);
try {
return civicrm_api3('Contribution', 'getvalue', ['id' => $contributionId, 'return' => 'contribution_recur_id']);
}
catch (Exception $e) {
$subscriptionId = CRM_Utils_Array::value('subscriptionId', $params);
if (!empty($subscriptionId)) {
try {
return civicrm_api3('ContributionRecur', 'getvalue', ['processor_id' => $subscriptionId, 'return' => 'id']);
}
catch (Exception $e) {
return NULL;
}
}
return NULL;
}
}
/**
*
* @param array $params ['name' => payment instrument name]
*
* @return int|null
* @throws \CiviCRM_API3_Exception
*/
public static function createPaymentInstrument($params) {
$mandatoryParams = ['name'];
foreach ($mandatoryParams as $value) {
if (empty($params[$value])) {
Civi::log()->error('createPaymentInstrument: Missing mandatory parameter: ' . $value);
return NULL;
}
}
// Create a Payment Instrument
// See if we already have this type
$paymentInstrument = civicrm_api3('OptionValue', 'get', [
'option_group_id' => "payment_instrument",
'name' => $params['name'],
]);
if (empty($paymentInstrument['count'])) {
// Otherwise create it
try {
$financialAccount = civicrm_api3('FinancialAccount', 'getsingle', [
'financial_account_type_id' => "Asset",
'name' => "Payment Processor Account",
]);
}
catch (Exception $e) {
$financialAccount = civicrm_api3('FinancialAccount', 'getsingle', [
'financial_account_type_id' => "Asset",
'name' => "Payment Processor Account",
'options' => ['limit' => 1, 'sort' => "id ASC"],
]);
}
$paymentParams = [
'option_group_id' => "payment_instrument",
'name' => $params['name'],
'description' => $params['name'],
'financial_account_id' => $financialAccount['id'],
];
$paymentInstrument = civicrm_api3('OptionValue', 'create', $paymentParams);
$paymentInstrumentId = $paymentInstrument['values'][$paymentInstrument['id']]['value'];
}
else {
$paymentInstrumentId = $paymentInstrument['id'];
}
return $paymentInstrumentId;
}
/**
* Get the error URL to "bounce" the user back to.
* @param $params
*
* @return string|null
*/
public static function getErrorUrl($params) {
// Get proper entry URL for returning on error.
if (!(array_key_exists('qfKey', $params))) {
// Probably not called from a civicrm form (e.g. webform) -
// will return error object to original api caller.
return NULL;
}
else {
$qfKey = $params['qfKey'];
$parsed_url = parse_url($params['entryURL']);
$url_path = substr($parsed_url['path'], 1);
return CRM_Utils_System::url($url_path, $parsed_url['query'] . "&_qf_Main_display=1&qfKey={$qfKey}", FALSE, NULL, FALSE);
}
}
/**
* Are we using a test processor?
*
* @return bool
*/
public function getIsTestMode() {
return isset($this->_paymentProcessor['is_test']) && $this->_paymentProcessor['is_test'] ? TRUE : FALSE;
}
/**
* Format the fields for the payment processor.
* @fixme Copied from CiviCRM Core 5.13. We should remove this when all forms submit using this function (eg updateSubscriptionBillingInfo)
*
* In order to pass fields to the payment processor in a consistent way we add some renamed
* parameters.
*
* @param array $fields
*
* @return array
*/
private function formatParamsForPaymentProcessor($fields) {
$billingLocationId = CRM_Core_BAO_LocationType::getBilling();
// also add location name to the array
$this->_params["address_name-{$billingLocationId}"] = CRM_Utils_Array::value('billing_first_name', $this->_params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $this->_params) . ' ' . CRM_Utils_Array::value('billing_last_name', $this->_params);
$this->_params["address_name-{$billingLocationId}"] = trim($this->_params["address_name-{$billingLocationId}"]);
// Add additional parameters that the payment processors are used to receiving.
if (!empty($this->_params["billing_state_province_id-{$billingLocationId}"])) {
$this->_params['state_province'] = $this->_params["state_province-{$billingLocationId}"] = $this->_params["billing_state_province-{$billingLocationId}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$billingLocationId}"]);
}
if (!empty($this->_params["billing_country_id-{$billingLocationId}"])) {
$this->_params['country'] = $this->_params["country-{$billingLocationId}"] = $this->_params["billing_country-{$billingLocationId}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$billingLocationId}"]);
}
list($hasAddressField, $addressParams) = CRM_Contribute_BAO_Contribution::getPaymentProcessorReadyAddressParams($this->_params, $billingLocationId);
if ($hasAddressField) {
$this->_params = array_merge($this->_params, $addressParams);
}
$nameFields = ['first_name', 'middle_name', 'last_name'];
foreach ($nameFields as $name) {
$fields[$name] = 1;
if (array_key_exists("billing_$name", $this->_params)) {
$this->_params[$name] = $this->_params["billing_{$name}"];
$this->_params['preserveDBName'] = TRUE;
}
}
return $fields;
}
/**
* Called at the beginning of each payment related function (doPayment, updateSubscription etc)
*
* @param array $params
*
* @return array
*/
private function setParams($params) {
$params['error_url'] = self::getErrorUrl($params);
$params = $this->formatParamsForPaymentProcessor($params);
$newParams = $params;
CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $newParams);
foreach ($newParams as $field => $value) {
$this->setParam($field, $value);
}
return $newParams;
}
/**
* Get the value of a field if set.
*
* @param string $field
* The field.
*
* @return mixed
* value of the field, or empty string if the field is
* not set
*/
private function getParam($field) {
return CRM_Utils_Array::value($field, $this->_params, '');
}
/**
* Set a field to the specified value. Value must be a scalar (int,
* float, string, or boolean)
*
* @param string $field
* @param mixed $value
*
* @return bool
* false if value is not a scalar, true if successful
*/
private function setParam($field, $value) {
if (!is_scalar($value)) {
return FALSE;
}
else {
$this->_params[$field] = $value;
}
}
/**
* Handle an error and notify the user
*
* @param string $errorCode
* @param string $errorMessage
* @param string $bounceURL
*
* @return string $errorMessage
* (or statusbounce if URL is specified)
*/
private function handleError($errorCode = NULL, $errorMessage = NULL, $bounceURL = NULL) {
$errorCode = empty($errorCode) ? '' : $errorCode . ': ';
$errorMessage = empty($errorMessage) ? 'Unknown System Error.' : $errorMessage;
$message = $errorCode . $errorMessage;
Civi::log()->debug($this->getPaymentTypeLabel() . ' Payment Error: ' . $message);
if ($bounceURL) {
CRM_Core_Error::statusBounce($message, $bounceURL, $this->getPaymentTypeLabel());
}
return $errorMessage;
}
/**
* Get the label for the payment processor
*
* @return string
*/
protected function getPaymentProcessorLabel() {
return $this->_paymentProcessor['name'];
}
/**
* Set the payment processor Order ID
*
* @param string $orderID
*/
protected function setPaymentProcessorOrderID($orderID) {
$this->paymentProcessorOrderID = $orderID;
}
/**
* Get the payment processor Order ID
*
* @return string
*/
protected function getPaymentProcessorOrderID() {
return $this->paymentProcessorOrderID;
}
/**
* Set the payment processor Subscription ID
*
* @param string $subscriptionID
*/
protected function setPaymentProcessorSubscriptionID($subscriptionID) {
$this->paymentProcessorSubscriptionID = $subscriptionID;
}
/**
* Get the payment processor Subscription ID
*
* @return string
*/
protected function getPaymentProcessorSubscriptionID() {
return $this->paymentProcessorSubscriptionID;
}
protected function beginDoPayment($params) {
// Set default contribution status
$params['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
$params = $this->setParams($params);
return $params;
}
/**
* Call this at the end of a call to doPayment to ensure everything is updated/returned correctly.
*
* @param array $params
* @param array $contributionParams;
* Parameters that should be saved to the contribution now instead of relying on CiviCRM to do so later
*
* @return array
* @throws \CiviCRM_API3_Exception
*/
protected function endDoPayment($params, $contributionParams) {
$contributionParams['trxn_id'] = $this->getPaymentProcessorOrderID();
if ($this->getContributionId($params)) {
$contributionParams['id'] = $this->getContributionId($params);
civicrm_api3('Contribution', 'create', $contributionParams);
unset($contributionParams['id']);
}
$params = array_merge($params, $contributionParams);
// We need to set this to ensure that contributions are set to the correct status
if (!empty($params['contribution_status_id'])) {
$params['payment_status_id'] = $params['contribution_status_id'];
}
return $params;
}
}
<?php
/**
* https://civicrm.org/licensing
*/
/**
* Class CRM_Mjwshared_Utils
*/
class CRM_Mjwshared_Utils {
/**********************
* MJW_Utils: 20190822
*********************/
/**
* Return the field ID for $fieldName custom field
*
* @param $fieldName
* @param $fieldGroup
* @param bool $fullString
*
* @return mixed
* @throws \CiviCRM_API3_Exception
*/
public static function getCustomByName($fieldName, $fieldGroup, $fullString = TRUE) {
if (!isset(Civi::$statics[__CLASS__][$fieldGroup][$fieldName])) {
$field = civicrm_api3('CustomField', 'get', array(
'custom_group_id' => $fieldGroup,
'name' => $fieldName,
));
if (!empty($field['id'])) {
Civi::$statics[__CLASS__][$fieldGroup][$fieldName]['id'] = $field['id'];
Civi::$statics[__CLASS__][$fieldGroup][$fieldName]['string'] = 'custom_' . $field['id'];
}
}
if ($fullString) {
return Civi::$statics[__CLASS__][$fieldGroup][$fieldName]['string'];
}
return Civi::$statics[__CLASS__][$fieldGroup][$fieldName]['id'];
}
}
This diff is collapsed.
# mjwshared
This extension does nothing by itself but is required by a number of other extensions developed by MJW Consulting.
The extension is licensed under [AGPL-3.0](LICENSE.txt).
## Requirements
* PHP v7.x+
* CiviCRM 5.16+
## Installation
See: https://docs.civicrm.org/sysadmin/en/latest/customize/extensions/#installing-a-new-extension
<?php
/**
* https://civicrm.org/licensing
*/
/**********************
* MJW_Payment_Api: 20190901
*********************/
/**
* @todo mjwpayment.get_contribution is a replacement for Contribution.get
* mjwpayment.get_payment is a replacement for Payment.get
* which support querying by contribution/payment trxn_id per https://github.com/civicrm/civicrm-core/pull/14748
* - These API functions should be REMOVED once core has the above PR merged and we increment the min version for the extension.
* - The change is small, but to re-implement them here we have to copy quite a lot over.
*/
/**
* Adjust Metadata for Get action.
*
* The metadata is used for setting defaults, documentation & validation.
*
* @param array $params
* Array of parameters determined by getfields.
*/
function _civicrm_api3_mjwpayment_get_contribution_spec(&$params) {
$params['contribution_test'] = [
'api.default' => 0,
'type' => CRM_Utils_Type::T_BOOLEAN,
'title' => 'Get Test Contributions?',
'api.aliases' => ['is_test'],
];
$params['financial_type_id']['api.aliases'] = ['contribution_type_id'];
$params['payment_instrument_id']['api.aliases'] = ['contribution_payment_instrument', 'payment_instrument'];
$params['contact_id'] = CRM_Utils_Array::value('contribution_contact_id', $params);
$params['contact_id']['api.aliases'] = ['contribution_contact_id'];
unset($params['contribution_contact_id']);
}
/**
* Retrieve a set of contributions.
*
* @param array $params
* Input parameters.
*
* @return array
* Array of contributions, if error an array with an error id and error message
*/
function civicrm_api3_mjwpayment_get_contribution($params) {
$contributionResult = civicrm_api3('Contribution', 'get', $params);
$foundContributions = CRM_Utils_Array::value('values', $contributionResult, []);
$contributions = [];
// If we have a trxn_id check payments for that transaction ID and also return any contributions associated with those payments
// An additional array property "payment_trxn_id" will be available containing all found trxn_ids (eg. if you did ['LIKE' => 'test124%'])
if (!empty($params['trxn_id'])) {
$payments = civicrm_api3('Payment', 'get', $params);
if (!empty($payments['count'])) {
foreach ($payments['values'] as $paymentID => $paymentValues) {
if (empty($contributions[$paymentValues['contribution_id']])) {
// Get the details of each additional contribution found via a payment
$contributions[$paymentValues['contribution_id']] = CRM_Contribute_BAO_Contribution::getValuesWithMappings(['id' => $paymentValues['contribution_id']]);
}
$contributions[$paymentValues['contribution_id']]['payment_trxn_id'][] = $paymentValues['trxn_id'];
}
}
}
foreach ($contributions as $id => $contribution) {
$softContribution = CRM_Contribute_BAO_ContributionSoft::getSoftContribution($id, TRUE);
$contributions[$id] = array_merge($contributions[$id], $softContribution);
// format soft credit for backward compatibility
_civicrm_api3_mjwpayment_format_soft_credit($contributions[$id]);
_civicrm_api3_mjwpayment_contribution_add_supported_fields($contributions[$id]);
}
foreach($foundContributions as $id => $detail) {
if (isset($contributions[$id])) {
$foundContributions[$id] = $contributions[$id];
}
}
return civicrm_api3_create_success($contributions, $params, 'Contribution', 'get');
}
/**
* This function is used to format the soft credit for backward compatibility.
*
* As of v4.4 we support multiple soft credit, so now contribution returns array with 'soft_credit' as key
* but we still return first soft credit as a part of contribution array
*
* @param $contribution
*/
function _civicrm_api3_mjwpayment_format_soft_credit(&$contribution) {
if (!empty($contribution['soft_credit'])) {
$contribution['soft_credit_to'] = $contribution['soft_credit'][1]['contact_id'];
$contribution['soft_credit_id'] = $contribution['soft_credit'][1]['soft_credit_id'];
}
}
/**
* Support for supported output variables.
*
* @param $contribution
*/
function _civicrm_api3_mjwpayment_contribution_add_supported_fields(&$contribution) {
// These are output fields that are supported in our test contract.
// Arguably we should also do the same with 'campaign_id' &
// 'source' - which are also fields being rendered with unique names.
// That seems more consistent with other api where we output the actual field names.
$outputAliases = [
'contribution_check_number' => 'check_number',
'contribution_address_id' => 'address_id',
'payment_instrument_id' => 'instrument_id',
'contribution_cancel_date' => 'cancel_date',
];
foreach ($outputAliases as $returnName => $copyTo) {
if (array_key_exists($returnName, $contribution)) {
$contribution[$copyTo] = $contribution[$returnName];
}
}
}
/**
* Adjust Metadata for Get action.
*
* The metadata is used for setting defaults, documentation & validation.
*
* @param array $params
* Array of parameters determined by getfields.
*/
function _civicrm_api3_mjwpayment_get_payment_spec(&$params) {
$params = [
'contribution_id' => [
'title' => 'Contribution ID',
'type' => CRM_Utils_Type::T_INT,
],
'entity_table' => [
'title' => 'Entity Table',
'api.default' => 'civicrm_contribution',
],
'entity_id' => [
'title' => 'Entity ID',
'type' => CRM_Utils_Type::T_INT,
'api.aliases' => ['contribution_id'],
],
'trxn_id' => [
'title' => 'Transaction ID',
'type' => CRM_Utils_Type::T_STRING,
],
];
}
/**
* Retrieve a set of financial transactions which are payments.
*
* @param array $params
* Input parameters.
*
* @return array
* Array of financial transactions which are payments, if error an array with an error id and error message
* @throws \CiviCRM_API3_Exception
*/
function civicrm_api3_mjwpayment_get_payment($params) {
$financialTrxn = [];
$limit = '';
if (isset($params['options']) && CRM_Utils_Array::value('limit', $params['options'])) {
$limit = CRM_Utils_Array::value('limit', $params['options']);
}
$params['options']['limit'] = 0;
$ftParams['is_payment'] = 1;
if ($limit) {
$ftParams['options']['limit'] = $limit;
}
if (!empty($params['trxn_id'])) {
$ftParams['trxn_id'] = $params['trxn_id'];
$financialTrxn = civicrm_api3('FinancialTrxn', 'get', $ftParams);
if (!empty($financialTrxn['count'])) {
$financialTrxnIDs = CRM_Utils_Array::collect('id', CRM_Utils_Array::value('values', $financialTrxn));
$params['financial_trxn_id'] = ['IN' => $financialTrxnIDs];
$eft = civicrm_api3('EntityFinancialTrxn', 'get', $params);
foreach ($eft['values'] as $eftID => $eftValues) {
$financialTrxn['values'][$eftValues['financial_trxn_id']]['contribution_id'] = $eftValues['entity_id'];
}
}
}
else {
$eft = civicrm_api3('EntityFinancialTrxn', 'get', $params);
if (!empty($eft['values'])) {
$eftIds = [];
foreach ($eft['values'] as $efts) {
if (empty($efts['financial_trxn_id'])) {
continue;
}
$eftIds[] = $efts['financial_trxn_id'];
$map[$efts['financial_trxn_id']] = $efts['entity_id'];
}
if (!empty($eftIds)) {
$ftParams['id'] = ['IN' => $eftIds];
$financialTrxn = civicrm_api3('FinancialTrxn', 'get', $ftParams);
foreach ($financialTrxn['values'] as &$values) {
$values['contribution_id'] = $map[$values['id']];
}
}
}
}
return civicrm_api3_create_success(CRM_Utils_Array::value('values', $financialTrxn, []), $params, 'Payment', 'get');
}
info.xml 0 → 100644
<?xml version="1.0"?>
<extension key="mjwshared" type="module">
<file>mjwshared</file>
<name>MJWShared</name>
<description>Extension containing shared code used by MJW extensions (normally copied into extension rather than linked from this one)</description>
<license>AGPL-3.0</license>
<maintainer>
<author>Matthew Wire (MJW Consulting)</author>
<email>mjw@mjwconsult.co.uk</email>
</maintainer>
<urls>
<url desc="Main Extension Page">https://github.com/mattwire/civicrm-mjwshared</url>
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2019-09-03</releaseDate>
<version>0.1</version>
<develStage>beta</develStage>
<compatibility>
<ver>5.13</ver>
</compatibility>
<civix>
<namespace>CRM/Mjwshared</namespace>
</civix>
</extension>
<?php
// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file
/**
* The ExtensionUtil class provides small stubs for accessing resources of this
* extension.
*/
class CRM_Mjwshared_ExtensionUtil {
const SHORT_NAME = "mjwshared";
const LONG_NAME = "mjwshared";
const CLASS_PREFIX = "CRM_Mjwshared";
/**
* Translate a string using the extension's domain.
*
* If the extension doesn't have a specific translation
* for the string, fallback to the default translations.
*
* @param string $text
* Canonical message text (generally en_US).
* @param array $params
* @return string
* Translated text.
* @see ts
*/
public static function ts($text, $params = array()) {
if (!array_key_exists('domain', $params)) {
$params['domain'] = array(self::LONG_NAME, NULL);
}
return ts($text, $params);
}
/**
* Get the URL of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: 'http://example.org/sites/default/ext/org.example.foo'.
* Ex: 'http://example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function url($file = NULL) {
if ($file === NULL) {
return rtrim(CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME), '/');
}
return CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME, $file);
}
/**
* Get the path of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo'.
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function path($file = NULL) {
// return CRM_Core_Resources::singleton()->getPath(self::LONG_NAME, $file);
return __DIR__ . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}
/**
* Get the name of a class within this extension.
*
* @param string $suffix
* Ex: 'Page_HelloWorld' or 'Page\\HelloWorld'.
* @return string
* Ex: 'CRM_Foo_Page_HelloWorld'.
*/
public static function findClass($suffix) {
return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix);
}
}
use CRM_Mjwshared_ExtensionUtil as E;
/**
* (Delegated) Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function _mjwshared_civix_civicrm_config(&$config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$template =& CRM_Core_Smarty::singleton();
$extRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR;
$extDir = $extRoot . 'templates';
if (is_array($template->template_dir)) {
array_unshift($template->template_dir, $extDir);
}
else {
$template->template_dir = array($extDir, $template->template_dir);
}
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
set_include_path($include_path);
}
/**
* (Delegated) Implements hook_civicrm_xmlMenu().
*
* @param $files array(string)
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function _mjwshared_civix_civicrm_xmlMenu(&$files) {
foreach (_mjwshared_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) {
$files[] = $file;
}
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function _mjwshared_civix_civicrm_install() {
_mjwshared_civix_civicrm_config();
if ($upgrader = _mjwshared_civix_upgrader()) {
$upgrader->onInstall();
}
}
/**
* Implements hook_civicrm_postInstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
*/
function _mjwshared_civix_civicrm_postInstall() {
_mjwshared_civix_civicrm_config();
if ($upgrader = _mjwshared_civix_upgrader()) {
if (is_callable(array($upgrader, 'onPostInstall'))) {
$upgrader->onPostInstall();
}
}
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function _mjwshared_civix_civicrm_uninstall() {
_mjwshared_civix_civicrm_config();
if ($upgrader = _mjwshared_civix_upgrader()) {
$upgrader->onUninstall();
}
}
/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function _mjwshared_civix_civicrm_enable() {
_mjwshared_civix_civicrm_config();
if ($upgrader = _mjwshared_civix_upgrader()) {
if (is_callable(array($upgrader, 'onEnable'))) {
$upgrader->onEnable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
* @return mixed
*/
function _mjwshared_civix_civicrm_disable() {
_mjwshared_civix_civicrm_config();
if ($upgrader = _mjwshared_civix_upgrader()) {
if (is_callable(array($upgrader, 'onDisable'))) {
$upgrader->onDisable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_upgrade().
*
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function _mjwshared_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
if ($upgrader = _mjwshared_civix_upgrader()) {
return $upgrader->onUpgrade($op, $queue);
}
}
/**
* @return CRM_Mjwshared_Upgrader
*/
function _mjwshared_civix_upgrader() {
if (!file_exists(__DIR__ . '/CRM/Mjwshared/Upgrader.php')) {
return NULL;
}
else {
return CRM_Mjwshared_Upgrader_Base::instance();
}
}
/**
* Search directory tree for files which match a glob pattern
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
*
* @param $dir string, base dir
* @param $pattern string, glob pattern, eg "*.txt"
* @return array(string)
*/
function _mjwshared_civix_find_files($dir, $pattern) {
if (is_callable(array('CRM_Utils_File', 'findFiles'))) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = array($dir);
$result = array();
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_mjwshared_civix_glob("$subdir/$pattern") as $match) {
if (!is_dir($match)) {
$result[] = $match;
}
}
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry{0} == '.') {
}
elseif (is_dir($path)) {
$todos[] = $path;
}
}
closedir($dh);
}
}
return $result;
}
/**
* (Delegated) Implements hook_civicrm_managed().
*
* Find any *.mgd.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function _mjwshared_civix_civicrm_managed(&$entities) {
$mgdFiles = _mjwshared_civix_find_files(__DIR__, '*.mgd.php');
sort($mgdFiles);
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = E::LONG_NAME;
}
if (empty($e['params']['version'])) {
$e['params']['version'] = '3';
}
$entities[] = $e;
}
}
}
/**
* (Delegated) Implements hook_civicrm_caseTypes().
*
* Find any and return any files matching "xml/case/*.xml"
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function _mjwshared_civix_civicrm_caseTypes(&$caseTypes) {
if (!is_dir(__DIR__ . '/xml/case')) {
return;
}
foreach (_mjwshared_civix_glob(__DIR__ . '/xml/case/*.xml') as $file) {
$name = preg_replace('/\.xml$/', '', basename($file));
if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) {
$errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name));
CRM_Core_Error::fatal($errorMessage);
// throw new CRM_Core_Exception($errorMessage);
}
$caseTypes[$name] = array(
'module' => E::LONG_NAME,
'name' => $name,
'file' => $file,
);
}
}
/**
* (Delegated) Implements hook_civicrm_angularModules().
*
* Find any and return any files matching "ang/*.ang.php"
*
* Note: This hook only runs in CiviCRM 4.5+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
*/
function _mjwshared_civix_civicrm_angularModules(&$angularModules) {
if (!is_dir(__DIR__ . '/ang')) {
return;
}
$files = _mjwshared_civix_glob(__DIR__ . '/ang/*.ang.php');
foreach ($files as $file) {
$name = preg_replace(':\.ang\.php$:', '', basename($file));
$module = include $file;
if (empty($module['ext'])) {
$module['ext'] = E::LONG_NAME;
}
$angularModules[$name] = $module;
}
}
/**
* Glob wrapper which is guaranteed to return an array.
*
* The documentation for glob() says, "On some systems it is impossible to
* distinguish between empty match and an error." Anecdotally, the return
* result for an empty match is sometimes array() and sometimes FALSE.
* This wrapper provides consistency.
*
* @link http://php.net/glob
* @param string $pattern
* @return array, possibly empty
*/
function _mjwshared_civix_glob($pattern) {
$result = glob($pattern);
return is_array($result) ? $result : array();
}
/**
* Inserts a navigation menu item at a given place in the hierarchy.
*
* @param array $menu - menu hierarchy
* @param string $path - path to parent of this item, e.g. 'my_extension/submenu'
* 'Mailing', or 'Administer/System Settings'
* @param array $item - the item to insert (parent/child attributes will be
* filled for you)
*/
function _mjwshared_civix_insert_navigation_menu(&$menu, $path, $item) {
// If we are done going down the path, insert menu
if (empty($path)) {
$menu[] = array(
'attributes' => array_merge(array(
'label' => CRM_Utils_Array::value('name', $item),
'active' => 1,
), $item),
);
return TRUE;
}
else {
// Find an recurse into the next level down
$found = FALSE;
$path = explode('/', $path);
$first = array_shift($path);
foreach ($menu as $key => &$entry) {
if ($entry['attributes']['name'] == $first) {
if (!isset($entry['child'])) {
$entry['child'] = array();
}
$found = _mjwshared_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item, $key);
}
}
return $found;
}
}
/**
* (Delegated) Implements hook_civicrm_navigationMenu().
*/
function _mjwshared_civix_navigationMenu(&$nodes) {
if (!is_callable(array('CRM_Core_BAO_Navigation', 'fixNavigationMenu'))) {
_mjwshared_civix_fixNavigationMenu($nodes);
}
}
/**
* Given a navigation menu, generate navIDs for any items which are
* missing them.
*/
function _mjwshared_civix_fixNavigationMenu(&$nodes) {
$maxNavID = 1;
array_walk_recursive($nodes, function($item, $key) use (&$maxNavID) {
if ($key === 'navID') {
$maxNavID = max($maxNavID, $item);
}
});
_mjwshared_civix_fixNavigationMenuItems($nodes, $maxNavID, NULL);
}
function _mjwshared_civix_fixNavigationMenuItems(&$nodes, &$maxNavID, $parentID) {
$origKeys = array_keys($nodes);
foreach ($origKeys as $origKey) {
if (!isset($nodes[$origKey]['attributes']['parentID']) && $parentID !== NULL) {
$nodes[$origKey]['attributes']['parentID'] = $parentID;
}
// If no navID, then assign navID and fix key.
if (!isset($nodes[$origKey]['attributes']['navID'])) {
$newKey = ++$maxNavID;
$nodes[$origKey]['attributes']['navID'] = $newKey;
$nodes[$newKey] = $nodes[$origKey];
unset($nodes[$origKey]);
$origKey = $newKey;
}
if (isset($nodes[$origKey]['child']) && is_array($nodes[$origKey]['child'])) {
_mjwshared_civix_fixNavigationMenuItems($nodes[$origKey]['child'], $maxNavID, $nodes[$origKey]['attributes']['navID']);
}
}
}
/**
* (Delegated) Implements hook_civicrm_alterSettingsFolders().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_alterSettingsFolders
*/
function _mjwshared_civix_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$settingsDir = __DIR__ . DIRECTORY_SEPARATOR . 'settings';
if (is_dir($settingsDir) && !in_array($settingsDir, $metaDataFolders)) {
$metaDataFolders[] = $settingsDir;
}
}
/**
* (Delegated) Implements hook_civicrm_entityTypes().
*
* Find any *.entityType.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_entityTypes
*/
function _mjwshared_civix_civicrm_entityTypes(&$entityTypes) {
$entityTypes = array_merge($entityTypes, array (
));
}
<?php
require_once 'mjwshared.civix.php';
use CRM_Mjwshared_ExtensionUtil as E;
/**
* Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function mjwshared_civicrm_config(&$config) {
_mjwshared_civix_civicrm_config($config);
}
/**
* Implements hook_civicrm_xmlMenu().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function mjwshared_civicrm_xmlMenu(&$files) {
_mjwshared_civix_civicrm_xmlMenu($files);
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function mjwshared_civicrm_install() {
_mjwshared_civix_civicrm_install();
}
/**
* Implements hook_civicrm_postInstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
*/
function mjwshared_civicrm_postInstall() {
_mjwshared_civix_civicrm_postInstall();
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function mjwshared_civicrm_uninstall() {
_mjwshared_civix_civicrm_uninstall();
}
/**
* Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function mjwshared_civicrm_enable() {
_mjwshared_civix_civicrm_enable();
}
/**
* Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
*/
function mjwshared_civicrm_disable() {
_mjwshared_civix_civicrm_disable();
}
/**
* Implements hook_civicrm_upgrade().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function mjwshared_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
return _mjwshared_civix_civicrm_upgrade($op, $queue);
}
/**
* Implements hook_civicrm_managed().
*
* Generate a list of entities to create/deactivate/delete when this module
* is installed, disabled, uninstalled.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function mjwshared_civicrm_managed(&$entities) {
_mjwshared_civix_civicrm_managed($entities);
}
/**
* Implements hook_civicrm_caseTypes().
*
* Generate a list of case-types.
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function mjwshared_civicrm_caseTypes(&$caseTypes) {
_mjwshared_civix_civicrm_caseTypes($caseTypes);
}
/**
* Implements hook_civicrm_angularModules().
*
* Generate a list of Angular modules.
*
* Note: This hook only runs in CiviCRM 4.5+. It may
* use features only available in v4.6+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
*/
function mjwshared_civicrm_angularModules(&$angularModules) {
_mjwshared_civix_civicrm_angularModules($angularModules);
}
/**
* Implements hook_civicrm_alterSettingsFolders().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_alterSettingsFolders
*/
function mjwshared_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) {
_mjwshared_civix_civicrm_alterSettingsFolders($metaDataFolders);
}
/**
* Implements hook_civicrm_entityTypes().
*
* Declare entity types provided by this module.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_entityTypes
*/
function mjwshared_civicrm_entityTypes(&$entityTypes) {
_mjwshared_civix_civicrm_entityTypes($entityTypes);
}
/**
* Implements hook_civicrm_navigationMenu().
*\/
function mjwshared_civicrm_navigationMenu(&$menu) {
$item = [
'label' => E::ts('Haystack theme settings'),
'name' => 'Haystack theme settings',
'url' => 'civicrm/admin/haystack/settings',
'permission' => 'administer CiviCRM',
'operator' => NULL,
'separator' => NULL,
];
_mjwshared_civix_insert_navigation_menu($menu, 'Administer/Customize Data and Screens', $item);
_mjwshared_civix_navigationMenu($menu);
}
*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment