3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2017
33 class CRM_Financial_BAO_FinancialType
extends CRM_Financial_DAO_FinancialType
{
36 * Static holder for the default LT.
38 static $_defaultContributionType = NULL;
40 * Static cache holder of available financial types for this session
42 static $_availableFinancialTypes = array();
44 * Static cache holder of status of ACL-FT enabled/disabled for this session
46 static $_statusACLFt = array();
51 public function __construct() {
52 parent
::__construct();
56 * Fetch object based on array of properties.
58 * @param array $params
59 * (reference ) an assoc array of name/value pairs.
60 * @param array $defaults
61 * (reference ) an assoc array to hold the flattened values.
63 * @return CRM_Contribute_BAO_ContributionType
65 public static function retrieve(&$params, &$defaults) {
66 $financialType = new CRM_Financial_DAO_FinancialType();
67 $financialType->copyValues($params);
68 if ($financialType->find(TRUE)) {
69 CRM_Core_DAO
::storeValues($financialType, $defaults);
70 return $financialType;
76 * Update the is_active flag in the db.
79 * Id of the database record.
80 * @param bool $is_active
81 * Value we want to set the is_active field.
84 * DAO object on success, null otherwise
86 public static function setIsActive($id, $is_active) {
87 return CRM_Core_DAO
::setFieldValue('CRM_Financial_DAO_FinancialType', $id, 'is_active', $is_active);
91 * Add the financial types.
93 * @param array $params
94 * Reference array contains the values submitted by the form.
96 * Reference array contains the id.
100 public static function add(&$params, &$ids = array()) {
101 if (empty($params['id'])) {
102 $params['is_active'] = CRM_Utils_Array
::value('is_active', $params, FALSE);
103 $params['is_deductible'] = CRM_Utils_Array
::value('is_deductible', $params, FALSE);
104 $params['is_reserved'] = CRM_Utils_Array
::value('is_reserved', $params, FALSE);
107 // action is taken depending upon the mode
108 $financialType = new CRM_Financial_DAO_FinancialType();
109 $financialType->copyValues($params);
110 if (!empty($ids['financialType'])) {
111 $financialType->id
= CRM_Utils_Array
::value('financialType', $ids);
112 if (self
::isACLFinancialTypeStatus()) {
113 $prevName = CRM_Core_DAO
::getFieldValue('CRM_Financial_DAO_FinancialType', $financialType->id
, 'name');
114 if ($prevName != $params['name']) {
115 CRM_Core_Session
::setStatus(ts("Changing the name of a Financial Type will result in losing the current permissions associated with that Financial Type.
116 Before making this change you should likely note the existing permissions at Administer > Users and Permissions > Permissions (Access Control),
117 then clicking the Access Control link for your Content Management System, then noting down the permissions for 'CiviCRM: {financial type name} view', etc.
118 Then after making the change of name, reset the permissions to the way they were."), ts('Warning'), 'warning');
122 $financialType->save();
124 if (empty($ids['financialType']) && empty($params['id'])) {
125 $titles = CRM_Financial_BAO_FinancialTypeAccount
::createDefaultFinancialAccounts($financialType);
126 $financialType->titles
= $titles;
128 return $financialType;
132 * Delete financial Types.
134 * @param int $financialTypeId
138 public static function del($financialTypeId) {
139 $financialType = new CRM_Financial_DAO_FinancialType();
140 $financialType->id
= $financialTypeId;
141 $financialType->find(TRUE);
142 // tables to ingore checks for financial_type_id
143 $ignoreTables = array('CRM_Financial_DAO_EntityFinancialAccount');
145 // TODO: if (!$financialType->find(true)) {
147 // ensure that we have no objects that have an FK to this financial type id TODO: that cannot be null
148 $occurrences = $financialType->findReferences();
151 foreach ($occurrences as $occurrence) {
152 $className = get_class($occurrence);
153 if (!in_array($className, $tables) && !in_array($className, $ignoreTables)) {
154 $tables[] = $className;
157 if (!empty($tables)) {
158 $message = ts('The following tables have an entry for this financial type: %1', array('%1' => implode(', ', $tables)));
161 $errors['is_error'] = 1;
162 $errors['error_message'] = $message;
167 // delete from financial Type table
168 $financialType->delete();
170 $entityFinancialType = new CRM_Financial_DAO_EntityFinancialAccount();
171 $entityFinancialType->entity_id
= $financialTypeId;
172 $entityFinancialType->entity_table
= 'civicrm_financial_type';
173 $entityFinancialType->delete();
178 * fetch financial type having relationship as Income Account is.
182 * all financial type with income account is relationship
184 public static function getIncomeFinancialType() {
186 $financialType = CRM_Contribute_PseudoConstant
::financialType();
187 $revenueFinancialType = array();
188 $relationTypeId = key(CRM_Core_PseudoConstant
::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Income Account is' "));
189 CRM_Core_PseudoConstant
::populate(
190 $revenueFinancialType,
191 'CRM_Financial_DAO_EntityFinancialAccount',
193 $retrieve = 'entity_id',
195 "account_relationship = $relationTypeId AND entity_table = 'civicrm_financial_type' "
198 foreach ($financialType as $key => $financialTypeName) {
199 if (!in_array($key, $revenueFinancialType)
200 ||
(CRM_Financial_BAO_FinancialType
::isACLFinancialTypeStatus()
201 && !CRM_Core_Permission
::check('add contributions of type ' . $financialTypeName))
203 unset($financialType[$key]);
206 return $financialType;
210 * Add permissions for financial types.
212 * @param array $permissions
213 * @param array $descriptions
217 public static function permissionedFinancialTypes(&$permissions, $descriptions) {
218 if (!self
::isACLFinancialTypeStatus()) {
221 $financialTypes = CRM_Contribute_PseudoConstant
::financialType();
222 $prefix = ts('CiviCRM') . ': ';
223 $actions = array('add', 'view', 'edit', 'delete');
224 foreach ($financialTypes as $id => $type) {
225 foreach ($actions as $action) {
227 $permissions[$action . ' contributions of type ' . $type] = array(
228 $prefix . ts($action . ' contributions of type ') . $type,
229 ts(ucfirst($action) . ' contributions of type ') . $type,
233 $permissions[$action . ' contributions of type ' . $type] = $prefix . ts($action . ' contributions of type ') . $type;
237 if (!$descriptions) {
238 $permissions['administer CiviCRM Financial Types'] = $prefix . ts('administer CiviCRM Financial Types');
241 $permissions['administer CiviCRM Financial Types'] = array(
242 $prefix . ts('administer CiviCRM Financial Types'),
243 ts('Administer access to Financial Types'),
249 * Wrapper aroung getAvailableFinancialTypes to get all including disabled FinancialTypes
250 * @param int|string $action
251 * the type of action, can be add, view, edit, delete
252 * @param bool $resetCache
253 * load values from static cache
257 public static function getAllAvailableFinancialTypes($action = CRM_Core_Action
::VIEW
, $resetCache = FALSE) {
258 // Flush pseudoconstant cache
259 CRM_Contribute_PseudoConstant
::flush('financialType');
260 $thisIsAUselessVariableButSolvesPHPError = NULL;
261 $financialTypes = self
::getAvailableFinancialTypes($thisIsAUselessVariableButSolvesPHPError, $action, $resetCache, TRUE);
262 return $financialTypes;
266 * Wrapper aroung getAvailableFinancialTypes to get all FinancialTypes Excluding Disabled ones.
267 * @param int|string $action
268 * the type of action, can be add, view, edit, delete
269 * @param bool $resetCache
270 * load values from static cache
274 public static function getAllEnabledAvailableFinancialTypes($action = CRM_Core_Action
::VIEW
, $resetCache = FALSE) {
275 $thisIsAUselessVariableButSolvesPHPError = NULL;
276 $financialTypes = self
::getAvailableFinancialTypes($thisIsAUselessVariableButSolvesPHPError, $action, $resetCache);
277 return $financialTypes;
281 * Get available Financial Types.
283 * @param array $financialTypes
284 * (reference ) an array of financial types
285 * @param int|string $action
286 * the type of action, can be add, view, edit, delete
287 * @param bool $resetCache
288 * load values from static cache
289 * @param bool $includeDisabled
290 * Whether we should load in disabled FinancialTypes or Not
294 public static function getAvailableFinancialTypes(&$financialTypes = NULL, $action = CRM_Core_Action
::VIEW
, $resetCache = FALSE, $includeDisabled = FALSE) {
295 if (empty($financialTypes)) {
296 $financialTypes = CRM_Contribute_PseudoConstant
::financialType(NULL, $includeDisabled);
298 if (!self
::isACLFinancialTypeStatus()) {
299 return $financialTypes;
302 CRM_Core_Action
::VIEW
=> 'view',
303 CRM_Core_Action
::UPDATE
=> 'edit',
304 CRM_Core_Action
::ADD
=> 'add',
305 CRM_Core_Action
::DELETE
=> 'delete',
307 // check cached value
308 if (CRM_Utils_Array
::value($action, self
::$_availableFinancialTypes) && !$resetCache) {
309 $financialTypes = self
::$_availableFinancialTypes[$action];
310 return self
::$_availableFinancialTypes[$action];
312 foreach ($financialTypes as $finTypeId => $type) {
313 if (!CRM_Core_Permission
::check($actions[$action] . ' contributions of type ' . $type)) {
314 unset($financialTypes[$finTypeId]);
317 self
::$_availableFinancialTypes[$action] = $financialTypes;
318 return $financialTypes;
322 * Get available Membership Types.
324 * @param array $membershipTypes
325 * (reference ) an array of membership types
326 * @param int|string $action
327 * the type of action, can be add, view, edit, delete
331 public static function getAvailableMembershipTypes(&$membershipTypes = NULL, $action = CRM_Core_Action
::VIEW
) {
332 if (empty($membershipTypes)) {
333 $membershipTypes = CRM_Member_PseudoConstant
::membershipType();
335 if (!self
::isACLFinancialTypeStatus()) {
336 return $membershipTypes;
339 CRM_Core_Action
::VIEW
=> 'view',
340 CRM_Core_Action
::UPDATE
=> 'edit',
341 CRM_Core_Action
::ADD
=> 'add',
342 CRM_Core_Action
::DELETE
=> 'delete',
344 foreach ($membershipTypes as $memTypeId => $type) {
345 $finTypeId = CRM_Core_DAO
::getFieldValue('CRM_Member_DAO_MembershipType', $memTypeId, 'financial_type_id');
346 $finType = CRM_Contribute_PseudoConstant
::financialType($finTypeId);
347 if (!CRM_Core_Permission
::check($actions[$action] . ' contributions of type ' . $finType)) {
348 unset($membershipTypes[$memTypeId]);
351 return $membershipTypes;
355 * Function to build a permissioned sql where clause based on available financial types.
357 * @param array $whereClauses
358 * (reference ) an array of clauses
359 * @param string $component
360 * the type of component
361 * @param string $alias
365 public static function buildPermissionedClause(&$whereClauses, $component = NULL, $alias = NULL) {
366 if (!self
::isACLFinancialTypeStatus()) {
369 if (is_array($whereClauses)) {
370 $types = self
::getAllEnabledAvailableFinancialTypes();
372 $whereClauses[] = ' ' . $alias . '.financial_type_id IN (0)';
375 $whereClauses[] = ' ' . $alias . '.financial_type_id IN (' . implode(',', array_keys($types)) . ')';
379 if ($component == 'contribution') {
380 $types = self
::getAllEnabledAvailableFinancialTypes();
381 $column = "financial_type_id";
383 if ($component == 'membership') {
384 self
::getAvailableMembershipTypes($types, CRM_Core_Action
::VIEW
);
385 $column = "membership_type_id";
387 if (!empty($whereClauses)) {
388 $whereClauses .= ' AND ';
391 $whereClauses .= " civicrm_{$component}.{$column} IN (0)";
394 $whereClauses .= " civicrm_{$component}.{$column} IN (" . implode(',', array_keys($types)) . ")";
399 * Function to check if lineitems present in a contribution have permissioned FTs.
404 * the mode of operation, can be add, view, edit, delete
409 public static function checkPermissionedLineItems($id, $op, $force = TRUE) {
410 if (!self
::isACLFinancialTypeStatus()) {
413 $lineItems = CRM_Price_BAO_LineItem
::getLineItemsByContributionID($id);
415 foreach ($lineItems as $items) {
416 if (!CRM_Core_Permission
::check($op . ' contributions of type ' . CRM_Contribute_PseudoConstant
::financialType($items['financial_type_id']))) {
418 CRM_Core_Error
::fatal(ts('You do not have permission to access this page.'));
432 * Check if the logged in user has permission to edit the given financial type.
434 * This is called when determining if they can edit things like option values
435 * in price sets. At the moment it is not possible to change an option value from
436 * a type you do not have permission to to a type that you do.
438 * @todo it is currently not possible to edit disabled types if you have ACLs on.
439 * Do ACLs still apply once disabled? That question should be resolved if tackling
442 * @param int $financialTypeID
446 public static function checkPermissionToEditFinancialType($financialTypeID) {
447 if (!self
::isACLFinancialTypeStatus()) {
450 $financialTypes = CRM_Financial_BAO_FinancialType
::getAllAvailableFinancialTypes(CRM_Core_Action
::UPDATE
);
451 return isset($financialTypes[$financialTypeID]);
455 * Check if FT-ACL is turned on or off.
457 * @todo rename this function e.g isFinancialTypeACLsEnabled.
461 public static function isACLFinancialTypeStatus() {
462 if (array_key_exists('acl_financial_type', self
::$_statusACLFt)) {
463 return self
::$_statusACLFt['acl_financial_type'];
465 $contributeSettings = Civi
::settings()->get('contribution_invoice_settings');
466 self
::$_statusACLFt['acl_financial_type'] = FALSE;
467 if (CRM_Utils_Array
::value('acl_financial_type', $contributeSettings)) {
468 self
::$_statusACLFt['acl_financial_type'] = TRUE;
470 return self
::$_statusACLFt['acl_financial_type'];