From 8784f4170daad717f98bdee42549bab8b3539784 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 02:21:32 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@448 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- oss/piwik/trunk/plugins/VisitTime/API.php | 55 ++++++ .../trunk/plugins/VisitTime/Controller.php | 60 ++++++ .../trunk/plugins/VisitTime/VisitTime.php | 147 +++++++++++++++ .../plugins/VisitTime/templates/index.tpl | 9 + .../trunk/plugins/VisitorInterest/API.php | 109 +++++++++++ .../plugins/VisitorInterest/Controller.php | 58 ++++++ .../VisitorInterest/VisitorInterest.php | 177 ++++++++++++++++++ .../VisitorInterest/templates/index.tpl | 7 + oss/piwik/trunk/plugins/VisitsSummary/API.php | 111 +++++++++++ .../plugins/VisitsSummary/Controller.php | 89 +++++++++ .../plugins/VisitsSummary/VisitsSummary.php | 51 +++++ .../plugins/VisitsSummary/templates/index.tpl | 14 ++ .../VisitsSummary/templates/sparklines.tpl | 13 ++ .../trunk/plugins/Widgetize/Controller.php | 69 +++++++ .../trunk/plugins/Widgetize/Widgetize.php | 28 +++ .../plugins/Widgetize/templates/iframe.tpl | 14 ++ .../plugins/Widgetize/templates/index.tpl | 97 ++++++++++ .../trunk/plugins/Widgetize/templates/js.tpl | 19 ++ .../Widgetize/templates/test_jsinclude.tpl | 20 ++ .../Widgetize/templates/test_jsinclude2.tpl | 27 +++ .../plugins/Widgetize/templates/widgetize.js | 102 ++++++++++ 21 files changed, 1276 insertions(+) create mode 100644 oss/piwik/trunk/plugins/VisitTime/API.php create mode 100644 oss/piwik/trunk/plugins/VisitTime/Controller.php create mode 100644 oss/piwik/trunk/plugins/VisitTime/VisitTime.php create mode 100644 oss/piwik/trunk/plugins/VisitTime/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/VisitorInterest/API.php create mode 100644 oss/piwik/trunk/plugins/VisitorInterest/Controller.php create mode 100644 oss/piwik/trunk/plugins/VisitorInterest/VisitorInterest.php create mode 100644 oss/piwik/trunk/plugins/VisitorInterest/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/VisitsSummary/API.php create mode 100644 oss/piwik/trunk/plugins/VisitsSummary/Controller.php create mode 100644 oss/piwik/trunk/plugins/VisitsSummary/VisitsSummary.php create mode 100644 oss/piwik/trunk/plugins/VisitsSummary/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/VisitsSummary/templates/sparklines.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/Controller.php create mode 100644 oss/piwik/trunk/plugins/Widgetize/Widgetize.php create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/iframe.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/js.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude2.tpl create mode 100644 oss/piwik/trunk/plugins/Widgetize/templates/widgetize.js diff --git a/oss/piwik/trunk/plugins/VisitTime/API.php b/oss/piwik/trunk/plugins/VisitTime/API.php new file mode 100644 index 00000000..602f5e3a --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitTime/API.php @@ -0,0 +1,55 @@ +getDataTable($name); + $dataTable->filter('Sort', array('label', 'asc', true)); + $dataTable->queueFilter('ColumnCallbackReplace', array('label', 'Piwik_getTimeLabel')); + $dataTable->queueFilter('ReplaceColumnNames'); + return $dataTable; + } + + public function getVisitInformationPerLocalTime( $idSite, $period, $date ) + { + return $this->getDataTable('VisitTime_localTime', $idSite, $period, $date ); + } + + public function getVisitInformationPerServerTime( $idSite, $period, $date ) + { + return $this->getDataTable('VisitTime_serverTime', $idSite, $period, $date ); + } +} + +function Piwik_getTimeLabel($label) +{ + return sprintf(Piwik_Translate('VisitTime_NHour'), $label); +} diff --git a/oss/piwik/trunk/plugins/VisitTime/Controller.php b/oss/piwik/trunk/plugins/VisitTime/Controller.php new file mode 100644 index 00000000..baece1cf --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitTime/Controller.php @@ -0,0 +1,60 @@ +dataTableVisitInformationPerLocalTime = $this->getVisitInformationPerLocalTime(true); + $view->dataTableVisitInformationPerServerTime = $this->getVisitInformationPerServerTime(true); + echo $view->render(); + } + + public function getVisitInformationPerServerTime( $fetch = false) + { + $view = Piwik_ViewDataTable::factory( 'graphVerticalBar'); + $view->init( $this->pluginName, __FUNCTION__, "VisitTime.getVisitInformationPerServerTime" ); + + $view->setColumnsToDisplay( array('label','nb_visits') ); + $view->setSortedColumn( 'label', 'asc' ); + $view->setColumnTranslation('label', Piwik_Translate('VisitTime_ColumnServerTime')); + $view->setLimit( 24 ); + $view->setGraphLimit( 24 ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + $view->enableShowGoals(); + + return $this->renderView($view, $fetch); + } + + public function getVisitInformationPerLocalTime( $fetch = false) + { + $view = Piwik_ViewDataTable::factory( 'graphVerticalBar'); + $view->init( $this->pluginName, __FUNCTION__, "VisitTime.getVisitInformationPerLocalTime" ); + $view->setColumnTranslation('label', Piwik_Translate('VisitTime_ColumnLocalTime')); + $view->setColumnsToDisplay( array('label','nb_visits') ); + $view->setSortedColumn( 'label', 'asc' ); + $view->setLimit( 24 ); + $view->setGraphLimit( 24 ); + $view->disableSearchBox(); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + + return $this->renderView($view, $fetch); + } +} diff --git a/oss/piwik/trunk/plugins/VisitTime/VisitTime.php b/oss/piwik/trunk/plugins/VisitTime/VisitTime.php new file mode 100644 index 00000000..f059a9a0 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitTime/VisitTime.php @@ -0,0 +1,147 @@ + Piwik_Translate('VisitTime_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + return $info; + } + + function getListHooksRegistered() + { + $hooks = array( + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + 'Goals.getAvailableGoalSegments' => 'addGoalSegments', + ); + return $hooks; + } + + function addWidgets() + { + Piwik_AddWidget( 'VisitTime_SubmenuTimes', 'VisitTime_WidgetLocalTime', 'VisitTime', 'getVisitInformationPerLocalTime'); + Piwik_AddWidget( 'VisitTime_SubmenuTimes', 'VisitTime_WidgetServerTime', 'VisitTime', 'getVisitInformationPerServerTime'); + } + + function addMenu() + { + Piwik_AddMenu('General_Visitors', 'VisitTime_SubmenuTimes', array('module' => 'VisitTime', 'action' => 'index')); + } + + function addGoalSegments( $notification ) + { + $segments =& $notification->getNotificationObject(); + $segments[] = array( + 'group' => Piwik_Translate('VisitTime_ColumnServerTime'), + 'name' => Piwik_Translate('VisitTime_ColumnServerTime'), + 'module' => 'VisitTime', + 'action' => 'getVisitInformationPerServerTime', + ); + } + + function archivePeriod( $notification ) + { + $archiveProcessing = $notification->getNotificationObject(); + $dataTableToSum = array( + 'VisitTime_localTime', + 'VisitTime_serverTime', + ); + $archiveProcessing->archiveDataTable($dataTableToSum); + } + + public function archiveDay( $notification ) + { + $archiveProcessing = $notification->getNotificationObject(); + $this->archiveDayAggregateVisits($archiveProcessing); + $this->archiveDayAggregateGoals($archiveProcessing); + $this->archiveDayRecordInDatabase($archiveProcessing); + } + + protected function archiveDayAggregateVisits($archiveProcessing) + { + $labelSQL = "HOUR(visitor_localtime)"; + $this->interestByLocalTime = $archiveProcessing->getArrayInterestForLabel($labelSQL); + + $labelSQL = "HOUR(visit_last_action_time)"; + $this->interestByServerTime = $archiveProcessing->getArrayInterestForLabel($labelSQL); + $this->interestByServerTime = $this->convertServerTimeToLocalTimezone($this->interestByServerTime, $archiveProcessing); + } + + protected function convertServerTimeToLocalTimezone($interestByServerTime, $archiveProcessing) + { + $date = Piwik_Date::factory($archiveProcessing->getStartDatetimeUTC())->toString(); + $timezone = $archiveProcessing->site->getTimezone(); + $visitsByHourTz = array(); + foreach($interestByServerTime as $hour => $stats) + { + $datetime = $date . ' '.$hour.':00:00'; + $hourInTz = (int)Piwik_Date::factory($datetime, $timezone)->toString('H'); + $visitsByHourTz[$hourInTz] = $stats; + } + return $visitsByHourTz; + } + + protected function archiveDayAggregateGoals($archiveProcessing) + { + $query = $archiveProcessing->queryConversionsBySingleSegment("HOUR(server_time)"); + $goalByServerTime = array(); + while($row = $query->fetch()) + { + $goalByServerTime[$row['label']][$row['idgoal']] = $archiveProcessing->getGoalRowFromQueryRow($row); + } + $goalByServerTime = $this->convertServerTimeToLocalTimezone($goalByServerTime, $archiveProcessing); + foreach($goalByServerTime as $hour => $goals) + { + $this->interestByServerTime[$hour][Piwik_Archive::INDEX_GOALS] = $goals; + } + $archiveProcessing->enrichConversionsByLabelArray($this->interestByServerTime); + } + + protected function archiveDayRecordInDatabase($archiveProcessing) + { + $tableLocalTime = $archiveProcessing->getDataTableFromArray($this->interestByLocalTime); + $this->makeSureAllHoursAreSet($tableLocalTime, $archiveProcessing); + $archiveProcessing->insertBlobRecord('VisitTime_localTime', $tableLocalTime->getSerialized()); + destroy($tableLocalTime); + + $tableServerTime = $archiveProcessing->getDataTableFromArray($this->interestByServerTime); + $this->makeSureAllHoursAreSet($tableServerTime, $archiveProcessing); + $archiveProcessing->insertBlobRecord('VisitTime_serverTime', $tableServerTime->getSerialized()); + destroy($tableServerTime); + } + + private function makeSureAllHoursAreSet($table, $archiveProcessing) + { + for($i=0; $i<=23; $i++) + { + if($table->getRowFromLabel($i) === false) + { + $row = $archiveProcessing->getNewInterestRowLabeled($i); + $table->addRow( $row ); + } + } + } +} + diff --git a/oss/piwik/trunk/plugins/VisitTime/templates/index.tpl b/oss/piwik/trunk/plugins/VisitTime/templates/index.tpl new file mode 100644 index 00000000..82af946c --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitTime/templates/index.tpl @@ -0,0 +1,9 @@ +
+

{'VisitTime_LocalTime'|translate}

+{$dataTableVisitInformationPerLocalTime} +
+ +
+

{'VisitTime_ServerTime'|translate}

+{$dataTableVisitInformationPerServerTime} +
diff --git a/oss/piwik/trunk/plugins/VisitorInterest/API.php b/oss/piwik/trunk/plugins/VisitorInterest/API.php new file mode 100644 index 00000000..9abae6e8 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorInterest/API.php @@ -0,0 +1,109 @@ +getDataTable($name); + $dataTable->filter('Sort',array(Piwik_Archive::INDEX_NB_VISITS)); + $dataTable->queueFilter('ReplaceColumnNames'); + $dataTable->queueFilter('Sort', array('label', 'asc', true)); + return $dataTable; + } + + public function getNumberOfVisitsPerVisitDuration( $idSite, $period, $date ) + { + $dataTable = $this->getDataTable('VisitorInterest_timeGap', $idSite, $period, $date); + $dataTable->queueFilter('ColumnCallbackReplace', array('label', 'Piwik_getDurationLabel')); + return $dataTable; + } + + public function getNumberOfVisitsPerPage( $idSite, $period, $date ) + { + $dataTable = $this->getDataTable('VisitorInterest_pageGap', $idSite, $period, $date); + $dataTable->queueFilter('ColumnCallbackReplace', array('label', 'Piwik_getPageGapLabel')); + return $dataTable; + } +} + +function Piwik_getDurationLabel($label) +{ + if(($pos = strpos($label,'-')) !== false) + { + $min = substr($label, 0, $pos); + $max = substr($label, $pos+1); + + if($min == 0 || $min == 30) + { + $XYSeconds = Piwik_Translate('VisitorInterest_BetweenXYSeconds'); + return sprintf($XYSeconds, $min, $max); + } + else + { + $min = $min / 60; + $max = $max / 60; + $XYMin = Piwik_Translate('VisitorInterest_BetweenXYMinutes'); + return sprintf($XYMin, $min, $max); + } + } + if(!is_numeric($label)) + { + return $label; + } + $time = intval($label) / 60; + $plusXMin = Piwik_Translate('VisitorInterest_PlusXMin'); + return sprintf($plusXMin, $time . urlencode('+')); +} + +function Piwik_getPageGapLabel($label) +{ + $return = false; + if(($pos = strpos($label,'-')) !== false) + { + $min = substr($label, 0, $pos); + $max = substr($label, $pos+1); + + if($min == $max) + { + $return = $min; + } + } + if(!$return) + { + $return = $label; + } + + if($return == 1) + { + return Piwik_Translate('VisitorInterest_OnePage'); + } + + return sprintf(Piwik_Translate('VisitorInterest_NPages'), $return); +} diff --git a/oss/piwik/trunk/plugins/VisitorInterest/Controller.php b/oss/piwik/trunk/plugins/VisitorInterest/Controller.php new file mode 100644 index 00000000..d5fb8eb1 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorInterest/Controller.php @@ -0,0 +1,58 @@ +dataTableNumberOfVisitsPerVisitDuration = $this->getNumberOfVisitsPerVisitDuration(true); + $view->dataTableNumberOfVisitsPerPage = $this->getNumberOfVisitsPerPage(true); + echo $view->render(); + } + + function getNumberOfVisitsPerVisitDuration( $fetch = false) + { + $view = Piwik_ViewDataTable::factory( 'cloud' ); + $view->init( $this->pluginName, __FUNCTION__, "VisitorInterest.getNumberOfVisitsPerVisitDuration" ); + + $view->setColumnsToDisplay( array('label','nb_visits') ); + $view->setSortedColumn( 'label', 'asc' ); + $view->setColumnTranslation('label', Piwik_Translate('VisitorInterest_ColumnVisitDuration')); + $view->disableSort(); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + $view->disableSearchBox(); + $view->disableShowAllColumns(); + + return $this->renderView($view, $fetch); + } + + function getNumberOfVisitsPerPage( $fetch = false) + { + $view = Piwik_ViewDataTable::factory( 'cloud' ); + $view->init( $this->pluginName, __FUNCTION__, "VisitorInterest.getNumberOfVisitsPerPage" ); + $view->setColumnsToDisplay( array('label','nb_visits') ); + $view->setSortedColumn( 'nb_visits', 'asc' ); + $view->setColumnTranslation('label', Piwik_Translate('VisitorInterest_ColumnPagesPerVisit')); + $view->disableExcludeLowPopulation(); + $view->disableOffsetInformation(); + $view->disableSearchBox(); + $view->disableSort(); + $view->disableShowAllColumns(); + + return $this->renderView($view, $fetch); + } +} diff --git a/oss/piwik/trunk/plugins/VisitorInterest/VisitorInterest.php b/oss/piwik/trunk/plugins/VisitorInterest/VisitorInterest.php new file mode 100644 index 00000000..13baab42 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorInterest/VisitorInterest.php @@ -0,0 +1,177 @@ + Piwik_Translate('VisitorInterest_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + + return $info; + } + + function getListHooksRegistered() + { + $hooks = array( + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + ); + return $hooks; + } + + protected $timeGap = array( + array(0, 0.5), + array(0.5, 1), + array(1, 2), + array(2, 4), + array(4, 6), + array(6, 8), + array(8, 11), + array(11, 15), + array(15) + ); + + protected $pageGap = array( + array(1, 1), + array(2, 2), + array(3, 3), + array(4, 4), + array(5, 5), + array(6, 7), + array(8, 10), + array(11, 14), + array(15, 20), + array(20) + ); + + function addWidgets() + { + Piwik_AddWidget( 'General_Visitors', 'VisitorInterest_WidgetLengths', 'VisitorInterest', 'getNumberOfVisitsPerVisitDuration'); + Piwik_AddWidget( 'General_Visitors', 'VisitorInterest_WidgetPages', 'VisitorInterest', 'getNumberOfVisitsPerPage'); + } + + function addMenu() + { + Piwik_RenameMenuEntry('General_Visitors', 'VisitFrequency_SubmenuFrequency', + 'General_Visitors', 'VisitorInterest_Engagement' ); + } + + function postLoad() + { + Piwik_AddAction('template_headerVisitsFrequency', array('Piwik_VisitorInterest','headerVisitsFrequency')); + Piwik_AddAction('template_footerVisitsFrequency', array('Piwik_VisitorInterest','footerVisitsFrequency')); + } + + + function archivePeriod( $notification ) + { + $archiveProcessing = $notification->getNotificationObject(); + + $dataTableToSum = array( + 'VisitorInterest_timeGap', + 'VisitorInterest_pageGap', + ); + $archiveProcessing->archiveDataTable($dataTableToSum); + } + + public function archiveDay( $notification ) + { + $this->archiveProcessing = $notification->getNotificationObject(); + + $recordName = 'VisitorInterest_timeGap'; + $tableTimegap = $this->getTableTimeGap(); + $this->archiveProcessing->insertBlobRecord($recordName, $tableTimegap->getSerialized()); + + $recordName = 'VisitorInterest_pageGap'; + $tablePagegap = $this->getTablePageGap(); + $this->archiveProcessing->insertBlobRecord($recordName, $tablePagegap->getSerialized()); + } + + protected function getTablePageGap() + { + $select = array(); + foreach($this->pageGap as $gap) + { + if(count($gap) == 2) + { + $minGap = $gap[0]; + $maxGap = $gap[1]; + $gapName = "'$minGap-$maxGap'"; + $select[] = "sum(case when visit_total_actions between $minGap and $maxGap then 1 else 0 end) as $gapName "; + } + else + { + $minGap = $gap[0]; + $plusEncoded = urlencode('+'); + $gapName = "'".$minGap.$plusEncoded."'"; + $select[] = "sum(case when visit_total_actions > $minGap then 1 else 0 end) as $gapName "; + } + } + $toSelect = implode(" , ", $select); + + return $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, Piwik_Archive::INDEX_NB_VISITS); + } + + protected function getTableTimeGap() + { + $select = array(); + foreach($this->timeGap as $gap) + { + if(count($gap) == 2) + { + $minGap = $gap[0] * 60; + $maxGap = $gap[1] * 60; + + $gapName = "'".$minGap."-".$maxGap."'"; + $select[] = "sum(case when visit_total_time between $minGap and $maxGap then 1 else 0 end) as $gapName "; + } + else + { + $minGap = $gap[0] * 60; + $gapName = "'$minGap'"; + $select[] = "sum(case when visit_total_time > $minGap then 1 else 0 end) as $gapName "; + } + } + $toSelect = implode(" , ", $select); + + $table = $this->archiveProcessing->getSimpleDataTableFromSelect($toSelect, Piwik_Archive::INDEX_NB_VISITS); + return $table; + } + + static public function headerVisitsFrequency($notification) + { + $out =& $notification->getNotificationObject(); + $out = '
'; + } + + static public function footerVisitsFrequency($notification) + { + $out =& $notification->getNotificationObject(); + $out = '
+
+ '; + $out .= Piwik_FrontController::getInstance()->fetchDispatch('VisitorInterest','index'); + $out .= '
'; + } +} + diff --git a/oss/piwik/trunk/plugins/VisitorInterest/templates/index.tpl b/oss/piwik/trunk/plugins/VisitorInterest/templates/index.tpl new file mode 100644 index 00000000..f3855a44 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorInterest/templates/index.tpl @@ -0,0 +1,7 @@ + +

{'VisitorInterest_VisitsPerDuration'|translate}

+{$dataTableNumberOfVisitsPerVisitDuration} + +

{'VisitorInterest_VisitsPerNbOfPages'|translate}

+{$dataTableNumberOfVisitsPerPage} + diff --git a/oss/piwik/trunk/plugins/VisitsSummary/API.php b/oss/piwik/trunk/plugins/VisitsSummary/API.php new file mode 100644 index 00000000..99b1e612 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitsSummary/API.php @@ -0,0 +1,111 @@ +getDataTableFromNumeric($toFetch); + if($bounceRateRequested !== false) + { + $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_rate', 'bounce_count', 'nb_visits', 0)); + $dataTable->deleteColumns($toFetch); + } + return $dataTable; + } + + protected function getNumeric( $idSite, $period, $date, $toFetch ) + { + Piwik::checkUserHasViewAccess( $idSite ); + $archive = Piwik_Archive::build($idSite, $period, $date ); + $dataTable = $archive->getNumeric($toFetch); + return $dataTable; + } + + public function getVisits( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_visits'); + } + + public function getUniqueVisitors( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_uniq_visitors'); + } + + public function getActions( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_actions'); + } + + public function getMaxActions( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'max_actions'); + } + + public function getBounceCount( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'bounce_count'); + } + + public function getVisitsConverted( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_visits_converted'); + } + + public function getSumVisitsLength( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'sum_visit_length'); + } + + public function getSumVisitsLengthPretty( $idSite, $period, $date ) + { + return Piwik::getPrettyTimeFromSeconds($this->getSumVisitsLength( $idSite, $period, $date )); + } +} diff --git a/oss/piwik/trunk/plugins/VisitsSummary/Controller.php b/oss/piwik/trunk/plugins/VisitsSummary/Controller.php new file mode 100644 index 00000000..1c480cf1 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitsSummary/Controller.php @@ -0,0 +1,89 @@ +setPeriodVariablesView($view); + $view->graphEvolutionVisitsSummary = $this->getEvolutionGraph( true, array('nb_visits') ); + $this->setSparklinesAndNumbers($view); + echo $view->render(); + } + + public function getSparklines() + { + $view = Piwik_View::factory('sparklines'); + $this->setSparklinesAndNumbers($view); + echo $view->render(); + } + + public function getEvolutionGraph( $fetch = false, $columns = false) + { + $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "VisitsSummary.get"); + if(empty($columns)) + { + $columns = Piwik_Common::getRequestVar('columns'); + } + $view->setColumnsToDisplay($columns); + return $this->renderView($view, $fetch); + } + + static public function getVisitsSummary() + { + $requestString = "method=VisitsSummary.get". + "&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=1"; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } + + static public function getVisits() + { + $requestString = "method=VisitsSummary.getVisits". + "&format=original". + "&disable_generic_filters=1"; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } + + protected function setSparklinesAndNumbers($view) + { + $view->urlSparklineNbVisits = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('nb_visits'))); + $view->urlSparklineNbActions = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('nb_actions'))); + $view->urlSparklineSumVisitLength = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('sum_visit_length'))); + $view->urlSparklineMaxActions = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('max_actions'))); + $view->urlSparklineBounceRate = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('bounce_rate'))); + + $dataTableVisit = self::getVisitsSummary(); + $dataRow = $dataTableVisit->getFirstRow(); + if($view->period != 'year') + { + $view->urlSparklineNbUniqVisitors = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('nb_uniq_visitors'))); + $view->nbUniqVisitors = $dataRow->getColumn('nb_uniq_visitors'); + } + $nbVisits = $dataRow->getColumn('nb_visits'); + $view->nbVisits = $nbVisits; + $view->nbActions = $dataRow->getColumn('nb_actions'); + $view->sumVisitLength = $dataRow->getColumn('sum_visit_length'); + $nbBouncedVisits = $dataRow->getColumn('bounce_count'); + $view->bounceRate = Piwik::getPercentageSafe($nbBouncedVisits, $nbVisits); + $view->maxActions = $dataRow->getColumn('max_actions'); + } +} diff --git a/oss/piwik/trunk/plugins/VisitsSummary/VisitsSummary.php b/oss/piwik/trunk/plugins/VisitsSummary/VisitsSummary.php new file mode 100644 index 00000000..4d64386a --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitsSummary/VisitsSummary.php @@ -0,0 +1,51 @@ + Piwik_Translate('VisitsSummary_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + return $info; + } + + function getListHooksRegistered() + { + return array( + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + ); + } + + function addWidgets() + { + Piwik_AddWidget( 'VisitsSummary_VisitsSummary', 'VisitsSummary_WidgetLastVisits', 'VisitsSummary', 'getEvolutionGraph', array('columns' => array('nb_visits'))); + Piwik_AddWidget( 'VisitsSummary_VisitsSummary', 'VisitsSummary_WidgetVisits', 'VisitsSummary', 'getSparklines'); + Piwik_AddWidget( 'VisitsSummary_VisitsSummary', 'VisitsSummary_WidgetOverviewGraph', 'VisitsSummary', 'index'); + } + + function addMenu() + { + Piwik_AddMenu('General_Visitors', 'VisitsSummary_SubmenuOverview', array('module' => 'VisitsSummary', 'action' => 'index'), true); + } +} + + diff --git a/oss/piwik/trunk/plugins/VisitsSummary/templates/index.tpl b/oss/piwik/trunk/plugins/VisitsSummary/templates/index.tpl new file mode 100644 index 00000000..4cf972d9 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitsSummary/templates/index.tpl @@ -0,0 +1,14 @@ + + + +

