Skip to content

Commit

Permalink
Merge pull request matomo-org#6802 from piwik/6075_2
Browse files Browse the repository at this point in the history
Tracker refactoring and added queued tracking plugin
  • Loading branch information
tsteur committed Dec 4, 2014
2 parents 590b048 + 6750360 commit 3639b0e
Show file tree
Hide file tree
Showing 90 changed files with 6,206 additions and 1,110 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
path = plugins/LoginHttpAuth
url = https://github.com/piwik/plugin-LoginHttpAuth.git
branch = master
[submodule "plugins/QueuedTracking"]
path = plugins/QueuedTracking
url = https://github.com/piwik/plugin-QueuedTracking.git
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ php:
- 5.3.3
# - hhvm

services:
- redis-server

# Separate different test suites
env:
matrix:
Expand Down
8 changes: 8 additions & 0 deletions config/global.ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,14 @@
; on a per-request basis;
pivot_by_filter_default_column_limit = 10


[Redis]
host = 127.0.0.1
port = 6379
timeout = 0.0

[Tracker]

; Piwik uses first party cookies by default. If set to 1,
; the visit ID cookie will be set on the Piwik server domain as well
; this is useful when you want to do cross websites analysis
Expand Down Expand Up @@ -709,6 +716,7 @@
Plugins[] = Morpheus
Plugins[] = Contents
Plugins[] = TestRunner
Plugins[] = BulkTracking

[PluginsInstalled]
PluginsInstalled[] = Login
Expand Down
6 changes: 4 additions & 2 deletions core/CliMulti/RequestCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ protected function execute(InputInterface $input, OutputInterface $output)

if ($this->isTestModeEnabled()) {
Config::getInstance()->setTestEnvironment();
$indexFile = '/tests/PHPUnit/proxy/index.php';
$indexFile = '/tests/PHPUnit/proxy/';
} else {
$indexFile = '/index.php';
$indexFile = '/';
}

$indexFile .= 'index.php';

