diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 1b02deccdeefbeb3684cea8a66b474e4376b326e..37ab59400ba020dc4683c0c222e93673e2d0cf0a 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -127,6 +127,8 @@ class Piwik_API_DocumentationGenerator 'languageCode' => 'fr', 'url' => 'http://forum.piwik.org/', + 'apiModule' => 'UserCountry', + 'apiAction' => 'getCountry' ); foreach($parametersToSet as $name => $value) diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index ae801c387ccb9794e9935d5301a2187f9fdf2c5f..7aeed06604bc11c62e13368cba5e8a7773f598fd 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -369,11 +369,18 @@ class Piwik_API_ResponseBuilder $key = str_replace(' ', '_', $key); $marginLeft = str_repeat("\t", $level + 1); if (is_array($value)) { - $xml.= $marginLeft . + if(empty($value)) + { + $xml .= $marginLeft . "<$key/>\n"; + } + else + { + $xml.= $marginLeft . "<$key>\n". $this->convertMultiDimensionalArrayToXml($value, $level + 1). "\n". $marginLeft . - "</$key>\n"; + "</$key>\n"; + } } else { $xml.= $marginLeft . "<$key>".$value."</$key>\n"; diff --git a/core/Controller.php b/core/Controller.php index 899b6e18ebb09509edab2902f0e9eae170ae6b84..3dba6730602d95958f47ced78aa3988edf5ddff7 100644 --- a/core/Controller.php +++ b/core/Controller.php @@ -301,10 +301,9 @@ abstract class Piwik_Controller try { $this->setPeriodVariablesView($view); - $periodString = Piwik_Common::getRequestVar('period'); - $date = Piwik_Date::factory($this->strDate); - $period = Piwik_Period::factory($periodString, $date); - $view->prettyDate = $period->getLocalizedLongString(); + + $date = Piwik_Date::factory($this->strDate); + $view->prettyDate = Piwik_Period::factory(Piwik_Common::getRequestVar('period'), $date)->getPrettyString(); $view->idSite = $this->idSite; if(is_null($this->site)) { diff --git a/plugins/API/API.php b/plugins/API/API.php index fab9f3ec13173f631a068363218b81f38f5e2ba5..eabe83e412fe6803368e4e3904553ba91e192351 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -158,7 +158,212 @@ class Piwik_API_API return $availableReports; } - + + public function getProcessedReport($idSite, $date, $period, $apiModule, $apiAction, $apiParameters = false) + { + if($apiParameters === false) + { + $apiParameters = array(); + } + // Is this report found in the Metadata available reports? + $reportMetadata = $this->getMetadata($idSite, $apiModule, $apiAction, $apiParameters); + if(!$reportMetadata) + { + throw new Exception("Requested report not found in the list of available reports. \n"); + } + + // Generate Api call URL passing custom parameters + $parameters = array_merge( $apiParameters, array( + 'method' => $apiModule.'.'.$apiAction, + 'idSite' => $idSite, + 'period' => $period, + 'date' => $date, + 'format' => 'original', + )); + $url = Piwik_Url::getQueryStringFromParameters($parameters); + $request = new Piwik_API_Request($url); + try { + /** @var Piwik_DataTable */ + $dataTable = $request->process(); + } catch(Exception $e) { + throw new Exception("API returned an error: ".$e->getMessage()."\n"); + } + + + // Table with a Dimension (Keywords, Pages, Browsers, etc.) + if(isset($reportMetadata['dimension'])) + { + $callback = 'handleTableReport'; + } + // Table without a dimension, simple list of general metrics (eg. VisitsSummary.get) + else + { + $callback = 'handleTableSimple'; + } + list($newReport, $columns, $rowsMetadata) = $this->$callback($idSite, $period, $dataTable, $reportMetadata); + foreach($columns as $columnId => &$name) + { + $name = ucfirst($name); + } + $website = new Piwik_Site($idSite); + return array( + 'website' => $website->getName(), + 'prettyDate' => Piwik_Period::factory($period, Piwik_Date::factory($date))->getLocalizedLongString(), + 'metadata' => $reportMetadata, + 'columns' => $columns, + 'reportData' => $newReport, + 'reportMetadata' => $rowsMetadata, + ); + } + + private function handleTableSimple($idSite, $period, $dataTable, $reportMetadata) + { + $renderer = new Piwik_DataTable_Renderer_Php(); + $renderer->setTable($dataTable); + $renderer->setSerialize(false); + $reportTable = $renderer->render(); + + $newReport = array(); + foreach($reportTable as $metric => $value) + { + // Use translated metric from metadata + // If translation not found, do not display the returned data + if(isset($reportMetadata['metrics'][$metric])) + { + $value = Piwik::getPrettyValue($idSite, $metric, $value, $htmlAllowed = false, $timeAsSentence = false); + + $metric = $reportMetadata['metrics'][$metric]; + $newReport[] = array( + 'label' => $metric, + 'value' => $value + ); + } + } + + $columns = array( + 'label' => Piwik_Translate('General_Name'), + 'value' => Piwik_Translate('General_Value'), + ); + return array( + $newReport, + $columns, + $rowsMetadata = array() + ); + } + + private function handleTableReport($idSite, $period, $dataTable, $reportMetadata) + { + // displayed columns + $columns = array_merge( + array('label' => $reportMetadata['dimension'] ), + $reportMetadata['metrics'] + ); + + if($period != 'day') + { + unset($columns['nb_uniq_visitors']); + } + + if(isset($reportMetadata['processedMetrics'])) + { + // Add processed metrics + $dataTable->filter('AddColumnsProcessedMetrics'); + $processedMetricsAdded = Piwik_API_API::getInstance()->getDefaultProcessedMetrics(); + foreach($processedMetricsAdded as $processedMetricId => $processedMetricTranslation) + { + // this processed metric can be displayed for this report + if(isset($reportMetadata['processedMetrics'][$processedMetricId])) + { + $columns[$processedMetricId] = $processedMetricTranslation; + } + } + } + // Display the global Goal metrics + if(isset($reportMetadata['metricsGoal'])) + { + $metricsGoalDisplay = array('conversion_rate', 'revenue'); + + // to have conversion_rate, we need to apply the Goal processed filter + // only requesting to process the basic metrics + $dataTable->filter('AddColumnsProcessedMetricsGoal', array($enable=true, Piwik_DataTable_Filter_AddColumnsProcessedMetricsGoal::GOALS_MINIMAL_REPORT)); + + // Add processed metrics to be displayed for this report + foreach($metricsGoalDisplay as $goalMetricId) + { + if(isset($reportMetadata['metricsGoal'][$goalMetricId])) + { + $columns[$goalMetricId] = $reportMetadata['metricsGoal'][$goalMetricId]; + } + } + } + $dataTable->filter('SafeDecodeLabel', array($outputHTML = false)); + $renderer = new Piwik_DataTable_Renderer_Php(); + $renderer->setTable($dataTable); + $renderer->setSerialize(false); + $reportTable = $renderer->render(); + $rowsMetadata = array(); + + $newReport = array(); + foreach($reportTable as $rowId => $row) + { + $newRow = array(); + foreach($row as $columnId => $value) + { + // Keep displayed columns + if(isset($columns[$columnId])) + { + $newRow[$columnId] = Piwik::getPrettyValue($idSite, $columnId, $value, $htmlAllowed = false, $timeAsSentence = false); + } + // We try and only keep metadata + // - if the column value is not an array (eg. metrics per goal) + // - if the column name doesn't contain _ (which is by standard, a metric column) + elseif(!is_array($value) + && strpos($columnId, '_') === false + ) + { + $rowsMetadata[$rowId][$columnId] = $value; + } + } + $newReport[] = $newRow; + } + return array( + $newReport, + $columns, + $rowsMetadata + ); + } + + private function getMetadata($idSite, $apiModule, $apiAction, $apiParameters = array()) + { + static $reportsMetadata = array(); + if(!isset($reportsMetadata[$idSite])) + { + $reportsMetadata[$idSite] = Piwik_API_API::getInstance()->getReportMetadata($idSite); + } + + foreach($reportsMetadata[$idSite] as $report) + { + if($report['module'] == $apiModule + && $report['action'] == $apiAction) + { + if(empty($apiParameters)) + { + return $report; + } + if(empty($report['parameters'])) + { + continue; + } + $diff = array_diff($report['parameters'], $apiParameters); + if(empty($diff)) + { + return $report; + } + } + } + return false; + } + /** * API metadata are sorted by category/name * @param $a diff --git a/plugins/CoreHome/templates/datatable.tpl b/plugins/CoreHome/templates/datatable.tpl index 56c508a151d280e415c520cb06f9ddf74c3e4607..76654601c4b93a22993e0f52745c4efc42b63728 100644 --- a/plugins/CoreHome/templates/datatable.tpl +++ b/plugins/CoreHome/templates/datatable.tpl @@ -4,7 +4,7 @@ {$arrayDataTable.message} {else} {if count($arrayDataTable) == 0} - <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div> + <div class="pk-emptyDataTable">{'CoreHome_ThereIsNoDataForThisReport'|translate}</div> {else} <a name="{$properties.uniqueId}"></a> <table cellspacing="0" class="dataTable"> diff --git a/plugins/CoreHome/templates/datatable_actions.tpl b/plugins/CoreHome/templates/datatable_actions.tpl index 44c8a16911f42eedc39908d7c72436d6ac67a8e3..46ac6c711d9c1cfc399d86f636ab0b8207e254b7 100644 --- a/plugins/CoreHome/templates/datatable_actions.tpl +++ b/plugins/CoreHome/templates/datatable_actions.tpl @@ -4,7 +4,7 @@ {$arrayDataTable.message} {else} {if count($arrayDataTable) == 0} - <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div> + <div class="pk-emptyDataTable">{'CoreHome_ThereIsNoDataForThisReport'|translate}</div> {else} <table cellspacing="0" class="dataTable dataTableActions"> <thead> diff --git a/plugins/CoreHome/templates/datatable_actions_recursive.tpl b/plugins/CoreHome/templates/datatable_actions_recursive.tpl index 48e98197d19eec4f532c39cc932b0d1088fbd6f2..60d95e6683dc140ad16b1f39413c998689bd5a24 100644 --- a/plugins/CoreHome/templates/datatable_actions_recursive.tpl +++ b/plugins/CoreHome/templates/datatable_actions_recursive.tpl @@ -4,7 +4,7 @@ {$arrayDataTable.message} {else} {if count($arrayDataTable) == 0} - <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div> + <div class="pk-emptyDataTable">{'CoreHome_ThereIsNoDataForThisReport'|translate}</div> {else} <table cellspacing="0" class="dataTable dataTableActions"> <thead> diff --git a/plugins/Referers/Referers.php b/plugins/Referers/Referers.php index cab1fa22770f0dabbff4f2bb0d02caa9dde7a134..82b35f475cac22248ca5f3fd64644cc557b73c24 100644 --- a/plugins/Referers/Referers.php +++ b/plugins/Referers/Referers.php @@ -50,6 +50,13 @@ class Piwik_Referers extends Piwik_Plugin { $reports = &$notification->getNotificationObject(); $reports = array_merge($reports, array( + array( + 'category' => Piwik_Translate('Referers_Referers'), + 'name' => Piwik_Translate('Referers_Type'), + 'module' => 'Referers', + 'action' => 'getRefererType', + 'dimension' => Piwik_Translate('Referers_ColumnRefererType') + ), array( 'category' => Piwik_Translate('Referers_Referers'), 'name' => Piwik_Translate('Referers_Keywords'), @@ -57,13 +64,6 @@ class Piwik_Referers extends Piwik_Plugin 'action' => 'getKeywords', 'dimension' => Piwik_Translate('Referers_ColumnKeyword'), ), - array( - 'category' => Piwik_Translate('Referers_Referers'), - 'name' => Piwik_Translate('Referers_SearchEngines'), - 'module' => 'Referers', - 'action' => 'getSearchEngines', - 'dimension' => Piwik_Translate('Referers_ColumnSearchEngine'), - ), array( 'category' => Piwik_Translate('Referers_Referers'), 'name' => Piwik_Translate('Referers_Websites'), @@ -73,17 +73,17 @@ class Piwik_Referers extends Piwik_Plugin ), array( 'category' => Piwik_Translate('Referers_Referers'), - 'name' => Piwik_Translate('Referers_Campaigns'), + 'name' => Piwik_Translate('Referers_SearchEngines'), 'module' => 'Referers', - 'action' => 'getCampaigns', - 'dimension' => Piwik_Translate('Referers_ColumnCampaign'), + 'action' => 'getSearchEngines', + 'dimension' => Piwik_Translate('Referers_ColumnSearchEngine'), ), array( 'category' => Piwik_Translate('Referers_Referers'), - 'name' => Piwik_Translate('Referers_Type'), + 'name' => Piwik_Translate('Referers_Campaigns'), 'module' => 'Referers', - 'action' => 'getRefererType', - 'dimension' => Piwik_Translate('Referers_ColumnRefererType') + 'action' => 'getCampaigns', + 'dimension' => Piwik_Translate('Referers_ColumnCampaign'), ), )); } diff --git a/tests/integration/Main.test.php b/tests/integration/Main.test.php index f18a71ba35c54ff36da1d0798da374c5914541c0..0fab6570e25b2e401e1f1a4ed3d1cc501de97dfc 100644 --- a/tests/integration/Main.test.php +++ b/tests/integration/Main.test.php @@ -42,7 +42,15 @@ class Test_Piwik_Integration_Main extends Test_Integration { $this->setApiNotToCall(array()); $this->setApiToCall( 'API' ); - $this->callGetApiCompareOutput(__FUNCTION__, 'xml'); + $dateTime = '2009-01-04 00:11:42'; + $idSite = $this->createWebsite($dateTime); + + $t = $this->getTracker($idSite, $dateTime, $defaultInit = true); + // Record 1st page view + $t->setUrl( 'http://example.org/index.htm' ); + $this->checkResponse($t->doTrackPageView( 'incredible title!')); + + $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime); } /* diff --git a/tests/integration/expected/test_TwoVisitors_twoWebsites_differentDays__VisitsSummary.get_day.xml b/tests/integration/expected/test_TwoVisitors_twoWebsites_differentDays__VisitsSummary.get_day.xml index dcc000fdc13f66cc735c54e8e1bf8710c8d70d31..792028cb999ee59c99da1e108076b851c74276d7 100644 --- a/tests/integration/expected/test_TwoVisitors_twoWebsites_differentDays__VisitsSummary.get_day.xml +++ b/tests/integration/expected/test_TwoVisitors_twoWebsites_differentDays__VisitsSummary.get_day.xml @@ -2,21 +2,21 @@ <results> <result idSite="1"> <result date="2010-01-03"> + <bounce_count>2</bounce_count> + <max_actions>1</max_actions> + <nb_actions>2</nb_actions> <nb_uniq_visitors>2</nb_uniq_visitors> <nb_visits>2</nb_visits> - <nb_actions>2</nb_actions> - <max_actions>1</max_actions> - <bounce_count>2</bounce_count> <bounce_rate>100%</bounce_rate> <nb_actions_per_visit>1</nb_actions_per_visit> <avg_time_on_site>0</avg_time_on_site> </result> <result date="2010-01-04" /> <result date="2010-01-05"> + <max_actions>2</max_actions> + <nb_actions>2</nb_actions> <nb_uniq_visitors>1</nb_uniq_visitors> <nb_visits>1</nb_visits> - <nb_actions>2</nb_actions> - <max_actions>2</max_actions> <sum_visit_length>360</sum_visit_length> <bounce_rate>0%</bounce_rate> <nb_actions_per_visit>2</nb_actions_per_visit> diff --git a/tests/integration/expected/test_apiGetReportMetadata__API.getProcessedReport_day.xml b/tests/integration/expected/test_apiGetReportMetadata__API.getProcessedReport_day.xml new file mode 100644 index 0000000000000000000000000000000000000000..18c35aed671db99c18fa8e8f3fdab285da42a6e4 --- /dev/null +++ b/tests/integration/expected/test_apiGetReportMetadata__API.getProcessedReport_day.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <website>Piwik test</website> + <prettyDate>Sunday 4 January 2009</prettyDate> + <metadata> + <category>General_Visitors</category> + <name>UserCountry_Country</name> + <module>UserCountry</module> + <action>getCountry</action> + <dimension>UserCountry_Country</dimension> + <metrics> + <nb_uniq_visitors>General_ColumnNbUniqVisitors</nb_uniq_visitors> + <nb_visits>General_ColumnNbVisits</nb_visits> + <nb_actions>General_ColumnNbActions</nb_actions> + + </metrics> + <processedMetrics> + <nb_actions_per_visit>General_ColumnActionsPerVisit</nb_actions_per_visit> + <avg_time_on_site>General_ColumnAvgTimeOnSite</avg_time_on_site> + <bounce_rate>General_ColumnBounceRate</bounce_rate> + <conversion_rate>General_ColumnConversionRate</conversion_rate> + + </processedMetrics> + <metricsGoal> + <nb_conversions>Goals_ColumnConversions</nb_conversions> + <conversion_rate>General_ColumnConversionRate</conversion_rate> + <revenue>Goals_ColumnRevenue</revenue> + + </metricsGoal> + <processedMetricsGoal> + <revenue_per_visit>General_ColumnValuePerVisit</revenue_per_visit> + + </processedMetricsGoal> + + </metadata> + <columns> + <label>UserCountry_Country</label> + <nb_uniq_visitors>General_ColumnNbUniqVisitors</nb_uniq_visitors> + <nb_visits>General_ColumnNbVisits</nb_visits> + <nb_actions>General_ColumnNbActions</nb_actions> + <nb_actions_per_visit>Actions per Visit</nb_actions_per_visit> + <avg_time_on_site>Avg. Time on Website</avg_time_on_site> + <bounce_rate>Bounce Rate</bounce_rate> + <conversion_rate>General_ColumnConversionRate</conversion_rate> + <revenue>Goals_ColumnRevenue</revenue> + + </columns> + <reportData> + <row> + <label>France</label> + <nb_uniq_visitors>1</nb_uniq_visitors> + <nb_visits>1</nb_visits> + <nb_actions>1</nb_actions> + <conversion_rate>0</conversion_rate> + <nb_actions_per_visit>1</nb_actions_per_visit> + <avg_time_on_site>00:00:00</avg_time_on_site> + <bounce_rate>100%</bounce_rate> + + </row> + + </reportData> + <reportMetadata> + <row> + <code>fr</code> + <logo>plugins/UserCountry/flags/fr.png</logo> + <logoWidth>18</logoWidth> + <logoHeight>12</logoHeight> + + </row> + + </reportMetadata> + +</result> \ No newline at end of file