From 3399721df81cfaef2c2a028b6c2677532ec19bc7 Mon Sep 17 00:00:00 2001 From: Roberto Segura - phproberto Date: Tue, 10 Nov 2015 02:53:54 +0100 Subject: [PATCH 1/3] [imp] allow users to accept & configure stats sending --- .../language/en-GB/en-GB.plg_system_stats.ini | 16 + media/plg_system_stats/js/stats.js | 81 ++++ plugins/system/stats/layouts/message.php | 38 ++ plugins/system/stats/stats.php | 352 +++++++++++++++--- plugins/system/stats/stats.xml | 35 +- 5 files changed, 468 insertions(+), 54 deletions(-) create mode 100644 media/plg_system_stats/js/stats.js create mode 100644 plugins/system/stats/layouts/message.php diff --git a/administrator/language/en-GB/en-GB.plg_system_stats.ini b/administrator/language/en-GB/en-GB.plg_system_stats.ini index dd908ac8af4d2..f140e881df99d 100644 --- a/administrator/language/en-GB/en-GB.plg_system_stats.ini +++ b/administrator/language/en-GB/en-GB.plg_system_stats.ini @@ -4,6 +4,22 @@ ; Note : All ini files need to be saved as UTF-8 PLG_SYSTEM_STATS="System - Joomla! Statistics" +PLG_SYSTEM_STATS_BTN_NEVER_SEND="Never" +PLG_SYSTEM_STATS_BTN_SEND_ALWAYS="Always" +PLG_SYSTEM_STATS_BTN_SEND_NOW="Once" +PLG_SYSTEM_STATS_DEBUG_DESC="Enable debug (stats sent every single time)" +PLG_SYSTEM_STATS_DEBUG_LABEL="Debug" +PLG_SYSTEM_STATS_INTERVAL_DESC="Stats will be sent each X hours. Default is 12" +PLG_SYSTEM_STATS_INTERVAL_LABEL="Interval (hours)" +PLG_SYSTEM_STATS_LABEL_MESSAGE_TITLE="Joomla! would like your permission collect some basic statistics." +PLG_SYSTEM_STATS_MODE_DESC="Selec the way you want that statistics are sent" +PLG_SYSTEM_STATS_MODE_LABEL="Mode" +PLG_SYSTEM_STATS_MODE_OPTION_ALWAYS_SEND="Always send" +PLG_SYSTEM_STATS_MODE_OPTION_NEVER_SEND="Never send" +PLG_SYSTEM_STATS_MODE_OPTION_ON_DEMAND="On demand" +PLG_SYSTEM_STATS_MSG_ALLOW_SENDING_DATA="Enable Joomla Statistics?" +PLG_SYSTEM_STATS_MSG_JOOMLA_WANTS_TO_SEND_DATA="In order to better understand our install base and end user environments, this plugin has been created to send those stats back to a Joomla controlled central server. No identifying data is captured at any point. You can change this settings later from Plugins > System Joomla! Statistics." +PLG_SYSTEM_STATS_MSG_WHAT_DATA_WILL_BE_SENT="Click here to see which information will be sent." PLG_SYSTEM_STATS_RESET_UNIQUE_ID="Reset Unique Id" PLG_SYSTEM_STATS_UNIQUE_ID_DESC="An identifier that allows the Joomla! project to count unique installs of the plugin. This is sent with the statistics back to the server." PLG_SYSTEM_STATS_UNIQUE_ID_LABEL="Unique ID" diff --git a/media/plg_system_stats/js/stats.js b/media/plg_system_stats/js/stats.js new file mode 100644 index 0000000000000..a3e8ec634a7c7 --- /dev/null +++ b/media/plg_system_stats/js/stats.js @@ -0,0 +1,81 @@ +(function ($) { + $(document).ready(function () { + var ajaxData = { + 'option' : 'com_ajax', + 'group' : 'system', + 'plugin' : 'renderStatsMessage', + 'format' : 'json' + }, + messageContainer = $('#system-message-container'); + + /** + * Initialise events for the message container + * + * @return void + */ + function initStatsEvents() + { + var globalContainer = messageContainer.find('.js-pstats-alert'), + detailsContainer = messageContainer.find('.js-pstats-data-details'); + + // Show details about the information being sent + messageContainer.on('click', '.js-pstats-btn-details', function(e){ + detailsContainer.toggle(200); + e.preventDefault(); + }); + + // Always allow + messageContainer.on('click', '.js-pstats-btn-allow-always', function(e){ + + // Remove message + globalContainer.hide(200); + detailsContainer.remove(); + ajaxData.plugin = 'sendAlways'; + + $.getJSON('index.php', ajaxData, function(response){ + + }); + e.preventDefault(); + }); + + // Allow once + messageContainer.on('click', '.js-pstats-btn-allow-once', function(e){ + + // Remove message + globalContainer.hide(200); + detailsContainer.remove(); + + ajaxData.plugin = 'sendOnce'; + + $.getJSON('index.php', ajaxData, function(response){ + + }); + e.preventDefault(); + }); + + // Never allow + messageContainer.on('click', '.js-pstats-btn-allow-never', function(e){ + + // Remove message + globalContainer.hide(200); + detailsContainer.remove(); + + ajaxData.plugin = 'sendNever'; + + $.getJSON('index.php', ajaxData, function(response){ + }); + e.preventDefault(); + }); + } + + ajaxData.plugin = 'renderStatsMessage'; + + $.getJSON('index.php', ajaxData, function(response){ + messageContainer + .append(response.data[0].html) + .find('.js-pstats-alert').show(200); + + initStatsEvents(); + }); + }); +})(jQuery); diff --git a/plugins/system/stats/layouts/message.php b/plugins/system/stats/layouts/message.php new file mode 100644 index 0000000000000..88174f2dce31f --- /dev/null +++ b/plugins/system/stats/layouts/message.php @@ -0,0 +1,38 @@ + + diff --git a/plugins/system/stats/stats.php b/plugins/system/stats/stats.php index 25cbdb2360af4..b04976f3de40f 100644 --- a/plugins/system/stats/stats.php +++ b/plugins/system/stats/stats.php @@ -9,9 +9,6 @@ defined('_JEXEC') or die; -// Uncomment the following line to enable debug mode (stats sent every single time) -// define('PLG_SYSTEM_STATS_DEBUG', 1); - /** * Statistics system plugin. This sends anonymous data back to the Joomla! Project about the * PHP, SQL, Joomla and OS versions @@ -20,6 +17,24 @@ */ class PlgSystemStats extends JPlugin { + /** + * @const integer + * @since 3.5 + */ + const MODE_ALLOW_ALWAYS = 1; + + /** + * @const integer + * @since 3.5 + */ + const MODE_ALLOW_ONCE = 2; + + /** + * @const integer + * @since 3.5 + */ + const MODE_ALLOW_NEVER = 3; + /** * Application object * @@ -28,6 +43,14 @@ class PlgSystemStats extends JPlugin */ protected $app; + /** + * Load plugin language files automatically + * + * @var boolean + * @since 3.5 + */ + protected $autoloadLanguage = true; + /** * Database object * @@ -36,6 +59,14 @@ class PlgSystemStats extends JPlugin */ protected $db; + /** + * Unique identifier for this site + * + * @var string + * @since 3.5 + */ + protected $uniqueId; + /** * Listener for the `onAfterInitialise` event * @@ -45,91 +76,269 @@ class PlgSystemStats extends JPlugin */ public function onAfterInitialise() { - // Only run this in admin - if (!$this->app->isAdmin()) + if (!$this->app->isAdmin() || !$this->isAllowedUser() || !$this->isUpdateRequired()) { return; } - $uniqueId = $this->params->get('unique_id', ''); + $mode = (int) $this->params->get('mode'); - /* - * If the unique ID is empty (because we have never submitted a piece of data before or because the refresh button - * has been used - generate a new ID and store it in the database for future use. - */ - if (empty($uniqueId)) + // Plugin parameters are saved and send always enabled + if ($mode === static::MODE_ALLOW_ALWAYS) { - $uniqueId = hash('sha1', JUserHelper::genRandomPassword(28) . time()); - $this->params->set('unique_id', $uniqueId); + try + { + $this->sendStats(); + } + catch (Exception $e) + { + JLog::add($e->getMessage(), JLog::WARNING, 'stats'); + } + + return; } - $last = (int) $this->params->get('lastrun', 0); + JHtml::_('jquery.framework'); + JHtml::script('plg_system_stats/stats.js', false, true, false); + } - // What's the time? - $now = time(); + /** + * Get the user message rendered + * + * @return array + * + * @since 3.5 + */ + public function onAjaxRenderStatsMessage() + { + if (!$this->isAllowedUser() || !$this->isAjaxRequest()) + { + throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); + } - if ($last == 0) + return array( + 'html' => $this->getRenderer('message')->render($this->getLayoutData()) + ); + } + + /** + * User selected to always send data + * + * @return void + * + * @since 3.5 + */ + public function onAjaxSendAlways() + { + if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { - // This is the first run of the plugin, we save a last time some hours in the future - // It allows people to disable the plugin before data is send the first time - $this->params->set('lastrun', $now + 21600); + throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); + } - $result = $this->saveParams(); + $this->params->set('mode', static::MODE_ALLOW_ALWAYS); - return; + if (!$this->saveParams()) + { + throw new RuntimeException('Unable to save plugin settings', 500); } - /* - * Do we need to run? Compare the last run timestamp stored in the plugin's options with the current - * timestamp. If the difference is greater than the cache timeout we shall not execute again. - * 12 hours - 60*60*12 = 43200 - */ - if (!defined('PLG_SYSTEM_STATS_DEBUG') && (abs($now - $last) < 43200)) + $this->sendStats(); + } + + /** + * User selected to never send data. + * + * @return void + * + * @since 3.5 + */ + public function onAjaxSendNever() + { + if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { - return; + throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); } - // Update last run status - $this->params->set('lastrun', $now); + $this->params->set('mode', static::MODE_ALLOW_NEVER); - $result = $this->saveParams(); + if (!$this->saveParams()) + { + throw new RuntimeException('Unable to save plugin settings', 500); + } + } - // Abort on failure - if (!$result) + /** + * User selected to send data once. + * + * @return void + * + * @since 3.5 + */ + public function onAjaxSendOnce() + { + if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { - return; + throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); + } + + $this->params->set('mode', static::MODE_ALLOW_ONCE); + + if (!$this->saveParams()) + { + throw new RuntimeException('Unable to save plugin settings', 500); } - $data = array( - 'unique_id' => $uniqueId, + $this->sendStats(); + } + + /** + * Get the data for the layout + * + * @return array + * + * @since 3.5 + */ + protected function getLayoutData() + { + return array( + 'plugin' => $this, + 'pluginParams' => $this->params, + 'statsData' => $this->getStatsData() + ); + } + + /** + * Get the layout paths + * + * @return array() + * + * @since 3.5 + */ + protected function getLayoutsPaths() + { + $template = JFactory::getApplication()->getTemplate(); + + return array( + JPATH_ADMINISTRATOR . '/templates/' . $template . '/html/layouts/plugins/' . $this->_type . '/' . $this->_name, + __DIR__ . '/layouts', + ); + } + + /** + * Get the plugin renderer + * + * @param string $layoutId Layout identifier + * + * @return JLayout + * + * @since 3.5 + */ + protected function getRenderer($layoutId = 'default') + { + $renderer = new JLayoutFile($layoutId); + + $renderer->setIncludePaths($this->getLayoutsPaths()); + + return $renderer; + } + + /** + * Get the data that will be sent to the stats server. + * + * @return array. + * + * @since 3.5 + */ + private function getStatsData() + { + return array( + 'unique_id' => $this->getUniqueId(), 'php_version' => PHP_VERSION, 'db_type' => $this->db->name, 'db_version' => $this->db->getVersion(), 'cms_version' => JVERSION, 'server_os' => php_uname('s') . ' ' . php_uname('r') ); + } - // Don't let the request take longer than 2 seconds to avoid page timeout issues - try - { - // Don't let the request take longer than 2 seconds to avoid page timeout issues - JHttpFactory::getHttp()->post($this->params->get('url', 'https://developer.joomla.org/stats/submit'), $data, null, 2); - } - catch (UnexpectedValueException $e) + /** + * Get the unique id. Generates one if none is set. + * + * @return integer + * + * @since 3.5 + */ + private function getUniqueId() + { + if (null === $this->uniqueId) { - // There was an error sending stats. Should we do anything? - JLog::add('Could not send site statistics to remote server: ' . $e->getMessage(), JLog::WARNING, 'stats'); + $this->uniqueId = $this->params->get('unique_id', hash('sha1', JUserHelper::genRandomPassword(28) . time())); } - catch (RuntimeException $e) + + return $this->uniqueId; + } + + /** + * Check if current user is allowed to send the data + * + * @return boolean + * + * @since 3.5 + */ + private function isAllowedUser() + { + return JFactory::getUser()->authorise('core.admin'); + } + + /** + * Check if the debug is enabled + * + * @return boolean + * + * @since 3.5 + */ + private function isDebugEnabled() + { + return ((int) $this->params->get('debug', 0) === 1); + } + + /** + * Check if last_run + interval > now + * + * @return boolean + * + * @since 3.5 + */ + private function isUpdateRequired() + { + $last = (int) $this->params->get('lastrun', 0); + $interval = (int) $this->params->get('interval', 12); + $mode = (int) $this->params->get('mode', 0); + + if ($mode === static::MODE_ALLOW_NEVER) { - // There was an error connecting to the server or in the post request - JLog::add('Could not connect to statistics server: ' . $e->getMessage(), JLog::WARNING, 'stats'); + return false; } - catch (Exception $e) + + // Never updated or debug enabled + if (!$last || !$interval || $this->isDebugEnabled()) { - // An unexpected error in processing; don't let this failure kill the site - JLog::add('Unexpected error connecting to statistics server: ' . $e->getMessage(), JLog::WARNING, 'stats'); + return true; } + + return (abs(time() - $last) > $interval * 3600); + } + + /** + * Check valid AJAX request + * + * @return boolean + * + * @since 3.5 + */ + private function isAjaxRequest() + { + return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); } /** @@ -141,6 +350,12 @@ public function onAfterInitialise() */ private function saveParams() { + // Update params + $this->params->set('lastrun', time()); + $this->params->set('unique_id', $this->getUniqueId()); + $interval = (int) $this->params->get('interval', 12); + $this->params->set('interval', $interval ? $interval : 12); + $query = $this->db->getQuery(true) ->update($this->db->quoteName('#__extensions')) ->set($this->db->quoteName('params') . ' = ' . $this->db->quote($this->params->toString('JSON'))) @@ -187,6 +402,39 @@ private function saveParams() return $result; } + /** + * Send the stats to the stats server + * + * @return boolean + * + * @since 3.5 + */ + private function sendStats() + { + try + { + // Don't let the request take longer than 2 seconds to avoid page timeout issues + $response = JHttpFactory::getHttp()->post($this->params->get('url', 'https://developer.joomla.org/stats/submit'), $this->getStatsData(), null, 2); + } + catch (UnexpectedValueException $e) + { + // There was an error sending stats. Should we do anything? + throw new RuntimeException('Could not send site statistics to remote server: ' . $e->getMessage(), 500); + } + catch (RuntimeException $e) + { + // There was an error connecting to the server or in the post request + throw new RuntimeException('Could not connect to statistics server: ' . $e->getMessage(), 500); + } + catch (Exception $e) + { + // An unexpected error in processing; don't let this failure kill the site + throw new RuntimeException('Unexpected error connecting to statistics server: ' . $e->getMessage(), 500); + } + + return true; + } + /** * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp. * diff --git a/plugins/system/stats/stats.xml b/plugins/system/stats/stats.xml index 5efc359eff2b8..f41c3f863a9da 100644 --- a/plugins/system/stats/stats.xml +++ b/plugins/system/stats/stats.xml @@ -10,8 +10,9 @@ 3.5.0 PLG_SYSTEM_STATS_XML_DESCRIPTION - stats.php fields + layouts + stats.php en-GB/en-GB.plg_system_stats.ini @@ -34,8 +35,38 @@ size="30" default="https://developer.joomla.org/stats/submit" description="PLG_SYSTEM_STATS_URL_DESC" - label="PLG_SYSTEM_STATS_URL_LABEL" + label="PLG_SYSTEM_STATS_URL_LABEL" + /> + + + + + + + + + + Date: Tue, 10 Nov 2015 10:19:20 +0100 Subject: [PATCH 2/3] [imp] remove stats plugin url setting & move debug to advanced --- plugins/system/stats/stats.xml | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/plugins/system/stats/stats.xml b/plugins/system/stats/stats.xml index f41c3f863a9da..b043fad8a2c82 100644 --- a/plugins/system/stats/stats.xml +++ b/plugins/system/stats/stats.xml @@ -28,15 +28,6 @@ label="PLG_SYSTEM_STATS_UNIQUE_ID_LABEL" size="10" /> - PLG_SYSTEM_STATS_MODE_OPTION_ON_DEMAND + + +
JYES -
From 67fe07a4f0b663b33f23b8fe2e9102ed5ffacf8d Mon Sep 17 00:00:00 2001 From: Roberto Segura - phproberto Date: Tue, 10 Nov 2015 10:43:32 +0100 Subject: [PATCH 3/3] [imp] always send system stats using AJAX --- .../language/en-GB/en-GB.plg_system_stats.ini | 4 +- media/plg_system_stats/js/stats.js | 25 ++--- plugins/system/stats/stats.php | 100 ++++++++++++------ 3 files changed, 79 insertions(+), 50 deletions(-) diff --git a/administrator/language/en-GB/en-GB.plg_system_stats.ini b/administrator/language/en-GB/en-GB.plg_system_stats.ini index f140e881df99d..c9995e85d74c8 100644 --- a/administrator/language/en-GB/en-GB.plg_system_stats.ini +++ b/administrator/language/en-GB/en-GB.plg_system_stats.ini @@ -7,7 +7,7 @@ PLG_SYSTEM_STATS="System - Joomla! Statistics" PLG_SYSTEM_STATS_BTN_NEVER_SEND="Never" PLG_SYSTEM_STATS_BTN_SEND_ALWAYS="Always" PLG_SYSTEM_STATS_BTN_SEND_NOW="Once" -PLG_SYSTEM_STATS_DEBUG_DESC="Enable debug (stats sent every single time)" +PLG_SYSTEM_STATS_DEBUG_DESC="Enable debug for testing purposes. Stats sent every page load." PLG_SYSTEM_STATS_DEBUG_LABEL="Debug" PLG_SYSTEM_STATS_INTERVAL_DESC="Stats will be sent each X hours. Default is 12" PLG_SYSTEM_STATS_INTERVAL_LABEL="Interval (hours)" @@ -23,6 +23,4 @@ PLG_SYSTEM_STATS_MSG_WHAT_DATA_WILL_BE_SENT="Click here to see which information PLG_SYSTEM_STATS_RESET_UNIQUE_ID="Reset Unique Id" PLG_SYSTEM_STATS_UNIQUE_ID_DESC="An identifier that allows the Joomla! project to count unique installs of the plugin. This is sent with the statistics back to the server." PLG_SYSTEM_STATS_UNIQUE_ID_LABEL="Unique ID" -PLG_SYSTEM_STATS_URL_DESC="The official Joomla server url" -PLG_SYSTEM_STATS_URL_LABEL="Url" PLG_SYSTEM_STATS_XML_DESCRIPTION="System Plugin that sends environment statistics to a server controlled by the Joomla! project for statistical analysis. Statistics sent include PHP version, CMS version, Database type, Database version and Server type." diff --git a/media/plg_system_stats/js/stats.js b/media/plg_system_stats/js/stats.js index a3e8ec634a7c7..6604bfe84bcdc 100644 --- a/media/plg_system_stats/js/stats.js +++ b/media/plg_system_stats/js/stats.js @@ -4,7 +4,7 @@ 'option' : 'com_ajax', 'group' : 'system', 'plugin' : 'renderStatsMessage', - 'format' : 'json' + 'format' : 'raw' }, messageContainer = $('#system-message-container'); @@ -32,9 +32,7 @@ detailsContainer.remove(); ajaxData.plugin = 'sendAlways'; - $.getJSON('index.php', ajaxData, function(response){ - - }); + $.getJSON('index.php', ajaxData, function(response){}); e.preventDefault(); }); @@ -47,9 +45,7 @@ ajaxData.plugin = 'sendOnce'; - $.getJSON('index.php', ajaxData, function(response){ - - }); + $.getJSON('index.php', ajaxData, function(response){}); e.preventDefault(); }); @@ -62,20 +58,21 @@ ajaxData.plugin = 'sendNever'; - $.getJSON('index.php', ajaxData, function(response){ - }); + $.getJSON('index.php', ajaxData, function(response){}); e.preventDefault(); }); } - ajaxData.plugin = 'renderStatsMessage'; + ajaxData.plugin = 'sendStats'; $.getJSON('index.php', ajaxData, function(response){ - messageContainer - .append(response.data[0].html) - .find('.js-pstats-alert').show(200); + if (response && response.html) { + messageContainer + .append(response.html) + .find('.js-pstats-alert').show(200); - initStatsEvents(); + initStatsEvents(); + } }); }); })(jQuery); diff --git a/plugins/system/stats/stats.php b/plugins/system/stats/stats.php index b04976f3de40f..718f868fc527b 100644 --- a/plugins/system/stats/stats.php +++ b/plugins/system/stats/stats.php @@ -59,6 +59,13 @@ class PlgSystemStats extends JPlugin */ protected $db; + /** + * Url to send the statistics. + * + * @var string + */ + protected $serverUrl = 'https://developer.joomla.org/stats/submit'; + /** * Unique identifier for this site * @@ -76,25 +83,13 @@ class PlgSystemStats extends JPlugin */ public function onAfterInitialise() { - if (!$this->app->isAdmin() || !$this->isAllowedUser() || !$this->isUpdateRequired()) + if (!$this->app->isAdmin() || !$this->isAllowedUser()) { return; } - $mode = (int) $this->params->get('mode'); - - // Plugin parameters are saved and send always enabled - if ($mode === static::MODE_ALLOW_ALWAYS) + if (!$this->isDebugEnabled() && !$this->isUpdateRequired()) { - try - { - $this->sendStats(); - } - catch (Exception $e) - { - JLog::add($e->getMessage(), JLog::WARNING, 'stats'); - } - return; } @@ -103,85 +98,120 @@ public function onAfterInitialise() } /** - * Get the user message rendered + * User selected to always send data * - * @return array + * @return void * * @since 3.5 + * + * @throws Exception If user is not allowed. + * @throws RuntimeException If there is an error saving the params or sending the data. */ - public function onAjaxRenderStatsMessage() + public function onAjaxSendAlways() { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); } - return array( - 'html' => $this->getRenderer('message')->render($this->getLayoutData()) - ); + $this->params->set('mode', static::MODE_ALLOW_ALWAYS); + + if (!$this->saveParams()) + { + throw new RuntimeException('Unable to save plugin settings', 500); + } + + $this->sendStats(); + + echo json_encode(array('sent' => 1)); } /** - * User selected to always send data + * User selected to never send data. * * @return void * * @since 3.5 + * + * @throws Exception If user is not allowed. + * @throws RuntimeException If there is an error saving the params. */ - public function onAjaxSendAlways() + public function onAjaxSendNever() { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); } - $this->params->set('mode', static::MODE_ALLOW_ALWAYS); + $this->params->set('mode', static::MODE_ALLOW_NEVER); if (!$this->saveParams()) { throw new RuntimeException('Unable to save plugin settings', 500); } - $this->sendStats(); + echo json_encode(array('sent' => 0)); } /** - * User selected to never send data. + * User selected to send data once. * * @return void * * @since 3.5 + * + * @throws Exception If user is not allowed. + * @throws RuntimeException If there is an error saving the params or sending the data. */ - public function onAjaxSendNever() + public function onAjaxSendOnce() { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); } - $this->params->set('mode', static::MODE_ALLOW_NEVER); + $this->params->set('mode', static::MODE_ALLOW_ONCE); if (!$this->saveParams()) { throw new RuntimeException('Unable to save plugin settings', 500); } + + $this->sendStats(); + + echo json_encode(array('sent' => 1)); } /** - * User selected to send data once. + * Send the stats to the server. + * On first load | on demand mode it will show a message asking users to select mode. * * @return void * * @since 3.5 + * + * @throws Exception If user is not allowed. + * @throws RuntimeException If there is an error saving the params or sending the data. */ - public function onAjaxSendOnce() + public function onAjaxSendStats() { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); } - $this->params->set('mode', static::MODE_ALLOW_ONCE); + // User has not selected the mode. Show message. + if ((int) $this->params->get('mode') !== static::MODE_ALLOW_ALWAYS) + { + $data = array( + 'sent' => 0, + 'html' => $this->getRenderer('message')->render($this->getLayoutData()) + ); + + echo json_encode($data); + + return; + } if (!$this->saveParams()) { @@ -189,6 +219,8 @@ public function onAjaxSendOnce() } $this->sendStats(); + + echo json_encode(array('sent' => 1)); } /** @@ -321,7 +353,7 @@ private function isUpdateRequired() } // Never updated or debug enabled - if (!$last || !$interval || $this->isDebugEnabled()) + if (!$last || $this->isDebugEnabled()) { return true; } @@ -338,7 +370,7 @@ private function isUpdateRequired() */ private function isAjaxRequest() { - return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); + return strtolower($this->app->input->server->get('HTTP_X_REQUESTED_WITH', '')) == 'xmlhttprequest'; } /** @@ -408,13 +440,15 @@ private function saveParams() * @return boolean * * @since 3.5 + * + * @throws RuntimeException If there is an error sending the data. */ private function sendStats() { try { // Don't let the request take longer than 2 seconds to avoid page timeout issues - $response = JHttpFactory::getHttp()->post($this->params->get('url', 'https://developer.joomla.org/stats/submit'), $this->getStatsData(), null, 2); + JHttpFactory::getHttp()->post($this->serverUrl, $this->getStatsData(), null, 2); } catch (UnexpectedValueException $e) {