if (!empty($_GET['pid'])) {
$process = new Process($_GET['pid']);

Expand Down
16 changes: 12 additions & 4 deletions core/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,13 @@ public static function getRequestVar($varName, $varDefault = null, $varType = nu
*/
public static function generateUniqId()
{
return md5(uniqid(rand(), true));
if (function_exists('mt_rand')) {
$rand = mt_rand();
} else {
$rand = rand();
}

return md5(uniqid($rand, true));
}

/**
Expand Down Expand Up @@ -1182,10 +1188,12 @@ public static function sendResponseCode($code)
}

if (strpos(PHP_SAPI, '-fcgi') === false) {
$key = $_SERVER['SERVER_PROTOCOL'];
$key = 'HTTP/1.1';

if (strlen($key) > 15 || empty($key)) {
$key = 'HTTP/1.1';
if (array_key_exists('SERVER_PROTOCOL', $_SERVER)
&& strlen($_SERVER['SERVER_PROTOCOL']) < 15
&& strlen($_SERVER['SERVER_PROTOCOL']) > 1) {
$key = $_SERVER['SERVER_PROTOCOL'];
}

} else {
Expand Down
3 changes: 2 additions & 1 deletion core/Cookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,8 @@ public function get($name)
*/
public function __toString()
{
$str = 'COOKIE ' . $this->name . ', rows count: ' . count($this->value) . ', cookie size = ' . strlen($this->generateContentString()) . " bytes\n";
$str = 'COOKIE ' . $this->name . ', rows count: ' . count($this->value) . ', cookie size = ' . strlen($this->generateContentString()) . " bytes, ";
$str .= 'path: ' . $this->path. ', expire: ' . $this->expire . "\n";
$str .= var_export($this->value, $return = true);

return $str;
Expand Down
11 changes: 11 additions & 0 deletions core/Date.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,17 @@ public static function adjustForTimezone($timestamp, $timezone)
return strtotime($datetime);
}

/**
* Returns the date in the "Y-m-d H:i:s" PHP format
*
* @param int $timestamp
* @return string
*/
public static function getDatetimeFromTimestamp($timestamp)
{
return date("Y-m-d H:i:s", $timestamp);
}

/**
* Returns the Unix timestamp of the date in UTC.
*
Expand Down
6 changes: 4 additions & 2 deletions core/Piwik.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,10 @@ public static function hasTheUserSuperUserAccess($theUser)
public static function hasUserSuperUserAccess()
{
try {
self::checkUserHasSuperUserAccess();
return true;
$hasAccess = Access::getInstance()->hasSuperUserAccess();

return $hasAccess;

} catch (Exception $e) {
return false;
}
Expand Down
28 changes: 23 additions & 5 deletions core/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,28 @@ public function __construct($pluginName = false)
}
$this->pluginName = $pluginName;

$metadataLoader = new MetadataLoader($pluginName);
$this->pluginInformation = $metadataLoader->load();
$cache = new PersistentCache('Plugin' . $pluginName . 'Metadata');

if ($this->hasDefinedPluginInformationInPluginClass() && $metadataLoader->hasPluginJson()) {
throw new \Exception('Plugin ' . $pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $pluginName);
if ($cache->has()) {
$this->pluginInformation = $cache->get();
} else {

$metadataLoader = new MetadataLoader($pluginName);
$this->pluginInformation = $metadataLoader->load();

if ($this->hasDefinedPluginInformationInPluginClass() && $metadataLoader->hasPluginJson()) {
throw new \Exception('Plugin ' . $pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $pluginName);
}

$cache->set($this->pluginInformation);
}
}

$this->cache = new PersistentCache('Plugin' . $pluginName);
private function createCacheIfNeeded()
{
if (is_null($this->cache)) {
$this->cache = new PersistentCache('Plugin' . $this->pluginName);
}
}

private function hasDefinedPluginInformationInPluginClass()
Expand Down Expand Up @@ -305,6 +319,8 @@ final public function getPluginName()
*/
public function findComponent($componentName, $expectedSubclass)
{
$this->createCacheIfNeeded();

$this->cache->setCacheKey('Plugin' . $this->pluginName . $componentName . $expectedSubclass);

$componentFile = sprintf('%s/plugins/%s/%s.php', PIWIK_INCLUDE_PATH, $this->pluginName, $componentName);
Expand Down Expand Up @@ -349,6 +365,8 @@ public function findComponent($componentName, $expectedSubclass)

public function findMultipleComponents($directoryWithinPlugin, $expectedSubclass)
{
$this->createCacheIfNeeded();

$this->cache->setCacheKey('Plugin' . $this->pluginName . $directoryWithinPlugin . $expectedSubclass);

if ($this->cache->has()) {
Expand Down
48 changes: 42 additions & 6 deletions core/Plugin/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class Manager extends Singleton
'ExampleTheme'
);

private $trackerPluginsNotToLoad = array();

/**
* Loads plugin that are enabled
*/
Expand All @@ -108,7 +110,7 @@ public function loadActivatedPlugins()
public function loadCorePluginsDuringTracker()
{
$pluginsToLoad = Config::getInstance()->Plugins['Plugins'];
$pluginsToLoad = array_diff($pluginsToLoad, Tracker::getPluginsNotToLoad());
$pluginsToLoad = array_diff($pluginsToLoad, $this->getTrackerPluginsNotToLoad());
$this->loadPlugins($pluginsToLoad);
}

Expand Down Expand Up @@ -139,18 +141,42 @@ public function loadTrackerPlugins()
}
}

$this->unloadPlugins();

if (empty($pluginsTracker)) {
$this->unloadPlugins();
return array();
}

$pluginsTracker = array_diff($pluginsTracker, Tracker::getPluginsNotToLoad());
$pluginsTracker = array_diff($pluginsTracker, $this->getTrackerPluginsNotToLoad());
$this->doNotLoadAlwaysActivatedPlugins();
$this->loadPlugins($pluginsTracker);

// we could simply unload all plugins first before loading plugins but this way it is much faster
// since we won't have to create each plugin again and we won't have to parse each plugin metadata file
// again etc
$this->makeSureOnlyActivatedPluginsAreLoaded();

return $pluginsTracker;
}

/**
* Do not load the specified plugins (used during testing, to disable Provider plugin)
* @param array $plugins
*/
public function setTrackerPluginsNotToLoad($plugins)
{
$this->trackerPluginsNotToLoad = $plugins;
}

/**
* Get list of plugins to not load
*
* @return array
*/
public function getTrackerPluginsNotToLoad()
{
return $this->trackerPluginsNotToLoad;
}

public function getCorePluginsDisabledByDefault()
{
return array_merge( $this->corePluginsDisabledByDefault, $this->coreThemesDisabledByDefault);
Expand Down Expand Up @@ -237,7 +263,7 @@ private function isPluginUninstallable($name)
public function isPluginActivated($name)
{
return in_array($name, $this->pluginsToLoad)
|| $this->isPluginAlwaysActivated($name);
|| ($this->doLoadAlwaysActivatedPlugins && $this->isPluginAlwaysActivated($name));
}

/**
Expand Down Expand Up @@ -1005,8 +1031,9 @@ private function executePluginInstall(Plugin $plugin)
*
* @param string $pluginName plugin name without prefix (eg. 'UserCountry')
* @param Plugin $newPlugin
* @internal
*/
private function addLoadedPlugin($pluginName, Plugin $newPlugin)
public function addLoadedPlugin($pluginName, Plugin $newPlugin)
{
$this->loadedPlugins[$pluginName] = $newPlugin;
}
Expand Down Expand Up @@ -1335,6 +1362,15 @@ private function removeInstalledVersionFromOptionTable($version)
{
Option::delete('version_' . $version);
}

private function makeSureOnlyActivatedPluginsAreLoaded()
{
foreach ($this->getLoadedPlugins() as $pluginName => $plugin) {
if (!in_array($pluginName, $this->pluginsToLoad)) {
$this->unloadPlugin($plugin);
}
}
}
}

/**
Expand Down
17 changes: 11 additions & 6 deletions core/Plugin/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,14 @@ public function getSettings()
*/
protected function addSetting(Setting $setting)
{
if (!ctype_alnum($setting->getName())) {
$name = $setting->getName();

if (!ctype_alnum($name)) {
$msg = sprintf('The setting name "%s" in plugin "%s" is not valid. Only alpha and numerical characters are allowed', $setting->getName(), $this->pluginName);
throw new \Exception($msg);
}

if (array_key_exists($setting->getName(), $this->settings)) {
if (array_key_exists($name, $this->settings)) {
throw new \Exception(sprintf('A setting with name "%s" does already exist for plugin "%s"', $setting->getName(), $this->pluginName));
}

Expand All @@ -195,7 +197,7 @@ protected function addSetting(Setting $setting)
$setting->setStorage($this->storage);
$setting->setPluginName($this->pluginName);

$this->settings[$setting->getName()] = $setting;
$this->settings[$name] = $setting;
}

/**
Expand Down Expand Up @@ -265,11 +267,14 @@ private function getDefaultCONTROL($type)

private function setDefaultTypeAndFieldIfNeeded(Setting $setting)
{
if (!is_null($setting->uiControlType) && is_null($setting->type)) {
$hasControl = !is_null($setting->uiControlType);
$hasType = !is_null($setting->type);

if ($hasControl && !$hasType) {
$setting->type = $this->getDefaultType($setting->uiControlType);
} elseif (!is_null($setting->type) && is_null($setting->uiControlType)) {
} elseif ($hasType && !$hasControl) {
$setting->uiControlType = $this->getDefaultCONTROL($setting->type);
} elseif (is_null($setting->uiControlType) && is_null($setting->type)) {
} elseif (!$hasControl && !$hasType) {
$setting->type = static::TYPE_STRING;
$setting->uiControlType = static::CONTROL_TEXT;
}
Expand Down
34 changes: 34 additions & 0 deletions core/Settings/Storage/StaticStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/

namespace Piwik\Settings\Storage;
use Piwik\Settings\Storage;

/**
* Static / temporary storage where a value will never be persisted meaning it will use the default value
* for each request until configured differently. Useful for tests.
*
* @api
*/
class StaticStorage extends Storage
{

protected function loadSettings()
{
return array();
}

/**
* Saves (persists) the current setting values in the database.
*/
public function save()
{
}

}
16 changes: 16 additions & 0 deletions core/SettingsServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ public static function isTrackerApiRequest()
return !empty($GLOBALS['PIWIK_TRACKER_MODE']);
}

/**
* Mark the current request as a Tracker API request
*/
public static function setIsTrackerApiRequest()
{
$GLOBALS['PIWIK_TRACKER_MODE'] = true;
}

/**
* Set the current request is not a tracker API request
*/
public static function setIsNotTrackerApiRequest()
{
$GLOBALS['PIWIK_TRACKER_MODE'] = false;
}

/**
* Returns `true` if running on Microsoft IIS 7 (or above), `false` if otherwise.
*
Expand Down
Loading

0 comments on commit 3639b0e

Please sign in to comment.