{'VisitsSummary_EvolutionOverLastPeriods'|translate:$periodsNames.$period.plural}

+{$graphEvolutionVisitsSummary} + +

{'VisitsSummary_Report'|translate}

+{include file=VisitsSummary/templates/sparklines.tpl} + +


+

+{'VisitsSummary_GenerateTime'|translate:$totalTimeGeneration:$totalNumberOfQueries} +{if $totalNumberOfQueries != 0}, {'VisitsSummary_GenerateQueries'|translate:$totalNumberOfQueries}{/if} +

diff --git a/oss/piwik/trunk/plugins/VisitsSummary/templates/sparklines.tpl b/oss/piwik/trunk/plugins/VisitsSummary/templates/sparklines.tpl new file mode 100644 index 00000000..8dfc3161 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitsSummary/templates/sparklines.tpl @@ -0,0 +1,13 @@ +
+
{sparkline src=$urlSparklineNbVisits} {'VisitsSummary_NbVisits'|translate:"$nbVisits"}
+ {if isset($urlSparklineNbUniqVisitors)} +
{sparkline src=$urlSparklineNbUniqVisitors} {'VisitsSummary_NbUniqueVisitors'|translate:"$nbUniqVisitors"}
+ {/if} +
{sparkline src=$urlSparklineNbActions} {'VisitsSummary_NbActionsDescription'|translate:"$nbActions"}
+
+
+
{sparkline src=$urlSparklineSumVisitLength} {assign var=sumtimeVisitLength value=$sumVisitLength|sumtime} {'VisitsSummary_TotalTime'|translate:"$sumtimeVisitLength"}
+
{sparkline src=$urlSparklineMaxActions} {'VisitsSummary_MaxNbActions'|translate:"$maxActions"}
+
{sparkline src=$urlSparklineBounceRate} {'VisitsSummary_NbVisitsBounced'|translate:"$bounceRate%"}
+
+
diff --git a/oss/piwik/trunk/plugins/Widgetize/Controller.php b/oss/piwik/trunk/plugins/Widgetize/Controller.php new file mode 100644 index 00000000..74011fb8 --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/Controller.php @@ -0,0 +1,69 @@ +availableWidgets = json_encode(Piwik_GetWidgetsList()); + $this->setGeneralVariablesView($view); + echo $view->render(); + } + + function testJsInclude1() + { + $view = Piwik_View::factory('test_jsinclude'); + $view->url1 = '?module=Widgetize&action=js&moduleToWidgetize=UserSettings&actionToWidgetize=getBrowser&idSite=1&period=day&date=yesterday'; + $view->url2 = '?module=Widgetize&action=js&moduleToWidgetize=API&actionToWidgetize=index&method=ExamplePlugin.getGoldenRatio&format=original'; + echo $view->render(); + } + + function testJsInclude2() + { + $view = Piwik_View::factory('test_jsinclude2'); + $view->url1 = '?module=Widgetize&action=js&moduleToWidgetize=UserSettings&actionToWidgetize=getBrowser&idSite=1&period=day&date=yesterday'; + $view->url2 = '?module=Widgetize&action=js&moduleToWidgetize=UserCountry&actionToWidgetize=getCountry&idSite=1&period=day&date=yesterday&viewDataTable=cloud&show_footer=0'; + $view->url3 = '?module=Widgetize&action=js&moduleToWidgetize=Referers&actionToWidgetize=getKeywords&idSite=1&period=day&date=yesterday&viewDataTable=table&show_footer=0'; + echo $view->render(); + } + + function js() + { + Piwik_API_Request::reloadAuthUsingTokenAuth(); + $controllerName = Piwik_Common::getRequestVar('moduleToWidgetize'); + $actionName = Piwik_Common::getRequestVar('actionToWidgetize'); + $parameters = array ( $fetch = true ); + $content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName, $parameters); + $view = Piwik_View::factory('js'); + $view->piwikUrl = Piwik_Url::getCurrentUrlWithoutFileName(); + $content = str_replace(array("\t","\n","\r\n","\r"), "", $content); + $view->content = $content; + echo $view->render(); + } + + function iframe() + { + Piwik_API_Request::reloadAuthUsingTokenAuth(); + $controllerName = Piwik_Common::getRequestVar('moduleToWidgetize'); + $actionName = Piwik_Common::getRequestVar('actionToWidgetize'); + $parameters = array ( $fetch = true ); + $outputDataTable = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName, $parameters); + $view = Piwik_View::factory('iframe'); + $view->content = $outputDataTable; + echo $view->render(); + } +} diff --git a/oss/piwik/trunk/plugins/Widgetize/Widgetize.php b/oss/piwik/trunk/plugins/Widgetize/Widgetize.php new file mode 100644 index 00000000..9e50ad83 --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/Widgetize.php @@ -0,0 +1,28 @@ + Piwik_Translate('Widgetize_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + } +} diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/iframe.tpl b/oss/piwik/trunk/plugins/Widgetize/templates/iframe.tpl new file mode 100644 index 00000000..06b28eec --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/iframe.tpl @@ -0,0 +1,14 @@ + + +{loadJavascriptTranslations plugins='CoreHome'} +{include file="CoreHome/templates/js_global_variables.tpl"} +{include file="CoreHome/templates/js_css_includes.tpl"} + + + +
+{$content} +
+ + + diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/index.tpl b/oss/piwik/trunk/plugins/Widgetize/templates/index.tpl new file mode 100644 index 00000000..3e705fb0 --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/index.tpl @@ -0,0 +1,97 @@ +{assign var=showSitesSelection value=true} +{assign var=showPeriodSelection value=true} +{include file="CoreHome/templates/header.tpl"} +{loadJavascriptTranslations plugins='Dashboard'} + + + + + + + + + + + + + + + + +{literal} + +{/literal} + + +
+

With Piwik, you can export your Web Analytics reports on your blog, website, or intranet dashboard... in one click. +

› Widget authentication: If you want your widgets to be viewable by everybody, you first have to set the 'view' permissions + to the anonymous user in the Users Management section. +
Alternatively, if you are publishing widgets on a password protected or private page, + you don't necessarily have to allow 'anonymous' to view your reports. In this case, you can add the secret token_auth parameter (found in the API page) in the widget URL. +

+

› Widgetize the full dashboard: You can also display the full Piwik dashboard in your application or website in an IFRAME (see example). + The date parameter can be set to a specific calendar date, "today", or "yesterday". The period parameter can be set to "day", "week", "month", or "year". + The language parameter can be set to the language code of a translation, such as language=fr. + For example, for idSite=1 and date=yesterday, you can write: +

+

› Select a report, and copy paste in your page the embed code below the widget: +

+ + + + +
+ +
diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/js.tpl b/oss/piwik/trunk/plugins/Widgetize/templates/js.tpl new file mode 100644 index 00000000..a92c76e6 --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/js.tpl @@ -0,0 +1,19 @@ +{loadJavascriptTranslations disableOutputScriptTag=1 plugins='CoreHome'} + +document.write(''); +document.write(''); +document.write(''); +document.write(''); + +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); +document.write(''); + +var content = '{$content|escape:'javascript'}'; +document.write('document.write(content)'); + diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude.tpl b/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude.tpl new file mode 100644 index 00000000..b2416ace --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude.tpl @@ -0,0 +1,20 @@ + + +

