Don't default membership type create to inactive
[civicrm-core.git] / CRM / Member / BAO / MembershipStatus.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035 16 */
23de8776 17class CRM_Member_BAO_MembershipStatus extends CRM_Member_DAO_MembershipStatus implements \Civi\Test\HookInterface {
6a488035 18
6a488035 19 /**
fe482240 20 * Fetch object based on array of properties.
6a488035 21 *
b2363ea8
TO
22 * @param array $params
23 * (reference ) an assoc array of name/value pairs.
24 * @param array $defaults
25 * (reference ) an assoc array to hold the flattened values.
6a488035 26 *
16b10e64 27 * @return CRM_Member_BAO_MembershipStatus
6a488035 28 */
00be9182 29 public static function retrieve(&$params, &$defaults) {
6a488035
TO
30 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
31 $membershipStatus->copyValues($params);
32 if ($membershipStatus->find(TRUE)) {
33 CRM_Core_DAO::storeValues($membershipStatus, $defaults);
34 return $membershipStatus;
35 }
36 return NULL;
37 }
38
39 /**
fe482240 40 * Update the is_active flag in the db.
6a488035 41 *
b2363ea8
TO
42 * @param int $id
43 * Id of the database record.
44 * @param bool $is_active
45 * Value we want to set the is_active field.
6a488035 46 *
8a4fede3 47 * @return bool
48 * true if we found and updated the object, else false
6a488035 49 */
00be9182 50 public static function setIsActive($id, $is_active) {
6a488035
TO
51 return CRM_Core_DAO::setFieldValue('CRM_Member_DAO_MembershipStatus', $id, 'is_active', $is_active);
52 }
53
54 /**
c07ec0f4 55 * Takes an associative array and creates a membership status object.
6a488035 56 *
b2363ea8 57 * @param array $params
e021e985 58 * Array of name/value pairs.
d9f93da9 59 *
e021e985 60 * @throws CRM_Core_Exception
61 * @return CRM_Member_DAO_MembershipStatus
6a488035 62 */
9b873358 63 public static function create($params) {
e021e985 64 if (empty($params['id'])) {
6a488035
TO
65 //don't allow duplicate names - if id not set
66 $status = new CRM_Member_DAO_MembershipStatus();
67 $status->name = $params['name'];
68 if ($status->find(TRUE)) {
e021e985 69 throw new CRM_Core_Exception('A membership status with this name already exists.');
6a488035
TO
70 }
71 }
e021e985 72 return self::add($params);
6a488035 73 }
353ffa53 74
6a488035 75 /**
c07ec0f4 76 * Add the membership status.
6a488035 77 *
b2363ea8
TO
78 * @param array $params
79 * Reference array contains the values submitted by the form.
80 * @param array $ids
81 * Array contains the id - this param is deprecated.
6a488035 82 *
e021e985 83 * @return CRM_Member_DAO_MembershipStatus
6a488035 84 */
be2fb01f 85 public static function add(&$params, $ids = []) {
e021e985 86 if (!empty($ids)) {
87 CRM_Core_Error::deprecatedFunctionWarning('ids is a deprecated parameter');
88 }
8df1a020 89 $id = $params['id'] ?? $ids['membershipStatus'] ?? NULL;
64d24a64
EM
90 if (!$id) {
91 CRM_Core_DAO::setCreateDefaults($params, self::getDefaults());
92 //copy name to label when not passed.
93 if (empty($params['label']) && !empty($params['name'])) {
94 $params['label'] = $params['name'];
95 }
96
97 if (empty($params['name']) && !empty($params['label'])) {
98 $params['name'] = $params['label'];
99 }
100 }
6a488035
TO
101
102 // set all other defaults to false.
64d24a64 103 if (!empty($params['is_default'])) {
6a488035 104 $query = "UPDATE civicrm_membership_status SET is_default = 0";
e03e1641 105 CRM_Core_DAO::executeQuery($query);
6a488035
TO
106 }
107
6a488035
TO
108 // action is taken depending upon the mode
109 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
110 $membershipStatus->copyValues($params);
111
64d24a64 112 $membershipStatus->id = $id;
6a488035
TO
113
114 $membershipStatus->save();
9d4d481e 115 CRM_Member_PseudoConstant::flush('membershipStatus');
6a488035
TO
116 return $membershipStatus;
117 }
118
64d24a64 119 /**
fe482240 120 * Get defaults for new entity.
64d24a64
EM
121 * @return array
122 */
00be9182 123 public static function getDefaults() {
be2fb01f 124 return [
64d24a64
EM
125 'is_active' => FALSE,
126 'is_current_member' => FALSE,
127 'is_admin' => FALSE,
128 'is_default' => FALSE,
be2fb01f 129 ];
64d24a64
EM
130 }
131
6a488035 132 /**
c07ec0f4 133 * Get membership status.
6a488035
TO
134 *
135 * @param int $membershipStatusId
d9f93da9
EM
136 *
137 * @return array
6a488035
TO
138 */
139 public static function getMembershipStatus($membershipStatusId) {
be2fb01f 140 $statusDetails = [];
6a488035
TO
141 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
142 $membershipStatus->id = $membershipStatusId;
143 if ($membershipStatus->find(TRUE)) {
144 CRM_Core_DAO::storeValues($membershipStatus, $statusDetails);
145 }
146 return $statusDetails;
147 }
148
149 /**
c07ec0f4 150 * Delete membership status.
6a488035
TO
151 *
152 * @param int $membershipStatusId
23de8776 153 * @deprecated
77b97be7 154 * @throws CRM_Core_Exception
6a488035 155 */
00be9182 156 public static function del($membershipStatusId) {
23de8776
CW
157 static::deleteRecord(['id' => $membershipStatusId]);
158 }
159
160 /**
161 * Callback for hook_civicrm_pre().
162 * @param \Civi\Core\Event\PreEvent $event
163 * @throws CRM_Core_Exception
164 */
165 public static function self_hook_civicrm_pre(\Civi\Core\Event\PreEvent $event) {
166 if ($event->action === 'delete') {
167 // Check if any membership records are assigned this membership status
168 $dependency = ['Membership'];
169 foreach ($dependency as $name) {
170 $baoString = 'CRM_Member_BAO_' . $name;
171 $dao = new $baoString();
172 $dao->status_id = $event->id;
173 if ($dao->find(TRUE)) {
174 throw new CRM_Core_Exception(ts('This membership status cannot be deleted. Memberships exist with this status.'));
175 }
6a488035 176 }
23de8776
CW
177 CRM_Utils_Weight::delWeight('CRM_Member_DAO_MembershipStatus', $event->id);
178 CRM_Member_PseudoConstant::flush('membershipStatus');
6a488035 179 }
6a488035
TO
180 }
181
182 /**
100fef9d 183 * Find the membership status based on start date, end date, join date & status date.
6a488035 184 *
04bc93fa 185 * Loop through all the membership status definitions, ordered by their
186 * weight. For each, we loop through all possible variations of the given
187 * start, end, and join dates and adjust the starts and ends based on that
188 * membership status's rules, where the last computed set of adjusted start
189 * and end becomes a candidate. Then we compare that candidate to either
190 * "today" or some other given date, and if it falls between the adjusted
191 * start and end we have a match and we stop looping through status
192 * definitions. Then we call a hook in case that wasn't enough loops.
193 *
b2363ea8
TO
194 * @param string $startDate
195 * Start date of the member whose membership status is to be calculated.
196 * @param string $endDate
197 * End date of the member whose membership status is to be calculated.
198 * @param string $joinDate
199 * Join date of the member whose membership status is to be calculated.
04bc93fa 200 * @param string $statusDate
201 * Either the string "today" or a date against which we compare the adjusted start and end based on the status rules.
202 * @param bool $excludeIsAdmin
203 * Exclude the statuses having is_admin = 1.
c490a46a 204 * @param int $membershipTypeID
04bc93fa 205 * Not used directly but gets passed to the hook.
b2363ea8 206 * @param array $membership
04bc93fa 207 * Membership params as available to calling function - not used directly but passed to the hook.
6a488035 208 *
da6b46f4 209 * @return array
6a488035 210 */
acb1052e 211 public static function getMembershipStatusByDate(
500cfe81 212 $startDate, $endDate, $joinDate,
2cb64970 213 $statusDate = 'now', $excludeIsAdmin = FALSE, $membershipTypeID = NULL, $membership = []
6a488035 214 ) {
be2fb01f 215 $membershipDetails = [];
5f11bbcc 216
2cb64970 217 if (!$statusDate || $statusDate === 'today') {
218 $statusDate = 'now';
219 CRM_Core_Error::deprecatedFunctionWarning('pass now rather than today in');
6a488035
TO
220 }
221
ccd459b8 222 $statusDate = date('Ymd', CRM_Utils_Time::strtotime($statusDate));
2cb64970 223
6a488035
TO
224 //fix for CRM-3570, if we have statuses with is_admin=1,
225 //exclude these statuses from calculatation during import.
226 $where = "is_active = 1";
227 if ($excludeIsAdmin) {
228 $where .= " AND is_admin != 1";
229 }
230
231 $query = "
232 SELECT *
233 FROM civicrm_membership_status
234 WHERE {$where}
235 ORDER BY weight ASC";
236
33621c4f 237 $membershipStatus = CRM_Core_DAO::executeQuery($query);
6a488035 238
7438fb00 239 $dates = [
ccd459b8
TO
240 'start' => ($startDate && $startDate !== 'null') ? date('Ymd', CRM_Utils_Time::strtotime($startDate)) : '',
241 'end' => ($endDate && $endDate !== 'null') ? date('Ymd', CRM_Utils_Time::strtotime($endDate)) : '',
242 'join' => ($joinDate && $joinDate !== 'null') ? date('Ymd', CRM_Utils_Time::strtotime($joinDate)) : '',
7438fb00 243 ];
244
6a488035
TO
245 while ($membershipStatus->fetch()) {
246 $startEvent = NULL;
247 $endEvent = NULL;
7438fb00 248 foreach (['start', 'end'] as $eve) {
249 foreach ($dates as $dat => $date) {
6a488035 250 // calculate start-event/date and end-event/date
7438fb00 251 if (($membershipStatus->{$eve . '_event'} === $dat . '_date') &&
252 $date
6a488035
TO
253 ) {
254 if ($membershipStatus->{$eve . '_event_adjust_unit'} &&
255 $membershipStatus->{$eve . '_event_adjust_interval'}
256 ) {
ccd459b8
TO
257 $month = date('m', CRM_Utils_Time::strtotime($date));
258 $day = date('d', CRM_Utils_Time::strtotime($date));
259 $year = date('Y', CRM_Utils_Time::strtotime($date));
6a488035 260 // add in months
5872a4b7 261 if ($membershipStatus->{$eve . '_event_adjust_unit'} === 'month') {
262 ${$eve . 'Event'} = date('Ymd', mktime(0, 0, 0,
263 $month + $membershipStatus->{$eve . '_event_adjust_interval'},
264 $day,
265 $year
b09fe5ed 266 ));
6a488035
TO
267 }
268 // add in days
5872a4b7 269 if ($membershipStatus->{$eve . '_event_adjust_unit'} === 'day') {
270 ${$eve . 'Event'} = date('Ymd', mktime(0, 0, 0,
271 $month,
272 $day + $membershipStatus->{$eve . '_event_adjust_interval'},
273 $year
b09fe5ed 274 ));
6a488035
TO
275 }
276 // add in years
5872a4b7 277 if ($membershipStatus->{$eve . '_event_adjust_unit'} === 'year') {
278 ${$eve . 'Event'} = date('Ymd', mktime(0, 0, 0,
279 $month,
280 $day,
281 $year + $membershipStatus->{$eve . '_event_adjust_interval'}
b09fe5ed 282 ));
6a488035
TO
283 }
284 // if no interval and unit, present
285 }
286 else {
7438fb00 287 ${$eve . 'Event'} = $date;
6a488035
TO
288 }
289 }
290 }
291 }
292
293 // check if statusDate is in the range of start & end events.
294 if ($startEvent && $endEvent) {
295 if (($statusDate >= $startEvent) && ($statusDate <= $endEvent)) {
296 $membershipDetails['id'] = $membershipStatus->id;
297 $membershipDetails['name'] = $membershipStatus->name;
298 }
299 }
300 elseif ($startEvent) {
301 if ($statusDate >= $startEvent) {
302 $membershipDetails['id'] = $membershipStatus->id;
303 $membershipDetails['name'] = $membershipStatus->name;
304 }
305 }
306 elseif ($endEvent) {
307 if ($statusDate <= $endEvent) {
308 $membershipDetails['id'] = $membershipStatus->id;
309 $membershipDetails['name'] = $membershipStatus->name;
310 }
311 }
312
313 // returns FIRST status record for which status_date is in range.
314 if ($membershipDetails) {
5f11bbcc 315 break;
6a488035
TO
316 }
317 }
318 //end fetch
319
5f11bbcc
EM
320 //we bundle the arguments into an array as we can't pass 8 variables to the hook otherwise
321 // the membership array might contain the pre-altered settings so we don't want to merge this
be2fb01f 322 $arguments = [
5f11bbcc
EM
323 'start_date' => $startDate,
324 'end_date' => $endDate,
325 'join_date' => $joinDate,
326 'status_date' => $statusDate,
327 'exclude_is_admin' => $endDate,
328 'membership_type_id' => $membershipTypeID,
329 'start_event' => $startEvent,
330 'end_event' => $endEvent,
be2fb01f 331 ];
5f11bbcc 332 CRM_Utils_Hook::alterCalculatedMembershipStatus($membershipDetails, $arguments, $membership);
6a488035
TO
333 return $membershipDetails;
334 }
335
336 /**
fe482240 337 * Function that return the status ids whose is_current_member is set.
6a488035 338 *
77b97be7 339 * @return array
6a488035
TO
340 */
341 public static function getMembershipStatusCurrent() {
be2fb01f 342 $statusIds = [];
6a488035
TO
343 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
344 $membershipStatus->is_current_member = 1;
345 $membershipStatus->find();
346 $membershipStatus->selectAdd();
347 $membershipStatus->selectAdd('id');
348 while ($membershipStatus->fetch()) {
349 $statusIds[] = $membershipStatus->id;
350 }
6a488035
TO
351 return $statusIds;
352 }
96025800 353
6a488035 354}