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