PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/event/main_listener.php

https://github.com/phpbb/customisation-db
PHP | 409 lines | 265 code | 65 blank | 79 comment | 20 complexity | ff4aeb0ef161f37028f47f49f7f9d609 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * This file is part of the phpBB Customisation Database 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\titania\event;
  14. use phpbb\db\driver\driver_interface as db_driver_interface;
  15. use phpbb\event\data;
  16. use phpbb\auth\auth;
  17. use phpbb\template\template;
  18. use phpbb\titania\controller\helper;
  19. use phpbb\titania\ext;
  20. use phpbb\user;
  21. use phpbb\request\request;
  22. use phpbb\titania\contribution\type\collection as type_collection;
  23. use phpbb\titania\access;
  24. use s9e\TextFormatter\Configurator\Items\TemplateDocument;
  25. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  26. use Symfony\Component\HttpKernel\HttpKernelInterface;
  27. /**
  28. * Event listener
  29. */
  30. class main_listener implements EventSubscriberInterface
  31. {
  32. /** @var request */
  33. protected $request;
  34. /** @var db_driver_interface */
  35. protected $db;
  36. /** @var \phpbb\user */
  37. protected $user;
  38. /** @var \phpbb\template\template */
  39. protected $template;
  40. /** @var \phpbb\titania\controller\helper */
  41. protected $controller_helper;
  42. /** @var access */
  43. protected $access;
  44. /** @var type_collection */
  45. protected $types;
  46. /** @var string */
  47. protected $phpbb_root_path;
  48. /** @var string */
  49. protected $php_ext;
  50. /** @var string */
  51. protected $ext_root_path;
  52. /** @var bool */
  53. protected $in_titania;
  54. /**
  55. * Constructor
  56. *
  57. * @param request $request
  58. * @param db_driver_interface $db
  59. * @param \phpbb\user $user
  60. * @param \phpbb\template\template $template
  61. * @param \phpbb\titania\controller\helper $controller_helper
  62. * @param access $access
  63. * @param type_collection $types
  64. * @param string $phpbb_root_path phpBB root path
  65. * @param string $ext_root_path Titania root path
  66. * @param string $php_ext PHP file extension
  67. */
  68. public function __construct(request $request, db_driver_interface $db, user $user, template $template, helper $controller_helper, access $access, type_collection $types, $phpbb_root_path, $ext_root_path, $php_ext)
  69. {
  70. $this->request = $request;
  71. $this->db = $db;
  72. $this->user = $user;
  73. $this->template = $template;
  74. $this->controller_helper = $controller_helper;
  75. $this->access = $access;
  76. $this->types = $types;
  77. $this->phpbb_root_path = $phpbb_root_path;
  78. $this->php_ext = $php_ext;
  79. $this->ext_root_path = $ext_root_path;
  80. $this->in_titania = false;
  81. }
  82. static public function getSubscribedEvents()
  83. {
  84. return array(
  85. 'core.permissions' => 'add_permissions',
  86. 'kernel.request' => array(array('startup', -1)),
  87. 'core.page_header_after' => 'overwrite_template_vars',
  88. 'core.text_formatter_s9e_configure_after' => 'inject_bbcode_code_lang',
  89. // Check whether a user is removed from a team
  90. 'core.group_delete_user_after' => 'remove_users_from_subscription',
  91. // Include quoted text when private messaging
  92. 'core.ucp_pm_compose_predefined_message' => 'quote_text_upon_pm',
  93. );
  94. }
  95. public function add_permissions($event)
  96. {
  97. $event['categories'] = array_merge($event['categories'], array(
  98. 'titania' => 'ACL_CAT_TITANIA',
  99. 'titania_moderate' => 'ACL_CAT_TITANIA_MODERATE',
  100. ));
  101. $event['permissions'] = array_merge($event['permissions'], array(
  102. // Common
  103. 'u_titania_contrib_submit' => array('lang' => 'ACL_U_TITANIA_CONTRIB_SUBMIT', 'cat' => 'titania'),
  104. 'u_titania_faq_create' => array('lang' => 'ACL_U_TITANIA_FAQ_CREATE', 'cat' => 'titania'),
  105. 'u_titania_faq_edit' => array('lang' => 'ACL_U_TITANIA_FAQ_EDIT', 'cat' => 'titania'),
  106. 'u_titania_faq_delete' => array('lang' => 'ACL_U_TITANIA_FAQ_DELETE', 'cat' => 'titania'),
  107. 'u_titania_rate' => array('lang' => 'ACL_U_TITANIA_RATE', 'cat' => 'titania'),
  108. 'u_titania_topic' => array('lang' => 'ACL_U_TITANIA_TOPIC', 'cat' => 'titania'),
  109. 'u_titania_post' => array('lang' => 'ACL_U_TITANIA_POST', 'cat' => 'titania'),
  110. 'u_titania_post_approved' => array('lang' => 'ACL_U_TITANIA_POST_APPROVED', 'cat' => 'titania'),
  111. 'u_titania_post_edit_own' => array('lang' => 'ACL_U_TITANIA_POST_EDIT_OWN', 'cat' => 'titania'),
  112. 'u_titania_post_delete_own' => array('lang' => 'ACL_U_TITANIA_POST_DELETE_OWN', 'cat' => 'titania'),
  113. 'u_titania_post_mod_own' => array('lang' => 'ACL_U_TITANIA_POST_MOD_OWN', 'cat' => 'titania'),
  114. 'u_titania_post_attach' => array('lang' => 'ACL_U_TITANIA_POST_ATTACH', 'cat' => 'titania'),
  115. 'u_titania_bbcode' => array('lang' => 'ACL_U_TITANIA_BBCODE', 'cat' => 'titania'),
  116. 'u_titania_smilies' => array('lang' => 'ACL_U_TITANIA_SMILIES', 'cat' => 'titania'),
  117. 'u_titania_post_hard_delete' => array('lang' => 'ACL_U_TITANIA_POST_HARD_DELETE', 'cat' => 'titania'),
  118. // Moderation
  119. 'u_titania_mod_author_mod' => array('lang' => 'ACL_U_TITANIA_MOD_AUTHOR_MOD', 'cat' => 'titania_moderate'),
  120. 'u_titania_mod_contrib_mod' => array('lang' => 'ACL_U_TITANIA_MOD_CONTRIB_MOD', 'cat' => 'titania_moderate'),
  121. 'u_titania_mod_faq_mod' => array('lang' => 'ACL_U_TITANIA_MOD_FAQ_MOD', 'cat' => 'titania_moderate'),
  122. 'u_titania_mod_rate_reset' => array('lang' => 'ACL_U_TITANIA_MOD_RATE_RESET', 'cat' => 'titania_moderate'),
  123. 'u_titania_mod_post_mod' => array('lang' => 'ACL_U_TITANIA_MOD_POST_MOD', 'cat' => 'titania_moderate'),
  124. 'u_titania_mod_style_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_STYLE_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  125. 'u_titania_mod_style_queue' => array('lang' => 'ACL_U_TITANIA_MOD_STYLE_QUEUE', 'cat' => 'titania_moderate'),
  126. 'u_titania_mod_style_validate' => array('lang' => 'ACL_U_TITANIA_MOD_STYLE_VALIDATE', 'cat' => 'titania_moderate'),
  127. 'u_titania_mod_style_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_STYLE_MODERATE', 'cat' => 'titania_moderate'),
  128. 'u_titania_mod_style_clr' => array('lang' => 'ACL_U_TITANIA_MOD_STYLE_CLR', 'cat' => 'titania_moderate'),
  129. 'u_titania_mod_modification_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_MODIFICATION_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  130. 'u_titania_mod_modification_queue' => array('lang' => 'ACL_U_TITANIA_MOD_MODIFICATION_QUEUE', 'cat' => 'titania_moderate'),
  131. 'u_titania_mod_modification_validate' => array('lang' => 'ACL_U_TITANIA_MOD_MODIFICATION_VALIDATE', 'cat' => 'titania_moderate'),
  132. 'u_titania_mod_modification_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_MODIFICATION_MODERATE', 'cat' => 'titania_moderate'),
  133. 'u_titania_mod_translation_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_TRANSLATION_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  134. 'u_titania_mod_translation_queue' => array('lang' => 'ACL_U_TITANIA_MOD_TRANSLATION_QUEUE', 'cat' => 'titania_moderate'),
  135. 'u_titania_mod_translation_validate' => array('lang' => 'ACL_U_TITANIA_MOD_TRANSLATION_VALIDATE', 'cat' => 'titania_moderate'),
  136. 'u_titania_mod_translation_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_TRANSLATION_MODERATE', 'cat' => 'titania_moderate'),
  137. 'u_titania_mod_converter_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_CONVERTER_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  138. 'u_titania_mod_converter_queue' => array('lang' => 'ACL_U_TITANIA_MOD_CONVERTER_QUEUE', 'cat' => 'titania_moderate'),
  139. 'u_titania_mod_converter_validate' => array('lang' => 'ACL_U_TITANIA_MOD_CONVERTER_VALIDATE', 'cat' => 'titania_moderate'),
  140. 'u_titania_mod_converter_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_CONVERTER_MODERATE', 'cat' => 'titania_moderate'),
  141. 'u_titania_mod_bbcode_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_BBCODE_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  142. 'u_titania_mod_bbcode_queue' => array('lang' => 'ACL_U_TITANIA_MOD_BBCODE_QUEUE', 'cat' => 'titania_moderate'),
  143. 'u_titania_mod_bbcode_validate' => array('lang' => 'ACL_U_TITANIA_MOD_BBCODE_VALIDATE', 'cat' => 'titania_moderate'),
  144. 'u_titania_mod_bbcode_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_BBCODE_MODERATE', 'cat' => 'titania_moderate'),
  145. 'u_titania_mod_bridge_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_BRIDGE_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  146. 'u_titania_mod_bridge_queue' => array('lang' => 'ACL_U_TITANIA_MOD_BRIDGE_QUEUE', 'cat' => 'titania_moderate'),
  147. 'u_titania_mod_bridge_validate' => array('lang' => 'ACL_U_TITANIA_MOD_BRIDGE_VALIDATE', 'cat' => 'titania_moderate'),
  148. 'u_titania_mod_bridge_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_BRIDGE_MODERATE', 'cat' => 'titania_moderate'),
  149. 'u_titania_mod_official_tool_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_OFFICIAL_TOOL_MODERATE', 'cat' => 'titania_moderate'),
  150. 'u_titania_mod_extension_queue_discussion' => array('lang' => 'ACL_U_TITANIA_MOD_EXTENSION_QUEUE_DISCUSSION', 'cat' => 'titania_moderate'),
  151. 'u_titania_mod_extension_queue' => array('lang' => 'ACL_U_TITANIA_MOD_EXTENSION_QUEUE', 'cat' => 'titania_moderate'),
  152. 'u_titania_mod_extension_validate' => array('lang' => 'ACL_U_TITANIA_MOD_EXTENSION_VALIDATE', 'cat' => 'titania_moderate'),
  153. 'u_titania_mod_extension_moderate' => array('lang' => 'ACL_U_TITANIA_MOD_EXTENSION_MODERATE', 'cat' => 'titania_moderate'),
  154. 'u_titania_admin' => array('lang' => 'ACL_U_TITANIA_ADMIN', 'cat' => 'titania_moderate'),
  155. ));
  156. }
  157. public function startup($event)
  158. {
  159. if ($event->getRequestType() !== HttpKernelInterface::MASTER_REQUEST ||
  160. strpos($event->getRequest()->attributes->get('_controller'), 'phpbb.titania') !== 0)
  161. {
  162. return;
  163. }
  164. $this->in_titania = true;
  165. require($this->ext_root_path . 'common.' . $this->php_ext);
  166. }
  167. public function overwrite_template_vars($event)
  168. {
  169. if ($this->user->data['is_registered'] && !$this->user->data['is_bot'])
  170. {
  171. $this->user->add_lang_ext('phpbb/titania', 'common');
  172. $u_my_contribs = $this->controller_helper->route('phpbb.titania.author', array(
  173. 'author' => urlencode($this->user->data['username_clean']),
  174. 'page' => 'contributions',
  175. ));
  176. $this->template->assign_vars(array(
  177. 'U_MY_CONTRIBUTIONS' => $this->controller_helper->get_real_url($u_my_contribs),
  178. ));
  179. }
  180. if (!$this->in_titania)
  181. {
  182. return;
  183. }
  184. $this->template->assign_vars(array(
  185. 'U_FAQ' => $this->controller_helper->route('phpbb.titania.faq'),
  186. 'U_SEARCH' => $this->controller_helper->route('phpbb.titania.search'),
  187. 'S_BODY_CLASS' => 'customisation-database',
  188. ));
  189. if ($this->user->data['user_id'] == ANONYMOUS)
  190. {
  191. $this->template->assign_vars(array(
  192. 'U_LOGIN_LOGOUT' => append_sid(
  193. "{$this->phpbb_root_path}ucp.{$this->php_ext}",
  194. array(
  195. 'mode' => 'login',
  196. 'redirect' => urlencode($this->controller_helper->get_current_url()),
  197. )
  198. ),
  199. ));
  200. }
  201. }
  202. /**
  203. * Reads the value for the lang attribute passed to each code BBCode, e.g. [code=diff] or [code lang=diff],
  204. * and adds it as a class attribute to the code element, e.g. <code class="diff">
  205. *
  206. * @param data $event
  207. */
  208. public function inject_bbcode_code_lang(data $event)
  209. {
  210. $tag = $event['configurator']->tags['CODE'];
  211. /** @var TemplateDocument $dom */
  212. $dom = $tag->template->asDOM();
  213. foreach ($dom->getElementsByTagName('code') as $code)
  214. {
  215. /** @var \DOMElement $code */
  216. $code->setAttribute('class', '{@lang}');
  217. }
  218. $dom->saveChanges();
  219. }
  220. /**
  221. * Remove users from queue subscription if they are removed from a team and subsequently lose all queue permissions
  222. * @param $event
  223. */
  224. public function remove_users_from_subscription($event)
  225. {
  226. if (!defined('TITANIA_WATCH_TABLE'))
  227. {
  228. // Include Titania so we can access the constants
  229. require($this->ext_root_path . 'common.' . $this->php_ext);
  230. }
  231. $queue_permissions = array(
  232. 'u_titania_mod_extension_queue',
  233. 'u_titania_mod_bridge_queue',
  234. 'u_titania_mod_bbcode_queue',
  235. 'u_titania_mod_converter_queue',
  236. 'u_titania_mod_translation_queue',
  237. 'u_titania_mod_modification_queue',
  238. 'u_titania_mod_style_queue'
  239. );
  240. $remove_user_ids = array();
  241. foreach ($event['user_id_ary'] as $user_id)
  242. {
  243. // For every user removed from the group, check if they should still receive emails
  244. $auth = new auth();
  245. $user_data = $auth->obtain_user_data($user_id);
  246. $auth->acl($user_data);
  247. $has_queue_access = false;
  248. foreach ($queue_permissions as $permission)
  249. {
  250. // If the user has access to any of the private queues, then it can be assumed they
  251. // will still be eligible to receive emails.
  252. if ($auth->acl_get($permission))
  253. {
  254. $has_queue_access = true;
  255. break;
  256. }
  257. }
  258. if (!$has_queue_access)
  259. {
  260. // Remove queue subscriptions
  261. $remove_user_ids[] = (int) $user_id;
  262. }
  263. }
  264. // Only continue if there are users to remove from the Titania queue subscriptions
  265. if (count($remove_user_ids))
  266. {
  267. // Remove subscription
  268. $sql = 'DELETE FROM ' . TITANIA_WATCH_TABLE . '
  269. WHERE ' . $this->db->sql_in_set('watch_user_id', $remove_user_ids) . '
  270. AND watch_object_type = ' . ext::TITANIA_QUEUE;
  271. $this->db->sql_query($sql);
  272. }
  273. }
  274. /**
  275. * When a user sends a PM from a Titania support topic, include the post as quoted text
  276. * @param $event
  277. */
  278. public function quote_text_upon_pm($event)
  279. {
  280. if (!defined('TITANIA_POSTS_TABLE'))
  281. {
  282. // Include Titania so we can access the constants
  283. require($this->ext_root_path . 'common.' . $this->php_ext);
  284. }
  285. // Check that this user has access to the Titania support post ID so that people can't just randomly
  286. // stick an ID in the URL and see the post contents
  287. $titania_post_id = $this->request->variable('titania_msg_id', 0);
  288. $access = $this->access;
  289. $sql_ary = array(
  290. 'SELECT' => 'p.post_id, p.post_text, p.post_subject, p.post_time, p.post_access, t.topic_access,
  291. t.topic_id, t.parent_id, u.user_id, u.username, c.contrib_name_clean, c.contrib_type',
  292. 'FROM' => array(
  293. TITANIA_POSTS_TABLE => 'p',
  294. TITANIA_TOPICS_TABLE => 't',
  295. TITANIA_CONTRIBS_TABLE => 'c',
  296. USERS_TABLE => 'u',
  297. ),
  298. 'WHERE' => 'p.post_approved = 1
  299. AND t.topic_approved = 1
  300. AND t.topic_type = ' . ext::TITANIA_SUPPORT . '
  301. AND p.post_id = ' . $titania_post_id . '
  302. AND t.topic_id = p.topic_id
  303. AND u.user_id = p.post_user_id
  304. AND t.parent_id = c.contrib_id',
  305. );
  306. $sql = $this->db->sql_build_query('SELECT', $sql_ary);
  307. $result = $this->db->sql_query($sql);
  308. $row = $this->db->sql_fetchrow($result);
  309. $contrib = new \titania_contribution;
  310. if ($row && $contrib->load((int) $row['parent_id'], $row['contrib_type']) && $contrib->is_visible())
  311. {
  312. if ($this->access->is_public() && ($contrib->is_active_coauthor || $contrib->is_author))
  313. {
  314. // If the current user is the author of the contribution they are trying to quote/PM from
  315. // then set their user level to author
  316. $this->access->set_level(access::AUTHOR_LEVEL);
  317. }
  318. // Now do a check to make sure their access level is sufficient.
  319. // This is to make sure authors can't see posts that are teams-only, and that the public can't see
  320. // any posts that are author-only.
  321. if ($row['post_access'] >= $access->get_level() && $row['topic_access'] >= $access->get_level())
  322. {
  323. // Add the subject of the Titania post to the PM
  324. $event['message_subject'] = $row['post_subject'];
  325. // If "Re:" isn't already on the subject line, add it for the private message
  326. if (strpos($event['message_subject'], 'Re: ') !== 0)
  327. {
  328. $event['message_subject'] = 'Re: ' . $event['message_subject'];
  329. }
  330. // Add the quote to the message
  331. // Format like: /foo/bar?p=123#p123
  332. $post_url = sprintf('%1$s?p=%2$d#p%2$d', $this->controller_helper->route('phpbb.titania.contrib.support.topic', array(
  333. 'contrib_type' => $this->types->get($row['contrib_type'])->url,
  334. 'contrib' => $row['contrib_name_clean'],
  335. 'topic_id' => $row['topic_id']
  336. )), (int) $row['post_id']);
  337. $post_url = sprintf('[url=%s]%s[/url]', $post_url, $this->user->lang('FWD_SUBJECT', $row['post_subject']));
  338. // No indenting here because it would appear in the send PM box
  339. $event['message_text'] = sprintf('%s
  340. [quote=%s time=%d user_id=%d]%s[/quote]', $post_url, $row['username'], $row['post_time'], $row['user_id'], $row['post_text']);
  341. }
  342. }
  343. }
  344. }