PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/functions.php

https://github.com/BrianPrz/worklist
PHP | 1733 lines | 1308 code | 214 blank | 211 comment | 332 complexity | 082115ddcb2d857e5fceaf00dc3f1b68 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. function worklist_autoloader($class) {
  3. if ($class != 'View' && substr($class, -4) == 'View') {
  4. $fileName = substr($class, 0, -4);
  5. $file = VIEWS_DIR . DIRECTORY_SEPARATOR . $fileName . '.php';
  6. } elseif ($class != 'Layout' && substr($class, -6) == 'Layout') {
  7. $fileName = substr($class, 0, -6);
  8. $file = VIEWS_DIR . DIRECTORY_SEPARATOR . 'layout' . DIRECTORY_SEPARATOR . $fileName . '.php';
  9. } else if ($class != 'Controller' && substr($class, -10) == 'Controller') {
  10. $fileName = substr($class, 0, -10);
  11. $file = CONTROLLERS_DIR . DIRECTORY_SEPARATOR . $fileName . '.php';
  12. } else if ($class != 'Model' && substr($class, -5) == 'Model') {
  13. $fileName = substr($class, 0, -5);
  14. $file = MODELS_DIR . DIRECTORY_SEPARATOR . $fileName . '.php';
  15. } else {
  16. $file = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classes') .
  17. DIRECTORY_SEPARATOR . "$class.class.php";
  18. }
  19. if (file_exists($file)) {
  20. require_once($file);
  21. }
  22. }
  23. spl_autoload_register('worklist_autoloader');
  24. /**
  25. * Timezones functions
  26. */
  27. function getTimeZoneDateTime($GMT) {
  28. $timezones = array(
  29. '-1200'=>'Pacific/Kwajalein',
  30. '-1100'=>'Pacific/Samoa',
  31. '-1000'=>'Pacific/Honolulu',
  32. '-0900'=>'America/Juneau',
  33. '-0800'=>'America/Los_Angeles',
  34. '-0700'=>'America/Denver',
  35. '-0600'=>'America/Mexico_City',
  36. '-0500'=>'America/New_York',
  37. '-0400'=>'America/Caracas',
  38. '-0330'=>'America/St_Johns',
  39. '-0300'=>'America/Argentina/Buenos_Aires',
  40. '-0200'=>'Atlantic/Azores',// no cities here so just picking an hour ahead
  41. '-0100'=>'Atlantic/Azores',
  42. '+0000'=>'Europe/London',
  43. '+0100'=>'Europe/Paris',
  44. '+0200'=>'Europe/Helsinki',
  45. '+0300'=>'Europe/Moscow',
  46. '+0330'=>'Asia/Tehran',
  47. '+0400'=>'Asia/Baku',
  48. '+0430'=>'Asia/Kabul',
  49. '+0500'=>'Asia/Karachi',
  50. '+0530'=>'Asia/Calcutta',
  51. '+0600'=>'Asia/Colombo',
  52. '+0700'=>'Asia/Bangkok',
  53. '+0800'=>'Asia/Singapore',
  54. '+0900'=>'Asia/Tokyo',
  55. '+0930'=>'Australia/Darwin',
  56. '+1000'=>'Pacific/Guam',
  57. '+1100'=>'Asia/Magadan',
  58. '+1200'=>'Asia/Kamchatka'
  59. );
  60. if(isset($timezones[$GMT])){
  61. return $timezones[$GMT];
  62. } else {
  63. return date_default_timezone_get();
  64. }
  65. }
  66. // @param $short == 1 -> return date format as 4:31 AM
  67. // else return date format as 04:31:22 AM
  68. function convertTimeZoneToLocalTime($timeoffset, $short) {
  69. $DefZone = getTimeZoneDateTime($timeoffset);
  70. date_default_timezone_set($DefZone);
  71. if (strlen($timeoffset) == 5) {
  72. $formatedTime = str_split($timeoffset);
  73. $Symbol = $formatedTime[0];
  74. $First = $formatedTime[1];
  75. $Second = $formatedTime[2];
  76. $Third = $formatedTime[3];
  77. $Fourth = $formatedTime[4];
  78. if ($Third=="3") {
  79. $Third =5;
  80. }
  81. $timezone_local = $Symbol.$First.$Second.".".$Third.$Fourth;
  82. } else {
  83. $timezone_local = 0;
  84. }
  85. $time = time();
  86. $timezone_offset = date("Z");
  87. $timezone_add = round($timezone_local*60*60);
  88. $ar = localtime($time,true);
  89. if ($ar['tm_isdst']) { $time += 3600; }
  90. $time = round($time-$timezone_offset+$timezone_add);
  91. if (isset($short) && $short == 1)
  92. $LocalTime = date("g:i A", $time);
  93. else
  94. $LocalTime = date("h:i:s A", $time);
  95. return $LocalTime;
  96. }
  97. function checkReferer() {
  98. $len = strlen(SERVER_NAME);
  99. if ( empty($_SERVER['HTTP_REFERER'])
  100. || ( substr($_SERVER['HTTP_REFERER'], 0, $len + 8) != 'https://'.SERVER_NAME )) {
  101. return false;
  102. } else {
  103. return true;
  104. }
  105. }
  106. function enforceRateLimit($class, $id, $test=false) {
  107. $classMap = array('love'=>array('cost'=>15, 'maximum'=>20));
  108. if (!isset($classMap[$class])) return 0;
  109. $cost = $classMap[$class]['cost'];
  110. $maximum = $classMap[$class]['maximum'];
  111. $qry = "select TIMESTAMPDIFF(SECOND,NOW(),expires) as expires from ".LIMITS." where class='$class' and id='$id'";
  112. $res = mysql_query($qry);
  113. if ($res && ($row = mysql_fetch_assoc($res))) {
  114. $expires = max(0, $row['expires']);
  115. if ($expires > $maximum) {
  116. return $expires - $maximum;
  117. }
  118. } else {
  119. $expires = 0;
  120. }
  121. if (!$test) {
  122. $expires += $cost;
  123. $res = mysql_query("update ".LIMITS." set expires=TIMESTAMPADD(SECOND,$expires,NOW()) where class='$class' and id='$id'");
  124. if (!$res) {
  125. $res = mysql_query("insert into ".LIMITS." set class='$class', id='$id', expires=TIMESTAMPADD(SECOND,$expires,NOW())");
  126. }
  127. }
  128. return 0;
  129. }
  130. // Get the userId from the session, or set it to 0 for Guests.
  131. function getSessionUserId() {
  132. return isset($_SESSION['userid']) ? (int)$_SESSION['userid'] : 0;
  133. }
  134. function getNickName($username) {
  135. static $map = array();
  136. if (!isset($map[$username])) {
  137. $strSQL = "select nickname from ".USERS." where username='".$username."'";
  138. $result = mysql_query($strSQL);
  139. $row = mysql_fetch_array($result);
  140. $map[$username] = $row['nickname'];
  141. }
  142. return $map[$username];
  143. }
  144. function getWorkItemSummary($itemid) {
  145. $query = "select summary from ".WORKLIST." where id='$itemid'";
  146. $rt = mysql_query($query);
  147. if ($rt) {
  148. $row = mysql_fetch_assoc($rt);
  149. $summary = $row['summary'];
  150. }
  151. return $summary;
  152. }
  153. /* initSessionData
  154. *
  155. * Initializes the session data for a user. Takes as input either a username or a an array containing
  156. * data from a row in the users table.
  157. *
  158. * NOTE: keep this function in sync with the same function in journal!!!
  159. */
  160. function initSessionData($user) {
  161. if (!is_array($user)) {
  162. $res = mysql_query("select * from ".USERS." where username='".mysql_real_escape_string($user)."'");
  163. $user_row = (($res) ? mysql_fetch_assoc($res) : null);
  164. if (empty($user_row)) return;
  165. } else {
  166. $user_row = $user;
  167. }
  168. $_SESSION['username'] = $user_row['username'];
  169. $_SESSION['userid'] = $user_row['id'];
  170. $_SESSION['confirm_string'] = $user_row['confirm_string'];
  171. $_SESSION['nickname'] = $user_row['nickname'];
  172. $_SESSION['timezone'] = $user_row['timezone'];
  173. $_SESSION['is_admin'] = intval($user_row['is_admin']);
  174. $_SESSION['is_runner'] = intval($user_row['is_runner']);
  175. $_SESSION['is_payer'] = intval($user_row['is_payer']);
  176. }
  177. //joanne - TODO - wl uses function initUserById($userid)journal uses $uid {
  178. //let's see if we can take this out and replace any calls with function initUserById($userid) {
  179. function initSessionDataByUserId($uid) {
  180. $res = mysql_query("select * from ".USERS." where id='".mysql_real_escape_string($uid)."'");
  181. $user_row = (($res) ? mysql_fetch_assoc($res) : null);
  182. if (empty($user_row)) return;
  183. $_SESSION['username'] = $user_row['username'];
  184. $_SESSION['confirm_string'] = isset($user_row['confirm_string']) ? $user_row['confirm_string'] : 0;
  185. $_SESSION['nickname'] = $user_row['nickname'];
  186. $_SESSION['timezone'] = isset($user_row['timezone']) ? $user_row['timezone'] : 0;
  187. $_SESSION['is_admin'] = $user_row['is_admin'];
  188. $_SESSION['is_runner'] = $user_row['is_runner'];
  189. $_SESSION['is_payer'] = isset($user_row['is_payer']) ? intval($user_row['is_payer']) : 0;
  190. }
  191. function initUserById($userid) {
  192. $res = mysql_query("select * from ".USERS." where id='".mysql_real_escape_string($userid)."'");
  193. $user_row = (($res) ? mysql_fetch_assoc($res) : null);
  194. if (empty($user_row)) return;
  195. $_SESSION['username'] = $user_row['username'];
  196. $_SESSION['userid'] = $user_row['id'];
  197. $_SESSION['confirm_string'] = $user_row['confirm_string'];
  198. $_SESSION['nickname'] = $user_row['nickname'];
  199. $_SESSION['timezone'] = $user_row['timezone'];
  200. $_SESSION['is_runner'] = intval($user_row['is_runner']);
  201. $_SESSION['is_payer'] = intval($user_row['is_payer']);
  202. // set the session variable for the inline message for new users before last seen is updated
  203. if ($user_row['last_seen'] === null) {
  204. $_SESSION['inlineHide'] = 0;
  205. } else {
  206. $_SESSION['inlineHide'] = 1;
  207. }
  208. $last_seen_db = substr($user_row['last_seen'], 0, 10);
  209. $today = date('Y-m-d');
  210. if ($last_seen_db != $today) {
  211. $res = mysql_query("UPDATE ".USERS." SET last_seen = NOW() WHERE id={$userid}");
  212. }
  213. $_SESSION['last_seen'] = $today;
  214. }
  215. function isEnabled($features) {
  216. if (empty($_SESSION['features']) || ($_SESSION['features'] & $features) != $features) {
  217. return false;
  218. } else {
  219. return true;
  220. }
  221. }
  222. function isSuperAdmin() {
  223. if (empty($_SESSION['features']) || ($_SESSION['features'] & FEATURE_SUPER_ADMIN) != FEATURE_SUPER_ADMIN) {
  224. return false;
  225. } else {
  226. return true;
  227. }
  228. }
  229. /* Function: countLoveToUser
  230. *
  231. * Purpose: Gets the count of love sent to a user.
  232. *
  233. * Parameters: username - The username of the desired user.
  234. * fromUser - If set will get the love sent by this user.
  235. */
  236. function countLove($username, $fromUsername="") {
  237. defineSendLoveAPI();
  238. //Wires off countLove to 0, ignores API (api working 5/24)
  239. //return array('status'=>SL_OK,'error'=>SL_NO_ERROR,array('count'=>0));
  240. if($fromUsername != "") {
  241. $params = array (
  242. 'action' => 'getcount',
  243. 'api_key' => SENDLOVE_API_KEY,
  244. 'username' => $username,
  245. 'fromUsername' => $fromUsername);
  246. } else {
  247. $params = array (
  248. 'action' => 'getcount',
  249. 'api_key' => SENDLOVE_API_KEY,
  250. 'username' => $username);
  251. }
  252. $referer = (empty($_SERVER['HTTPS'])?'http://':'https://').$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  253. $retval = json_decode(postRequest (SENDLOVE_API_URL, $params, array(CURLOPT_REFERER => $referer)), true);
  254. if ($retval['status'] == "ok") {
  255. return $retval['data']['count'];
  256. } else {
  257. return -1;
  258. }
  259. }
  260. /* Function: getUserLove
  261. *
  262. * Purpose: Get Love sent to the user
  263. *
  264. * Parameters: username - The username of the user to get love from.
  265. * fromUsername - If set it will filter to the love sent by this username.
  266. */
  267. function getUserLove($username, $fromUsername="") {
  268. defineSendLoveAPI();
  269. //Wires off getUserLove to 0, ignores API (api working 5/24)
  270. //return array('status'=>SL_OK,'error'=>SL_NO_ERROR,array('count'=>0));
  271. if($fromUsername != "") {
  272. $params = array (
  273. 'action' => 'getlove',
  274. 'api_key' => SENDLOVE_API_KEY,
  275. 'username' => $username,
  276. 'fromUsername' => $fromUsername,
  277. 'pagination' => 0);
  278. } else {
  279. $params = array (
  280. 'action' => 'getlove',
  281. 'api_key' => SENDLOVE_API_KEY,
  282. 'username' => $username,
  283. 'pagination' => 0);
  284. }
  285. $referer = (empty($_SERVER['HTTPS'])?'http://':'https://').$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  286. $retval = json_decode(postRequest (SENDLOVE_API_URL, $params, array(CURLOPT_REFERER => $referer)), true);
  287. if ($retval['status'] == "ok") {
  288. return $retval['data'];
  289. } else {
  290. return -1;
  291. }
  292. }
  293. function defineSendLoveAPI() {
  294. // Sendlove API status and error codes. Keep in sync with .../sendlove/api.php
  295. // only define constants once
  296. if (!defined('SL_OK')){
  297. define ('SL_OK', 'ok');
  298. define ('SL_ERROR', 'error');
  299. define ('SL_WARNING', 'warning');
  300. define ('SL_NO_ERROR', '');
  301. define ('SL_NO_RESPONSE', 'no response');
  302. define ('SL_BAD_CALL', 'bad call');
  303. define ('SL_DB_FAILURE', 'db failure');
  304. define ('SL_UNKNOWN_USER', 'unknown user');
  305. define ('SL_NOT_COWORKER', 'receiver not co-worker');
  306. define ('SL_RATE_LIMIT', 'rate limit');
  307. define ('SL_SEND_FAILED', 'send failed');
  308. define ('SL_JOURNAL_FAILED', 'journal failed');
  309. define ('SL_NO_SSL', 'no ssl call');
  310. define ('SL_WRONG_KEY', 'wrong api key');
  311. define ('SL_LOVE_DISABLED', 'sendlove disabled');
  312. }
  313. }
  314. // This will be handled by Rewarder API
  315. /*
  316. * Populate the rewarder team automatically. It's based on who added a fee to a task you worked on in the last 30 days.
  317. *
  318. *
  319. */
  320. function PopulateRewarderTeam($user_id, $worklist_id = '') {
  321. //Wire off rewarder interface for the time being - gj 5/21/10
  322. // returns results of mysql update operation (success=true)
  323. return true;
  324. $where = !empty($worklist_id) ? " f.worklist_id = $worklist_id " : " f.worklist_id IN (SELECT DISTINCT f1.worklist_id FROM " . FEES . " f1 WHERE f1.user_id = $user_id and f1.rewarder = 0) ";
  325. $rewarder_limit_day = GetPopulateRewarderLimit($user_id);
  326. $rewarder_limit_day = $rewarder_limit_day == 0 ? 30 : $rewarder_limit_day;
  327. $where .= " AND f.paid_date BETWEEN (NOW() - INTERVAL $rewarder_limit_day day) AND NOW() " ;
  328. // This will be replaced with an API call
  329. // $sql = "INSERT INTO " . REWARDER . " (giver_id,receiver_id,rewarder_points) SELECT DISTINCT $user_id, u.id, 0 FROM " . USERS . " u INNER JOIN " . FEES . " f ON (f.user_id = u.id) WHERE $where AND NOT EXISTS (SELECT 1 FROM " . REWARDER . " rd WHERE rd.giver_id = $user_id) AND u.id <> $user_id ";
  330. // mysql_query($sql);
  331. }
  332. function GetPopulateRewarderLimit($user_id) {
  333. //Wire off rewarder, will use API - gj 5/24/10
  334. //Rewarder limit/day just return 0
  335. return 0;
  336. $sql = "SELECT rewarder_limit_day FROM ". USERS . " WHERE id= $user_id ";
  337. $rt = mysql_query($sql);
  338. if($row = mysql_fetch_assoc($rt)) {
  339. return $row['rewarder_limit_day'];
  340. }
  341. return 0;
  342. }
  343. /* postRequest
  344. *
  345. * Function for performing a CURL request given an url and post data.
  346. * Returns the results.
  347. */
  348. function postRequest($url, $post_data, $options = array(), $curlopt_timeout = 30) {
  349. if (!function_exists('curl_init')) {
  350. error_log('Curl is not enabled.');
  351. return 'error: curl is not enabled.';
  352. }
  353. $ch = curl_init($url);
  354. curl_setopt($ch, CURLOPT_POST, 1);
  355. curl_setopt($ch, CURLOPT_TIMEOUT, $curlopt_timeout);
  356. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  357. curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  358. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  359. if (count($options)) {
  360. curl_setopt_array($ch, $options);
  361. }
  362. $result = curl_exec($ch);
  363. curl_close($ch);
  364. return $result;
  365. }
  366. //converts unix timestamp to user's time according to his timezone settings
  367. function getUserTime($timestamp){
  368. //need a default to not spew errors when browser is not logged in
  369. //We should probably change logic to always has a SESSION defined (from default)
  370. //Determine login status by SESSION['userid'] etc
  371. if (!empty($_SESSION['timezone'])) {
  372. $tz_correction = $_SESSION['timezone'];
  373. if(strpos($_SESSION['timezone'], "+") === 0){
  374. $tz_correction = "-".substr($_SESSION['timezone'],1);
  375. }elseif(strpos($_SESSION['timezone'], "-") === 0){
  376. $tz_correction = "+".substr($_SESSION['timezone'],1);
  377. }
  378. } else { $tz_correction=0; }
  379. $server_tz = date_default_timezone_get();
  380. date_default_timezone_set ("Europe/London");
  381. $userTime = date("m/d/Y h:i a", strtotime(date("Y-m-d H:i", $timestamp)." ".$tz_correction));
  382. date_default_timezone_set ($server_tz);
  383. return $userTime;
  384. }
  385. // converts server time to users timzone time
  386. function convertTimezone($timestamp){
  387. if (isset($_SESSION['timezone']) && !empty($_SESSION['timezone'])) {
  388. $time_zone_date_time = getTimeZoneDateTime($_SESSION['timezone']);
  389. if ($time_zone_date_time) {
  390. $oTz = date_default_timezone_get();
  391. date_default_timezone_set($time_zone_date_time);
  392. $new_time = date('m/d/Y h:i a', $timestamp);
  393. date_default_timezone_set($oTz);
  394. return $new_time;
  395. }
  396. }
  397. return date('m/d/Y h:i a', $timestamp);
  398. }
  399. /* Function: AddFee
  400. *
  401. * Purpose: This function inserts
  402. *
  403. * Parameters: itemid - id of the worklist entry
  404. * fee_amount - amount of the fee
  405. * fee_category - accounting category for the fee (Refer to below list)
  406. * fee_desc - description of the fee entry
  407. * mechanic_id - userid of the mechanic
  408. *
  409. * Fee Categories: Bid, Code Review, Design Spec, Misc Expense, Management Fee
  410. *
  411. */
  412. function AddFee($itemid, $fee_amount, $fee_category, $fee_desc, $mechanic_id, $is_expense, $is_rewarder=0)
  413. {
  414. if ($is_rewarder) $is_expense = 0;
  415. // Get work item summary
  416. $query = "select summary from ".WORKLIST." where id='$itemid'";
  417. $rt = mysql_query($query);
  418. if ($rt) {
  419. $row = mysql_fetch_assoc($rt);
  420. $summary = $row['summary'];
  421. }
  422. $query = "INSERT INTO `".FEES."` (`id`, `worklist_id`, `amount`, `category`, `user_id`, `desc`, `date`, `paid`, `expense`) ".
  423. "VALUES (NULL, '".(int)$itemid."', '".(float)$fee_amount."', '".(int)$fee_category."', '".(int)$mechanic_id."', '".mysql_real_escape_string($fee_desc)."', NOW(), '0', '".mysql_real_escape_string($is_expense)."' )";
  424. $result = mysql_unbuffered_query($query);
  425. // Journal notification
  426. if($mechanic_id == $_SESSION['userid'])
  427. {
  428. $journal_message = '@' . $_SESSION['nickname'] . ' added a fee of $' . $fee_amount . ' to #' . $itemid;
  429. }
  430. else
  431. {
  432. // Get the mechanic's nickname
  433. $rt = mysql_query("select nickname from ".USERS." where id='".(int)$mechanic_id."'");
  434. if ($rt) {
  435. $row = mysql_fetch_assoc($rt);
  436. $nickname = $row['nickname'];
  437. }
  438. else
  439. {
  440. $nickname = "unknown-{$mechanic_id}";
  441. }
  442. $journal_message = '@' . $_SESSION['nickname'] . ' on behalf of @' . $nickname . ' added a fee of $' . $fee_amount . ' to #' . $itemid;
  443. }
  444. return $journal_message;
  445. }
  446. function AddTip($itemid, $tip_amount, $tip_desc, $mechanic_id) {
  447. // Get work item summary
  448. $query = "SELECT `summary` FROM " . WORKLIST. " WHERE `id` = '{$itemid}'";
  449. $rt = mysql_query($query);
  450. if ($rt) {
  451. $row = mysql_fetch_assoc($rt);
  452. $summary = $row['summary'];
  453. }
  454. // get the tippee's nickname
  455. $rt = mysql_query("SELECT nickname FROM " . USERS . " WHERE id = '". (int) $mechanic_id . "'");
  456. if ($rt) {
  457. $row = mysql_fetch_assoc($rt);
  458. $nickname = $row['nickname'];
  459. }
  460. // validate
  461. $query = "
  462. SELECT * FROM " . FEES . "
  463. WHERE
  464. `worklist_id` = $itemid
  465. AND `user_id` = " . getSessionUserId() . "
  466. AND `desc` = 'Accepted Bid'
  467. AND `withdrawn` = 0";
  468. $rt = mysql_query($query);
  469. if ($rt) {
  470. if (mysql_num_rows($rt) > 0) {
  471. $row = mysql_fetch_assoc($rt);
  472. // deduct the tip from the mechanic's accepted bid fee
  473. if ($tip_amount > 0 && $tip_amount <= $row['amount']) {
  474. $adjusted_amount = $row['amount'] - $tip_amount;
  475. // reduce the mechanic's accepted bid
  476. $query = "UPDATE " . FEES . " SET amount = {$adjusted_amount} WHERE id = {$row['id']}";
  477. mysql_query($query);
  478. }
  479. // add the tip as a fee on the job
  480. $tip_desc = 'Tip: ' . $tip_desc;
  481. $query = "INSERT INTO `".FEES."` (`id`, `worklist_id`, `amount`, `user_id`, `desc`, `date`, `paid`) ".
  482. "VALUES (NULL, '".(int)$itemid."', '".(float)$tip_amount."', '".(int)$mechanic_id."', '".mysql_real_escape_string($tip_desc)."', NOW(), '0')";
  483. $result = mysql_unbuffered_query($query);
  484. return $_SESSION['nickname'] . " tipped $nickname on job #$itemid: $summary. ";
  485. }
  486. }
  487. return '';
  488. }
  489. function payBonusToUser($user_id, $amount, $notes, $budget_id) {
  490. $query = "INSERT INTO `".FEES."` (`id`, `worklist_id`, `budget_id`, `payer_id`, `user_id`, `amount`, `notes`, `desc`, `date`, `bonus`,`paid`,`category`)".
  491. "VALUES ".
  492. "(NULL, 0, '" . (int)$budget_id . "', '" . (int)$_SESSION['userid'] . "', '" . (int)$user_id . "', '" . (float)$amount . "', 'BONUS','" . mysql_real_escape_string($notes) . "', NOW(), 1, 0,0)";
  493. $result = mysql_unbuffered_query($query);
  494. if (mysql_insert_id()) {
  495. return true;
  496. } else {
  497. return false;
  498. }
  499. }
  500. function formatableRelativeTime($timestamp, $detailLevel = 1) {
  501. $periods = array("sec", "min", "hr", "day", "week", "mnth", "yr", "decade");
  502. $lengths = array("60", "60", "24", "7", "4.357", "12", "10");
  503. $now = time();
  504. if(empty($timestamp)) {
  505. return "Unknown time";
  506. }
  507. if($now > $timestamp) {
  508. $difference = $now - $timestamp;
  509. $tense = "";
  510. } else {
  511. $difference = $timestamp - $now;
  512. $tense = "from now";
  513. }
  514. if ($difference == 0) {
  515. return "1 second ago";
  516. }
  517. $remainders = array();
  518. for($j = 0; $j < count($lengths); $j++) {
  519. $remainders[$j] = floor(fmod($difference, $lengths[$j]));
  520. $difference = floor($difference / $lengths[$j]);
  521. }
  522. $difference = round($difference);
  523. $remainders[] = $difference;
  524. $string = "";
  525. for ($i = count($remainders) - 1; $i >= 0; $i--) {
  526. if ($remainders[$i]) {
  527. $string .= $remainders[$i] . " " . $periods[$i];
  528. if($remainders[$i] != 1) {
  529. $string .= "s";
  530. }
  531. $string .= " ";
  532. $detailLevel--;
  533. if ($detailLevel <= 0) {
  534. break;
  535. }
  536. }
  537. }
  538. return $string . $tense;
  539. }
  540. function relativeTime($time, $withIn = true, $justNow = true, $withAgo = true, $specific = true) {
  541. $secs = abs($time);
  542. $mins = 60;
  543. $hour = $mins * 60;
  544. $day = $hour * 24;
  545. $week = $day * 7;
  546. $month = $day * 30;
  547. $year = $day * 365;
  548. // years
  549. $segments = array();
  550. $segments['yr'] = intval($secs / $year);
  551. $secs %= $year;
  552. // month
  553. $segments['mnth'] = intval($secs / $month);
  554. $secs %= $month;
  555. if (!$segments['yr']) {
  556. $segments['day'] = intval($secs / $day);
  557. $secs %= $day;
  558. if (!$segments['mnth']) {
  559. $segments['hr'] = intval($secs / $hour);
  560. $secs %= $hour;
  561. if (!$segments['day']) {
  562. $segments['min'] = intval($secs / $mins);
  563. $secs %= $mins;
  564. if (!$segments['hr'] && !$segments['min']) {
  565. $segments['sec'] = $secs;
  566. }
  567. }
  568. }
  569. }
  570. $relTime = '';
  571. foreach ($segments as $unit=>$cnt) {
  572. if ($segments[$unit]) {
  573. if (strlen($relTime)) {
  574. $relTime .= ', ';
  575. }
  576. $relTime .= "$cnt $unit";
  577. if ($cnt > 1) {
  578. $relTime .= 's';
  579. }
  580. if (!$specific) {
  581. break;
  582. }
  583. }
  584. }
  585. if (!empty($relTime)) {
  586. return ($time < 0) ? ($withAgo ? '' : '-') . ("$relTime " . ($withAgo ? 'ago' : '')) : ($withIn ? "in $relTime" : $relTime);
  587. } else {
  588. return $justNow ? 'just now' : '';
  589. }
  590. }
  591. function is_runner() {
  592. return !empty($_SESSION['is_runner']) ? true : false;
  593. }
  594. function sendJournalNotification($message) {
  595. $entry = new EntryModel();
  596. return $entry->notify($message);
  597. global $chat;
  598. $username = mysql_real_escape_string(JOURNAL_API_USER);
  599. $password = mysql_real_escape_string(sha1(JOURNAL_API_PWD));
  600. $sql = "select id, nickname from ".USERS." where username='$username' and password='$password' and confirm='1'";
  601. if (! $res = mysql_query($sql)) {
  602. error_log("jadd.mysql: ".mysql_error());
  603. }
  604. if($res && mysql_num_rows($res) > 0) {
  605. $row = mysql_fetch_assoc($res);
  606. $data = $chat->sendEntry($row['nickname'], $message, array('userid' => $row['id']), false, false);
  607. if($data['status'] == 'ok') {
  608. return "ok";
  609. } else {
  610. return "error: failed while writing entry with status: {$data['status']}.";
  611. }
  612. } else {
  613. return "error: invalid user.";
  614. }
  615. }
  616. function withdrawBid($bid_id, $withdraw_reason) {
  617. $res = mysql_query('SELECT * FROM `' . BIDS . '` WHERE `id`='.$bid_id);
  618. $bid = mysql_fetch_object($res);
  619. // checking if is bidder or runner
  620. if (is_runner() || ($bid->bidder_id == $_SESSION['userid'])) {
  621. // getting the job
  622. $res = mysql_query('SELECT * FROM `' . WORKLIST . '` WHERE `id` = ' . $bid->worklist_id);
  623. $job = mysql_fetch_assoc($res);
  624. if (! in_array($job['status'], array(
  625. 'Draft',
  626. 'Suggested',
  627. 'SuggestedWithBid',
  628. 'Bidding',
  629. 'Done'
  630. ))) {
  631. $creator_fee_desc = 'Creator';
  632. $runner_fee_desc = 'Runner';
  633. $WorkItem = new WorkItem($bid->worklist_id);
  634. $fees = $WorkItem->getFees($WorkItem->getId());
  635. foreach ($fees as $fee) {
  636. if ($fee['desc'] == $creator_fee_desc) {
  637. deleteFee($fee['id']);
  638. }
  639. if ($fee['desc'] == $runner_fee_desc) {
  640. deleteFee($fee['id']);
  641. }
  642. }
  643. }
  644. // additional changes if status is WORKING, SVNHOLD, FUNCTIONAL or REVIEW
  645. if (($job['status'] == 'Working' || $job['status'] == 'SVNHold' || $job['status'] == 'Review' || $job['status'] == 'Functional')
  646. && ($bid->accepted == 1) && (is_runner() || ($bid->bidder_id == $_SESSION['userid']))) {
  647. // change status of worklist item
  648. mysql_unbuffered_query("UPDATE `" . WORKLIST . "`
  649. SET `mechanic_id` = '0',
  650. `status` = 'Bidding'
  651. WHERE `id` = $bid->worklist_id
  652. LIMIT 1 ;");
  653. }
  654. // set back to suggested if swb and is only bid
  655. $res = mysql_query('SELECT count(*) AS count_bids FROM `' . BIDS . '` WHERE `worklist_id` = ' . $job['id'] . ' AND `withdrawn` = 0');
  656. $bidCount = mysql_fetch_assoc($res);
  657. if ($bidCount['count_bids'] == 1 && $job['status'] == 'SuggestedWithBid') {
  658. mysql_unbuffered_query("UPDATE `" . WORKLIST . "` SET `status` = 'Suggested' WHERE `id` = $bid->worklist_id LIMIT 1 ;");
  659. }
  660. // change bid to withdrawn and set bids.accepted to 0
  661. mysql_unbuffered_query('UPDATE `' . BIDS . '`
  662. SET `withdrawn` = 1 , `accepted` = 0
  663. WHERE `id` = ' . $bid->id);
  664. // delete the fee entry for this bid
  665. mysql_unbuffered_query('UPDATE `' . FEES . '`
  666. SET `withdrawn` = 1
  667. WHERE `worklist_id` = ' . $bid->worklist_id . '
  668. AND `user_id` = ' . $bid->bidder_id . '
  669. AND `bid_id` = ' . $bid->id);
  670. // Get user
  671. $user = getUserById($bid->bidder_id);
  672. // Journal message
  673. $message = 'A bid was deleted from #' . $job['id'];
  674. // Journal notification
  675. sendJournalNotification($message);
  676. // Sending email to the bidder or runner
  677. $subject = "Bid: " . $job['id'] . " (" . $job['summary']. ")";
  678. if(is_runner()){
  679. // Send to bidder
  680. $recipient=$user;
  681. $body = "<p>Your bid has been deleted from item #" . $job['id'] . " by: ".$_SESSION['nickname']."</p>";
  682. } else {
  683. // Send to runner
  684. $recipient=getUserById($job['runner_id']);
  685. $body = "<p>A bid has been deleted from item #" . $job['id'] . " by: ".$_SESSION['nickname']."</p>";
  686. }
  687. if(strlen($withdraw_reason)>0) {
  688. // nl2br is added for proper formatting in email alert 12-MAR-2011 <webdev>
  689. $body .= "<p>Reason: " .nl2br($withdraw_reason)."</p>";
  690. }
  691. // Continue adding text to email body
  692. $item_link = SERVER_URL . $bid->worklist_id;
  693. $body .= "<p><a href='${item_link}'>View Item</a></p>";
  694. $body .= "<p>If you think this has been done in error, please contact the job Runner.</p>";
  695. if (!send_email($recipient->username, $subject, $body)) { error_log("withdrawBid: send_email failed"); }
  696. // Check if there are any active bids remaining
  697. $res = mysql_query("SELECT count(*) AS active_bids FROM `" . BIDS . "` WHERE `worklist_id` = " . $job['id'] . " AND `withdrawn` = 0 AND (NOW() < `bid_expires` OR `bid_expires`='0000-00-00 00:00:00')");
  698. $bids = mysql_fetch_assoc($res);
  699. if ($bids['active_bids'] < 1) {
  700. // There are no active bids, so resend notifications
  701. $workitem = new WorkItem();
  702. $workitem->loadById($job['id']);
  703. Notification::massStatusNotify($workitem);
  704. }
  705. }
  706. }
  707. function deleteFee($fee_id) {
  708. $res = mysql_query('SELECT * FROM `' . FEES . '` WHERE `id`='.$fee_id);
  709. $fee = mysql_fetch_object($res);
  710. // checking if is bidder or runner
  711. if (is_runner() || ($fee->user_id == $_SESSION['userid'])) {
  712. mysql_unbuffered_query('UPDATE `' . FEES . '`
  713. SET `withdrawn` = 1
  714. WHERE `id` = ' . $fee_id);
  715. // Get worklist item summary
  716. $summary = getWorkItemSummary($fee->worklist_id);
  717. // Get user
  718. $user = getUserById($fee->user_id);
  719. if ($user !== false) {
  720. // Journal message
  721. $message = '@' . $_SESSION['nickname'] . ' deleted a fee from @';
  722. $message .= $user->nickname . ' on #' . $fee->worklist_id;
  723. // Journal notification
  724. sendJournalNotification($message);
  725. //sending email to the bidder
  726. $options = array();
  727. $options['emails'] = array($user->username);
  728. $options['workitem'] = new WorkItem();
  729. $options['workitem']->loadById($fee->worklist_id);
  730. $options['type'] = "fee_deleted";
  731. Notification::workitemNotify($options);
  732. $data = array(
  733. 'nick' => $_SESSION['nickname'],
  734. 'fee_nick' => $user->nickname
  735. );
  736. Notification::workitemNotifyHipchat($options, $data);
  737. }
  738. }
  739. }
  740. function getUserById($id) {
  741. $res = mysql_query('SELECT * FROM `' . USERS . '` WHERE `id` = ' . $id . ' AND `is_active` = 1');
  742. if ($res && (mysql_num_rows($res) == 1)) {
  743. return mysql_fetch_object($res);
  744. }
  745. return false;
  746. }
  747. function getUserByNickname($nickname) {
  748. $res = mysql_query('SELECT * FROM `' . USERS . '` WHERE `nickname` = "' . $nickname . '" AND `is_active` = 1;');
  749. if ($res && (mysql_num_rows($res) == 1)) {
  750. return mysql_fetch_object($res);
  751. }
  752. return false;
  753. }
  754. function getWorklistById($id) {
  755. $query = "select * from ".WORKLIST." where id='$id'";
  756. $rt = mysql_query($query);
  757. if ($rt && (mysql_num_rows($rt) == 1)) {
  758. return mysql_fetch_assoc($rt);
  759. }
  760. return false;
  761. }
  762. /**
  763. Validate an email address.
  764. Provide email address (raw input)
  765. Returns true if the email address has the email
  766. address format and the domain exists.
  767. */
  768. function validEmail($email) {
  769. $isValid = true;
  770. $atIndex = strrpos($email, "@");
  771. if (is_bool($atIndex) && !$atIndex) {
  772. $isValid = false;
  773. } else {
  774. $domain = substr($email, $atIndex+1);
  775. $local = substr($email, 0, $atIndex);
  776. $localLen = strlen($local);
  777. $domainLen = strlen($domain);
  778. if ($localLen < 1 || $localLen > 64) {
  779. // local part length exceeded
  780. $isValid = false;
  781. } else if ($domainLen < 1 || $domainLen > 255) {
  782. // domain part length exceeded
  783. $isValid = false;
  784. } else if ($local[0] == '.' || $local[$localLen-1] == '.') {
  785. // local part starts or ends with '.'
  786. $isValid = false;
  787. } else if (preg_match('/\\.\\./', $local)) {
  788. // local part has two consecutive dots
  789. $isValid = false;
  790. } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
  791. // character not valid in domain part
  792. $isValid = false;
  793. } else if (preg_match('/\\.\\./', $domain)) {
  794. // domain part has two consecutive dots
  795. $isValid = false;
  796. } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) {
  797. // character not valid in local part unless
  798. // local part is quoted
  799. if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
  800. $isValid = false;
  801. }
  802. }
  803. if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
  804. // domain not found in DNS
  805. $isValid = false;
  806. }
  807. }
  808. return $isValid;
  809. }
  810. function GetTimeStamp($MySqlDate, $i='')
  811. {
  812. if (empty($MySqlDate)) $MySqlDate = date('Y/m/d');
  813. $date_array = explode("/",$MySqlDate); // split the array
  814. $var_year = $date_array[0];
  815. $var_month = $date_array[1];
  816. $var_day = $date_array[2];
  817. $var_timestamp=$date_array[2]."-".$date_array[0]."-".$date_array[1];
  818. //$var_timestamp=$var_month ."/".$var_day ."-".$var_year;
  819. return($var_timestamp); // return it to the user
  820. }
  821. // is user posting data without being logged in
  822. function handleUnloggedPost() {
  823. // get the IP address
  824. $request_ip = $_SERVER['REMOTE_ADDR'];
  825. $request_uri = $_SERVER['REQUEST_URI'];
  826. error_log('Possible hack attempt from ' . $request_ip . ' on: ' . $request_uri);
  827. error_log(json_encode($_REQUEST));
  828. die('You are not authorized to post to this URL. Click ' .
  829. '<a href="' . SERVER_URL . '">here</a> to go to the main page. ' . "\n");
  830. }
  831. function checkLogin() {
  832. if (! getSessionUserId()) {
  833. $_SESSION = array();
  834. session_destroy();
  835. if (!empty($_POST)) {
  836. handleUnloggedPost();
  837. }
  838. Utils::redirect('./github/login?expired=1&redir=' . urlencode($_SERVER['REQUEST_URI']));
  839. exit;
  840. }
  841. }
  842. /* linkify function
  843. *
  844. * this takes some input and makes links where it thinks they should go
  845. *
  846. */
  847. function linkify($url, $author = null, $bot = false, $process = true)
  848. {
  849. $original = $url;
  850. if(!$process) {
  851. if (mb_detect_encoding($url, 'UTF-8', true) === FALSE) {
  852. $url = utf8_encode($url);
  853. }
  854. return '<a href="http://' . htmlentities($url, ENT_QUOTES, "UTF-8") . '">' . htmlspecialchars($url) . '</a>';
  855. }
  856. $class = '';
  857. if(strpos($url, "helper/get_attachment.php") > 0)
  858. {
  859. $bot = true;
  860. $class=' class="attachment noicon"';
  861. } else {
  862. $class='';
  863. }
  864. $url = html_entity_decode($url, ENT_QUOTES);
  865. if (preg_match("/\<a href=\"([^\"]*)\"/i", $url) == 0) {
  866. // modified this so that it will exclude certain characters from the end of the url
  867. // add to this as you see fit as I assume the list is not exhaustive
  868. $regexp="/((?:(?:ht|f)tps?\:\/\/|www\.)\S+[^\s\.\)\"\'])/i";
  869. $url= preg_replace($regexp, DELIMITER . '<a href="$0"' . $class . '>$0</a>' . DELIMITER, $url);
  870. $regexp="/href=\"(www\.\S+?)\"/i";
  871. $url = preg_replace($regexp,'href="http://$1"', $url);
  872. }
  873. $regexp="/(href=)(.)?((www\.)\S+(\.)\S+)/i";
  874. $url = preg_replace($regexp,'href="http://$3"', $url);
  875. // Replace '#<number>' with a link to the worklist item with the same number
  876. $regexp = "/\#([1-9][0-9]{4})(\s|[^0-9a-z]|$)/i";
  877. if (!function_exists('workitemLinkPregReplaceCallback')) {
  878. /**
  879. * Checks whether a #<number> string should be taken as a workitem link or not.
  880. * This function is used as a callback with preg_replace_callback (see below lines)
  881. */
  882. function workitemLinkPregReplaceCallback($matches) {
  883. $job_id = (int) $matches[1];
  884. if ($job_id < 99999 && WorkItem::idExists($job_id)) {
  885. return
  886. DELIMITER .
  887. '<a href="' . WORKLIST_URL . $job_id . '"' .
  888. ' class="worklist-item" id="worklist-' . $job_id . '" >#' . $job_id . '</a>' .
  889. DELIMITER . $matches[2];
  890. } else {
  891. return $matches[0];
  892. }
  893. }
  894. }
  895. $url = preg_replace_callback($regexp, 'workitemLinkPregReplaceCallback', $url);
  896. // Replace '##<projectName>##' with a link to the worklist project with the same name
  897. // This is used in situations where the project name has a space or spaces or no space
  898. $regexp = "/\#\#([A-Za-z0-9_ ]+)\#\#/";
  899. $link = DELIMITER . '<a href="' . WORKLIST_URL . '$1">$1</a>' . DELIMITER;
  900. $url = preg_replace($regexp, $link, $url);
  901. // Replace '##<projectName>' with a link to the worklist project with the same name
  902. // This is used in situations where the first space encountered is assumed to
  903. // be the end of the project name. Left mainly for backward compatibility.
  904. $regexp = "/\#\#([A-Za-z0-9_]+)/";
  905. $link = DELIMITER . '<a href="' . WORKLIST_URL . '$1">$1</a>' . DELIMITER;
  906. $url = preg_replace($regexp, $link, $url);
  907. // Replace '#<nick>/<url>' with a link to the author sandbox
  908. $regexp="/\#([A-Za-z]+)\/(\S*)/i";
  909. $url = preg_replace(
  910. $regexp, DELIMITER .
  911. '<a href="https://' . SANDBOX_SERVER . '/~$1/$2" class="sandbox-item" id="sandbox-$1">$1 : $2</a>' . DELIMITER,
  912. $url
  913. );
  914. // Replace '<repo> v####' with a link to the SVN server
  915. $regexp = '/([a-zA-Z0-9]+)\s[v]([0-9_]+)/i';
  916. $link = DELIMITER . '<a href="' . SVN_REV_URL . '$1&rev=$2">$1 v$2</a>' . DELIMITER;
  917. $url = preg_replace($regexp, $link, $url);
  918. // Replace '#/<url>' with a link to the author sandbox
  919. $regexp="/\#\/(\S*)/i";
  920. if (strpos(SERVER_BASE, '~') === false) {
  921. $url = preg_replace(
  922. $regexp, DELIMITER .
  923. '<a href="' . SERVER_BASE . '~' . $author . '/$1" class="sandbox-item" id="sandbox-$1">'.$author.' : $1</a>' . DELIMITER,
  924. $url
  925. );
  926. } else { // link on a sand box :
  927. $url = preg_replace(
  928. $regexp, DELIMITER .
  929. '<a href="' . SERVER_BASE . '/../~' . $author . '/$1" class="sandbox-item" id="sandbox-$1" >'.$author.' : $1</a>' . DELIMITER,
  930. $url
  931. );
  932. }
  933. $regexp="/\b(?<=mailto:)([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})/i";
  934. if(preg_match($regexp,$url)){
  935. $regexp="/\b(mailto:)(?=([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4}))/i";
  936. $url=preg_replace($regexp,"",$url);
  937. }
  938. $regexp = "/\b([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})/i";
  939. $url = preg_replace($regexp, DELIMITER . '<a href="mailto:$0">$0</a>' . DELIMITER, $url);
  940. // find anything that looks like a link and add target=_blank so it will open in a new window
  941. $url = htmlspecialchars_decode($url);
  942. $url = preg_replace("/<a\s+href=\"/", "<a target=\"_blank\" href=\"" , $url);
  943. if (mb_detect_encoding($url, 'UTF-8', true) === FALSE) {
  944. $url = utf8_encode($url);
  945. }
  946. if (!$bot) {
  947. $url = htmlentities($url, ENT_QUOTES, "UTF-8");
  948. }
  949. $url = nl2br($url);
  950. $reg = '/' . DELIMITER . '.+' . DELIMITER . '/';
  951. $url = preg_replace_callback($reg, 'decodeDelimitedLinks', $url);
  952. // mentions - @username, comments and job descriptions
  953. $url = preg_replace(
  954. '/(^|[^a-z0-9_])@([a-z0-9_]+)/i',
  955. '$1<a href="' . WORKLIST_URL . 'user/$2">@$2</a>',
  956. $url);
  957. return $url;
  958. }
  959. /**
  960. * Auxiliar function to help decode anchors in linkify function
  961. */
  962. function decodeDelimitedLinks($matches) {
  963. $result = preg_replace('/' . DELIMITER . '/', '', $matches[0]);
  964. return html_entity_decode($result, ENT_QUOTES);
  965. }
  966. /**
  967. * Return a trimmed version of the nickname
  968. */
  969. function getSubNickname($nickname, $length = 18) {
  970. if (strlen($nickname) > $length) {
  971. return substr($nickname, 0, $length) . '...';
  972. } else {
  973. return $nickname;
  974. }
  975. }
  976. function getProjectList() {
  977. $query = "SELECT * FROM `".PROJECTS."` WHERE active=1";
  978. $query = mysql_query($query);
  979. $projects = array();
  980. $i = 0;
  981. while ($project = mysql_fetch_array($query)) {
  982. $projects[$i]['name'] = $project['name'];
  983. $projects[$i]['id'] = $project['project_id'];
  984. $projects[$i]['repo'] = $project['repository'];
  985. $i++;
  986. }
  987. return $projects;
  988. }
  989. /* This function is used to add <br/> to encoded strings
  990. */
  991. function replaceEncodedNewLinesWithBr($string) {
  992. $new_liners = array('\n\r','\r\n','\n','\r');
  993. return str_replace($new_liners, '<br/>', $string);
  994. }
  995. /* outputForJS
  996. *
  997. * Pass a variable and it'll check that it's not null so empty numeric/date vars don't error
  998. * Returns either an empty quotes string or the variable
  999. * takes an optional second param as an alternative replacement
  1000. */
  1001. function outputForJS($var, $rep = "''") {
  1002. return (is_null($var) || empty($var)) ? $rep : $var;
  1003. }
  1004. function isSpammer($ip) {
  1005. $sql = 'SELECT `ipv4` FROM `' . BLOCKED_IP . '` WHERE (`blocktime` + `duration`) > UNIX_TIMESTAMP(NOW());';
  1006. $result = mysql_query($sql);
  1007. if ($result && (mysql_num_rows($result) > 0)) {
  1008. while ($row = mysql_fetch_array($result)) {
  1009. if ($row['ipv4'] == $ip) {
  1010. return true;
  1011. }
  1012. }
  1013. }
  1014. return false;
  1015. }
  1016. function sendReviewNotification($reviewee_id, $type, $oReview) {
  1017. $review = $oReview[0]['feeRange'] . " " . $oReview[0]['review'];
  1018. $reviewee = new User();
  1019. $reviewee->findUserById($reviewee_id);
  1020. $worklist_link = WORKLIST_URL;
  1021. $to = $reviewee->getNickname() . ' <' . $reviewee->getUsername() . '>';
  1022. $body = "<p>" . $review . "</p>";
  1023. $nickname = $reviewee->getNickname();
  1024. $headers = array();
  1025. if ($type == "new") {
  1026. $userinfo_link = WORKLIST_URL . 'user/?id=' . $reviewee->getId();
  1027. $headers['From'] = 'worklist<donotreply@worklist.net>';
  1028. $subject = 'New Peer Review';
  1029. $journal = '@' . $nickname . " received a new review: " . $review;
  1030. $body = '<p>Hello ' . $nickname . ',</p><br />';
  1031. $body .= '<p>You have received a review from one of your peers in the Worklist.</p><br />';
  1032. $body .= '<p>To see your current user reviews, click <a href="' . $userinfo_link . '">here</a>.</p>';
  1033. $body .= '<p><a href="' . $userinfo_link . '">' . $userinfo_link . '</a></p><br />';
  1034. $body .= '<p><a href="' . WORKLIST_URL . '"jobs>worklist' . '</a></p>';
  1035. } else if ($type == "update") {
  1036. $subject = "A review of you has been updated";
  1037. $journal = "A review of @" . $nickname . " has been updated: ". $review;
  1038. } else {
  1039. $subject = "One of your reviews has been deleted";
  1040. $journal = "One review of @" . $nickname . " has been deleted: ". $review;
  1041. }
  1042. if (!send_email($to, $subject, $body, null, $headers)) {
  1043. error_log("sendReviewNotification: send_email failed");
  1044. }
  1045. sendJournalNotification($journal);
  1046. }
  1047. function truncateText($text, $chars = 200, $lines = 5) {
  1048. $truncated = false;
  1049. $total = strlen($text);
  1050. if ($total > $chars) {
  1051. $text = substr($text, 0, $chars);
  1052. $truncated = true;
  1053. }
  1054. $text = nl2br($text);
  1055. $textArray = explode('<br/>', $text);
  1056. $textArraySize = count($textArray);
  1057. // Remove extra lines
  1058. if ($textArraySize > $lines) {
  1059. $count = $textArraySize - $lines;
  1060. for ($i = 0; $i < $count; $i++) {
  1061. array_pop($textArray);
  1062. }
  1063. $truncated = true;
  1064. }
  1065. $text = implode('<br/>', $textArray);
  1066. if ($truncated == true) {
  1067. $text = $text . " (...)";
  1068. }
  1069. return $text;
  1070. }
  1071. function getRelated($input) {
  1072. $related = "";
  1073. $twoIds = false;
  1074. if (preg_match_all('/(\#[1-9][0-9]{4})(\s|[^0-9a-z]|$)/i', $input, $matches)) {
  1075. $distinctMatches = array_unique($matches[1]);
  1076. foreach($distinctMatches as $match) {
  1077. $job_id = (int) substr($match, 1);
  1078. if ($job_id != $worklist_id && WorkItem::idExists($job_id)) {
  1079. if ($related != "") {
  1080. $twoIds = true;
  1081. $related .= ", #" . $job_id;
  1082. } else {
  1083. $related = " #" . $job_id;
  1084. }
  1085. }
  1086. }
  1087. }
  1088. if ($related != "") {
  1089. $related .= ")";
  1090. if ($twoIds == true) {
  1091. $related = " (related jobs: " . $related;
  1092. } else {
  1093. $related = " (related job: " . $related;
  1094. }
  1095. }
  1096. return $related;
  1097. }
  1098. function addRewarderBalance($userId, $points, $worklist_id = 0, $fee_id = 0) {
  1099. //Wire off rewarder interface for the time being - gj 5/21/10
  1100. if(true) return 1;
  1101. defineSendLoveAPI();
  1102. $reason = "Worklist paid you $" . $points;
  1103. $params = array (
  1104. 'action' => 'change_balance',
  1105. 'api_key' => REWARDER_API_KEY,
  1106. 'user_id' => $userId,
  1107. 'points' => $points,
  1108. 'reason' => $reason,
  1109. 'worklist_id' => $worklist_id,
  1110. 'fee_id' => $fee_id,
  1111. );
  1112. $referer = (empty($_SERVER['HTTPS'])?'http://':'https://').$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  1113. $retval = json_decode(postRequest (REWARDER_API_URL, $params, array(CURLOPT_REFERER => $referer)), true);
  1114. if ($retval['status'] == "ok") {
  1115. return 1;
  1116. } else {
  1117. return -1;
  1118. }
  1119. }
  1120. /*
  1121. * getRewardedPoints - api call to rewarder to get how many
  1122. * points $giverId has given to $receiverId
  1123. *
  1124. */
  1125. function getRewardedPoints($giverId, $receiverId) {
  1126. defineSendLoveAPI();
  1127. $params = array (
  1128. 'action' => 'get_points',
  1129. 'api_key' => REWARDER_API_KEY,
  1130. 'giver_id' => $giverId,
  1131. 'receiver_id' => $receiverId,
  1132. );
  1133. $referer = (empty($_SERVER['HTTPS'])?'http://':'https://').$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  1134. $retval = json_decode(postRequest (REWARDER_API_URL, $params, array(CURLOPT_REFERER => $referer)), true);
  1135. if ($retval['status'] == "ok") {
  1136. return $retval['data'];
  1137. } else {
  1138. return -1;
  1139. }
  1140. }
  1141. /*
  1142. * rewardUser - api call to rewarder to grant
  1143. * rewarder points from $giverId to $receiverId
  1144. *
  1145. */
  1146. function rewardUser($giverId, $receiverId, $points) {
  1147. defineSendLoveAPI();
  1148. $params = array (
  1149. 'action' => 'reward_user',
  1150. 'api_key' => REWARDER_API_KEY,
  1151. 'giver_id' => $giverId,
  1152. 'receiver_id' => $receiverId,
  1153. 'points' => $points,
  1154. );
  1155. $referer = (empty($_SERVER['HTTPS'])?'http://':'https://').$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  1156. $retval = json_decode(postRequest (REWARDER_API_URL, $params, array(CURLOPT_REFERER => $referer)), true);
  1157. if ($retval['status'] == "ok") {
  1158. return $retval['data'];
  1159. } else {
  1160. return -1;
  1161. }
  1162. }
  1163. /*******************************************************
  1164. PPHttpPost: NVP post function for masspay.
  1165. Author: Jason (jkofoed@gmail.com)
  1166. Date: 2010-04-01 [Happy April Fool's!]
  1167. ********************************************************/
  1168. function PPHttpPost($methodName_, $nvpStr_, $credentials) {
  1169. $environment = PAYPAL_ENVIRONMENT;
  1170. $pp_user = $credentials['pp_api_username'];
  1171. $pp_pass = $credentials['pp_api_password'];
  1172. $pp_signature = $credentials['pp_api_signature'];
  1173. $API_Endpoint = "https://api-3t.paypal.com/nvp";
  1174. if("sandbox" === $environment || "beta-sandbox" === $environment) {
  1175. $API_Endpoint = "https://api.$environment.paypal.com/nvp";
  1176. }
  1177. $version = urlencode('51.0');
  1178. // Set the curl parameters.
  1179. $ch = curl_init();
  1180. curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
  1181. curl_setopt($ch, CURLOPT_VERBOSE, 1);
  1182. // Turn off the server and peer verification (TrustManager Concept).
  1183. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1184. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  1185. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  1186. curl_setopt($ch, CURLOPT_POST, 1);
  1187. // Set the API operation, version, and API signature in the request.
  1188. $nvpreq = 'METHOD='.$methodName_.'&VERSION='.$version.'&PWD='.$pp_pass.'&USER='.$pp_user.'&SIGNATURE='.$pp_signature.''.$nvpStr_;
  1189. // Set the request as a POST FIELD for curl.
  1190. curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
  1191. // Get response from the server.
  1192. $httpResponse = curl_exec($ch);
  1193. if(!$httpResponse) {
  1194. exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
  1195. }
  1196. // Extract the response details.
  1197. $httpResponseAr = explode("&", $httpResponse);
  1198. $httpParsedResponseAr = array();
  1199. foreach ($httpResponseAr as $i => $value) {
  1200. $tmpAr = explode("=", $value);
  1201. if(sizeof($tmpAr) > 1) {
  1202. $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
  1203. }
  1204. }
  1205. $httpParsedResponseAr["nvpEndpoint"] = $API_Endpoint;
  1206. $httpParsedResponseAr["nvpString"] = $nvpreq;
  1207. if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
  1208. exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
  1209. }
  1210. return $httpParsedResponseAr;
  1211. }
  1212. /* send_email
  1213. *
  1214. * send email using local mail()
  1215. */
  1216. function send_email($to, $subject, $html, $plain = null, $headers = array()) {
  1217. //Validate arguments
  1218. $html= replaceEncodedNewLinesWithBr($html);
  1219. if (empty($to) ||
  1220. empty($subject) ||
  1221. (empty($html) && empty($plain) ||
  1222. !is_array($headers))) {
  1223. error_log("attempted to send an empty or misconfigured message");
  1224. return false;
  1225. }
  1226. $nameAndAddressRege

Large files files are truncated, but you can click here to view the full file