Skip to content

Commit

Permalink
Add anonymous stats collection plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsonge committed Nov 5, 2015
1 parent 38aac08 commit 72af8d5
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 2 deletions.
39 changes: 39 additions & 0 deletions administrator/components/com_admin/script.php
Expand Up @@ -36,6 +36,45 @@ public function update($installer)
$this->updateDatabase();
$this->clearRadCache();
$this->updateAssets();
$this->clearStatsCache();
}

/**
* Method to clear our stats plugin cache to ensure we get fresh data on Joomla Update
*
* @return void
* @since 3.5
*/
protected function clearStatsCache()
{
$db = JFactory::getDbo();

// Get the params for the stats plugin
$params = $db->setQuery(
$db->getQuery(true)
->select($db->quoteName('params'))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
->where($db->quoteName('element') . ' = ' . $db->quote('stats'))
)->loadResult();

$params = json_decode($params, true);

// Reset the last run parameter
if (isset($params['lastrun']))
{
$params['lastrun'] = '';
}

$query = $db->getQuery(true)
->update($db->quoteName('#__extensions'))
->set($db->quoteName('params') . ' = ' . $db->quote($params))
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
->where($db->quoteName('element') . ' = ' . $db->quote('stats'));

$db->setQuery($query)->execute();
}

/**
Expand Down
@@ -0,0 +1,2 @@
INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
@@ -0,0 +1,2 @@
INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
@@ -0,0 +1,6 @@
SET IDENTITY_INSERT [#__extensions] ON;

INSERT [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
7 changes: 7 additions & 0 deletions administrator/language/en-GB/en-GB.plg_system_stats.ini
@@ -0,0 +1,7 @@
PLG_SYSTEM_STATS="J!Stats"
PLG_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 and Database version."
PLG_STATS_UNIQUE_ID_DESC="An identifier that allows us to count unique installs of the plugin. This is sent with the statistics back to the server."
PLG_STATS_UNIQUE_ID_LABEL="Unique ID"
PLG_STATS_URL_DESC="The official Joomla server url"
PLG_STATS_URL_LABEL="Url"
PLG_STATS_RESET_UNIQUE_ID="Reset Unique Id"
4 changes: 4 additions & 0 deletions administrator/language/en-GB/en-GB.plg_system_stats.sys.ini
@@ -0,0 +1,4 @@
PLG_SYSTEM_STATS="J!Stats"
PLG_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 and Database version."
PLG_STATS_UNIQUE_ID_DESC="An identifier that allows us to count unique installs of the plugin. This is sent with the statistics back to the server."
PLG_STATS_UNIQUE_ID_LABEL="Unique ID"
1 change: 1 addition & 0 deletions installation/sql/mysql/joomla.sql
Expand Up @@ -610,6 +610,7 @@ INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`
(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(503, 'beez3', 'template', 'beez3', '', 0, 1, 1, 0, '', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(504, 'hathor', 'template', 'hathor', '', 1, 1, 1, 0, '', '{"showSiteName":"0","colourChoice":"0","boldText":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(506, 'protostar', 'template', 'protostar', '', 0, 1, 1, 0, '', '{"templateColor":"","logoFile":"","googleFont":"1","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
Expand Down
3 changes: 2 additions & 1 deletion installation/sql/postgresql/joomla.sql
Expand Up @@ -609,7 +609,8 @@ INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder"
(450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
(453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

-- Templates
INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
Expand Down
4 changes: 3 additions & 1 deletion installation/sql/sqlazure/joomla.sql
Expand Up @@ -999,7 +999,9 @@ SELECT 451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"se
UNION ALL
SELECT 452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;
SELECT 453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;


INSERT [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
Expand Down
42 changes: 42 additions & 0 deletions plugins/system/stats/fields/uniqueid.php
@@ -0,0 +1,42 @@
<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

defined('JPATH_BASE') or die;

/**
* Unique ID Field class for the Stats Plugin.
*
* @since 3.5
*/
class StatsFormFieldUniqueid extends JFormField
{
/**
* The form field type.
*
* @var string
* @since 3.5
*/
protected $type = 'Uniqueid';

/**
* Method to get the field input markup.
*
* @return string The field input markup.
*
* @since 3.5
*/
protected function getInput()
{
$onclick = ' onclick="document.getElementById(\'' . $this->id . '\').value=\'\';Joomla.submitbutton(\'plugin.apply\');"';

return '<input type="hidden" name="' . $this->name . '" id="' . $this->id . '" value="'
. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '" /> <a class="btn" ' . $onclick . '>'
. '<span class="icon-refresh"></span> ' . JText::_('PLG_STATS_RESET_UNIQUE_ID') . '</a>';
}
}
196 changes: 196 additions & 0 deletions plugins/system/stats/stats.php
@@ -0,0 +1,196 @@
<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