This text is after the JS INCLUDE

+ + +

Test tag cloud in a JS include

+ +
+ +
+ +

This text is after the JS INCLUDE

+ +

Test calling the API in Javascript

+

using a javascript include. This is a dirty way (much better to ajax call the API!) but an interesting show case.

+ + +

This text is after the JS INCLUDE 2

+ + diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude2.tpl b/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude2.tpl new file mode 100644 index 00000000..fb5d288e --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/test_jsinclude2.tpl @@ -0,0 +1,27 @@ + + +

This text is after the JS INCLUDE

+ +

Test table in a JS include

+ + + + +

This text is after the JS INCLUDE

+ +

Test another table in a JS include

+ + + + +

This text is after the 2nd JS INCLUDE

+ +

Test tag cloud in a JS include

+ + + + +

This text is after the JS INCLUDE

+ + + diff --git a/oss/piwik/trunk/plugins/Widgetize/templates/widgetize.js b/oss/piwik/trunk/plugins/Widgetize/templates/widgetize.js new file mode 100644 index 00000000..5f8a3c36 --- /dev/null +++ b/oss/piwik/trunk/plugins/Widgetize/templates/widgetize.js @@ -0,0 +1,102 @@ +function widgetize() +{ + var self = this; + + this.getInputFormWithHtml = function(inputId, htmlEmbed) + { + return ''; + } + + this.getEmbedUrl = function( parameters, exportFormat ) + { + copyParameters = {}; + for(var variableName in parameters) { + copyParameters[variableName] = parameters[variableName]; + } + copyParameters['moduleToWidgetize'] = parameters['module']; + copyParameters['actionToWidgetize'] = parameters['action']; + delete copyParameters['action']; + delete copyParameters['module']; + var sourceUrl; + sourceUrl = document.location.protocol + '//' + document.location.hostname + document.location.pathname + '?'; + sourceUrl += "module=Widgetize" + + "&action="+exportFormat+ + "&"+piwikHelper.getQueryStringFromParameters(copyParameters)+ + "&idSite="+piwik.idSite+ + "&period="+piwik.period+ + "&date="+piwik.currentDateString+ + "&disableLink=1"; + return sourceUrl; + } + + this.deleteEmbedElements = function() + { + $('#exportButtons').remove(); + } + + this.htmlentities = function(s) + { + return s.replace( /[<>&]/g, function(m) { return "&" + m.charCodeAt(0) + ";"; }); + } + + this.callbackAddExportButtonsUnderWidget = function ( widgetUniqueId, + loadedWidgetElement) + { + widget = widgetsHelper.getWidgetObjectFromUniqueId(widgetUniqueId); + widgetName = widget["name"]; + widgetParameters = widget['parameters']; + + self.deleteEmbedElements(); + var exportButtonsElement = $(''); + + // We first build the HTML code that will load the widget in an IFRAME + var widgetIframeHtml = '
'+ + ''+ + '
'; + + // Add the input field containing the widget in an Iframe + $(exportButtonsElement).append( + '
'+ + ''+ + ''+ + self.getInputFormWithHtml('iframeEmbed', widgetIframeHtml)+ + ''+ + '
' + ); + + // Add the Flash Export if a flash is found in the widget + $(loadedWidgetElement) + .find('embed,object') + .each(function() { + var htmlEmbed = $(this).parent().html(); + + htmlEmbed = htmlEmbed.replace(/ (data=")/, ' $1' + unescape(piwik.piwik_url)); + htmlEmbed = htmlEmbed.replace(/ (value=")x-(data-file=)/, ' $1$2' + piwik.piwik_url + 'index.php'); + + $(exportButtonsElement).append( + '
'+ + ''+ + ''+ + self.getInputFormWithHtml('flashEmbed', htmlEmbed) + + ''+ + '
' + ); + }); + + // We then replace the div iframeDivToExport with the actual Iframe html + $('#iframeDivToExport') + .html(widgetIframeHtml); + + // Finally we append the content to the parent widget DIV + $(loadedWidgetElement) + .parent() + .append(exportButtonsElement); + + // JS is buggy at least on IE + //var widgetJS = '