From 4cbe7488c1787f39e9b9d09dac375704e31fe2ae Mon Sep 17 00:00:00 2001 From: mattpiwik <matthieu.aubry@gmail.com> Date: Thu, 6 Sep 2007 17:52:15 +0000 Subject: [PATCH] The full page with all the reports is OK missing the Actions plugins reports (all page views, etc..) looks quite nice actually :) git-svn-id: http://dev.piwik.org/svn/trunk@62 59fd770c-687e-43c8-a1e3-f5a4ff64c105 --- README | 3 + TODO | 3 + config/config.ini.php | 4 + index.php | 4 + libs/jquery/truncate/jquery.truncate.js | 3 +- modules/API/Proxy.php | 22 +- modules/API/Request.php | 6 + modules/ArchiveProcessing.php | 14 +- modules/ArchiveProcessing/Day.php | 3 + modules/ArchiveProcessing/Period.php | 1 + modules/DataFiles/SearchEngines.php | 54 +- modules/DataTable.php | 16 +- modules/DataTable/Filter/Sort.php | 8 +- modules/Log/Error.php | 3 - modules/PluginsManager.php | 13 +- modules/View.php | 3 + plugins/API/Controller.php | 23 + plugins/Referers/API.php | 3 +- plugins/UserCountry/API.php | 2 +- plugins/UserSettings.php | 2 +- plugins/UserSettings/API.php | 17 +- plugins/UserSettings/Controller.php | 740 +++++++++++++++++-- plugins/UserSettings/templates/datatable.tpl | 79 +- plugins/UserSettings/templates/index.tpl | 254 +++++-- plugins/VisitTime.php | 1 + plugins/VisitTime/API.php | 2 +- plugins/VisitorInterest.php | 4 +- tests/modules/PHP_Related.test.php | 14 + 28 files changed, 1068 insertions(+), 233 deletions(-) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000000..ca9123bcbd --- /dev/null +++ b/README @@ -0,0 +1,3 @@ + +Listing all the plugins API +?module=API&action=listAllAPI diff --git a/TODO b/TODO index ebbb2ad5f4..34b9037335 100644 --- a/TODO +++ b/TODO @@ -9,10 +9,13 @@ FEATURES - Provide Config file feature for plugins (works as the translation system) - Translate exception +- CHANGE setColumnsToDisplay TO setColumnsIdsToDisplay BUGS ==== +- monthly unique visitors count is WRONG +- check that ajax called made onceper request - create the tmp directory + subdir automatically - the referer URLs with host registered as main_url or alias_url should NOT be counted as referer - the token md5 generation doesn't check that the md5 generated is unique, diff --git a/config/config.ini.php b/config/config.ini.php index 0c34bb3ddf..62b426ec1c 100755 --- a/config/config.ini.php +++ b/config/config.ini.php @@ -33,6 +33,9 @@ enabled[] = VisitFrequency enabled[] = VisitTime enabled[] = VisitorInterest +[Debug] +always_archive_data = false + [Plugins_LogStats] enabled[] = Provider @@ -46,6 +49,7 @@ action_category_delimiter = / dataTable_default_limit = 10 + [LogStats] ; set to 0 if you want to stop tracking the visitors. Useful if you need to stop all the connections on the DB. record_statistics = 1 diff --git a/index.php b/index.php index 0ee11955e4..7066ca942d 100755 --- a/index.php +++ b/index.php @@ -18,6 +18,10 @@ assert_options(ASSERT_ACTIVE, 1); assert_options(ASSERT_WARNING, 1); assert_options(ASSERT_BAIL, 1); +if(!defined('E_STRICT')) define('E_STRICT', 2048); +if(!defined('E_RECOVERABLE_ERROR')) define('E_RECOVERABLE_ERROR', 4096); +if(!defined('E_EXCEPTION')) define('E_EXCEPTION', 8192); + /** * Error / exception handling functions */ diff --git a/libs/jquery/truncate/jquery.truncate.js b/libs/jquery/truncate/jquery.truncate.js index 558699f2f8..e67f364705 100644 --- a/libs/jquery/truncate/jquery.truncate.js +++ b/libs/jquery/truncate/jquery.truncate.js @@ -1,7 +1,8 @@ jQuery.fn.truncate = function(max) { return this.each(function() { var trail = '...'; - if (jQuery(this).children().length == 0) { + if (jQuery(this).children().length == 0) + { v = jQuery.trim(jQuery(this).text()); while (max < v.length) { c = v.charAt(max); diff --git a/modules/API/Proxy.php b/modules/API/Proxy.php index 89e0d28198..4cc38eb29d 100755 --- a/modules/API/Proxy.php +++ b/modules/API/Proxy.php @@ -14,7 +14,7 @@ class Piwik_API_Proxy { static $classCalled = null; protected $alreadyRegistered = array(); - private $api = null; + private $api = array(); const NO_DEFAULT_VALUE = null; @@ -118,15 +118,29 @@ class Piwik_API_Proxy } $this->api[$class][$name]['parameters'] = $aParameters; $this->api[$class][$name]['numberOfRequiredParameters'] = $method->getNumberOfRequiredParameters(); - -// Piwik::log("- $name is public ".$this->getStrListParameters($class, $name)); } } -// Piwik::log("List of the public methods for the class $class"); $this->alreadyRegistered[$fileName] = true; } + public function getAllInterfaceString() + { + $str = ''; + foreach($this->api as $class => $info) + { + $str .= "\n<br>" . "List of the public methods for the class ".$class; + + foreach($info as $methodName => $infoMethod) + { + $params = $this->getStrListParameters($class, $methodName); + $str .= "\n<br>" . "- $methodName : " . $params; + } + $str.="\n<br>"; + } + return $str; + } + /** * Returns the methods $class.$name parameters (and default value if provided) * as a string. diff --git a/modules/API/Request.php b/modules/API/Request.php index 670db30696..767f226960 100644 --- a/modules/API/Request.php +++ b/modules/API/Request.php @@ -237,6 +237,12 @@ class Piwik_API_Request // if asked for original dataStructure if($format == 'original') { + // if the original dataStructure is a simple data structure + if($dataTable instanceof Piwik_DataTable_Simple + && $dataTable->getRowsCount() == 1) + { + return $dataTable->getRowFromId(0)->getColumn('value'); + } return $dataTable; } diff --git a/modules/ArchiveProcessing.php b/modules/ArchiveProcessing.php index 79a0b21232..386421c454 100644 --- a/modules/ArchiveProcessing.php +++ b/modules/ArchiveProcessing.php @@ -44,7 +44,15 @@ abstract class Piwik_ArchiveProcessing public $logTable; public $logVisitActionTable; public $logActionTable; - + + protected $debugAlwaysArchive = false; + + public function __construct() + { + $this->debugAlwaysArchive = Zend_Registry::get('config')->Debug->always_archive_data; + //TODO remove + + } /** * */ @@ -239,6 +247,10 @@ abstract class Piwik_ArchiveProcessing protected function isArchived() { + if($this->debugAlwaysArchive) + { + return false; + } // Piwik::log("Is archive site=$idsite for period = ".$this->period->getLabel()." for date_start = $strDateStart ?"); $bindSQL = array( $this->idsite, $this->strDateStart, diff --git a/modules/ArchiveProcessing/Day.php b/modules/ArchiveProcessing/Day.php index a38e2dcb2c..14bdf8b2a4 100644 --- a/modules/ArchiveProcessing/Day.php +++ b/modules/ArchiveProcessing/Day.php @@ -13,6 +13,7 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing function __construct() { + parent::__construct(); $this->db = Zend_Registry::get('db'); } @@ -71,6 +72,8 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing } $table = new Piwik_DataTable; $table->loadFromArrayLabelIsKey($data); +// echo $table; +// exit; return $table; } diff --git a/modules/ArchiveProcessing/Period.php b/modules/ArchiveProcessing/Period.php index ce40097478..68833aadfa 100644 --- a/modules/ArchiveProcessing/Period.php +++ b/modules/ArchiveProcessing/Period.php @@ -6,6 +6,7 @@ class Piwik_ArchiveProcessing_Period extends Piwik_ArchiveProcessing { function __construct() { + parent::__construct(); } private function archiveNumericValuesGeneral($aNames, $operationToApply) diff --git a/modules/DataFiles/SearchEngines.php b/modules/DataFiles/SearchEngines.php index aa49183e5a..0b9df818dd 100644 --- a/modules/DataFiles/SearchEngines.php +++ b/modules/DataFiles/SearchEngines.php @@ -89,6 +89,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) "apollo7.de" => array("Apollo7", "query"), // AOL + "search.aol.com" => array("AOL", "query"), "aolsearch.aol.com" => array("AOL", "query"), "www.aolrecherche.aol.fr" => array("AOL", "q"), "www.aolrecherches.aol.fr" => array("AOL", "query"), @@ -104,7 +105,6 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) "suche.aol.de" => array("AOL", "q"), "aolbusqueda.aol.com.mx" => array("AOL", "query"), - "search.aol.com" => array("AOL", "query"), // Aport "sm.aport.ru" => array("Aport", "r"), @@ -134,8 +134,8 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) "www2.austronaut.at" => array("Austronaut", "begriff"), // Baidu - "www1.baidu.com" => array("Baidu", "wd"), "www.baidu.com" => array("Baidu", "wd"), + "www1.baidu.com" => array("Baidu", "wd"), // BBC "search.bbc.co.uk" => array("BBC", "q"), @@ -304,31 +304,6 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) "ocnsearch.goo.ne.jp" => array("goo", "mt"), - // Powered by Google (add or not?) - "www.charter.net" => array("Google", "q"), - "brisbane.t-online.de" => array("Google", "q"), - "www.eniro.se" => array("Google", "q"), - "www.eniro.no" => array("Google", "q"), - "miportal.bellsouth.net" => array("Google", "string"), - "home.bellsouth.net" => array("Google", "string"), - "pesquisa.clix.pt" => array("Google", "q"), - "google.startsiden.no" => array("Google", "q"), - "arianna.libero.it" => array("Google", "query"), - "google.startpagina.nl" => array("Google", "q"), - "search.peoplepc.com" => array("Google", "q"), - "www.google.interia.pl" => array("Google", "q"), - "buscador.terra.es" => array("Google", "query"), - "buscador.terra.cl" => array("Google", "query"), - "buscador.terra.com.br" => array("Google", "query"), - "www.icq.com" => array("Google", "q"), - "www.adelphia.net" => array("Google", "q"), - "www.comcast.net" => array("Google", "query"), - "so.qq.com" => array("Google", "word"), - "misc.skynet.be" => array("Google", "keywords"), - "www.start.no" => array("Google", "q"), - "verden.abcsok.no" => array("Google", "q"), - "search.sweetim.com" => array("Google", "q"), - // Google "www.google.com" => array("Google", "q"), "gogole.fr" => array("Google", "q"), @@ -485,6 +460,29 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) "www.google.co.ma" => array("Google", "q"), "www.goggle.com" => array("Google", "q"), + + // Powered by Google + "www.charter.net" => array("Google", "q"), + "brisbane.t-online.de" => array("Google", "q"), + "miportal.bellsouth.net" => array("Google", "string"), + "home.bellsouth.net" => array("Google", "string"), + "pesquisa.clix.pt" => array("Google", "q"), + "google.startsiden.no" => array("Google", "q"), + "google.startpagina.nl" => array("Google", "q"), + "search.peoplepc.com" => array("Google", "q"), + "www.google.interia.pl" => array("Google", "q"), + "buscador.terra.es" => array("Google", "query"), + "buscador.terra.cl" => array("Google", "query"), + "buscador.terra.com.br" => array("Google", "query"), + "www.icq.com" => array("Google", "q"), + "www.adelphia.net" => array("Google", "q"), + "so.qq.com" => array("Google", "word"), + "misc.skynet.be" => array("Google", "keywords"), + "www.start.no" => array("Google", "q"), + "verden.abcsok.no" => array("Google", "q"), + "search.sweetim.com" => array("Google", "q"), + + //Google Blogsearch "blogsearch.google.com" => array("Google Blogsearch", "q"), "blogsearch.google.de" => array("Google Blogsearch", "q"), @@ -666,7 +664,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] )) // Live.com "www.live.com" => array("Live", "q"), - "beta.search.live.com" => array("Live", "q"), + "beta.search.live.com" => array("Live", "q"), "search.live.com" => array("Live", "q"), "g.msn.com" => array("Live", " "), diff --git a/modules/DataTable.php b/modules/DataTable.php index 99d63d2dfe..146dbeb9d2 100644 --- a/modules/DataTable.php +++ b/modules/DataTable.php @@ -254,6 +254,15 @@ class Piwik_DataTable } return $this->rows[$this->rowsIndexByLabel[$label]]; } + + public function getRowFromId($id) + { + if(!isset($this->rows[$id])) + { + return false; + } + return $this->rows[$id]; + } public function __destruct() { @@ -502,8 +511,11 @@ class Piwik_DataTable $cleanRow = array(); foreach($array as $label => $row) { - $cleanRow[Piwik_DataTable_Row::COLUMNS] = $row; - $cleanRow[Piwik_DataTable_Row::COLUMNS]['label'] = $label; + // we make sure that the label column is first in the list! + // important for the UI javascript mainly... + // array_merge doesn't work here as it reindex the numeric value + // see the test testMergeArray in PHP_Related.test.php + $cleanRow[Piwik_DataTable_Row::COLUMNS] = array('label' => $label) + $row; if(!is_null($subtablePerLabel) // some rows of this table don't have subtables // (for examplecase of the campaign without keywords ) diff --git a/modules/DataTable/Filter/Sort.php b/modules/DataTable/Filter/Sort.php index 26585f2473..9269d1bf61 100644 --- a/modules/DataTable/Filter/Sort.php +++ b/modules/DataTable/Filter/Sort.php @@ -60,6 +60,10 @@ class Piwik_DataTable_Filter_Sort extends Piwik_DataTable_Filter protected function filter() { + if($this->table instanceof Piwik_DataTable_Simple) + { + return; + } $rows = $this->table->getRows(); if(count($rows) == 0) @@ -69,9 +73,9 @@ class Piwik_DataTable_Filter_Sort extends Piwik_DataTable_Filter $row = current($rows); $value = $row->getColumn($this->columnToSort); - if($value == false) + if($value === false) { - return; + throw new Exception("The column to sort by '".$this->columnToSort."' is unknown in the row ". implode(array_keys($row->getColumns()), ',')); } if( Piwik::isNumeric($value)) diff --git a/modules/Log/Error.php b/modules/Log/Error.php index 208bfb5ae5..175bd9a778 100644 --- a/modules/Log/Error.php +++ b/modules/Log/Error.php @@ -68,9 +68,6 @@ class Piwik_Log_Formatter_Error_ScreenFormatter implements Zend_Log_Formatter_In // it gives an errno 0, and in this case the objective is to NOT display anything on the screen! // is there any other case where the errno is zero at this point? if($errno == 0) return ''; - if(!defined('E_STRICT')) define('E_STRICT', 2048); - if(!defined('E_RECOVERABLE_ERROR')) define('E_RECOVERABLE_ERROR', 4096); - if(!defined('E_EXCEPTION')) define('E_EXCEPTION', 8192); $strReturned .= "\n<div style='word-wrap: break-word; border: 3px solid red; padding:4px; width:70%; background-color:#FFFF96;'><b>"; switch($errno) { diff --git a/modules/PluginsManager.php b/modules/PluginsManager.php index c1fbcebe87..5a97bd6d63 100644 --- a/modules/PluginsManager.php +++ b/modules/PluginsManager.php @@ -35,6 +35,7 @@ class Piwik_PluginsManager protected $installPlugins = false; protected $doLoadPlugins = true; protected $languageToLoad = null; + protected $loadedPlugins = array(); static private $instance = null; @@ -81,6 +82,16 @@ class Piwik_PluginsManager { return $this->installPlugins; } + + protected function addLoadedPlugin($newPlugin) + { + $this->loadedPlugins[] = $newPlugin; + } + + public function getLoadedPlugins() + { + return $this->loadedPlugins; + } /** * Load the plugins classes installed. * Register the observers for every plugin. @@ -134,7 +145,7 @@ class Piwik_PluginsManager $newPlugin->registerTranslation( $this->languageToLoad ); $this->addPluginObservers( $newPlugin ); - + $this->addLoadedPlugin($pluginName); } } } diff --git a/modules/View.php b/modules/View.php index e8b34ca3c9..aa6f5aabfa 100644 --- a/modules/View.php +++ b/modules/View.php @@ -21,6 +21,9 @@ class Piwik_View $this->smarty->$key = $value; } $this->smarty->template_dir = $smConf->template_dir->toArray(); + +// $this->smarty->load_filter('output','trimwhitespace'); + } /** diff --git a/plugins/API/Controller.php b/plugins/API/Controller.php index 144ec683c9..9184243d95 100644 --- a/plugins/API/Controller.php +++ b/plugins/API/Controller.php @@ -9,5 +9,28 @@ class Piwik_API_Controller extends Piwik_Controller $request = new Piwik_API_Request(); echo $request->process(); } + + function listAllAPI() + { + echo "<h1>List of all modules API</h1>"; + $errors = ''; + $plugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins(); + $loaded = 0; + foreach( $plugins as $plugin ) + { + try { + Piwik_API_Proxy::getInstance()->registerClass($plugin); + $loaded++; + } + catch(Exception $e){ + $errors .= "<br>\n" . $e->getMessage(); + } + } + echo "<p> Loaded successfully $loaded APIs</p>\n"; + echo Piwik_API_Proxy::getInstance()->getAllInterfaceString(); + + echo "<p>Errors = " . $errors . "</p>\n"; + } + } diff --git a/plugins/Referers/API.php b/plugins/Referers/API.php index e8668f0f59..ba0116b650 100644 --- a/plugins/Referers/API.php +++ b/plugins/Referers/API.php @@ -173,8 +173,7 @@ function Piwik_getSearchEngineLogoFromName($url) { require_once PIWIK_DATAFILES_INCLUDE_PATH . "/SearchEngines.php"; $path = PIWIK_PLUGINS_PATH . '/Referers/images/searchEngines/%s.png'; - - $beginningUrl = strpos($url,'//')+2; + $beginningUrl = strpos($url,'//') + 2; $normalPath = sprintf($path, substr($url,$beginningUrl)); // flags not in the package ! diff --git a/plugins/UserCountry/API.php b/plugins/UserCountry/API.php index b797f17220..b97f48e75e 100644 --- a/plugins/UserCountry/API.php +++ b/plugins/UserCountry/API.php @@ -26,7 +26,7 @@ class Piwik_UserCountry_API extends Piwik_Apiable $archive = Piwik_Archive::build($idSite, $date, $period ); $dataTable = $archive->getDataTable('UserCountry_country'); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'code', create_function('$label', 'return $label;'))); - $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'flag', 'Piwik_getFlagFromCode')); + $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'logo', 'Piwik_getFlagFromCode')); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_CountryTranslate')); $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); return $dataTable; diff --git a/plugins/UserSettings.php b/plugins/UserSettings.php index 4462abf312..5eb9ef9c88 100644 --- a/plugins/UserSettings.php +++ b/plugins/UserSettings.php @@ -194,7 +194,7 @@ class Piwik_UserSettings extends Piwik_Plugin sum(case config_realplayer when 1 then 1 else 0 end) as realplayer, sum(case config_windowsmedia when 1 then 1 else 0 end) as windowsmedia, sum(case config_cookie when 1 then 1 else 0 end) as cookie "; - return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, 'nb_visits'); + return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, Piwik_Archive::INDEX_NB_VISITS); } } diff --git a/plugins/UserSettings/API.php b/plugins/UserSettings/API.php index 808cd582ff..9f79ea19fa 100644 --- a/plugins/UserSettings/API.php +++ b/plugins/UserSettings/API.php @@ -47,6 +47,7 @@ class Piwik_UserSettings_API extends Piwik_Apiable $archive = Piwik_Archive::build($idSite, $date, $period ); $dataTable = $archive->getDataTable('UserSettings_os'); $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); + $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'logo', 'Piwik_getOSLogo')); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array( 'label', 'shortLabel', 'Piwik_getOSShortLabel') ); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array( 'label', 'Piwik_getOSLabel') ); return $dataTable; @@ -80,7 +81,8 @@ class Piwik_UserSettings_API extends Piwik_Apiable Piwik::checkUserHasViewAccess( $idSite ); $archive = Piwik_Archive::build($idSite, $date, $period ); $dataTable = $archive->getDataTable('UserSettings_wideScreen'); - $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); + $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); + $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'logo', 'Piwik_getScreensLogo')); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'ucfirst')); return $dataTable; } @@ -177,6 +179,17 @@ function Piwik_getBrowserVersion($str) function Piwik_getBrowsersLogo($label) { $id = Piwik_getBrowserId($label); - return "/plugins/UserSettings/images/browsers/". $id . ".gif"; + return PIWIK_PLUGINS_PATH . "/UserSettings/images/browsers/". $id . ".gif"; } +function Piwik_getOSLogo($label) +{ + $path = PIWIK_PLUGINS_PATH . "/UserSettings/images/os/". $label . ".gif"; +// echo $path;exit; + return $path; +} + +function Piwik_getScreensLogo($label) +{ + return PIWIK_PLUGINS_PATH . "/UserSettings/images/screens/" . $label . ".gif"; +} \ No newline at end of file diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php index 0a65b403f1..0041b66b65 100644 --- a/plugins/UserSettings/Controller.php +++ b/plugins/UserSettings/Controller.php @@ -6,69 +6,469 @@ class Piwik_UserSettings_Controller extends Piwik_Controller { $view = new Piwik_View('UserSettings/templates/index.tpl'); - $view->dataTableResolution = $this->getResolution(true); - $view->dataTableSearchEngines = $this->getSearchEngines(true); + /* User settings */ + $view->dataTablePlugin = $this->getPlugin( true ); + $view->dataTableResolution = $this->getResolution( true ); + $view->dataTableConfiguration = $this->getConfiguration( true ); + $view->dataTableOS = $this->getOS( true ); + $view->dataTableBrowser = $this->getBrowser( true ); + $view->dataTableBrowserType = $this->getBrowserType ( true ); + $view->dataTableWideScreen = $this->getWideScreen( true ); + + /* VisitorTime */ + $view->dataTableVisitInformationPerLocalTime = $this->getVisitInformationPerLocalTime(true); + $view->dataTableVisitInformationPerServerTime = $this->getVisitInformationPerServerTime(true); + + /* VisitFrequency */ + $arrayFrequency = $this->getSummary(true); + + $view->nbVisitsReturning = $arrayFrequency['nb_visits_returning']; + $view->nbActionsReturning = $arrayFrequency['nb_actions_returning']; + $view->maxActionsReturning = $arrayFrequency['max_actions_returning']; + $view->sumVisitLengthReturning = $arrayFrequency['sum_visit_length_returning']; + $view->bounceCountReturning = $arrayFrequency['bounce_count_returning']; + + /* Visitor Interest */ + $view->dataTableNumberOfVisitsPerVisitDuration = $this->getNumberOfVisitsPerVisitDuration(true); + $view->dataTableNumberOfVisitsPerPage = $this->getNumberOfVisitsPerPage(true); + + /* Provider */ + $view->dataTableProvider = $this->getProvider(true); + + /* User Country */ + $view->dataTableCountry = $this->getCountry(true); + $view->dataTableContinent = $this->getContinent(true); + + /* Referers */ + $view->dataTableRefererType = $this->getRefererType(true); $view->dataTableKeywords = $this->getKeywords(true); - $view->dataTableBrowser = $this->getBrowser(true); + $view->dataTableSearchEngines = $this->getSearchEngines(true); + $view->dataTableCampaigns = $this->getCampaigns(true); + $view->dataTableWebsites = $this->getWebsites(true); + $view->dataTablePartners = $this->getPartners(true); + + $view->numberDistinctSearchEngines = $this->getNumberOfDistinctSearchEngines(true); + $view->numberDistinctKeywords = $this->getNumberOfDistinctKeywords(true); + $view->numberDistinctCampaigns = $this->getNumberOfDistinctCampaigns(true); + $view->numberDistinctWebsites = $this->getNumberOfDistinctWebsites(true); + $view->numberDistinctWebsitesUrls = $this->getNumberOfDistinctWebsitesUrls(true); + $view->numberDistinctPartners = $this->getNumberOfDistinctPartners(true); + $view->numberDistinctPartnersUrls = $this->getNumberOfDistinctPartnersUrls(true); + echo $view->render(); } + + protected function renderView($view, $fetch) + { + $rendered = $view->getView()->render(); + if($fetch) + { + return $rendered; + } + echo $rendered; + } + protected function getNumericValue( $methodToCall ) + { + $requestString = 'method='.$methodToCall.'&format=original'; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } + /* + * + +List of the public methods for the class Piwik_Actions_API +- getActions : [idSite, period, date, expanded = , idSubtable = ] +- getDownloads : [idSite, period, date, expanded = , idSubtable = ] +- getOutlinks : [idSite, period, date, expanded = , idSubtable = ] + + */ + + /** + * VisitFrequency + */ + function getSummary( $fetch = false) + { + $requestString = 'method='."VisitFrequency.getSummary".'&format=php&serialize=0'; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } - function getSearchEnginesFromKeywordId( $fetch = false ) + /** + * VisitTime + */ + function getVisitInformationPerServerTime( $fetch = false) { - $view = $this->getTable( 'getSearchEnginesFromKeywordId', - 'Referers.getSearchEnginesFromKeywordId', - 'ReferersKeywordsSe' - ); + $view = new Piwik_View_DataTable( __FUNCTION__, "VisitTime.getVisitInformationPerServerTime" ); + + $view->setColumnsToDisplay( array(0,2) ); + $view->setSortedColumn( '0', 'asc' ); + $view->setDefaultLimit( 24 ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + + return $this->renderView($view, $fetch); + } + + function getVisitInformationPerLocalTime( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "VisitTime.getVisitInformationPerLocalTime" ); + + $view->setColumnsToDisplay( array(0,2) ); + $view->setSortedColumn( '0', 'asc' ); + $view->setDefaultLimit( 24 ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + + return $this->renderView($view, $fetch); + } + /** + * VisitorInterest + */ + function getNumberOfVisitsPerVisitDuration( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "VisitorInterest.getNumberOfVisitsPerVisitDuration" ); + + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 'nb_visits' ); + $view->setDefaultLimit( 5 ); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + $view->disableSearchBox(); + + return $this->renderView($view, $fetch); + } + + function getNumberOfVisitsPerPage( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "VisitorInterest.getNumberOfVisitsPerPage" ); + + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 'nb_visits' ); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + $view->disableSearchBox(); + $view->main(); +// echo $view->dataTable; + return $this->renderView($view, $fetch); + } + + /** + * Provider + */ + function getProvider( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "Provider.getProvider" ); + + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 1 ); + $view->setDefaultLimit( 5 ); + + return $this->renderView($view, $fetch); + } + + /** + * User Country + */ + function getCountry( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "UserCountry.getCountry" ); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,1) ); +// $view->setSortedColumn( 1 ); + $view->setDefaultLimit( 5 ); + + return $this->renderView($view, $fetch); + } + + function getContinent( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, "UserCountry.getContinent" ); + $view->disableExcludeLowPopulation(); + $view->disableSearchBox(); + $view->disableOffsetInformation(); + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 1 ); return $this->renderView($view, $fetch); } + + /** + * User settings + */ + function getStandardDataTableUserSettings( $currentControllerAction, + $APItoCall ) + { + $view = new Piwik_View_DataTable( $currentControllerAction, $APItoCall ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 1 ); + $view->setDefaultLimit( 5 ); + + return $view; + } + function getResolution( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getResolution' + ); + return $this->renderView($view, $fetch); + } + + function getConfiguration( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getConfiguration' + ); + return $this->renderView($view, $fetch); + } + function getOS( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getOS' + ); + return $this->renderView($view, $fetch); + } + function getBrowser( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getBrowser' + ); + return $this->renderView($view, $fetch); + } + function getBrowserType ( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getBrowserType' + ); + $view->disableOffsetInformation(); + return $this->renderView($view, $fetch); + } + function getWideScreen( $fetch = false) + { + $view = $this->getStandardDataTableUserSettings( + __FUNCTION__, + 'UserSettings.getWideScreen' + ); + $view->disableOffsetInformation(); + return $this->renderView($view, $fetch); + } + function getPlugin( $fetch = false) + { + $view = new Piwik_View_DataTable( __FUNCTION__, 'UserSettings.getPlugin' ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,1) ); + $view->setSortedColumn( 2 ); + $view->setDefaultLimit( 5 ); + + return $this->renderView($view, $fetch); + } + + + + /** + * Referers + */ + function getRefererType( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getRefererType', + 'Referers.getRefererType' + ); + $view->disableSearchBox(); + $view->disableOffsetInformation(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,1,2) ); + + return $this->renderView($view, $fetch); + } function getKeywords( $fetch = false) { - $view = $this->getTable( 'getKeywords', - 'Referers.getKeywords', - 'ReferersKeywords' + $view = new Piwik_View_DataTable( 'getKeywords', + 'Referers.getKeywords', + 'getSearchEnginesFromKeywordId' + ); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + + return $this->renderView($view, $fetch); + } + + function getSearchEnginesFromKeywordId( $fetch = false ) + { + $view = new Piwik_View_DataTable( 'getSearchEnginesFromKeywordId', + 'Referers.getSearchEnginesFromKeywordId' ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + return $this->renderView($view, $fetch); } + + + function getSearchEngines( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getSearchEngines', + 'Referers.getSearchEngines', + 'getKeywordsFromSearchEngineId' + ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,2) ); + + return $this->renderView($view, $fetch); + } + + function getKeywordsFromSearchEngineId( $fetch = false ) { - $view = $this->getTable( 'getKeywordsFromSearchEngineId', - 'Referers.getKeywordsFromSearchEngineId', - 'ReferersSeKeywords' + $view = new Piwik_View_DataTable( 'getKeywordsFromSearchEngineId', + 'Referers.getKeywordsFromSearchEngineId' ); - //TODO setup a method for this - $view->dataTableColumns = array( - array('id' => 0, 'name' => 'label'), - array('id' => Piwik_Archive::INDEX_NB_VISITS, 'name' => 'nb_visits'), - ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + + return $this->renderView($view, $fetch); + } + + function getCampaigns( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getCampaigns', + 'Referers.getCampaigns', + 'getKeywordsFromCampaignId' + ); + + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,2) ); return $this->renderView($view, $fetch); } + function getKeywordsFromCampaignId( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getKeywordsFromCampaignId', + 'Referers.getKeywordsFromCampaignId' + ); + + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + + return $this->renderView($view, $fetch); + } - function getSearchEngines( $fetch = false) + function getWebsites( $fetch = false) { - $view = $this->getTable( 'getSearchEngines', - 'Referers.getSearchEngines', - 'ReferersSe' + $view = new Piwik_View_DataTable( 'getWebsites', + 'Referers.getWebsites', + 'getUrlsFromWebsiteId' ); - //TODO setup a method for this - $view->dataTableColumns = array( - array('id' => 0, 'name' => 'label'), - array('id' => Piwik_Archive::INDEX_NB_VISITS, 'name' => 'nb_visits'), - ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,2) ); + + return $this->renderView($view, $fetch); + } + + function getUrlsFromWebsiteId( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getUrlsFromWebsiteId', + 'Referers.getUrlsFromWebsiteId' + ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + + return $this->renderView($view, $fetch); + } + + function getPartners( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getPartners', + 'Referers.getPartners', + 'getUrlsFromPartnerId' + ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + + $view->setColumnsToDisplay( array(0,2) ); + + return $this->renderView($view, $fetch); + } + + function getUrlsFromPartnerId( $fetch = false) + { + $view = new Piwik_View_DataTable( 'getUrlsFromPartnerId', + 'Referers.getUrlsFromPartnerId' + ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->setColumnsToDisplay( array(0,2)); + return $this->renderView($view, $fetch); } + function getNumberOfDistinctSearchEngines( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctKeywords( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctCampaigns( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctWebsites( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctWebsitesUrls( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctPartners( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + function getNumberOfDistinctPartnersUrls ( $fetch = false) + { + return $this->getNumericValue('Referers.' . __FUNCTION__); + } + + + + + + /* + + function getResolution( $fetch = false) { $view = $this->getTable( 'getResolution', - 'UserSettings.getResolution', - 'UserSettingsResolution' + 'UserSettings.getResolution' ); //TODO setup a method for this $view->dataTableColumns = array( @@ -81,64 +481,204 @@ class Piwik_UserSettings_Controller extends Piwik_Controller function getBrowser( $fetch = false) { $view = $this->getTable( 'getBrowser', - 'UserSettings.getBrowser', - 'UserSettingsBrowser' + 'UserSettings.getBrowser' ); return $this->renderView($view, $fetch); } - + */ +} +class Piwik_View_DataTable +{ protected $dataTableTemplate = 'UserSettings/templates/datatable.tpl'; + protected $currentControllerAction; + protected $moduleNameAndMethod; + protected $actionToLoadTheSubTable; + + protected $JSsearchBox = true; + protected $JSoffsetInformation = true; + protected $JSexcludeLowPopulation = true; + protected $JSsortColumn = false; + protected $JSsortOrder = false; + protected $JSlimit = false; + + protected $mainAlreadyExecuted = false; + protected $columnsToDisplay = array(); + + function __construct( $currentControllerAction, + $moduleNameAndMethod, + $actionToLoadTheSubTable = null) + { + $this->currentControllerAction = $currentControllerAction; + $this->moduleNameAndMethod = $moduleNameAndMethod; + $this->actionToLoadTheSubTable = $actionToLoadTheSubTable; + + $this->idSubtable = Piwik_Common::getRequestVar('idSubtable', false,'int'); + } - protected function getTable( $currentControllerAction, $moduleNameAndMethod, $uniqIdTable ) + function getView() { - $requestString = 'method='.$moduleNameAndMethod.' - &format=original'; - - $idSubtable = Piwik_Common::getRequestVar('idSubtable', false,'int'); - if( $idSubtable != false) + $this->main(); + return $this->view; + } + + public function main() + { + if($this->mainAlreadyExecuted) { - $requestString .= '&idSubtable='.$idSubtable; - - $uniqIdTable = 'subDataTable_' . $idSubtable; + return; } - $request = new Piwik_API_Request($requestString); + $this->mainAlreadyExecuted = true; - $dataTable = $request->process(); -// echo $dataTable; exit; +// $i=0;while($i<1500000){ $j=$i*$i;$i++;} + + // is there a Sub DataTable requested ? + // for example do we request the details for the search engine Google? + + + $this->loadDataTableFromAPI(); + + + // We apply a filter to the DataTable, decoding the label column (useful for keywords for example) $filter = new Piwik_DataTable_Filter_ColumnCallbackReplace( - $dataTable, + $this->dataTable, 'label', 'urldecode' ); - $renderer = Piwik_DataTable_Renderer::factory('php'); - $renderer->setTable($dataTable); - $renderer->setSerialize( false ); - $phpArray = $renderer->render(); - -// var_dump( $data );exit; + $view = new Piwik_View($this->dataTableTemplate); - $view->id = $uniqIdTable; + + $view->id = $this->getUniqIdTable(); + + // We get the PHP array converted from the DataTable + $phpArray = $this->getPHPArrayFromDataTable(); + $view->dataTable = $phpArray; -// $i=0;while($i<1500000){ $j=$i*$i;$i++;} + $view->dataTableColumns = $this->getColumnsToDisplay($phpArray); - $dataTableColumns = array(); + $view->javascriptVariablesToSet + = $this->getJavascriptVariablesToSet(); + + $this->view = $view; + } + + protected function getUniqIdTable() + { + + // the $uniqIdTable variable is used as the DIV ID in the rendered HTML + // we use the current Controller action name as it is supposed to be unique in the rendered page + $uniqIdTable = $this->currentControllerAction; + + // if we request a subDataTable the $this->currentControllerAction DIV ID is already there in the page + // we make the DIV ID really unique by appending the ID of the subtable requested + if( $this->idSubtable != false) + { + $uniqIdTable = 'subDataTable_' . $this->idSubtable; + } + return $uniqIdTable; + } + + public function setColumnsToDisplay( $arrayIds) + { + $this->columnsToDisplay = $arrayIds; + } + + protected function isColumnToDisplay( $idColumn ) + { + // we return true + // - we didn't set any column to display (means we display all the columns) + // - the column has been set as to display + if( count($this->columnsToDisplay) == 0 + || in_array($idColumn, $this->columnsToDisplay)) + { + return true; + } + return false; + } + + protected function getColumnsToDisplay($phpArray) + { + + $dataTableColumns = array(); if(count($phpArray) > 0) { // build column information $id = 0; foreach($phpArray[0]['columns'] as $columnName => $row) { - $dataTableColumns[] = array('id' => $id, 'name' => $columnName); + if( $this->isColumnToDisplay( $id, $columnName) ) + { + $dataTableColumns[] = array('id' => $id, 'name' => $columnName); + } $id++; } } - $view->dataTableColumns = $dataTableColumns; - - + return $dataTableColumns; + } + + protected function getDefaultOrCurrent( $nameVar ) + { + if(isset($_REQUEST[$nameVar])) + { + return $_REQUEST[$nameVar]; + } + $default = $this->getDefault($nameVar); + return $default; + } + + protected function getDefault($nameVar) + { + if(!isset($this->variablesDefault[$nameVar])) + { + return false; + } + return $this->variablesDefault[$nameVar]; + } + + public function setDefaultLimit( $limit ) + { + $this->variablesDefault['filter_limit'] = $limit; + } + + public function setSortedColumn( $columnId, $order = 'desc') + { + $this->variablesDefault['filter_sort_column']= $columnId; + $this->variablesDefault['filter_sort_order']= $order; + } + + + public function disableOffsetInformation() + { + $this->JSoffsetInformation = 'false'; + } + public function getOffsetInformation() + { + return $this->JSoffsetInformation; + } + + public function disableSearchBox() + { + $this->JSsearchBox = 'false'; + } + public function getSearchBox() + { + return $this->JSsearchBox; + } + public function disableExcludeLowPopulation() + { + $this->JSexcludeLowPopulation = 'false'; + } + + public function getExcludeLowPopulation() + { + return $this->JSexcludeLowPopulation; + } + + protected function getJavascriptVariablesToSet( ) + { // build javascript variables to set $javascriptVariablesToSet = array(); @@ -152,10 +692,19 @@ class Piwik_UserSettings_Controller extends Piwik_Controller if(isset($filterInfo[1])) { $javascriptVariablesToSet[$filterVariableName] = $filterInfo[1]; + + // we set the default specified column and Order to sort by + // when this javascript variable is not set already + // for example during an AJAX call this variable will be set in the URL + // so this will not be executed ( and the default sorted not be used as the sorted column might have changed in the meanwhile) + if( false !== ($defaultValue = $this->getDefault($filterVariableName))) + { + $javascriptVariablesToSet[$filterVariableName] = $defaultValue; + } } } } - +// var_dump($javascriptVariablesToSet);exit; //TODO check security of printing javascript variables; inject some JS code here?? foreach($_GET as $name => $value) { @@ -168,35 +717,66 @@ class Piwik_UserSettings_Controller extends Piwik_Controller $javascriptVariablesToSet[$name] = $requestValue; } - $javascriptVariablesToSet['action'] = $currentControllerAction; + $javascriptVariablesToSet['action'] = $this->currentControllerAction; - // mapping between the current action call and the API method to call when a SubDataTable is requested - // for a row returned by this action method - $mapping = array( - 'getKeywords' => 'getSearchEnginesFromKeywordId', - 'getSearchEngines' => 'getKeywordsFromSearchEngineId', - ); - if(isset($mapping[$currentControllerAction])) + if(!is_null($this->actionToLoadTheSubTable)) { - $javascriptVariablesToSet['actionToLoadTheSubTable'] = $mapping[$currentControllerAction]; + $javascriptVariablesToSet['actionToLoadTheSubTable'] = $this->actionToLoadTheSubTable; } - $javascriptVariablesToSet['totalRows'] = $dataTable->getRowsCountBeforeLimitFilter(); - $view->javascriptVariablesToSet = $javascriptVariablesToSet; + $javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter(); - return $view; + $javascriptVariablesToSet['show_search'] = $this->getSearchBox(); + $javascriptVariablesToSet['show_offset_information'] = $this->getOffsetInformation(); + $javascriptVariablesToSet['show_exclude_low_population'] = $this->getExcludeLowPopulation(); + + return $javascriptVariablesToSet; } - - protected function renderView($view, $fetch) + protected function loadDataTableFromAPI() { - $rendered = $view->render(); - if($fetch) + + // we prepare the string to give to the API Request + // we setup the method and format variable + // - we request the method to call to get this specific DataTable + // - the format = original specifies that we want to get the original DataTable structure itself, not rendered + $requestString = 'method='.$this->moduleNameAndMethod.'&format=original'; + + // if a subDataTable is requested we add the variable to the API request string + if( $this->idSubtable != false) { - return $rendered; + $requestString .= '&this->idSubtable='.$this->idSubtable; } - echo $rendered; - return; + + $toSetEventually = array( + 'filter_limit', + 'filter_sort_column', + 'filter_sort_order', + ); + foreach($toSetEventually as $varToSet) + { + $value = $this->getDefaultOrCurrent($varToSet); + if( false !== $value ) + { + $requestString .= '&'.$varToSet.'='.$value; + } + } + // We finally make the request to the API + $request = new Piwik_API_Request($requestString); + + // and get the DataTable structure + $dataTable = $request->process(); + + $this->dataTable = $dataTable; + } + + protected function getPHPArrayFromDataTable( ) + { + $renderer = Piwik_DataTable_Renderer::factory('php'); + $renderer->setTable($this->dataTable); + $renderer->setSerialize( false ); + $phpArray = $renderer->render(); + return $phpArray; } - } + diff --git a/plugins/UserSettings/templates/datatable.tpl b/plugins/UserSettings/templates/datatable.tpl index 58e049fa36..018be86fcf 100644 --- a/plugins/UserSettings/templates/datatable.tpl +++ b/plugins/UserSettings/templates/datatable.tpl @@ -1,6 +1,9 @@ <div id="{$id}" class="parentDiv"> - {if isset($dataTable.result) and $dataTable.result == 'error'} - {$dataTable.message} +{if isset($dataTable.result) and $dataTable.result == 'error'} + {$dataTable.message} +{else} + {if count($dataTable) == 0} + No data for this table. {else} <table class="dataTable"> <thead> @@ -14,43 +17,51 @@ <tbody> {foreach from=$dataTable item=row} <tr {if $row.idsubdatatable}class="subDataTable" id="{$row.idsubdatatable}"{/if}> - {foreach from=$dataTableColumns item=column} - <td> {$row.columns[$column.name]}</td> + {foreach from=$dataTableColumns key=idColumn item=column} + <td> + {if $idColumn==0 && isset($row.details.url)}<span id="urlLink">{$row.details.url}</span>{/if} + {if $idColumn==0 && isset($row.details.logo)}<img src="{$row.details.logo}" />{/if} + {if false && $idColumn==0} + <span id="label">{$row.columns[$column.name]}</span> + {else} + {$row.columns[$column.name]} + {/if} + + + </td> {/foreach} </tr> {/foreach} </tbody> </table> + {/if} + <div id="dataTableFeatures"> + <span id="dataTableExcludeLowPopulation"></span> + + <span id="dataTableSearchPattern"> + <input id="keyword" type="text" length="15"> + <input type="submit" value="Search"> + </span> + + <span id="dataTablePages"></span> + <span id="dataTablePrevious">< Previous</span> + <span id="dataTableNext">Next ></span> + <span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif"> Loading...</span> + + </div> - <div id="dataTableFeatures"> - <span id="dataTableExcludeLowPopulation"></span> - - <span id="dataTableSearchPattern"> - <input id="keyword" type="text" length="15"> - <input type="submit" value="Search"> - </span> - - <span id="dataTablePages"></span> - <span id="dataTablePrevious">< Previous</span> - <span id="dataTableNext">Next ></span> - <span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif"> Loading...</span> - - </div> - - - - <script type="text/javascript" defer="defer"> - function populateVar() - {$smarty.ldelim} - requestVariables.{$id} = new Object; - - {foreach from=$javascriptVariablesToSet key=name item=value} - requestVariables.{$id}.{$name} = '{$value}'; - {/foreach} - - //alert('loaded'); - {$smarty.rdelim} - populateVar(); - </script> + <script type="text/javascript" defer="defer"> + function populateVar() + {$smarty.ldelim} + requestVariables.{$id} = new Object; + + {foreach from=$javascriptVariablesToSet key=name item=value} + requestVariables.{$id}.{$name} = '{$value}'; + {/foreach} + + //alert('loaded'); + {$smarty.rdelim} + populateVar(); + </script> {/if} </div> \ No newline at end of file diff --git a/plugins/UserSettings/templates/index.tpl b/plugins/UserSettings/templates/index.tpl index 9f20f8930f..50b07a3cce 100644 --- a/plugins/UserSettings/templates/index.tpl +++ b/plugins/UserSettings/templates/index.tpl @@ -112,6 +112,40 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; } } + function resetAllFilters() + { + var FiltersToRestore = new Array(); + filters = [ + 'filter_column', + 'filter_pattern', + 'filter_excludelowpop', + 'filter_excludelowpop_value', + 'filter_offset', + 'filter_limit', + 'filter_sort_column', + 'filter_sort_order', + ]; + + for(key in filters) + { + value = filters[key]; + FiltersToRestore[value] = getRequestVariable(value); + //if(FiltersToRestore[value]!=false) alert('save '+value+'='+FiltersToRestore[value]); + addFilter(value, false); + } + + + return FiltersToRestore; + } + + function restoreAllFilters(FiltersToRestore) + { + for(key in FiltersToRestore) + { + value = FiltersToRestore[key]; + addFilter(key, value); + } + } /* List of the filters to be applied // pattern search 'filter_column' @@ -130,10 +164,35 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; 'filter_limit' */ - $('#loadingDataTable', this).hide(); + if(getRequestVariable( 'show_search' ) == true) + { + $('#dataTableSearchPattern', this).show(); + } + + if( getRequestVariable( 'show_offset_information' ) == true ) + { + $('#dataTablePages', this).each( + function(){ + var offset = 1+Number(getRequestVariable('filter_offset')); + var offsetEnd = Number(getRequestVariable('filter_offset')) + + Number(getRequestVariable('filter_limit')); + var totalRows = Number(getRequestVariable('totalRows')); + offsetEndDisp = offsetEnd; + // alert(totalRows); + if(offsetEnd > totalRows) offsetEndDisp = totalRows; + var str = offset + '-' + offsetEndDisp + ' of ' + totalRows; + //alert(str); + $(this).text(str); + } + ); + } + + if( getRequestVariable( 'show_exclude_low_population' ) == true) + { + $('#dataTableExcludeLowPopulation', this) + .each( setExcludeLowPopulationString ); + } - $('#dataTableExcludeLowPopulation', this) - .each( setExcludeLowPopulationString ); $('#dataTableExcludeLowPopulation', this) .click( @@ -158,21 +217,6 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; ); - $('#dataTablePages', this).each( - function(){ - var offset = 1+Number(getRequestVariable('filter_offset')); - var offsetEnd = Number(getRequestVariable('filter_offset')) - + Number(getRequestVariable('filter_limit')); - var totalRows = Number(getRequestVariable('totalRows')); - offsetEndDisp = offsetEnd; -// alert(totalRows); - if(offsetEnd > totalRows) offsetEndDisp = totalRows; - var str = offset + '-' + offsetEndDisp + ' of ' + totalRows; - //alert(str); - $(this).text(str); - } - ); - // @@ -182,7 +226,7 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; var offsetEnd = Number(getRequestVariable('filter_offset')) + Number(getRequestVariable('filter_limit')); var totalRows = Number(getRequestVariable('totalRows')); - if(offsetEnd <= totalRows) + if(offsetEnd < totalRows) { $(this).css('display','inline'); } @@ -250,8 +294,26 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; // we truncate the labels columns from the second row - $("td:first-child", this).truncate(30); + $("table tr td:first-child", this).truncate(30); $('.truncated', this).Tooltip(); + + // we add a link based on the <span id="urlLink"> present in the column label (the first column) + // if this span is there, we add the link around the HTML in the TD + // but we add this link only for the rows that are not clickable already (subDataTable) + $("tr:not('.subDataTable') td:first-child:has('#urlLink')", this).each( function(){ + + var imgToPrepend = ''; + if( $(this).find('img').length == 0 ) + { + imgToPrepend = '<img src="themes/default/images/link.gif" /> '; + } + var urlToLink = $('#urlLink',this).text(); + + $(this).html( + '<a target="_blank" href="' + urlToLink + '">' + imgToPrepend + $(this).html() + '</a>' + ); + }); + $("td:first-child:odd", this).addClass('label labelodd'); $("td:first-child:even", this).addClass('label labeleven'); @@ -363,40 +425,6 @@ if(!requestVariables[workingDivId]) requestVariables[workingDivId] = new Object; - function resetAllFilters() - { - var FiltersToRestore = new Array(); - filters = [ - 'filter_column', - 'filter_pattern', - 'filter_excludelowpop', - 'filter_excludelowpop_value', - 'filter_offset', - 'filter_limit', - 'filter_sort_column', - 'filter_sort_order', - ]; - - for(key in filters) - { - value = filters[key]; - FiltersToRestore[value] = getRequestVariable(value); - //if(FiltersToRestore[value]!=false) alert('save '+value+'='+FiltersToRestore[value]); - addFilter(value, false); - } - - - return FiltersToRestore; - } - - function restoreAllFilters(FiltersToRestore) - { - for(key in FiltersToRestore) - { - value = FiltersToRestore[key]; - addFilter(key, value); - } - } } function bindAllDataTableEvent() @@ -460,6 +488,11 @@ table.dataTable { font-size:0.9em; } +table.dataTable img { + border:0; + margin-right:1em; + margin-left:0.5em; +} table.dataTable tr.subDataTable{ cursor:pointer; } @@ -482,11 +515,15 @@ table.dataTable td.label { } table.dataTable td { - margin:0; border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7; - background: #fff; padding: 6px 6px 6px 12px; + background: #fff; +} + +table.dataTable td,table.dataTable td a { + margin:0; + text-decoration:none; color: #4f6b72; } @@ -530,21 +567,24 @@ table.subDataTable tr.columnodd td { background:#f7fbff } - table.subDataTable td { - color:#678197; border-bottom:1px solid #e5eff8; border-left:1px solid #e5eff8; padding:.3em 1em; +} + +table.subDataTable td, table.subDataTable td a { + text-decoration:none; + color:#678197; text-align:left; } -table.subDataTable td.label { +table.subDataTable td.label, table.subDataTable td.label a { background:#ffffff; width:80%; } -table.subDataTable td.labelodd { +table.subDataTable td.labelodd, table.subDataTable td.labelodd a{ background:#f4f9fe; } @@ -566,6 +606,11 @@ table.subDataTable thead th { /* misc SPAN and DIV */ +/* A link in a column in the DataTable */ +table td #urlLink { + display:none; +} + #dataTablePages { color:grey; font-weight:bold; @@ -609,7 +654,7 @@ table.subDataTable thead th { div.subDataTable { font-size:0.8em; } -#dataTableNext, #dataTablePrevious { +#dataTableNext, #dataTablePrevious, #dataTableSearchPattern, #loadingDataTable { display:none; } @@ -624,14 +669,87 @@ div.subDataTable { </style> {/literal} -<h1>User Settings<h1> +<h1>All the Piwik reports<h1> -<h2>Search engines</h2> -{$dataTableSearchEngines} -<h2>Keywords</h2> +<h2>User Country</h2> + +<h3>Country</h3> +{$dataTableCountry} + +<h3>Continent</h3> +{$dataTableContinent} + +<h2>Provider</h2> +{$dataTableProvider} + +<h2>Referers</h2> +<h3>Numbers</h3> +{$numberDistinctSearchEngines} distinct search engines <br> +{$numberDistinctKeywords} distinct keywords<br> +{$numberDistinctCampaigns} distinct campaigns <br> +{$numberDistinctWebsites} distinct websites<br> +{$numberDistinctWebsitesUrls} distinct websites URLs<br> +{$numberDistinctPartners} distinct partners<br> +{$numberDistinctPartnersUrls} distinct partners URLs<br> + + +<h3>Referer Type</h3> +{$dataTableRefererType} + +<h3>Keywords</h3> {$dataTableKeywords} -<h2>Browsers</h2> -{$dataTableBrowser} -<h2>Resolutions</h2> + +<h3>Search Engines</h3> +{$dataTableSearchEngines} + +<h3>Campaigns</h3> +{$dataTableCampaigns} + +<h3>Websites</h3> +{$dataTableWebsites} + +<h3>Partners</h3> +{$dataTablePartners} + +<h2>User Settings</h2> +<h3>Configurations</h3> +{$dataTableConfiguration} + +<h3>Resolutions</h3> {$dataTableResolution} +<h3>Operating systems</h3> +{$dataTableOS} + +<h3>Browsers</h3> +{$dataTableBrowser} + +<h3>Browser families</h3> +{$dataTableBrowserType} + +<h3>Wide Screen</h3> +{$dataTableWideScreen} + +<h3>Plugins</h3> +{$dataTablePlugin} + + +<h2>Frequency</h2> +{$nbVisitsReturning} returning visits<br> +{$nbActionsReturning} actions by the returning visits<br> +{$maxActionsReturning} maximum actions by a returning visit<br> +{$sumVisitLengthReturning} total time spent by returning visits<br> +{$bounceCountReturning} times that a returning visit has bounced<br> + +<h2>Visit Time</h2> +<h3>Visit per local time</h3> +{$dataTableVisitInformationPerLocalTime} +<h3>Visit per server time</h3> +{$dataTableVisitInformationPerServerTime} + +<h2>Visitor Interest</h2> +<h3>Visits per visit duration</h3> +{$dataTableNumberOfVisitsPerVisitDuration} +<h3>Visits per number of pages</h3> +{$dataTableNumberOfVisitsPerPage} + \ No newline at end of file diff --git a/plugins/VisitTime.php b/plugins/VisitTime.php index 4a4171b832..4e985b646c 100644 --- a/plugins/VisitTime.php +++ b/plugins/VisitTime.php @@ -56,6 +56,7 @@ class Piwik_VisitTime extends Piwik_Plugin $recordName = 'VisitTime_localTime'; $labelSQL = "HOUR(visitor_localtime)"; $tableLocalTime = $archiveProcessing->getDataTableInterestForLabel($labelSQL); + $record = new Piwik_ArchiveProcessing_Record_Blob_Array($recordName, $tableLocalTime->getSerialized()); // echo $tableLocalTime; diff --git a/plugins/VisitTime/API.php b/plugins/VisitTime/API.php index 951aedf43a..6127f08da1 100644 --- a/plugins/VisitTime/API.php +++ b/plugins/VisitTime/API.php @@ -24,7 +24,7 @@ class Piwik_VisitTime_API extends Piwik_Apiable $archive = Piwik_Archive::build($idSite, $date, $period ); $dataTable = $archive->getDataTable($name); - $dataTable->queueFilter('Piwik_DataTable_Filter_Sort', array('label', 'asc')); + //$dataTable->queueFilter('Piwik_DataTable_Filter_Sort', array('label', 'asc')); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getTimeLabel')); $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); diff --git a/plugins/VisitorInterest.php b/plugins/VisitorInterest.php index 90093ab12f..9e45440440 100644 --- a/plugins/VisitorInterest.php +++ b/plugins/VisitorInterest.php @@ -114,7 +114,7 @@ class Piwik_VisitorInterest extends Piwik_Plugin } $toSelect = implode(" , ", $select); - return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, 'nb_visits'); + return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, Piwik_Archive::INDEX_NB_VISITS); } protected function getTableTimeGap() @@ -142,6 +142,6 @@ class Piwik_VisitorInterest extends Piwik_Plugin } $toSelect = implode(" , ", $select); - return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, 'nb_visits'); + return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, Piwik_Archive::INDEX_NB_VISITS); } } \ No newline at end of file diff --git a/tests/modules/PHP_Related.test.php b/tests/modules/PHP_Related.test.php index 019cee94e7..48e0ff7405 100644 --- a/tests/modules/PHP_Related.test.php +++ b/tests/modules/PHP_Related.test.php @@ -41,6 +41,20 @@ class Test_PHP_Related extends UnitTestCase { } + public function testMergeArray() + { + $a = array('label' => 'test'); + $b = array('test' => 1, 1 => 2100); + + $expected = array( + 'label' => 'test', + 'test' => 1, 1 => 2100 + ); + +// $this->assertEqual( array_merge($a,$b), $expected); + $this->assertEqual( $a+$b, $expected); + } + /** * test reading static attribute of a variable class */ -- GitLab