PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/wwwroot/phpbb/phpbb/notification/type/base.php

https://github.com/spring/spring-website
PHP | 569 lines | 259 code | 81 blank | 229 comment | 15 complexity | 772125ebe27e15fdb1be55869395adf7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, LGPL-3.0, BSD-3-Clause
  1. <?php
  2. /**
  3. *
  4. * This file is part of the phpBB Forum Software package.
  5. *
  6. * @copyright (c) phpBB Limited <https://www.phpbb.com>
  7. * @license GNU General Public License, version 2 (GPL-2.0)
  8. *
  9. * For full copyright and license information, please see
  10. * the docs/CREDITS.txt file.
  11. *
  12. */
  13. namespace phpbb\notification\type;
  14. /**
  15. * Base notifications class
  16. */
  17. abstract class base implements \phpbb\notification\type\type_interface
  18. {
  19. /** @var \phpbb\notification\manager */
  20. protected $notification_manager;
  21. /** @var \phpbb\user_loader */
  22. protected $user_loader;
  23. /** @var \phpbb\db\driver\driver_interface */
  24. protected $db;
  25. /** @var \phpbb\cache\driver\driver_interface */
  26. protected $cache;
  27. /** @var \phpbb\template\template */
  28. protected $template;
  29. /** @var \phpbb\user */
  30. protected $user;
  31. /** @var \phpbb\auth\auth */
  32. protected $auth;
  33. /** @var \phpbb\config\config */
  34. protected $config;
  35. /** @var string */
  36. protected $phpbb_root_path;
  37. /** @var string */
  38. protected $php_ext;
  39. /** @var string */
  40. protected $notification_types_table;
  41. /** @var string */
  42. protected $notifications_table;
  43. /** @var string */
  44. protected $user_notifications_table;
  45. /**
  46. * Notification option data (for outputting to the user)
  47. *
  48. * @var bool|array False if the service should use its default data
  49. * Array of data (including keys 'id', 'lang', and 'group')
  50. */
  51. public static $notification_option = false;
  52. /**
  53. * The notification_type_id, set upon creation of the class
  54. * This is the notification_type_id from the notification_types table
  55. *
  56. * @var int
  57. */
  58. protected $notification_type_id;
  59. /**
  60. * Indentification data
  61. * notification_type_id - ID of the item type (auto generated, from notification types table)
  62. * item_id - ID of the item (e.g. post_id, msg_id)
  63. * item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
  64. * user_id
  65. * notification_read
  66. * notification_time
  67. * notification_data (special serialized field that each notification type can use to store stuff)
  68. *
  69. * @var array $data Notification row from the database
  70. * This must be private, all interaction should use __get(), __set(), get_data(), set_data()
  71. */
  72. private $data = array();
  73. /**
  74. * Notification Type Base Constructor
  75. *
  76. * @param \phpbb\user_loader $user_loader
  77. * @param \phpbb\db\driver\driver_interface $db
  78. * @param \phpbb\cache\driver\driver_interface $cache
  79. * @param \phpbb\user $user
  80. * @param \phpbb\auth\auth $auth
  81. * @param \phpbb\config\config $config
  82. * @param string $phpbb_root_path
  83. * @param string $php_ext
  84. * @param string $notification_types_table
  85. * @param string $notifications_table
  86. * @param string $user_notifications_table
  87. * @return \phpbb\notification\type\base
  88. */
  89. public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
  90. {
  91. $this->user_loader = $user_loader;
  92. $this->db = $db;
  93. $this->cache = $cache;
  94. $this->user = $user;
  95. $this->auth = $auth;
  96. $this->config = $config;
  97. $this->phpbb_root_path = $phpbb_root_path;
  98. $this->php_ext = $php_ext;
  99. $this->notification_types_table = $notification_types_table;
  100. $this->notifications_table = $notifications_table;
  101. $this->user_notifications_table = $user_notifications_table;
  102. }
  103. /**
  104. * Set notification manager (required)
  105. *
  106. * @param \phpbb\notification\manager $notification_manager
  107. */
  108. public function set_notification_manager(\phpbb\notification\manager $notification_manager)
  109. {
  110. $this->notification_manager = $notification_manager;
  111. $this->notification_type_id = $this->notification_manager->get_notification_type_id($this->get_type());
  112. }
  113. /**
  114. * Set initial data from the database
  115. *
  116. * @param array $data Row directly from the database
  117. */
  118. public function set_initial_data($data = array())
  119. {
  120. // The row from the database (unless this is a new notification we're going to add)
  121. $this->data = $data;
  122. $this->data['notification_data'] = (isset($this->data['notification_data'])) ? unserialize($this->data['notification_data']) : array();
  123. }
  124. /**
  125. * Magic method to get data from this notification
  126. *
  127. * @param mixed $name
  128. * @return mixed
  129. */
  130. public function __get($name)
  131. {
  132. return (!isset($this->data[$name])) ? null : $this->data[$name];
  133. }
  134. /**
  135. * Magic method to set data on this notification
  136. *
  137. * @param mixed $name
  138. * @param mixed $value
  139. *
  140. * @return null
  141. */
  142. public function __set($name, $value)
  143. {
  144. $this->data[$name] = $value;
  145. }
  146. /**
  147. * Magic method to get a string of this notification
  148. *
  149. * Primarily for testing
  150. *
  151. * @return mixed
  152. */
  153. public function __toString()
  154. {
  155. return (!empty($this->data)) ? var_export($this->data, true) : $this->get_type();
  156. }
  157. /**
  158. * Get special data (only important for the classes that extend this)
  159. *
  160. * @param string $name Name of the variable to get
  161. * @return mixed
  162. */
  163. protected function get_data($name)
  164. {
  165. return ($name === false) ? $this->data['notification_data'] : ((isset($this->data['notification_data'][$name])) ? $this->data['notification_data'][$name] : null);
  166. }
  167. /**
  168. * Set special data (only important for the classes that extend this)
  169. *
  170. * @param string $name Name of the variable to set
  171. * @param mixed $value Value to set to the variable
  172. * @return mixed
  173. */
  174. protected function set_data($name, $value)
  175. {
  176. $this->data['notification_data'][$name] = $value;
  177. }
  178. /**
  179. * Function for preparing the data for insertion in an SQL query
  180. * (The service handles insertion)
  181. *
  182. * @param array $type_data Data unique to this notification type
  183. * @param array $pre_create_data Data from pre_create_insert_array()
  184. * @return array Array of data ready to be inserted into the database
  185. */
  186. public function create_insert_array($type_data, $pre_create_data = array())
  187. {
  188. // Defaults
  189. $this->data = array_merge(array(
  190. 'item_id' => static::get_item_id($type_data),
  191. 'notification_type_id' => $this->notification_type_id,
  192. 'item_parent_id' => static::get_item_parent_id($type_data),
  193. 'notification_time' => time(),
  194. 'notification_read' => false,
  195. 'notification_data' => array(),
  196. ), $this->data);
  197. $data = $this->data;
  198. $data['notification_data'] = serialize($data['notification_data']);
  199. return $data;
  200. }
  201. /**
  202. * Function for preparing the data for update in an SQL query
  203. * (The service handles insertion)
  204. *
  205. * @param array $type_data Data unique to this notification type
  206. * @return array Array of data ready to be updated in the database
  207. */
  208. public function create_update_array($type_data)
  209. {
  210. $data = $this->create_insert_array($type_data);
  211. // Unset data unique to each row
  212. unset(
  213. $data['notification_time'], // Also unsetting time, since it always tries to change the time to current (if you actually need to change the time, over-ride this function)
  214. $data['notification_id'],
  215. $data['notification_read'],
  216. $data['user_id']
  217. );
  218. return $data;
  219. }
  220. /**
  221. * Mark this item read
  222. *
  223. * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
  224. * @return string|null If $return is False, nothing will be returned, else the sql code to update this item
  225. */
  226. public function mark_read($return = false)
  227. {
  228. return $this->mark(false, $return);
  229. }
  230. /**
  231. * Mark this item unread
  232. *
  233. * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
  234. * @return string|null If $return is False, nothing will be returned, else the sql code to update this item
  235. */
  236. public function mark_unread($return = false)
  237. {
  238. return $this->mark(true, $return);
  239. }
  240. /**
  241. * {inheritDoc}
  242. */
  243. public function get_redirect_url()
  244. {
  245. return $this->get_url();
  246. }
  247. /**
  248. * Prepare to output the notification to the template
  249. *
  250. * @return array Template variables
  251. */
  252. public function prepare_for_display()
  253. {
  254. $mark_hash = generate_link_hash('mark_notification_read');
  255. if ($this->get_url())
  256. {
  257. $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;hash=' . $mark_hash);
  258. }
  259. else
  260. {
  261. $redirect = (($this->user->page['page_dir']) ? $this->user->page['page_dir'] . '/' : '') . $this->user->page['page_name'] . (($this->user->page['query_string']) ? '?' . $this->user->page['query_string'] : '');
  262. $u_mark_read = append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'mark_notification=' . $this->notification_id . '&amp;hash=' . $mark_hash . '&amp;redirect=' . urlencode($redirect));
  263. }
  264. return array(
  265. 'NOTIFICATION_ID' => $this->notification_id,
  266. 'STYLING' => $this->get_style_class(),
  267. 'AVATAR' => $this->get_avatar(),
  268. 'FORMATTED_TITLE' => $this->get_title(),
  269. 'REFERENCE' => $this->get_reference(),
  270. 'FORUM' => $this->get_forum(),
  271. 'REASON' => $this->get_reason(),
  272. 'URL' => $this->get_url(),
  273. 'TIME' => $this->user->format_date($this->notification_time),
  274. 'UNREAD' => !$this->notification_read,
  275. 'U_MARK_READ' => (!$this->notification_read) ? $u_mark_read : '',
  276. );
  277. }
  278. /**
  279. * -------------- Fall back functions -------------------
  280. */
  281. /**
  282. * URL to unsubscribe to this notification (fall back)
  283. *
  284. * @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item
  285. */
  286. public function get_unsubscribe_url($method = false)
  287. {
  288. return false;
  289. }
  290. /**
  291. * Get the CSS style class of the notification (fall back)
  292. *
  293. * @return string
  294. */
  295. public function get_style_class()
  296. {
  297. return '';
  298. }
  299. /**
  300. * Get the user's avatar (fall back)
  301. *
  302. * @return string
  303. */
  304. public function get_avatar()
  305. {
  306. return '';
  307. }
  308. /**
  309. * Get the reference of the notifcation (fall back)
  310. *
  311. * @return string
  312. */
  313. public function get_reference()
  314. {
  315. return '';
  316. }
  317. /**
  318. * Get the forum of the notification reference (fall back)
  319. *
  320. * @return string
  321. */
  322. public function get_forum()
  323. {
  324. return '';
  325. }
  326. /**
  327. * Get the reason for the notifcation (fall back)
  328. *
  329. * @return string
  330. */
  331. public function get_reason()
  332. {
  333. return '';
  334. }
  335. /**
  336. * Get the special items to load (fall back)
  337. *
  338. * @return array
  339. */
  340. public function get_load_special()
  341. {
  342. return array();
  343. }
  344. /**
  345. * Load the special items (fall back)
  346. */
  347. public function load_special($data, $notifications)
  348. {
  349. return;
  350. }
  351. /**
  352. * Is available (fall back)
  353. *
  354. * @return bool
  355. */
  356. public function is_available()
  357. {
  358. return true;
  359. }
  360. /**
  361. * Pre create insert array function (fall back)
  362. *
  363. * @return array
  364. */
  365. public function pre_create_insert_array($type_data, $notify_users)
  366. {
  367. return array();
  368. }
  369. /**
  370. * -------------- Helper functions -------------------
  371. */
  372. /**
  373. * Find the users who want to receive notifications (helper)
  374. *
  375. * @param array $user_ids User IDs to check if they want to receive notifications
  376. * (Bool False to check all users besides anonymous and bots (USER_IGNORE))
  377. *
  378. * @return array
  379. */
  380. protected function check_user_notification_options($user_ids = false, $options = array())
  381. {
  382. $options = array_merge(array(
  383. 'ignore_users' => array(),
  384. 'item_type' => $this->get_type(),
  385. 'item_id' => 0, // Global by default
  386. ), $options);
  387. if ($user_ids === false)
  388. {
  389. $user_ids = array();
  390. $sql = 'SELECT user_id
  391. FROM ' . USERS_TABLE . '
  392. WHERE user_id <> ' . ANONYMOUS . '
  393. AND user_type <> ' . USER_IGNORE;
  394. $result = $this->db->sql_query($sql);
  395. while ($row = $this->db->sql_fetchrow($result))
  396. {
  397. $user_ids[] = $row['user_id'];
  398. }
  399. $this->db->sql_freeresult($result);
  400. }
  401. if (empty($user_ids))
  402. {
  403. return array();
  404. }
  405. $rowset = $resulting_user_ids = array();
  406. $sql = 'SELECT user_id, method, notify
  407. FROM ' . $this->user_notifications_table . '
  408. WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . "
  409. AND item_type = '" . $this->db->sql_escape($options['item_type']) . "'
  410. AND item_id = " . (int) $options['item_id'];
  411. $result = $this->db->sql_query($sql);
  412. while ($row = $this->db->sql_fetchrow($result))
  413. {
  414. $resulting_user_ids[] = $row['user_id'];
  415. if (!$row['notify'] || (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']])))
  416. {
  417. continue;
  418. }
  419. if (!isset($rowset[$row['user_id']]))
  420. {
  421. $rowset[$row['user_id']] = array();
  422. }
  423. $rowset[$row['user_id']][] = $row['method'];
  424. }
  425. $this->db->sql_freeresult($result);
  426. foreach ($user_ids as $user_id)
  427. {
  428. if (!in_array($user_id, $resulting_user_ids) && !isset($options['ignore_users'][$user_id]))
  429. {
  430. // No rows at all for this user, default to ''
  431. $rowset[$user_id] = array('');
  432. }
  433. }
  434. return $rowset;
  435. }
  436. /**
  437. * Mark this item read/unread helper
  438. *
  439. * @param bool $unread Unread (True/False) (Default: False)
  440. * @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
  441. * @return string|null If $return is False, nothing will be returned, else the sql code to update this item
  442. */
  443. protected function mark($unread = true, $return = false)
  444. {
  445. $this->notification_read = (bool) !$unread;
  446. $where = array(
  447. 'notification_type_id = ' . (int) $this->notification_type_id,
  448. 'item_id = ' . (int) $this->item_id,
  449. 'user_id = ' . (int) $this->user_id,
  450. );
  451. $where = implode(' AND ', $where);
  452. if ($return)
  453. {
  454. return $where;
  455. }
  456. $sql = 'UPDATE ' . $this->notifications_table . '
  457. SET notification_read = ' . (int) $this->notification_read . '
  458. WHERE ' . $where;
  459. $this->db->sql_query($sql);
  460. }
  461. /**
  462. * Get a list of users that are authorised to receive notifications
  463. *
  464. * @param array $users Array of users that have subscribed to a notification
  465. * @param int $forum_id Forum ID of the forum
  466. * @param array $options Array of notification options
  467. * @param bool $sort Whether the users array should be sorted. Default: false
  468. * @return array Array of users that are authorised recipients
  469. */
  470. protected function get_authorised_recipients($users, $forum_id, $options, $sort = false)
  471. {
  472. if (empty($users))
  473. {
  474. return array();
  475. }
  476. $users = array_unique($users);
  477. if ($sort)
  478. {
  479. sort($users);
  480. }
  481. $auth_read = $this->auth->acl_get_list($users, 'f_read', $forum_id);
  482. if (empty($auth_read))
  483. {
  484. return array();
  485. }
  486. return $this->check_user_notification_options($auth_read[$forum_id]['f_read'], $options);
  487. }
  488. }