Continued a bit:
[mailer.git] / inc / referral-functions.php
1 <?php
2 /************************************************************************
3  * Mailer v0.2.1-FINAL                                Start: 07/12/2011 *
4  * ===================                          Last change: 07/12/2011 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : referral-functions.php                           *
8  * -------------------------------------------------------------------- *
9  * Short description : All referral system functions                    *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Alle zum Referral-System gehoerenden Funktionen  *
12  * -------------------------------------------------------------------- *
13  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
14  * Copyright (c) 2009 - 2016 by Mailer Developer Team                   *
15  * For more information visit: http://mxchange.org                      *
16  *                                                                      *
17  * This program is free software; you can redistribute it and/or modify *
18  * it under the terms of the GNU General Public License as published by *
19  * the Free Software Foundation; either version 2 of the License, or    *
20  * (at your option) any later version.                                  *
21  *                                                                      *
22  * This program is distributed in the hope that it will be useful,      *
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
25  * GNU General Public License for more details.                         *
26  *                                                                      *
27  * You should have received a copy of the GNU General Public License    *
28  * along with this program; if not, write to the Free Software          *
29  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
30  * MA  02110-1301  USA                                                  *
31  ************************************************************************/
32
33 // Some security stuff...
34 if (!defined('__SECURITY')) {
35         die();
36 } // END - if
37
38 // Initializes the referral system
39 function initReferralSystem () {
40         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, ' Referral system initialized!');
41         $GLOBALS['ref_level']  = NULL;
42         $GLOBALS['ref_system'] = TRUE;
43 }
44
45 // Getter fro ref level percents
46 function getReferralLevelPercents ($level) {
47         // Default is zero
48         $data['percents'] = '0';
49
50         // Is there cache?
51         if ((isset($GLOBALS['cache_array']['refdepths']['level'])) && (isExtensionActive('cache'))) {
52                 // First look for level
53                 $key = array_search($level, $GLOBALS['cache_array']['refdepths']['level']);
54                 if ($key !== FALSE) {
55                         // Entry found
56                         $data['percents'] = $GLOBALS['cache_array']['refdepths']['percents'][$key];
57
58                         // Count cache hit
59                         incrementStatsEntry('cache_hits');
60                 } // END - if
61         } elseif (!isExtensionActive('cache')) {
62                 // Get referral data
63                 $result_level = sqlQueryEscaped("SELECT `percents` FROM `{?_MYSQL_PREFIX?}_refdepths` WHERE `level`=%s LIMIT 1",
64                         array(bigintval($level)), __FUNCTION__, __LINE__);
65
66                 // Entry found?
67                 if (sqlNumRows($result_level) == 1) {
68                         // Get percents
69                         $data = sqlFetchArray($result_level);
70                 } // END - if
71
72                 // Free result
73                 sqlFreeResult($result_level);
74         }
75
76         // Return percent
77         return $data['percents'];
78 }
79
80 /**
81  * Dynamic Referral and points system, can also send mails!
82  *
83  * subject       = Subject line, write in lower-case letters and underscore is allowed
84  * userid        = Referral id wich should receive...
85  * points        = ... xxx points
86  * refid         = inc/modules/guest/what-confirm.php need this
87  */
88 function addPointsThroughReferralSystem ($subject, $userid, $points, $refid = NULL) {
89         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',points=' . $points . ',refid=' . convertNullToZero($refid) . ' - ENTERED!');
90         // By default nothing has been added
91         $added = FALSE;
92
93         // Determine payment method and notification
94         $paymentMethod = strtoupper(getPaymentMethodFromSubject($subject));
95         $sendNotify    = isPaymentRecipientNotificationEnabled($subject);
96
97         // When $userid is NULL add points to jackpot
98         if ((!isValidId($userid)) && ($paymentMethod == 'DIRECT') && (isExtensionActive('jackpot'))) {
99                 // Add points to jackpot only in DIRECT mode
100                 return addPointsToJackpot($points);
101         } // END - if
102
103         // Set userid as current
104         setCurrentUserId($userid);
105
106         // Check user account
107         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',points=' . $points . ',paymentMethod=' . $paymentMethod . ',sendNotify=' . intval($sendNotify));
108         if (fetchUserData($userid)) {
109                 // Determine whether the user has some mails to click before he/she gets the points
110                 $isLocked = ifUserPointsLocked($userid);
111
112                 // Detect database column
113                 $pointsColumn = determinePointsColumnFromSubjectLocked($subject, $isLocked);
114
115                 // Get percents
116                 $percents = getReferralLevelPercents($GLOBALS['ref_level']);
117                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',points=' . $points . ',depth=' . convertNullToZero($GLOBALS['ref_level']) . ',percents=' . $percents . ',mode=' . $paymentMethod . ',pointsColumn=' . $pointsColumn . ',isLocked=' . intval($isLocked) . ',refid=' . getUserData('refid'));
118
119                 // Some percents found?
120                 if ($percents > 0) {
121                         // Calculate new points
122                         $ref_points = $points * $percents / 100;
123
124                         // Pay refback here if level > 0 and in ref-mode
125                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',refid=' . convertNullToZero(getUserData('refid')) . ',points=' . $points . ',paymentMethod=' . $paymentMethod);
126                         if (($userid != $refid) && (substr($subject, 0, 8) != 'refback:') &&($paymentMethod == 'REFERRAL') && (isValidId(getUserData('refid'))) && (isExtensionActive('refback'))) {
127                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',refid=' . convertNullToZero(getUserData('refid')) . ',ref_points=' . $ref_points . ',depth=' . convertNullToZero($GLOBALS['ref_level']) . ' - BEFORE!');
128                                 $ref_points = addRefbackPoints($userid, getUserData('refid'), $points, $ref_points);
129                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',refid=' . convertNullToZero(getUserData('refid')) . ',ref_points=' . $ref_points . ',depth=' . convertNullToZero($GLOBALS['ref_level']) . ' - AFTER!');
130                         } // END - if
131
132                         // Update points...
133                         if (is_null($GLOBALS['ref_level'])) {
134                                 // Level NULL (self)
135                                 sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_points` SET `%s`=`%s`+%s WHERE `userid`=%s AND `ref_depth` IS NULL LIMIT 1",
136                                         array(
137                                                 $pointsColumn,
138                                                 $pointsColumn,
139                                                 $ref_points,
140                                                 bigintval($userid)
141                                         ), __FUNCTION__, __LINE__);
142                         } else {
143                                 // Level 1+
144                                 sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_points` SET `%s`=`%s`+%s WHERE `userid`=%s AND `ref_depth`=%s LIMIT 1",
145                                         array(
146                                                 $pointsColumn,
147                                                 $pointsColumn,
148                                                 $ref_points,
149                                                 bigintval($userid),
150                                                 bigintval($GLOBALS['ref_level'])
151                                         ), __FUNCTION__, __LINE__);
152                         }
153                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'pointsColumn='.$pointsColumn.',ref_points='.$ref_points.',userid='.$userid.',depth='.convertNullToZero($GLOBALS['ref_level']).',mode='.$paymentMethod.' - UPDATE! ('.sqlAffectedRows().')');
154
155                         // No entry updated?
156                         if (ifSqlHasZeroAffectedRows()) {
157                                 // First ref in this level! :-)
158                                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_user_points` (`userid`, `ref_depth`, `%s`) VALUES (%s, %s, %s)",
159                                         array(
160                                                 $pointsColumn,
161                                                 bigintval($userid),
162                                                 convertZeroToNull($GLOBALS['ref_level']),
163                                                 $ref_points
164                                         ), __FUNCTION__, __LINE__);
165                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'data='.$pointsColumn.',ref_points='.$ref_points.',userid='.$userid.',depth='.convertNullToZero($GLOBALS['ref_level']).',mode='.$paymentMethod.' - INSERTED! ('.sqlAffectedRows().')');
166                         } // END - if
167
168                         // Check affected rows
169                         $added = (sqlAffectedRows() == 1);
170                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'added=' . intval($added) . ' - BEFORE FILTER');
171
172                         // Prepare data for the filter
173                         $filterData = array(
174                                 'subject'     => $subject,
175                                 'userid'      => $userid,
176                                 'points'      => $points,
177                                 'ref_points'  => $ref_points,
178                                 'column'      => $pointsColumn,
179                                 'notify'      => $sendNotify,
180                                 'refid'       => $refid,
181                                 'locked'      => $isLocked,
182                                 'points_mode' => 'add',
183                                 'add_mode'    => $paymentMethod,
184                                 'added'       => $added
185                         );
186
187                         // Filter it now
188                         $filterData = runFilterChain('post_add_points', $filterData);
189
190                         // Extract $added
191                         $added = $filterData['added'];
192                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'added=' . intval($added) . ' - AFTER FILTER');
193
194                         // Debug message
195                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',refid=' . $refid . ',paymentMethod=' . $paymentMethod . ',sendNotify=' . intval($sendNotify) . ',isLocked=' . intval($isLocked));
196
197                         // Send "referral confirmed" mails out?
198                         if ((isValidId($refid)) && ($refid != $userid) && ($sendNotify === TRUE)) {
199                                 // Calculate the referral's points and percents
200                                 $percentsReferral = getReferralLevelPercents($GLOBALS['ref_level'] + 1);
201
202                                 // Calculate new points
203                                 $ref_points = $ref_points * $percentsReferral / 100;
204
205                                 // Prepare content
206                                 $content = array(
207                                         'userid'         => bigintval($userid),
208                                         'refid'          => $refid,
209                                         'level'          => bigintval($GLOBALS['ref_level'] + 1),
210                                         'percents'       => $percentsReferral,
211                                         'points'         => ($paymentMethod == 'REFERRAL' ? $ref_points : '0'),
212                                         'payment_method' => $paymentMethod,
213                                         'subject'        => $subject,
214                                 );
215
216                                 // Load email template
217                                 $message = loadEmailTemplate('guest_user_confirmed_referral', $content, bigintval($userid));
218
219                                 // Send email
220                                 sendEmail($userid, '{--THANKS_REFERRAL_ONE_SUBJECT--}', $message);
221                         } // END - if
222
223                         // Points updated, maybe I shall send him an email?
224                         if (($sendNotify === TRUE) && ($isLocked === FALSE)) {
225                                 // "Explode" subject
226                                 $subjectArray = explode(':', $subject);
227                                 $subjectUserid = (isset($subjectArray[1])) ? $subjectArray[1] : '0';
228
229                                 // Generic delivery of mails, so prepare data
230                                 $content = array(
231                                         'userid'         => $userid,
232                                         'percents'       => $percents,
233                                         'level'          => bigintval($GLOBALS['ref_level']),
234                                         'points'         => $ref_points,
235                                         'column'         => $pointsColumn,
236                                         'subject'        => $subjectArray[0],
237                                         'subject_userid' => $subjectUserid,
238                                         'payment_method' => $paymentMethod,
239                                 );
240
241                                 // Load email template
242                                 $message = loadEmailTemplate('member_' . $subjectArray[0] . '_' . strtolower($paymentMethod), $content, $userid);
243
244                                 // Send email
245                                 sendEmail($userid, '{%message,MEMBER_' . $paymentMethod . '_' . strtoupper($subjectArray[0]) . '_SUBJECT=' . $subjectUserid . '%}', $message);
246
247                                 // Also send admin notification
248                                 sendAdminNotification(
249                                         // Subject
250                                         '{%message,ADMIN_' . $paymentMethod . '_' . strtoupper($subjectArray[0]) . '_SUBJECT=' . $subjectUserid . '%}',
251                                         // Template name
252                                         'admin_' . $subjectArray[0] . '_' . strtolower($paymentMethod),
253                                         // Template content (data array)
254                                         $content,
255                                         // User id
256                                         $userid
257                                 );
258                         } // END - if
259
260                         // Increase referral level, if payment method is 'REFERRAL'
261                         if ($paymentMethod == 'REFERRAL') {
262                                 // Increase it
263                                 $GLOBALS['ref_level']++;
264                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Referral level increased, ref_level=' . convertNullToZero($GLOBALS['ref_level']) . ',points=' . $points . ',refid=' . convertNullToZero(getUserData('refid')) . ',userid=' . $userid . ',paymentMethod=' . $paymentMethod);
265                         } elseif (isDebugModeEnabled()) {
266                                 // Not increasing referral level, DIRECT payment method
267                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Referral level *NOT* increased, ref_level=' . convertNullToZero($GLOBALS['ref_level']) . ',points=' . $points . ',refid=' . convertNullToZero(getUserData('refid')) . ',userid=' . $userid . ',paymentMethod=' . $paymentMethod);
268                         }
269
270                         // Remove any :x
271                         $subject = removeDoubleDotFromSubject($subject);
272
273                         // Maybe there's another ref?
274                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'points=' . $points . ',refid(var|data)=' . convertNullToZero($refid) . '|' . convertNullToZero(getUserData('refid')) . ',userid=' . $userid . ',paymentMethod=' . $paymentMethod . ',subject=' . $subject . ',ref_level=' . $GLOBALS['ref_level']);
275                         if (($paymentMethod == 'REFERRAL') && (isValidId(getUserData('refid'))) && ($points > 0) && (getUserData('refid') != $userid)) {
276                                 // Is _ref there?
277                                 if (ifSubjectHasReferralSuffix($subject)) {
278                                         // Then remove it, no double _ref suffix!
279                                         $subject = substr($subject, 0, -4);
280                                 } // END - if
281
282                                 // Then let's credit him here...
283                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',refid=' . convertNullToZero(getUserData('refid')) . ',points=' . $points . ',ref_points=' . $ref_points . ',added[' . gettype($added) . ']=' . intval($added) . ',ref_level=' . $GLOBALS['ref_level'] . ' - ADVANCE!');
284                                 $added = ($added && addPointsThroughReferralSystem(sprintf('%s_ref:%s', $subject, $GLOBALS['ref_level']), getUserData('refid'), $points, getFetchedUserData('userid', getUserData('refid'), 'refid')));
285                         } // END - if
286                 } // END - if
287         } // END - if
288
289         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'subject=' . $subject . ',userid=' . $userid . ',points=' . $points . ',sendNotify=' . intval($sendNotify) . ',refid=' . convertNullToZero($refid) . ',paymentMethod=' . $paymentMethod . ' - EXIT!');
290         return $added;
291 }
292
293 // Updates the referral counter
294 function updateReferralCounter ($userid) {
295         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ENTERED!');
296         // Init referral id
297         $refid = NULL;
298
299         // Check for his referral
300         if (fetchUserData($userid)) {
301                 // Get it
302                 $refid = getUserData('refid');
303                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',refid=' . convertZeroToNull($refid) . ' - FETCHED!');
304         } // END - if
305
306         // Init entries
307         if (empty($GLOBALS['cache_array']['ref_level'][$userid])) {
308                 $GLOBALS['cache_array']['ref_level'][$userid] = NULL;
309         } // END - if
310         if (empty($GLOBALS['cache_array']['ref_level'][$refid])) {
311                 $GLOBALS['cache_array']['ref_level'][$refid] = NULL;
312         } // END - if
313
314         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',refid=' . convertZeroToNull($refid));
315
316         // When he has a referral...
317         if ((isValidId($refid)) && ($refid != $userid)) {
318                 // Move to next referral level and count his counter one up
319                 $GLOBALS['cache_array']['ref_level'][$refid] = $GLOBALS['cache_array']['ref_level'][$userid] + 1;
320                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',refid(' . $refid . ')=' . $GLOBALS['cache_array']['ref_level'][$refid] . ' - ADVANCED!');
321
322                 // Update counter
323                 sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_refsystem` SET `counter`=`counter`+1 WHERE `userid`=%s AND `level`=%s LIMIT 1",
324                         array(
325                                 bigintval($refid),
326                                 bigintval($GLOBALS['cache_array']['ref_level'][$refid])
327                         ), __FUNCTION__, __LINE__);
328
329                 // When no entry was updated then we have to create it here
330                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'refid=' . $refid . ',level=' . $GLOBALS['cache_array']['ref_level'][$refid] . ',updated=' . sqlAffectedRows());
331                 if (ifSqlHasZeroAffectedRows()) {
332                         // First count!
333                         sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_refsystem` (`userid`, `level`, `counter`) VALUES (%s,%s,1)",
334                                 array(
335                                         bigintval($refid),
336                                         convertZeroToNull($GLOBALS['cache_array']['ref_level'][$refid])
337                                 ), __FUNCTION__, __LINE__);
338                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'refid=' . $refid . ',level=' . $GLOBALS['cache_array']['ref_level'][$refid] . ',sqlAffectedRows()=' . sqlAffectedRows());
339                 } // END - if
340
341                 // Advance to next level
342                 updateReferralCounter($refid);
343         } elseif ((($refid == $userid) || (!isValidId($refid))) && (isExtensionInstalledAndNewer('cache', '0.1.2'))) {
344                 // Remove cache here
345                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'refid=' . convertZeroToNull($refid) . ' - CACHE!');
346                 rebuildCache('refsystem', 'refsystem');
347         }
348
349         // Update the referral table
350         updateReferralTable($userid);
351
352         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',refid=' . convertZeroToNull($refid) . ',level=' . convertZeroToNull($GLOBALS['cache_array']['ref_level'][$refid]) . ' - EXIT!');
353 }
354
355 // Subtract points from database and mediadata cache
356 function subtractPoints ($subject, $userid, $points) {
357         // Add points to used points
358         sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_data` SET `used_points`=`used_points`+%s WHERE `userid`=%s LIMIT 1",
359                 array(
360                         $points,
361                         bigintval($userid)
362                 ), __FUNCTION__, __LINE__);
363
364         // Prepare filter data
365         $filterData = array(
366                 'subject'     => $subject,
367                 'userid'      => $userid,
368                 'points'      => $points,
369                 'points_mode' => 'sub',
370                 'column'      => 'used_points',
371                 'added'       => (!ifSqlHasZeroAffectedRows())
372         );
373
374         // Insert booking record
375         $filterData = runFilterChain('post_sub_points', $filterData);
376
377         // Return result
378         return $filterData['added'];
379 }
380 // "Getter" for array for user refs and points in given level
381 function getUserReferralPoints ($userid, $level) {
382         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ' - ENTERED!');
383         // Default is no refs and no nickname
384         $refs = array();
385
386         // Get refs from database
387         $result = sqlQueryEscaped('SELECT
388         `ur`.`id`,
389         `ur`.`refid`,
390         `ud`.`status`,
391         `ud`.`last_online`,
392         `ud`.`mails_confirmed`,
393         `ud`.`emails_received`,
394         `ud`.`subid`
395 FROM
396         `{?_MYSQL_PREFIX?}_user_refs` AS `ur`
397 LEFT JOIN
398         `{?_MYSQL_PREFIX?}_user_points` AS `up`
399 ON
400         `ur`.`refid`=`up`.`userid` AND
401         (`ur`.`level`=0 OR `ur`.`level` IS NULL)
402 LEFT JOIN
403         `{?_MYSQL_PREFIX?}_user_data` AS `ud`
404 ON
405         `ur`.`refid`=`ud`.`userid`
406 WHERE
407         `ur`.`userid`=%s AND
408         `ur`.`level`=%s
409 ORDER BY
410         `ur`.`refid` ASC',
411                 array(
412                         bigintval($userid),
413                         bigintval($level)
414                 ), __FUNCTION__, __LINE__);
415
416         // Are there some entries?
417         if (!ifSqlHasZeroNumRows($result)) {
418                 // Fetch all entries
419                 while ($row = sqlFetchArray($result)) {
420                         // Init click rate with zero
421                         $row['click_rate'] = calculatePercentageRate($row['mails_confirmed'], $row['emails_received']);
422
423                         // Activity is 'active' by default because if ext-autopurge is not installed
424                         $row['activity'] = '{--MEMBER_ACTIVITY_ACTIVE--}';
425
426                         // Is autopurge installed and the user inactive?
427                         if ((isExtensionActive('autopurge')) && ((time() - getApInactiveSince()) >= $row['last_online']))  {
428                                 // Inactive user!
429                                 $row['activity'] = '{--MEMBER_ACTIVITY_INACTIVE--}';
430                         } // END - if
431
432                         // Remove some entries
433                         unset($row['mails_confirmed']);
434                         unset($row['emails_received']);
435                         unset($row['last_online']);
436
437                         // Add row
438                         $refs[$row['id']] = $row;
439                 } // END - while
440         } // END - if
441
442         // Free result
443         sqlFreeResult($result);
444
445         // Return result
446         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ' - EXIT!');
447         return $refs;
448 }
449
450 // Get points data for given subject
451 function getPointsDataArrayFromSubject ($subject) {
452         // Extension ext-sql_patches must be up-to-date
453         if (isExtensionInstalledAndOlder('sql_patches', '0.8.2')) {
454                 // Please update ext-sql_patches
455                 reportBug(__FUNCTION__, __LINE__, 'sql_patches is out-dated. Please update to at least 0.8.2 to continue. subject=' . $subject);
456         } elseif (substr($subject, -8, 8) == '_ref_ref') {
457                 // Please report ALL finiding
458                 reportBug(__FUNCTION__, __LINE__, 'subject=' . $subject . ' contains invalid double-suffix _ref.');
459         }
460
461         // Remove any double-dot from it
462         $subject = removeDoubleDotFromSubject($subject);
463
464         // If we have cache, shortcut it here
465         if (isset($GLOBALS['cache_array']['points_data'][$subject])) {
466                 // Count cache hit
467                 incrementStatsEntry('cache_hits');
468
469                 // Return it
470                 return $GLOBALS['cache_array']['points_data'][$subject];
471         } // END - if
472
473         // Now checkout the entry in database table
474         $result = sqlQueryEscaped("SELECT
475         `id`,
476         `subject`,
477         `column_name`,
478         `locked_mode`,
479         `payment_method`,
480         `notify_recipient`
481 FROM
482         `{?_MYSQL_PREFIX?}_points_data`
483 WHERE
484         `subject`='%s'
485 LIMIT 1",
486                 array(
487                         $subject
488                 ), __FUNCTION__, __LINE__
489         );
490
491         // Is there an entry?
492         if (sqlNumRows($result) == 1) {
493                 // Then load it
494                 $pointsData = sqlFetchArray($result);
495
496                 // Add all entries to our cache array
497                 foreach ($pointsData as $key => $value) {
498                         $GLOBALS['cache_array']['points_data'][$subject][$key] = $value;
499                 } // END - foreach
500         } else {
501                 // Register this automatically
502                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_points_data` (`subject`, `column_name`, `locked_mode`, `payment_method`, `notify_recipient`) VALUES ('%s','points','LOCKED','REFERRAL','N')",
503                         array($subject), __FUNCTION__, __LINE__);
504
505                 // Re-request it
506                 return getPointsDataArrayFromSubject($subject);
507         }
508
509         // Free result
510         sqlFreeResult($result);
511
512         // Return it
513         return $GLOBALS['cache_array']['points_data'][$subject];
514 }
515
516 // Determines the right points column name for given subject and 'locked'
517 function getPointsColumnNameFromSubjectLocked ($subject, $isLocked) {
518         // Get the points_data entry
519         $pointsData = getPointsDataArrayFromSubject($subject);
520
521         // Regular points by default
522         $columnName = $pointsData['column_name'];
523
524         // Are the points locked?
525         if (($isLocked === TRUE) && ($pointsData['locked_mode'] == 'LOCKED')) {
526                 // Locked points, so prefix it
527                 $columnName = 'locked_' . $pointsData['column_name'];
528         } // END - if
529
530         // Return the result
531         return $columnName;
532 }
533
534 // Determines the payment method for given extension and 'locked'
535 function getPaymentMethodFromSubject ($subject) {
536         // Get the points_data entry
537         $pointsData = getPointsDataArrayFromSubject($subject);
538
539         // Regular points by default
540         $paymentMethod = $pointsData['payment_method'];
541
542         // Return the result
543         return $paymentMethod;
544 }
545
546 // Checks whether notification of points recipient is enabled
547 function isPaymentRecipientNotificationEnabled ($subject) {
548         // Get the points_data entry
549         $pointsData = getPointsDataArrayFromSubject($subject);
550
551         // Is it enabled?
552         $isEnabled = ($pointsData['notify_recipient'] == 'Y');
553
554         // Return the result
555         return $isEnabled;
556 }
557
558 // Update "referral table"
559 function updateReferralTable ($userid) {
560         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ENTERED!');
561         // Load all referrals
562         loadReferralTable($userid);
563
564         // Add missing level > 1
565         addMissingReferralLevels($userid);
566
567         // The last step is to flush all userid's entries to the database
568         flushReferralTableToDatabase($userid);
569
570         // Rebuild cache
571         rebuildCache('refsystem', 'refsystem');
572
573         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - EXIT!');
574 }
575
576 // Loads all referrals for given userid
577 function loadReferralTable ($userid) {
578         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ENTERED!');
579         // Init array
580         $GLOBALS['referral_refid'][$userid] = array();
581
582         // Get all level entries from the refsystem table
583         $GLOBALS['referral_result'][$userid] = sqlQueryEscaped('SELECT `level` FROM `{?_MYSQL_PREFIX?}_refsystem` WHERE `userid`=%s ORDER BY `level` ASC',
584                 array($userid), __FUNCTION__, __LINE__);
585
586         // Are there entries?
587         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',sqlNumRows()=' . sqlNumRows($GLOBALS['referral_result'][$userid]));
588         if (sqlNumRows($GLOBALS['referral_result'][$userid]) > 0) {
589                 // Then walk through all levels
590                 while (list($level) = sqlFetchRow($GLOBALS['referral_result'][$userid])) {
591                         // Init array
592                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level);
593                         $GLOBALS['referral_refid'][$userid][$level] = array();
594
595                         // Level is = 1?
596                         if ($level == 1) {
597                                 // Load all referrals of this user
598                                 $GLOBALS['referral_result_refs'][$userid] = sqlQueryEscaped('SELECT `userid` FROM `{?_MYSQL_PREFIX?}_user_data` WHERE `refid`=%s ORDER BY `userid` ASC',
599                                         array($userid), __FUNCTION__, __LINE__);
600
601                                 // Are there entries?
602                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',sqlNumRows()=' . sqlNumRows($GLOBALS['referral_result_refs'][$userid]));
603                                 if (sqlNumRows($GLOBALS['referral_result_refs'][$userid]) > 0) {
604                                         // Then again walk through all
605                                         while (list($refid) = sqlFetchRow($GLOBALS['referral_result_refs'][$userid])) {
606                                                 // Add this refid
607                                                 array_push($GLOBALS['referral_refid'][$userid][$level], $refid);
608                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . $refid . ' - ADDED!');
609
610                                                 // Load the refid's array as well
611                                                 loadReferralTable($refid);
612                                         } // END - while
613                                 } // END - if
614
615                                 // Free result
616                                 sqlFreeResult($GLOBALS['referral_result_refs'][$userid]);
617                         } // END - if
618                 } // END - while
619         } // END - if
620
621         // Free result
622         sqlFreeResult($GLOBALS['referral_result'][$userid]);
623         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - EXIT!');
624 }
625
626 // Adds missing referral levels to the array
627 function addMissingReferralLevels ($userid) {
628         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ENTERED!');
629         // If the array is gone, you have called this function without calling loadReferralTable()
630         if (!isset($GLOBALS['referral_refid'][$userid])) {
631                 // Please fix your code
632                 reportBug(__FUNCTION__, __LINE__, 'Called without calling loadReferralTable() before! userid=' . $userid);
633         } // END - if
634         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',count()=' . count($GLOBALS['referral_refid'][$userid]));
635
636         // Sort the array reversed
637         krsort($GLOBALS['referral_refid']);
638
639         // Now walk through the array, first levels
640         foreach ($GLOBALS['referral_refid'][$userid] as $level => $levelArray) {
641                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',count()=' . count($levelArray));
642                 // Next are the users
643                 foreach ($levelArray as $refid) {
644                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . $refid);
645                         // Does the refid have an array?
646                         if (isset($GLOBALS['referral_refid'][$refid])) {
647                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . convertNullToZero($refid) . ',count()=' . count($GLOBALS['referral_refid'][$refid]));
648                                 // Add also this user's (maybe) missing levels
649                                 addMissingReferralLevels($refid);
650
651                                 // Okay, then walk through here, too
652                                 foreach ($GLOBALS['referral_refid'][$refid] as $refLevel => $refArray) {
653                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . convertNullToZero($refid) . ',refLevel=' . $refLevel . ',count()=' . count($refArray));
654                                         // Also walk through this one
655                                         foreach ($refArray as $refRefid) {
656                                                 // Calculate new level
657                                                 $newLevel = $level + $refLevel;
658                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . convertNullToZero($refid) . ',refLevel=' . $refLevel . ',refRefid=' . $refRefid . ',newLevel=' . $newLevel);
659                                                 // Is the refRefid not in?
660                                                 if ((!isset($GLOBALS['referral_refid'][$userid][$newLevel])) || (!in_array($refRefid, $GLOBALS['referral_refid'][$userid][$newLevel]))) {
661                                                         // Then we must add this ref's refid to the userid's next level
662                                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',newLevel=' . $newLevel . ',refRefid=' . $refRefid . ' - ADDED!');
663                                                         array_push($GLOBALS['referral_refid'][$userid][$newLevel], $refRefid);
664
665                                                         // Add also this user's (maybe) missing levels
666                                                         addMissingReferralLevels($refRefid);
667                                                 } // END - if
668                                         } // END - foreach
669                                 } // END - foreach
670                         } // END - foreach
671                 } // END - foreach
672         } // END - foreach
673         //die('<pre>'.print_r($GLOBALS['referral_refid'][$userid],TRUE).'</pre>');
674         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - EXIT!');
675 }
676
677 // Flush all entries for given userid to database
678 function flushReferralTableToDatabase ($userid) {
679         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ENTERED!');
680         // If the array is gone, you have called this function without calling loadReferralTable()
681         if (!isset($GLOBALS['referral_refid'][$userid])) {
682                 // Please fix your code
683                 reportBug(__FUNCTION__, __LINE__, 'Called without calling loadReferralTable() before! userid=' . $userid);
684         } // END - if
685         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',count()=' . count($GLOBALS['referral_refid'][$userid]));
686
687         // If no entries are there, skip this whole step
688         if (!isFilledArray($GLOBALS['referral_refid'][$userid])) {
689                 // No entries found
690                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - ABORTING...');
691                 return;
692         } // END - if
693
694         // Prepare SQL
695         $SQL = 'INSERT INTO `{?_MYSQL_PREFIX?}_user_refs` (`userid`, `level`, `refid`) VALUES ';
696         $executeSql = FALSE;
697
698         // Now walk through the array, first levels
699         foreach ($GLOBALS['referral_refid'][$userid] as $level => $levelArray) {
700                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',count()=' . count($levelArray));
701                 // Next are the users
702                 foreach ($levelArray as $refid) {
703                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',level=' . $level . ',refid=' . $refid);
704                         // Query the user_refs table
705                         $count = countSumTotalData(bigintval($userid), 'user_refs', 'id', 'userid', TRUE, ' AND `level`=' . bigintval($level) . ' AND `refid`=' . bigintval($refid));
706
707                         // Is there no entry?
708                         if ($count == 0) {
709                                 // Then add it to the SQL
710                                 $SQL .= '(' . $userid . ',' . $level . ',' . $refid . '),';
711
712                                 // Some has been added, so execute the query
713                                 $executeSql = TRUE;
714                         } // END - if
715                 } // END - foreach
716         } // END - foreach
717
718         // Remove last comma from SQL
719         $SQL = substr($SQL, 0, -1);
720
721         // And run it
722         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ',SQL=' . $SQL);
723         if ($executeSql === TRUE) {
724                 sqlQuery($SQL, __FUNCTION__, __LINE__);
725         } // END - if
726
727         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . $userid . ' - EXIT!');
728 }
729
730 // Generator (somewhat getter) for points_data, locked_mode
731 function generatePointsLockedModeOptions ($lockedMode = NULL) {
732         // Is this cached?
733         if (!isset($GLOBALS[__FUNCTION__][$lockedMode])) {
734                 // Generate output and cache it
735                 $GLOBALS[__FUNCTION__][$lockedMode] = generateOptions(
736                         '/ARRAY/',
737                         array(
738                                 'LOCKED',
739                                 'UNLOCKED'
740                         ),
741                         array(),
742                         $lockedMode,
743                         '', '',
744                         array(),
745                         'translatePointsLockedMode'
746                 );
747         } // END - if
748
749         // Return content
750         return $GLOBALS[__FUNCTION__][$lockedMode];
751 }
752
753 // Generator (somewhat getter) for points_data, payment_method
754 function generatePointsPaymentMethodOptions ($paymentMethod = NULL) {
755         // Is this cached?
756         if (!isset($GLOBALS[__FUNCTION__][$paymentMethod])) {
757                 // Generate output and cache it
758                 $GLOBALS[__FUNCTION__][$paymentMethod] = generateOptions(
759                         '/ARRAY/',
760                         array(
761                                 'DIRECT',
762                                 'REFERRAL'
763                         ),
764                         array(),
765                         $paymentMethod,
766                         '', '',
767                         array(),
768                         'translatePointsPaymentMethod'
769                 );
770         } // END - if
771
772         // Return content
773         return $GLOBALS[__FUNCTION__][$paymentMethod];
774 }
775
776 // Generator (somewhat getter) for points_data, notify_recipient
777 function generatePointsNotifyRecipientOptions ($notifyRecipient = NULL) {
778         // Is this cached?
779         if (!isset($GLOBALS[__FUNCTION__][$notifyRecipient])) {
780                 // Generate output and cache it
781                 $GLOBALS[__FUNCTION__][$notifyRecipient] = generateOptions(
782                         '/ARRAY/',
783                         array(
784                                 'Y',
785                                 'N'
786                         ),
787                         array(),
788                         $notifyRecipient,
789                         '', '',
790                         array(),
791                         'translatePointsNotifyRecipient'
792                 );
793         } // END - if
794
795         // Return content
796         return $GLOBALS[__FUNCTION__][$notifyRecipient];
797 }
798
799 // Setter for referral id (no bigintval, or nicknames will fail!)
800 function setReferralId ($refid) {
801         $GLOBALS['__refid'] = $refid;
802 }
803
804 // Checks if 'refid' is valid
805 function isValidReferralId () {
806         return ((isset($GLOBALS['__refid'])) && (isValidId(getReferralId())));
807 }
808
809 // Getter for referral id
810 function getReferralId () {
811         return $GLOBALS['__refid'];
812 }
813
814 // Determines referral id and sets it
815 function determineReferralId () {
816         // Is it already detected?
817         if (isValidReferralId()) {
818                 // Do not determine it, just return it
819                 return getReferralId();
820         } elseif ((!isHtmlOutputMode()) && (getModule() != 'ref')) {
821                 // Skip this in non-html-mode and outside ref.php
822                 return FALSE;
823         }
824
825         // Check if refid is set
826         if (isValidReferralId()) {
827                 // This is fine...
828                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using refid from GLOBALS (' . getReferralId() . ')');
829         } elseif (isPostRequestElementSet('refid')) {
830                 // Get referral id from POST element refid
831                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using refid from POST data (' . postRequestElement('refid') . ')');
832                 setReferralId(secureString(postRequestElement('refid')));
833         } elseif (isGetRequestElementSet('refid')) {
834                 // Get referral id from GET parameter refid
835                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using refid from GET data (' . getRequestElement('refid') . ')');
836                 setReferralId(getRequestElement('refid'));
837         } elseif (isGetRequestElementSet('ref')) {
838                 // Set refid=ref (the referral link uses such variable)
839                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using ref from GET data (' . getRequestElement('ref') . ')');
840                 setReferralId(getRequestElement('ref'));
841         } elseif ((isGetRequestElementSet('user')) && (getModule() == 'click')) {
842                 // The variable user comes from  click.php
843                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using user from GET data (' . getRequestElement('user') . ')');
844                 setReferralId(bigintval(getRequestElement('user')));
845         } elseif ((isSessionVariableSet('refid')) && (isValidId(getSession('refid')))) {
846                 // Set session refid as global
847                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using refid from SESSION data (' . getSession('refid') . ')');
848                 setReferralId(bigintval(getSession('refid')));
849         } elseif ((isExtensionInstalledAndNewer('user', '0.3.4')) && (isRandomReferralIdEnabled())) {
850                 // Select a random user which has confirmed enougth mails
851                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Checking random referral id');
852                 setReferralId(determineRandomReferralId());
853         } elseif ((isExtensionInstalledAndNewer('sql_patches', '0.1.2')) && (isValidId(getDefRefid()))) {
854                 // Set default refid as refid in URL
855                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using default refid (' . getDefRefid() . ')');
856                 setReferralId(getDefRefid());
857         } else {
858                 // No default id when ext-sql_patches is not installed or none set
859                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using NULL as refid');
860                 setReferralId(NULL);
861         }
862
863         // Set cookie when default refid > 0
864         if ((!isSessionVariableSet('refid')) || (!isValidId(getReferralId())) || ((!isValidId(getSession('refid'))) && (isExtensionInstalledAndNewer('sql_patches', '0.1.2')) && (isValidId(getDefRefid())))) {
865                 // Default is not found
866                 $found = FALSE;
867
868                 // Is there nickname or userid set?
869                 if ((isExtensionActive('nickname')) && (isNicknameUsed(getReferralId()))) {
870                         // Nickname in URL, so load the id
871                         $found = fetchUserData(getReferralId(), 'nickname');
872
873                         // If we found it, use the userid as referral id
874                         if ($found === TRUE) {
875                                 // Set the userid as 'refid'
876                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using refid from user account by nickname (' . getUserData('userid') . ')');
877                                 setReferralId(getUserData('userid'));
878                         } // END - if
879                 } elseif (isValidId(getReferralId())) {
880                         // Direct userid entered
881                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using direct userid (' . getReferralId() . ')');
882                         $found = fetchUserData(getReferralId());
883                 }
884
885                 // Is the record valid?
886                 if ((($found === FALSE) || (!isUserDataValid())) && (isExtensionInstalledAndNewer('sql_patches', '0.1.2'))) {
887                         // No, then reset referral id
888                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using default refid (' . getDefRefid() . ')');
889                         setReferralId(getDefRefid());
890                 } // END - if
891
892                 // Set cookie
893                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Saving refid to session (' . getReferralId() . ') #1');
894                 setSession('refid', getReferralId());
895         } elseif ((!isValidReferralId()) || (!fetchUserData(getReferralId()))) {
896                 // Not valid!
897                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Not valid referral id (' . getReferralId() . '), setting NULL in session');
898                 setReferralId(NULL);
899                 setSession('refid', NULL);
900         } else {
901                 // Set it from GLOBALS array in session
902                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Saving refid to session (' . getReferralId() . ') #2');
903                 setSession('refid', getReferralId());
904         }
905
906         // Run post validation filter chain
907         runFilterChain('post_refid_validation');
908
909         // Return determined refid
910         return getReferralId();
911 }
912
913 // [EOF]
914 ?>