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