1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683:
<?php
if (!defined('SMF'))
die('No direct access...');
class Likes
{
protected $_js = false;
protected $_error = false;
protected $_type = '';
protected $_extra = false;
protected $_content = 0;
protected $_numLikes = 0;
protected $_alreadyLiked = false;
protected $_validLikes = array(
'can_like' => false,
'redirect' => '',
'type' => '',
'flush_cache' => '',
'callback' => false,
'json' => false,
);
protected $_user;
protected $_idTopic = 0;
protected $_setResponse = true;
public function __construct()
{
global $db_show_debug;
$this->_type = isset($_GET['ltype']) ? $_GET['ltype'] : '';
$this->_content = isset($_GET['like']) ? (int) $_GET['like'] : 0;
$this->_js = isset($_GET['js']) ? true : false;
$this->_sa = isset($_GET['sa']) ? $_GET['sa'] : 'like';
$this->_extra = isset($_GET['extra']) ? $_GET['extra'] : false;
if ($this->_js)
$db_show_debug = false;
}
public function call()
{
global $context;
$this->_user = $context['user'];
$this->check();
$subActions = array(
'like',
'view',
'delete',
'insert',
'_count',
);
if (in_array($this->_sa, $subActions) && !is_string($this->_error))
{
$call = $this->_sa;
if ($call != 'view')
is_not_guest();
checkSession('get');
$this->$call();
}
$this->response();
}
public function get($property = '')
{
$property = '_' . $property;
return property_exists($this, $property) ? $this->$property : false;
}
protected function check()
{
global $smcFunc, $modSettings;
if (empty($modSettings['enable_likes']))
return $this->_error = 'like_disable';
preg_match('~^([a-z0-9\-\_]{1,6})~i', $this->_type, $matches);
$this->_type = isset($matches[1]) ? $matches[1] : '';
if ($this->_type == '' || $this->_content <= 0)
return $this->_error = 'cannot_';
if ($this->_type == 'msg')
{
$request = $smcFunc['db_query']('', '
SELECT m.id_topic, m.id_member
FROM {db_prefix}messages AS m
INNER JOIN {db_prefix}boards AS b ON (m.id_board = b.id_board)
WHERE {query_see_board}
AND m.id_msg = {int:msg}',
array(
'msg' => $this->_content,
)
);
if ($smcFunc['db_num_rows']($request) == 1)
list ($this->_idTopic, $topicOwner) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
if (empty($this->_idTopic))
return $this->_error = 'cannot_';
$this->_validLikes['type'] = 'msg';
$this->_validLikes['flush_cache'] = 'likes_topic_' . $this->_idTopic . '_' . $this->_user['id'];
$this->_validLikes['redirect'] = 'topic=' . $this->_idTopic . '.msg' . $this->_content . '#msg' . $this->_content;
$this->_validLikes['can_like'] = ($this->_user['id'] == $topicOwner ? 'cannot_like_content' : (allowedTo('likes_like') ? true : 'cannot_like_content'));
}
else
{
$can_like = call_integration_hook('integrate_valid_likes', array($this->_type, $this->_content, $this->_sa, $this->_js, $this->_extra));
$found = false;
if (!empty($can_like))
{
$can_like = (array) $can_like;
foreach ($can_like as $result)
{
if ($result !== false)
{
if (!isset($result['type']) || $result['type'] != $this->_type)
return $this->_error = 'not_valid_like_type';
$this->_type = $result['type'];
$this->_validLikes = array_merge($this->_validLikes, $result);
$found = true;
break;
}
}
}
if (!$found)
return $this->_error = 'cannot_';
}
if ($this->_sa != 'view' && isset($this->_validLikes['can_like']) && is_string($this->_validLikes['can_like']))
return $this->_error = $this->_validLikes['can_like'];
}
protected function delete()
{
global $smcFunc;
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}user_likes
WHERE content_id = {int:like_content}
AND content_type = {string:like_type}
AND id_member = {int:id_member}',
array(
'like_content' => $this->_content,
'like_type' => $this->_type,
'id_member' => $this->_user['id'],
)
);
if ($this->_sa == __FUNCTION__)
$this->_data = __FUNCTION__;
}
protected function insert()
{
global $smcFunc;
$type = $this->_type;
$content = $this->_content;
$user = $this->_user;
$time = time();
call_integration_hook('integrate_issue_like_before', array(&$type, &$content, &$user, &$time));
$smcFunc['db_insert']('insert',
'{db_prefix}user_likes',
array('content_id' => 'int', 'content_type' => 'string-6', 'id_member' => 'int', 'like_time' => 'int'),
array($content, $type, $user['id'], $time),
array('content_id', 'content_type', 'id_member')
);
if ($this->_type == 'msg')
$smcFunc['db_insert']('insert',
'{db_prefix}background_tasks',
array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'),
array('$sourcedir/tasks/Likes-Notify.php', 'Likes_Notify_Background', $smcFunc['json_encode'](array(
'content_id' => $content,
'content_type' => $type,
'sender_id' => $user['id'],
'sender_name' => $user['name'],
'time' => $time,
)), 0),
array('id_task')
);
if ($this->_sa == __FUNCTION__)
$this->_data = __FUNCTION__;
}
protected function _count()
{
global $smcFunc;
$request = $smcFunc['db_query']('', '
SELECT COUNT(id_member)
FROM {db_prefix}user_likes
WHERE content_id = {int:like_content}
AND content_type = {string:like_type}',
array(
'like_content' => $this->_content,
'like_type' => $this->_type,
)
);
list ($this->_numLikes) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
if ($this->_sa == __FUNCTION__)
$this->_data = $this->_numLikes;
}
protected function like()
{
global $smcFunc;
if (empty($this->_type) || empty($this->_content))
return $this->_error = 'cannot_';
$request = $smcFunc['db_query']('', '
SELECT content_id, content_type, id_member
FROM {db_prefix}user_likes
WHERE content_id = {int:like_content}
AND content_type = {string:like_type}
AND id_member = {int:id_member}',
array(
'like_content' => $this->_content,
'like_type' => $this->_type,
'id_member' => $this->_user['id'],
)
);
$this->_alreadyLiked = (bool) $smcFunc['db_num_rows']($request) != 0;
$smcFunc['db_free_result']($request);
if ($this->_alreadyLiked)
$this->delete();
else
$this->insert();
$this->_count();
if ($this->_type == 'msg')
$this->msgIssueLike();
elseif (!empty($this->_validLikes['callback']))
{
$call = call_helper($this->_validLikes['callback'], true);
if (!empty($call))
call_user_func_array($call, array($this));
}
call_integration_hook('integrate_issue_like', array($this));
if (!empty($this->_validLikes['flush_cache']))
cache_put_data($this->_validLikes['flush_cache'], null);
$this->_data = array(
'id_topic' => !empty($this->_idTopic) ? $this->_idTopic : 0,
'id_content' => $this->_content,
'count' => $this->_numLikes,
'can_like' => $this->_validLikes['can_like'],
'already_liked' => empty($this->_alreadyLiked),
'type' => $this->_type,
);
}
function msgIssueLike()
{
global $smcFunc;
if ($this->_type !== 'msg')
return;
$smcFunc['db_query']('', '
UPDATE {db_prefix}messages
SET likes = {int:num_likes}
WHERE id_msg = {int:id_msg}',
array(
'id_msg' => $this->_content,
'num_likes' => $this->_numLikes,
)
);
}
function view()
{
global $smcFunc, $txt, $context, $memberContext;
$context['likers'] = array();
$request = $smcFunc['db_query']('', '
SELECT id_member, like_time
FROM {db_prefix}user_likes
WHERE content_id = {int:like_content}
AND content_type = {string:like_type}
ORDER BY like_time DESC',
array(
'like_content' => $this->_content,
'like_type' => $this->_type,
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
$context['likers'][$row['id_member']] = array('timestamp' => $row['like_time']);
$members = array_keys($context['likers']);
$loaded = loadMemberData($members);
if (count($loaded) != count($members))
{
$members = array_diff($members, $loaded);
foreach ($members as $not_loaded)
unset ($context['likers'][$not_loaded]);
}
foreach ($context['likers'] as $liker => $dummy)
{
$loaded = loadMemberContext($liker);
if (!$loaded)
{
unset ($context['likers'][$liker]);
continue;
}
$context['likers'][$liker]['profile'] = &$memberContext[$liker];
$context['likers'][$liker]['time'] = !empty($dummy['timestamp']) ? timeformat($dummy['timestamp']) : '';
}
$count = count($context['likers']);
$title_base = isset($txt['likes_' . $count]) ? 'likes_' . $count : 'likes_n';
$context['page_title'] = strip_tags(sprintf($txt[$title_base], '', comma_format($count)));
loadTemplate('Likes');
loadLanguage('Help');
$context['template_layers'] = array();
$context['sub_template'] = 'popup';
$this->_setResponse = false;
}
protected function response()
{
global $context, $txt;
if (!$this->_setResponse)
return;
if ($this->_validLikes['json'])
return $this->jsonResponse();
loadTemplate('Likes');
$context['template_layers'] = array();
if ($this->_error)
{
if ($this->_error == 'cannot_')
$this->_error = $this->_sa == 'view' ? 'cannot_view_likes' : 'cannot_like_content';
if ($this->_js)
{
$context['sub_template'] = 'generic';
$context['data'] = isset($txt[$this->_error]) ? $txt[$this->_error] : $txt['like_error'];
}
else
redirectexit(!empty($this->_validLikes['redirect']) ? $this->_validLikes['redirect'] . ';error=' . $this->_error : '');
return;
}
else
{
if (!$this->_js)
redirectexit(!empty($this->_validLikes['redirect']) ? $this->_validLikes['redirect'] : '');
$generic = array('delete', 'insert', '_count');
if (in_array($this->_sa, $generic))
{
$context['sub_template'] = 'generic';
$context['data'] = isset($txt['like_' . $this->_data]) ? $txt['like_' . $this->_data] : $this->_data;
}
else
{
$context['sub_template'] = $this->_sa;
$context['data'] = $this->_data;
}
}
}
protected function jsonResponse()
{
global $smcFunc;
$print = array(
'data' => $this->_data,
);
if ($this->_error)
{
if ($this->_error == 'cannot_')
$this->_error = $this->_sa == 'view' ? 'cannot_view_likes' : 'cannot_like_content';
$print['error'] = $this->_error;
}
call_integration_hook('integrate_likes_json_response', array(&$print));
smf_serverResponse($smcFunc['json_encode']($print));
die;
}
}
function BookOfUnknown()
{
global $context, $scripturl;
echo '<!DOCTYPE html>
<html', $context['right_to_left'] ? ' dir="rtl"' : '', '>
<head>
<title>The Book of Unknown, ', @$_GET['verse'] == '2:18' ? '2:18' : '4:16', '</title>
<style>
em
{
font-size: 1.3em;
line-height: 0;
}
</style>
</head>
<body style="background-color: #444455; color: white; font-style: italic; font-family: serif;">
<div style="margin-top: 12%; font-size: 1.1em; line-height: 1.4; text-align: center;">';
if (!isset($_GET['verse']) || ($_GET['verse'] != '2:18' && $_GET['verse'] != '22:1-2'))
$_GET['verse'] = '4:16';
if ($_GET['verse'] == '2:18')
echo '
Woe, it was that his name wasn\'t <em>known</em>, that he came in mystery, and was recognized by none. And it became to be in those days <em>something</em>. Something not yet <em id="unknown" name="[Unknown]">unknown</em> to mankind. And thus what was to be known the <em>secret project</em> began into its existence. Henceforth the opposition was only <em>weary</em> and <em>fearful</em>, for now their match was at arms against them.';
elseif ($_GET['verse'] == '4:16')
echo '
And it came to pass that the <em>unbelievers</em> dwindled in number and saw rise of many <em>proselytizers</em>, and the opposition found fear in the face of the <em>x</em> and the <em>j</em> while those who stood with the <em>something</em> grew stronger and came together. Still, this was only the <em>beginning</em>, and what lay in the future was <em id="unknown" name="[Unknown]">unknown</em> to all, even those on the right side.';
elseif ($_GET['verse'] == '22:1-2')
echo '
<p>Now <em>behold</em>, that which was once the secret project was <em id="unknown" name="[Unknown]">unknown</em> no longer. Alas, it needed more than <em>only one</em>, but yet even thought otherwise. It became that the opposition <em>rumored</em> and lied, but still to no avail. Their match, though not <em>perfect</em>, had them outdone.</p>
<p style="margin: 2ex 1ex 0 1ex; font-size: 1.05em; line-height: 1.5; text-align: center;">Let it continue. <em>The end</em>.</p>';
echo '
</div>
<div style="margin-top: 2ex; font-size: 2em; text-align: right;">';
if ($_GET['verse'] == '2:18')
echo '
from <span style="font-family: Georgia, serif;"><strong><a href="', $scripturl, '?action=about:unknown;verse=4:16" style="color: white; text-decoration: none; cursor: text;">The Book of Unknown</a></strong>, 2:18</span>';
elseif ($_GET['verse'] == '4:16')
echo '
from <span style="font-family: Georgia, serif;"><strong><a href="', $scripturl, '?action=about:unknown;verse=22:1-2" style="color: white; text-decoration: none; cursor: text;">The Book of Unknown</a></strong>, 4:16</span>';
elseif ($_GET['verse'] == '22:1-2')
echo '
from <span style="font-family: Georgia, serif;"><strong>The Book of Unknown</strong>, 22:1-2</span>';
echo '
</div>
</body>
</html>';
obExit(false);
}
?>