c3508a7e17765b0a40aa52538626090cc8cfdd09
[civicrm-core.git] / CRM / Member / BAO / MembershipStatus.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2019
32 * $Id$
33 *
34 */
35 class CRM_Member_BAO_MembershipStatus extends CRM_Member_DAO_MembershipStatus {
36
37 /**
38 * Static holder for the default LT.
39 * @var int
40 */
41 public static $_defaultMembershipStatus = NULL;
42
43 /**
44 * Class constructor.
45 */
46 public function __construct() {
47 parent::__construct();
48 }
49
50 /**
51 * Fetch object based on array of properties.
52 *
53 * @param array $params
54 * (reference ) an assoc array of name/value pairs.
55 * @param array $defaults
56 * (reference ) an assoc array to hold the flattened values.
57 *
58 * @return CRM_Member_BAO_MembershipStatus
59 */
60 public static function retrieve(&$params, &$defaults) {
61 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
62 $membershipStatus->copyValues($params);
63 if ($membershipStatus->find(TRUE)) {
64 CRM_Core_DAO::storeValues($membershipStatus, $defaults);
65 return $membershipStatus;
66 }
67 return NULL;
68 }
69
70 /**
71 * Update the is_active flag in the db.
72 *
73 * @param int $id
74 * Id of the database record.
75 * @param bool $is_active
76 * Value we want to set the is_active field.
77 *
78 * @return bool
79 * true if we found and updated the object, else false
80 */
81 public static function setIsActive($id, $is_active) {
82 return CRM_Core_DAO::setFieldValue('CRM_Member_DAO_MembershipStatus', $id, 'is_active', $is_active);
83 }
84
85 /**
86 * Takes an associative array and creates a membership Status object.
87 * See http://wiki.civicrm.org/confluence/display/CRM/Database+layer
88 *
89 * @param array $params
90 * (reference ) an assoc array of name/value pairs.
91 *
92 * @throws Exception
93 * @return CRM_Member_BAO_MembershipStatus
94 */
95 public static function create($params) {
96 $ids = [];
97 if (!empty($params['id'])) {
98 $ids['membershipStatus'] = $params['id'];
99 }
100 else {
101 //don't allow duplicate names - if id not set
102 $status = new CRM_Member_DAO_MembershipStatus();
103 $status->name = $params['name'];
104 if ($status->find(TRUE)) {
105 throw new Exception('A membership status with this name already exists.');
106 }
107 }
108 $membershipStatusBAO = CRM_Member_BAO_MembershipStatus::add($params, $ids);
109 return $membershipStatusBAO;
110 }
111
112 /**
113 * Add the membership types.
114 *
115 * @param array $params
116 * Reference array contains the values submitted by the form.
117 * @param array $ids
118 * Array contains the id - this param is deprecated.
119 *
120 *
121 * @return object
122 */
123 public static function add(&$params, $ids = []) {
124 $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('membershipStatus', $ids));
125 if (!$id) {
126 CRM_Core_DAO::setCreateDefaults($params, self::getDefaults());
127 //copy name to label when not passed.
128 if (empty($params['label']) && !empty($params['name'])) {
129 $params['label'] = $params['name'];
130 }
131
132 if (empty($params['name']) && !empty($params['label'])) {
133 $params['name'] = $params['label'];
134 }
135 }
136
137 // set all other defaults to false.
138 if (!empty($params['is_default'])) {
139 $query = "UPDATE civicrm_membership_status SET is_default = 0";
140 CRM_Core_DAO::executeQuery($query,
141 CRM_Core_DAO::$_nullArray
142 );
143 }
144
145 // action is taken depending upon the mode
146 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
147 $membershipStatus->copyValues($params);
148
149 $membershipStatus->id = $id;
150
151 $membershipStatus->save();
152 CRM_Member_PseudoConstant::flush('membershipStatus');
153 return $membershipStatus;
154 }
155
156 /**
157 * Get defaults for new entity.
158 * @return array
159 */
160 public static function getDefaults() {
161 return [
162 'is_active' => FALSE,
163 'is_current_member' => FALSE,
164 'is_admin' => FALSE,
165 'is_default' => FALSE,
166 ];
167 }
168
169 /**
170 * Get membership status.
171 *
172 * @param int $membershipStatusId
173 *
174 * @return array
175 */
176 public static function getMembershipStatus($membershipStatusId) {
177 $statusDetails = [];
178 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
179 $membershipStatus->id = $membershipStatusId;
180 if ($membershipStatus->find(TRUE)) {
181 CRM_Core_DAO::storeValues($membershipStatus, $statusDetails);
182 }
183 return $statusDetails;
184 }
185
186 /**
187 * Delete membership Types.
188 *
189 * @param int $membershipStatusId
190 *
191 * @throws CRM_Core_Exception
192 */
193 public static function del($membershipStatusId) {
194 //check dependencies
195 //checking if membership status is present in some other table
196 $check = FALSE;
197
198 $dependency = ['Membership', 'MembershipLog'];
199 foreach ($dependency as $name) {
200 $baoString = 'CRM_Member_BAO_' . $name;
201 $dao = new $baoString();
202 $dao->status_id = $membershipStatusId;
203 if ($dao->find(TRUE)) {
204 throw new CRM_Core_Exception(ts('This membership status cannot be deleted as memberships exist with this status'));
205 }
206 }
207 CRM_Utils_Weight::delWeight('CRM_Member_DAO_MembershipStatus', $membershipStatusId);
208 //delete from membership Type table
209 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
210 $membershipStatus->id = $membershipStatusId;
211 if (!$membershipStatus->find()) {
212 throw new CRM_Core_Exception(ts('Cannot delete membership status ' . $membershipStatusId));
213 }
214 $membershipStatus->delete();
215 CRM_Member_PseudoConstant::flush('membershipStatus');
216 }
217
218 /**
219 * Find the membership status based on start date, end date, join date & status date.
220 *
221 * @param string $startDate
222 * Start date of the member whose membership status is to be calculated.
223 * @param string $endDate
224 * End date of the member whose membership status is to be calculated.
225 * @param string $joinDate
226 * Join date of the member whose membership status is to be calculated.
227 * @param \date|string $statusDate status date of the member whose membership status is to be calculated.
228 * @param bool $excludeIsAdmin the statuses those having is_admin = 1.
229 * Exclude the statuses those having is_admin = 1.
230 * @param int $membershipTypeID
231 * @param array $membership
232 * Membership params as available to calling function - passed to the hook.
233 *
234 * @return array
235 */
236 public static function getMembershipStatusByDate(
237 $startDate, $endDate, $joinDate,
238 $statusDate = 'today', $excludeIsAdmin = FALSE, $membershipTypeID, $membership = []
239 ) {
240 $membershipDetails = [];
241
242 if (!$statusDate || $statusDate == 'today') {
243 $statusDate = getdate();
244 $statusDate = date('Ymd',
245 mktime($statusDate['hours'],
246 $statusDate['minutes'],
247 $statusDate['seconds'],
248 $statusDate['mon'],
249 $statusDate['mday'],
250 $statusDate['year']
251 )
252 );
253 }
254 else {
255 $statusDate = CRM_Utils_Date::customFormat($statusDate, '%Y%m%d');
256 }
257
258 $dates = ['start', 'end', 'join'];
259 $events = ['start', 'end'];
260
261 foreach ($dates as $dat) {
262 if (${$dat . 'Date'} && ${$dat . 'Date'} != "null") {
263 ${$dat . 'Date'} = CRM_Utils_Date::customFormat(${$dat . 'Date'}, '%Y%m%d');
264
265 ${$dat . 'Year'} = substr(${$dat . 'Date'}, 0, 4);
266
267 ${$dat . 'Month'} = substr(${$dat . 'Date'}, 4, 2);
268
269 ${$dat . 'Day'} = substr(${$dat . 'Date'}, 6, 2);
270 }
271 else {
272 ${$dat . 'Date'} = '';
273 }
274 }
275
276 //fix for CRM-3570, if we have statuses with is_admin=1,
277 //exclude these statuses from calculatation during import.
278 $where = "is_active = 1";
279 if ($excludeIsAdmin) {
280 $where .= " AND is_admin != 1";
281 }
282
283 $query = "
284 SELECT *
285 FROM civicrm_membership_status
286 WHERE {$where}
287 ORDER BY weight ASC";
288
289 $membershipStatus = CRM_Core_DAO::executeQuery($query);
290 $hour = $minute = $second = 0;
291
292 while ($membershipStatus->fetch()) {
293 $startEvent = NULL;
294 $endEvent = NULL;
295 foreach ($events as $eve) {
296 foreach ($dates as $dat) {
297 // calculate start-event/date and end-event/date
298 if (($membershipStatus->{$eve . '_event'} == $dat . '_date') &&
299 ${$dat . 'Date'}
300 ) {
301 if ($membershipStatus->{$eve . '_event_adjust_unit'} &&
302 $membershipStatus->{$eve . '_event_adjust_interval'}
303 ) {
304 // add in months
305 if ($membershipStatus->{$eve . '_event_adjust_unit'} == 'month') {
306 ${$eve . 'Event'} = date('Ymd', mktime($hour, $minute, $second,
307 ${$dat . 'Month'} + $membershipStatus->{$eve . '_event_adjust_interval'},
308 ${$dat . 'Day'},
309 ${$dat . 'Year'}
310 ));
311 }
312 // add in days
313 if ($membershipStatus->{$eve . '_event_adjust_unit'} == 'day') {
314 ${$eve . 'Event'} = date('Ymd', mktime($hour, $minute, $second,
315 ${$dat . 'Month'},
316 ${$dat . 'Day'} + $membershipStatus->{$eve . '_event_adjust_interval'},
317 ${$dat . 'Year'}
318 ));
319 }
320 // add in years
321 if ($membershipStatus->{$eve . '_event_adjust_unit'} == 'year') {
322 ${$eve . 'Event'} = date('Ymd', mktime($hour, $minute, $second,
323 ${$dat . 'Month'},
324 ${$dat . 'Day'},
325 ${$dat . 'Year'} + $membershipStatus->{$eve . '_event_adjust_interval'}
326 ));
327 }
328 // if no interval and unit, present
329 }
330 else {
331 ${$eve . 'Event'} = ${$dat . 'Date'};
332 }
333 }
334 }
335 }
336
337 // check if statusDate is in the range of start & end events.
338 if ($startEvent && $endEvent) {
339 if (($statusDate >= $startEvent) && ($statusDate <= $endEvent)) {
340 $membershipDetails['id'] = $membershipStatus->id;
341 $membershipDetails['name'] = $membershipStatus->name;
342 }
343 }
344 elseif ($startEvent) {
345 if ($statusDate >= $startEvent) {
346 $membershipDetails['id'] = $membershipStatus->id;
347 $membershipDetails['name'] = $membershipStatus->name;
348 }
349 }
350 elseif ($endEvent) {
351 if ($statusDate <= $endEvent) {
352 $membershipDetails['id'] = $membershipStatus->id;
353 $membershipDetails['name'] = $membershipStatus->name;
354 }
355 }
356
357 // returns FIRST status record for which status_date is in range.
358 if ($membershipDetails) {
359 break;
360 }
361 }
362 //end fetch
363
364 //we bundle the arguments into an array as we can't pass 8 variables to the hook otherwise
365 // the membership array might contain the pre-altered settings so we don't want to merge this
366 $arguments = [
367 'start_date' => $startDate,
368 'end_date' => $endDate,
369 'join_date' => $joinDate,
370 'status_date' => $statusDate,
371 'exclude_is_admin' => $endDate,
372 'membership_type_id' => $membershipTypeID,
373 'start_event' => $startEvent,
374 'end_event' => $endEvent,
375 ];
376 CRM_Utils_Hook::alterCalculatedMembershipStatus($membershipDetails, $arguments, $membership);
377 return $membershipDetails;
378 }
379
380 /**
381 * Function that return the status ids whose is_current_member is set.
382 *
383 * @return array
384 */
385 public static function getMembershipStatusCurrent() {
386 $statusIds = [];
387 $membershipStatus = new CRM_Member_DAO_MembershipStatus();
388 $membershipStatus->is_current_member = 1;
389 $membershipStatus->find();
390 $membershipStatus->selectAdd();
391 $membershipStatus->selectAdd('id');
392 while ($membershipStatus->fetch()) {
393 $statusIds[] = $membershipStatus->id;
394 }
395 return $statusIds;
396 }
397
398 }