jimport('joomla.filesystem.file');

// 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
*
* @since 3.5
*/
class PlgSystemStats extends JPlugin
{
/**
* Application object
*
* @var JApplicationCms
* @since 3.5
*/
protected $app;

/**
* Database object
*
* @var JDatabaseDriver
* @since 3.5
*/
protected $db;

/**
* Listener for the `onAfterInitialise` event
*
* @return void
*
* @since 3.5
*/
public function onAfterInitialise()
{
// Only run this in admin
if (!$this->app->isAdmin())
{
return;
}

// 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.
$now = time();
$last = (int) $this->params->get('lastrun', 0);

// 12 hours - 60*60*12 = 43200
if (!defined('PLG_SYSTEM_STATS_DEBUG') && (abs($now - $last) < 43200))
{
return;
}

// Update last run status
$this->params->set('lastrun', $now);

$uniqueId = $this->params->get('unique_id', '');

/*
* 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))
{
$this->params->set('unique_id', hash('sha1', JUserHelper::genRandomPassword(28) . time()));
}

$query = $this->db->getQuery(true)
->update($this->db->quoteName('#__extensions'))
->set($this->db->quoteName('params') . ' = ' . $this->db->quote($this->params->toString('JSON')))
->where($this->db->quoteName('type') . ' = ' . $this->db->quote('plugin'))
->where($this->db->quoteName('folder') . ' = ' . $this->db->quote('system'))
->where($this->db->quoteName('element') . ' = ' . $this->db->quote('stats'));

try
{
// Lock the tables to prevent multiple plugin executions causing a race condition
$this->db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue execution
return;
}

try
{
// Update the plugin parameters
$result = $this->db->setQuery($query)->execute();

$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$this->db->unlockTables();
$result = false;
}

try
{
// Unlock the tables after writing
$this->db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}

// Abort on failure
if (!$result)
{
return;
}

$data = array(
'unique_id' => $uniqueId,
'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)
{
// 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');
}
catch (RuntimeException $e)
{
// 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');
}
catch (Exception $e)
{
// 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');
}
}

/**
* Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.5
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients = array(0, 1))
{
$conf = JFactory::getConfig();

foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR . '/cache' :
$conf->get('cache_path', JPATH_SITE . '/cache')
);

$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
48 changes: 48 additions & 0 deletions plugins/system/stats/stats.xml
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin" group="system" method="upgrade">
<name>plg_system_stats</name>
<author>Joomla! Project</author>
<creationDate>November 2013</creationDate>
<copyright>Copyright (C) 2005 - 2015 Open Source Matters. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>3.5.0</version>
<description>PLG_STATS_XML_DESCRIPTION</description>
<files>
<filename plugin="stats">stats.php</filename>
<folder>fields</folder>
</files>
<languages folder="language">
<language tag="en-GB">en-GB/en-GB.plg_system_stats.ini</language>
<language tag="en-GB">en-GB/en-GB.plg_system_stats.sys.ini</language>
</languages>
<config>
<fields name="params" addfieldpath="/plugins/system/stats/fields">
<fieldset name="basic">
<field
name="unique_id"
type="stats.uniqueid"
description="PLG_STATS_UNIQUE_ID_DESC"
label="PLG_STATS_UNIQUE_ID_LABEL"
size="10"
/>
<field
name="url"
type="url"
filter="url"
size="30"
default="https://developer.joomla.org/stats/submit"
description="PLG_STATS_URL_DESC"
label="PLG_STATS_URL_LABEL"
/>
<field
name="lastrun"
type="hidden"
default="0"
size="15"
/>
</fieldset>
</fields>
</config>
</extension>

0 comments on commit 72af8d5

Please sign in to comment.