PageRenderTime 24ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/plugins/system/actionlogs/actionlogs.php

https://bitbucket.org/ke2083/transfans.co.uk-website
PHP | 445 lines | 261 code | 61 blank | 123 comment | 26 complexity | cbcdc7de51eb10f57c1ffaa70766ab5b MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Plugins
  4. * @subpackage System.actionlogs
  5. *
  6. * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. /**
  11. * Joomla! Users Actions Logging Plugin.
  12. *
  13. * @since 3.9.0
  14. */
  15. class PlgSystemActionLogs extends JPlugin
  16. {
  17. /**
  18. * Application object.
  19. *
  20. * @var JApplicationCms
  21. * @since 3.9.0
  22. */
  23. protected $app;
  24. /**
  25. * Database object.
  26. *
  27. * @var JDatabaseDriver
  28. * @since 3.9.0
  29. */
  30. protected $db;
  31. /**
  32. * Load plugin language file automatically so that it can be used inside component
  33. *
  34. * @var boolean
  35. * @since 3.9.0
  36. */
  37. protected $autoloadLanguage = true;
  38. /**
  39. * Constructor.
  40. *
  41. * @param object &$subject The object to observe.
  42. * @param array $config An optional associative array of configuration settings.
  43. *
  44. * @since 3.9.0
  45. */
  46. public function __construct(&$subject, $config)
  47. {
  48. parent::__construct($subject, $config);
  49. // Import actionlog plugin group so that these plugins will be triggered for events
  50. JPluginHelper::importPlugin('actionlog');
  51. }
  52. /**
  53. * Adds additional fields to the user editing form for logs e-mail notifications
  54. *
  55. * @param JForm $form The form to be altered.
  56. * @param mixed $data The associated data for the form.
  57. *
  58. * @return boolean
  59. *
  60. * @since 3.9.0
  61. */
  62. public function onContentPrepareForm($form, $data)
  63. {
  64. if (!$form instanceof JForm)
  65. {
  66. $this->subject->setError('JERROR_NOT_A_FORM');
  67. return false;
  68. }
  69. $formName = $form->getName();
  70. $allowedFormNames = array(
  71. 'com_users.profile',
  72. 'com_admin.profile',
  73. 'com_users.user',
  74. );
  75. if (!in_array($formName, $allowedFormNames))
  76. {
  77. return true;
  78. }
  79. /**
  80. * We only allow users who has Super User permission change this setting for himself or for other users
  81. * who has same Super User permission
  82. */
  83. $user = JFactory::getUser();
  84. if (!$user->authorise('core.admin'))
  85. {
  86. return true;
  87. }
  88. // If we are on the save command, no data is passed to $data variable, we need to get it directly from request
  89. $jformData = $this->app->input->get('jform', array(), 'array');
  90. if ($jformData && !$data)
  91. {
  92. $data = $jformData;
  93. }
  94. if (is_array($data))
  95. {
  96. $data = (object) $data;
  97. }
  98. if (empty($data->id) || !JUser::getInstance($data->id)->authorise('core.admin'))
  99. {
  100. return true;
  101. }
  102. JForm::addFormPath(dirname(__FILE__) . '/forms');
  103. $form->loadFile('actionlogs', false);
  104. }
  105. /**
  106. * Runs on content preparation
  107. *
  108. * @param string $context The context for the data
  109. * @param object $data An object containing the data for the form.
  110. *
  111. * @return boolean
  112. *
  113. * @since 3.9.0
  114. */
  115. public function onContentPrepareData($context, $data)
  116. {
  117. if (!in_array($context, array('com_users.profile', 'com_admin.profile', 'com_users.user')))
  118. {
  119. return true;
  120. }
  121. if (is_array($data))
  122. {
  123. $data = (object) $data;
  124. }
  125. if (!JUser::getInstance($data->id)->authorise('core.admin'))
  126. {
  127. return true;
  128. }
  129. $query = $this->db->getQuery(true)
  130. ->select($this->db->quoteName(array('notify', 'extensions')))
  131. ->from($this->db->quoteName('#__action_logs_users'))
  132. ->where($this->db->quoteName('user_id') . ' = ' . (int) $data->id);
  133. try
  134. {
  135. $values = $this->db->setQuery($query)->loadObject();
  136. }
  137. catch (JDatabaseExceptionExecuting $e)
  138. {
  139. return false;
  140. }
  141. if (!$values)
  142. {
  143. return true;
  144. }
  145. $data->actionlogs = new StdClass;
  146. $data->actionlogs->actionlogsNotify = $values->notify;
  147. $data->actionlogs->actionlogsExtensions = $values->extensions;
  148. return true;
  149. }
  150. /**
  151. * Runs after the HTTP response has been sent to the client and delete log records older than certain days
  152. *
  153. * @return void
  154. *
  155. * @since 3.9.0
  156. */
  157. public function onAfterRespond()
  158. {
  159. $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0);
  160. if ($daysToDeleteAfter <= 0)
  161. {
  162. return;
  163. }
  164. // The delete frequency will be once per day
  165. $deleteFrequency = 3600 * 24;
  166. // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current
  167. // timestamp. If the difference is greater than the cache timeout we shall not execute again.
  168. $now = time();
  169. $last = (int) $this->params->get('lastrun', 0);
  170. if (abs($now - $last) < $deleteFrequency)
  171. {
  172. return;
  173. }
  174. // Update last run status
  175. $this->params->set('lastrun', $now);
  176. $db = $this->db;
  177. $query = $db->getQuery(true)
  178. ->update($db->qn('#__extensions'))
  179. ->set($db->qn('params') . ' = ' . $db->q($this->params->toString('JSON')))
  180. ->where($db->qn('type') . ' = ' . $db->q('plugin'))
  181. ->where($db->qn('folder') . ' = ' . $db->q('system'))
  182. ->where($db->qn('element') . ' = ' . $db->q('actionlogs'));
  183. try
  184. {
  185. // Lock the tables to prevent multiple plugin executions causing a race condition
  186. $db->lockTable('#__extensions');
  187. }
  188. catch (Exception $e)
  189. {
  190. // If we can't lock the tables it's too risky to continue execution
  191. return;
  192. }
  193. try
  194. {
  195. // Update the plugin parameters
  196. $result = $db->setQuery($query)->execute();
  197. $this->clearCacheGroups(array('com_plugins'), array(0, 1));
  198. }
  199. catch (Exception $exc)
  200. {
  201. // If we failed to execite
  202. $db->unlockTables();
  203. $result = false;
  204. }
  205. try
  206. {
  207. // Unlock the tables after writing
  208. $db->unlockTables();
  209. }
  210. catch (Exception $e)
  211. {
  212. // If we can't lock the tables assume we have somehow failed
  213. $result = false;
  214. }
  215. // Abort on failure
  216. if (!$result)
  217. {
  218. return;
  219. }
  220. $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0);
  221. $now = $db->quote(JFactory::getDate()->toSql());
  222. if ($daysToDeleteAfter > 0)
  223. {
  224. $conditions = array($db->quoteName('log_date') . ' < ' . $query->dateAdd($now, -1 * $daysToDeleteAfter, ' DAY'));
  225. $query->clear()
  226. ->delete($db->quoteName('#__action_logs'))->where($conditions);
  227. $db->setQuery($query);
  228. try
  229. {
  230. $db->execute();
  231. }
  232. catch (RuntimeException $e)
  233. {
  234. // Ignore it
  235. return;
  236. }
  237. }
  238. }
  239. /**
  240. * Utility method to act on a user after it has been saved.
  241. *
  242. * @param array $user Holds the new user data.
  243. * @param boolean $isNew True if a new user is stored.
  244. * @param boolean $success True if user was successfully stored in the database.
  245. * @param string $msg Message.
  246. *
  247. * @return boolean
  248. *
  249. * @since 3.9.0
  250. */
  251. public function onUserAfterSave($user, $isNew, $success, $msg)
  252. {
  253. if (!$success)
  254. {
  255. return false;
  256. }
  257. // Clear access rights in case user groups were changed.
  258. $userObject = JFactory::getUser($user['id']);
  259. $userObject->clearAccessRights();
  260. $authorised = $userObject->authorise('core.admin');
  261. $query = $this->db->getQuery(true)
  262. ->select('COUNT(*)')
  263. ->from($this->db->quoteName('#__action_logs_users'))
  264. ->where($this->db->quoteName('user_id') . ' = ' . (int) $user['id']);
  265. try
  266. {
  267. $exists = (bool) $this->db->setQuery($query)->loadResult();
  268. }
  269. catch (JDatabaseExceptionExecuting $e)
  270. {
  271. return false;
  272. }
  273. // If preferences don't exist, insert.
  274. if (!$exists && $authorised && isset($user['actionlogs']))
  275. {
  276. $values = array((int) $user['id'], (int) $user['actionlogs']['actionlogsNotify']);
  277. $columns = array('user_id', 'notify');
  278. if (isset($user['actionlogs']['actionlogsExtensions']))
  279. {
  280. $values[] = $this->db->quote(json_encode($user['actionlogs']['actionlogsExtensions']));
  281. $columns[] = 'extensions';
  282. }
  283. $query = $this->db->getQuery(true)
  284. ->insert($this->db->quoteName('#__action_logs_users'))
  285. ->columns($this->db->quoteName($columns))
  286. ->values(implode(',', $values));
  287. }
  288. elseif ($exists && $authorised && isset($user['actionlogs']))
  289. {
  290. // Update preferences.
  291. $values = array($this->db->quoteName('notify') . ' = ' . (int) $user['actionlogs']['actionlogsNotify']);
  292. if (isset($user['actionlogs']['actionlogsExtensions']))
  293. {
  294. $values[] = $this->db->quoteName('extensions') . ' = ' . $this->db->quote(json_encode($user['actionlogs']['actionlogsExtensions']));
  295. }
  296. $query = $this->db->getQuery(true)
  297. ->update($this->db->quoteName('#__action_logs_users'))
  298. ->set($values)
  299. ->where($this->db->quoteName('user_id') . ' = ' . (int) $user['id']);
  300. }
  301. elseif ($exists && !$authorised)
  302. {
  303. // Remove preferences if user is not authorised.
  304. $query = $this->db->getQuery(true)
  305. ->delete($this->db->quoteName('#__action_logs_users'))
  306. ->where($this->db->quoteName('user_id') . ' = ' . (int) $user['id']);
  307. }
  308. try
  309. {
  310. $this->db->setQuery($query)->execute();
  311. }
  312. catch (JDatabaseExceptionExecuting $e)
  313. {
  314. return false;
  315. }
  316. return true;
  317. }
  318. /**
  319. * Removes user preferences
  320. *
  321. * Method is called after user data is deleted from the database
  322. *
  323. * @param array $user Holds the user data
  324. * @param boolean $success True if user was successfully stored in the database
  325. * @param string $msg Message
  326. *
  327. * @return boolean
  328. *
  329. * @since 3.9.0
  330. */
  331. public function onUserAfterDelete($user, $success, $msg)
  332. {
  333. if (!$success)
  334. {
  335. return false;
  336. }
  337. $query = $this->db->getQuery(true)
  338. ->delete($this->db->quoteName('#__action_logs_users'))
  339. ->where($this->db->quoteName('user_id') . ' = ' . (int) $user['id']);
  340. try
  341. {
  342. $this->db->setQuery($query)->execute();
  343. }
  344. catch (JDatabaseExceptionExecuting $e)
  345. {
  346. return false;
  347. }
  348. return true;
  349. }
  350. /**
  351. * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp.
  352. *
  353. * @param array $clearGroups The cache groups to clean
  354. * @param array $cacheClients The cache clients (site, admin) to clean
  355. *
  356. * @return void
  357. *
  358. * @since 3.9.0
  359. */
  360. private function clearCacheGroups(array $clearGroups, array $cacheClients = array(0, 1))
  361. {
  362. $conf = JFactory::getConfig();
  363. foreach ($clearGroups as $group)
  364. {
  365. foreach ($cacheClients as $clientId)
  366. {
  367. try
  368. {
  369. $options = array(
  370. 'defaultgroup' => $group,
  371. 'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' :
  372. $conf->get('cache_path', JPATH_SITE . '/cache')
  373. );
  374. $cache = JCache::getInstance('callback', $options);
  375. $cache->clean();
  376. }
  377. catch (Exception $e)
  378. {
  379. // Ignore it
  380. }
  381. }
  382. }
  383. }
  384. }