Merge pull request #18158 from mattwire/createProfileContact
[civicrm-core.git] / ext / financialacls / financialacls.php
CommitLineData
e7339d59 1<?php
2
3require_once 'financialacls.civix.php';
4// phpcs:disable
5use CRM_Financialacls_ExtensionUtil as E;
6// phpcs:enable
7
8/**
9 * Implements hook_civicrm_config().
10 *
11 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
12 */
13function financialacls_civicrm_config(&$config) {
14 _financialacls_civix_civicrm_config($config);
15}
16
af4cccf7
TO
17/**
18 * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
19 */
20function financialacls_civicrm_container($container) {
21 $dispatcherDefn = $container->getDefinition('dispatcher');
22 $container->addResource(new \Symfony\Component\Config\Resource\FileResource(__FILE__));
23 $dispatcherDefn->addMethodCall('addListener', ['civi.api4.authorizeRecord::Contribution', '_financialacls_civi_api4_authorizeContribution']);
24}
25
e7339d59 26/**
27 * Implements hook_civicrm_install().
28 *
29 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
30 */
31function financialacls_civicrm_install() {
32 _financialacls_civix_civicrm_install();
33}
34
35/**
36 * Implements hook_civicrm_postInstall().
37 *
38 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_postInstall
39 */
40function financialacls_civicrm_postInstall() {
41 _financialacls_civix_civicrm_postInstall();
42}
43
44/**
45 * Implements hook_civicrm_uninstall().
46 *
47 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_uninstall
48 */
49function financialacls_civicrm_uninstall() {
50 _financialacls_civix_civicrm_uninstall();
51}
52
53/**
54 * Implements hook_civicrm_enable().
55 *
56 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
57 */
58function financialacls_civicrm_enable() {
59 _financialacls_civix_civicrm_enable();
60}
61
62/**
63 * Implements hook_civicrm_disable().
64 *
65 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_disable
66 */
67function financialacls_civicrm_disable() {
68 _financialacls_civix_civicrm_disable();
69}
70
71/**
72 * Implements hook_civicrm_upgrade().
73 *
74 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_upgrade
75 */
76function financialacls_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
77 return _financialacls_civix_civicrm_upgrade($op, $queue);
78}
79
e7339d59 80/**
81 * Implements hook_civicrm_entityTypes().
82 *
83 * Declare entity types provided by this module.
84 *
85 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_entityTypes
86 */
87function financialacls_civicrm_entityTypes(&$entityTypes) {
88 _financialacls_civix_civicrm_entityTypes($entityTypes);
89}
90
b82fb202 91/**
92 * Intervene to prevent deletion, where permissions block it.
93 *
aeee327d 94 * @param string $op
b82fb202 95 * @param string $objectName
96 * @param int|null $id
97 * @param array $params
98 *
99 * @throws \API_Exception
100 * @throws \CRM_Core_Exception
101 */
102function financialacls_civicrm_pre($op, $objectName, $id, &$params) {
34509ae3 103 if (!financialacls_is_acl_limiting_enabled()) {
104 return;
105 }
aeee327d 106 if ($objectName === 'LineItem' && !empty($params['check_permissions'])) {
34509ae3 107 $operationMap = ['delete' => CRM_Core_Action::DELETE, 'edit' => CRM_Core_Action::UPDATE, 'create' => CRM_Core_Action::ADD];
108 CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($types, $operationMap[$op]);
109 if (empty($params['financial_type_id'])) {
110 $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_LineItem', $params['id'], 'financial_type_id');
111 }
c3f7ab62 112 if (!array_key_exists($params['financial_type_id'], $types)) {
34509ae3 113 throw new API_Exception('You do not have permission to ' . $op . ' this line item');
b82fb202 114 }
115 }
d646594f 116 if ($objectName === 'FinancialType' && !empty($params['id']) && !empty($params['name'])) {
117 $prevName = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', $params['id']);
118 if ($prevName !== $params['name']) {
119 CRM_Core_Session::setStatus(ts("Changing the name of a Financial Type will result in losing the current permissions associated with that Financial Type.
120 Before making this change you should likely note the existing permissions at Administer > Users and Permissions > Permissions (Access Control),
121 then clicking the Access Control link for your Content Management System, then noting down the permissions for 'CiviCRM: {financial type name} view', etc.
122 Then after making the change of name, reset the permissions to the way they were."), ts('Warning'), 'warning');
123 }
124 }
b82fb202 125}
126
28188a1e 127/**
128 * Implements hook_civicrm_selectWhereClause().
129 *
130 * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_selectWhereClause
131 */
132function financialacls_civicrm_selectWhereClause($entity, &$clauses) {
34509ae3 133 if (!financialacls_is_acl_limiting_enabled()) {
134 return;
135 }
2dc76e8d
MW
136
137 switch ($entity) {
138 case 'LineItem':
139 case 'MembershipType':
f4a72e8d 140 case 'ContributionRecur':
2dc76e8d
MW
141 $types = [];
142 CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($types);
143 if ($types) {
144 $clauses['financial_type_id'] = 'IN (' . implode(',', array_keys($types)) . ')';
145 }
146 else {
147 $clauses['financial_type_id'] = '= 0';
148 }
149 break;
150
28188a1e 151 }
152
153}
154
07d89c14 155/**
34509ae3 156 * Remove unpermitted options.
07d89c14 157 *
158 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_buildAmount
159 *
160 * @param string $component
161 * @param \CRM_Core_Form $form
162 * @param array $feeBlock
163 */
164function financialacls_civicrm_buildAmount($component, $form, &$feeBlock) {
34509ae3 165 if (!financialacls_is_acl_limiting_enabled()) {
166 return;
167 }
168
169 foreach ($feeBlock as $key => $value) {
170 foreach ($value['options'] as $k => $options) {
171 if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
172 unset($feeBlock[$key]['options'][$k]);
07d89c14 173 }
174 }
34509ae3 175 if (empty($feeBlock[$key]['options'])) {
176 unset($feeBlock[$key]);
177 }
07d89c14 178 }
179}
180
e9eed3db 181/**
182 * Remove unpermitted membership types from selection availability..
183 *
184 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_membershipTypeValues
185 *
186 * @param \CRM_Core_Form $form
187 * @param array $membershipTypeValues
188 */
189function financialacls_civicrm_membershipTypeValues($form, &$membershipTypeValues) {
34509ae3 190 if (!financialacls_is_acl_limiting_enabled()) {
191 return;
192 }
e9eed3db 193 $financialTypes = NULL;
194 $financialTypes = CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialTypes, CRM_Core_Action::ADD);
195 foreach ($membershipTypeValues as $id => $type) {
196 if (!isset($financialTypes[$type['financial_type_id']])) {
197 unset($membershipTypeValues[$id]);
198 }
199 }
200}
201
4e0bf3e8 202/**
203 * Add permissions.
204 *
205 * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_permission/
206 *
207 * @param array $permissions
208 */
209function financialacls_civicrm_permission(&$permissions) {
210 if (!financialacls_is_acl_limiting_enabled()) {
211 return;
212 }
213 $actions = [
214 'add' => ts('add'),
215 'view' => ts('view'),
216 'edit' => ts('edit'),
217 'delete' => ts('delete'),
218 ];
219 $financialTypes = \CRM_Contribute_BAO_Contribution::buildOptions('financial_type_id', 'validate');
220 foreach ($financialTypes as $id => $type) {
221 foreach ($actions as $action => $action_ts) {
222 $permissions[$action . ' contributions of type ' . $type] = [
223 ts("CiviCRM: %1 contributions of type %2", [1 => $action_ts, 2 => $type]),
224 ts('%1 contributions of type %2', [1 => $action_ts, 2 => $type]),
225 ];
226 }
227 }
228 $permissions['administer CiviCRM Financial Types'] = [
229 ts('CiviCRM: administer CiviCRM Financial Types'),
230 ts('Administer access to Financial Types'),
231 ];
232}
233
9cef6066 234/**
af4cccf7 235 * Listener for 'civi.api4.authorizeRecord::Contribution'
9cef6066 236 *
af4cccf7 237 * @param \Civi\Api4\Event\AuthorizeRecordEvent $e
9cef6066 238 * @throws \CRM_Core_Exception
239 */
af4cccf7 240function _financialacls_civi_api4_authorizeContribution(\Civi\Api4\Event\AuthorizeRecordEvent $e) {
9cef6066 241 if (!financialacls_is_acl_limiting_enabled()) {
242 return;
243 }
0552d667
EM
244 if ($e->getEntityName() === 'Contribution') {
245 $contributionID = $e->getRecord()['id'] ?? NULL;
246 $financialTypeID = $e->getRecord()['financial_type_id'] ?? CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionID, 'financial_type_id');
247 if (!CRM_Core_Permission::check(_financialacls_getRequiredPermission($financialTypeID, $e->getActionName()), $e->getUserID())) {
af4cccf7 248 $e->setAuthorized(FALSE);
9cef6066 249 }
0552d667
EM
250 if ($e->getActionName() === 'delete') {
251 // First check contribution financial type
252 // Now check permissioned line items & permissioned contribution
253 if (!CRM_Financial_BAO_FinancialType::checkPermissionedLineItems($contributionID, 'delete', FALSE, $e->getUserID())
254 ) {
255 $e->setAuthorized(FALSE);
256 }
257 }
9cef6066 258 }
259}
260
0552d667
EM
261/**
262 * Get the permission required to perform this action on this financial type.
263 *
264 * @param int $financialTypeID
265 * @param string $action
266 *
267 * @return string
268 */
269function _financialacls_getRequiredPermission(int $financialTypeID, string $action): string {
270 $financialType = CRM_Core_PseudoConstant::getName('CRM_Contribute_DAO_Contribution', 'financial_type_id', $financialTypeID);
271 $actionMap = [
272 'create' => 'add',
273 'update' => 'edit',
274 'delete' => 'delete',
275 ];
276 return $actionMap[$action] . ' contributions of type ' . $financialType;
277}
278
51d1f926 279/**
280 * Remove unpermitted financial types from field Options in search context.
281 *
282 * Search context is described as
283 * 'search' => "search: searchable options are returned; labels are translated.",
284 * So this is appropriate to removing the options from search screens.
285 *
286 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_fieldOptions
287 *
288 * @param string $entity
289 * @param string $field
290 * @param array $options
291 * @param array $params
292 */
293function financialacls_civicrm_fieldOptions($entity, $field, &$options, $params) {
34509ae3 294 if (!financialacls_is_acl_limiting_enabled()) {
295 return;
296 }
f4a72e8d 297 if (in_array($entity, ['Contribution', 'ContributionRecur'], TRUE) && $field === 'financial_type_id' && $params['context'] === 'search') {
51d1f926 298 $action = CRM_Core_Action::VIEW;
299 // At this stage we are only considering the view action. Code from
300 // CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes().
301 $actions = [
302 CRM_Core_Action::VIEW => 'view',
303 CRM_Core_Action::UPDATE => 'edit',
304 CRM_Core_Action::ADD => 'add',
305 CRM_Core_Action::DELETE => 'delete',
306 ];
307 $cacheKey = 'available_types_' . $action;
308 if (!isset(\Civi::$statics['CRM_Financial_BAO_FinancialType'][$cacheKey])) {
309 foreach ($options as $finTypeId => $type) {
310 if (!CRM_Core_Permission::check($actions[$action] . ' contributions of type ' . $type)) {
311 unset($options[$finTypeId]);
312 }
313 }
314 \Civi::$statics['CRM_Financial_BAO_FinancialType'][$cacheKey] = $options;
315 }
316 $options = \Civi::$statics['CRM_Financial_BAO_FinancialType'][$cacheKey];
317 }
318}
319
34509ae3 320/**
321 * Is financial acl limiting enabled.
322 *
323 * Once this extension is detangled enough to be optional this will go
324 * and the status of the extension rather than the setting will dictate.
325 *
326 * @return bool
327 */
d646594f 328function financialacls_is_acl_limiting_enabled(): bool {
34509ae3 329 return (bool) Civi::settings()->get('acl_financial_type');
330}
331
a572646e
EM
332/**
333 * Clear the statics cache when the setting is enabled or disabled.
334 *
335 * Note the setting will eventually disappear in favour of whether
336 * the extension is enabled or disabled.
337 */
338function financialacls_toggle() {
339 unset(\Civi::$statics['CRM_Financial_BAO_FinancialType']);
340}
341
e7339d59 342// --- Functions below this ship commented out. Uncomment as required. ---
343
344/**
345 * Implements hook_civicrm_preProcess().
346 *
347 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_preProcess
348 */
349//function financialacls_civicrm_preProcess($formName, &$form) {
350//
351//}
352
353/**
354 * Implements hook_civicrm_navigationMenu().
355 *
356 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_navigationMenu
357 */
358//function financialacls_civicrm_navigationMenu(&$menu) {
359// _financialacls_civix_insert_navigation_menu($menu, 'Mailings', array(
360// 'label' => E::ts('New subliminal message'),
361// 'name' => 'mailing_subliminal_message',
362// 'url' => 'civicrm/mailing/subliminal',
363// 'permission' => 'access CiviMail',
364// 'operator' => 'OR',
365// 'separator' => 0,
366// ));
367// _financialacls_civix_navigationMenu($menu);
368//}