source: trunk/inc/membership_levels.inc.php

Last change on this file was 2, checked in by george, 14 years ago
  • Přidáno: Trunk revize 13719.
File size: 27.6 KB
Line 
1<?php
2
3/***************************************************************************
4* Dolphin Smart Community Builder
5* -----------------
6* begin : Mon Mar 23 2006
7* copyright : (C) 2006 BoonEx Group
8* website : http://www.boonex.com/
9* This file is part of Dolphin - Smart Community Builder
10*
11* Dolphin is free software. This work is licensed under a Creative Commons Attribution 3.0 License.
12* http://creativecommons.org/licenses/by/3.0/
13*
14* Dolphin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16* See the Creative Commons Attribution 3.0 License for more details.
17* You should have received a copy of the Creative Commons Attribution 3.0 License along with Dolphin,
18* see license.txt file; if not, write to marketing@boonex.com
19***************************************************************************/
20
21
22require_once( 'header.inc.php' );
23require_once( BX_DIRECTORY_PATH_INC . 'db.inc.php' );
24require_once( BX_DIRECTORY_PATH_INC . 'languages.inc.php' );
25require_once( BX_DIRECTORY_PATH_INC . 'profiles.inc.php' );
26
27//MESSAGE CONSTANTS PASSED TO _t_ext() FUNCTION BY checkAction()
28//NOTE: checkAction() RETURNS LANGUAGE DEPENDANT MESSAGES
29
30define('CHECK_ACTION_MESSAGE_NOT_ALLOWED', "_ACTION_NOT_ALLOWED");
31define('CHECK_ACTION_MESSAGE_NOT_ACTIVE', "_ACTION_NOT_ACTIVE");
32define('CHECK_ACTION_MESSAGE_LIMIT_REACHED', "_ACTION_LIMIT_REACHED");
33define('CHECK_ACTION_MESSAGE_MESSAGE_EVERY_PERIOD', "_ACTION_EVERY_PERIOD");
34define('CHECK_ACTION_MESSAGE_NOT_ALLOWED_BEFORE', "_ACTION_NOT_ALLOWED_BEFORE");
35define('CHECK_ACTION_MESSAGE_NOT_ALLOWED_AFTER', "_ACTION_NOT_ALLOWED_AFTER");
36
37//NODES OF THE $args ARRAY THAT IS PASSED TO THE _t_ext() FUNCTION BY checkAction()
38
39define('CHECK_ACTION_LANG_FILE_ACTION', 1);
40define('CHECK_ACTION_LANG_FILE_MEMBERSHIP', 2);
41define('CHECK_ACTION_LANG_FILE_LIMIT', 3);
42define('CHECK_ACTION_LANG_FILE_PERIOD', 4);
43define('CHECK_ACTION_LANG_FILE_AFTER', 5);
44define('CHECK_ACTION_LANG_FILE_BEFORE', 6);
45define('CHECK_ACTION_LANG_FILE_SITE_EMAIL', 7);
46
47//ACTION ID's
48
49define('ACTION_ID_SEND_VKISS', 1);
50define('ACTION_ID_VIEW_PROFILES', 2);
51define('ACTION_ID_VOTE', 3);
52define('ACTION_ID_SEND_MESSAGE', 4);
53define('ACTION_ID_GET_EMAIL', 5);
54define('ACTION_ID_COMMENTS_POST', 6);
55define('ACTION_ID_COMMENTS_VOTE', 7);
56define('ACTION_ID_COMMENTS_EDIT_OWN', 8);
57define('ACTION_ID_COMMENTS_REMOVE_OWN', 9);
58
59//PREDEFINED MEMBERSHIP ID's
60
61define('MEMBERSHIP_ID_NON_MEMBER', 1);
62define('MEMBERSHIP_ID_STANDARD', 2);
63define('MEMBERSHIP_ID_PROMOTION', 3);
64
65//INDICES FOR checkAction() RESULT ARRAY
66
67define('CHECK_ACTION_RESULT', 0);
68define('CHECK_ACTION_MESSAGE', 1);
69define('CHECK_ACTION_PARAMETER', 3);
70
71//CHECK_ACTION_RESULT NODE VALUES
72
73define('CHECK_ACTION_RESULT_ALLOWED', 0);
74define('CHECK_ACTION_RESULT_NOT_ALLOWED', 1);
75define('CHECK_ACTION_RESULT_NOT_ACTIVE', 2);
76define('CHECK_ACTION_RESULT_LIMIT_REACHED', 3);
77define('CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE', 4);
78define('CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER', 5);
79
80/**
81 * Returns number of members with a given membership at a given time
82 *
83 * @param int $membershipID - members of what membership should be counted.
84 * if 0, then all members are counted ($except is not considered);
85 * if MEMBERSHIP_ID_NON_MEMBER is specified, function returns -1
86 *
87 * @param unix_timestamp $time - date/time to use when counting members.
88 * if not specified, uses the present moment
89 * @param boolean $except - if true, counts all members that DON'T have specified membership
90 *
91 *
92 */
93/*function getMembersCount($membershipID = 0, $time = '', $except = false) //'A' just old unused function
94{
95 $membershipID = (int)$membershipID;
96 $time = ($time == '') ? time() : (int)$time;
97 $except = $except ? true : false;
98
99 if($membershipID == MEMBERSHIP_ID_NON_MEMBER || $membershipID < 0) return -1;
100
101 $resProfiles = db_res("SELECT COUNT(*) FROM Profiles");
102
103 $totalProfiles = mysql_fetch_row($resProfiles);
104 $totalProfiles = (int)$totalProfiles[0];
105
106 if($membershipID == 0) return $totalProfiles;
107
108 $queryWhereMembership = '';
109
110 if($membershipID != MEMBERSHIP_ID_STANDARD) $queryWhereMembership = "IDLevel = $membershipID AND";
111
112 $query = "
113 SELECT COUNT(DISTINCT IDMember)
114 FROM `sys_acl_levels_members`
115 WHERE $queryWhereMembership
116 (DateExpires IS NULL OR UNIX_TIMESTAMP(DateExpires) > $time) AND
117 (DateStarts IS NULL OR UNIX_TIMESTAMP(DateStarts) <= $time)";
118
119 $resProfileMemLevels = db_res($query);
120
121 $membershipProfiles = mysql_fetch_row($resProfileMemLevels);
122 $membershipProfiles = (int)$membershipProfiles[0];
123
124 if($membershipID == MEMBERSHIP_ID_STANDARD) $membershipProfiles = $totalProfiles - $membershipProfiles;
125
126 if($except) $membershipProfiles = $totalProfiles - $membershipProfiles;
127
128 return $membershipProfiles;
129}*/
130
131/**
132 * This is an internal function - do NOT use it outside of membership_levels.inc.php!
133 */
134function getMemberMembershipInfo_current($memberID, $time = '')
135{
136 $sCacheName = 'arrMemLevel'.$memberID.$time;
137 $memberID = (int)$memberID;
138 $time = ($time == '') ? time() : (int)$time;
139
140 //fetch the last purchased/assigned membership
141 //that is still active for the given member
142
143 $arrMemLevel =& $GLOBALS['MySQL']->fromMemory($sCacheName, 'getRow', "
144 SELECT `sys_acl_levels_members`.IDLevel as ID,
145 `sys_acl_levels`.Name as Name,
146 UNIX_TIMESTAMP(`sys_acl_levels_members`.DateStarts) as DateStarts,
147 UNIX_TIMESTAMP(`sys_acl_levels_members`.DateExpires) as DateExpires,
148 `sys_acl_levels_members`.`TransactionID` AS `TransactionID`
149 FROM `sys_acl_levels_members`
150 RIGHT JOIN Profiles
151 ON `sys_acl_levels_members`.IDMember = Profiles.ID
152 AND (`sys_acl_levels_members`.DateStarts IS NULL
153 OR `sys_acl_levels_members`.DateStarts <= FROM_UNIXTIME($time))
154 AND (`sys_acl_levels_members`.DateExpires IS NULL
155 OR `sys_acl_levels_members`.DateExpires > FROM_UNIXTIME($time))
156 LEFT JOIN `sys_acl_levels`
157 ON `sys_acl_levels_members`.IDLevel = `sys_acl_levels`.ID
158
159 WHERE Profiles.ID = $memberID
160
161 ORDER BY `sys_acl_levels_members`.DateStarts DESC
162
163 LIMIT 0, 1");
164
165 //no such member found
166
167 if (!$arrMemLevel || !count($arrMemLevel))
168 {
169 //fetch info about Non-member membership
170 $arrMemLevel =& $GLOBALS['MySQL']->fromCache('sys_acl_levels'.MEMBERSHIP_ID_NON_MEMBER, 'getRow', "SELECT ID, Name FROM `sys_acl_levels` WHERE ID = ".MEMBERSHIP_ID_NON_MEMBER);
171 if (!$arrMemLevel || !count($arrMemLevel))
172 {
173
174 //this should never happen, but just in case
175 echo "<br /><b>getMemberMembershipInfo()</b> fatal error: <b>Non-Member</b> membership not found.";
176 exit();
177 }
178
179 return $arrMemLevel;
180 }
181
182
183 //no purchased/assigned memberships for the member or all of them
184 //have expired -- the member is assumed to have Standard membership
185
186 if(is_null($arrMemLevel['ID']))
187 {
188 $arrMemLevel =& $GLOBALS['MySQL']->fromCache('sys_acl_levels'.MEMBERSHIP_ID_STANDARD, 'getRow', "SELECT ID, Name FROM `sys_acl_levels` WHERE ID = ".MEMBERSHIP_ID_STANDARD);
189 if (!$arrMemLevel || !count($arrMemLevel))
190 {
191 //again, this should never happen, but just in case
192 echo "<br /><b>getMemberMembershipInfo()</b> fatal error: <b>Standard</b> membership not found.";
193 exit();
194 }
195 }
196
197 return $arrMemLevel;
198}
199
200/**
201 * Retrieves information about membership for a given member at a given moment.
202 *
203 * If there are no memberships purchased/assigned to the
204 * given member or all of them have expired at the given point,
205 * the member is assumed to be a standard member, and the function
206 * returns information about the Standard membership. This will
207 * also happen if a member wasnt actually registered in the database
208 * at that point - the function will still return info about Standard
209 * membership, not the Non-member one.
210 *
211 * If there is no profile with the given $memberID,
212 * the function returns information about the Non-member
213 * predefined membership.
214 *
215 * The Standard and Non-member memberships have their
216 * DateStarts and DateExpires attributes set to NULL.
217 *
218 * @param int $memberID - ID of a member to get info about
219 * @param int $time - specifies the time to use when determining membership;
220 * if not specified, the function takes the current time
221 *
222 * @return array( 'ID' => membership id,
223 * 'Name' => membership name,
224 * 'DateStarts' => (UNIX timestamp) date/time purchased,
225 * 'DateExpires' => (UNIX timestamp) date/time expires )
226 *
227 */
228function getMemberMembershipInfo($memberID, $time = '')
229{
230 $time = ($time == '') ? time() : (int)$time;
231
232 $originalMembership = getMemberMembershipInfo_current($memberID, $time);
233
234 if( $originalMembership['ID'] == MEMBERSHIP_ID_STANDARD ||
235 $originalMembership['ID'] == MEMBERSHIP_ID_NON_MEMBER )
236 {
237 return $originalMembership;
238 }
239
240 $arrMembership = $originalMembership;
241
242 do
243 {
244 $dateStarts = $arrMembership['DateStarts'];
245 $arrMembership = getMemberMembershipInfo_current($memberID, $dateStarts - 1);
246 }
247 while($arrMembership['ID'] == $originalMembership['ID'] && (int)$arrMembership['DateStarts']);
248
249 $arrMembership = $originalMembership;
250
251 do
252 {
253 $dateExpires = $arrMembership['DateExpires'];
254 $arrMembership = getMemberMembershipInfo_current($memberID, $dateExpires);
255 }
256 while($arrMembership['ID'] == $originalMembership['ID'] && (int)$arrMembership['DateExpires']);
257
258 $originalMembership['DateStarts'] = $dateStarts;
259 $originalMembership['DateExpires'] = $dateExpires;
260
261 return $originalMembership;
262}
263
264/**
265 * This is an internal function - do NOT use it outside of membership_levels.inc.php!
266 */
267function getMemberMembershipInfo_latest($memberID, $time = '')
268{
269 $time = ($time == '') ? time() : (int)$time;
270
271 $originalMembership = getMemberMembershipInfo_current($memberID, $time);
272
273 if( $originalMembership['ID'] == MEMBERSHIP_ID_STANDARD ||
274 $originalMembership['ID'] == MEMBERSHIP_ID_NON_MEMBER )
275 {
276 return $originalMembership;
277 }
278
279 $arrMembership = $originalMembership;
280 $lastMembership = $originalMembership;
281
282 do
283 {
284 $dateExpires = $arrMembership['DateExpires'];
285 $arrMembership = getMemberMembershipInfo_current($memberID, $dateExpires);
286 if(!is_null($dateExpires))
287 $lastMembership = $arrMembership;
288 }
289 while($arrMembership['ID'] != MEMBERSHIP_ID_STANDARD && (int)$arrMembership['DateExpires']);
290
291 $arrMembership = $lastMembership;
292
293 do
294 {
295 $dateStarts = $arrMembership['DateStarts'];
296 $arrMembership = getMemberMembershipInfo_current($memberID, $dateStarts - 1);
297 }
298 while($arrMembership['ID'] == $lastMembership['ID'] && (int)$arrMembership['DateStarts']);
299
300 $originalMembership['DateStarts'] = $dateStarts;
301 $originalMembership['DateExpires'] = $dateExpires;
302
303 return $originalMembership;
304}
305
306/**
307 * Checks if a given action is allowed for a given member and updates action information if the
308 * action is performed.
309 *
310 * @param int $memberID - ID of a member that is going to perform an action
311 * @param int $actionID - ID of the action itself
312 * @param boolean $performAction - if true, then action information is updated, i.e. action
313 * is 'performed'
314 *
315 * @return array( CHECK_ACTION_RESULT => CHECK_ACTION_RESULT_ constant,
316 * CHECK_ACTION_MESSAGE => CHECK_ACTION_MESSAGE_ constant,
317 * CHECK_ACTION_PARAMETER => additional action parameter (string) )
318 *
319 *
320 * NOTES:
321 *
322 * $result[CHECK_ACTION_MESSAGE] contains a message with detailed information about the result,
323 * already processed by the language file
324 *
325 * if $result[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED then this node contains
326 * an empty string
327 *
328 * The error messages themselves are stored in the language file. Additional variables are
329 * passed to the languages.inc.php function _t_ext() as an array and can be used there in the form of
330 * {0}, {1}, {2} ...
331 *
332 * Additional variables passed to the lang. file on errors (can be used in error messages):
333 *
334 * For all errors:
335 *
336 * $arg0[CHECK_ACTION_LANG_FILE_ACTION] = name of the action
337 * $arg0[CHECK_ACTION_LANG_FILE_MEMBERSHIP]= name of the current membership
338 *
339 * CHECK_ACTION_RESULT_LIMIT_REACHED:
340 *
341 * $arg0[CHECK_ACTION_LANG_FILE_LIMIT] = limit on number of actions allowed for the member
342 * $arg0[CHECK_ACTION_LANG_FILE_PERIOD] = period that the limit is set for (in hours, 0 if unlimited)
343 *
344 * CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE:
345 *
346 * $arg0[CHECK_ACTION_LANG_FILE_BEFORE] = date/time since when the action is allowed
347 *
348 * CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER:
349 *
350 * $arg0[CHECK_ACTION_LANG_FILE_AFTER] = date/time since when the action is not allowed
351 *
352 * $result[CHECK_ACTION_PARAMETER] contains an additional parameter that can be considered
353 * when performing the action (like the number of profiles to show in search result)
354*/
355function checkAction($memberID, $actionID, $performAction = false, $iForcedProfID = 0)
356{
357 global $logged;
358 global $site;
359
360 //output array initialization
361
362 $result = array();
363 $arrLangFileParams = array();
364
365 $dateFormat = "F j, Y, g:i a"; //used when displaying error messages
366
367 //input validation
368
369 $memberID = (int)$memberID;
370 $actionID = (int)$actionID;
371 $performAction = $performAction ? true : false;
372
373 //get current member's membership information
374
375 $arrMembership = getMemberMembershipInfo($memberID);
376
377 $arrLangFileParams[CHECK_ACTION_LANG_FILE_MEMBERSHIP] = $arrMembership['Name'];
378 $arrLangFileParams[CHECK_ACTION_LANG_FILE_SITE_EMAIL] = $site['email'];
379
380 //profile active check
381
382 if($arrMembership['ID'] != MEMBERSHIP_ID_NON_MEMBER || $logged['admin'] || $logged['moderator'])
383 {
384 $iDestID = $memberID;
385 if (($logged['admin'] || $logged['moderator']) && $iForcedProfID>0) {
386 $iDestID = $iForcedProfID;
387 $performAction = false;
388 }
389 $active = getProfileInfo( $iDestID );
390 $active = ($active['Status'] == 'Active');
391
392 if(!$active)
393 {
394 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ACTIVE;
395 $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ACTIVE, $arrLangFileParams);
396
397 return $result;
398 }
399 }
400
401 //get permissions for the current action
402
403 $resMembershipAction = db_res("
404 SELECT Name,
405 IDAction,
406 AllowedCount,
407 AllowedPeriodLen,
408 UNIX_TIMESTAMP(AllowedPeriodStart) as AllowedPeriodStart,
409 UNIX_TIMESTAMP(AllowedPeriodEnd) as AllowedPeriodEnd,
410 AdditionalParamValue
411 FROM `sys_acl_actions`
412 LEFT JOIN `sys_acl_matrix`
413 ON `sys_acl_matrix`.IDAction = `sys_acl_actions`.ID
414 AND `sys_acl_matrix`.IDLevel = {$arrMembership['ID']}
415 WHERE `sys_acl_actions`.ID = $actionID");
416
417 //no such action
418
419 if(mysql_num_rows($resMembershipAction) < 1)
420 {
421 echo "<br /><b>checkAction()</b> fatal error. Unknown action ID: $actionID<br />";
422 exit();
423 }
424
425 $arrAction = mysql_fetch_assoc($resMembershipAction);
426
427 $result[CHECK_ACTION_PARAMETER] = $arrAction['AdditionalParamValue'];
428 $arrLangFileParams[CHECK_ACTION_LANG_FILE_ACTION] = _t('_'.$arrAction['Name']);
429
430 //action is not allowed for the current membership
431
432 if(is_null($arrAction['IDAction']))
433 {
434 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED;
435 $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED, $arrLangFileParams);
436 return $result;
437 }
438
439 //Check fixed period limitations if present (also for non-members)
440
441 if($arrAction['AllowedPeriodStart'] && time() < $arrAction['AllowedPeriodStart'])
442 {
443
444 $arrLangFileParams[CHECK_ACTION_LANG_FILE_BEFORE] = date($dateFormat, $arrAction['AllowedPeriodStart']);
445
446 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE;
447 $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_BEFORE, $arrLangFileParams);
448
449 return $result;
450 }
451
452 if($arrAction['AllowedPeriodEnd'] && time() > $arrAction['AllowedPeriodEnd'])
453 {
454
455 $arrLangFileParams[CHECK_ACTION_LANG_FILE_AFTER] = date($dateFormat, $arrAction['AllowedPeriodEnd']);
456
457 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER;
458 $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_AFTER, $arrLangFileParams);
459
460 return $result;
461 }
462
463 //if non-member, allow action without performing further checks
464
465 if ($arrMembership['ID'] == MEMBERSHIP_ID_NON_MEMBER)
466 {
467 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
468 return $result;
469 }
470
471 //check other limitations (for members only)
472
473 $allowedCnt = (int)$arrAction['AllowedCount']; //number of allowed actions
474 //if not specified or 0, number of
475 //actions is unlimited
476
477 $periodLen = (int)$arrAction['AllowedPeriodLen']; //period for AllowedCount in hours
478 //if not specified, AllowedCount is
479 //treated as total number of actions
480 //permitted
481
482 //number of actions is limited
483
484 if($allowedCnt > 0)
485 {
486 //get current action info for the member
487
488 $actionTrack = db_res("SELECT ActionsLeft,
489 UNIX_TIMESTAMP(ValidSince) as ValidSince
490 FROM `sys_acl_actions_track`
491 WHERE IDAction = $actionID AND IDMember = $memberID");
492
493 $actionsLeft = $performAction ? $allowedCnt - 1 : $allowedCnt;
494 $validSince = time();
495
496 //member is requesting/performing this action for the first time,
497 //and there is no corresponding record in sys_acl_actions_track table
498
499 if(mysql_num_rows($actionTrack) <= 0)
500 {
501 //add action to sys_acl_actions_track table
502
503 db_res("
504 INSERT INTO `sys_acl_actions_track` (IDAction, IDMember, ActionsLeft, ValidSince)
505 VALUES ($actionID, $memberID, $actionsLeft, FROM_UNIXTIME($validSince))");
506
507 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
508 return $result;
509 }
510
511 //action has been requested/performed at least once at this point
512 //and there is a corresponding record in sys_acl_actions_track table
513
514 $actionTrack = mysql_fetch_assoc($actionTrack);
515
516 //action record in sys_acl_actions_track table is out of date
517
518 $periodEnd = (int)$actionTrack['ValidSince'] + $periodLen * 3600; //ValidSince is in seconds, PeriodLen is in hours
519
520 if($periodLen > 0 && $periodEnd < time())
521 {
522 db_res("
523 UPDATE `sys_acl_actions_track`
524 SET ActionsLeft = $actionsLeft, ValidSince = FROM_UNIXTIME($validSince)
525 WHERE IDAction = $actionID AND IDMember = $memberID");
526
527 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
528 return $result;
529 }
530
531 //action record is up to date
532
533 $actionsLeft = (int)$actionTrack['ActionsLeft'];
534
535 //action limit reached for now
536
537 if($actionsLeft <= 0 )
538 {
539 $arrLangFileParams[CHECK_ACTION_LANG_FILE_LIMIT] = $allowedCnt;
540 $arrLangFileParams[CHECK_ACTION_LANG_FILE_PERIOD] = $periodLen;
541
542 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_LIMIT_REACHED;
543 $result[CHECK_ACTION_MESSAGE] = '<div style="width: 80%">' .
544 _t_ext(CHECK_ACTION_MESSAGE_LIMIT_REACHED, $arrLangFileParams) .
545 ($periodLen > 0 ? _t_ext(CHECK_ACTION_MESSAGE_MESSAGE_EVERY_PERIOD, $arrLangFileParams) : '') .
546 '.</div>';
547
548 return $result;
549 }
550
551 if($performAction)
552 {
553 $actionsLeft--;
554
555 db_res("
556 UPDATE `sys_acl_actions_track`
557 SET ActionsLeft = $actionsLeft
558 WHERE IDAction = $actionID AND IDMember = $memberID");
559 }
560 }
561
562 $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
563 return $result;
564}
565
566/**
567 * Buy a membership for a member
568 *
569 * @param int $memberID - member that is going to get the membership
570 * @param int $membershipID - bought membership
571 * @param int $transactionID - internal key of the transaction (ID from Transactions table)
572 * @param boolean $startsNow - if true, the membership will start immediately;
573 * if false, the membership will start after the current
574 * membership expires
575 *
576 * @return boolean - true in case of success, false in case of failure
577 *
578 *
579 */
580function buyMembership($memberID, $membershipID, $transactionID, $startsNow=false) {
581 //input validation
582 $memberID = (int)$memberID;
583 $membershipID = (int)$membershipID;
584 $price = (float)$price;
585
586 $arrMembership = db_arr("SELECT
587 `tl`.`ID` AS `ID`,
588 `tlp`.`Days` AS `Days`,
589 `tl`.`Active` AS `Active`,
590 `tl`.`Purchasable` AS `Purchasable`
591 FROM `sys_acl_levels` AS `tl`
592 LEFT JOIN `sys_acl_level_prices` AS `tlp` ON `tl`.`ID`=`tlp`.`IDLevel`
593 WHERE `tlp`.`id`='" . $membershipID . "'"
594 );
595 if(!is_array($arrMembership) || empty($arrMembership))
596 return false;
597
598 $membershipID = (int)$arrMembership['ID'];
599
600 //check for predefined non-purchasable memberships
601 if(in_array($membershipID, array(MEMBERSHIP_ID_NON_MEMBER, MEMBERSHIP_ID_STANDARD, MEMBERSHIP_ID_PROMOTION)))
602 return false;
603
604 //check if membership is active and purchasable
605 if($arrMembership['Active'] != 'yes' || $arrMembership['Purchasable'] != 'yes')
606 return false;
607
608 return setMembership($memberID, $membershipID, $arrMembership['Days'], $startsNow, $transactionID);
609}
610
611/**
612 * Set a membership for a member
613 *
614 * @param int $memberID - member that is going to get the membership
615 * @param int $membershipID - membership that is going to be assigned to the member
616 * if $membershipID == MEMBERSHIP_ID_STANDARD then $days
617 * and $startsNow parameters are not used, so Standard
618 * membership is always set immediately and `forever`
619 *
620 * @param int $days - number of days to set membership for
621 * if 0, then the membership is set forever
622 *
623 * @param boolean $startsNow - if true, the membership will start immediately;
624 * if false, the membership will start after the current
625 * membership expires
626 *
627 * @return boolean - true in case of success, false in case of failure
628 *
629 *
630 */
631function setMembership($memberID, $membershipID, $days = 0, $startsNow = false, $transactionID = '')
632{
633 $memberID = (int)$memberID;
634 $membershipID = (int)$membershipID;
635 $days = (int)$days;
636 $startsNow = $startsNow ? true : false;
637 $SECONDS_IN_DAY = 86400;
638
639 if(empty($transactionID))
640 $transactionID = 'NULL';
641
642 //check if member exists
643 $res = db_res("SELECT COUNT(ID) FROM Profiles WHERE ID = $memberID");
644 $res = mysql_fetch_row($res);
645 if($res[0]!=1) return false;
646
647 //check if membership exists
648 $res = db_res("SELECT COUNT(ID) FROM `sys_acl_levels` WHERE ID = $membershipID");
649 $res = mysql_fetch_row($res);
650 if($res[0]!=1) return false;
651
652 if($membershipID == MEMBERSHIP_ID_NON_MEMBER) return false;
653
654 $currentMembership = getMemberMembershipInfo($memberID);
655 $latestMembership = getMemberMembershipInfo_latest($memberID);
656
657 if($membershipID == MEMBERSHIP_ID_STANDARD)
658 {
659 //return if already Standard
660
661 if($currentMembership['ID'] == MEMBERSHIP_ID_STANDARD) return true;
662
663 //delete any present and future memberships
664
665 db_res("
666 DELETE FROM `sys_acl_levels_members`
667 WHERE IDMember = $memberID
668 AND (DateExpires IS NULL OR DateExpires > NOW())");
669
670 if(db_affected_rows() > 0)
671 {
672 return true;
673 }
674 else
675 {
676 return false;
677 }
678 }
679
680 if($days < 0) return false;
681
682 $dateStarts = time();
683
684 if(!$startsNow)
685 {
686 //make the membership start after the current membership expires
687
688 if(!is_null($latestMembership['DateExpires']))
689 {
690 $dateStarts = $latestMembership['DateExpires'];
691
692 // if membership already exists then it's unlimited - just shift or delete it
693 $res = db_res("
694 SELECT IDMember
695 FROM `sys_acl_levels_members`
696 WHERE IDMember = $memberID
697 AND UNIX_TIMESTAMP(DateStarts) = $dateStarts
698 AND IDLevel = $membershipID");
699 $res = mysql_fetch_row($res);
700 if($res[0])
701 {
702 if($days == 0)
703 {
704 db_res("DELETE FROM `sys_acl_levels_members`
705 WHERE IDMember = $memberID
706 AND UNIX_TIMESTAMP(DateStarts) = $dateStarts
707 AND IDLevel = $membershipID");
708 }
709 else
710 {
711 db_res("UPDATE `sys_acl_levels_members`
712 SET DateStarts = FROM_UNIXTIME(". ((int)$dateStarts + $days * $SECONDS_IN_DAY) .")
713 WHERE IDMember = $memberID
714 AND UNIX_TIMESTAMP(DateStarts) = $dateStarts
715 AND IDLevel = $membershipID");
716 }
717 }
718 }
719 }
720
721 if($days == 0)
722 {
723 //if days==0 then set the membership forever
724 $dateExpires = 'NULL';
725 }
726 else
727 {
728 $dateExpires = (int)$dateStarts + $days * $SECONDS_IN_DAY;
729 }
730
731 //insert corresponding record into sys_acl_levels_members
732
733 db_res("
734 INSERT `sys_acl_levels_members` (IDMember, IDLevel, DateStarts, DateExpires, TransactionID)
735 VALUES ($memberID, $membershipID, FROM_UNIXTIME($dateStarts), FROM_UNIXTIME($dateExpires), '$transactionID')");
736
737 if(db_affected_rows() <= 0) return false;
738
739 return true;
740}
741
742/**
743 * Get the list of existing memberships
744 *
745 * @param bool $purchasableOnly - if true, fetches only purchasable memberships;
746 * 'purchasable' here means that:
747 * 1. MemLevels.Purchasable = 'yes'
748 * 2. MemLevels.Active = 'yes'
749 * 3. there is at least one pricing option for the membership
750 *
751 * @return array( membershipID_1 => membershipName_1, membershipID_2 => membershipName_2, ...) - if no such memberships, then just array()
752 *
753 *
754 */
755function getMemberships($purchasableOnly = false)
756{
757 $result = array();
758
759 $queryPurchasable = '';
760
761 if($purchasableOnly)
762 {
763 $queryPurchasable = "INNER JOIN `sys_acl_level_prices` ON `sys_acl_level_prices`.IDLevel = `sys_acl_levels`.ID WHERE Purchasable = 'yes' AND Active = 'yes'";
764 }
765
766 $resMemLevels = db_res("SELECT DISTINCT `sys_acl_levels`.ID, `sys_acl_levels`.Name FROM `sys_acl_levels` $queryPurchasable");
767
768 while(list($id, $name) = mysql_fetch_row($resMemLevels))
769 {
770 $result[(int)$id] = $name;
771 }
772
773 return $result;
774}
775
776/**
777 * Get pricing options for the given membership
778 *
779 * @param int $membershipID - membership to get prices for
780 *
781 * @return array( days1 => price1, days2 => price2, ...) - if no prices set, then just array()
782 *
783 *
784 */
785function getMembershipPrices($membershipID)
786{
787 $membershipID = (int)$membershipID;
788 $result = array();
789
790 $resMemLevelPrices = db_res("SELECT Days, Price FROM `sys_acl_level_prices` WHERE IDLevel = $membershipID ORDER BY Days ASC");
791
792 while(list($days, $price) = mysql_fetch_row($resMemLevelPrices))
793 {
794 $result[(int)$days] = (float)$price;
795 }
796
797 return $result;
798}
799
800/**
801 * Get info about a given membership
802 *
803 * @param int $membershipID - membership to get info about
804 *
805 * @return array( 'Name' => name,
806 * 'Active' => active,
807 * 'Purchasable' => purchasable,
808 * 'Removable' => removable)
809 *
810 *
811 */
812function getMembershipInfo($membershipID)
813{
814 $membershipID = (int)$membershipID;
815 $result = array();
816
817 $resMemLevels = db_res("SELECT Name, Active, Purchasable, Removable FROM `sys_acl_levels` WHERE ID = $membershipID");
818
819 if(mysql_num_rows($resMemLevels) > 0)
820 {
821 $result = mysql_fetch_assoc($resMemLevels);
822 }
823
824 return $result;
825}
826
827
828/**
829 * Define action, dirine defining all names are transl;ated the following way:
830 * my action => BX_MY_ACTION
831 *
832 * @param $aActions array of actions from sys_acl_actions table, with default array keys (starting from 0) and text values
833 */
834function defineMembershipActions ($aActions, $sPrefix = 'BX_')
835{
836 if (defined($sPrefix . strtoupper(str_replace(' ', '_', $aActions[0]))))
837 return;
838 $sActions = implode("','", $aActions);
839 $res = db_res("SELECT `ID`, `Name` FROM `sys_acl_actions` WHERE `Name` IN('$sActions')");
840 while ($r = mysql_fetch_array($res)) {
841 define ($sPrefix . strtoupper(str_replace(' ', '_', $r['Name'])), $r['ID']);
842 }
843}
844
845?>
Note: See TracBrowser for help on using the repository browser.