diff options
author | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2009-05-05 02:55:35 +0400 |
---|---|---|
committer | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2009-05-05 02:55:35 +0400 |
commit | cb346a4546a53bdc5054129d3331470cb3a447fc (patch) | |
tree | 155a924d3e86b7869c89022e3fbf19ca7be2ce2f | |
parent | 92da6b8181282800f4f28cae77d776b67540b477 (diff) |
- ADDED search field below data tables is now using the regular expression syntax. For example, a search for "google|yahoo" would match all rows containing "google" or "yahoo". All search strings containing any of the special characters from this list: . \ + * ? [ ^ ] $ ( ) { } = ! < > | must be escaped with a back slash, eg. if you want to search for keywords containing "piwik!" you would search for "piwik\!".
- ADDED new configuration option: default number of rows returned in API responses "API_datatable_default_limit = 50"
- REMOVED the automatic generic filters. The limit and sort and safe decode are applied by each module when necessary.
- removed exact match filter. Now all searches are using regular expressions syntax. Exact match can be done using ^exact search here$
- fixed notice when natural sort on a non existing column
- fixed CSV export for datatable_array
- clarified code for plotting multiple lines in an evolution chart
- FIXED #624 Added icon "save as image" below all graphs (next to the Export icon)
- moved all JS functions into the piwikHelper static class
- added example in ExampleUI plugin to plot only visits from google and yahoo! in 4 lines of code
- added message when flash is disabled and graph not showing, linking to piwik faq.
- added expressInstall.swf feature
61 files changed, 458 insertions, 460 deletions
diff --git a/config/global.ini.php b/config/global.ini.php index 8afdc24ef7..b2a985d4b2 100755 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -73,11 +73,11 @@ default_currency = "$" ; plugin, and set this default_language (users won't see the language drop down) default_language = en -; default sorting order used by all datatables (desc or asc) -dataTable_default_sort_order = desc - ; default number of elements in the datatable -dataTable_default_limit = 10 +datatable_default_limit = 10 + +; default number of rows returned in API responses +API_datatable_default_limit = 50 ; if set to 1, the website selector will be displayed in the Piwik UI ; if your Piwik installation has thousands of websites, you may disable the website selector diff --git a/core/API/DataTableGenericFilter.php b/core/API/DataTableGenericFilter.php index 0143397d40..59e616e1ee 100644 --- a/core/API/DataTableGenericFilter.php +++ b/core/API/DataTableGenericFilter.php @@ -36,10 +36,6 @@ class Piwik_API_DataTableGenericFilter 'filter_column_recursive' => array('string'), 'filter_pattern_recursive' => array('string'), ), - 'ExactMatch' => array( - 'filter_exact_column' => array('string'), - 'filter_exact_pattern' => array('array'), - ), 'ExcludeLowPopulation' => array( 'filter_excludelowpop' => array('string'), 'filter_excludelowpop_value'=> array('float', '0'), @@ -52,13 +48,12 @@ class Piwik_API_DataTableGenericFilter ), 'Sort' => array( 'filter_sort_column' => array('string'), - 'filter_sort_order' => array('string', Zend_Registry::get('config')->General->dataTable_default_sort_order), + 'filter_sort_order' => array('string'), ), 'Limit' => array( 'filter_offset' => array('integer', '0'), - 'filter_limit' => array('integer', Zend_Registry::get('config')->General->dataTable_default_limit), + 'filter_limit' => array('integer'), ), - 'SafeDecodeLabel' => array(), ); return $genericFilters; diff --git a/core/API/Request.php b/core/API/Request.php index 60bef14822..c9d9d3202f 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -67,7 +67,6 @@ class Piwik_API_Request Piwik_PostEvent('API.Request.authenticate', $requestArray['token_auth']); Zend_Registry::get('access')->reloadAccess(); } - $requestArray = $requestArray + $defaultRequest; } diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index 1f6f04c8fb..87c279fabe 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -249,6 +249,9 @@ class Piwik_API_ResponseBuilder $genericFilter->filter(); } + // we automatically safe decode all datatable labels (against xss) + $datatable->queueFilter('SafeDecodeLabel'); + // if the flag disable_queued_filters is defined we skip the filters that were queued if(Piwik_Common::getRequestVar('disable_queued_filters', 'false', 'string', $this->request) == 'false') { diff --git a/core/Archive/Array/IndexedByDate.php b/core/Archive/Array/IndexedByDate.php index f9fe5eb3a1..3a84e30089 100644 --- a/core/Archive/Array/IndexedByDate.php +++ b/core/Archive/Array/IndexedByDate.php @@ -83,9 +83,7 @@ class Piwik_Archive_Array_IndexedByDate extends Piwik_Archive_Array FROM $table WHERE idarchive IN ( $inIds ) AND name IN ( $inNames )"; - $values = $db->fetchAll($sql); - foreach($values as $value) { $arrayValues[$value['timestamp']][$value['name']] = (float)$value['value']; diff --git a/core/ArchiveProcessing.php b/core/ArchiveProcessing.php index d2b5c6f72f..66d0a33a9b 100644 --- a/core/ArchiveProcessing.php +++ b/core/ArchiveProcessing.php @@ -592,11 +592,9 @@ abstract class Piwik_ArchiveProcessing protected function isArchivingDisabled() { static $archivingIsDisabled = null; - if(is_null($archivingIsDisabled)) { $archivingIsDisabled = false; - $enableBrowserArchivingTriggering = (bool)Zend_Registry::get('config')->General->enable_browser_archiving_triggering; if($enableBrowserArchivingTriggering == false) { @@ -606,7 +604,6 @@ abstract class Piwik_ArchiveProcessing } } } - return $archivingIsDisabled; } } diff --git a/core/Common.php b/core/Common.php index 8c3b79c25b..9c53ef72ce 100644 --- a/core/Common.php +++ b/core/Common.php @@ -46,17 +46,20 @@ class Piwik_Common */ static public function prefixTable($table) { - $prefixTable = false; - if(defined('PIWIK_TRACKER_MODE') && PIWIK_TRACKER_MODE) + static $prefixTable = null; + if(is_null($prefixTable)) { - $prefixTable = Piwik_Tracker_Config::getInstance()->database['tables_prefix']; - } - else - { - $config = Zend_Registry::get('config'); - if($config !== false) + if(defined('PIWIK_TRACKER_MODE') && PIWIK_TRACKER_MODE) { - $prefixTable = $config->database->tables_prefix; + $prefixTable = Piwik_Tracker_Config::getInstance()->database['tables_prefix']; + } + else + { + $config = Zend_Registry::get('config'); + if($config !== false) + { + $prefixTable = $config->database->tables_prefix; + } } } return $prefixTable . $table; @@ -402,9 +405,7 @@ class Piwik_Common { $requestArrayToUse = $_GET + $_POST; } - $varDefault = self::sanitizeInputValues( $varDefault ); - if($varType == 'int') { // settype accepts only integer @@ -435,7 +436,7 @@ class Piwik_Common return $varDefault; } } - + // Normal case, there is a value available in REQUEST for the requested varName $value = self::sanitizeInputValues( $requestArrayToUse[$varName] ); @@ -483,7 +484,6 @@ class Piwik_Common } } } - return $value; } diff --git a/core/Controller.php b/core/Controller.php index 36c56852a0..9d99b2f8ae 100644 --- a/core/Controller.php +++ b/core/Controller.php @@ -67,7 +67,7 @@ abstract class Piwik_Controller { return 'index'; } - + protected $standardColumnNameToTranslation = array( 'label' => 'General_ColumnLabel', 'nb_visits' => 'General_ColumnNbVisits', @@ -82,7 +82,7 @@ abstract class Piwik_Controller 'revenue_per_visit' => 'General_ColumnValuePerVisit', 'goals_conversion_rate' => 'General_ColumnVisitsWithConversions', ); - + /** * Given an Object implementing Piwik_iView interface, we either: * - echo the output of the rendering if fetch = false @@ -129,6 +129,9 @@ abstract class Piwik_Controller require_once "ViewDataTable/GenerateGraphHTML.php"; $view = Piwik_ViewDataTable::factory('graphEvolution'); $view->init( $currentModuleName, $currentControllerAction, $apiMethod ); + $view->disableExcludeLowPopulation(); + $view->disableShowAllViewsIcons(); + $view->disableShowTable(); // if the date is not yet a nicely formatted date range ie. YYYY-MM-DD,YYYY-MM-DD we build it // otherwise the current controller action is being called with the good date format already so it's fine diff --git a/core/DataTable/Filter.php b/core/DataTable/Filter.php index 46984d5426..64654905ce 100644 --- a/core/DataTable/Filter.php +++ b/core/DataTable/Filter.php @@ -57,7 +57,6 @@ require_once "DataTable/Filter/ReplaceColumnNames.php"; require_once "DataTable/Filter/Sort.php"; require_once "DataTable/Filter/AddSummaryRow.php"; require_once "DataTable/Filter/ReplaceSummaryRowLabel.php"; -require_once "DataTable/Filter/ExactMatch.php"; require_once "DataTable/Filter/SafeDecodeLabel.php"; require_once "DataTable/Filter/AddColumnsWhenShowAllColumns.php"; require_once "DataTable/Filter/UpdateColumnsWhenShowAllGoals.php"; diff --git a/core/DataTable/Filter/ExactMatch.php b/core/DataTable/Filter/ExactMatch.php deleted file mode 100644 index 3f68658d61..0000000000 --- a/core/DataTable/Filter/ExactMatch.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later - * @version $Id$ - * - * @package Piwik_DataTable - */ - -/** - * Delete all rows for which the given $columnToFilter do not equal $patternToSearch - * This filter can be used on both integer and string columns. - * You can pass an array of integers in $patternToSearch parameter. - * - * @package Piwik_DataTable - * @subpackage Piwik_DataTable_Filter - */ -class Piwik_DataTable_Filter_ExactMatch extends Piwik_DataTable_Filter -{ - private $columnToFilter; - private $patternToSearch; - - public function __construct( $table, $columnToFilter, $patternToSearch ) - { - parent::__construct($table); - $this->patternToSearch = $patternToSearch; - $this->columnToFilter = $columnToFilter; - $this->filter(); - } - - protected function filter() - { - foreach($this->table->getRows() as $key => $row) - { - if( is_array($this->patternToSearch) ) - { - if( in_array($row->getColumn($this->columnToFilter), $this->patternToSearch) == false ) - { - $this->table->deleteRow($key); - } - } - else if( $row->getColumn($this->columnToFilter) != $this->patternToSearch ) - { - $k = $row->getColumn($this->columnToFilter); - $this->table->deleteRow($key); - } - } - } -} - diff --git a/core/DataTable/Filter/Pattern.php b/core/DataTable/Filter/Pattern.php index d12e4920ec..8a3c1eb7fe 100644 --- a/core/DataTable/Filter/Pattern.php +++ b/core/DataTable/Filter/Pattern.php @@ -34,7 +34,7 @@ class Piwik_DataTable_Filter_Pattern extends Piwik_DataTable_Filter static public function getPatternQuoted( $pattern ) { - return "/". preg_quote($pattern, '/') ."/"; + return "/". str_replace('/','\/', $pattern) ."/"; } /* @@ -42,8 +42,7 @@ class Piwik_DataTable_Filter_Pattern extends Piwik_DataTable_Filter */ static public function match($pattern, $patternQuoted, $string) { - return preg_match($patternQuoted . "i", $string) == 1 - && stripos($string, $pattern) !== false; + return @preg_match($patternQuoted . "i", $string) == 1; } protected function filter() diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php index 0b80a322d8..5c066cbe54 100644 --- a/core/DataTable/Filter/Sort.php +++ b/core/DataTable/Filter/Sort.php @@ -76,10 +76,20 @@ class Piwik_DataTable_Filter_Sort extends Piwik_DataTable_Filter function naturalSort($a, $b) { - return $this->sign * strnatcasecmp( - $a->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort], - $b->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort] - ); + return !isset($a->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort]) + && !isset($b->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort] ) + ? 0 + : (!isset($a->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort]) + ? 1 + : (!isset($b->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort] ) + ? -1 + : $this->sign * strnatcasecmp( + $a->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort], + $b->c[Piwik_DataTable_Row::COLUMNS][$this->columnToSort] + ) + ) + ) + ; } function sortString($a, $b) diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php index 53dbc25a8d..567ece1b6f 100644 --- a/core/DataTable/Renderer/Csv.php +++ b/core/DataTable/Renderer/Csv.php @@ -65,7 +65,7 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer function render() { - return $this->renderTable($this->table); + return $this->output($this->renderTable($this->table)); } protected function renderTable($table) @@ -104,8 +104,7 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer { $str = $this->renderDataTable($table); } - - return $this->output($str); + return $str; } protected function renderDataTable( $table ) diff --git a/core/Date.php b/core/Date.php index 394adab8d4..001af599fa 100644 --- a/core/Date.php +++ b/core/Date.php @@ -67,16 +67,6 @@ class Piwik_Date $this->timestamp = $date ; } - /* - * @param int Timestamp - * @return string Pretty date in the current locale - */ - static public function getPrettyDateFromTimestamp($timestamp) - { - $date = Piwik_Date::factory($timestamp); - return $date->getLocalized(Piwik_Translate('CoreHome_LocalizedDateFormat')); - } - /** * Sets the time part of the date * Doesn't modify $this @@ -237,7 +227,12 @@ class Piwik_Date return date($part, $this->getTimestamp()); } - //TODO to test + /** + * Returns a localized date string, given a template. + * Allowed tags are: %day%, %shortDay%, %longDay%, etc. + * @param $template string eg. %shortMonth% %longYear% + * @return string eg. "Aug 2009" + */ public function getLocalized($template) { $day = $this->toString('j'); diff --git a/core/FrontController.php b/core/FrontController.php index 8270f53212..0eb1112c10 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -230,14 +230,9 @@ class Piwik_FrontController Piwik::createDatabaseObject(); Piwik::createLogObject(); - // creating the access object, so that core/Updates/* can enforce Super User and use some APIs Piwik::createAccessObject(); - - require_once "CoreUpdater/Controller.php"; - //TODO should not be a controller! - $updaterController = new Piwik_CoreUpdater_Controller(); - $updaterController->checkForCoreAndPluginsUpdates(); + Piwik::displayScreenForCoreAndPluginsUpdatesIfNecessary(); Piwik_PluginsManager::getInstance()->installLoadedPlugins(); Piwik::install(); diff --git a/core/Piwik.php b/core/Piwik.php index 8f928ccf3f..428b17ead6 100644 --- a/core/Piwik.php +++ b/core/Piwik.php @@ -904,6 +904,30 @@ class Piwik return false; } + static public function displayScreenForCoreAndPluginsUpdatesIfNecessary() + { + require_once "Updater.php"; + require_once "Version.php"; + $updater = new Piwik_Updater(); + $updater->addComponentToCheck('core', Piwik_Version::VERSION); + + $plugins = Piwik_PluginsManager::getInstance()->getInstalledPlugins(); + foreach($plugins as $pluginName => $plugin) + { + $updater->addComponentToCheck($pluginName, $plugin->getVersion()); + } + + $componentsWithUpdateFile = $updater->getComponentsWithUpdateFile(); + if(count($componentsWithUpdateFile) == 0) + { + return; + } + + require_once "CoreUpdater/Controller.php"; + $updaterController = new Piwik_CoreUpdater_Controller(); + $updaterController->runUpdaterAndExit($componentsWithUpdateFile); + } + /** * Sends http request ensuring the request will fail before $timeout seconds * Returns the response content (no header, trimmed) diff --git a/core/Url.php b/core/Url.php index 27b57310ec..c1fca7f647 100644 --- a/core/Url.php +++ b/core/Url.php @@ -165,14 +165,28 @@ class Piwik_Url static function getCurrentQueryStringWithParametersModified( $params ) { $urlValues = self::getArrayFromCurrentQueryString(); - foreach($params as $key => $value) { $urlValues[$key] = $value; } - + $query = self::getQueryStringFromParameters($urlValues); + if(strlen($query) > 0) + { + return '?'.$query; + } + return ''; + } + + /** + * Given an array of parameters name->value, returns the query string. + * Also works with array values using the php array syntax for GET parameters. + * @param $parameters eg. array( 'param1' => 10, 'param2' => array(1,2)) + * @return string eg. "param1=10¶m2[]=1¶m2[]=2" + */ + static public function getQueryStringFromParameters($parameters) + { $query = ''; - foreach($urlValues as $name => $value) + foreach($parameters as $name => $value) { if(empty($value)) { @@ -191,15 +205,7 @@ class Piwik_Url } } $query = substr($query, 0, -1); - - if(strlen($query) > 0) - { - return '?'.$query; - } - else - { - return ''; - } + return $query; } /** diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php index 0321171ba9..df329b585f 100644 --- a/core/ViewDataTable.php +++ b/core/ViewDataTable.php @@ -251,8 +251,10 @@ abstract class Piwik_ViewDataTable $this->viewProperties['show_goals'] = false; $this->viewProperties['show_search'] = Piwik_Common::getRequestVar('show_search', true); + $this->viewProperties['show_table'] = Piwik_Common::getRequestVar('show_table', true); $this->viewProperties['show_table_all_columns'] = Piwik_Common::getRequestVar('show_table_all_columns', true); $this->viewProperties['show_all_views_icons'] = Piwik_Common::getRequestVar('show_all_views_icons', true); + $this->viewProperties['show_export_as_image_icon'] = Piwik_Common::getRequestVar('show_export_as_image_icon', false); $this->viewProperties['show_exclude_low_population'] = Piwik_Common::getRequestVar('show_exclude_low_population', true); $this->viewProperties['show_offset_information'] = Piwik_Common::getRequestVar('show_offset_information', true);; $this->viewProperties['show_footer'] = Piwik_Common::getRequestVar('show_footer', true); @@ -368,8 +370,6 @@ abstract class Piwik_ViewDataTable 'filter_excludelowpop_value', 'filter_column', 'filter_pattern', - 'filter_exact_pattern', - 'filter_exact_column', 'disable_generic_filters', 'disable_queued_filters' ); @@ -666,6 +666,15 @@ abstract class Piwik_ViewDataTable } /** + * Whether or not to show the "View table" icon + * @return void + */ + public function disableShowTable() + { + $this->viewProperties['show_table'] = false; + } + + /** * Whether or not to show the "View more data" icon * @return void */ @@ -696,19 +705,6 @@ abstract class Piwik_ViewDataTable } /** - * Sets the pattern to look for in the table (only rows with column equal to the pattern will be kept) - * - * @param array $pattern arrays of patterns to look for - * @param string $column to compare the pattern to - * @return void - */ - public function setExactPattern($pattern, $column) - { - $this->variablesDefault['filter_exact_pattern'] = $pattern; - $this->variablesDefault['filter_exact_column'] = $column; - } - - /** * Sets the value to use for the Exclude low population filter. * * @param int|float If a row value is less than this value, it will be removed from the dataTable diff --git a/core/ViewDataTable/Cloud.php b/core/ViewDataTable/Cloud.php index c5fc45a67e..8c3d93a5f0 100644 --- a/core/ViewDataTable/Cloud.php +++ b/core/ViewDataTable/Cloud.php @@ -22,9 +22,9 @@ class Piwik_ViewDataTable_Cloud extends Piwik_ViewDataTable { protected $displayLogoInsteadOfLabel = false; - public function displayLogoInTagCloud() + public function setDisplayLogoInTagCloud($bool) { - $this->displayLogoInsteadOfLabel = true; + $this->displayLogoInsteadOfLabel = $bool; } protected function getViewDataTableId() @@ -79,6 +79,7 @@ class Piwik_ViewDataTable_Cloud extends Piwik_ViewDataTable $columnTranslation = $this->getColumnTranslation($columnToDisplay); $values = $this->dataTable->getColumn($columnToDisplay); $labels = $this->dataTable->getColumn('label'); + $labelMetadata = array(); foreach($this->dataTable->getRows() as $row) { $logo = false; diff --git a/core/ViewDataTable/GenerateGraphData.php b/core/ViewDataTable/GenerateGraphData.php index af61510bac..a197a88bf8 100644 --- a/core/ViewDataTable/GenerateGraphData.php +++ b/core/ViewDataTable/GenerateGraphData.php @@ -59,11 +59,27 @@ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable * * @return int */ - function getGraphLimit() + public function getGraphLimit() { return $this->graphLimit; } + protected $displayPercentageInTooltip = true; + + /** + * The percentage in tooltips is computed based on the sum of all values for the plotted column. + * If the sum of the column in the data set is not the number of elements in the data set, + * for example when plotting visits that have a given plugin enabled: + * one visit can have several plugins, hence the sum is much greater than the number of visits. + * In this case displaying the percentage doesn't make sense. + * + * @return void + */ + public function disallowPercentageInGraphTooltip() + { + $this->displayPercentageInTooltip = false; + } + public function main() { if($this->mainAlreadyExecuted) @@ -74,7 +90,6 @@ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable // the queued filters will be manually applied later. This is to ensure that filtering using search // will be done on the table before the labels are enhanced (see ReplaceColumnNames) - $this->disableGenericFilters(); $this->disableQueuedFilters(); $this->loadDataTableFromAPI(); @@ -97,14 +112,12 @@ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable } else { - $this->generateDataFromDataTable(); + $this->initChartObjectData(); } - //TODO rename - $this->view->customizeGraph(); + $this->view->customizeChartProperties(); } - //TODO rename - protected function generateDataFromDataTable() + protected function initChartObjectData() { $this->dataTable->applyQueuedFilters(); @@ -118,16 +131,16 @@ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable unset($columnNames[$labelColumnFound]); } - $columnNameToTranslation = $columnNameToValue = $columnNameToUnit = array(); + $columnNameToTranslation = $columnNameToValue = array(); foreach($columnNames as $columnName) { $columnNameToTranslation[$columnName] = $this->getColumnTranslation($columnName); $columnNameToValue[$columnName] = $this->dataTable->getColumn($columnName); - $columnNameToUnit[$columnName] = $this->yAxisUnit; } $this->view->setAxisXLabels($xLabels); $this->view->setAxisYValues($columnNameToValue); $this->view->setAxisYLabels($columnNameToTranslation); - $this->view->setAxisYUnits($columnNameToUnit); + $this->view->setAxisYUnit($this->yAxisUnit); + $this->view->setDisplayPercentageInTooltip($this->displayPercentageInTooltip); } } diff --git a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php index dc4eab30c0..6e950a1ada 100644 --- a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php +++ b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php @@ -19,13 +19,32 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat $this->view = new Piwik_Visualization_Chart_Evolution; } - protected function generateDataFromDataTable() + protected function guessUnitFromRequestedColumnNames($requestedColumnNames) + { + $nameToUnit = array( + '_rate' => '%', + '_revenue' => Piwik::getCurrency(), + ); + foreach($requestedColumnNames as $columnName) + { + foreach($nameToUnit as $pattern => $type) + { + if(strpos($columnName, $pattern) !== false) + { + return $type; + } + } + } + return false; + } + + protected function initChartObjectData() { // if the loaded datatable is a simple DataTable, it is most likely a plugin plotting some custom data // we don't expect plugin developers to return a well defined Piwik_DataTable_Array if($this->dataTable instanceof Piwik_DataTable) { - return parent::generateDataFromDataTable(); + return parent::initChartObjectData(); } $this->dataTable->applyQueuedFilters(); @@ -33,42 +52,53 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat { throw new Exception("Expecting a DataTable_Array with custom format to draw an evolution chart"); } + + // the X label is extracted from the 'period' object in the table's metadata $xLabels = $uniqueIdsDataTable = array(); foreach($this->dataTable->metadata as $idDataTable => $metadataDataTable) { + //eg. "Aug 2009" $xLabels[] = $metadataDataTable['period']->getLocalizedShortString(); + // we keep track of all unique data table that we need to set a Y value for $uniqueIdsDataTable[] = $idDataTable; } - // list of column names requested to be plotted, we only need to forward these to the Graph object - $columnNameRequested = $this->getColumnsToDisplay(); - - $columnNameToValue = array(); + $requestedColumnNames = $this->getColumnsToDisplay(); + $yAxisLabelToValue = array(); foreach($this->dataTable->getArray() as $idDataTable => $dataTable) { - if($dataTable->getRowsCount() > 1) + foreach($dataTable->getRows() as $row) { - throw new Exception("Expecting only one row per DataTable"); - } - $row = $dataTable->getFirstRow(); - if($row !== false) - { - foreach($row->getColumns() as $columnName => $columnValue) + $rowLabel = $row->getColumn('label'); + foreach($requestedColumnNames as $requestedColumnName) { - if(array_search($columnName, $columnNameRequested) !== false) + $metricLabel = $this->getColumnTranslation($requestedColumnName); + if($rowLabel !== false) + { + // eg. "Yahoo! (Visits)" + $yAxisLabel = "$rowLabel ($metricLabel)"; + } + else { - $columnNameToValue[$columnName][$idDataTable] = $columnValue; + // eg. "Visits" + $yAxisLabel = $metricLabel; + } + if(($columnValue = $row->getColumn($requestedColumnName)) !== false) + { + $yAxisLabelToValue[$yAxisLabel][$idDataTable] = $columnValue; } } } } - // make sure all column values are set (at least zero) in order for all unique idDataTable - $columnNameToValueCleaned = array(); + // make sure all column values are set to at least zero (no gap in the graph) + $yAxisLabelToValueCleaned = array(); + $yAxisLabels = array(); foreach($uniqueIdsDataTable as $uniqueIdDataTable) { - foreach($columnNameToValue as $columnName => $idDataTableToColumnValue) + foreach($yAxisLabelToValue as $yAxisLabel => $idDataTableToColumnValue) { + $yAxisLabels[$yAxisLabel] = $yAxisLabel; if(isset($idDataTableToColumnValue[$uniqueIdDataTable])) { $columnValue = $idDataTableToColumnValue[$uniqueIdDataTable]; @@ -77,43 +107,20 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat { $columnValue = 0; } - $columnNameToValueCleaned[$columnName][] = $columnValue; + $yAxisLabelToValueCleaned[$yAxisLabel][] = $columnValue; } } - $columnNames = array_keys($columnNameToValueCleaned); - $columnNameToTranslation = array(); - $columnNameToUnit = array(); - $nameToUnit = array( - '_rate' => '%', - '_revenue' => Piwik::getCurrency(), - ); - foreach($columnNames as $columnName) + + $unit = $this->yAxisUnit; + if(empty($unit)) { - $columnNameToTranslation[$columnName] = $this->getColumnTranslation($columnName); - - $columnNameToUnit[$columnName] = false; - // if the unit was specified, we use it - if(!empty($this->yAxisUnit)) - { - $columnNameToUnit[$columnName] = $this->yAxisUnit; - } - // otherwise we guess the unit from the column name - else - { - foreach($nameToUnit as $pattern => $type) - { - if(strpos($columnName, $pattern) !== false) - { - $columnNameToUnit[$columnName] = $type; - break; - } - } - } + $unit = $this->guessUnitFromRequestedColumnNames($requestedColumnNames); } + $this->view->setAxisXLabels($xLabels); - $this->view->setAxisYValues($columnNameToValueCleaned); - $this->view->setAxisYLabels($columnNameToTranslation); - $this->view->setAxisYUnits($columnNameToUnit); + $this->view->setAxisYValues($yAxisLabelToValueCleaned); + $this->view->setAxisYLabels($yAxisLabels); + $this->view->setAxisYUnit($unit); $firstDatatable = reset($this->dataTable->metadata); $period = $firstDatatable['period']; @@ -134,14 +141,14 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat $period = $metadataDataTable['period']; $dateInUrl = $period->getDateStart(); $link = Piwik_Url::getCurrentUrlWithoutQueryString() . - Piwik_Url::getCurrentQueryStringWithParametersModified( array( - 'date' => $dateInUrl, + '?' . + Piwik_Url::getQueryStringFromParameters( array( 'module' => 'CoreHome', 'action' => 'index', - 'viewDataTable' => null, // we reset the viewDataTable parameter (useless in the link) - 'idGoal' => null, // we reset idGoal - 'columns' => null, - )); + 'idSite' => Piwik_Common::getRequestVar('idSite'), + 'period' => $period->getLabel(), + 'date' => $dateInUrl, + )); $axisXOnClick[] = $link; } $this->view->setAxisXOnClick($axisXOnClick); diff --git a/core/ViewDataTable/GenerateGraphHTML.php b/core/ViewDataTable/GenerateGraphHTML.php index 0523531a82..445824f98e 100644 --- a/core/ViewDataTable/GenerateGraphHTML.php +++ b/core/ViewDataTable/GenerateGraphHTML.php @@ -38,6 +38,8 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable $this->disableOffsetInformation(); $this->disableExcludeLowPopulation(); $this->disableSearchBox(); + $this->enableShowExportAsImageIcon(); + $this->parametersToModify = array( 'viewDataTable' => $this->getViewDataTableIdToLoad(), // in the case this controller is being executed by another controller @@ -48,6 +50,11 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable ); } + public function enableShowExportAsImageIcon() + { + $this->viewProperties['show_export_as_image_icon'] = true; + } + /** * Sets parameters to modify in the future generated URL * @param array $array array('nameParameter' => $newValue, ...) @@ -58,6 +65,15 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable } /** + * We persist the parametersToModify values in the javascript footer. + * This is used by the "export links" that use the "date" attribute from the json properties array in the datatable footer. + */ + protected function getJavascriptVariablesToSet() + { + return $this->parametersToModify + parent::getJavascriptVariablesToSet(); + } + + /** * @see Piwik_ViewDataTable::main() */ public function main() @@ -76,61 +92,73 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable $view = new Piwik_View($this->dataTableTemplate); $this->uniqueIdViewDataTable = $this->getUniqueIdViewDataTable(); $view->graphType = $this->graphType; + $this->chartDivId = $this->uniqueIdViewDataTable . "Chart_swf"; $this->parametersToModify['action'] = $this->currentControllerAction; + $this->parametersToModify = array_merge($this->variablesDefault, $this->parametersToModify); + $url = Piwik_Url::getCurrentQueryStringWithParametersModified($this->parametersToModify); $view->jsInvocationTag = $this->getFlashInvocationCode($url); $view->urlGraphData = $url; - + $view->chartDivId = $this->chartDivId; $view->formEmbedId = "formEmbed".$this->uniqueIdViewDataTable; - $view->graphCodeEmbed = $this->graphCodeEmbed; - $view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet(); $view->properties = $this->getViewProperties(); return $view; } - protected function getFlashInvocationCode( $url = 'libs/open-flash-chart/data-files/nodata.txt', $use_swfobject = true ) + protected function getFlashInvocationCode( $url = 'libs/open-flash-chart/data-files/nodata.txt' ) { $width = $this->width; $height = $this->height; - $libPathInPiwik = 'libs/open-flash-chart/'; $currentPath = Piwik_Url::getCurrentUrlWithoutFileName(); - $pathToLibraryOpenChart = $currentPath . $libPathInPiwik; + $pathToLibraryOpenChart = $currentPath . 'libs/open-flash-chart/'; + $pathToLibrarySwfObject = $currentPath . 'libs/swfobject/'; $url = Piwik_Url::getCurrentUrlWithoutQueryString() . $url; // escape the & and stuff: $url = urlencode($url); - $obj_id = $this->uniqueIdViewDataTable . "Chart"; - $div_name = $this->uniqueIdViewDataTable . "FlashContent"; - $return = ''; - if( $use_swfobject ) - { - // Using library for auto-enabling Flash object on IE, disabled-Javascript proof - $return .= ' -<div id="'. $div_name .'"><div id="'. $obj_id .'_swf"><noscript>'; - } - $urlGraph = $pathToLibraryOpenChart."open-flash-chart.swf?data=" . $url; - - // when the object/embed is changed, see also widgetize.js; it may require a logic update - $this->graphCodeEmbed .= '<div><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="' . $width . '" height="' . $height . '" id="'. $obj_id .'" > -<param name="movie" value="'.$urlGraph.'" /> -<param name="wmode" value="opaque" /> -<param name="allowScriptAccess" value="sameDomain" /> -<embed src="'.$urlGraph.'" wmode="opaque" allowScriptAccess="sameDomain" quality="high" bgcolor="#FFFFFF" width="'. $width .'" height="'. $height .'" name="open-flash-chart" type="application/x-shockwave-flash" id="'. $obj_id .'" /> -</object></div>'; - $return .= $this->graphCodeEmbed; - if( $use_swfobject ) - { - $return .= ' -</noscript></div></div> -<script type="text/javascript"> -swfobject.embedSWF("'.$pathToLibraryOpenChart.'open-flash-chart.swf", "'. $obj_id .'_swf", "'. $width . '", "' . $height . '", "9.0.0", false, {"data-file":"'.$url.'"}, {"allowScriptAccess":"sameDomain","wmode":"opaque"}, {"bgcolor":"#FFFFFF"}); -</script>'; - } + $requiredFlashVersion = "9.0.0"; + // - Export as Image feature from Open Flash Chart + // - Using library for auto-enabling Flash object on IE, disabled-Javascript proof + $return = ' + <div id="'. $this->chartDivId .'">Displaying Graphs in Piwik requires Flash >= '.$requiredFlashVersion.'. <a target="_blank" href="misc/redirectToUrl.php?url=http://piwik.org/faq/troubleshooting/#faq_53">More information about displaying graphs in Piwik.</a></div> + <script type="text/javascript"> + OFC = {}; + OFC.jquery = { + name: "jQuery", + rasterize: function (src, dst) { $("#"+ dst).replaceWith(Control.OFC.image(src)) }, + image: function(src) { return "<img title=\'Piwik Graph\' src=\'data:image/png;base64," + $("#"+src)[0].get_img_binary() + "\' />"}, + popup: function(src) { + var img_win = window.open("", "Charts: Export as Image") + with(img_win.document) { + write("<html><head><title>'.Piwik_Translate('General_ExportAsImage').'<\/title><\/head><body>" + Control.OFC.image(src) + "<br><br><p>'.htmlentities(Piwik_Translate('General_SaveImageOnYourComputer')).'</p><\/body><\/html>") } + } + } + if (typeof(Control == "undefined")) {var Control = {OFC: OFC.jquery}} + // By default, right-clicking on OFC and choosing "save image locally" calls this function. + function save_image() { OFC.jquery.popup("'.$this->chartDivId.'") } + + swfobject.embedSWF( + "'.$pathToLibraryOpenChart.'open-flash-chart.swf", + "'. $this->chartDivId .'", + "'. $width . '", "' . $height . '", + "'.$requiredFlashVersion.'", + "'.$pathToLibrarySwfObject.'expressInstall.swf", + { + "data-file":"'.$url.'", + "loading":"'.htmlspecialchars(Piwik_Translate('General_Loading')).'" + }, + { + "allowScriptAccess":"sameDomain", + "wmode":"opaque" + }, + {"bgcolor":"#FFFFFF"} + ); + </script>'; return $return; } } diff --git a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php index 77082e99f9..8729a452f4 100644 --- a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php +++ b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php @@ -35,7 +35,8 @@ class Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution extends Piwik_ViewDat $apiMethodToRequestDataTable ); $this->setParametersToModify(array('date' => Piwik_Common::getRequestVar('date', 'last30', 'string'))); - $this->disableFooter(); + $this->disableShowAllViewsIcons(); + $this->disableShowTable(); } /** @@ -46,6 +47,10 @@ class Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution extends Piwik_ViewDat */ public function setColumnsToDisplay( $columnsNames) { + if(!is_array($columnsNames)) + { + $columnsNames = array($columnsNames); + } $this->setParametersToModify( array('columns' => $columnsNames) ); } } diff --git a/core/ViewDataTable/HtmlTable.php b/core/ViewDataTable/HtmlTable.php index cfd079da48..f3dab41d5f 100644 --- a/core/ViewDataTable/HtmlTable.php +++ b/core/ViewDataTable/HtmlTable.php @@ -48,7 +48,8 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable $controllerActionCalledWhenRequestSubTable); $this->dataTableTemplate = 'CoreHome/templates/datatable.tpl'; $this->variablesDefault['enable_sort'] = '1'; - + $this->setSortedColumn('nb_visits', 'desc'); + $this->setLimit(Zend_Registry::get('config')->General->datatable_default_limit); $this->handleLowPopulation(); } diff --git a/core/ViewDataTable/Sparkline.php b/core/ViewDataTable/Sparkline.php index 4a2d0c1514..3ada3c5fbe 100644 --- a/core/ViewDataTable/Sparkline.php +++ b/core/ViewDataTable/Sparkline.php @@ -34,7 +34,6 @@ class Piwik_ViewDataTable_Sparkline extends Piwik_ViewDataTable } $this->mainAlreadyExecuted = true; - $this->disableGenericFilters(); $this->loadDataTableFromAPI(); $this->isDataAvailable = $this->dataTable->getRowsCount() != 0; diff --git a/core/Visualization/Chart.php b/core/Visualization/Chart.php index 9a1ca5ebc2..f51e308519 100644 --- a/core/Visualization/Chart.php +++ b/core/Visualization/Chart.php @@ -29,7 +29,11 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView protected $yLabels = array(); protected $yValues = array(); - protected $yUnits = array(); + protected $yUnit = ''; + + protected $maxValue; + protected $minValue; + protected $displayPercentageInTooltip = true; function __construct() { @@ -51,9 +55,12 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView $this->yValues = $values; } - function setAxisYUnits($yUnits) + function setAxisYUnit($yUnit) { - $this->yUnits = $yUnits; + if(!empty($yUnit)) + { + $this->yUnit = $yUnit; + } } public function setAxisYLabels($labels) @@ -61,6 +68,11 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView $this->yLabels = $labels; } + public function setDisplayPercentageInTooltip($bool) + { + $this->displayPercentageInTooltip = $bool; + } + //TODO call + make sure matches beginning of period? (hard..) // day -> every 7 days @@ -115,7 +127,7 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView return $this->chart->toPrettyString(); } - function customizeGraph() + function customizeChartProperties() { $this->chart->set_number_format($num_decimals = 0, $is_fixed_num_decimals_forced = true, @@ -124,8 +136,8 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView $gridColour = '#E0E1E4'; $countValues = count($this->xLabels); - $maxValue = $this->getMaxValue(); - $minValue = 0; + $this->maxValue = $this->getMaxValue(); + $this->minValue = 0; // X Axis $this->x = new x_axis(); @@ -154,21 +166,17 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView $this->y->set_colour('#ffffff'); $this->y->set_grid_colour($gridColour); $stepsCount = 2; - $stepsEveryNLabel = ceil(($maxValue - $minValue) / $stepsCount); - if($maxValue == 0) + $stepsEveryNLabel = ceil(($this->maxValue - $this->minValue) / $stepsCount); + if($this->maxValue == 0) { - $maxValue = 1; + $this->maxValue = 1; } - $this->y->set_range( $minValue, $maxValue, $stepsEveryNLabel); + $this->y->set_range( $this->minValue, $this->maxValue, $stepsEveryNLabel); $dataSetsToDisplay = $this->getDataSetsToDisplay(); if($dataSetsToDisplay != false) { $dataSetToDisplay = current($dataSetsToDisplay); - if(isset($this->yUnits[$dataSetToDisplay])) - { - $unit = $this->yUnits[$dataSetToDisplay]; - $this->y->set_label_text("#val#$unit"); - } + $this->y->set_label_text("#val#".$this->yUnit); } // Tooltip diff --git a/core/Visualization/Chart/Evolution.php b/core/Visualization/Chart/Evolution.php index 314acbffd9..3b28fa3d4c 100644 --- a/core/Visualization/Chart/Evolution.php +++ b/core/Visualization/Chart/Evolution.php @@ -18,9 +18,9 @@ require_once "Visualization/Chart.php"; */ class Piwik_Visualization_Chart_Evolution extends Piwik_Visualization_Chart { - function customizeGraph() + function customizeChartProperties() { - parent::customizeGraph(); + parent::customizeChartProperties(); $dataSetsToDisplay = $this->getDataSetsToDisplay(); if($dataSetsToDisplay === false) { @@ -61,18 +61,14 @@ class Piwik_Visualization_Chart_Evolution extends Piwik_Visualization_Chart $lineValues = array(); $j = 0; foreach($this->xLabels as $label) { - $value = $yValues[$j]; + $value = (float)$yValues[$j]; $lineValue = new hollow_dot($value); - $unit = ''; - if(!empty($this->yUnits[$dataSetToDisplay])) - { - $unit = $this->yUnits[$dataSetToDisplay]; - } + $unit = $this->yUnit; $lineValue->tooltip("$label<br>$value$unit $labelName"); if(!empty($this->xOnClick)) { - $lineValue->on_click('redirectToUrl("'.$this->xOnClick[$j].'")'); + $lineValue->on_click('piwikHelper.redirectToUrl("'.$this->xOnClick[$j].'")'); } $lineValues[] = $lineValue; $j++; @@ -87,8 +83,8 @@ class Piwik_Visualization_Chart_Evolution extends Piwik_Visualization_Chart } // if one column is a percentage we set the grid accordingly // note: it is invalid to plot a percentage dataset along with a numeric dataset - //TODO only if the max was 100!! - if(array_search('%', $this->yUnits) !== false) + if($this->yUnit == '%' + && $this->maxValue > 90) { $this->y->set_range( 0, 100, 50); } diff --git a/core/Visualization/Chart/Pie.php b/core/Visualization/Chart/Pie.php index 12effb7f6c..542770e6f4 100644 --- a/core/Visualization/Chart/Pie.php +++ b/core/Visualization/Chart/Pie.php @@ -28,9 +28,9 @@ class Piwik_Visualization_Chart_Pie extends Piwik_Visualization_Chart return array_slice($dataSetsToDisplay, 0, 1); } - function customizeGraph() + function customizeChartProperties() { - parent::customizeGraph(); + parent::customizeChartProperties(); $dataSetsToDisplay = $this->getDataSetsToDisplay(); if($dataSetsToDisplay === false) { @@ -49,12 +49,12 @@ class Piwik_Visualization_Chart_Pie extends Piwik_Visualization_Chart // create the Pie values $yValues = $this->yValues[$dataSetToDisplay]; $labelName = $this->yLabels[$dataSetToDisplay]; - $unit = @$this->yUnits[$dataSetToDisplay]; + $unit = $this->yUnit; $sum = array_sum($yValues); $pieValues = array(); $i = 0; foreach($this->xLabels as $label) { - $value = $yValues[$i]; + $value = (float)$yValues[$i]; $i++; // we never plot empty pie slices (eg. visits by server time pie chart) if($value <= 0) { diff --git a/core/Visualization/Chart/VerticalBar.php b/core/Visualization/Chart/VerticalBar.php index c9794f4f00..5dbd954bac 100644 --- a/core/Visualization/Chart/VerticalBar.php +++ b/core/Visualization/Chart/VerticalBar.php @@ -29,9 +29,9 @@ class Piwik_Visualization_Chart_VerticalBar extends Piwik_Visualization_Chart return array_slice($dataSetsToDisplay, 0, 1); } - function customizeGraph() + function customizeChartProperties() { - parent::customizeGraph(); + parent::customizeChartProperties(); $dataSetsToDisplay = $this->getDataSetsToDisplay(); if($dataSetsToDisplay === false) { @@ -52,13 +52,21 @@ class Piwik_Visualization_Chart_VerticalBar extends Piwik_Visualization_Chart // create the bar values $yValues = $this->yValues[$dataSetToDisplay]; $labelName = $this->yLabels[$dataSetToDisplay]; - $unit = @$this->yUnits[$dataSetToDisplay]; + $unit = $this->yUnit; $barValues = array(); $i = 0; + $sum = array_sum($yValues); foreach($this->xLabels as $label) { - $value = $yValues[$i]; + $value = (float)$yValues[$i]; + + $displayPercentage = ''; + if($this->displayPercentageInTooltip) + { + $percentage = round(100 * $value / $sum); + $displayPercentage = "($percentage%)"; + } $barValue = new bar_value($value); - $barValue->set_tooltip("$label<br>$value$unit $labelName"); + $barValue->set_tooltip("$label<br>$value$unit $labelName $displayPercentage"); $barValues[] = $barValue; $i++; } diff --git a/core/Visualization/Cloud.php b/core/Visualization/Cloud.php index 287c57d86c..b3d6d26719 100644 --- a/core/Visualization/Cloud.php +++ b/core/Visualization/Cloud.php @@ -44,6 +44,9 @@ class Piwik_Visualization_Cloud { $this->shuffleCloud(); $return = array(); + if(empty($this->wordsArray)) { + return array(); + } $maxValue = max($this->wordsArray); foreach ($this->wordsArray as $word => $popularity) { diff --git a/core/Visualization/Sparkline.php b/core/Visualization/Sparkline.php index 5dba26696a..369f0b3e6c 100644 --- a/core/Visualization/Sparkline.php +++ b/core/Visualization/Sparkline.php @@ -69,7 +69,7 @@ class Piwik_Visualization_Sparkline implements Piwik_iView $i++; } $sparkline->SetYMin(0); - $sparkline->setYMax($max[1] + 1); // the +1 seems to be mandatory to not lose some pixels when value = max + $sparkline->setYMax($max[1] + 0.5); // the +0.5 seems to be mandatory to not lose some pixels when value = max $sparkline->SetPadding( 3, 0, 2, 0); $font = FONT_2; // the -0.5 is a hack as the sparkline samping rendering is obviously slightly bugged @@ -78,7 +78,9 @@ class Piwik_Visualization_Sparkline implements Piwik_iView $sparkline->SetFeaturePoint($max[0] -0.5, $max[1], 'green', 5); $sparkline->SetFeaturePoint($last[0] -0.5, $last[1], 'blue', 5); $sparkline->SetLineSize(3); // for renderresampled, linesize is on virtual image - $sparkline->RenderResampled($width, $height); + $ratio = 1; +// var_dump($min);var_dump($max);var_dump($lasts);exit; + $sparkline->RenderResampled($width*$ratio, $height*$ratio); $this->sparkline = $sparkline; } diff --git a/core/iView.php b/core/iView.php index 04c93c6600..6c21b1e94f 100644 --- a/core/iView.php +++ b/core/iView.php @@ -10,18 +10,13 @@ */ /** - * Piwik_ViewDataTable must create a $view attribute which implements this interface. - * * @package Piwik_Visualization */ interface Piwik_iView { /** * Outputs the data. - * Either outputs html, xml, an image, nothing, etc. - * - * @return mixed - * + * @return mixed (image, array, html...) */ function render(); } diff --git a/lang/en.php b/lang/en.php index 26e63e35ad..1f89a01aa2 100644 --- a/lang/en.php +++ b/lang/en.php @@ -26,6 +26,7 @@ $translations = array( 'General_Logout' => 'Sign out', 'General_Done' => 'Done', 'General_LoadingData' => 'Loading data...', + 'General_Loading' => 'Loading...', 'General_ErrorRequest' => 'Oops… problem during the request, please try again.', 'General_Next' => 'Next', 'General_Previous' => 'Previous', @@ -36,6 +37,8 @@ $translations = array( 'General_TagCloud' => 'Tag Cloud', 'General_VBarGraph' => 'Vertical bar graph', 'General_Export' => 'Export', + 'General_ExportAsImage' => 'Export as Image', + 'General_SaveImageOnYourComputer' => 'To save the image on your computer, right click on the image and select "Save Image As..."', 'General_Refresh' => 'Refresh the page', 'General_Visitors' => 'Visitors', 'General_ColumnNbUniqVisitors' => 'Unique visitors', diff --git a/libs/swfobject/expressInstall.swf b/libs/swfobject/expressInstall.swf Binary files differnew file mode 100644 index 0000000000..86958bf3a7 --- /dev/null +++ b/libs/swfobject/expressInstall.swf diff --git a/plugins/API/Controller.php b/plugins/API/Controller.php index 8eb442cca1..29c1d64cd1 100644 --- a/plugins/API/Controller.php +++ b/plugins/API/Controller.php @@ -20,6 +20,11 @@ class Piwik_API_Controller extends Piwik_Controller { function index() { + // when calling the API through http, we limit the number of returned results + if(!isset($_GET['filter_limit'])) + { + $_GET['filter_limit'] = Zend_Registry::get('config')->General->API_datatable_default_limit; + } $request = new Piwik_API_Request('token_auth='.Piwik_Common::getRequestVar('token_auth', 'anonymous', 'string')); echo $request->process(); } diff --git a/plugins/Actions/Controller.php b/plugins/Actions/Controller.php index b3b7e13d42..9240161877 100644 --- a/plugins/Actions/Controller.php +++ b/plugins/Actions/Controller.php @@ -108,7 +108,6 @@ class Piwik_Actions_Controller extends Piwik_Controller $view->setLimit( 100 ); $view->setColumnsToDisplay( array('label','nb_hits','nb_visits') ); - $view->setSortedColumn( 'nb_visits', 'desc' ); $view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnPageviews')); $view->setColumnTranslation('nb_visits', Piwik_Translate('General_ColumnUniquePageviews')); @@ -143,7 +142,6 @@ class Piwik_Actions_Controller extends Piwik_Controller $view->setColumnsToDisplay( array('label','nb_visits','nb_hits') ); $view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnDownloads')); $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueDownloads')); - $view->setSortedColumn( 'nb_visits','desc' ); $view->disableExcludeLowPopulation(); $view->setLimit( 15 ); } @@ -153,7 +151,6 @@ class Piwik_Actions_Controller extends Piwik_Controller $view->setColumnsToDisplay( array('label','nb_visits','nb_hits') ); $view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnClicks')); $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueClicks')); - $view->setSortedColumn( 'nb_visits','desc' ); $view->disableExcludeLowPopulation(); $view->setLimit( 15 ); } diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js index 9dae015f58..a19e99424c 100644 --- a/plugins/CoreHome/templates/datatable.js +++ b/plugins/CoreHome/templates/datatable.js @@ -114,7 +114,7 @@ dataTable.prototype = url: piwik.piwik_url + 'index.php', dataType: 'html', async: true, - error: ajaxHandleError, // Callback when the request fails + error: piwikHelper.ajaxHandleError, // Callback when the request fails success: callbackSuccess, // Callback when the request succeeds data: new Object }; @@ -178,7 +178,7 @@ dataTable.prototype = else { dataTableSel.html( $(content).html() ); - lazyScrollTo(dataTableSel[0], 400); + piwikHelper.lazyScrollTo(dataTableSel[0], 400); } }, @@ -486,7 +486,7 @@ dataTable.prototype = .click( function(){ // we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30 - // this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10 + // this value is stored in config file General->datatable_default_limit but this is more an edge case so ok to set it to 10 delete self.param.filter_limit; delete self.param.enable_filter_excludelowpop; self.param.viewDataTable = 'tableGoals'; @@ -499,7 +499,7 @@ dataTable.prototype = .click( function(){ // we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30 - // this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10 + // this value is stored in config file General->datatable_default_limit but this is more an edge case so ok to set it to 10 delete self.param.filter_limit; self.param.viewDataTable = self.param.viewDataTable == 'table' ? 'tableAllColumns' : 'table'; // when switching to display simple table, do not exclude low pop by default @@ -953,7 +953,7 @@ actionDataTable.prototype = var dataTableSel = $('#'+idToReplace); dataTableSel.html($(content).html()); - lazyScrollTo(dataTableSel[0], 400); + piwikHelper.lazyScrollTo(dataTableSel[0], 400); }, // Called when a set of rows for a category of actions is loaded diff --git a/plugins/CoreHome/templates/datatable_footer.tpl b/plugins/CoreHome/templates/datatable_footer.tpl index 6c3f3a0d06..0921b01523 100644 --- a/plugins/CoreHome/templates/datatable_footer.tpl +++ b/plugins/CoreHome/templates/datatable_footer.tpl @@ -20,32 +20,39 @@ <div> <span id="dataTableFooterIcons"> <span id="exportToFormat" style="display:none;padding-left:4px;"> + {if $properties.show_export_as_image_icon} + <span id="dataTableFooterExportAsImageIcon"> + <a href="javascript:OFC.jquery.popup('{$chartDivId}');"><img title="{'General_ExportAsImage'|translate}" src="{$piwikUrl}themes/default/images/image.png" /></a> + </span> + {/if} <img width="16" height="16" src="{$piwikUrl}themes/default/images/export.png" title="{'General_Export'|translate}" /> - <span id="linksExportToFormat" style="display:none;"> + <span id="linksExportToFormat" style="display:none"> <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="CSV" filter_limit="100">CSV</a> | <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="XML" filter_limit="100">XML</a> | <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="JSON" filter_limit="100">Json</a> | <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="PHP" filter_limit="100">Php</a> | <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="RSS" filter_limit="100" date="last10"><img border="0" src="{$piwikUrl}themes/default/images/feed.png"></a> </span> - {if $properties.show_all_views_icons} - <a class="viewDataTable" format="cloud"><img width="16" height="16" src="{$piwikUrl}themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a> - <a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="{$piwikUrl}themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a> - <a class="viewDataTable" format="graphPie"><img width="16" height="16" src="{$piwikUrl}themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a> - {/if} + {if $properties.show_all_views_icons} + <a class="viewDataTable" format="cloud"><img width="16" height="16" src="{$piwikUrl}themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a> + <a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="{$piwikUrl}themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a> + <a class="viewDataTable" format="graphPie"><img width="16" height="16" src="{$piwikUrl}themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a> + {/if} </span> <span id="dataTableFooterIconsShow" style="display:none;padding-left:4px;"> <img src="{$piwikUrl}plugins/CoreHome/templates/images/more.png" /> </span> - {if $properties.show_table_all_columns} + + {if $properties.show_table} <span id="tableAllColumnsSwitch" style="display:none;float:right;padding-right:4px;border-right:1px solid #82A1D2;"> {if $javascriptVariablesToSet.viewDataTable != 'table'} <img title="{'General_DisplayNormalTable'|translate}" src="{$piwikUrl}themes/default/images/table.png" /> - {else} + {elseif $properties.show_table_all_columns} <img title="{'General_DisplayMoreData'|translate}" src="{$piwikUrl}themes/default/images/table_more.png" /> {/if} </span> {/if} + {if $properties.show_goals} <span id="tableGoals" style="display:none;float:right;padding-right:4px;"> {if $javascriptVariablesToSet.viewDataTable != 'tableGoals'} diff --git a/plugins/CoreHome/templates/graph.tpl b/plugins/CoreHome/templates/graph.tpl index 097090bc78..b0f827dcaf 100644 --- a/plugins/CoreHome/templates/graph.tpl +++ b/plugins/CoreHome/templates/graph.tpl @@ -1,7 +1,6 @@ <div id="{$properties.uniqueId}"> <div class="{if $graphType=='evolution'}dataTableGraphEvolutionWrapper{else}dataTableGraphWrapper{/if}"> {$jsInvocationTag} - {if $properties.show_footer} {include file="CoreHome/templates/datatable_footer.tpl"} {include file="CoreHome/templates/datatable_js.tpl"} diff --git a/plugins/CoreHome/templates/menu.js b/plugins/CoreHome/templates/menu.js index 5f0603c55f..9c4e00800d 100644 --- a/plugins/CoreHome/templates/menu.js +++ b/plugins/CoreHome/templates/menu.js @@ -18,7 +18,7 @@ menu.prototype = customAjaxHandleError: function () { menu.prototype.lastUrlRequested = null; - ajaxHandleError(); + piwikHelper.ajaxHandleError(); }, overMainLI: function () diff --git a/plugins/CoreHome/templates/sparkline.js b/plugins/CoreHome/templates/sparkline.js index 5753235977..1d7712516e 100644 --- a/plugins/CoreHome/templates/sparkline.js +++ b/plugins/CoreHome/templates/sparkline.js @@ -15,8 +15,8 @@ $(document).ready( function(){ //on click, reload the graph with the new url $(this).click( function() { //get the main page graph and reload with new data - findSWFGraph(graph.attr('graphId')+"Chart_swf").reload(url); - lazyScrollTo(graph[0], 400); + piwikHelper.findSWFGraph(graph.attr('graphId')+"Chart_swf").reload(url); + piwikHelper.lazyScrollTo(graph[0], 400); }); $(this).hover( function() { diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php index 613028b2a3..4d08d03bb4 100644 --- a/plugins/CoreUpdater/Controller.php +++ b/plugins/CoreUpdater/Controller.php @@ -1,14 +1,10 @@ <?php -require_once "Updater.php"; -require_once "Version.php"; - class Piwik_CoreUpdater_Controller extends Piwik_Controller { const CONFIG_FILE_BACKUP = '/config/global.ini.auto-backup-before-update.php'; const PATH_TO_EXTRACT_LATEST_VERSION = '/tmp/latest'; const LATEST_PIWIK_URL = 'http://piwik.org/latest.zip'; - private $componentsWithUpdateFile = array(); private $coreError = false; private $warningMessages = array(); private $errorMessages = array(); @@ -59,26 +55,6 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller $view->feedbackMessages = $messages; echo $view->render(); } - - public function checkForCoreAndPluginsUpdates() - { - $this->updater = new Piwik_Updater(); - $this->updater->addComponentToCheck('core', Piwik_Version::VERSION); - - $plugins = Piwik_PluginsManager::getInstance()->getInstalledPlugins(); - foreach($plugins as $pluginName => $plugin) - { - $this->updater->addComponentToCheck($pluginName, $plugin->getVersion()); - } - - $this->componentsWithUpdateFile = $this->updater->getComponentsWithUpdateFile(); - if(count($this->componentsWithUpdateFile) == 0) - { - return; - } - - $this->runUpdaterAndExit(); - } private function checkNewVersionIsAvailableOrDie() { @@ -152,20 +128,20 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller { } - private function runUpdaterAndExit() + private function runUpdaterAndExit($componentsWithUpdateFile) { if(Piwik_Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1) { - $this->doExecuteUpdates(); + $this->doExecuteUpdates($componentsWithUpdateFile); } else { - $this->doWelcomeUpdates(); + $this->doWelcomeUpdates($componentsWithUpdateFile); } exit; } - private function doWelcomeUpdates() + private function doWelcomeUpdates($componentsWithUpdateFile) { $view = new Piwik_View('CoreUpdater/templates/update_welcome.tpl'); $view->new_piwik_version = Piwik_Version::VERSION; @@ -178,7 +154,7 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller $pluginNamesToUpdate = array(); $coreToUpdate = false; - foreach($this->componentsWithUpdateFile as $name => $filenames) + foreach($componentsWithUpdateFile as $name => $filenames) { if($name == 'core') { @@ -195,9 +171,9 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller echo $view->render(); } - private function doExecuteUpdates() + private function doExecuteUpdates($componentsWithUpdateFile) { - $this->loadAndExecuteUpdateFiles(); + $this->loadAndExecuteUpdateFiles($componentsWithUpdateFile); $view = new Piwik_View('CoreUpdater/templates/update_database_done.tpl'); $view->coreError = $this->coreError; @@ -213,7 +189,7 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller // if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE // if warning in any core update or in any plugins update, show message + CONTINUE // if no error or warning, success message + CONTINUE - foreach($this->componentsWithUpdateFile as $name => $filenames) + foreach($componentsWithUpdateFile as $name => $filenames) { try { $this->warningMessages = array_merge($this->warningMessages, $this->updater->update($name)); diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php index f270efaf0d..0ee2d6f8c0 100644 --- a/plugins/Dashboard/Controller.php +++ b/plugins/Dashboard/Controller.php @@ -24,7 +24,8 @@ class Piwik_Dashboard_Controller extends Piwik_Controller $layout = html_entity_decode($this->getLayout()); if(strstr($layout, '[[') == false) { $layout = "'$layout'"; - } + } + $view->layout = $layout; $view->availableWidgets = json_encode(Piwik_GetWidgetsList()); return $view; } diff --git a/plugins/Dashboard/templates/Dashboard.js b/plugins/Dashboard/templates/Dashboard.js index de12a8fcc6..c8c1aded31 100644 --- a/plugins/Dashboard/templates/Dashboard.js +++ b/plugins/Dashboard/templates/Dashboard.js @@ -221,7 +221,7 @@ dashboard.prototype = url: 'index.php', dataType: 'html', async: true, - error: ajaxHandleError, + error: piwikHelper.ajaxHandleError, data: { "module": "Dashboard", "action": "saveLayout", "layout": layoutString diff --git a/plugins/Dashboard/templates/index.tpl b/plugins/Dashboard/templates/index.tpl index 0b2f8d044a..faf0a11323 100644 --- a/plugins/Dashboard/templates/index.tpl +++ b/plugins/Dashboard/templates/index.tpl @@ -25,7 +25,6 @@ ] ]; {/literal} - {* the old dashboard layout style is: piwik.dashboardLayout = 'VisitsSummary.getEvolutionGraph~VisitorInterest.getNumberOfVisitsPerVisitDuration~UserSettings.getBrowser~ExampleFeedburner.feedburner|Referers.getKeywords~Referers.getWebsites|Referers.getSearchEngines~VisitTime.getVisitInformationPerServerTime~ExampleRssWidget.rssPiwik|'; diff --git a/plugins/Dashboard/templates/widgetMenu.js b/plugins/Dashboard/templates/widgetMenu.js index 701056be78..d6e4a8e4aa 100644 --- a/plugins/Dashboard/templates/widgetMenu.js +++ b/plugins/Dashboard/templates/widgetMenu.js @@ -48,7 +48,7 @@ widgetsHelper.getLoadWidgetAjaxRequest = function (widgetUniqueId, widgetParamet url: 'index.php', dataType: 'html', async: true, - error: ajaxHandleError, + error: piwikHelper.ajaxHandleError, success: onWidgetLoadedCallback, data: piwikHelper.getQueryStringFromParameters(widgetParameters) + "&idSite="+piwik.idSite+"&period="+piwik.period+"&date="+piwik.currentDateString }; diff --git a/plugins/ExampleUI/API.php b/plugins/ExampleUI/API.php index 97f0ad8100..688fe6a00f 100644 --- a/plugins/ExampleUI/API.php +++ b/plugins/ExampleUI/API.php @@ -54,8 +54,8 @@ class Piwik_ExampleUI_API function getTemperatures() { $xAxis = array( - '12AM', '1AM', '2AM', '3AM', '4AM', '5AM', '6AM', '7AM', '8AM', '9AM', '10AM', '11AM', - '12PM', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM', '7PM', '8PM', '9PM', '10PM', '11PM', + '0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', + '12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h', ); $temperatureValues = array_slice(range(50,90), 0, count($xAxis)); shuffle($temperatureValues); diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php index 92041a3fd5..ccf88bdaec 100644 --- a/plugins/ExampleUI/Controller.php +++ b/plugins/ExampleUI/Controller.php @@ -19,6 +19,7 @@ class Piwik_ExampleUI_Controller extends Piwik_Controller $view = Piwik_ViewDataTable::factory('table'); $view->init( $this->pluginName, __FUNCTION__, 'ExampleUI.getTemperatures' ); $view->setColumnTranslation('value', "Temperature in °C"); + $view->setSortedColumn('label', 'asc'); $view->setGraphLimit( 24 ); $view->setLimit( 24 ); $view->disableExcludeLowPopulation(); @@ -90,7 +91,7 @@ class Piwik_ExampleUI_Controller extends Piwik_Controller { $view = Piwik_ViewDataTable::factory('cloud'); $view->init( $this->pluginName, __FUNCTION__, 'ExampleUI.getPlanetRatiosWithLogos' ); - $view->displayLogoInTagCloud(); + $view->setDisplayLogoInTagCloud(true); $view->disableFooterExceptExportIcons(); $view->setColumnsToDisplay( array('label','value') ); $view->setColumnTranslation('value', "times the diameter of Earth"); @@ -118,8 +119,17 @@ class Piwik_ExampleUI_Controller extends Piwik_Controller $this->renderView($view); } - function sparklinesWithEvolutionGraph() + function misc() { - + echo "<h2>Evolution graph filtered to Google and Yahoo!</h2>"; + $this->echoDataTableSearchEnginesFiltered(); } + + function echoDataTableSearchEnginesFiltered() + { + $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Referers.getSearchEngines'); + $view->setColumnsToDisplay( 'nb_visits' ); + $view->setSearchPattern('^(Google|Yahoo!)$', 'label'); + return $this->renderView($view); + } }
\ No newline at end of file diff --git a/plugins/ExampleUI/ExampleUI.php b/plugins/ExampleUI/ExampleUI.php index 8ef1e8e15f..4f36f55782 100644 --- a/plugins/ExampleUI/ExampleUI.php +++ b/plugins/ExampleUI/ExampleUI.php @@ -50,7 +50,7 @@ class Piwik_ExampleUI extends Piwik_Plugin 'Pie graph' => 'pieGraph', 'Tag clouds' => 'tagClouds', 'Sparklines' => 'sparklines', - 'Sparklines with evolution graph' => 'sparklinesWithEvolutionGraph', + 'Misc' => 'misc', ); foreach($menus as $subMenu => $action) { diff --git a/plugins/Goals/templates/GoalForm.js b/plugins/Goals/templates/GoalForm.js index a3f82154c5..48240a561f 100644 --- a/plugins/Goals/templates/GoalForm.js +++ b/plugins/Goals/templates/GoalForm.js @@ -84,8 +84,8 @@ function bindListGoalEdit() } function getAjaxDeleteGoal(idGoal) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; parameters.idSite = piwik.idSite; @@ -100,8 +100,8 @@ function getAjaxDeleteGoal(idGoal) function getAjaxAddGoal() { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; diff --git a/plugins/Referers/Controller.php b/plugins/Referers/Controller.php index ed120e09e4..6690f6ca36 100644 --- a/plugins/Referers/Controller.php +++ b/plugins/Referers/Controller.php @@ -178,20 +178,6 @@ class Piwik_Referers_Controller extends Piwik_Controller return $this->renderView($view, $fetch); } - - // TODO FIXME WITH NEW API - // example of how to show evolution of a given column over multiple days - public function getSearchEnginesEvolution($fetch = false) - { - $view = Piwik_ViewDataTable::factory('graphEvolution'); - $view->init( $this->pluginName, __FUNCTION__, 'Referers.getSearchEngines' ); - - $view->setColumnsToDisplay( 'nb_visits' ); - $view->setExactPattern( array('Google','Yahoo!'), 'label'); - - return $this->renderView($view, $fetch); - } - protected function getReferersVisitorsByType() { // we disable the queued filters because here we want to get the visits coming from search engines diff --git a/plugins/Referers/Referers.php b/plugins/Referers/Referers.php index 8bf6446d0f..4c16fe7bf0 100644 --- a/plugins/Referers/Referers.php +++ b/plugins/Referers/Referers.php @@ -64,7 +64,6 @@ class Piwik_Referers extends Piwik_Plugin Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuSearchEngines', array('module' => 'Referers', 'action' => 'getSearchEnginesAndKeywords')); Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuWebsites', array('module' => 'Referers', 'action' => 'getWebsites')); Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuCampaigns', array('module' => 'Referers', 'action' => 'getCampaigns')); - //Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuEvolution', array('module' => 'Referers', 'action' => 'getSearchEnginesEvolution')); } function archivePeriod( $notification ) diff --git a/plugins/SitesManager/templates/SitesManager.js b/plugins/SitesManager/templates/SitesManager.js index e21e7a2e2d..172340b9b3 100644 --- a/plugins/SitesManager/templates/SitesManager.js +++ b/plugins/SitesManager/templates/SitesManager.js @@ -1,7 +1,7 @@ function getDeleteSiteAJAX( idSite ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; parameters.module = 'API'; @@ -17,8 +17,8 @@ function getDeleteSiteAJAX( idSite ) function getAddSiteAJAX( row ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; var siteName = $(row).find('input[@id=siteadd_name]').val(); @@ -41,8 +41,8 @@ function getAddSiteAJAX( row ) function getUpdateSiteAJAX( row ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var siteName = $(row).find('input[@id=siteName]').val(); var idSite = $(row).children('#idSite').html(); @@ -65,7 +65,7 @@ function getUpdateSiteAJAX( row ) $(document).ready( function() { $('.addRowSite').click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); $(this).toggle(); var numberOfRows = $('table#editSites')[0].rows.length; @@ -82,13 +82,13 @@ $(document).ready( function() { ; $('#'+newRowId).keypress( submitSiteOnEnter ); $('.addsite').click( function(){ $.ajax( getAddSiteAJAX($('tr#'+newRowId)) ); } ); - $('.cancel').click(function() { ajaxHideError(); $(this).parents('tr').remove(); $('.addRowSite').toggle(); }); + $('.cancel').click(function() { piwikHelper.ajaxHideError(); $(this).parents('tr').remove(); $('.addRowSite').toggle(); }); } ); // when click on deleteuser, the we ask for confirmation and then delete the user $('.deleteSite').click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); var idRow = $(this).attr('id'); var nameToDelete = $(this).parent().parent().find('#siteName').html(); var idsiteToDelete = $(this).parent().parent().find('#idSite').html(); @@ -101,7 +101,7 @@ $(document).ready( function() { var alreadyEdited = new Array; $('.editSite') .click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); var idRow = $(this).attr('id'); if(alreadyEdited[idRow]==1) return; alreadyEdited[idRow] = 1; diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php index a7fadc8b17..ad6b406323 100644 --- a/plugins/UserCountry/Controller.php +++ b/plugins/UserCountry/Controller.php @@ -59,6 +59,7 @@ class Piwik_UserCountry_Controller extends Piwik_Controller function getLastDistinctCountriesGraph( $fetch = false ) { $view = $this->getLastUnitGraph('UserCountry',__FUNCTION__, "UserCountry.getNumberOfDistinctCountries"); + $view->setColumnsToDisplay('UserCountry_distinctCountries'); return $this->renderView($view, $fetch); } } diff --git a/plugins/UserCountry/templates/index.tpl b/plugins/UserCountry/templates/index.tpl index efea18c986..da9b84f503 100644 --- a/plugins/UserCountry/templates/index.tpl +++ b/plugins/UserCountry/templates/index.tpl @@ -8,7 +8,9 @@ <h2>{'UserCountry_Continent'|translate}</h2> {$dataTableContinent} -<p>{sparkline src=$urlSparklineCountries}<span> -{'UserCountry_DistinctCountries'|translate:"<strong>$numberDistinctCountries</strong>"} </span></p> +<div class="sparkline"> + {sparkline src=$urlSparklineCountries} + {'UserCountry_DistinctCountries'|translate:"<strong>$numberDistinctCountries</strong>"} +</div> {postEvent name="template_footerUserCountry"} diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php index f8306b39d0..eda8b076ba 100644 --- a/plugins/UserSettings/Controller.php +++ b/plugins/UserSettings/Controller.php @@ -85,12 +85,10 @@ class Piwik_UserSettings_Controller extends Piwik_Controller $view->disableSort(); $view->disableOffsetInformation(); $view->disableShowAllColumns(); - + $view->disallowPercentageInGraphTooltip(); $view->setColumnsToDisplay( array('label','nb_visits') ); - $view->setSortedColumn( 'nb_visits' ); $view->setGraphLimit( 10 ); $view->setLimit( 10 ); - return $this->renderView($view, $fetch); } diff --git a/plugins/UsersManager/templates/UsersManager.js b/plugins/UsersManager/templates/UsersManager.js index 5dc9fa9ca2..62cb090baa 100644 --- a/plugins/UsersManager/templates/UsersManager.js +++ b/plugins/UsersManager/templates/UsersManager.js @@ -1,7 +1,7 @@ function getUpdateUserAJAX( row ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; parameters.module = 'API'; @@ -21,8 +21,8 @@ function getUpdateUserAJAX( row ) function getDeleteUserAJAX( login ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; parameters.module = 'API'; @@ -38,8 +38,8 @@ function getDeleteUserAJAX( login ) function getAddUserAJAX( row ) { - var ajaxRequest = getStandardAjaxConf(); - toggleAjaxLoading(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); + piwikHelper.toggleAjaxLoading(); var parameters = new Object; parameters.module = 'API'; @@ -63,7 +63,7 @@ function getIdSites() function getUpdateUserAccess(login, access, successCallback) { - var ajaxRequest = getStandardAjaxConf(); + var ajaxRequest = piwikHelper.getStandardAjaxConf(); ajaxRequest.success = successCallback; ajaxRequest.async = false; @@ -113,12 +113,12 @@ function bindUpdateAccess() // if the permission couldn't be granted if(response.result == "error") { - ajaxShowError(response.message); + piwikHelper.ajaxShowError(response.message); } // if the permission change was successful else { - ajaxHideError(); + piwikHelper.ajaxHideError(); $(self).parent().parent().find('.accessGranted') .attr("src","plugins/UsersManager/images/no-access.png" ) @@ -163,7 +163,7 @@ $(document).ready( function() { // when click on edituser, the cells become editable $('.edituser') .click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); var idRow = $(this).attr('id'); if(alreadyEdited[idRow]==1) return; alreadyEdited[idRow] = 1; @@ -197,7 +197,7 @@ $(document).ready( function() { // when click on deleteuser, the we ask for confirmation and then delete the user $('.deleteuser') .click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); var idRow = $(this).attr('id'); var loginToDelete = $(this).parent().parent().find('#userLogin').html(); if( confirm(sprintf(_pk_translate('UsersManager_DeleteConfirm_js'),'"'+loginToDelete+'"')) ) @@ -208,7 +208,7 @@ $(document).ready( function() { ); $('.addrow').click( function() { - ajaxHideError(); + piwikHelper.ajaxHideError(); $(this).toggle(); var numberOfRows = $('table#users')[0].rows.length; @@ -228,7 +228,7 @@ $(document).ready( function() { ; $('#'+newRowId).keypress( submitOnEnter ); $('.adduser').click( function(){ $.ajax( getAddUserAJAX($('tr#'+newRowId)) ); } ); - $('.cancel').click(function() { ajaxHideError(); $(this).parents('tr').remove(); $('.addrow').toggle(); }); + $('.cancel').click(function() { piwikHelper.ajaxHideError(); $(this).parents('tr').remove(); $('.addrow').toggle(); }); }); $('.updateAccess') diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php index 48d43d97aa..ab648ada62 100644 --- a/plugins/VisitsSummary/Controller.php +++ b/plugins/VisitsSummary/Controller.php @@ -36,7 +36,7 @@ class Piwik_VisitsSummary_Controller extends Piwik_Controller "&format=original". // we disable filters for example "search for pattern", in the case this method is called // by a method that already calls the API with some generic filters applied - "&disable_generic_filters=true"; + "&disable_generic_filters=1"; $request = new Piwik_API_Request($requestString); return $request->process(); } @@ -45,7 +45,7 @@ class Piwik_VisitsSummary_Controller extends Piwik_Controller { $requestString = "method=VisitsSummary.getVisits". "&format=original". - "&disable_generic_filters=true"; + "&disable_generic_filters=1"; $request = new Piwik_API_Request($requestString); return $request->process(); } diff --git a/tests/core/DataTable/Filter/Pattern.test.php b/tests/core/DataTable/Filter/Pattern.test.php index 0bcf3db83b..71c902a754 100644 --- a/tests/core/DataTable/Filter/Pattern.test.php +++ b/tests/core/DataTable/Filter/Pattern.test.php @@ -25,45 +25,30 @@ class Test_Piwik_DataTable_Filter_Pattern extends UnitTestCase array( $idcol => array('label'=>'piwik')), array( $idcol => array('label'=>'yahoo')), array( $idcol => array('label'=>'amazon')), - array( $idcol => array('label'=>'238975247578949')), - array( $idcol => array('label'=>'Q*(%&*("$&%*(&"$*")"))'))); - + array( $idcol => array('label'=>'2389752/47578949')), + array( $idcol => array('label'=>'Q*(%&*("$&%*(&"$*")"))')) + ); $table->addRowsFromArray( $rows ); - - - $expectedtable = clone $table; - $expectedtable->deleteRows(array(1,2,4,5,6)); - - $filter = new Piwik_DataTable_Filter_Pattern($table, 'label', 'oo'); - - $this->assertEqual($table->getRows(), $expectedtable->getRows()); + $rowIds = array_keys($rows); + + $tests = array( + array('ask', array(1)), + array('oo', array(0,3)), + array('^yah', array(3)), + array('\*', array(6)), + array('2/4', array(5)), + array('amazon|yahoo', array(3,4)), + ); + + foreach($tests as $test) { + $pattern = $test[0]; + $expectedRows = $test[1]; + $rowToDelete = array_diff($rowIds, $expectedRows); + $expectedtable = clone $table; + $expectedtable->deleteRows($rowToDelete); + $filteredTable = clone $table; + $filteredTable->filter('Pattern', array('label', $pattern)); + $this->assertEqual($filteredTable->getRows(), $expectedtable->getRows(), "pattern search failed for pattern $pattern"); + } } - /** - * Test to filter a column with a pattern - */ - function test_filter_Pattern2() - { - $table = new Piwik_DataTable; - - $idcol = Piwik_DataTable_Row::COLUMNS; - - $rows = array( - array( $idcol => array('label'=>'google')), - array( $idcol => array('label'=>'ask')), - array( $idcol => array('label'=>'piwik')), - array( $idcol => array('label'=>'yahoo')), - array( $idcol => array('label'=>'amazon')), - array( $idcol => array('label'=>'238975247578949')), - array( $idcol => array('label'=>'Q*(%&*("$&%*(&"$*")"))'))); - - $table->addRowsFromArray( $rows ); - - - $expectedtable = clone $table; - $expectedtable->deleteRows(array(0,1,2,3,4,5)); - - $filter = new Piwik_DataTable_Filter_Pattern($table, 'label', '*'); - - $this->assertEqual($table->getRows(), $expectedtable->getRows()); - } -} +}
\ No newline at end of file diff --git a/themes/default/common.js b/themes/default/common.js index 29a16923dd..7135e3df3c 100644 --- a/themes/default/common.js +++ b/themes/default/common.js @@ -28,8 +28,7 @@ piwikHelper.getQueryStringFromParameters = function(parameters) return queryString.substring(0, queryString.length-1); } -//TODO all piwik global functions should be static of piwikHelper -function findSWFGraph(name) { +piwikHelper.findSWFGraph = function(name) { if (navigator.appName.indexOf("Microsoft")!= -1) { return window[name]; } else { @@ -37,10 +36,12 @@ function findSWFGraph(name) { } } -function redirectToUrl(url) { +piwikHelper.redirectToUrl = function(url) { + alert(url); window.location = url; } -function ajaxHandleError() + +piwikHelper.ajaxHandleError = function() { $('#loadingError').show(); setTimeout( function(){ @@ -48,55 +49,48 @@ function ajaxHandleError() }, 2000); } -function ajaxShowError( string ) +piwikHelper.ajaxShowError = function( string ) { $('#ajaxError').html(string).show(); } -function ajaxHideError() +piwikHelper.ajaxHideError = function() { $('#ajaxError').hide(); } -function ajaxHandleResponse(response) +piwikHelper.ajaxHandleResponse = function(response) { if(response.result == "error") { - ajaxShowError(response.message); + piwikHelper.ajaxShowError(response.message); } else { window.location.reload(); } - toggleAjaxLoading(); + piwikHelper.toggleAjaxLoading(); } -function toggleAjaxLoading() +piwikHelper.toggleAjaxLoading = function() { $('#ajaxLoading').toggle(); } -String.prototype.trim = function() { - return this.replace(/^\s+|\s+$/g,""); -} - -function getStandardAjaxConf() +piwikHelper.getStandardAjaxConf = function() { var ajaxRequest = new Object; - - //prepare the ajax request ajaxRequest.type = 'GET'; ajaxRequest.url = 'index.php'; ajaxRequest.dataType = 'json'; - ajaxRequest.error = ajaxHandleError; - ajaxRequest.success = ajaxHandleResponse; - + ajaxRequest.error = piwikHelper.ajaxHandleError; + ajaxRequest.success = piwikHelper.ajaxHandleResponse; return ajaxRequest; } -//scroll the window to the jquery element 'elem' if necessary -//time specify the duration of the animation in ms -function lazyScrollTo(elem, time) +// Scrolls the window to the jquery element 'elem' if necessary. +// "time" specifies the duration of the animation in ms +piwikHelper.lazyScrollTo = function(elem, time) { var elemTop = $(elem).offset().top; //only scroll the page if the graph is not visible @@ -107,3 +101,7 @@ function lazyScrollTo(elem, time) $.scrollTo(elem, time); } } + +String.prototype.trim = function() { + return this.replace(/^\s+|\s+$/g,""); +} diff --git a/themes/default/images/image.png b/themes/default/images/image.png Binary files differnew file mode 100644 index 0000000000..fbcdb8ea71 --- /dev/null +++ b/themes/default/images/image.png |