Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@gmail.com>2015-07-03 03:54:27 +0300
committersgiehl <stefan@piwik.org>2015-10-06 18:25:13 +0300
commit9ba8f216fd7856ce5fef06bf82ecb8f8a2e7e630 (patch)
tree6ce07d18a85d00b39ab720abe042361c0775aead /plugins
parent8ccc9dc05da021325cdbf141a548637fa52f16b2 (diff)
generate pages instead of implementing them in each controller
Diffstat (limited to 'plugins')
-rw-r--r--plugins/API/API.php162
-rw-r--r--plugins/API/ProcessedReport.php86
-rw-r--r--plugins/API/Reports/Get.php6
-rw-r--r--plugins/API/SegmentMetadata.php167
-rw-r--r--plugins/API/WidgetMetadata.php282
-rw-r--r--plugins/API/tests/Unit/WidgetMetadataTest.php278
-rw-r--r--plugins/Actions/API.php3
-rw-r--r--plugins/Actions/Actions.php1
-rw-r--r--plugins/Actions/Categories/DownloadsSubcategory.php19
-rw-r--r--plugins/Actions/Categories/EntryPagesSubcategory.php19
-rw-r--r--plugins/Actions/Categories/ExitPagesSubcategory.php19
-rw-r--r--plugins/Actions/Categories/OutlinksSubcategory.php19
-rw-r--r--plugins/Actions/Categories/PageTitlesSubcategory.php19
-rw-r--r--plugins/Actions/Categories/PagesSubcategory.php19
-rw-r--r--plugins/Actions/Categories/SiteSearchSubcategory.php19
-rw-r--r--plugins/Actions/Controller.php45
-rw-r--r--plugins/Actions/Menu.php29
-rw-r--r--plugins/Actions/Reports/Base.php2
-rw-r--r--plugins/Actions/Reports/GetDownloads.php3
-rw-r--r--plugins/Actions/Reports/GetEntryPageTitles.php12
-rw-r--r--plugins/Actions/Reports/GetEntryPageUrls.php8
-rw-r--r--plugins/Actions/Reports/GetExitPageTitles.php14
-rw-r--r--plugins/Actions/Reports/GetExitPageUrls.php8
-rw-r--r--plugins/Actions/Reports/GetOutlinks.php3
-rw-r--r--plugins/Actions/Reports/GetPageTitles.php10
-rw-r--r--plugins/Actions/Reports/GetPageTitlesFollowingSiteSearch.php6
-rw-r--r--plugins/Actions/Reports/GetPageUrls.php11
-rw-r--r--plugins/Actions/Reports/GetPageUrlsFollowingSiteSearch.php8
-rw-r--r--plugins/Actions/Reports/GetSiteSearchCategories.php5
-rw-r--r--plugins/Actions/Reports/GetSiteSearchKeywords.php2
-rw-r--r--plugins/Actions/Reports/GetSiteSearchNoResultKeywords.php5
-rw-r--r--plugins/Actions/Reports/SiteSearchBase.php2
-rw-r--r--plugins/Actions/templates/indexSiteSearch.twig21
-rw-r--r--plugins/Contents/Categories/ContentsSubcategory.php19
-rw-r--r--plugins/Contents/Contents.php2
-rw-r--r--plugins/Contents/Controller.php51
-rw-r--r--plugins/Contents/Menu.php24
-rw-r--r--plugins/Contents/Reports/Base.php13
-rw-r--r--plugins/Contents/Reports/GetContentNames.php1
-rw-r--r--plugins/Contents/Reports/GetContentPieces.php2
-rw-r--r--plugins/Contents/Widgets/ContentsByDimension.php21
-rw-r--r--plugins/Contents/tests/System/expected/.gitkeep0
-rw-r--r--plugins/Contents/tests/System/expected/test_Contents_Contents.getContentNames_lastN__API.getProcessedReport_day.xml1
-rw-r--r--plugins/Contents/tests/System/expected/test_Contents_Contents.getContentPieces_lastN__API.getProcessedReport_day.xml1
-rw-r--r--plugins/CoreConsole/Commands/GenerateReport.php24
-rw-r--r--plugins/CoreConsole/Commands/GenerateWidget.php76
-rw-r--r--plugins/CoreHome/Categories/ActionsCategory.php17
-rw-r--r--plugins/CoreHome/Categories/DevicesSubcategory.php19
-rw-r--r--plugins/CoreHome/Categories/EngagementSubcategory.php19
-rw-r--r--plugins/CoreHome/Categories/SoftwareSubcategory.php19
-rw-r--r--plugins/CoreHome/Categories/VisitorsCategory.php17
-rw-r--r--plugins/CoreHome/Categories/VisitorsOverviewSubcategory.php19
-rw-r--r--plugins/CoreHome/Columns/Metrics/AverageTimeOnSite.php2
-rw-r--r--plugins/CoreHome/Controller.php35
-rw-r--r--plugins/CoreHome/CoreHome.php32
-rw-r--r--plugins/CoreHome/Widgets.php63
-rw-r--r--plugins/CoreHome/Widgets/GetDonateForm.php48
-rw-r--r--plugins/CoreHome/Widgets/GetPromoVideo.php44
-rw-r--r--plugins/CoreHome/angularjs/activity-indicator/activityindicator.directive.js31
-rw-r--r--plugins/CoreHome/angularjs/activity-indicator/activityindicator.html3
-rw-r--r--plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js4
-rw-r--r--plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js8
-rw-r--r--plugins/CoreHome/angularjs/common/filters/escape.js16
-rw-r--r--plugins/CoreHome/angularjs/common/services/global-ajax-queue.js14
-rw-r--r--plugins/CoreHome/angularjs/common/services/piwik-url.js54
-rw-r--r--plugins/CoreHome/angularjs/common/services/report-metadata-model.js52
-rw-r--r--plugins/CoreHome/angularjs/common/services/reporting-pages-model.js58
-rw-r--r--plugins/CoreHome/angularjs/history/history.service.js21
-rw-r--r--plugins/CoreHome/angularjs/http404check.js6
-rw-r--r--plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html2
-rw-r--r--plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js13
-rw-r--r--plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js74
-rw-r--r--plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js153
-rw-r--r--plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js125
-rw-r--r--plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html40
-rw-r--r--plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js31
-rw-r--r--plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js196
-rw-r--r--plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js56
-rw-r--r--plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html25
-rw-r--r--plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js31
-rw-r--r--plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html25
-rw-r--r--plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js67
-rw-r--r--plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html10
-rw-r--r--plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js32
-rw-r--r--plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html13
-rw-r--r--plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js134
-rw-r--r--plugins/CoreHome/angularjs/widget/widget.directive.html23
-rw-r--r--plugins/CoreHome/angularjs/widget/widget.directive.js93
-rw-r--r--plugins/CoreHome/javascripts/broadcast.js67
-rwxr-xr-xplugins/CoreHome/javascripts/corehome.js54
-rw-r--r--plugins/CoreHome/javascripts/dataTable.js1
-rw-r--r--plugins/CoreHome/javascripts/menu.js114
-rw-r--r--plugins/CoreHome/javascripts/menu_init.js19
-rw-r--r--plugins/CoreHome/javascripts/sparkline.js28
-rw-r--r--plugins/CoreHome/lang/en.json3
-rw-r--r--plugins/CoreHome/stylesheets/coreHome.less6
-rw-r--r--plugins/CoreHome/stylesheets/zen-mode.less16
-rw-r--r--plugins/CoreHome/templates/ReportsByDimension/_reportsByDimension.twig29
-rw-r--r--plugins/CoreHome/templates/_indexContent.twig3
-rw-r--r--plugins/CoreHome/templates/getDefaultIndexView.twig5
-rwxr-xr-xplugins/CoreHome/templates/widgetContainer.twig18
-rw-r--r--plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php41
-rw-r--r--plugins/CoreVisualizations/Visualizations/Sparkline.php4
-rw-r--r--plugins/CoreVisualizations/Visualizations/Sparklines.php147
-rw-r--r--plugins/CoreVisualizations/Visualizations/Sparklines/Config.php354
-rw-r--r--plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js35
-rw-r--r--plugins/CoreVisualizations/templates/_dataTableViz_sparklines.twig31
-rw-r--r--plugins/CoreVisualizations/templates/macros.twig32
-rw-r--r--plugins/CoreVisualizations/tests/Integration/SparklinesConfigTest.php128
-rw-r--r--plugins/CoreVisualizations/tests/Unit/SparklinesConfigTest.php130
-rw-r--r--plugins/CustomVariables/Categories/CustomVariablesSubcategory.php19
-rw-r--r--plugins/CustomVariables/Reports/Base.php2
-rw-r--r--plugins/CustomVariables/Reports/GetCustomVariables.php4
-rw-r--r--plugins/DBStats/Reports/GetMetricDataSummary.php3
-rw-r--r--plugins/DBStats/Reports/GetMetricDataSummaryByYear.php3
-rw-r--r--plugins/DBStats/Reports/GetReportDataSummary.php3
-rw-r--r--plugins/DBStats/Reports/GetReportDataSummaryByYear.php3
-rw-r--r--plugins/Dashboard/API.php54
-rw-r--r--plugins/Dashboard/Categories/DashboardCategory.php17
-rw-r--r--plugins/Dashboard/Controller.php17
-rw-r--r--plugins/Dashboard/Dashboard.php64
-rw-r--r--plugins/Dashboard/Menu.php19
-rw-r--r--plugins/Dashboard/Model.php8
-rw-r--r--plugins/Dashboard/angularjs/common/services/dashboards-model.js68
-rw-r--r--plugins/Dashboard/angularjs/dashboard/dashboard.directive.js103
-rw-r--r--plugins/Dashboard/javascripts/dashboard.js106
-rw-r--r--plugins/Dashboard/javascripts/dashboardObject.js143
-rwxr-xr-xplugins/Dashboard/javascripts/dashboardWidget.js9
-rw-r--r--plugins/Dashboard/javascripts/widgetMenu.js102
-rw-r--r--plugins/Dashboard/templates/embeddedIndex.twig8
-rw-r--r--plugins/DevicePlugins/Reports/Base.php2
-rw-r--r--plugins/DevicePlugins/Reports/GetPlugin.php5
-rw-r--r--plugins/DevicesDetection/Controller.php41
-rw-r--r--plugins/DevicesDetection/Menu.php7
-rw-r--r--plugins/DevicesDetection/Reports/Base.php2
-rw-r--r--plugins/DevicesDetection/Reports/GetBrand.php5
-rw-r--r--plugins/DevicesDetection/Reports/GetBrowserEngines.php5
-rw-r--r--plugins/DevicesDetection/Reports/GetBrowserVersions.php8
-rw-r--r--plugins/DevicesDetection/Reports/GetBrowsers.php10
-rw-r--r--plugins/DevicesDetection/Reports/GetModel.php3
-rw-r--r--plugins/DevicesDetection/Reports/GetOsFamilies.php8
-rw-r--r--plugins/DevicesDetection/Reports/GetOsVersions.php8
-rw-r--r--plugins/DevicesDetection/Reports/GetType.php3
-rw-r--r--plugins/DevicesDetection/templates/devices.twig19
-rw-r--r--plugins/DevicesDetection/templates/software.twig23
-rw-r--r--plugins/Ecommerce/Categories/EcommerceCategory.php17
-rw-r--r--plugins/Ecommerce/Categories/EcommerceLogSubcategory.php19
-rw-r--r--plugins/Ecommerce/Categories/EcommerceOverviewSubcategory.php19
-rw-r--r--plugins/Ecommerce/Categories/ProductSubcategory.php19
-rw-r--r--plugins/Ecommerce/Categories/SalesSubcategory.php19
-rw-r--r--plugins/Ecommerce/Controller.php117
-rw-r--r--plugins/Ecommerce/Menu.php41
-rw-r--r--plugins/Ecommerce/Reports/Base.php5
-rw-r--r--plugins/Ecommerce/Reports/BaseItem.php45
-rw-r--r--plugins/Ecommerce/Reports/GetItemsCategory.php3
-rw-r--r--plugins/Ecommerce/Reports/GetItemsName.php3
-rw-r--r--plugins/Ecommerce/Reports/GetItemsSku.php3
-rw-r--r--plugins/Ecommerce/Widgets.php35
-rw-r--r--plugins/Ecommerce/Widgets/GetEcommerceLog.php28
-rw-r--r--plugins/Ecommerce/Widgets/ProductsByDimension.php34
-rw-r--r--plugins/Ecommerce/templates/conversionOverview.twig15
-rw-r--r--plugins/Ecommerce/templates/ecommerceLog.twig3
-rw-r--r--plugins/Ecommerce/templates/getSparklines.twig55
-rw-r--r--plugins/Events/Categories/EventsSubcategory.php19
-rw-r--r--plugins/Events/Controller.php104
-rw-r--r--plugins/Events/Events.php3
-rw-r--r--plugins/Events/Menu.php21
-rw-r--r--plugins/Events/Reports/Base.php20
-rw-r--r--plugins/Events/Reports/GetAction.php1
-rw-r--r--plugins/Events/Reports/GetActionFromCategoryId.php2
-rw-r--r--plugins/Events/Reports/GetActionFromNameId.php2
-rw-r--r--plugins/Events/Reports/GetCategory.php1
-rw-r--r--plugins/Events/Reports/GetCategoryFromActionId.php2
-rw-r--r--plugins/Events/Reports/GetCategoryFromNameId.php2
-rw-r--r--plugins/Events/Reports/GetName.php1
-rw-r--r--plugins/Events/Reports/GetNameFromActionId.php2
-rw-r--r--plugins/Events/Reports/GetNameFromCategoryId.php2
-rw-r--r--plugins/Events/Widgets/EventsByDimension.php22
-rw-r--r--plugins/Events/templates/index.twig2
-rw-r--r--plugins/ExamplePlugin/Menu.php13
-rw-r--r--plugins/ExamplePlugin/Widgets.php67
-rw-r--r--plugins/ExamplePlugin/Widgets/MyExampleWidget.php80
-rw-r--r--plugins/ExampleReport/Reports/Base.php2
-rw-r--r--plugins/ExampleReport/Reports/GetExampleReport.php8
-rw-r--r--plugins/ExampleRssWidget/Widgets/RssChangelog.php (renamed from plugins/ExampleRssWidget/Widgets.php)30
-rw-r--r--plugins/ExampleRssWidget/Widgets/RssPiwik.php47
-rw-r--r--plugins/ExampleUI/API.php1
-rw-r--r--plugins/ExampleUI/Categories/ExampleUiCategory.php17
-rw-r--r--plugins/ExampleUI/Controller.php154
-rw-r--r--plugins/ExampleUI/Menu.php25
-rw-r--r--plugins/ExampleUI/Reports/Base.php19
-rw-r--r--plugins/ExampleUI/Reports/GetPlanetRatios.php74
-rw-r--r--plugins/ExampleUI/Reports/GetPlanetRatiosWithLogos.php44
-rw-r--r--plugins/ExampleUI/Reports/GetTemperatures.php93
-rw-r--r--plugins/ExampleUI/Reports/GetTemperaturesEvolution.php95
-rw-r--r--plugins/ExampleUI/lang/en.json8
-rw-r--r--plugins/ExampleUI/plugin.json17
-rw-r--r--plugins/Goals/API.php3
-rw-r--r--plugins/Goals/Categories/AddANewGoalSubcategory.php19
-rw-r--r--plugins/Goals/Categories/GoalsCategory.php17
-rw-r--r--plugins/Goals/Categories/GoalsOverviewSubcategory.php19
-rw-r--r--plugins/Goals/Categories/ManageGoalsSubcategory.php19
-rw-r--r--plugins/Goals/Controller.php251
-rw-r--r--plugins/Goals/Conversions.php45
-rw-r--r--plugins/Goals/Goals.php58
-rw-r--r--plugins/Goals/Menu.php43
-rw-r--r--plugins/Goals/Pages.php339
-rw-r--r--plugins/Goals/Reports/Base.php2
-rw-r--r--plugins/Goals/Reports/Get.php111
-rw-r--r--plugins/Goals/Widgets.php39
-rw-r--r--plugins/Goals/Widgets/AddNewGoal.php38
-rw-r--r--plugins/Goals/Widgets/EditGoals.php37
-rw-r--r--plugins/Goals/lang/en.json5
-rw-r--r--plugins/Goals/templates/_titleAndEvolutionGraph.twig86
-rw-r--r--plugins/Goals/templates/addNewGoal.twig1
-rw-r--r--plugins/Goals/templates/conversionOverview.twig15
-rw-r--r--plugins/Goals/templates/editGoals.twig2
-rw-r--r--plugins/Goals/templates/getGoalReportView.twig66
-rw-r--r--plugins/Goals/templates/getOverviewView.twig58
-rw-r--r--plugins/Insights/Widgets.php20
-rw-r--r--plugins/Insights/Widgets/GetInsightsOverview.php20
-rw-r--r--plugins/Insights/Widgets/GetOverallMoversAndShakers.php20
-rw-r--r--plugins/Live/Categories/LiveCategory.php17
-rw-r--r--plugins/Live/Categories/VisitorLogSubcategory.php19
-rw-r--r--plugins/Live/Reports/Base.php2
-rw-r--r--plugins/Live/Reports/GetLastVisitsDetails.php24
-rw-r--r--plugins/Live/Reports/GetSimpleLastVisitCount.php9
-rw-r--r--plugins/Live/Widgets.php27
-rw-r--r--plugins/Live/Widgets/GetVisitorProfilePopup.php33
-rw-r--r--plugins/Live/Widgets/Widget.php21
-rw-r--r--plugins/Live/templates/index.twig2
-rw-r--r--plugins/Morpheus/javascripts/piwikHelper.js8
-rw-r--r--plugins/Morpheus/stylesheets/ui/_map.less4
-rw-r--r--plugins/Morpheus/templates/layout.twig2
-rw-r--r--plugins/MultiSites/Categories/MultiSitesCategory.php17
-rw-r--r--plugins/MultiSites/Reports/Base.php2
-rw-r--r--plugins/Provider/Reports/GetProvider.php13
-rw-r--r--plugins/Referrers/Categories/AllReferrersSubcategory.php19
-rw-r--r--plugins/Referrers/Categories/CampaignsSubcategory.php19
-rw-r--r--plugins/Referrers/Categories/ReferrersCategory.php17
-rw-r--r--plugins/Referrers/Categories/ReferrersOverviewSubcategory.php19
-rw-r--r--plugins/Referrers/Categories/SearchEnginesSubcategory.php19
-rw-r--r--plugins/Referrers/Categories/WebsitesSubcategory.php19
-rw-r--r--plugins/Referrers/Controller.php192
-rw-r--r--plugins/Referrers/Menu.php23
-rw-r--r--plugins/Referrers/Reports/Base.php2
-rw-r--r--plugins/Referrers/Reports/GetAll.php12
-rw-r--r--plugins/Referrers/Reports/GetCampaigns.php4
-rw-r--r--plugins/Referrers/Reports/GetKeywords.php4
-rw-r--r--plugins/Referrers/Reports/GetReferrerType.php36
-rw-r--r--plugins/Referrers/Reports/GetSearchEngines.php3
-rw-r--r--plugins/Referrers/Reports/GetSocials.php11
-rw-r--r--plugins/Referrers/Reports/GetWebsites.php5
-rw-r--r--plugins/Referrers/Widgets.php24
-rw-r--r--plugins/Referrers/Widgets/GetKeywordsForPage.php23
-rw-r--r--plugins/Referrers/templates/allReferrers.twig11
-rw-r--r--plugins/Referrers/templates/getSearchEnginesAndKeywords.twig13
-rw-r--r--plugins/Referrers/templates/index.twig89
-rw-r--r--plugins/Referrers/templates/indexWebsites.twig13
-rw-r--r--plugins/Resolution/Reports/Base.php2
-rw-r--r--plugins/Resolution/Reports/GetConfiguration.php8
-rw-r--r--plugins/Resolution/Reports/GetResolution.php8
-rw-r--r--plugins/SEO/Widgets/GetRank.php (renamed from plugins/SEO/Widgets.php)15
-rw-r--r--plugins/Transitions/Controller.php6
-rw-r--r--plugins/Transitions/lang/en.json3
-rw-r--r--plugins/UserCountry/Categories/LocationsSubcategory.php19
-rw-r--r--plugins/UserCountry/Controller.php9
-rw-r--r--plugins/UserCountry/Menu.php6
-rw-r--r--plugins/UserCountry/Reports/Base.php2
-rw-r--r--plugins/UserCountry/Reports/GetCity.php5
-rw-r--r--plugins/UserCountry/Reports/GetContinent.php17
-rw-r--r--plugins/UserCountry/Reports/GetCountry.php3
-rw-r--r--plugins/UserCountry/Reports/GetRegion.php4
-rw-r--r--plugins/UserCountry/templates/getDistinctCountries.twig5
-rw-r--r--plugins/UserCountry/templates/index.twig29
-rw-r--r--plugins/UserCountryMap/Categories/RealTimeMapSubcategory.php19
-rw-r--r--plugins/UserCountryMap/Menu.php24
-rw-r--r--plugins/UserCountryMap/UserCountryMap.php17
-rw-r--r--plugins/UserCountryMap/Widgets/GetRealtimeMap.php29
-rw-r--r--plugins/UserCountryMap/Widgets/GetVisitorMap.php23
-rw-r--r--plugins/UserCountryMap/templates/visitorMap.twig2
-rw-r--r--plugins/UserLanguage/Reports/Base.php3
-rw-r--r--plugins/UserLanguage/Reports/GetLanguage.php6
-rw-r--r--plugins/UserLanguage/Reports/GetLanguageCode.php4
-rw-r--r--plugins/VisitFrequency/Controller.php63
-rw-r--r--plugins/VisitFrequency/Menu.php19
-rw-r--r--plugins/VisitFrequency/Reports/Get.php62
-rw-r--r--plugins/VisitFrequency/Widgets.php23
-rw-r--r--plugins/VisitFrequency/lang/en.json10
-rw-r--r--plugins/VisitFrequency/templates/_sparklines.twig39
-rw-r--r--plugins/VisitFrequency/templates/getSparklines.twig1
-rw-r--r--plugins/VisitFrequency/templates/index.twig9
-rw-r--r--plugins/VisitTime/Categories/TimesSubcategory.php19
-rw-r--r--plugins/VisitTime/Controller.php25
-rw-r--r--plugins/VisitTime/Menu.php19
-rw-r--r--plugins/VisitTime/Reports/Base.php2
-rw-r--r--plugins/VisitTime/Reports/GetByDayOfWeek.php10
-rw-r--r--plugins/VisitTime/Reports/GetVisitInformationPerLocalTime.php18
-rw-r--r--plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php7
-rw-r--r--plugins/VisitTime/templates/index.twig13
-rw-r--r--plugins/VisitorInterest/Controller.php24
-rw-r--r--plugins/VisitorInterest/Menu.php20
-rw-r--r--plugins/VisitorInterest/Reports/Base.php3
-rw-r--r--plugins/VisitorInterest/Reports/GetNumberOfVisitsByDaysSinceLast.php11
-rw-r--r--plugins/VisitorInterest/Reports/GetNumberOfVisitsByVisitCount.php1
-rw-r--r--plugins/VisitorInterest/Reports/GetNumberOfVisitsPerPage.php10
-rw-r--r--plugins/VisitorInterest/Reports/GetNumberOfVisitsPerVisitDuration.php10
-rw-r--r--plugins/VisitorInterest/templates/index.twig21
-rw-r--r--plugins/VisitsSummary/API.php3
-rw-r--r--plugins/VisitsSummary/Controller.php134
-rw-r--r--plugins/VisitsSummary/Menu.php20
-rw-r--r--plugins/VisitsSummary/Reports/Get.php147
-rw-r--r--plugins/VisitsSummary/Widgets.php22
-rw-r--r--plugins/VisitsSummary/Widgets/Index.php47
-rw-r--r--plugins/VisitsSummary/lang/en.json30
-rw-r--r--plugins/Widgetize/Controller.php4
-rw-r--r--plugins/Widgetize/templates/iframe.twig1
-rw-r--r--plugins/Widgetize/templates/index.twig1
-rw-r--r--plugins/Widgetize/tests/System/WidgetTest.php1932
-rw-r--r--plugins/ZenMode/ZenMode.php1
-rw-r--r--plugins/ZenMode/angularjs/zen-mode/zen-mode-disabler.js35
-rw-r--r--plugins/ZenMode/javascripts/zen-mode.js10
322 files changed, 8192 insertions, 3952 deletions
diff --git a/plugins/API/API.php b/plugins/API/API.php
index 4ea0cb4055..8245d0712e 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -10,7 +10,10 @@ namespace Piwik\Plugins\API;
use Piwik\API\Proxy;
use Piwik\API\Request;
-use Piwik\Columns\Dimension;
+use Piwik\Cache;
+use Piwik\CacheId;
+use Piwik\Category\CategoryList;
+use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\DataTable;
@@ -23,11 +26,13 @@ use Piwik\Period;
use Piwik\Period\Range;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Plugin\Report;
use Piwik\Plugins\API\DataTable\MergeDataTables;
use Piwik\Plugins\CoreAdminHome\CustomLogo;
use Piwik\Translation\Translator;
use Piwik\Measurable\Type\TypeManager;
use Piwik\Version;
+use Piwik\Widget\WidgetsList;
require_once PIWIK_INCLUDE_PATH . '/core/Config.php';
@@ -122,83 +127,20 @@ class API extends \Piwik\Plugin\API
{
$isAuthenticatedWithViewAccess = Piwik::isUserHasViewAccess($idSites) && !Piwik::isUserIsAnonymous();
- $segments = array();
- foreach (Dimension::getAllDimensions() as $dimension) {
- foreach ($dimension->getSegments() as $segment) {
- if ($segment->isRequiresAtLeastViewAccess()) {
- $segment->setPermission($isAuthenticatedWithViewAccess);
- }
+ $sites = (is_array($idSites) ? implode('.', $idSites) : (int) $idSites);
+ $cache = Cache::getTransientCache();
+ $cachKey = 'API.getSegmentsMetadata' . $sites . '_' . (int) $_hideImplementationData . '_' . (int) $isAuthenticatedWithViewAccess;
+ $cachKey = CacheId::pluginAware($cachKey);
- $segments[] = $segment->toArray();
- }
+ if ($cache->contains($cachKey)) {
+ return $cache->fetch($cachKey);
}
- /**
- * Triggered when gathering all available segment dimensions.
- *
- * This event can be used to make new segment dimensions available.
- *
- * **Example**
- *
- * public function getSegmentsMetadata(&$segments, $idSites)
- * {
- * $segments[] = array(
- * 'type' => 'dimension',
- * 'category' => Piwik::translate('General_Visit'),
- * 'name' => 'General_VisitorIP',
- * 'segment' => 'visitIp',
- * 'acceptedValues' => '13.54.122.1, etc.',
- * 'sqlSegment' => 'log_visit.location_ip',
- * 'sqlFilter' => array('Piwik\IP', 'P2N'),
- * 'permission' => $isAuthenticatedWithViewAccess,
- * );
- * }
- *
- * @param array &$dimensions The list of available segment dimensions. Append to this list to add
- * new segments. Each element in this list must contain the
- * following information:
- *
- * - **type**: Either `'metric'` or `'dimension'`. `'metric'` means
- * the value is a numeric and `'dimension'` means it is
- * a string. Also, `'metric'` values will be displayed
- * under **Visit (metrics)** in the Segment Editor.
- * - **category**: The segment category name. This can be an existing
- * segment category visible in the segment editor.
- * - **name**: The pretty name of the segment. Can be a translation token.
- * - **segment**: The segment name, eg, `'visitIp'` or `'searches'`.
- * - **acceptedValues**: A string describing one or two exacmple values, eg
- * `'13.54.122.1, etc.'`.
- * - **sqlSegment**: The table column this segment will segment by.
- * For example, `'log_visit.location_ip'` for the
- * **visitIp** segment.
- * - **sqlFilter**: A PHP callback to apply to segment values before
- * they are used in SQL.
- * - **permission**: True if the current user has view access to this
- * segment, false if otherwise.
- * @param array $idSites The list of site IDs we're getting the available segments
- * for. Some segments (such as Goal segments) depend on the
- * site.
- */
- Piwik::postEvent('API.getSegmentDimensionMetadata', array(&$segments, $idSites));
-
- foreach ($segments as &$segment) {
- $segment['name'] = Piwik::translate($segment['name']);
- $segment['category'] = Piwik::translate($segment['category']);
-
- if ($_hideImplementationData) {
- unset($segment['sqlFilter']);
- unset($segment['sqlFilterValue']);
- unset($segment['sqlSegment']);
-
- if (isset($segment['suggestedValuesCallback'])
- && !is_string($segment['suggestedValuesCallback'])
- ) {
- unset($segment['suggestedValuesCallback']);
- }
- }
- }
+ $metadata = new SegmentMetadata();
+ $segments = $metadata->getSegmentsMetadata($idSites, $_hideImplementationData, $isAuthenticatedWithViewAccess);
+
+ $cache->save($cachKey, $segments);
- usort($segments, array($this, 'sortSegments'));
return $segments;
}
@@ -219,32 +161,6 @@ class API extends \Piwik\Plugin\API
return $values;
}
- private function sortSegments($row1, $row2)
- {
- $customVarCategory = Piwik::translate('CustomVariables_CustomVariables');
-
- $columns = array('type', 'category', 'name', 'segment');
- foreach ($columns as $column) {
- // Keep segments ordered alphabetically inside categories..
- $type = -1;
- if ($column == 'name') $type = 1;
-
- $compare = $type * strcmp($row1[$column], $row2[$column]);
-
- // hack so that custom variables "page" are grouped together in the doc
- if ($row1['category'] == $customVarCategory
- && $row1['category'] == $row2['category']
- ) {
- $compare = strcmp($row1['segment'], $row2['segment']);
- return $compare;
- }
- if ($compare != 0) {
- return $compare;
- }
- }
- return $compare;
- }
-
/**
* Returns the url to application logo (~280x110px)
*
@@ -343,6 +259,41 @@ class API extends \Piwik\Plugin\API
}
/**
+ * Get a list of all pages that shall be shown in a Piwik UI including a list of all widgets that shall
+ * be shown within each page.
+ *
+ * @param int $idSite
+ * @return array
+ */
+ public function getReportPagesMetadata($idSite)
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+
+ $widgetsList = WidgetsList::get();
+ $categoryList = CategoryList::get();
+ $metadata = new WidgetMetadata();
+
+ return $metadata->getPagesMetadata($categoryList, $widgetsList);
+ }
+
+ /**
+ * Get a list of all widgetizable widgets.
+ *
+ * @param int $idSite
+ * @return array
+ */
+ public function getWidgetMetadata($idSite)
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+
+ $widgetsList = WidgetsList::get();
+ $categoryList = CategoryList::get();
+ $metadata = new WidgetMetadata();
+
+ return $metadata->getWidgetMetadata($categoryList, $widgetsList);
+ }
+
+ /**
* Get a combined report of the *.get API methods.
*/
public function get($idSite, $period, $date, $segment = false, $columns = false)
@@ -555,7 +506,12 @@ class API extends \Piwik\Plugin\API
if ($suggestedValuesCallbackRequiresTable) {
$values = call_user_func($segmentFound['suggestedValuesCallback'], $idSite, $maxSuggestionsToReturn, $table);
} else {
- $values = $this->getSegmentValuesFromVisitorLog($segmentName, $table);
+ // Cleanup data to return the top suggested (non empty) labels for this segment
+ $values = $table->getColumn($segmentName);
+
+ // Select also flattened keys (custom variables "page" scope, page URLs for one visit, page titles for one visit)
+ $valuesBis = $table->getColumnsStartingWith($segmentName . ColumnDelete::APPEND_TO_COLUMN_NAME_TO_KEEP);
+ $values = array_merge($values, $valuesBis);
}
$values = $this->getMostFrequentValues($values);
@@ -600,9 +556,7 @@ class API extends \Piwik\Plugin\API
// If you update this, also update flattenVisitorDetailsArray
$segmentsNeedActionsInfo = array('visitConvertedGoalId',
'pageUrl', 'pageTitle', 'siteSearchKeyword',
- 'entryPageTitle', 'entryPageUrl', 'exitPageTitle', 'exitPageUrl',
- 'outlinkUrl', 'downloadUrl'
- );
+ 'entryPageTitle', 'entryPageUrl', 'exitPageTitle', 'exitPageUrl');
$isCustomVariablePage = stripos($segmentName, 'customVariablePage') !== false;
$isEventSegment = stripos($segmentName, 'event') !== false;
$isContentSegment = stripos($segmentName, 'content') !== false;
diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php
index d9d315b4c0..65b59a2051 100644
--- a/plugins/API/ProcessedReport.php
+++ b/plugins/API/ProcessedReport.php
@@ -23,9 +23,11 @@ use Piwik\Metrics\Formatter;
use Piwik\Period;
use Piwik\Piwik;
use Piwik\Plugin\Report;
+use Piwik\Plugin\Reports;
use Piwik\Site;
use Piwik\Timer;
use Piwik\Url;
+use Piwik\Category\Category;
class ProcessedReport
{
@@ -166,77 +168,14 @@ class ProcessedReport
$availableReports = array();
- foreach (Report::getAllReports() as $report) {
+ $reports = new Reports();
+ foreach ($reports->getAllReports() as $report) {
$report->configureReportMetadata($availableReports, $parameters);
}
- /**
- * Triggered when gathering metadata for all available reports.
- *
- * Plugins that define new reports should use this event to make them available in via
- * the metadata API. By doing so, the report will become available in scheduled reports
- * as well as in the Piwik Mobile App. In fact, any third party app that uses the metadata
- * API will automatically have access to the new report.
- *
- * @param string &$availableReports The list of available reports. Append to this list
- * to make a report available.
- *
- * Every element of this array must contain the following
- * information:
- *
- * - **category**: A translated string describing the report's category.
- * - **name**: The translated display title of the report.
- * - **module**: The plugin of the report.
- * - **action**: The API method that serves the report.
- *
- * The following information is optional:
- *
- * - **dimension**: The report's [dimension](/guides/all-about-analytics-data#dimensions) if any.
- * - **metrics**: An array mapping metric names with their display names.
- * - **metricsDocumentation**: An array mapping metric names with their
- * translated documentation.
- * - **processedMetrics**: The array of metrics in the report that are
- * calculated using existing metrics. Can be set to
- * `false` if the report contains no processed
- * metrics.
- * - **order**: The order of the report in the list of reports
- * with the same category.
- *
- * @param array $parameters Contains the values of the sites and period we are
- * getting reports for. Some reports depend on this data.
- * For example, Goals reports depend on the site IDs being
- * requested. Contains the following information:
- *
- * - **idSites**: The array of site IDs we are getting reports for.
- * - **period**: The period type, eg, `'day'`, `'week'`, `'month'`,
- * `'year'`, `'range'`.
- * - **date**: A string date within the period or a date range, eg,
- * `'2013-01-01'` or `'2012-01-01,2013-01-01'`.
- *
- * TODO: put dimensions section in all about analytics data
- * @deprecated since 2.5.0 Use Report Classes instead.
- * @ignore
- */
- Piwik::postEvent('API.getReportMetadata', array(&$availableReports, $parameters));
-
- // TODO we can remove this one once we remove API.getReportMetadata event (except hideMetricsDoc)
foreach ($availableReports as &$availableReport) {
- // can be removed once we remove hook API.getReportMetadata
- if (!isset($availableReport['metrics'])) {
- $availableReport['metrics'] = Metrics::getDefaultMetrics();
- }
- // can be removed once we remove hook API.getReportMetadata
- if (!isset($availableReport['processedMetrics'])) {
- $availableReport['processedMetrics'] = Metrics::getDefaultProcessedMetrics();
- }
-
- if ($hideMetricsDoc) // remove metric documentation if it's not wanted
- {
+ if ($hideMetricsDoc) {
unset($availableReport['metricsDocumentation']);
- } else if (!isset($availableReport['metricsDocumentation'])) {
- // set metric documentation to default if it's not set
- // can be removed once we remove hook API.getReportMetadata
- $availableReport['metricsDocumentation'] = Metrics::getDefaultMetricsDocumentation();
}
}
@@ -270,6 +209,9 @@ class ProcessedReport
$columnsToRemove = $this->getColumnsToRemove();
foreach ($availableReports as &$availableReport) {
+ $availableReport['category'] = Piwik::translate($availableReport['category']);
+ $availableReport['subcategory'] = Piwik::translate($availableReport['subcategory']);
+
// Ensure all metrics have a translation
$metrics = $availableReport['metrics'];
$cleanedMetrics = array();
@@ -349,16 +291,8 @@ class ProcessedReport
*/
private static function sortReports($a, $b)
{
- static $order = null;
- if (is_null($order)) {
- $order = array();
- foreach (Report::$orderOfReports as $category) {
- $order[] = Piwik::translate($category);
- }
- }
- return ($category = strcmp(array_search($a['category'], $order), array_search($b['category'], $order))) == 0
- ? (@$a['order'] < @$b['order'] ? -1 : 1)
- : $category;
+ $reports = new Reports();
+ return $reports->compareCategories($a['category'], $a['subcategory'], $a['order'], $b['category'], $b['subcategory'], $b['order']);
}
public function getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false,
diff --git a/plugins/API/Reports/Get.php b/plugins/API/Reports/Get.php
index de087d0a86..61cded3856 100644
--- a/plugins/API/Reports/Get.php
+++ b/plugins/API/Reports/Get.php
@@ -10,6 +10,7 @@ namespace Piwik\Plugins\API\Reports;
use Piwik\Piwik;
use Piwik\Plugin\Report;
+use Piwik\Plugin\Reports;
class Get extends Report
{
@@ -29,7 +30,7 @@ class Get extends Report
$this->module = 'API';
$this->action = 'get';
- $this->category = 'API';
+ $this->categoryId = 'API';
$this->name = Piwik::translate('General_MainMetrics');
$this->documentation = '';
@@ -80,8 +81,9 @@ class Get extends Report
*/
private function getReportsToMerge()
{
+ $reports = new Reports();
$result = array();
- foreach (Report::getAllReportClasses() as $reportClass) {
+ foreach ($reports->getAllReportClasses() as $reportClass) {
if ($reportClass == 'Piwik\\Plugins\\API\\Reports\\Get') {
continue;
}
diff --git a/plugins/API/SegmentMetadata.php b/plugins/API/SegmentMetadata.php
new file mode 100644
index 0000000000..9d7e563bfb
--- /dev/null
+++ b/plugins/API/SegmentMetadata.php
@@ -0,0 +1,167 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\API;
+
+use Piwik\Columns\Dimension;
+use Piwik\Piwik;
+
+class SegmentMetadata
+{
+ public function getSegmentsMetadata($idSites = array(), $_hideImplementationData = true, $isAuthenticatedWithViewAccess)
+ {
+ $segments = array();
+
+ foreach (Dimension::getAllDimensions() as $dimension) {
+ foreach ($dimension->getSegments() as $segment) {
+ $segments[] = $segment->toArray();
+ }
+ }
+
+ /**
+ * Triggered when gathering all available segment dimensions.
+ *
+ * This event can be used to make new segment dimensions available.
+ *
+ * **Example**
+ *
+ * public function getSegmentsMetadata(&$segments, $idSites)
+ * {
+ * $segments[] = array(
+ * 'type' => 'dimension',
+ * 'category' => Piwik::translate('General_Visit'),
+ * 'name' => 'General_VisitorIP',
+ * 'segment' => 'visitIp',
+ * 'acceptedValues' => '13.54.122.1, etc.',
+ * 'sqlSegment' => 'log_visit.location_ip',
+ * 'sqlFilter' => array('Piwik\IP', 'P2N'),
+ * 'permission' => $isAuthenticatedWithViewAccess,
+ * );
+ * }
+ *
+ * @param array &$dimensions The list of available segment dimensions. Append to this list to add
+ * new segments. Each element in this list must contain the
+ * following information:
+ *
+ * - **type**: Either `'metric'` or `'dimension'`. `'metric'` means
+ * the value is a numeric and `'dimension'` means it is
+ * a string. Also, `'metric'` values will be displayed
+ * under **Visit (metrics)** in the Segment Editor.
+ * - **category**: The segment category name. This can be an existing
+ * segment category visible in the segment editor.
+ * - **name**: The pretty name of the segment. Can be a translation token.
+ * - **segment**: The segment name, eg, `'visitIp'` or `'searches'`.
+ * - **acceptedValues**: A string describing one or two exacmple values, eg
+ * `'13.54.122.1, etc.'`.
+ * - **sqlSegment**: The table column this segment will segment by.
+ * For example, `'log_visit.location_ip'` for the
+ * **visitIp** segment.
+ * - **sqlFilter**: A PHP callback to apply to segment values before
+ * they are used in SQL.
+ * - **permission**: True if the current user has view access to this
+ * segment, false if otherwise.
+ * @param array $idSites The list of site IDs we're getting the available segments
+ * for. Some segments (such as Goal segments) depend on the
+ * site.
+ */
+ Piwik::postEvent('API.getSegmentDimensionMetadata', array(&$segments, $idSites));
+
+ $segments[] = array(
+ 'type' => 'dimension',
+ 'category' => Piwik::translate('General_Visit'),
+ 'name' => 'General_UserId',
+ 'segment' => 'userId',
+ 'acceptedValues' => 'any non empty unique string identifying the user (such as an email address or a username).',
+ 'sqlSegment' => 'log_visit.user_id',
+ 'permission' => $isAuthenticatedWithViewAccess,
+ );
+
+ $segments[] = array(
+ 'type' => 'dimension',
+ 'category' => Piwik::translate('General_Visit'),
+ 'name' => 'General_VisitorID',
+ 'segment' => 'visitorId',
+ 'acceptedValues' => '34c31e04394bdc63 - any 16 Hexadecimal chars ID, which can be fetched using the Tracking API function getVisitorId()',
+ 'sqlSegment' => 'log_visit.idvisitor',
+ 'sqlFilterValue' => array('Piwik\Common', 'convertVisitorIdToBin'),
+ 'permission' => $isAuthenticatedWithViewAccess,
+ );
+
+ $segments[] = array(
+ 'type' => 'dimension',
+ 'category' => Piwik::translate('General_Visit'),
+ 'name' => Piwik::translate('General_Visit') . " ID",
+ 'segment' => 'visitId',
+ 'acceptedValues' => 'Any integer. ',
+ 'sqlSegment' => 'log_visit.idvisit',
+ 'permission' => $isAuthenticatedWithViewAccess,
+ );
+
+ $segments[] = array(
+ 'type' => 'metric',
+ 'category' => Piwik::translate('General_Visit'),
+ 'name' => 'General_VisitorIP',
+ 'segment' => 'visitIp',
+ 'acceptedValues' => '13.54.122.1. </code>Select IP ranges with notation: <code>visitIp>13.54.122.0;visitIp<13.54.122.255',
+ 'sqlSegment' => 'log_visit.location_ip',
+ 'sqlFilterValue' => array('Piwik\Network\IPUtils', 'stringToBinaryIP'),
+ 'permission' => $isAuthenticatedWithViewAccess,
+ );
+
+ foreach ($segments as &$segment) {
+ $segment['name'] = Piwik::translate($segment['name']);
+ $segment['category'] = Piwik::translate($segment['category']);
+
+ if ($_hideImplementationData) {
+ unset($segment['sqlFilter']);
+ unset($segment['sqlFilterValue']);
+ unset($segment['sqlSegment']);
+ }
+
+ if (isset($segment['suggestedValuesCallback'])
+ && !is_string($segment['suggestedValuesCallback'])
+ ) {
+ unset($segment['suggestedValuesCallback']);
+ }
+ }
+
+ usort($segments, array($this, 'sortSegments'));
+
+ return $segments;
+ }
+
+ private function sortSegments($row1, $row2)
+ {
+ $customVarCategory = Piwik::translate('CustomVariables_CustomVariables');
+
+ $columns = array('type', 'category', 'name', 'segment');
+
+ foreach ($columns as $column) {
+ // Keep segments ordered alphabetically inside categories..
+ $type = -1;
+ if ($column == 'name') $type = 1;
+
+ $compare = $type * strcmp($row1[$column], $row2[$column]);
+
+ // hack so that custom variables "page" are grouped together in the doc
+ if ($row1['category'] == $customVarCategory
+ && $row1['category'] == $row2['category']
+ ) {
+ $compare = strcmp($row1['segment'], $row2['segment']);
+ return $compare;
+ }
+
+ if ($compare != 0) {
+ return $compare;
+ }
+ }
+
+ return $compare;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/API/WidgetMetadata.php b/plugins/API/WidgetMetadata.php
new file mode 100644
index 0000000000..ef12800a39
--- /dev/null
+++ b/plugins/API/WidgetMetadata.php
@@ -0,0 +1,282 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\API;
+
+use Piwik\Category\CategoryList;
+use Piwik\Piwik;
+use Piwik\Report\ReportWidgetConfig;
+use Piwik\Category\Category;
+use Piwik\Category\Subcategory;
+use Piwik\Widget\WidgetContainerConfig;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Widget\WidgetsList;
+
+class WidgetMetadata
+{
+ public function getPagesMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
+ {
+ $this->createMissingCategoriesAndSubcategories($categoryList, $widgetsList->getWidgetConfigs());
+
+ return $this->buildPagesMetadata($categoryList, $widgetsList);
+ }
+
+ public function getWidgetMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
+ {
+ $this->createMissingCategoriesAndSubcategories($categoryList, $widgetsList->getWidgetConfigs());
+
+ $flat = array();
+
+ foreach ($widgetsList->getWidgetConfigs() as $widgetConfig) {
+
+ /** @var WidgetConfig[] $widgets */
+ $widgets = array($widgetConfig);
+ if ($widgetConfig instanceof WidgetContainerConfig) {
+ // so far we go only one level down, in theory these widgetConfigs could have again containers containing configs
+ $widgets = array_merge($widgets, $widgetConfig->getWidgetConfigs());
+ }
+
+ foreach ($widgets as $widget) {
+ // make sure to include only widgetizable widgets
+ if (!$widget->isWidgetizeable() || !$widget->getName()) {
+ continue;
+ }
+
+ $flat[] = $this->buildWidgetMetadata($widget, $categoryList);
+ }
+ }
+
+ usort($flat, array($this, 'sortWidgets'));
+
+ return $flat;
+ }
+
+ /**
+ * @param WidgetConfig $widget
+ * @param CategoryList|null $categoryList If null, no category information will be added to the widgets in first
+ * level (they will be added to nested widgets as potentially needed eg for
+ * widgets in ByDimensionView where they are needed to build the left menu)
+ * @return array
+ */
+ public function buildWidgetMetadata(WidgetConfig $widget, $categoryList = null)
+ {
+ $item = array(
+ 'name' => Piwik::translate($widget->getName())
+ );
+
+ if (isset($categoryList)) {
+ $category = $categoryList->getCategory($widget->getCategoryId());
+ $subcategory = $category ? $category->getSubcategory($widget->getSubcategoryId()) : null;
+
+ $item['category'] = $this->buildCategoryMetadata($category);
+ $item['subcategory'] = $this->buildSubcategoryMetadata($subcategory);
+ }
+
+ $item['module'] = $widget->getModule();
+ $item['action'] = $widget->getAction();
+ $item['order'] = $widget->getOrder();
+ $item['parameters'] = $widget->getParameters();
+ $item['uniqueId'] = $widget->getUniqueId();
+
+ $middleware = $widget->getMiddlewareParameters();
+
+ if (!empty($middleware)) {
+ $item['middlewareParameters'] = $middleware;
+ }
+
+ if ($widget instanceof ReportWidgetConfig) {
+ $item['viewDataTable'] = $widget->getViewDataTable();
+ $item['isReport'] = true;
+ }
+
+ if ($widget instanceof WidgetContainerConfig) {
+ $item['layout'] = $widget->getLayout();
+ $item['isContainer'] = true;
+
+ // we do not want to create categories to the inital categoryList. Otherwise we'd maybe display more pages
+ // etc.
+ $subCategoryList = new CategoryList();
+ $this->createMissingCategoriesAndSubcategories($subCategoryList, $widget->getWidgetConfigs());
+
+ $children = array();
+ foreach ($widget->getWidgetConfigs() as $widgetConfig) {
+ $children[] = $this->buildWidgetMetadata($widgetConfig, $subCategoryList);
+ }
+ $item['widgets'] = $children;
+ }
+
+ return $item;
+ }
+
+ private function sortWidgets($widgetA, $widgetB) {
+ $orderA = $widgetA['category']['order'];
+ $orderB = $widgetB['category']['order'];
+
+ if ($orderA === $orderB) {
+ if (!empty($widgetA['subcategory']['order']) && !empty($widgetB['subcategory']['order'])) {
+
+ $subOrderA = $widgetA['subcategory']['order'];
+ $subOrderB = $widgetB['subcategory']['order'];
+
+ if ($subOrderA === $subOrderB) {
+ return 0;
+ }
+
+ return $subOrderA > $subOrderB ? 1 : -1;
+
+ } elseif (!empty($orderA)) {
+
+ return 1;
+ }
+
+ return -1;
+ }
+
+ return $orderA > $orderB ? 1 : -1;
+ }
+
+ /**
+ * @param Category|null $category
+ * @return array
+ */
+ private function buildCategoryMetadata($category)
+ {
+ if (!isset($category)) {
+ return null;
+ }
+
+ return array(
+ 'id' => (string) $category->getId(),
+ 'name' => Piwik::translate($category->getId()),
+ 'order' => $category->getOrder(),
+ );
+ }
+
+ /**
+ * @param Subcategory|null $subcategory
+ * @return array
+ */
+ private function buildSubcategoryMetadata($subcategory)
+ {
+ if (!isset($subcategory)) {
+ return null;
+ }
+
+ return array(
+ 'id' => (string) $subcategory->getId(),
+ 'name' => Piwik::translate($subcategory->getName()),
+ 'order' => $subcategory->getOrder(),
+ );
+ }
+
+ /**
+ * @param CategoryList $categoryList
+ * @param WidgetConfig[] $widgetConfigs
+ */
+ private function createMissingCategoriesAndSubcategories($categoryList, $widgetConfigs)
+ {
+ // move reports into categories/subcategories and create missing ones if needed
+ foreach ($widgetConfigs as $widgetConfig) {
+ $categoryId = $widgetConfig->getCategoryId();
+ $subcategoryId = $widgetConfig->getSubcategoryId();
+
+ if (!$categoryId) {
+ continue;
+ }
+
+ if ($widgetConfig instanceof WidgetContainerConfig && !$widgetConfig->getWidgetConfigs()) {
+ // if a container does not contain any widgets, ignore it
+ continue;
+ }
+
+ if (!$categoryList->hasCategory($categoryId)) {
+ $categoryList->addCategory($this->createCategory($categoryId));
+ }
+
+ if (!$subcategoryId) {
+ continue;
+ }
+
+ $category = $categoryList->getCategory($categoryId);
+
+ if (!$category->hasSubcategory($subcategoryId)) {
+ $category->addSubcategory($this->createSubcategory($categoryId, $subcategoryId));
+ }
+ }
+ }
+
+ private function createCategory($categoryId)
+ {
+ $category = new Category();
+ $category->setId($categoryId);
+ return $category;
+ }
+
+ private function createSubcategory($categoryId, $subcategoryId)
+ {
+ $subcategory = new Subcategory();
+ $subcategory->setCategoryId($categoryId);
+ $subcategory->setId($subcategoryId);
+ return $subcategory;
+ }
+
+ /**
+ * @param CategoryList $categoryList
+ * @param WidgetsList $widgetsList
+ * @return array
+ */
+ private function buildPagesMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
+ {
+ $pages = array();
+
+ $widgets = array();
+ foreach ($widgetsList->getWidgetConfigs() as $config) {
+ $pageId = $this->buildPageId($config->getCategoryId(), $config->getSubcategoryId());
+
+ if (!isset($widgets[$pageId])) {
+ $widgets[$pageId] = array();
+ }
+
+ $widgets[$pageId][] = $config;
+ }
+
+ foreach ($categoryList->getCategories() as $category) {
+ foreach ($category->getSubcategories() as $subcategory) {
+ $pageId = $this->buildPageId($category->getId(), $subcategory->getId());
+
+ if (!empty($widgets[$pageId])) {
+ $pages[] = $this->buildPageMetadata($category, $subcategory, $widgets[$pageId]);
+ }
+ }
+ }
+
+ return $pages;
+ }
+
+ private function buildPageId($categoryId, $subcategoryId)
+ {
+ return $categoryId . '.' . $subcategoryId;
+ }
+
+ public function buildPageMetadata(Category $category, Subcategory $subcategory, $widgetConfigs)
+ {
+ $ca = array(
+ 'uniqueId' => $this->buildPageId($category->getId(), $subcategory->getId()),
+ 'category' => $this->buildCategoryMetadata($category),
+ 'subcategory' => $this->buildSubcategoryMetadata($subcategory),
+ 'widgets' => array()
+ );
+
+ foreach ($widgetConfigs as $config) {
+ $ca['widgets'][] = $this->buildWidgetMetadata($config);
+ }
+
+ return $ca;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/API/tests/Unit/WidgetMetadataTest.php b/plugins/API/tests/Unit/WidgetMetadataTest.php
new file mode 100644
index 0000000000..bb4379a010
--- /dev/null
+++ b/plugins/API/tests/Unit/WidgetMetadataTest.php
@@ -0,0 +1,278 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\API\tests\Unit;
+
+use Piwik\Category\Category;
+use Piwik\Category\CategoryList;
+use Piwik\Category\Subcategory;
+use Piwik\DataTable;
+use Piwik\Plugins\API\Renderer\Console;
+use Piwik\Plugins\API\WidgetMetadata;
+use Piwik\Plugins\CoreHome\CoreHome;
+use Piwik\Report\ReportWidgetConfig;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Widget\WidgetContainerConfig;
+
+/**
+ * @group Widget
+ * @group Widgets
+ * @group WidgetMetadata
+ * @group WidgetMetadataTest
+ */
+class WidgetMetadataTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @var WidgetMetadata
+ */
+ private $metadata;
+
+ public function setUp()
+ {
+ $this->metadata = new WidgetMetadata();
+ }
+
+ public function test_buildWidgetMetadata_ShouldGenerateMetadata()
+ {
+ $config = $this->createWidgetConfig('Test', 'CategoryId', 'SubcategoryId');
+ $list = $this->createCategoryList(array('CategoryId' => array('SubcategoryId')));
+ $metadata = $this->metadata->buildWidgetMetadata($config, $list);
+
+ $this->assertEquals(array(
+ 'name' => 'Test',
+ 'category' => array(
+ 'id' => 'CategoryId',
+ 'name' => 'CategoryId',
+ 'order' => 99,
+ ),
+ 'subcategory' => array(
+ 'id' => 'SubcategoryId',
+ 'name' => 'SubcategoryIdName',
+ 'order' => 99,
+ ),
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ 'order' => 99,
+ 'parameters' => array (
+ 'module' => 'CoreHome',
+ 'action' => 'render'
+ ),
+ 'uniqueId' => 'widgetCoreHomerender'
+ ), $metadata);
+ }
+
+ public function test_buildWidgetMetadata_ShouldSetCategoryAndSubcategoryToNull_IfBothGivenButNotExistInList()
+ {
+ $config = $this->createWidgetConfig('Test', 'CategoryId', 'SubcategoryId');
+ $list = $this->createCategoryList();
+ $metadata = $this->metadata->buildWidgetMetadata($config, $list);
+
+ $this->assertNull($metadata['category']);
+ $this->assertNull($metadata['subcategory']);
+ }
+
+ public function test_buildWidgetMetadata_ShouldSetSubcategoryToNull_IfCategoryGivenInListButSubcategoryNot()
+ {
+ $config = $this->createWidgetConfig('Test', 'CategoryId', 'SubcategoryId');
+ $list = $this->createCategoryList(array('CategoryId' => array()));
+ $metadata = $this->metadata->buildWidgetMetadata($config, $list);
+
+ $this->assertSame(array(
+ 'id' => 'CategoryId',
+ 'name' => 'CategoryId',
+ 'order' => 99,
+ ), $metadata['category']);
+ $this->assertNull($metadata['subcategory']);
+ }
+
+ public function test_buildWidgetMetadata_ShouldNotAddCategoryAndSubcategoryToNull_IfNoCategoryListGiven()
+ {
+ $config = $this->createWidgetConfig('Test', 'CategoryId', 'SubcategoryId');
+ $metadata = $this->metadata->buildWidgetMetadata($config);
+
+ $this->assertArrayNotHasKey('category', $metadata);
+ $this->assertArrayNotHasKey('subcategory', $metadata);
+ }
+
+ public function test_buildWidgetMetadata_ShouldAddOptionalMiddlewareParameters()
+ {
+ $config = $this->createWidgetConfig('Test', 'CategoryId', 'SubcategoryId');
+ $config->setMiddlewareParameters(array('module' => 'Goals', 'action' => 'hasAnyConversions'));
+ $metadata = $this->metadata->buildWidgetMetadata($config);
+
+ $this->assertSame(array('module' => 'Goals', 'action' => 'hasAnyConversions'), $metadata['middlewareParameters']);
+ }
+
+ public function test_buildWidgetMetadata_ShouldAddReportInformtion_IfReportWidgetConfigGiven()
+ {
+ $config = new ReportWidgetConfig();
+ $config->setDefaultViewDataTable('graph');
+ $metadata = $this->metadata->buildWidgetMetadata($config);
+
+ $this->assertSame('graph', $metadata['viewDataTable']);
+ $this->assertTrue($metadata['isReport']);
+ }
+
+ public function test_buildWidgetMetadata_ShouldAddContainerInformtion_IfWidgetContainerConfigGiven()
+ {
+ $config = new WidgetContainerConfig();
+ $config->setLayout('ByDimension');
+ $config->addWidgetConfig($this->createWidgetConfig('NestedName1', 'NestedCategory1', 'NestedSubcategory1'));
+ $config->addWidgetConfig($this->createWidgetConfig('NestedName2', 'NestedCategory2', 'NestedSubcategory2'));
+ $metadata = $this->metadata->buildWidgetMetadata($config);
+
+ $this->assertSame('ByDimension', $metadata['layout']);
+ $this->assertTrue($metadata['isContainer']);
+ $this->assertCount(2, $metadata['widgets']);
+
+ $widget1 = $metadata['widgets'][0];
+ $widget2 = $metadata['widgets'][1];
+ $this->assertSame(array(
+ 'name' => 'NestedName1',
+ 'category' => array (
+ 'id' => 'NestedCategory1',
+ 'name' => 'NestedCategory1',
+ 'order' => 99
+ ),
+ 'subcategory' => array (
+ 'id' => 'NestedSubcategory1',
+ 'name' => 'NestedSubcategory1',
+ 'order' => 99
+ ),
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ 'order' => 99,
+ 'parameters' => array (
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ ),
+ 'uniqueId' => 'widgetCoreHomerender'
+ ), $widget1);
+ $this->assertSame(array(
+ 'name' => 'NestedName2',
+ 'category' => array (
+ 'id' => 'NestedCategory2',
+ 'name' => 'NestedCategory2',
+ 'order' => 99
+ ),
+ 'subcategory' => array (
+ 'id' => 'NestedSubcategory2',
+ 'name' => 'NestedSubcategory2',
+ 'order' => 99
+ ),
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ 'order' => 99,
+ 'parameters' => array (
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ ),
+ 'uniqueId' => 'widgetCoreHomerender'
+ ), $widget2);
+ }
+
+ public function test_buildPageMetadata_ShouldAddContainerInformtion_IfWidgetContainerConfigGiven()
+ {
+ $config = new WidgetContainerConfig();
+ $config->setLayout('ByDimension');
+
+ $widgets = array(
+ $this->createWidgetConfig('NestedName1', 'NestedCategory1', 'NestedSubcategory1'),
+ $this->createWidgetConfig('NestedName2', 'NestedCategory2', 'NestedSubcategory1'),
+ );
+
+ $category = $this->createCategory('NestedCategory1');
+ $subcategory = $this->createSubcategory('NestedCategory1' ,'NestedSubcategory1');
+
+ $metadata = $this->metadata->buildPageMetadata($category, $subcategory, $widgets);
+
+ $this->assertSame(array(
+ 'uniqueId' => 'NestedCategory1.NestedSubcategory1',
+ 'category' => array (
+ 'id' => 'NestedCategory1',
+ 'name' => 'NestedCategory1',
+ 'order' => 99,
+ ),
+ 'subcategory' => array (
+ 'id' => 'NestedSubcategory1',
+ 'name' => 'NestedSubcategory1Name',
+ 'order' => 99,
+ ),
+ 'widgets' => array (
+ 0 => array ( // widgets should not have category / subcategory again, it's already present above
+ 'name' => 'NestedName1',
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ 'order' => 99,
+ 'parameters' => array (
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ ),
+ 'uniqueId' => 'widgetCoreHomerender',
+ ), array (
+ 'name' => 'NestedName2',
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ 'order' => 99,
+ 'parameters' => array (
+ 'module' => 'CoreHome',
+ 'action' => 'render',
+ ),
+ 'uniqueId' => 'widgetCoreHomerender'
+ )
+ )
+ ), $metadata);
+ }
+
+ private function createWidgetConfig($name, $categoryId, $subcategoryId = '')
+ {
+ $widgetConfig = new WidgetConfig();
+ $widgetConfig->setName($name);
+ $widgetConfig->setCategoryId($categoryId);
+ $widgetConfig->setSubcategoryId($subcategoryId);
+ $widgetConfig->setModule('CoreHome');
+ $widgetConfig->setAction('render');
+
+ return $widgetConfig;
+ }
+
+ private function createCategoryList($categories = array())
+ {
+ $list = new CategoryList();
+
+ foreach ($categories as $categoryId => $subcategoryIds) {
+ $category = $this->createCategory($categoryId);
+ $list->addCategory($category);
+
+ foreach ($subcategoryIds as $subcategoryId) {
+ $subcategory = $this->createSubcategory($categoryId, $subcategoryId);
+ $category->addSubcategory($subcategory);
+ }
+ }
+
+ return $list;
+ }
+
+ private function createSubcategory($categoryId, $subcategoryId)
+ {
+ $subcategory = new Subcategory();
+ $subcategory->setCategoryId($categoryId);
+ $subcategory->setId($subcategoryId);
+ $subcategory->setName($subcategoryId . 'Name');
+
+ return $subcategory;
+ }
+
+ private function createCategory($categoryId)
+ {
+ $category = new Category();
+ $category->setId($categoryId);
+ return $category;
+ }
+
+}
diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php
index 891400e122..e475f4240c 100644
--- a/plugins/Actions/API.php
+++ b/plugins/Actions/API.php
@@ -22,6 +22,7 @@ use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
use Piwik\Plugins\CustomVariables\API as APICustomVariables;
use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
+use Piwik\Plugin\Reports;
use Piwik\Tracker\Action;
use Piwik\Tracker\PageUrl;
@@ -55,7 +56,7 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasViewAccess($idSite);
- $report = Report::factory("Actions", "get");
+ $report = Reports::factory("Actions", "get");
$archive = Archive::build($idSite, $period, $date, $segment);
$requestedColumns = Piwik::getArrayFromApiParameter($columns);
diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php
index 557e4c77b8..bca4396271 100644
--- a/plugins/Actions/Actions.php
+++ b/plugins/Actions/Actions.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\Actions;
use Piwik\ArchiveProcessor;
use Piwik\Common;
use Piwik\Db;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Site;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
diff --git a/plugins/Actions/Categories/DownloadsSubcategory.php b/plugins/Actions/Categories/DownloadsSubcategory.php
new file mode 100644
index 0000000000..ac432b11d1
--- /dev/null
+++ b/plugins/Actions/Categories/DownloadsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class DownloadsSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'General_Downloads';
+ protected $order = 35;
+
+}
diff --git a/plugins/Actions/Categories/EntryPagesSubcategory.php b/plugins/Actions/Categories/EntryPagesSubcategory.php
new file mode 100644
index 0000000000..d4ee657b79
--- /dev/null
+++ b/plugins/Actions/Categories/EntryPagesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class EntryPagesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Actions_SubmenuPagesEntry';
+ protected $order = 10;
+
+}
diff --git a/plugins/Actions/Categories/ExitPagesSubcategory.php b/plugins/Actions/Categories/ExitPagesSubcategory.php
new file mode 100644
index 0000000000..b1a5a636c6
--- /dev/null
+++ b/plugins/Actions/Categories/ExitPagesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class ExitPagesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Actions_SubmenuPagesExit';
+ protected $order = 15;
+
+}
diff --git a/plugins/Actions/Categories/OutlinksSubcategory.php b/plugins/Actions/Categories/OutlinksSubcategory.php
new file mode 100644
index 0000000000..975ca9003e
--- /dev/null
+++ b/plugins/Actions/Categories/OutlinksSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class OutlinksSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'General_Outlinks';
+ protected $order = 30;
+
+}
diff --git a/plugins/Actions/Categories/PageTitlesSubcategory.php b/plugins/Actions/Categories/PageTitlesSubcategory.php
new file mode 100644
index 0000000000..1a88b6dbd2
--- /dev/null
+++ b/plugins/Actions/Categories/PageTitlesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class PageTitlesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Actions_SubmenuPageTitles';
+ protected $order = 20;
+
+}
diff --git a/plugins/Actions/Categories/PagesSubcategory.php b/plugins/Actions/Categories/PagesSubcategory.php
new file mode 100644
index 0000000000..5d407859b1
--- /dev/null
+++ b/plugins/Actions/Categories/PagesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class PagesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'General_Pages';
+ protected $order = 5;
+
+}
diff --git a/plugins/Actions/Categories/SiteSearchSubcategory.php b/plugins/Actions/Categories/SiteSearchSubcategory.php
new file mode 100644
index 0000000000..e915803679
--- /dev/null
+++ b/plugins/Actions/Categories/SiteSearchSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Actions\Categories;
+
+use Piwik\Category\Subcategory;
+
+class SiteSearchSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Actions_SubmenuSitesearch';
+ protected $order = 25;
+
+}
diff --git a/plugins/Actions/Controller.php b/plugins/Actions/Controller.php
deleted file mode 100644
index 51c7d7ba3a..0000000000
--- a/plugins/Actions/Controller.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Actions;
-
-use Piwik\Plugin\Report;
-use Piwik\View;
-
-/**
- * Actions controller
- *
- */
-class Controller extends \Piwik\Plugin\Controller
-{
- //
- // Actions that render whole pages
- //
-
- public function indexSiteSearch()
- {
- $view = new View('@Actions/indexSiteSearch');
-
- $keyword = Report::factory($this->pluginName, 'getSiteSearchKeywords');
- $noResult = Report::factory($this->pluginName, 'getSiteSearchNoResultKeywords');
- $pageUrls = Report::factory($this->pluginName, 'getPageUrlsFollowingSiteSearch');
-
- $view->keywords = $keyword->render();
- $view->noResultKeywords = $noResult->render();
- $view->pagesUrlsFollowingSiteSearch = $pageUrls->render();
-
- $categoryTrackingEnabled = Actions::isCustomVariablesPluginsEnabled();
- if ($categoryTrackingEnabled) {
- $categories = Report::factory($this->pluginName, 'getSiteSearchCategories');
- $view->categories = $categories->render();
- }
-
- return $view->render();
- }
-
-}
diff --git a/plugins/Actions/Menu.php b/plugins/Actions/Menu.php
deleted file mode 100644
index 9a7424b4e9..0000000000
--- a/plugins/Actions/Menu.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Actions;
-
-use Piwik\Common;
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addActionsItem('', $this->urlForAction('menuGetPageUrls'), 15);
-
- $idSite = Common::getRequestVar('idSite', 0, 'int');
- $idSites = Common::getRequestVar('idSites', '', 'string');
-
- $actions = new Actions();
- if ($actions->isSiteSearchEnabled($idSites, $idSite)) {
- $menu->addActionsItem('Actions_SubmenuSitesearch', $this->urlForAction('indexSiteSearch'), 5);
- }
- }
-
-}
diff --git a/plugins/Actions/Reports/Base.php b/plugins/Actions/Reports/Base.php
index 45c9c0af9c..20e35593d8 100644
--- a/plugins/Actions/Reports/Base.php
+++ b/plugins/Actions/Reports/Base.php
@@ -21,7 +21,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_Actions';
+ $this->categoryId = 'General_Actions';
$this->processedMetrics = false;
$this->recursiveLabelSeparator = '/';
}
diff --git a/plugins/Actions/Reports/GetDownloads.php b/plugins/Actions/Reports/GetDownloads.php
index f168cba878..92975b969e 100644
--- a/plugins/Actions/Reports/GetDownloads.php
+++ b/plugins/Actions/Reports/GetDownloads.php
@@ -26,8 +26,7 @@ class GetDownloads extends Base
$this->actionToLoadSubTables = $this->action;
$this->order = 9;
- $this->menuTitle = 'General_Downloads';
- $this->widgetTitle = 'General_Downloads';
+ $this->subcategoryId = 'General_Downloads';
}
public function getMetrics()
diff --git a/plugins/Actions/Reports/GetEntryPageTitles.php b/plugins/Actions/Reports/GetEntryPageTitles.php
index 7c029f4b02..9df1d74450 100644
--- a/plugins/Actions/Reports/GetEntryPageTitles.php
+++ b/plugins/Actions/Reports/GetEntryPageTitles.php
@@ -15,6 +15,9 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetEntryPageTitles extends Base
{
@@ -35,8 +38,11 @@ class GetEntryPageTitles extends Base
);
$this->order = 6;
$this->actionToLoadSubTables = $this->action;
+ }
- $this->widgetTitle = 'Actions_WidgetEntryPageTitles';
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig($factory->createWidget()->setName('Actions_WidgetEntryPageTitles'));
}
public function getProcessedMetrics()
@@ -79,8 +85,8 @@ class GetEntryPageTitles extends Base
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getPageTitles'),
- self::factory('Actions', 'getEntryPageUrls')
+ Reports::factory('Actions', 'getPageTitles'),
+ Reports::factory('Actions', 'getEntryPageUrls')
);
}
}
diff --git a/plugins/Actions/Reports/GetEntryPageUrls.php b/plugins/Actions/Reports/GetEntryPageUrls.php
index f3795db099..c934c7ab10 100644
--- a/plugins/Actions/Reports/GetEntryPageUrls.php
+++ b/plugins/Actions/Reports/GetEntryPageUrls.php
@@ -17,6 +17,9 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetEntryPageUrls extends Base
{
@@ -40,8 +43,7 @@ class GetEntryPageUrls extends Base
$this->actionToLoadSubTables = $this->action;
- $this->menuTitle = 'Actions_SubmenuPagesEntry';
- $this->widgetTitle = 'Actions_WidgetPagesEntry';
+ $this->subcategoryId = 'Actions_SubmenuPagesEntry';
}
public function getProcessedMetrics()
@@ -83,7 +85,7 @@ class GetEntryPageUrls extends Base
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getEntryPageTitles'),
+ Reports::factory('Actions', 'getEntryPageTitles'),
);
}
}
diff --git a/plugins/Actions/Reports/GetExitPageTitles.php b/plugins/Actions/Reports/GetExitPageTitles.php
index 6cc5b1f320..53f235209d 100644
--- a/plugins/Actions/Reports/GetExitPageTitles.php
+++ b/plugins/Actions/Reports/GetExitPageTitles.php
@@ -15,6 +15,9 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetExitPageTitles extends Base
{
@@ -37,8 +40,13 @@ class GetExitPageTitles extends Base
$this->order = 7;
$this->actionToLoadSubTables = $this->action;
+ }
- $this->widgetTitle = 'Actions_WidgetExitPageTitles';
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ // we have to do it manually since it's only done automatically if a subcategoryId is specified,
+ // we do not set a subcategoryId since this report is not supposed to be shown in the UI
+ $widgetsList->addWidgetConfig($factory->createWidget());
}
public function getProcessedMetrics()
@@ -86,8 +94,8 @@ class GetExitPageTitles extends Base
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getPageTitles'),
- self::factory('Actions', 'getExitPageUrls'),
+ Reports::factory('Actions', 'getPageTitles'),
+ Reports::factory('Actions', 'getExitPageUrls'),
);
}
}
diff --git a/plugins/Actions/Reports/GetExitPageUrls.php b/plugins/Actions/Reports/GetExitPageUrls.php
index 2ef5d7a957..f46ac478cd 100644
--- a/plugins/Actions/Reports/GetExitPageUrls.php
+++ b/plugins/Actions/Reports/GetExitPageUrls.php
@@ -17,6 +17,9 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetExitPageUrls extends Base
{
@@ -40,8 +43,7 @@ class GetExitPageUrls extends Base
$this->order = 4;
- $this->menuTitle = 'Actions_SubmenuPagesExit';
- $this->widgetTitle = 'Actions_WidgetPagesExit';
+ $this->subcategoryId = 'Actions_SubmenuPagesExit';
}
public function getProcessedMetrics()
@@ -97,7 +99,7 @@ class GetExitPageUrls extends Base
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getExitPageTitles'),
+ Reports::factory('Actions', 'getExitPageTitles'),
);
}
diff --git a/plugins/Actions/Reports/GetOutlinks.php b/plugins/Actions/Reports/GetOutlinks.php
index adf21c572c..fb5e13e831 100644
--- a/plugins/Actions/Reports/GetOutlinks.php
+++ b/plugins/Actions/Reports/GetOutlinks.php
@@ -29,8 +29,7 @@ class GetOutlinks extends Base
$this->actionToLoadSubTables = $this->action;
- $this->menuTitle = 'General_Outlinks';
- $this->widgetTitle = 'General_Outlinks';
+ $this->subcategoryId = 'General_Outlinks';
}
public function getMetrics()
diff --git a/plugins/Actions/Reports/GetPageTitles.php b/plugins/Actions/Reports/GetPageTitles.php
index 8f7e193f9b..0c70086611 100644
--- a/plugins/Actions/Reports/GetPageTitles.php
+++ b/plugins/Actions/Reports/GetPageTitles.php
@@ -17,6 +17,9 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetPageTitles extends Base
{
@@ -40,8 +43,7 @@ class GetPageTitles extends Base
$this->actionToLoadSubTables = $this->action;
- $this->menuTitle = 'Actions_SubmenuPageTitles';
- $this->widgetTitle = 'Actions_WidgetPageTitles';
+ $this->subcategoryId = 'Actions_SubmenuPageTitles';
}
public function getMetrics()
@@ -81,8 +83,8 @@ class GetPageTitles extends Base
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getEntryPageTitles'),
- self::factory('Actions', 'getExitPageTitles'),
+ Reports::factory('Actions', 'getEntryPageTitles'),
+ Reports::factory('Actions', 'getExitPageTitles'),
);
}
}
diff --git a/plugins/Actions/Reports/GetPageTitlesFollowingSiteSearch.php b/plugins/Actions/Reports/GetPageTitlesFollowingSiteSearch.php
index 657e88211d..3d50ba4f95 100644
--- a/plugins/Actions/Reports/GetPageTitlesFollowingSiteSearch.php
+++ b/plugins/Actions/Reports/GetPageTitlesFollowingSiteSearch.php
@@ -15,6 +15,7 @@ use Piwik\Plugins\Actions\Columns\Metrics\AveragePageGenerationTime;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
+use Piwik\Plugin\Reports;
class GetPageTitlesFollowingSiteSearch extends SiteSearchBase
{
@@ -32,7 +33,8 @@ class GetPageTitlesFollowingSiteSearch extends SiteSearchBase
new AveragePageGenerationTime()
);
$this->order = 19;
- $this->widgetTitle = 'Actions_WidgetPageTitlesFollowingSearch';
+
+ $this->subcategoryId = 'Actions_SubmenuSitesearch';
}
public function configureView(ViewDataTable $view)
@@ -80,7 +82,7 @@ class GetPageTitlesFollowingSiteSearch extends SiteSearchBase
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getPageUrlsFollowingSiteSearch'),
+ Reports::factory('Actions', 'getPageUrlsFollowingSiteSearch'),
);
}
}
diff --git a/plugins/Actions/Reports/GetPageUrls.php b/plugins/Actions/Reports/GetPageUrls.php
index 0af899ef0e..2c850a5339 100644
--- a/plugins/Actions/Reports/GetPageUrls.php
+++ b/plugins/Actions/Reports/GetPageUrls.php
@@ -15,6 +15,8 @@ use Piwik\Plugins\Actions\Columns\Metrics\BounceRate;
use Piwik\Plugins\Actions\Columns\PageUrl;
use Piwik\Plugins\Actions\Columns\Metrics\ExitRate;
use Piwik\Plugins\Actions\Columns\Metrics\AverageTimeOnPage;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetPageUrls extends Base
{
@@ -37,10 +39,13 @@ class GetPageUrls extends Base
new AveragePageGenerationTime()
);
- $this->segmentSql = 'log_visit.visit_entry_idaction_url';
+ $this->segmentSql = 'log_visit.visit_entry_idaction_url';
+ $this->subcategoryId = 'General_Pages';
+ }
- $this->menuTitle = 'General_Pages';
- $this->widgetTitle = 'General_Pages';
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig($factory->createWidget()->setName($this->subcategoryId));
}
public function getMetrics()
diff --git a/plugins/Actions/Reports/GetPageUrlsFollowingSiteSearch.php b/plugins/Actions/Reports/GetPageUrlsFollowingSiteSearch.php
index 2d8ba1a3a2..063d3855b5 100644
--- a/plugins/Actions/Reports/GetPageUrlsFollowingSiteSearch.php
+++ b/plugins/Actions/Reports/GetPageUrlsFollowingSiteSearch.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\Actions\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Actions\Columns\DestinationPage;
+use Piwik\Plugin\Reports;
class GetPageUrlsFollowingSiteSearch extends GetPageTitlesFollowingSiteSearch
{
@@ -20,8 +21,9 @@ class GetPageUrlsFollowingSiteSearch extends GetPageTitlesFollowingSiteSearch
$this->dimension = new DestinationPage();
$this->name = Piwik::translate('Actions_WidgetPageUrlsFollowingSearch');
$this->documentation = Piwik::translate('Actions_SiteSearchFollowingPagesDoc') . '<br/>' . Piwik::translate('General_UsePlusMinusIconsDocumentation');
- $this->order = 18;
- $this->widgetTitle = 'Actions_WidgetPageUrlsFollowingSearch';
+ $this->order = 16;
+
+ $this->subcategoryId = 'Actions_SubmenuSitesearch';
}
public function configureView(ViewDataTable $view)
@@ -34,7 +36,7 @@ class GetPageUrlsFollowingSiteSearch extends GetPageTitlesFollowingSiteSearch
public function getRelatedReports()
{
return array(
- self::factory('Actions', 'getPageTitlesFollowingSiteSearch'),
+ Reports::factory('Actions', 'getPageTitlesFollowingSiteSearch'),
);
}
}
diff --git a/plugins/Actions/Reports/GetSiteSearchCategories.php b/plugins/Actions/Reports/GetSiteSearchCategories.php
index 6d41e3c334..5388ff9198 100644
--- a/plugins/Actions/Reports/GetSiteSearchCategories.php
+++ b/plugins/Actions/Reports/GetSiteSearchCategories.php
@@ -23,8 +23,9 @@ class GetSiteSearchCategories extends SiteSearchBase
$this->name = Piwik::translate('Actions_WidgetSearchCategories');
$this->documentation = Piwik::translate('Actions_SiteSearchCategories1') . '<br/>' . Piwik::translate('Actions_SiteSearchCategories2');
$this->metrics = array('nb_visits', 'nb_pages_per_search', 'exit_rate');
- $this->order = 17;
- $this->widgetTitle = 'Actions_WidgetSearchCategories';
+ $this->order = 20;
+
+ $this->subcategoryId = 'Actions_SubmenuSitesearch';
}
protected function isEnabledForIdSites($idSites, $idSite)
diff --git a/plugins/Actions/Reports/GetSiteSearchKeywords.php b/plugins/Actions/Reports/GetSiteSearchKeywords.php
index d88684cd15..dc4b5e2d16 100644
--- a/plugins/Actions/Reports/GetSiteSearchKeywords.php
+++ b/plugins/Actions/Reports/GetSiteSearchKeywords.php
@@ -33,7 +33,7 @@ class GetSiteSearchKeywords extends SiteSearchBase
new AveragePageGenerationTime()
);
$this->order = 15;
- $this->widgetTitle = 'Actions_WidgetSearchKeywords';
+ $this->subcategoryId = 'Actions_SubmenuSitesearch';
}
public function getMetrics()
diff --git a/plugins/Actions/Reports/GetSiteSearchNoResultKeywords.php b/plugins/Actions/Reports/GetSiteSearchNoResultKeywords.php
index 94b19e8566..c1c01ca504 100644
--- a/plugins/Actions/Reports/GetSiteSearchNoResultKeywords.php
+++ b/plugins/Actions/Reports/GetSiteSearchNoResultKeywords.php
@@ -31,8 +31,9 @@ class GetSiteSearchNoResultKeywords extends SiteSearchBase
new ExitRate(),
new AveragePageGenerationTime()
);
- $this->order = 16;
- $this->widgetTitle = 'Actions_WidgetSearchNoResultKeywords';
+ $this->order = 18;
+
+ $this->subcategoryId = 'Actions_SubmenuSitesearch';
}
public function getMetrics()
diff --git a/plugins/Actions/Reports/SiteSearchBase.php b/plugins/Actions/Reports/SiteSearchBase.php
index e30a2243d8..d4715e04e6 100644
--- a/plugins/Actions/Reports/SiteSearchBase.php
+++ b/plugins/Actions/Reports/SiteSearchBase.php
@@ -18,7 +18,7 @@ abstract class SiteSearchBase extends Base
protected function init()
{
parent::init();
- $this->category = 'Actions_SubmenuSitesearch';
+ $this->categoryId = 'General_Actions';
}
public function isEnabled()
diff --git a/plugins/Actions/templates/indexSiteSearch.twig b/plugins/Actions/templates/indexSiteSearch.twig
deleted file mode 100644
index 8d9eaa0909..0000000000
--- a/plugins/Actions/templates/indexSiteSearch.twig
+++ /dev/null
@@ -1,21 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchKeywords'|translate }}</h2>
- {{ keywords|raw }}
-
- <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchNoResultKeywords'|translate }}</h2>
- {{ noResultKeywords|raw }}
-
- {% if categories is defined %}
- <h2 piwik-enriched-headline>{{ 'Actions_WidgetSearchCategories'|translate }}</h2>
- {{ categories|raw }}
- {% endif %}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Actions_WidgetPageUrlsFollowingSearch'|translate }}</h2>
- {{ pagesUrlsFollowingSiteSearch|raw }}
- </div>
-
-</div>
diff --git a/plugins/Contents/Categories/ContentsSubcategory.php b/plugins/Contents/Categories/ContentsSubcategory.php
new file mode 100644
index 0000000000..735d376e4f
--- /dev/null
+++ b/plugins/Contents/Categories/ContentsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Contents\Categories;
+
+use Piwik\Category\Subcategory;
+
+class ContentsSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Contents_Contents';
+ protected $order = 45;
+
+}
diff --git a/plugins/Contents/Contents.php b/plugins/Contents/Contents.php
index 10536930af..49df9a730b 100644
--- a/plugins/Contents/Contents.php
+++ b/plugins/Contents/Contents.php
@@ -18,7 +18,7 @@ class Contents extends \Piwik\Plugin
return array(
'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
- 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
+ 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles'
);
}
diff --git a/plugins/Contents/Controller.php b/plugins/Contents/Controller.php
deleted file mode 100644
index a17ec3fdce..0000000000
--- a/plugins/Contents/Controller.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Contents;
-
-use Piwik\Plugin\Report;
-use Piwik\View;
-
-class Controller extends \Piwik\Plugin\Controller
-{
-
- public function index()
- {
- $reportsView = new View\ReportsByDimension('Contents');
-
- /** @var \Piwik\Plugin\Report[] $reports */
- $contentNames = Report::factory($this->pluginName, 'getContentNames');
- $contentPieces = Report::factory($this->pluginName, 'getContentPieces');
- $reports = array($contentNames, $contentPieces);
-
- foreach($reports as $report) {
- $reportsView->addReport(
- $report->getCategory(),
- $report->getName(),
- 'Contents.' . Report::PREFIX_ACTION_IN_MENU . ucfirst($report->getAction())
- );
- }
-
- return $reportsView->render();
- }
-
- public function menuGetContentNames()
- {
- $report = Report::factory($this->pluginName, 'getContentNames');
-
- return View::singleReport($report->getName(), $report->render());
- }
-
- public function menuGetContentPieces()
- {
- $report = Report::factory($this->pluginName, 'getContentPieces');
-
- return View::singleReport($report->getName(), $report->render());
- }
-
-}
diff --git a/plugins/Contents/Menu.php b/plugins/Contents/Menu.php
deleted file mode 100644
index 2e0d25bb7f..0000000000
--- a/plugins/Contents/Menu.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Contents;
-
-use Piwik\Menu\MenuReporting;
-
-/**
- * This class allows you to add, remove or rename menu items.
- * To configure a menu (such as Admin Menu, Reporting Menu, User Menu...) simply call the corresponding methods as
- * described in the API-Reference http://developer.piwik.org/api-reference/Piwik/Menu/MenuAbstract
- */
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addActionsItem('Contents_Contents', array('module' => 'Contents', 'action' => 'index'), $orderId = 40);
- }
-}
diff --git a/plugins/Contents/Reports/Base.php b/plugins/Contents/Reports/Base.php
index f07baf973d..e323bebdbe 100644
--- a/plugins/Contents/Reports/Base.php
+++ b/plugins/Contents/Reports/Base.php
@@ -8,18 +8,27 @@
*/
namespace Piwik\Plugins\Contents\Reports;
-use Piwik\Columns\Dimension;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Contents\Dimensions;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
abstract class Base extends Report
{
protected function init()
{
- $this->category = 'General_Actions';
+ $this->categoryId = 'General_Actions';
+ $this->subcategoryId = 'Contents_Contents';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widget = $factory->createWidget();
+
+ $widgetsList->addToContainerWidget('Contents', $widget);
}
/**
diff --git a/plugins/Contents/Reports/GetContentNames.php b/plugins/Contents/Reports/GetContentNames.php
index d217af5d71..6afb8e071e 100644
--- a/plugins/Contents/Reports/GetContentNames.php
+++ b/plugins/Contents/Reports/GetContentNames.php
@@ -32,7 +32,6 @@ class GetContentNames extends Base
$this->order = 35;
$this->actionToLoadSubTables = 'getContentNames';
- $this->widgetTitle = 'Contents_ContentName';
$this->metrics = array('nb_impressions', 'nb_interactions');
$this->processedMetrics = array(new InteractionRate());
}
diff --git a/plugins/Contents/Reports/GetContentPieces.php b/plugins/Contents/Reports/GetContentPieces.php
index 7ab3f1ed1c..ede8da9405 100644
--- a/plugins/Contents/Reports/GetContentPieces.php
+++ b/plugins/Contents/Reports/GetContentPieces.php
@@ -32,8 +32,6 @@ class GetContentPieces extends Base
$this->order = 36;
$this->actionToLoadSubTables = 'getContentPieces';
- $this->widgetTitle = 'Contents_ContentPiece';
-
$this->metrics = array('nb_impressions', 'nb_interactions');
$this->processedMetrics = array(new InteractionRate());
}
diff --git a/plugins/Contents/Widgets/ContentsByDimension.php b/plugins/Contents/Widgets/ContentsByDimension.php
new file mode 100644
index 0000000000..3f2291e8d8
--- /dev/null
+++ b/plugins/Contents/Widgets/ContentsByDimension.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Contents\Widgets;
+
+use Piwik\Plugins\CoreHome\CoreHome;
+use Piwik\Widget\WidgetContainerConfig;
+
+class ContentsByDimension extends WidgetContainerConfig
+{
+ protected $layout = CoreHome::WIDGET_CONTAINER_LAYOUT_BY_DIMENSION;
+ protected $id = 'Contents';
+ protected $categoryId = 'General_Actions';
+ protected $subcategoryId = 'Contents_Contents';
+
+}
diff --git a/plugins/Contents/tests/System/expected/.gitkeep b/plugins/Contents/tests/System/expected/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/Contents/tests/System/expected/.gitkeep
diff --git a/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentNames_lastN__API.getProcessedReport_day.xml b/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentNames_lastN__API.getProcessedReport_day.xml
index 5c1cc502a7..8eed477e8b 100644
--- a/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentNames_lastN__API.getProcessedReport_day.xml
+++ b/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentNames_lastN__API.getProcessedReport_day.xml
@@ -4,6 +4,7 @@
<prettyDate>January 3 – 9, 2010</prettyDate>
<metadata>
<category>Actions</category>
+ <subcategory>Contents</subcategory>
<name>Content Name</name>
<module>Contents</module>
<action>getContentNames</action>
diff --git a/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentPieces_lastN__API.getProcessedReport_day.xml b/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentPieces_lastN__API.getProcessedReport_day.xml
index b43860be63..f0115ea581 100644
--- a/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentPieces_lastN__API.getProcessedReport_day.xml
+++ b/plugins/Contents/tests/System/expected/test_Contents_Contents.getContentPieces_lastN__API.getProcessedReport_day.xml
@@ -4,6 +4,7 @@
<prettyDate>January 3 – 9, 2010</prettyDate>
<metadata>
<category>Actions</category>
+ <subcategory>Contents</subcategory>
<name>Content Piece</name>
<module>Contents</module>
<action>getContentPieces</action>
diff --git a/plugins/CoreConsole/Commands/GenerateReport.php b/plugins/CoreConsole/Commands/GenerateReport.php
index 9eb7313400..3f9fda4939 100644
--- a/plugins/CoreConsole/Commands/GenerateReport.php
+++ b/plugins/CoreConsole/Commands/GenerateReport.php
@@ -10,8 +10,10 @@
namespace Piwik\Plugins\CoreConsole\Commands;
use Piwik\Columns\Dimension;
+use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugin\Report;
+use Piwik\Plugin\Reports;
use Piwik\Translate;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -67,8 +69,8 @@ class GenerateReport extends GeneratePluginBase
$this->copyTemplateToPlugin($exampleFolder, $pluginName, $replace, $whitelistFiles);
$this->writeSuccessMessage($output, array(
- sprintf('Reports/%s.php for %s generated.', ucfirst($apiName), $pluginName),
- 'You should now implement the method called "' . lcfirst($apiName) . '" in API.php',
+ sprintf('plugins/%s/Reports/%s.php for %s generated.', $pluginName, ucfirst($apiName)),
+ 'You should now implement the method called <comment>"' . lcfirst($apiName) . '()"</comment> in API.php',
// 'Read more about this here: link to developer guide',
'Enjoy!'
));
@@ -78,8 +80,10 @@ class GenerateReport extends GeneratePluginBase
{
$order = 1;
- foreach (Report::getAllReports() as $report) {
- if ($report->getCategory() === $category) {
+ $reports = new Reports();
+
+ foreach ($reports->getAllReports() as $report) {
+ if ($report->getCategoryId() === $category) {
if ($report->getOrder() > $order) {
$order = $report->getOrder() + 1;
}
@@ -189,10 +193,12 @@ class GenerateReport extends GeneratePluginBase
$category = $input->getOption('category');
+ $reports = new Reports();
+
$categories = array();
- foreach (Report::getAllReports() as $report) {
- if ($report->getCategory()) {
- $categories[] = $report->getCategory();
+ foreach ($reports->getAllReports() as $report) {
+ if ($report->getCategoryId()) {
+ $categories[] = Piwik::translate($report->getCategoryId());
}
}
$categories = array_values(array_unique($categories));
@@ -226,7 +232,9 @@ class GenerateReport extends GeneratePluginBase
$dimensions = array();
$dimensionNames = array();
- foreach (Report::getAllReports() as $report) {
+ $reports = new Reports();
+
+ foreach ($reports->getAllReports() as $report) {
$dimension = $report->getDimension();
if (is_object($dimension)) {
$name = $dimension->getName();
diff --git a/plugins/CoreConsole/Commands/GenerateWidget.php b/plugins/CoreConsole/Commands/GenerateWidget.php
index da4f8e349d..05f92bd4af 100644
--- a/plugins/CoreConsole/Commands/GenerateWidget.php
+++ b/plugins/CoreConsole/Commands/GenerateWidget.php
@@ -10,8 +10,8 @@
namespace Piwik\Plugins\CoreConsole\Commands;
use Piwik\Piwik;
-use Piwik\Plugin\Widgets;
use Piwik\Translate;
+use Piwik\Widget\WidgetsList;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -25,6 +25,7 @@ class GenerateWidget extends GeneratePluginBase
$this->setName('generate:widget')
->setDescription('Adds a plugin widget class to an existing plugin')
->addOption('pluginname', null, InputOption::VALUE_REQUIRED, 'The name of an existing plugin which does not have any widgets defined yet')
+ ->addOption('widgetname', null, InputOption::VALUE_REQUIRED, 'The name of the widget you want to create')
->addOption('category', null, InputOption::VALUE_REQUIRED, 'The name of the category the widget should belong to');
}
@@ -33,6 +34,7 @@ class GenerateWidget extends GeneratePluginBase
$pluginName = $this->getPluginName($input, $output);
$this->checkAndUpdateRequiredPiwikVersion($pluginName, $output);
+ $widgetName = $this->getWidgetName($input, $output);
$category = $this->getCategory($input, $output);
if ($category === Piwik::translate($category)) {
@@ -40,26 +42,78 @@ class GenerateWidget extends GeneratePluginBase
$category = $this->makeTranslationIfPossible($pluginName, $category);
}
+ $widgetMethod = $this->getWidgetMethodName($widgetName);
+ $widgetClass = ucfirst($widgetMethod);
+
$exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin';
- $replace = array('ExamplePlugin' => $pluginName,
- 'Example Category' => $category);
- $whitelistFiles = array('/Widgets.php');
+ $replace = array('ExamplePlugin' => $pluginName,
+ 'MyExampleWidget' => $widgetClass,
+ 'Example Widget Name' => $this->makeTranslationIfPossible($pluginName, $widgetName),
+ 'Example Widgets' => $category);
+ $whitelistFiles = array('/Widgets', '/Widgets/MyExampleWidget.php');
$this->copyTemplateToPlugin($exampleFolder, $pluginName, $replace, $whitelistFiles);
$this->writeSuccessMessage($output, array(
- sprintf('Widgets.php for %s generated.', $pluginName),
- 'You can now start defining your plugin widgets',
+ sprintf('plugins/%s/Widgets/%s.php generated.', $pluginName, $widgetClass),
+ 'You can now start implementing the <comment>render()</comment> method.',
'Enjoy!'
));
}
+ private function getWidgetMethodName($methodName)
+ {
+ $methodName = trim($methodName);
+ $methodName = str_replace(' ', '', $methodName);
+ $methodName = preg_replace("/[^A-Za-z0-9]/", '', $methodName);
+
+ if (0 !== strpos(strtolower($methodName), 'get')) {
+ $methodName = 'get' . ucfirst($methodName);
+ }
+
+ return lcfirst($methodName);
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return array
+ * @throws \RuntimeException
+ */
+ protected function getWidgetName(InputInterface $input, OutputInterface $output)
+ {
+ $validate = function ($widgetName) {
+ if (empty($widgetName)) {
+ throw new \InvalidArgumentException('Please enter the name of your widget');
+ }
+
+ if (preg_match("/[^A-Za-z0-9 ]/", $widgetName)) {
+ throw new \InvalidArgumentException('Only alpha numerical characters and whitespaces are allowed');
+ }
+
+ return $widgetName;
+ };
+
+ $widgetName = $input->getOption('widgetname');
+
+ if (empty($widgetName)) {
+ $dialog = $this->getHelperSet()->get('dialog');
+ $widgetName = $dialog->askAndValidate($output, 'Enter the name of your Widget, for instance "Browser Families": ', $validate);
+ } else {
+ $validate($widgetName);
+ }
+
+ $widgetName = ucfirst($widgetName);
+
+ return $widgetName;
+ }
+
protected function getExistingCategories()
{
$categories = array();
- foreach (Widgets::getAllWidgets() as $widget) {
- if ($widget->getCategory()) {
- $categories[] = Piwik::translate($widget->getCategory());
+ foreach (WidgetsList::get()->getWidgetConfigs() as $widget) {
+ if ($widget->getCategoryId()) {
+ $categories[] = Piwik::translate($widget->getCategoryId());
}
}
$categories = array_values(array_unique($categories));
@@ -111,8 +165,8 @@ class GenerateWidget extends GeneratePluginBase
*/
protected function getPluginName(InputInterface $input, OutputInterface $output)
{
- $pluginNames = $this->getPluginNamesHavingNotSpecificFile('Widgets.php');
- $invalidName = 'You have to enter the name of an existing plugin which does not already have any widgets defined';
+ $pluginNames = $this->getPluginNames();
+ $invalidName = 'You have to enter a name of an existing plugin.';
return $this->askPluginNameAndValidate($input, $output, $pluginNames, $invalidName);
}
diff --git a/plugins/CoreHome/Categories/ActionsCategory.php b/plugins/CoreHome/Categories/ActionsCategory.php
new file mode 100644
index 0000000000..e995df110d
--- /dev/null
+++ b/plugins/CoreHome/Categories/ActionsCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Category;
+
+class ActionsCategory extends Category
+{
+ protected $id = 'General_Actions';
+ protected $order = 10;
+}
diff --git a/plugins/CoreHome/Categories/DevicesSubcategory.php b/plugins/CoreHome/Categories/DevicesSubcategory.php
new file mode 100644
index 0000000000..9d68e5b30c
--- /dev/null
+++ b/plugins/CoreHome/Categories/DevicesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Subcategory;
+
+class DevicesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'DevicesDetection_Devices';
+ protected $order = 15;
+
+}
diff --git a/plugins/CoreHome/Categories/EngagementSubcategory.php b/plugins/CoreHome/Categories/EngagementSubcategory.php
new file mode 100644
index 0000000000..1a4f4b1d40
--- /dev/null
+++ b/plugins/CoreHome/Categories/EngagementSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Subcategory;
+
+class EngagementSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'VisitorInterest_Engagement';
+ protected $order = 30;
+
+}
diff --git a/plugins/CoreHome/Categories/SoftwareSubcategory.php b/plugins/CoreHome/Categories/SoftwareSubcategory.php
new file mode 100644
index 0000000000..34188afe97
--- /dev/null
+++ b/plugins/CoreHome/Categories/SoftwareSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Subcategory;
+
+class SoftwareSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'DevicesDetection_Software';
+ protected $order = 20;
+
+}
diff --git a/plugins/CoreHome/Categories/VisitorsCategory.php b/plugins/CoreHome/Categories/VisitorsCategory.php
new file mode 100644
index 0000000000..c4604c4035
--- /dev/null
+++ b/plugins/CoreHome/Categories/VisitorsCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Category;
+
+class VisitorsCategory extends Category
+{
+ protected $id = 'General_Visitors';
+ protected $order = 5;
+}
diff --git a/plugins/CoreHome/Categories/VisitorsOverviewSubcategory.php b/plugins/CoreHome/Categories/VisitorsOverviewSubcategory.php
new file mode 100644
index 0000000000..3db3e260d2
--- /dev/null
+++ b/plugins/CoreHome/Categories/VisitorsOverviewSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Categories;
+
+use Piwik\Category\Subcategory;
+
+class VisitorsOverviewSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'General_Overview';
+ protected $order = 2;
+
+}
diff --git a/plugins/CoreHome/Columns/Metrics/AverageTimeOnSite.php b/plugins/CoreHome/Columns/Metrics/AverageTimeOnSite.php
index e590e19871..b56364aa7f 100644
--- a/plugins/CoreHome/Columns/Metrics/AverageTimeOnSite.php
+++ b/plugins/CoreHome/Columns/Metrics/AverageTimeOnSite.php
@@ -38,7 +38,7 @@ class AverageTimeOnSite extends ProcessedMetric
public function format($value, Formatter $formatter)
{
- return $formatter->getPrettyTimeFromSeconds($value);
+ return $formatter->getPrettyTimeFromSeconds($value, true);
}
public function getTranslatedName()
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
index a61419e5fb..a0866c0ff2 100644
--- a/plugins/CoreHome/Controller.php
+++ b/plugins/CoreHome/Controller.php
@@ -11,12 +11,13 @@ namespace Piwik\Plugins\CoreHome;
use Exception;
use Piwik\API\Request;
use Piwik\Common;
+use Piwik\DataTable\Renderer\Json;
use Piwik\Date;
use Piwik\FrontController;
-use Piwik\Menu\MenuReporting;
use Piwik\Notification\Manager as NotificationManager;
use Piwik\Piwik;
use Piwik\Plugin\Report;
+use Piwik\Widget\Widget;
use Piwik\Plugins\CoreHome\DataTableRowAction\MultiRowEvolution;
use Piwik\Plugins\CoreHome\DataTableRowAction\RowEvolution;
use Piwik\Plugins\CorePluginsAdmin\MarketplaceApiClient;
@@ -28,7 +29,6 @@ use Piwik\UpdateCheck;
use Piwik\Url;
use Piwik\View;
use Piwik\ViewDataTable\Manager as ViewDataTableManager;
-use Piwik\Plugin\Widgets as PluginWidgets;
class Controller extends \Piwik\Plugin\Controller
{
@@ -49,40 +49,38 @@ class Controller extends \Piwik\Plugin\Controller
return 'redirectToCoreHomeIndex';
}
- public function renderReportMenu(Report $report)
+ public function renderReportWidget(Report $report)
{
Piwik::checkUserHasSomeViewAccess();
$this->checkSitePermission();
$report->checkIsEnabled();
- $menuTitle = $report->getMenuTitle();
-
- if (empty($menuTitle)) {
- throw new Exception('This report is not supposed to be displayed in the menu, please define a $menuTitle in your report.');
- }
-
- $menuTitle = $this->translator->translate($menuTitle);
- $content = $this->renderReportWidget($report);
-
- return View::singleReport($menuTitle, $content);
+ return $report->render();
}
- public function renderReportWidget(Report $report)
+ public function renderWidgetContainer()
{
Piwik::checkUserHasSomeViewAccess();
$this->checkSitePermission();
- $report->checkIsEnabled();
+ $view = new View('@CoreHome/widgetContainer');
+ $view->isWidgetized = (bool) Common::getRequestVar('widget', 0, 'int');
+ $view->containerId = Common::getRequestVar('containerId', null, 'string');
- return $report->render();
+ return $view->render();
}
- public function renderWidget(PluginWidgets $widget, $method)
+ /**
+ * @param Widget $widget
+ * @return mixed
+ * @throws Exception
+ */
+ public function renderWidget($widget)
{
Piwik::checkUserHasSomeViewAccess();
- return $widget->$method();
+ return $widget->render();
}
function redirectToCoreHomeIndex()
@@ -133,7 +131,6 @@ class Controller extends \Piwik\Plugin\Controller
{
$view = new View('@CoreHome/getDefaultIndexView');
$this->setGeneralVariablesView($view);
- $view->menu = MenuReporting::getInstance()->getMenu();
$view->dashboardSettingsControl = new DashboardManagerControl();
$view->content = '';
return $view;
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index 23da8326aa..c8b2b428d0 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -14,6 +14,13 @@ namespace Piwik\Plugins\CoreHome;
class CoreHome extends \Piwik\Plugin
{
/**
+ * Defines a widget container layout that will display all widgets within a container inside a "tab" menu
+ * where on the left side a link is shown for each widget and on the right side the selected widget.
+ * @api
+ */
+ const WIDGET_CONTAINER_LAYOUT_BY_DIMENSION = 'ByDimension';
+
+ /**
* @see Piwik\Plugin::registerEvents
*/
public function registerEvents()
@@ -105,8 +112,6 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/javascripts/dataTable_rowactions.js";
$jsFiles[] = "plugins/CoreHome/javascripts/popover.js";
$jsFiles[] = "plugins/CoreHome/javascripts/broadcast.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/menu.js";
- $jsFiles[] = "plugins/CoreHome/javascripts/menu_init.js";
$jsFiles[] = "plugins/CoreHome/javascripts/calendar.js";
$jsFiles[] = "plugins/CoreHome/javascripts/sparkline.js";
$jsFiles[] = "plugins/CoreHome/javascripts/corehome.js";
@@ -120,8 +125,12 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/angularjs/piwikApp.config.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/services/service.module.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/common/services/global-ajax-queue.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/services/piwik.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/services/piwik-api.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/common/services/piwik-url.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/common/services/report-metadata-model.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/common/services/reporting-pages-model.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/filters/filter.module.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/filters/translate.js";
@@ -130,6 +139,7 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/angularjs/common/filters/length.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/filters/trim.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/filters/pretty-url.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/escape.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/directives/directive.module.js";
$jsFiles[] = "plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js";
@@ -146,6 +156,8 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/angularjs/history/history.service.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/activity-indicator/activityindicator.directive.js";
+
$jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js";
$jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector.controller.js";
$jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector.directive.js";
@@ -163,6 +175,21 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "plugins/CoreHome/angularjs/ajax-form/ajax-form.controller.js";
$jsFiles[] = "plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js";
+
+ $jsFiles[] = "plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/widget/widget.directive.js";
+
+ $jsFiles[] = "plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js";
+
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js";
+
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js";
+ $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js";
}
public function getClientSideTranslationKeys(&$translationKeys)
@@ -258,5 +285,6 @@ class CoreHome extends \Piwik\Plugin
$translationKeys[] = 'CoreHome_UndoPivotBySubtable';
$translationKeys[] = 'CoreHome_PivotBySubtable';
$translationKeys[] = 'General_LearnMore';
+ $translationKeys[] = 'CoreHome_NoSuchPage';
}
}
diff --git a/plugins/CoreHome/Widgets.php b/plugins/CoreHome/Widgets.php
deleted file mode 100644
index 17d888bd35..0000000000
--- a/plugins/CoreHome/Widgets.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\CoreHome;
-
-use Piwik\Common;
-use Piwik\Piwik;
-use Piwik\Translation\Translator;
-use Piwik\View;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'Example Widgets';
-
- /**
- * @var Translator
- */
- private $translator;
-
- public function __construct(Translator $translator)
- {
- $this->translator = $translator;
- }
-
- protected function init()
- {
- $this->addWidget('CoreHome_SupportPiwik', 'getDonateForm');
- $this->addWidget('Installation_Welcome', 'getPromoVideo');
- }
-
- /**
- * Renders and echo's the in-app donate form w/ slider.
- */
- public function getDonateForm()
- {
- $view = new View('@CoreHome/getDonateForm');
-
- if (Common::getRequestVar('widget', false)
- && Piwik::hasUserSuperUserAccess()) {
- $view->footerMessage = $this->translator->translate('CoreHome_OnlyForSuperUserAccess');
- }
-
- return $view->render();
- }
-
- /**
- * Renders and echo's HTML that displays the Piwik promo video.
- */
- public function getPromoVideo()
- {
- $view = new View('@CoreHome/getPromoVideo');
- $view->shareText = $this->translator->translate('CoreHome_SharePiwikShort');
- $view->shareTextLong = $this->translator->translate('CoreHome_SharePiwikLong');
- $view->promoVideoUrl = 'https://www.youtube.com/watch?v=OslfF_EH81g';
-
- return $view->render();
- }
-}
diff --git a/plugins/CoreHome/Widgets/GetDonateForm.php b/plugins/CoreHome/Widgets/GetDonateForm.php
new file mode 100644
index 0000000000..093fe8c3a2
--- /dev/null
+++ b/plugins/CoreHome/Widgets/GetDonateForm.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Widgets;
+
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Widget\Widget;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Translation\Translator;
+use Piwik\View;
+
+class GetDonateForm extends Widget
+{
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ public function __construct(Translator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Example Widgets');
+ $config->setName('CoreHome_SupportPiwik');
+ $config->setOrder(5);
+ }
+
+ public function render()
+ {
+ $view = new View('@CoreHome/getDonateForm');
+
+ if (Common::getRequestVar('widget', false)
+ && Piwik::hasUserSuperUserAccess()) {
+ $view->footerMessage = $this->translator->translate('CoreHome_OnlyForSuperUserAccess');
+ }
+
+ return $view->render();
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Widgets/GetPromoVideo.php b/plugins/CoreHome/Widgets/GetPromoVideo.php
new file mode 100644
index 0000000000..49636b5e0e
--- /dev/null
+++ b/plugins/CoreHome/Widgets/GetPromoVideo.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Widgets;
+
+use Piwik\Widget\Widget;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Translation\Translator;
+use Piwik\View;
+
+class GetPromoVideo extends Widget
+{
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ public function __construct(Translator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Example Widgets');
+ $config->setName('Installation_Welcome');
+ $config->setOrder(10);
+ }
+
+ public function render()
+ {
+ $view = new View('@CoreHome/getPromoVideo');
+ $view->shareText = $this->translator->translate('CoreHome_SharePiwikShort');
+ $view->shareTextLong = $this->translator->translate('CoreHome_SharePiwikLong');
+ $view->promoVideoUrl = 'https://www.youtube.com/watch?v=OslfF_EH81g';
+
+ return $view->render();
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/activity-indicator/activityindicator.directive.js b/plugins/CoreHome/angularjs/activity-indicator/activityindicator.directive.js
new file mode 100644
index 0000000000..4417cea7ac
--- /dev/null
+++ b/plugins/CoreHome/angularjs/activity-indicator/activityindicator.directive.js
@@ -0,0 +1,31 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Shows a general loading message while [loading] is set to true.
+ *
+ * @param {Boolean} loading If true, the activity indicator is shown, otherwise the indicator is hidden.
+ *
+ * Example:
+ * <div piwik-activity-indicator loading="true|false"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikActivityIndicator', piwikActivityIndicator);
+
+ piwikActivityIndicator.$inject = ['piwik'];
+
+ function piwikActivityIndicator(piwik){
+ return {
+ restrict: 'A',
+ transclude: true,
+ scope: {
+ loading: '='
+ },
+ templateUrl: 'plugins/CoreHome/angularjs/activity-indicator/activityindicator.html?cb=' + piwik.cacheBuster
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/activity-indicator/activityindicator.html b/plugins/CoreHome/angularjs/activity-indicator/activityindicator.html
new file mode 100644
index 0000000000..f6080ae817
--- /dev/null
+++ b/plugins/CoreHome/angularjs/activity-indicator/activityindicator.html
@@ -0,0 +1,3 @@
+<div ng-show="loading" class="loadingPiwik">
+ <img src="plugins/Morpheus/images/loading-blue.gif" alt=""/>{{ 'General_LoadingData'|translate }}
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js b/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js
index 89d572cedf..2eef346ec6 100644
--- a/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js
+++ b/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js
@@ -132,7 +132,9 @@
scope.ajaxForm.data[name] = val;
if (!skipScopeApply) {
- scope.$apply();
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
}
}
};
diff --git a/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js b/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
index 0617c5df88..ee1a2cf219 100644
--- a/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
+++ b/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
@@ -24,13 +24,17 @@
function onClickOutsideElement (event) {
if (element.has(event.target).length === 0) {
- scope.$apply(attr.piwikFocusAnywhereButHere);
+ setTimeout(function () {
+ scope.$apply(attr.piwikFocusAnywhereButHere);
+ }, 0);
}
}
function onEscapeHandler (event) {
if (event.which === 27) {
- scope.$apply(attr.piwikFocusAnywhereButHere);
+ setTimeout(function () {
+ scope.$apply(attr.piwikFocusAnywhereButHere);
+ }, 0);
}
}
diff --git a/plugins/CoreHome/angularjs/common/filters/escape.js b/plugins/CoreHome/angularjs/common/filters/escape.js
new file mode 100644
index 0000000000..382e84b5ac
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/filters/escape.js
@@ -0,0 +1,16 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.filter').filter('escape', escape);
+
+ function escape() {
+
+ return function(value) {
+ return piwikHelper.escape(piwikHelper.htmlEntities(value));
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/global-ajax-queue.js b/plugins/CoreHome/angularjs/common/services/global-ajax-queue.js
new file mode 100644
index 0000000000..f831995810
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/services/global-ajax-queue.js
@@ -0,0 +1,14 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue);
+
+ function ajaxQueue() {
+
+ return globalAjaxQueue;
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-url.js b/plugins/CoreHome/angularjs/common/services/piwik-url.js
new file mode 100644
index 0000000000..f2d6e9bb0c
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/services/piwik-url.js
@@ -0,0 +1,54 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').service('piwikUrl', piwikUrl);
+
+ piwikUrl.$inject = ['$location', 'piwik'];
+
+ /**
+ * Similar to angulars $location but works around some limitation. Use it if you need to access search params
+ */
+ function piwikUrl($location, piwik) {
+
+ var model = {
+ getSearchParam: getSearchParam
+ }
+
+ return model;
+
+ function getSearchParam(paramName)
+ {
+ if (paramName === 'segment') {
+ var hash = window.location.href.split('#');
+ if (hash && hash[1]) {
+ return piwik.broadcast.getValueFromHash(paramName, hash[1]);
+ }
+
+ return broadcast.getValueFromUrl(paramName);
+ }
+
+ // available in global scope
+ var search = $location.search();
+
+ if (!search[paramName]) {
+ // see https://github.com/angular/angular.js/issues/7239 (issue is resolved but problem still exists)
+ search[paramName] = piwik.broadcast.getValueFromUrl(paramName);
+ }
+
+ if (search[paramName]) {
+ var value = search[paramName];
+
+ if (angular.isArray(search[paramName])) {
+ // use last one. Eg when having period=day&period=year angular would otherwise return ['day', 'year']
+ return value[value.length - 1];
+ }
+
+ return value;
+ }
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/report-metadata-model.js b/plugins/CoreHome/angularjs/common/services/report-metadata-model.js
new file mode 100644
index 0000000000..f158861423
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/services/report-metadata-model.js
@@ -0,0 +1,52 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').factory('reportMetadataModel', reportMetadataModel);
+
+ reportMetadataModel.$inject = ['piwik', 'piwikApi'];
+
+ function reportMetadataModel (piwik, piwikApi) {
+
+ var reportsPromise = null;
+
+ var model = {
+ reports: [],
+ fetchReportMetadata: fetchReportMetadata,
+ findReport: findReport
+ };
+
+ return model;
+
+ function findReport(module, action)
+ {
+ var found = [];
+
+ angular.forEach(model.reports, function (report) {
+ if (report.module === module && report.action === action) {
+ found = report;
+ }
+ });
+
+ return found;
+ }
+
+ function fetchReportMetadata()
+ {
+ if (!reportsPromise) {
+ reportsPromise = piwikApi.fetch({
+ method: 'API.getReportMetadata',
+ idSites: piwik.idSite || piwik.broadcast.getValueFromUrl('idSite'),
+ }).then(function (response) {
+ model.reports = response;
+ return response;
+ });
+ }
+
+ return reportsPromise;
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js b/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js
new file mode 100644
index 0000000000..1b1e406c95
--- /dev/null
+++ b/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js
@@ -0,0 +1,58 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').factory('reportingPagesModel', reportingPagesModelService);
+
+ reportingPagesModelService.$inject = ['piwikApi'];
+
+ function reportingPagesModelService (piwikApi) {
+ var fetchAllPagesPromise = false;
+
+ // those sites are going to be displayed
+ var model = {
+ pages : [],
+ findPage: findPage,
+ reloadAllPages : reloadAllPages,
+ getAllPages : getAllPages
+ };
+
+ return model;
+
+ function findPage(categoryId, subcategoryId)
+ {
+ var found = null;
+
+ angular.forEach(model.pages, function (page) {
+ if (page &&
+ page.category && page.subcategory &&
+ page.category.id === categoryId && ('' + page.subcategory.id) === subcategoryId) {
+ found = page;
+ }
+ });
+
+ return found;
+ }
+
+ function reloadAllPages()
+ {
+ fetchAllPagesPromise = null;
+ return getAllPages();
+ }
+
+ function getAllPages()
+ {
+ if (!fetchAllPagesPromise) {
+ fetchAllPagesPromise = piwikApi.fetch({method: 'API.getReportPagesMetadata'}).then(function (response) {
+ model.pages = response;
+ return response;
+ });
+ }
+
+ return fetchAllPagesPromise;
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/history/history.service.js b/plugins/CoreHome/angularjs/history/history.service.js
index 2c6486a517..7dadf35ad0 100644
--- a/plugins/CoreHome/angularjs/history/history.service.js
+++ b/plugins/CoreHome/angularjs/history/history.service.js
@@ -36,6 +36,19 @@
loadCurrentPage();
}
+ function cleanHash(hash)
+ {
+ var chars = ['#', '/', '?'];
+ for (var i = 0; i != chars.length; ++i) {
+ var charToRemove = chars[i];
+ if (hash.charAt(0) == charToRemove) {
+ hash = hash.substring(1);
+ }
+ }
+
+ return hash;
+ }
+
// currently, the AJAX content URL is stored in $location.search(), but before it was stored in $location.path().
// this function makes sure URLs like http://piwik.net/?...#/module=Whatever&action=whatever still work.
function changePathToSearch() {
@@ -82,13 +95,7 @@
function load(hash) {
// make sure the hash is just the query parameter values, w/o a starting #, / or ? char. broadcast.pageload & $location.path should get neither
- var chars = ['#', '/', '?'];
- for (var i = 0; i != chars.length; ++i) {
- var charToRemove = chars[i];
- if (hash.charAt(0) == charToRemove) {
- hash = hash.substring(1);
- }
- }
+ hash = cleanHash(hash);
if (location.hash === '#?' + hash) {
loadCurrentPage(); // it would not trigger a location change success event as URL is the same, call it manually
diff --git a/plugins/CoreHome/angularjs/http404check.js b/plugins/CoreHome/angularjs/http404check.js
index f2e2a86edf..5b720c9472 100644
--- a/plugins/CoreHome/angularjs/http404check.js
+++ b/plugins/CoreHome/angularjs/http404check.js
@@ -1,9 +1,9 @@
(function () {
angular.module('piwikApp').factory('http404CheckInterceptor', http404CheckInterceptor);
- http404CheckInterceptor.$inject = ['$q'];
+ http404CheckInterceptor.$inject = ['$q', 'globalAjaxQueue'];
- function http404CheckInterceptor($q) {
+ function http404CheckInterceptor($q, globalAjaxQueue) {
function isClientError(rejection)
{
@@ -15,8 +15,8 @@
}
return {
-
'responseError': function(rejection) {
+
if (rejection &&
isClientError(rejection) &&
rejection.config &&
diff --git a/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html b/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html
index d1964d1ac4..14191ac20e 100644
--- a/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html
+++ b/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html
@@ -23,7 +23,7 @@
class="reset"
src="plugins/CoreHome/images/reset_search.png"/>
</div>
- <div ng-transclude>
+ <div ng-transclude ng-click="selectItem($event)">
</div>
</div>
diff --git a/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js b/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js
index 00fbf87d7b..313ef00d6c 100644
--- a/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js
+++ b/plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js
@@ -34,10 +34,10 @@
templateUrl: 'plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.html?cb=' + piwik.cacheBuster,
link: function(scope, element, attrs) {
- element.find('.item').on('click', function () {
- var $self = angular.element(this);
+ scope.selectItem = function (event) {
+ var $self = angular.element(event.target);
- if ($self.hasClass('disabled') || $self.hasClass('separator')) {
+ if (!$self.hasClass('item') || $self.hasClass('disabled') || $self.hasClass('separator')) {
return;
}
@@ -47,11 +47,14 @@
});
}
scope.$eval('view.showItems = false');
- scope.$apply();
+
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
element.find('.item').removeClass('active');
$self.addClass('active');
- });
+ };
scope.searchItems = function (searchTerm)
{
diff --git a/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js b/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js
new file mode 100644
index 0000000000..ea15f025b0
--- /dev/null
+++ b/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js
@@ -0,0 +1,74 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * When present in the page it listens to a popover URL parameter.
+ *
+ * If present it will try to load the related content in a popover or if the URL is empty it will close an
+ * opened popover.
+ *
+ * Example:
+ * <div piwik-popover-handler></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikPopoverHandler', piwikPopoverHandler);
+
+ piwikPopoverHandler.$inject = ['$location', '$rootScope', 'piwik'];
+
+ function piwikPopoverHandler($location, $rootScope, piwik){
+
+ return {
+ restrict: 'A',
+ scope: {},
+ controller: function () {
+
+ function close()
+ {
+ Piwik_Popover.close();
+ }
+
+ function open(popoverParam)
+ {
+ // in case the $ was encoded (e.g. when using copy&paste on urls in some browsers)
+ popoverParam = decodeURIComponent(popoverParam);
+ // revert special encoding from broadcast.propagateNewPopoverParameter()
+ popoverParam = popoverParam.replace(/\$/g, '%');
+ popoverParam = decodeURIComponent(popoverParam);
+
+ var popoverParamParts = popoverParam.split(':');
+ var handlerName = popoverParamParts[0];
+ popoverParamParts.shift();
+ var param = popoverParamParts.join(':');
+ if (typeof piwik.broadcast.popoverHandlers[handlerName] != 'undefined'
+ && !piwik.broadcast.isLoginPage()) {
+ piwik.broadcast.popoverHandlers[handlerName](param);
+ }
+ }
+
+ function openOrClose()
+ {
+ // should be rather done by routing
+ var popoverParam = $location.search().popover;
+ if (popoverParam) {
+ open(popoverParam);
+ } else {
+ close();
+ }
+ }
+
+ $rootScope.$on('$locationChangeSuccess', function () {
+ // should be rather done by routing
+ $(function () {
+ // make sure all popover handles were registered
+ openOrClose();
+ });
+ });
+
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js
new file mode 100644
index 0000000000..adc1b97936
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js
@@ -0,0 +1,153 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp').factory('reportingMenuModel', reportingMenuModelService);
+
+ reportingMenuModelService.$inject = ['$filter', '$q', 'piwikApi', 'reportingPagesModel', '$location'];
+
+ function reportingMenuModelService ($filter, $q, piwikApi, reportingPagesModel, $location) {
+
+ // those sites are going to be displayed
+ var model = {
+ menu: [],
+ selected: [],
+ fetchMenuItems: fetchMenuItems,
+ reloadMenuItems: reloadMenuItems,
+ findSubcategory: findSubcategory
+ };
+
+ return model;
+
+ function isNumeric(text) {
+ return !isNaN(parseFloat(text)) && isFinite(text);
+ }
+
+ function findSubcategory(categoryId, subcategoryId)
+ {
+ var foundCategory = null;
+ var foundSubcategory = null;
+
+ angular.forEach(model.menu, function (category) {
+ if (category.id !== categoryId) {
+ return;
+ }
+ angular.forEach(category.subcategories, function (subcategory) {
+ if (subcategory.id === subcategoryId) {
+ foundCategory = category;
+ foundSubcategory = subcategory;
+ }
+ });
+ });
+
+ return {category: foundCategory, subcategory: foundSubcategory};
+ }
+
+ function buildMenuFromPages(pages)
+ {
+ var menu = [];
+
+ var activeCategory = $location.search().category;
+ var activeSubcategory = $location.search().subcategory;
+
+ var categoriesHandled = {};
+ angular.forEach(pages, function (page, key) {
+ var category = page.category;
+ var categoryId = category.id;
+
+ if (categoriesHandled[categoryId]) {
+ return;
+ }
+
+ categoriesHandled[categoryId] = true;
+
+ if (activeCategory && category.id === activeCategory) {
+ // this doesn't really belong here but placed it here for convenience
+ category.active = true;
+ category.hover = true;
+ }
+
+ category.subcategories = [];
+
+ var goalsGroup = false;
+
+ angular.forEach(pages, function (page, key) {
+ if (page.category.id === categoryId) {
+ var subcategory = page.subcategory;
+
+ if (subcategory.id === activeSubcategory) {
+ subcategory.active = true;
+ }
+
+ if (page.widgets && page.widgets[0] && page.category.id === 'Goals_Goals' && isNumeric(page.subcategory.id)) {
+ // we handle a goal
+ if (!goalsGroup) {
+ goalsGroup = angular.copy(subcategory);
+ goalsGroup.name = $filter('translate')('Goals_ChooseGoal');
+ goalsGroup.isGroup = true;
+ goalsGroup.subcategories = [];
+ goalsGroup.order = 10;
+ }
+
+ if (subcategory.active) {
+ goalsGroup.name = subcategory.name;
+ }
+
+ var goalId = page.subcategory.id;
+ subcategory.tooltip = subcategory.name + ' (id = ' + goalId + ' )';
+
+ goalsGroup.subcategories.push(subcategory);
+ return;
+ }
+
+ category.subcategories.push(subcategory);
+ }
+ });
+
+ if (goalsGroup && goalsGroup.subcategories && goalsGroup.subcategories.length <= 3) {
+ angular.forEach(goalsGroup.subcategories, function (subcategory) {
+ category.subcategories.push(subcategory);
+ });
+ } else if(goalsGroup) {
+ category.subcategories.push(goalsGroup);
+ }
+
+ category.subcategories = sortMenuItems(category.subcategories);
+
+ menu.push(category);
+
+ return menu;
+ });
+
+ menu = sortMenuItems(menu);
+
+ return menu;
+ }
+
+ function sortMenuItems(menu) {
+ return $filter('orderBy')(menu, 'order');
+ };
+
+ function reloadMenuItems()
+ {
+ var pagesPromise = reportingPagesModel.reloadAllPages();
+ return pagesPromise.then(function (pages) {
+ model.menu = buildMenuFromPages(pages);
+ });
+ }
+
+ function fetchMenuItems()
+ {
+ var pagesPromise = reportingPagesModel.getAllPages();
+
+ return pagesPromise.then(function (pages) {
+ model.menu = buildMenuFromPages(pages);
+
+ return model.menu;
+ });
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js
new file mode 100644
index 0000000000..85dc0f17c5
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js
@@ -0,0 +1,125 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp').controller('ReportingMenuController', ReportingMenuController);
+
+ ReportingMenuController.$inject = ['$scope', 'piwik', '$location', '$timeout', 'reportingMenuModel', '$rootScope'];
+
+ function ReportingMenuController($scope, piwik, $location, $timeout, menuModel, $rootScope) {
+
+ function markAllCategoriesAsInactive()
+ {
+ angular.forEach(menuModel.menu, function (cat) {
+ cat.active = false;
+ cat.hover = false;
+ angular.forEach(cat.subcategories, function (subcat) {
+ subcat.active = false;
+ });
+ });
+ }
+
+ function getUrlParam(param)
+ {
+ var value = piwik.broadcast.getValueFromHash(param);
+ if (!value) {
+ value = piwik.broadcast.getValueFromUrl(param);
+ }
+ return value;
+ }
+
+ $scope.menuModel = menuModel;
+
+ var timeoutPromise = null;
+
+ // show subcategories of the currently hovered category
+ $scope.enterCategory = function (category) {
+
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+
+ angular.forEach(menuModel.menu, function (cat) {
+ cat.hover = false;
+ });
+
+ category.hover = true;
+ };
+
+ // show subcategories of the current active category again (after 2 sec max)
+ $scope.leaveCategory = function (category) {
+
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+
+ timeoutPromise = $timeout(function () {
+ angular.forEach(menuModel.menu, function (cat) {
+ if (cat.active) {
+ cat.hover = true;
+ } else {
+ cat.hover = false;
+ }
+ });
+ }, 2000);
+ };
+
+ // highlight the currently hovered subcategory (and category)
+ $scope.enterSubcategory = function (category, subcategory) {
+ if (!category || !subcategory) {
+ return;
+ }
+
+ markAllCategoriesAsInactive();
+
+ category.active = true;
+ category.hover = true;
+ subcategory.active = true;
+ };
+
+ var idSite = getUrlParam('idSite');
+ var period = getUrlParam('period');
+ var date = getUrlParam('date');
+ var segment = getUrlParam('segment');
+
+ $scope.makeUrl = function (category, subcategory) {
+ var url = 'idSite=' + idSite + '&period=' + period + '&date=' + date + '&category=' + category.id + '&subcategory=' + subcategory.id;
+ if (segment) {
+ url+= '&segment='+ segment;
+ }
+ return url;
+ }
+
+ $scope.loadSubcategory = function (category, subcategory) {
+ if (subcategory && subcategory.active) {
+ // this menu item is already active, a location change success would not be triggered,
+ // instead trigger an event
+ $rootScope.$emit('loadPage', category.id, subcategory.id);
+ }
+ };
+
+ menuModel.fetchMenuItems().then(function (menu) {
+ if (!$location.search().subcategory) {
+ // load first, initial page if no subcategory is present
+ $scope.enterSubcategory(menu[0], menu[0].subcategories[0]);
+ $location.search($scope.makeUrl(menu[0], menu[0].subcategories[0]));
+ }
+ });
+
+ $rootScope.$on('$locationChangeSuccess', function () {
+ var category = $location.search().category;
+ var subcategory = $location.search().subcategory;
+
+ if (!category || !subcategory) {
+ return;
+ }
+
+ var found = menuModel.findSubcategory(category, subcategory);
+ $scope.enterSubcategory(found.category, found.subcategory);
+ });
+
+ }
+})();
diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html
new file mode 100644
index 0000000000..bbfd687517
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html
@@ -0,0 +1,40 @@
+<div class="Menu--dashboard">
+ <ul class="Menu-tabList">
+ <li ng-repeat="category in menuModel.menu"
+ ng-class="{'sfActive': category.active, 'sfHover': category.hover}"
+ ng-mouseenter="enterCategory(category)"
+ ng-mouseleave="leaveCategory(category)">
+ <a class="menuItem"
+ ng-href="#?{{ makeUrl(category,category.subcategories[0]) }}"
+ ng-click="loadSubcategory(category, category.subcategories[0])">
+ {{ category.name }}
+ </a>
+ <ul ng-show="(category.subcategories|length) > 1">
+ <li ng-repeat="subcategory in category.subcategories"
+ ng-class="{'sfHover': subcategory.active}">
+ <div ng-if="subcategory.isGroup" piwik-menudropdown show-search="true" menu-title="{{ subcategory.name|escape }}">
+ <a class="item"
+ ng-repeat="subcat in subcategory.subcategories"
+ title="{{ subcat.tooltip }}"
+ ng-class="{'active': subcat.active}"
+ ng-href="#?{{ makeUrl(category,subcat) }}"
+ ng-click='loadSubcategory(category, subcat)'>
+ {{ subcat.name }}
+ </a>
+ </div>
+
+ <a ng-if="!subcategory.isGroup"
+ ng-href="#?{{ makeUrl(category,subcategory) }}"
+ class="menuItem"
+ ng-click='loadSubcategory(category, subcategory)'>
+ {{ subcategory.name }}
+ </a>
+ </li>
+ </ul>
+ </li>
+ <li id="Searchmenu">
+ <span piwik-quick-access></span>
+ </li>
+ </ul>
+
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js
new file mode 100644
index 0000000000..7cdd9e951b
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js
@@ -0,0 +1,31 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Shows the Piwik reporting menu.
+ *
+ * It automatically calls the API to fetch all data.
+ *
+ * Example:
+ * <div piwik-reporting-menu></div>
+ */
+
+(function () {
+ angular.module('piwikApp').directive('piwikReportingMenu', piwikReportingMenu);
+
+ piwikReportingMenu.$inject = ['piwik'];
+
+ function piwikReportingMenu(piwik){
+
+ return {
+ restrict: 'A',
+ scope: {},
+ templateUrl: 'plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html?cb=' + piwik.cacheBuster,
+ controller: 'ReportingMenuController'
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js
new file mode 100644
index 0000000000..4018fcee8c
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js
@@ -0,0 +1,196 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp').factory('reportingPageModel', reportingPageModelService);
+
+ reportingPageModelService.$inject = ['$filter', 'piwikApi', 'reportingPagesModel', 'reportMetadataModel'];
+
+ function reportingPageModelService ($filter, piwikApi, reportingPagesModel, reportMetadataModel) {
+ var init = false;
+
+ // those sites are going to be displayed
+ var model = {
+ fetchPage: fetchPage,
+ resetPage: resetPage,
+ widgets: [],
+ page: null,
+ pageContentUrl: '',
+ evolutionReports: [],
+ sparklineReports: []
+ };
+
+ return model;
+
+ function resetPage()
+ {
+ model.page = null;
+ model.widgets = [];
+ model.pageContentUrl = '';
+ model.evolutionReports = [];
+ model.sparklineReports = [];
+ }
+
+ function sortWidgets(widgets)
+ {
+ return $filter('orderBy')(widgets, 'order');
+ }
+
+ function shouldBeRenderedWithFullWidth(widget)
+ {
+ // rather controller logic
+ if ((widget.isContainer && widget.layout && widget.layout === 'ByDimension')
+ || widget.viewDataTable === 'bydimension') {
+ return true;
+ }
+
+ return widget.viewDataTable && widget.viewDataTable === 'tableAllColumns';
+ }
+
+ function buildPage(page)
+ {
+ if (!page) {
+ return;
+ }
+
+ var widgets = [];
+ var evolutionReports = [];
+ var sparklineReports = [];
+ var reportsToIgnore = [];
+
+ angular.forEach(page.widgets, function (widget) {
+
+ if (isIgnoredReport(reportsToIgnore, widget)) {
+ return;
+ }
+
+ reportsToIgnore = reportsToIgnore.concat(getRelatedReports(widget));
+
+ if (widget.viewDataTable && widget.viewDataTable === 'graphEvolution') {
+ evolutionReports.push(widget);
+ } else if (widget.viewDataTable && widget.viewDataTable === 'sparklines') {
+ sparklineReports.push(widget);
+ } else {
+ widgets.push(widget);
+ }
+ });
+
+ widgets = sortWidgets(widgets);
+
+ var groupedWidgets = [];
+
+ if (widgets.length === 1) {
+ // if there is only one widget, we always display it full width
+ groupedWidgets = widgets;
+ } else {
+ for (var i = 0; i < widgets.length; i++) {
+ var widget = widgets[i];
+
+ if (shouldBeRenderedWithFullWidth(widget) || (widgets[i+1] && shouldBeRenderedWithFullWidth(widgets[i+1]))) {
+ widget.widgets = sortWidgets(widget.widgets);
+
+ groupedWidgets.push(widget);
+ } else {
+
+ var counter = 0;
+ var left = [widget];
+ var right = [];
+
+ while (widgets[i+1] && !shouldBeRenderedWithFullWidth(widgets[i+1])) {
+ i++;
+ counter++;
+ if (counter % 2 === 0) {
+ left.push(widgets[i]);
+ } else {
+ right.push(widgets[i]);
+ }
+ }
+
+ groupedWidgets.push({group: true, left: left, right: right});
+ }
+ }
+ }
+
+ var copyWidgets = angular.copy(groupedWidgets);
+ var copyEvolution = angular.copy(evolutionReports);
+ var copySparklines = angular.copy(sparklineReports);
+
+ if (copyEvolution.length) {
+ copyEvolution = markWidgetsInFirstRowOfPage(copyEvolution);
+ } else if (copySparklines.length) {
+ copySparklines = markWidgetsInFirstRowOfPage(copySparklines);
+ } else {
+ copyWidgets = markWidgetsInFirstRowOfPage(copyWidgets);
+ }
+
+ // angular.copy forces the page to re-render. Otherwise it won't reload some pages
+ model.evolutionReports = copyEvolution;
+ model.sparklineReports = copySparklines;
+ model.widgets = copyWidgets;
+ }
+
+ function markWidgetsInFirstRowOfPage(widgets)
+ {
+ if (widgets && widgets[0]) {
+ if (widgets[0].group) {
+ markWidgetsInFirstRowOfPage(widgets[0].left);
+ markWidgetsInFirstRowOfPage(widgets[0].right);
+ } else {
+ widgets[0].isFirstInPage = true;
+ }
+ }
+
+ return widgets;
+ }
+
+ function getRelatedReports(widget)
+ {
+ if (widget.isReport) {
+ var report = reportMetadataModel.findReport(widget.module, widget.action);
+
+ if (report && report.relatedReports) {
+ return report.relatedReports;
+ }
+ }
+
+ return [];
+ }
+
+ function isIgnoredReport(reportsToIgnore, widget)
+ {
+ var found = false;
+
+ if (widget.isReport) {
+ angular.forEach(reportsToIgnore, function (report) {
+ if (report.module === widget.module &&
+ report.action === widget.action) {
+ found = true;
+ }
+ });
+ }
+
+ return found;
+ }
+
+ function fetchPage(category, subcategory)
+ {
+ resetPage();
+
+ var pagesPromise = reportingPagesModel.getAllPages();
+ var reportsPromise = reportMetadataModel.fetchReportMetadata();
+
+ return pagesPromise.then(function () {
+ model.page = reportingPagesModel.findPage(category, subcategory);
+
+ reportsPromise.then(function () {
+ buildPage(model.page);
+ });
+
+ return model.page;
+ });
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js
new file mode 100644
index 0000000000..cf0d424b55
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js
@@ -0,0 +1,56 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp').controller('ReportingPageController', ReportingPageController);
+
+ ReportingPageController.$inject = ['$scope', 'piwik', '$rootScope', '$location', 'reportingPageModel'];
+
+ function ReportingPageController($scope, piwik, $rootScope, $location, pageModel) {
+ pageModel.resetPage();
+ $scope.pageModel = pageModel;
+
+ var currentCategory = null;
+ var currentSubcategory = null;
+
+ $scope.renderPage = function (category, subcategory) {
+ if (!category || !subcategory) {
+ pageModel.resetPage();
+ $scope.loading = false;
+ return;
+ }
+
+ currentCategory = category;
+ currentSubcategory = subcategory;
+
+ pageModel.fetchPage(category, subcategory).then(function () {
+ $scope.hasNoPage = !pageModel.page;
+ $scope.loading = false;
+ });
+ }
+
+ $scope.loading = true; // we only set loading on initial load
+
+ $scope.renderPage($location.search().category, $location.search().subcategory);
+
+ $rootScope.$on('$locationChangeSuccess', function () {
+ // should be handled by $route
+ var category = $location.search().category;
+ var subcategory = $location.search().subcategory;
+
+ if (category === currentCategory && subcategory === currentSubcategory) {
+ // this page is already loaded
+ return;
+ }
+
+ $scope.renderPage(category, subcategory);
+ });
+
+ $rootScope.$on('loadPage', function (event, category, subcategory) {
+ $scope.renderPage(category, subcategory);
+ });
+ }
+})();
diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html
new file mode 100644
index 0000000000..9a8974e313
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html
@@ -0,0 +1,25 @@
+<div class="reporting-page">
+
+ <div piwik-activity-indicator loading="loading"/>
+
+ <div ng-show="hasNoPage">{{ 'CoreHome_NoSuchPage'|translate }}</div>
+
+ <div class="row" ng-repeat="evolutionReport in pageModel.evolutionReports">
+ <div class="col-md-12" piwik-widget="evolutionReport"></div>
+ </div>
+
+ <div class="row" ng-repeat="sparklineReport in pageModel.sparklineReports">
+ <div class="col-md-12" piwik-widget="sparklineReport"></div>
+ </div>
+
+ <div class="row" ng-repeat="widget in pageModel.widgets">
+ <div class="col-md-12" ng-if="!widget.group" piwik-widget="widget"></div>
+
+ <div ng-if="widget.group" class="col-md-6">
+ <div ng-repeat="widgetInGroup in widget.left" piwik-widget="widgetInGroup"></div>
+ </div>
+ <div ng-if="widget.group" class="col-md-6">
+ <div ng-repeat="widgetInGroup in widget.right" piwik-widget="widgetInGroup"></div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js
new file mode 100644
index 0000000000..a146ed3112
--- /dev/null
+++ b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js
@@ -0,0 +1,31 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Shows a piwik reporting page.
+ *
+ * The content to be displayed is automatically loaded via API based on the current URL. The URL parameters
+ * 'category' and 'subcategory' need to be present in the URL in order to see something in the reporting page.
+ *
+ * Example:
+ * <div piwik-reporting-page></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikReportingPage', piwikReportingPage);
+
+ piwikReportingPage.$inject = ['piwik'];
+
+ function piwikReportingPage(piwik){
+
+ return {
+ restrict: 'A',
+ scope: {},
+ templateUrl: 'plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html?cb=' + piwik.cacheBuster,
+ controller: 'ReportingPageController'
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html
new file mode 100644
index 0000000000..db98dee895
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html
@@ -0,0 +1,25 @@
+<div class="reportsByDimensionView">
+
+ <div class="entityList">
+ <div class='dimensionCategory' ng-repeat="category in widgetsByCategory">
+ {{ category.name }}
+ <ul class='listCircle'>
+ <li ng-repeat="widget in category.widgets"
+ class="reportDimension"
+ ng-class="{activeDimension: (selectedWidget.uniqueId===widget.uniqueId)}"
+ ng-click="selectWidget(widget)">
+ <span class='dimension'>{{widget.name}}</span>
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ <div style="float:left;max-width:900px;">
+ <h2 ng-if="selectedWidget.name" class="noTopMargin">{{ selectedWidget.name }}</h2>
+
+ <div ng-if="selectedWidget.parameters" class="dimensionReport"
+ piwik-widget-loader="selectedWidget.parameters"></div>
+ </div>
+ <div class="clear"></div>
+
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js
new file mode 100644
index 0000000000..1620be2a9d
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js
@@ -0,0 +1,67 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Renders a widget that is a container widget having the layout "ByDimension".
+ *
+ * The "ByDimension" layout shows a menu on the left letting you choose any widgets within this container. The
+ * currently selected widget is shown on the right.
+ *
+ * @param {Object} piwikWidgetByDimensionContainer a widget object as returned by the WidgetMetadata API.
+ *
+ * Example:
+ * <div piwik-widget-by-dimension-container="containerWidget"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikWidgetByDimensionContainer', piwikWidgetContainer);
+
+ piwikWidgetContainer.$inject = ['piwik', '$filter'];
+
+ function piwikWidgetContainer(piwik, $filter){
+ return {
+ restrict: 'A',
+ scope: {
+ container: '=piwikWidgetByDimensionContainer'
+ },
+ templateUrl: 'plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html?cb=' + piwik.cacheBuster,
+ compile: function (element, attrs) {
+
+ return function (scope, element, attrs, ngModel) {
+
+ var widgetsSorted = $filter('orderBy')(scope.container.widgets, 'order');
+ var widgetsByCategory = {};
+
+ angular.forEach(widgetsSorted, function (widget) {
+ var category = widget.subcategory.name;
+
+ if (!widgetsByCategory[category]) {
+ widgetsByCategory[category] = {name: category, order: widget.order, widgets: []};
+ }
+
+ widgetsByCategory[category].widgets.push(widget);
+ });
+
+ // only an array can be sorted
+ var finalWidgetsByCategory = [];
+ angular.forEach(widgetsByCategory, function (category) {
+ finalWidgetsByCategory.push(category);
+ });
+
+ scope.widgetsByCategory = $filter('orderBy')(finalWidgetsByCategory, 'order');
+
+ scope.selectWidget = function (widget) {
+ scope.selectedWidget = widget;
+ }
+
+ if (widgetsSorted && widgetsSorted.length) {
+ scope.selectWidget(widgetsSorted[0]);
+ }
+ };
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html
new file mode 100644
index 0000000000..21ebd3d0cd
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html
@@ -0,0 +1,10 @@
+<div>
+ <!-- custom template prevents recursion -->
+ <script id="mywidget.html" type="text/ng-template">
+ <div piwik-widget="widget"></div>
+ </script>
+
+ <div ng-repeat="widget in container.widgets">
+ <div ng-include src="'mywidget.html'"/>
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js
new file mode 100644
index 0000000000..c378637c71
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js
@@ -0,0 +1,32 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Renders a widget that is a container widget having no specific layout (which is the default).
+ *
+ * It shows all widgets vertically aligned one widget after another.
+ *
+ * @param {Object} piwikWidgetContainer a widget object as returned by the WidgetMetadata API.
+ *
+ * Example:
+ * <div piwik-widget-container="containerWidget"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikWidgetContainer', piwikWidgetContainer);
+
+ piwikWidgetContainer.$inject = ['piwik'];
+
+ function piwikWidgetContainer(piwik){
+ return {
+ restrict: 'A',
+ scope: {
+ container: '=piwikWidgetContainer'
+ },
+ templateUrl: 'plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html?cb=' + piwik.cacheBuster
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html
new file mode 100644
index 0000000000..d1f0cb51f1
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html
@@ -0,0 +1,13 @@
+<div>
+
+ <div piwik-activity-indicator loading="loading"/>
+
+ <div ng-show="loadingFailed">
+ <div class="notification system notification-error">
+ {{ 'General_ErrorRequest'|translate:(''):('') }}
+ </div>
+ </div>
+
+ <div class="theWidgetContent"></div>
+
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js
new file mode 100644
index 0000000000..4e1859e789
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js
@@ -0,0 +1,134 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Loads any custom widget or URL based on the given parameters.
+ *
+ * The currently active idSite, period, date and segment (if needed) is automatically appended to the parameters. If
+ * this widget is removed from the DOM and requests are in progress, these requests will be aborted. A loading message
+ * or an error message on failure is shown as well. It's kinda similar to ng-include but there it is not possible to
+ * listen to HTTP errors etc.
+ *
+ * Example:
+ * <div piwik-widget-loader="{module: '', action: '', ...}"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikWidgetLoader', piwikWidgetLoader);
+
+ piwikWidgetLoader.$inject = ['piwik', 'piwikUrl', '$http', '$compile', '$q'];
+
+ function piwikWidgetLoader(piwik, piwikUrl, $http, $compile, $q){
+ return {
+ restrict: 'A',
+ transclude: true,
+ scope: {
+ piwikWidgetLoader: '='
+ },
+ templateUrl: 'plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html?cb=' + piwik.cacheBuster,
+ compile: function (element, attrs) {
+
+ return function (scope, element, attrs, ngModel) {
+ var changeCounter = 0,
+ currentScope,
+ currentElement,
+ httpCanceler,
+ contentNode = element.find('.theWidgetContent');
+
+ var cleanupLastWidgetContent = function() {
+ if (currentElement) {
+ currentElement.remove();
+ currentElement = null;
+ }
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ };
+
+ var abortHttpRequestIfNeeded = function () {
+ if (httpCanceler) {
+ httpCanceler.resolve();
+ httpCanceler = null;
+ }
+ }
+
+ function getFullWidgetUrl(parameters) {
+
+ var url = $.param(parameters);
+
+ var idSite = piwikUrl.getSearchParam('idSite');
+ var period = piwikUrl.getSearchParam('period');
+ var date = piwikUrl.getSearchParam('date');
+ var segment = piwikUrl.getSearchParam('segment');
+
+ url += '&idSite=' + idSite + '&period=' + period;
+ url += '&date=' + date + '&random=' + parseInt(Math.random() * 10000);
+
+ if (segment) {
+ url += '&segment=' + segment;
+ }
+
+ return '?' + url;
+ }
+
+ function loadWidgetUrl(parameters, thisChangeId)
+ {
+ scope.loading = true;
+
+ var url = getFullWidgetUrl(parameters);
+
+ abortHttpRequestIfNeeded();
+ cleanupLastWidgetContent();
+
+ httpCanceler = $q.defer();
+
+ $http.get(url, {timeout: httpCanceler.promise}).success(function(response) {
+ if (thisChangeId !== changeCounter || !response) {
+ // another widget was requested meanwhile, ignore this response
+ return;
+ }
+
+ httpCanceler = null;
+
+ var newScope = scope.$new();
+ currentScope = newScope;
+
+ scope.loading = false;
+ scope.loadingFailed = false;
+
+ currentElement = contentNode.html(response).children();
+ $compile(currentElement)(newScope);
+
+ }).error(function () {
+ if (thisChangeId !== changeCounter) {
+ // another widget was requested meanwhile, ignore this response
+ return;
+ }
+
+ httpCanceler = null;
+
+ cleanupLastWidgetContent();
+
+ scope.loading = false;
+ scope.loadingFailed = true;
+ });
+ }
+
+ scope.$watch('piwikWidgetLoader', function (parameters, oldUrl) {
+ if (parameters) {
+ loadWidgetUrl(parameters, ++changeCounter);
+ }
+ });
+
+ element.on('$destroy', function() {
+ abortHttpRequestIfNeeded();
+ });
+ };
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget/widget.directive.html b/plugins/CoreHome/angularjs/widget/widget.directive.html
new file mode 100644
index 0000000000..86cdc91291
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget/widget.directive.html
@@ -0,0 +1,23 @@
+<div id="{{ widget.uniqueId }}"
+ ng-show="view.showWidget"
+ class="{{widget.viewDataTable}}"
+ ng-class="{'smallTopMargin': (!widget.isFirstInPage && (!widget.name || widgetized))}"
+ >
+ <!--smallTopMargin: we display small margin if it's not the first widget on the page and if there's no headline -->
+ <h2 ng-if="!widget.parameters.widget && widget.name && !widgetized"
+ piwik-enriched-headline
+ ng-class="{'noTopMargin': widget.isFirstInPage}"
+ feature-name="{{widget.name}}">{{widget.name}}</h2>
+ <h2 ng-if="widget.parameters.widget && widget.name && !widgetized">{{widget.name}}</h2>
+
+ <div ng-if="!widget.isContainer && widget.parameters"
+ piwik-widget-loader="widget.parameters"></div>
+
+ <div ng-if="widget.isContainer && widget.layout!='ByDimension'">
+ <div piwik-widget-container="widget"></div>
+ </div>
+
+ <div ng-if="widget.isContainer && widget.layout=='ByDimension'">
+ <div piwik-widget-by-dimension-container="widget"></div>
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/widget/widget.directive.js b/plugins/CoreHome/angularjs/widget/widget.directive.js
new file mode 100644
index 0000000000..86574870f2
--- /dev/null
+++ b/plugins/CoreHome/angularjs/widget/widget.directive.js
@@ -0,0 +1,93 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Renders any kind of widget. If you have a widget and you want to have it rendered, use this directive. It will
+ * display a name on top and the actual widget below. It can handle any kind of widget, no matter whether it is a
+ * regular widget or a container.
+ *
+ * @param {Object} piwikWidget A widget object as returned by the WidgetMetadata API.
+ * @param {Object} piwikWidget.middlewareParameters If present, we will request a URL using the given parameters and
+ * only if this URL returns a JSON `true` the widget will be shown.
+ * Otherwise the widget won't be shown.
+ * @param {String} containerId If you do not have a widget object but a containerId we will find the correct widget
+ * object based on the given containerId. Be aware that we might not find the widget if
+ * it is for example not available for the current user or period/date.
+ * @param {Boolean} widgetized true if the widget is widgetized (eg in Dashboard or exported). In this case we will add
+ * a URL parameter widget=1 to all widgets. Eg sparklines will be then displayed one after
+ * another (vertically aligned) instead of two next to each other.
+ *
+ * Example:
+ * <div piwik-widget="widget"></div>
+ * <div piwik-widget containerid="widgetGoalsOverview"></div> // in this case we will find the correct widget automatically
+ * <div piwik-widget="widget" widetized="true"></div> // disables rating feature, no initial headline
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikWidget', piwikWidget);
+
+ piwikWidget.$inject = ['piwik', 'piwikApi'];
+
+ function piwikWidget(piwik, piwikApi){
+
+ function findContainerWidget(containerId, scope) {
+ widgetsHelper.getAvailableWidgets(function (categorizedWidgets) {
+
+ angular.forEach(categorizedWidgets, function (widgets) {
+ angular.forEach(widgets, function (widget) {
+
+ if (widget && widget.isContainer && widget.parameters.containerId === containerId) {
+ widget = angular.copy(widget);
+ if (scope.widgetized) {
+ widget.isFirstInPage = '1';
+ widget.parameters.widget = '1';
+ angular.forEach(widget.widgets, function (widget) {
+ widget.parameters.widget = '1';
+ });
+ }
+ scope.widget = widget;
+ applyMiddleware(scope);
+ }
+ });
+ });
+
+ });
+ }
+
+ function applyMiddleware(scope)
+ {
+ if (!scope.widget.middlewareParameters) {
+ scope.$eval('view.showWidget = true');
+ } else {
+ var params = angular.copy(scope.widget.middlewareParameters);
+ piwikApi.fetch(params).then(function (response) {
+ var enabled = response ? 'true' : 'false';
+ scope.$eval('view.showWidget = ' + enabled);
+ });
+ }
+ }
+
+ return {
+ restrict: 'A',
+ scope: {
+ widget: '=?piwikWidget',
+ widgetized: '=?',
+ containerid: '='
+ },
+ templateUrl: 'plugins/CoreHome/angularjs/widget/widget.directive.html?cb=' + piwik.cacheBuster,
+ compile: function (element, attrs) {
+
+ return function (scope, element, attrs, ngModel) {
+ if (scope.widget) {
+ applyMiddleware(scope);
+ } else if (attrs.containerid) {
+ findContainerWidget(attrs.containerid, scope);
+ }
+ }
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js
index 706a8e59d5..3d5fb0432c 100644
--- a/plugins/CoreHome/javascripts/broadcast.js
+++ b/plugins/CoreHome/javascripts/broadcast.js
@@ -159,7 +159,6 @@ var broadcast = {
} else {
// start page
Piwik_Popover.close();
-
$('.pageWrap #content:not(.admin)').empty();
}
},
@@ -173,6 +172,7 @@ var broadcast = {
},
/**
+ * ONLY USED BY OVERLAY
* propagateAjax -- update hash values then make ajax calls.
* example :
* 1) <a href="javascript:broadcast.propagateAjax('module=Referrers&action=getKeywords')">View keywords report</a>
@@ -229,6 +229,47 @@ var broadcast = {
},
/**
+ * propagateAjax -- update hash values then make ajax calls.
+ * example :
+ * 1) <a href="javascript:broadcast.propagateAjax('module=Referrers&action=getKeywords')">View keywords report</a>
+ * 2) Main menu li also goes through this function.
+ *
+ * Will propagate your new value into the current hash string and make ajax calls.
+ *
+ * NOTE: this method will only make ajax call and replacing main content.
+ *
+ * @param {string} ajaxUrl querystring with parameters to be updated
+ * @param {boolean} [disableHistory] the hash change won't be available in the browser history
+ * @return {void}
+ */
+ buildReportingUrl: function (ajaxUrl, disableHistory) {
+
+ // available in global scope
+ var currentHashStr = broadcast.getHash();
+
+ ajaxUrl = ajaxUrl.replace(/^\?|&#/, '');
+
+ var params_vals = ajaxUrl.split("&");
+ for (var i = 0; i < params_vals.length; i++) {
+ currentHashStr = broadcast.updateParamValue(params_vals[i], currentHashStr);
+ }
+
+ // if the module is not 'Goals', we specifically unset the 'idGoal' parameter
+ // this is to ensure that the URLs are clean (and that clicks on graphs work as expected - they are broken with the extra parameter)
+ var action = broadcast.getParamValue('action', currentHashStr);
+ if (action != 'goalReport' && action != 'ecommerceReport' && action != 'products' && action != 'sales') {
+ currentHashStr = broadcast.updateParamValue('idGoal=', currentHashStr);
+ }
+ // unset idDashboard if use doesn't display a dashboard
+ var module = broadcast.getParamValue('module', currentHashStr);
+ if (module != 'Dashboard') {
+ currentHashStr = broadcast.updateParamValue('idDashboard=', currentHashStr);
+ }
+
+ return '#' + currentHashStr;
+ },
+
+ /**
* propagateNewPage() -- update url value and load new page,
* Example:
* 1) We want to update idSite to both search query and hash then reload the page,
@@ -349,9 +390,9 @@ var broadcast = {
*/
propagateNewPopoverParameter: function (handlerName, value) {
// init broadcast if not already done (it is required to make popovers work in widgetize mode)
- broadcast.init(true);
+ //broadcast.init(true);
- var hash = broadcast.getHashFromUrl(window.location.href);
+ var $location = angular.element(document).injector().get('$location');
var popover = '';
if (handlerName) {
@@ -365,24 +406,14 @@ var broadcast = {
}
if ('' == value || 'undefined' == typeof value) {
- var newHash = hash.replace(/(&?popover=.*)/, '');
- } else if (broadcast.getParamValue('popover', hash)) {
- var newHash = broadcast.updateParamValue('popover='+popover, hash);
- } else if (hash && hash != '#') {
- var newHash = hash + '&popover=' + popover
+ $location.search('popover', '');
} else {
- var newHash = '#popover='+popover;
- }
-
- // never use an empty hash, as that might reload the page
- if ('' == newHash) {
- newHash = '#';
+ $location.search('popover', popover);
}
- broadcast.forceReload = false;
- angular.element(document).injector().invoke(function (historyService) {
- historyService.load(newHash);
- });
+ setTimeout(function () {
+ angular.element(document).injector().get('$rootScope').$apply();
+ }, 1);
},
/**
diff --git a/plugins/CoreHome/javascripts/corehome.js b/plugins/CoreHome/javascripts/corehome.js
index 5bddc23f9e..6e8729611b 100755
--- a/plugins/CoreHome/javascripts/corehome.js
+++ b/plugins/CoreHome/javascripts/corehome.js
@@ -114,60 +114,6 @@
handleSectionToggle(this, 'inline', !$(this).is(':checked'));
});
- //
- // reports by dimension list behavior
- //
-
- // when a report dimension is clicked, load the appropriate report
- var currentWidgetLoading = null;
- $('body').on('click', '.reportDimension', function (e) {
- var view = $(this).closest('.reportsByDimensionView'),
- report = $('.dimensionReport', view),
- loading = $('.loadingPiwik', view);
-
- // make this dimension the active one
- $('.activeDimension', view).removeClass('activeDimension');
- $(this).addClass('activeDimension');
-
- // hide the visible report & show the loading elem
- report.hide();
- loading.show();
-
- // load the report using the data-url attribute (which holds the URL to the report)
- var widgetParams = broadcast.getValuesFromUrl($(this).attr('data-url'));
- for (var key in widgetParams) {
- widgetParams[key] = decodeURIComponent(widgetParams[key]);
- }
-
- var widgetUniqueId = widgetParams.module + widgetParams.action;
- currentWidgetLoading = widgetUniqueId;
-
- widgetsHelper.loadWidgetAjax(widgetUniqueId, widgetParams, function (response) {
- // if the widget that was loaded was not for the latest clicked link, do nothing w/ the response
- if (widgetUniqueId != currentWidgetLoading) {
- return;
- }
-
- loading.hide();
- report.css('display', 'inline-block').html($(response));
-
- // scroll to report
- piwikHelper.lazyScrollTo(report, 400);
- }, function (deferred, status) {
- if (status == 'abort' || !deferred || deferred.status < 400 || deferred.status >= 600) {
- return;
- }
-
- loading.hide();
-
- var errorMessage = _pk_translate('General_ErrorRequest', ['', '']);
- if ($('#loadingError').html()) {
- errorMessage = $('#loadingError').html();
- }
-
- report.css('display', 'inline-block').html('<div class="dimensionLoadingError">' + errorMessage + '</div>');
- });
- });
});
}(jQuery));
diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js
index 0561185de8..4bd5fb609a 100644
--- a/plugins/CoreHome/javascripts/dataTable.js
+++ b/plugins/CoreHome/javascripts/dataTable.js
@@ -1,3 +1,4 @@
+
/*!
* Piwik - free/libre analytics platform
*
diff --git a/plugins/CoreHome/javascripts/menu.js b/plugins/CoreHome/javascripts/menu.js
deleted file mode 100644
index 2f5e16c827..0000000000
--- a/plugins/CoreHome/javascripts/menu.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/*!
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-/**
- * @constructor
- */
-function menu() {
- this.param = {};
-}
-
-menu.prototype =
-{
- resetTimer: null,
-
- adaptSubMenuHeight: function() {
- var subNavHeight = $('.sfHover > ul').outerHeight();
- $('.nav_sep').height(subNavHeight);
- },
-
- overMainLI: function () {
- var $this = $(this);
- $this.siblings().removeClass('sfHover');
- $this.addClass('sfHover');
- menu.prototype.adaptSubMenuHeight();
- clearTimeout(menu.prototype.resetTimer);
- },
-
- outMainLI: function () {
- clearTimeout(menu.prototype.resetTimer);
- menu.prototype.resetTimer = setTimeout(function() {
- $('.Menu-tabList > .sfHover', this.menuNode).removeClass('sfHover');
- $('.Menu-tabList > .sfActive', this.menuNode).addClass('sfHover');
- menu.prototype.adaptSubMenuHeight();
- }, 2000);
- },
-
- onItemClick: function (e) {
- if (e.which === 2) {
- return;
- }
- $('.Menu--dashboard').trigger('piwikSwitchPage', this);
- broadcast.propagateAjax( $(this).attr('href').substr(1) );
- return false;
- },
-
- init: function () {
- this.menuNode = $('.Menu--dashboard');
-
- this.menuNode.find("li:has(ul),li#Searchmenu").hover(this.overMainLI, this.outMainLI);
- this.menuNode.find("li:has(ul),li#Searchmenu").focusin(this.overMainLI);
-
- this.menuNode.find('a.menuItem').click(this.onItemClick);
-
- menu.prototype.adaptSubMenuHeight();
- },
-
- activateMenu: function (module, action, params) {
- params = params || {};
- params.module = module;
- params.action = action;
-
- this.menuNode.find('li').removeClass('sfHover').removeClass('sfActive');
- var $activeLink = this.menuNode.find('a').filter(function () {
- var url = $(this).attr('href');
- if (!url) {
- return false;
- }
-
- for (var key in params) {
- if (!params.hasOwnProperty(key)
- || !params[key]
- ) {
- continue;
- }
-
- var actual = broadcast.getValueFromHash(key, url);
- if (actual != params[key]) {
- return false;
- }
- }
-
- return true;
- });
-
- $activeLink.closest('li').addClass('sfHover');
- $activeLink.closest('li.menuTab').addClass('sfActive').addClass('sfHover');
- },
-
- // getting the right li is a little tricky since goals uses idGoal, and overview is index.
- getSubmenuID: function (module, id, action) {
- var $li = '';
- // So, if module is Goals, id is present, and action is not Index, must be one of the goals
- if ((module == 'Goals' || module == 'Ecommerce') && id != '' && (action != 'index')) {
- $li = $("#" + module + "_" + action + "_" + id);
- // if module is Dashboard and id is present, must be one of the dashboards
- } else if (module == 'Dashboard') {
- if (!id) id = 1;
- $li = $("#" + module + "_" + action + "_" + id);
- } else {
- $li = $("#" + module + "_" + action);
- }
- return $li;
- },
-
- loadFirstSection: function () {
- if (broadcast.isHashExists() == false) {
- $('li:first a:first', this.menuNode).click().addClass('sfHover').addClass('sfActive');
- }
- }
-};
diff --git a/plugins/CoreHome/javascripts/menu_init.js b/plugins/CoreHome/javascripts/menu_init.js
deleted file mode 100644
index 490c859185..0000000000
--- a/plugins/CoreHome/javascripts/menu_init.js
+++ /dev/null
@@ -1,19 +0,0 @@
-$(function () {
- var isPageHasMenu = $('.Menu--dashboard').size();
- var isPageIsAdmin = $('#content.admin').size();
- if (isPageHasMenu) {
- piwikMenu = new menu();
- piwikMenu.init();
- piwikMenu.loadFirstSection();
- }
-
- if(isPageIsAdmin) {
- // don't use broadcast in admin pages
- return;
- }
- if(isPageHasMenu) {
- broadcast.init();
- } else {
- broadcast.init(true);
- }
-});
diff --git a/plugins/CoreHome/javascripts/sparkline.js b/plugins/CoreHome/javascripts/sparkline.js
index fc3b74f692..256e6f1589 100644
--- a/plugins/CoreHome/javascripts/sparkline.js
+++ b/plugins/CoreHome/javascripts/sparkline.js
@@ -35,14 +35,30 @@ piwik.initSparklines = function() {
};
window.initializeSparklines = function () {
- var sparklineUrlParamsToIgnore = ['module', 'action', 'idSite', 'period', 'date', 'viewDataTable'];
+ var sparklineUrlParamsToIgnore = ['module', 'action', 'idSite', 'period', 'date', 'viewDataTable', 'forceView', 'random'];
- $("[data-graph-id]").each(function () {
+ $('.graphEvolution [data-report]').each(function () {
var graph = $(this);
- // try to find sparklines and add them clickable behaviour
- graph.parent().find('div.sparkline').each(function () {
+ // we search for .widget to make sure eg in the Dashboard to not update any graph of another report
+ var selectorsToFindParent = ['.widget', '.reporting-page', 'body'];
+ var index = 0, selector, parent;
+ for (index; index < selectorsToFindParent.length; index++) {
+ selector = selectorsToFindParent[index];
+ parent = graph.parents(selector).first();
+ if (parent && parent.length) {
+ break;
+ }
+ }
+
+ if (!parent || !parent.length) {
+ return;
+ }
+ var sparklines = parent.find('div.sparkline');
+
+ // try to find sparklines and add them clickable behaviour
+ sparklines.each(function () {
// find the sparkline and get it's src attribute
var sparklineUrl = $('img', this).attr('data-src');
@@ -66,8 +82,8 @@ window.initializeSparklines = function () {
// on click, reload the graph with the new url
$(this).off('click.sparkline');
$(this).on('click.sparkline', function () {
- var reportId = graph.attr('data-graph-id'),
- dataTable = $(require('piwik/UI').DataTable.getDataTableByReport(reportId));
+ var reportId = graph.attr('data-report'),
+ dataTable = graph;
// when the metrics picker is used, the id of the data table might be updated (which is correct behavior).
// for example, in goal reports it might change from GoalsgetEvolutionGraph to GoalsgetEvolutionGraph1.
diff --git a/plugins/CoreHome/lang/en.json b/plugins/CoreHome/lang/en.json
index a6bab4a544..7b3d4bbcf3 100644
--- a/plugins/CoreHome/lang/en.json
+++ b/plugins/CoreHome/lang/en.json
@@ -48,6 +48,7 @@
"YouAreUsingTheLatestVersion": "You are using the latest version of Piwik!",
"ClickRowToExpandOrContract": "Click this row to expand or contract the subtable.",
"UndoPivotBySubtable": "This report has been pivoted %s Undo pivot",
- "PivotBySubtable": "This report is not pivoted %s Pivot by %s"
+ "PivotBySubtable": "This report is not pivoted %s Pivot by %s",
+ "NoSuchPage": "This page does not exist"
}
}
diff --git a/plugins/CoreHome/stylesheets/coreHome.less b/plugins/CoreHome/stylesheets/coreHome.less
index 5474eae3d2..63607d749f 100644
--- a/plugins/CoreHome/stylesheets/coreHome.less
+++ b/plugins/CoreHome/stylesheets/coreHome.less
@@ -120,6 +120,12 @@ div.ui-datepicker {
display: none;
}
+.reporting-page {
+ .sparklines {
+ max-width: 1250px;
+ }
+}
+
div .sparkline {
float: left;
clear: both;
diff --git a/plugins/CoreHome/stylesheets/zen-mode.less b/plugins/CoreHome/stylesheets/zen-mode.less
index 124c3395ff..112c6b2da6 100644
--- a/plugins/CoreHome/stylesheets/zen-mode.less
+++ b/plugins/CoreHome/stylesheets/zen-mode.less
@@ -77,13 +77,25 @@
#content:not(.admin), .widget {
- h2:nth-of-type(n+2) {
- margin-top: 40px;
+ .reporting-page {
+ .smallTopMargin:not(.graphEvolution) {
+ margin-top: 20px;
+ }
}
h2 {
+ margin-top: 40px;
padding-left: 10px;
font-size: 24px;
+
+ &.noTopMargin {
+ margin-top: 0px;
+ }
+ }
+
+ .widget [piwik-widget-container] [piwik-widget]:first-child h2 {
+ // eg Visits Overview with Graph should not have a margin-top
+ margin-top: 0px;
}
}
diff --git a/plugins/CoreHome/templates/ReportsByDimension/_reportsByDimension.twig b/plugins/CoreHome/templates/ReportsByDimension/_reportsByDimension.twig
deleted file mode 100644
index 57ec8279d5..0000000000
--- a/plugins/CoreHome/templates/ReportsByDimension/_reportsByDimension.twig
+++ /dev/null
@@ -1,29 +0,0 @@
-<div class="reportsByDimensionView">
-
- <div class="entityList">
- {% for category, dimensions in dimensionCategories %}
- {% set firstCategory = (loop.index0 == 0) %}
- <div class='dimensionCategory'>
- {{ category|translate }}
- <ul class='listCircle'>
- {% for idx, dimension in dimensions %}
- <li class="reportDimension {% if idx == 0 and firstCategory %}activeDimension{% endif %}"
- data-url="{{ dimension.url }}">
- <span class='dimension'>{{ dimension.title|translate }}</span>
- </li>
- {% endfor %}
- </ul>
- </div>
- {% endfor %}
- </div>
-
- <div style="float:left;max-width:900px;">
- <div class="loadingPiwik" style="display:none;">
- <img src="plugins/Morpheus/images/loading-blue.gif" alt=""/>{{ 'General_LoadingData'|translate }}
- </div>
-
- <div class="dimensionReport">{{ firstReport|raw }}</div>
- </div>
- <div class="clear"></div>
-
-</div>
diff --git a/plugins/CoreHome/templates/_indexContent.twig b/plugins/CoreHome/templates/_indexContent.twig
index 46d2f13579..671c26e782 100644
--- a/plugins/CoreHome/templates/_indexContent.twig
+++ b/plugins/CoreHome/templates/_indexContent.twig
@@ -12,8 +12,11 @@
{{ ajax.loadingDiv() }}
+ <div piwik-popover></div>
+
<div id="content" class="home">
{% if content %}{{ content }}{% endif %}
+ <div piwik-reporting-page ng-cloak></div>
</div>
<div class="clear"></div>
</div>
diff --git a/plugins/CoreHome/templates/getDefaultIndexView.twig b/plugins/CoreHome/templates/getDefaultIndexView.twig
index 7b46ca3f76..4efd453159 100644
--- a/plugins/CoreHome/templates/getDefaultIndexView.twig
+++ b/plugins/CoreHome/templates/getDefaultIndexView.twig
@@ -4,9 +4,8 @@
{% include "@CoreHome/_siteSelectHeader.twig" %}
-{% if (menu is defined and menu) %}
- {% include "@CoreHome/_menu.twig" %}
-{% endif %}
+<div piwik-reporting-menu></div>
+<div class="nav_sep"></div>
{% include "@CoreHome/_indexContent.twig" %}
diff --git a/plugins/CoreHome/templates/widgetContainer.twig b/plugins/CoreHome/templates/widgetContainer.twig
new file mode 100755
index 0000000000..b3eda12997
--- /dev/null
+++ b/plugins/CoreHome/templates/widgetContainer.twig
@@ -0,0 +1,18 @@
+<div>
+ <div piwik-widget
+ containerid="{{ containerId|e('html_attr') }}"
+ widgetized="{% if isWidgetized %}true{% else %}false{% endif %}"></div>
+
+ <script type="text/javascript">
+ $(function () {
+
+ var piwikWidget = $('[piwik-widget][containerid={{ containerId|e('js') }}]');
+
+ angular.element(document).injector().invoke(function($compile) {
+ var scope = angular.element(piwikWidget).scope();
+ $compile(piwikWidget)(scope.$new());
+ });
+
+ });
+ </script>
+</div> \ No newline at end of file
diff --git a/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php
index 5675153c34..5114167364 100644
--- a/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php
+++ b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php
@@ -12,7 +12,6 @@ use Piwik\Archive\DataTableFactory;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\DataTable\Row;
-use Piwik\Menu\MenuMain;
use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator;
use Piwik\Url;
@@ -76,7 +75,6 @@ class Evolution extends JqplotDataGenerator
$periodLabel = reset($dataTables)->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX)->getLabel();
$axisXOnClick = array();
- $queryStringAsHash = $this->getQueryStringAsHash();
foreach ($dataTable->getDataTables() as $metadataDataTable) {
$dateInUrl = $metadataDataTable->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX)->getDateStart();
$parameters = array(
@@ -85,16 +83,7 @@ class Evolution extends JqplotDataGenerator
'date' => $dateInUrl->toString(),
'segment' => \Piwik\API\Request::getRawSegmentFromRequest()
);
- $hash = '';
- if (!empty($queryStringAsHash)) {
- $hash = '#' . Url::getQueryStringFromParameters($queryStringAsHash + $parameters);
- }
- $link = 'index.php?' .
- Url::getQueryStringFromParameters(array(
- 'module' => 'CoreHome',
- 'action' => 'index',
- ) + $parameters)
- . $hash;
+ $link = Url::getQueryStringFromParameters($parameters);
$axisXOnClick[] = $link;
}
$visualization->setAxisXOnClick($axisXOnClick);
@@ -144,34 +133,6 @@ class Evolution extends JqplotDataGenerator
return $label;
}
- /**
- * We link the graph dots to the same report as currently being displayed (only the date would change).
- *
- * In some cases the widget is loaded within a report that doesn't exist as such.
- * For example, the dashboards loads the 'Last visits graph' widget which can't be directly linked to.
- * Instead, the graph must link back to the dashboard.
- *
- * In other cases, like Visitors>Overview or the Goals graphs, we can link the graph clicks to the same report.
- *
- * To detect whether or not we can link to a report, we simply check if the current URL from which it was loaded
- * belongs to the menu or not. If it doesn't belong to the menu, we do not append the hash to the URL,
- * which results in loading the dashboard.
- *
- * @return array Query string array to append to the URL hash or false if the dashboard should be displayed
- */
- private function getQueryStringAsHash()
- {
- $queryString = Url::getArrayFromCurrentQueryString();
- $piwikParameters = array('idSite', 'date', 'period', 'XDEBUG_SESSION_START', 'KEY');
- foreach ($piwikParameters as $parameter) {
- unset($queryString[$parameter]);
- }
- if (MenuMain::getInstance()->isUrlFound($queryString)) {
- return $queryString;
- }
- return false;
- }
-
private function isLinkEnabled()
{
static $linkEnabled;
diff --git a/plugins/CoreVisualizations/Visualizations/Sparkline.php b/plugins/CoreVisualizations/Visualizations/Sparkline.php
index 2ca75bbcfe..3c1dbf5a56 100644
--- a/plugins/CoreVisualizations/Visualizations/Sparkline.php
+++ b/plugins/CoreVisualizations/Visualizations/Sparkline.php
@@ -25,7 +25,7 @@ class Sparkline extends ViewDataTable
* @see ViewDataTable::main()
* @return mixed
*/
- protected function buildView()
+ public function render()
{
// If period=range, we force the sparkline to draw daily data points
$period = Common::getRequestVar('period');
@@ -58,7 +58,7 @@ class Sparkline extends ViewDataTable
$graph->main();
- return $graph;
+ return $graph->render();
}
/**
diff --git a/plugins/CoreVisualizations/Visualizations/Sparklines.php b/plugins/CoreVisualizations/Visualizations/Sparklines.php
new file mode 100644
index 0000000000..3b576c885e
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/Sparklines.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreVisualizations\Visualizations;
+
+use Piwik\DataTable;
+use Piwik\Metrics;
+use Piwik\Plugin\ViewDataTable;
+use Piwik\Url;
+use Piwik\View;
+
+/**
+ * Reads the requested DataTable from the API and prepares data for the Sparklines view. It can display any amount
+ * of sparklines. Within a reporting page sparklines are shown in 2 columns, in a dashboard or when exported as a widget
+ * the sparklines are shown in one column.
+ *
+ * The sparklines view currently only supports requesting columns from the same API (the API method of the defining
+ * report) via {Sparklines\Config::addSparklineMetric($columns = array('nb_visits', 'nb_unique_visitors'))}.
+ *
+ * Example:
+ * $view->config->addSparklineMetric('nb_visits'); // if an array of metrics given, they will be displayed comma separated
+ * $view->config->addTranslation('nb_visits', 'Visits');
+ * Results in: [sparkline image] X visits
+ * Data is fetched from the configured $view->requestConfig->apiMethodToRequestDataTable.
+ *
+ * In case you want to add any custom sparklines from any other API method you can call
+ * {@link Sparklines\Config::addSparkline()}.
+ *
+ * Example:
+ * $sparklineUrlParams = array('columns' => array('nb_visits));
+ * $evolution = array('currentValue' => 5, 'pastValue' => 10, 'tooltip' => 'Foo bar');
+ * $view->config->addSparkline($sparklineUrlParams, $value = 5, $description = 'Visits', $evolution);
+ *
+ * @property Sparklines\Config $config
+ */
+class Sparklines extends ViewDataTable
+{
+ const ID = 'sparklines';
+
+ public static function getDefaultConfig()
+ {
+ return new Sparklines\Config();
+ }
+
+ /**
+ * @see ViewDataTable::main()
+ * @return mixed
+ */
+ public function render()
+ {
+ $view = new View('@CoreVisualizations/_dataTableViz_sparklines.twig');
+
+ $columnsList = array();
+ if ($this->config->hasSparklineMetrics()) {
+ foreach ($this->config->getSparklineMetrics() as $cols) {
+ $columnsList = array_merge($cols['columns'], $columnsList);
+ }
+ }
+
+ $this->requestConfig->request_parameters_to_modify['columns'] = $columnsList;
+ $this->requestConfig->request_parameters_to_modify['format_metrics'] = '1';
+
+ if (!empty($this->requestConfig->apiMethodToRequestDataTable)) {
+ $this->fetchConfiguredSparklines();
+ }
+
+ $view->sparklines = $this->config->getSortedSparklines();
+
+ return $view->render();
+ }
+
+ private function fetchConfiguredSparklines()
+ {
+ $data = $this->loadDataTableFromAPI();
+
+ $this->applyFilters($data);
+
+ if (!$this->config->hasSparklineMetrics()) {
+ foreach ($data->getColumns() as $column) {
+ $this->config->addSparklineMetric($column);
+ }
+ }
+
+ $translations = $this->config->translations;
+
+ $firstRow = $data->getFirstRow();
+
+ foreach ($this->config->getSparklineMetrics() as $sparklineMetric) {
+ $column = $sparklineMetric['columns'];
+ $order = $sparklineMetric['order'];
+
+ if ($column === 'label') {
+ continue;
+ }
+
+ if (empty($column)) {
+ $this->config->addPlaceholder($order);
+ continue;
+ }
+
+ if (!is_array($column)) {
+ $column = array($column);
+ }
+
+ $values = array();
+ $descriptions = array();
+
+ foreach ($column as $col) {
+ $value = $firstRow->getColumn($col);
+
+ if ($value === false) {
+ $value = 0;
+ }
+
+ $values[] = $value;
+ $descriptions[] = isset($translations[$col]) ? $translations[$col] : $col;
+ }
+
+ $sparklineUrlParams = array(
+ 'columns' => $column,
+ 'module' => $this->requestConfig->getApiModuleToRequest(),
+ 'action' => $this->requestConfig->getApiMethodToRequest()
+ );
+
+ $this->config->addSparkline($sparklineUrlParams, $values, $descriptions, null, $order);
+ }
+ }
+
+ private function applyFilters(DataTable\DataTableInterface $table)
+ {
+ foreach ($this->config->getPriorityFilters() as $filter) {
+ $table->filter($filter[0], $filter[1]);
+ }
+
+ // queue other filters so they can be applied later if queued filters are disabled
+ foreach ($this->config->getPresentationFilters() as $filter) {
+ $table->queueFilter($filter[0], $filter[1]);
+ }
+
+ $table->applyQueuedFilters();
+ }
+}
diff --git a/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php b/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php
new file mode 100644
index 0000000000..ca54a6d564
--- /dev/null
+++ b/plugins/CoreVisualizations/Visualizations/Sparklines/Config.php
@@ -0,0 +1,354 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Common;
+use Piwik\DataTable\Filter\CalculateEvolutionFilter;
+use Piwik\Metrics;
+use Piwik\NoAccessException;
+use Piwik\Period\Range;
+use Piwik\Site;
+use Piwik\Url;
+
+/**
+ * DataTable Visualization that derives from Sparklines.
+ */
+class Config extends \Piwik\ViewDataTable\Config
+{
+ /**
+ * Holds metrics / column names that will be used to fetch data from the configured $requestConfig API.
+ * Default value: array
+ */
+ private $sparkline_metrics = array();
+
+ /**
+ * Holds the actual sparkline entries based on fetched data that will be used in the template.
+ * @var array
+ */
+ private $sparklines = array();
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->translations = Metrics::getDefaultMetricTranslations();
+ }
+
+ /**
+ * @ignore
+ * @return array
+ */
+ public function getSparklineMetrics()
+ {
+ return $this->sparkline_metrics;
+ }
+
+ /**
+ * @ignore
+ * @return bool
+ */
+ public function hasSparklineMetrics()
+ {
+ return !empty($this->sparkline_metrics);
+ }
+
+ /**
+ * Removes an existing sparkline entry. Especially useful in dataTable filters in case sparklines should be not
+ * displayed depending on the fetched data.
+ *
+ * Example:
+ * $config->addSparklineMetric('nb_users');
+ * $config->filters[] = function ($dataTable) use ($config) {
+ * if ($dataTable->getFirstRow()->getColumn('nb_users') == 0) {
+ * // do not show a sparkline if there are no recorded users
+ * $config->removeSparklineMetric('nb_users');
+ * }
+ * }
+ *
+ * @param array|string $metricNames The name of the metrics in the same format they were used when added via
+ * {@link addSparklineMetric}
+ */
+ public function removeSparklineMetric($metricNames)
+ {
+ foreach ($this->sparkline_metrics as $index => $metric) {
+ if ($metric['columns'] === $metricNames) {
+ array_splice($this->sparkline_metrics, $index, 1);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Replaces an existing sparkline entry with different columns. Especially useful in dataTable filters in case
+ * sparklines should be not displayed depending on the fetched data.
+ *
+ * Example:
+ * $config->addSparklineMetric('nb_users');
+ * $config->filters[] = function ($dataTable) use ($config) {
+ * if ($dataTable->getFirstRow()->getColumn('nb_users') == 0) {
+ * // instead of showing the sparklines for users, show a placeholder if there are no recorded users
+ * $config->replaceSparklineMetric(array('nb_users'), '');
+ * }
+ * }
+ *
+ * @param array|string $metricNames The name of the metrics in the same format they were used when added via
+ * {@link addSparklineMetric}
+ * @param array|string $replacementColumns The removed columns will be replaced with these columns
+ */
+ public function replaceSparklineMetric($metricNames, $replacementColumns)
+ {
+ foreach ($this->sparkline_metrics as $index => $metric) {
+ if ($metric['columns'] === $metricNames) {
+ $this->sparkline_metrics[$index]['columns'] = $replacementColumns;
+ }
+ }
+ }
+
+ /**
+ * Adds a new sparkline.
+ *
+ * It will show a sparkline image, the value of the resolved metric name and a descrption. Optionally, multiple
+ * values can be shown after a sparkline image by passing multiple metric names
+ * (eg array('nb_visits', 'nb_actions')). The data will be requested from the configured api method see
+ * {@link Piwik\ViewDataTable\RequestConfig::$apiMethodToRequestDataTable}.
+ *
+ * Example:
+ * $config->addSparklineMetric('nb_visits');
+ * $config->addTranslation('nb_visits', 'Visits');
+ * Results in: [sparkline image] X visits
+ *
+ * Example:
+ * $config->addSparklineMetric(array('nb_visits', 'nb_actions'));
+ * $config->addTranslations(array('nb_visits' => 'Visits', 'nb_actions' => 'Actions'));
+ * Results in: [sparkline image] X visits, Y actions
+ *
+ * @param string|array $metricName Either one metric name (eg 'nb_visits') or an array of metric names
+ * @param int|null $order Defines the order. The lower the order the earlier the sparkline will be displayed.
+ * By default the sparkline will be appended to the end.
+ */
+ public function addSparklineMetric($metricName, $order = null)
+ {
+ $this->sparkline_metrics[] = array(
+ 'columns' => $metricName,
+ 'order' => $order
+ );
+ }
+
+ /**
+ * Adds a placeholder. In this case nothing will be shown, neither a sparkline nor any description. This can be
+ * useful if you want to have some kind of separator. Eg if you want to have a sparkline on the left side but
+ * not sparkline on the right side.
+ *
+ * @param int|null $order Defines the order. The lower the order the earlier the sparkline will be displayed.
+ * By default the sparkline will be appended to the end.
+ */
+ public function addPlaceholder($order = null)
+ {
+ $this->sparklines[] = array(
+ 'url' => '',
+ 'metrics' => array(),
+ 'order' => $this->getSparklineOrder($order)
+ );
+ }
+
+ /**
+ * Add a new sparkline to be displayed to the view.
+ *
+ * Each sparkline can consist of one or multiple metrics. One metric consists of a value and a description. By
+ * default the value is shown first, then the description. The description can optionally contain a '%s' in case
+ * the value shall be displayed within the description. If multiple metrics are given, they will be separated by
+ * a comma.
+ *
+ * @param array $requestParamsForSparkline You need to at least set a module / action eg
+ * array('columns' => array('nb_visit'), 'module' => '', 'action' => '')
+ * @param int|float|string|array $value Either the metric value or an array of values.
+ * @param string|array $description Either one description or an array of descriptions. If an array, both
+ * $value and $description need the same amount of array entries.
+ * $description[0] should be the description for $value[0].
+ * $description should be already translated. If $value should appear
+ * somewhere within the text a `%s` can be used in the translation.
+ * @param array|null $evolution Optional array containing at least the array keys 'currentValue' and
+ * 'pastValue' which are needed to calculate the correct percentage.
+ * An optional 'tooltip' can be set as well. Eg
+ * array('currentValue' => 10, 'pastValue' => 20,
+ * 'tooltip' => '10 visits in 2015-07-26 compared to 20 visits in 2015-07-25')
+ * @param int $order Defines the order. The lower the order the earlier the sparkline will be
+ * displayed. By default the sparkline will be appended to the end.
+ * @throws \Exception In case an evolution parameter is set but has wrong data structure
+ */
+ public function addSparkline($requestParamsForSparkline, $value, $description, $evolution = null, $order = null)
+ {
+ $metrics = array();
+
+ if (is_array($value)) {
+ $values = $value;
+ } else {
+ $values = array($value);
+ }
+
+ if (!is_array($description)) {
+ $description = array($description);
+ }
+
+ if (count($values) === count($description)) {
+ foreach ($values as $index => $value) {
+ $metrics[] = array(
+ 'value' => $value,
+ 'description' => $description[$index]
+ );
+ }
+ } else {
+ $msg = 'The number of values and descriptions need to be the same to add a sparkline. ';
+ $msg .= 'Values: ' . implode(', ', $values). ' Descriptions: ' . implode(', ', $description);
+ throw new \Exception($msg);
+ }
+
+ if (empty($metrics)) {
+ return;
+ }
+
+ $sparkline = array(
+ 'url' => $this->getUrlSparkline($requestParamsForSparkline),
+ 'metrics' => $metrics,
+ 'order' => $this->getSparklineOrder($order)
+ );
+
+ if (!empty($evolution)) {
+ if (!is_array($evolution) ||
+ !array_key_exists('currentValue', $evolution) ||
+ !array_key_exists('pastValue', $evolution)) {
+ throw new \Exception('In order to show an evolution in the sparklines view a currentValue and pastValue array key needs to be present');
+ }
+
+ $evolutionPercent = CalculateEvolutionFilter::calculate($evolution['currentValue'], $evolution['pastValue'], $precision = 1);
+
+ // do not display evolution if evolution percent is 0 and current value is 0
+ if ($evolutionPercent != 0 || $evolution['currentValue'] != 0) {
+ $sparkline['evolution'] = array(
+ 'percent' => $evolutionPercent,
+ 'tooltip' => !empty($evolution['tooltip']) ? $evolution['tooltip'] : null
+ );
+ }
+
+ }
+
+ $this->sparklines[] = $sparkline;
+ }
+
+ /**
+ * @return array
+ * @ignore
+ */
+ public function getSortedSparklines()
+ {
+ usort($this->sparklines, function ($a, $b) {
+ if ($a['order'] == $b['order']) {
+ return 0;
+ }
+ return ($a['order'] < $b['order']) ? -1 : 1;
+ });
+
+ return $this->sparklines;
+ }
+
+ private function getSparklineOrder($order)
+ {
+ if (!isset($order)) {
+ // make sure to append to the end if nothing set (in the order they are added)
+ $order = 999 + count($this->sparklines);
+ }
+
+ return (int) $order;
+ }
+
+ /**
+ * Returns a URL to a sparkline image for a report served by the current plugin.
+ *
+ * The result of this URL should be used with the [sparkline()](/api-reference/Piwik/View#twig) twig function.
+ *
+ * The current site ID and period will be used.
+ *
+ * @param array $customParameters The array of query parameter name/value pairs that
+ * should be set in result URL.
+ * @return string The generated URL.
+ */
+ private function getUrlSparkline($customParameters = array())
+ {
+ $customParameters['viewDataTable'] = 'sparkline';
+
+ $params = $this->getGraphParamsModified($customParameters);
+
+ // convert array values to comma separated
+ foreach ($params as &$value) {
+ if (is_array($value)) {
+ $value = rawurlencode(implode(',', $value));
+ }
+ }
+ $url = Url::getCurrentQueryStringWithParametersModified($params);
+ return $url;
+ }
+
+ /**
+ * Returns the array of new processed parameters once the parameters are applied.
+ * For example: if you set range=last30 and date=2008-03-10,
+ * the date element of the returned array will be "2008-02-10,2008-03-10"
+ *
+ * Parameters you can set:
+ * - range: last30, previous10, etc.
+ * - date: YYYY-MM-DD, today, yesterday
+ * - period: day, week, month, year
+ *
+ * @param array $paramsToSet array( 'date' => 'last50', 'viewDataTable' =>'sparkline' )
+ * @throws \Piwik\NoAccessException
+ * @return array
+ */
+ private function getGraphParamsModified($paramsToSet = array())
+ {
+ if (!isset($paramsToSet['period'])) {
+ $period = Common::getRequestVar('period');
+ } else {
+ $period = $paramsToSet['period'];
+ }
+
+ if ($period == 'range') {
+ return $paramsToSet;
+ }
+
+ if (!isset($paramsToSet['range'])) {
+ $range = 'last30';
+ } else {
+ $range = $paramsToSet['range'];
+ }
+
+ if (!isset($paramsToSet['idSite'])) {
+ $idSite = Common::getRequestVar('idSite');
+ } else {
+ $idSite = $paramsToSet['idSite'];
+ }
+
+ if (!isset($paramsToSet['date'])) {
+ $endDate = Common::getRequestVar('date', 'yesterday', 'string');
+ } else {
+ $endDate = $paramsToSet['date'];
+ }
+
+ $site = new Site($idSite);
+
+ if (is_null($site)) {
+ throw new NoAccessException("Website not initialized, check that you are logged in and/or using the correct token_auth.");
+ }
+
+ $paramDate = Range::getRelativeToEndDate($period, $range, $endDate, $site);
+
+ $params = array_merge($paramsToSet, array('date' => $paramDate));
+ return $params;
+ }
+
+}
diff --git a/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js b/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js
index 3b62e9197e..b77add4962 100644
--- a/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js
+++ b/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js
@@ -90,36 +90,7 @@
&& typeof self.jqplotParams.axes.xaxis.onclick[lastTick] == 'string') {
var url = self.jqplotParams.axes.xaxis.onclick[lastTick];
- if (url && -1 === url.indexOf('#')) {
- var module = broadcast.getValueFromHash('module');
- var action = broadcast.getValueFromHash('action');
- var idGoal = broadcast.getValueFromHash('idGoal');
- var idSite = broadcast.getValueFromUrl('idSite', url);
- var period = broadcast.getValueFromUrl('period', url);
- var date = broadcast.getValueFromUrl('date', url);
-
- if (module && action) {
- url += '#module=' + module + '&action=' + action;
-
- if (idSite) {
- url += '&idSite=' + idSite;
- }
-
- if (idGoal) {
- url += '&idGoal=' + idGoal;
- }
-
- if (period) {
- url += '&period=' + period;
- }
-
- if (period) {
- url += '&date=' + date;
- }
- }
- }
-
- piwikHelper.redirectToUrl(url);
+ broadcast.propagateNewPage(url);
}
})
.on('jqplotPiwikTickOver', function (e, tick) {
@@ -161,6 +132,10 @@
render: function () {
JqplotGraphDataTablePrototype.render.call(this);
+
+ if (initializeSparklines) {
+ initializeSparklines();
+ }
}
});
diff --git a/plugins/CoreVisualizations/templates/_dataTableViz_sparklines.twig b/plugins/CoreVisualizations/templates/_dataTableViz_sparklines.twig
new file mode 100644
index 0000000000..359c0f9768
--- /dev/null
+++ b/plugins/CoreVisualizations/templates/_dataTableViz_sparklines.twig
@@ -0,0 +1,31 @@
+{% import '@CoreVisualizations/macros.twig' as macros %}
+
+{% if not isWidget %}
+<div class="row">
+ <div class="col-md-6">
+{% endif %}
+
+ {% for key, sparkline in sparklines %}
+ {% if key is even %}
+ {{ macros.singleSparkline(sparkline) }}
+ {% endif %}
+ {% endfor %}
+
+{% if not isWidget %}
+ </div>
+ <div class="col-md-6">
+{% endif %}
+
+ {% for key, sparkline in sparklines %}
+ {% if key is odd %}
+ {{ macros.singleSparkline(sparkline) }}
+ {% endif %}
+ {% endfor %}
+
+{% if not isWidget %}
+ </div>
+</div>
+{% endif %}
+
+{% include "_sparklineFooter.twig" %}
+
diff --git a/plugins/CoreVisualizations/templates/macros.twig b/plugins/CoreVisualizations/templates/macros.twig
new file mode 100644
index 0000000000..ffd1885be1
--- /dev/null
+++ b/plugins/CoreVisualizations/templates/macros.twig
@@ -0,0 +1,32 @@
+{% macro singleSparkline(sparkline) %}
+ <div class="sparkline">
+ {% if sparkline.url %}{{ sparkline(sparkline.url)|raw }}{% endif %}
+ {% for metric in sparkline.metrics %}
+ {% if '%s' in metric.description -%}
+ {{ metric.description|translate("<strong>"~metric.value~"</strong>")|raw }}
+ {%- else %}
+ <strong>{{ metric.value }}</strong> {{ metric.description }}
+ {%- endif %}{% if not loop.last %}, {% endif %}
+ {% endfor %}
+ {% if sparkline.evolution is defined %}
+
+ {% set evolutionPretty = sparkline.evolution.percent %}
+
+ {% if sparkline.evolution.percent < 0 %}
+ {% set evolutionClass = 'negative-evolution' %}
+ {% set evolutionIcon = 'arrow_down.png' %}
+ {% elseif sparkline.evolution.percent == 0 %}
+ {% set evolutionClass = 'neutral-evolution' %}
+ {% set evolutionIcon = 'stop.png' %}
+ {% else %}
+ {% set evolutionClass = 'positive-evolution' %}
+ {% set evolutionIcon = 'arrow_up.png' %}
+ {% set evolutionPretty = '+' ~ sparkline.evolution.percent %}
+ {% endif %}
+
+ <span class="metricEvolution" title="{{ sparkline.evolution.tooltip }}"><img
+ style="padding-right:4px" src="plugins/MultiSites/images/{{ evolutionIcon }}"/>
+ <strong class="{{ evolutionClass }}">{{ evolutionPretty }}</strong></span>
+ {% endif %}
+ </div>
+{% endmacro %}
diff --git a/plugins/CoreVisualizations/tests/Integration/SparklinesConfigTest.php b/plugins/CoreVisualizations/tests/Integration/SparklinesConfigTest.php
new file mode 100644
index 0000000000..3541344f04
--- /dev/null
+++ b/plugins/CoreVisualizations/tests/Integration/SparklinesConfigTest.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\CoreVisualizations\tests\Integration;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines\Config;
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Tests\Framework\Mock\FakeAccess;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+
+/**
+ * @group CoreVisualizations
+ * @group SparklinesConfigTest
+ * @group Plugins
+ */
+class SparklinesConfigTest extends IntegrationTestCase
+{
+ /**
+ * @var Config
+ */
+ private $config;
+
+ public function setUp()
+ {
+ parent::setUp();
+ FakeAccess::$superUser = true;
+
+ if (!Fixture::siteCreated(1)) {
+ Fixture::createWebsite('2014-01-01 00:00:00');
+ }
+
+ $this->config = new Config();
+ }
+
+ public function test_addSparkline_shouldAddAMinimalSparklineWithOneValueAndUseDefaultOrder()
+ {
+ $this->config->addSparkline($this->sparklineParams(), $value = 10, $description = 'Visits');
+
+ $expectedSparkline = array(
+ 'url' => '?period=day&date=2012-03-06,2012-04-04&idSite=1&module=CoreHome&action=renderMe&viewDataTable=sparkline',
+ 'metrics' => array (
+ array ('value' => 10, 'description' => 'Visits'),
+ ),
+ 'order' => 999
+ );
+
+ $this->assertSame(array($expectedSparkline), $this->config->getSortedSparklines());
+ }
+
+ public function test_addSparkline_shouldAddSparklineWithMultipleValues()
+ {
+ $this->config->addSparkline($this->sparklineParams(), $values = array(10, 20), $description = array('Visits', 'Actions'));
+
+ $sparklines = $this->config->getSortedSparklines();
+
+ $this->assertSame(array (
+ array ('value' => 10, 'description' => 'Visits'),
+ array ('value' => 20, 'description' => 'Actions'),
+ ), $sparklines[0]['metrics']);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Values: 10, 20, 30 Descriptions: Visits, Actions
+ */
+ public function test_addSparkline_shouldThrowAnException_IfValuesDoesNotMatchAmountOfDescriptions()
+ {
+ $this->config->addSparkline($this->sparklineParams(), $values = array(10, 20, 30), $description = array('Visits', 'Actions'));
+ }
+
+ public function test_addSparkline_shouldAddEvolution()
+ {
+ $evolution = array('currentValue' => 10, 'pastValue' => 21,
+ 'tooltip' => '1 visit compared to 2 visits');
+ $this->config->addSparkline($this->sparklineParams(), $value = 10, $description = 'Visits', $evolution);
+
+ $sparklines = $this->config->getSortedSparklines();
+
+ $this->assertSame(array (
+ 'percent' => '-52.4%',
+ 'tooltip' => '1 visit compared to 2 visits'
+ ), $sparklines[0]['evolution']);
+ }
+
+ public function test_addSparkline_shouldAddOrder()
+ {
+ $this->config->addSparkline($this->sparklineParams(), $value = 10, $description = 'Visits', $evolution = null, $order = '42');
+
+ $sparklines = $this->config->getSortedSparklines();
+
+ $this->assertSame(42, $sparklines[0]['order']);
+ }
+
+ public function test_addSparkline_shouldBeAbleToBuildSparklineUrlBasedOnGETparams()
+ {
+ $oldGet = $_GET;
+ $_GET = $this->sparklineParams();
+ $this->config->addSparkline(array('columns' => 'nb_visits'), $value = 10, $description = 'Visits');
+ $_GET = $oldGet;
+
+ $sparklines = $this->config->getSortedSparklines();
+
+ $this->assertSame('?columns=nb_visits&viewDataTable=sparkline&date=2012-03-06,2012-04-04', $sparklines[0]['url']);
+ }
+
+ private function sparklineParams($params = array())
+ {
+ $params['period'] = 'day';
+ $params['date'] = '2012-04-04';
+ $params['idSite'] = '1';
+ $params['module'] = 'CoreHome';
+ $params['action'] = 'renderMe';
+
+ return $params;
+ }
+
+ public function provideContainerConfig()
+ {
+ return array(
+ 'Piwik\Access' => new FakeAccess()
+ );
+ }
+}
diff --git a/plugins/CoreVisualizations/tests/Unit/SparklinesConfigTest.php b/plugins/CoreVisualizations/tests/Unit/SparklinesConfigTest.php
new file mode 100644
index 0000000000..516f19f8e1
--- /dev/null
+++ b/plugins/CoreVisualizations/tests/Unit/SparklinesConfigTest.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\CoreVisualizations\tests\Unit;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines\Config;
+
+/**
+ * @group CoreVisualizations
+ * @group SparklinesConfigTest
+ * @group Sparklines
+ * @group Plugins
+ */
+class SparklinesConfigTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @var Config
+ */
+ private $config;
+
+ public function setUp()
+ {
+ $this->config = new Config();
+ }
+
+ public function test_hasSparklineMetrics_shouldNotHaveSparklineMetrics_ByDefault()
+ {
+ $this->assertFalse($this->config->hasSparklineMetrics());
+ }
+
+ public function test_hasSparklineMetrics_shouldHaveSparklineMetrics_IfAtLeastOneWasAdded()
+ {
+ $this->config->addSparklineMetric('nb_visits');
+
+ $this->assertTrue($this->config->hasSparklineMetrics());
+ }
+
+ public function test_getSparklineMetrics_shouldNotHaveSparklineMetrics_ByDefault()
+ {
+ $this->assertSame(array(), $this->config->getSparklineMetrics());
+ }
+
+ public function test_addSparklineMetric_getSparklineMetrics_shouldReturnAllAddedSparklineMetrics()
+ {
+ $this->addFewSparklines();
+
+ $this->assertSame(array(
+ array('columns' => 'nb_visits', 'order' => null),
+ array('columns' => 'nb_unique_visitors', 'order' => 99),
+ array('columns' => array('nb_downloads', 'nb_outlinks'), 'order' => null),
+ ), $this->config->getSparklineMetrics());
+ }
+
+ public function test_removeSparklineMetric_shouldRemoveMetric_IfOnlySingleMetricIsGiven()
+ {
+ $this->addFewSparklines();
+
+ $this->config->removeSparklineMetric('nb_unique_visitors');
+
+ $this->assertSame(array(
+ array('columns' => 'nb_visits', 'order' => null),
+ array('columns' => array('nb_downloads', 'nb_outlinks'), 'order' => null),
+ ), $this->config->getSparklineMetrics());
+ }
+
+ public function test_removeSparklineMetric_shouldRemoveMetric_IfMultipleMetricsAreGiven()
+ {
+ $this->addFewSparklines();
+
+ $this->config->removeSparklineMetric(array('nb_downloads', 'nb_outlinks'));
+
+ $this->assertSame(array(
+ array('columns' => 'nb_visits', 'order' => null),
+ array('columns' => 'nb_unique_visitors', 'order' => 99),
+ ), $this->config->getSparklineMetrics());
+ }
+
+ public function test_replaceSparklineMetric_shouldBeAbleToReplaceColumns_IfSingleMetricIsGiven()
+ {
+ $this->addFewSparklines();
+
+ $this->config->replaceSparklineMetric('nb_unique_visitors', '');
+
+ $this->assertSame(array(
+ array('columns' => 'nb_visits', 'order' => null),
+ array('columns' => '', 'order' => 99),
+ array('columns' => array('nb_downloads', 'nb_outlinks'), 'order' => null),
+ ), $this->config->getSparklineMetrics());
+ }
+
+ public function test_replaceSparklineMetric_shouldBeAbleToReplaceColumns_IfMultipleMetricsAreGiven()
+ {
+ $this->addFewSparklines();
+
+ $this->config->replaceSparklineMetric(array('nb_downloads', 'nb_outlinks'), '');
+
+ $this->assertSame(array(
+ array('columns' => 'nb_visits', 'order' => null),
+ array('columns' => 'nb_unique_visitors', 'order' => 99),
+ array('columns' => '', 'order' => null),
+ ), $this->config->getSparklineMetrics());
+ }
+
+ public function test_addPlaceholder_getSortedSparklines()
+ {
+ $this->config->addPlaceholder();
+ $this->config->addPlaceholder($order = 10);
+ $this->config->addPlaceholder();
+ $this->config->addPlaceholder($order = 3);
+
+ $this->assertSame(array(
+ array('url' => '', 'metrics' => array(), 'order' => 3),
+ array('url' => '', 'metrics' => array(), 'order' => 10),
+ array('url' => '', 'metrics' => array(), 'order' => 999),
+ array('url' => '', 'metrics' => array(), 'order' => 1001),
+ ), $this->config->getSortedSparklines());
+ }
+
+ private function addFewSparklines()
+ {
+ $this->config->addSparklineMetric('nb_visits');
+ $this->config->addSparklineMetric('nb_unique_visitors', 99);
+ $this->config->addSparklineMetric(array('nb_downloads', 'nb_outlinks'));
+ }
+
+}
diff --git a/plugins/CustomVariables/Categories/CustomVariablesSubcategory.php b/plugins/CustomVariables/Categories/CustomVariablesSubcategory.php
new file mode 100644
index 0000000000..d81b56568c
--- /dev/null
+++ b/plugins/CustomVariables/Categories/CustomVariablesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CustomVariables\Categories;
+
+use Piwik\Category\Subcategory;
+
+class CustomVariablesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'CustomVariables_CustomVariables';
+ protected $order = 10;
+
+}
diff --git a/plugins/CustomVariables/Reports/Base.php b/plugins/CustomVariables/Reports/Base.php
index be48bf4d44..0c6bcbec0b 100644
--- a/plugins/CustomVariables/Reports/Base.php
+++ b/plugins/CustomVariables/Reports/Base.php
@@ -14,7 +14,7 @@ abstract class Base extends \Piwik\Plugin\Report
protected function init()
{
- $this->category = 'General_Visitors';
+ $this->categoryId = 'General_Visitors';
}
}
diff --git a/plugins/CustomVariables/Reports/GetCustomVariables.php b/plugins/CustomVariables/Reports/GetCustomVariables.php
index 2ddedc4e97..c6b28b6562 100644
--- a/plugins/CustomVariables/Reports/GetCustomVariables.php
+++ b/plugins/CustomVariables/Reports/GetCustomVariables.php
@@ -23,8 +23,8 @@ class GetCustomVariables extends Base
array('<br />', '<a href="http://piwik.org/docs/custom-variables/" rel="noreferrer" target="_blank">', '</a>'));
$this->actionToLoadSubTables = 'getCustomVariablesValuesFromNameId';
$this->order = 10;
- $this->widgetTitle = 'CustomVariables_CustomVariables';
- $this->menuTitle = 'CustomVariables_CustomVariables';
+
+ $this->subcategoryId = 'CustomVariables_CustomVariables';
$this->hasGoalMetrics = true;
}
diff --git a/plugins/DBStats/Reports/GetMetricDataSummary.php b/plugins/DBStats/Reports/GetMetricDataSummary.php
index 92b93fce9b..94735c4e03 100644
--- a/plugins/DBStats/Reports/GetMetricDataSummary.php
+++ b/plugins/DBStats/Reports/GetMetricDataSummary.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DBStats\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
+use Piwik\Plugin\Reports;
/**
* Shows a datatable that displays the amount of space each numeric archive table
@@ -34,7 +35,7 @@ class GetMetricDataSummary extends Base
public function getRelatedReports()
{
return array(
- self::factory('DBStats', 'getMetricDataSummaryByYear'),
+ Reports::factory('DBStats', 'getMetricDataSummaryByYear'),
);
}
diff --git a/plugins/DBStats/Reports/GetMetricDataSummaryByYear.php b/plugins/DBStats/Reports/GetMetricDataSummaryByYear.php
index bc5e8e5c3c..81b89d5d99 100644
--- a/plugins/DBStats/Reports/GetMetricDataSummaryByYear.php
+++ b/plugins/DBStats/Reports/GetMetricDataSummaryByYear.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DBStats\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
+use Piwik\Plugin\Reports;
/**
* Shows a datatable that displays the amount of space each numeric archive table
@@ -35,7 +36,7 @@ class GetMetricDataSummaryByYear extends Base
public function getRelatedReports()
{
return array(
- self::factory('DBStats', 'getMetricDataSummary'),
+ Reports::factory('DBStats', 'getMetricDataSummary'),
);
}
diff --git a/plugins/DBStats/Reports/GetReportDataSummary.php b/plugins/DBStats/Reports/GetReportDataSummary.php
index d38f3ee717..58c1b065c5 100644
--- a/plugins/DBStats/Reports/GetReportDataSummary.php
+++ b/plugins/DBStats/Reports/GetReportDataSummary.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DBStats\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
+use Piwik\Plugin\Reports;
/**
* Shows a datatable that displays the amount of space each blob archive table
@@ -34,7 +35,7 @@ class GetReportDataSummary extends Base
public function getRelatedReports()
{
return array(
- self::factory('DBStats', 'getReportDataSummaryByYear'),
+ Reports::factory('DBStats', 'getReportDataSummaryByYear'),
);
}
}
diff --git a/plugins/DBStats/Reports/GetReportDataSummaryByYear.php b/plugins/DBStats/Reports/GetReportDataSummaryByYear.php
index 1bbe67e467..7ff78a638b 100644
--- a/plugins/DBStats/Reports/GetReportDataSummaryByYear.php
+++ b/plugins/DBStats/Reports/GetReportDataSummaryByYear.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DBStats\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
+use Piwik\Plugin\Reports;
/**
* Shows a datatable that displays the amount of space each blob archive table
@@ -35,7 +36,7 @@ class GetReportDataSummaryByYear extends Base
public function getRelatedReports()
{
return array(
- self::factory('DBStats', 'getReportDataSummary'),
+ Reports::factory('DBStats', 'getReportDataSummary'),
);
}
diff --git a/plugins/Dashboard/API.php b/plugins/Dashboard/API.php
index f4637e862a..7bd5bd73a5 100644
--- a/plugins/Dashboard/API.php
+++ b/plugins/Dashboard/API.php
@@ -8,7 +8,6 @@
namespace Piwik\Plugins\Dashboard;
use Piwik\Piwik;
-use Piwik\WidgetsList;
/**
* This API is the <a href='http://piwik.org/docs/analytics-api/reference/' rel='noreferrer' target='_blank'>Dashboard API</a>: it gives information about dashboards.
@@ -43,25 +42,22 @@ class API extends \Piwik\Plugin\API
/**
* Get the default dashboard.
- *
- * @return array[]
+ * @return \array[]
*/
private function getDefaultDashboard()
{
$defaultLayout = $this->dashboard->getDefaultLayout();
$defaultLayout = $this->dashboard->decodeLayout($defaultLayout);
+ $defaultDashboard = array('name' => Piwik::translate('Dashboard_Dashboard'), 'layout' => $defaultLayout, 'iddashboard' => 1);
- $defaultDashboard = array('name' => Piwik::translate('Dashboard_Dashboard'), 'layout' => $defaultLayout);
-
- $widgets = $this->getExistingWidgetsWithinDashboard($defaultDashboard);
+ $widgets = $this->getVisibleWidgetsWithinDashboard($defaultDashboard);
return $this->buildDashboard($defaultDashboard, $widgets);
}
/**
* Get all dashboards which a user has created.
- *
- * @return array[]
+ * @return \array[]
*/
private function getUserDashboards()
{
@@ -71,17 +67,14 @@ class API extends \Piwik\Plugin\API
$dashboards = array();
foreach ($userDashboards as $userDashboard) {
-
- if ($this->hasDashboardColumns($userDashboard)) {
- $widgets = $this->getExistingWidgetsWithinDashboard($userDashboard);
- $dashboards[] = $this->buildDashboard($userDashboard, $widgets);
- }
+ $widgets = $this->getVisibleWidgetsWithinDashboard($userDashboard);
+ $dashboards[] = $this->buildDashboard($userDashboard, $widgets);
}
return $dashboards;
}
- private function getExistingWidgetsWithinDashboard($dashboard)
+ private function getVisibleWidgetsWithinDashboard($dashboard)
{
$columns = $this->getColumnsFromDashboard($dashboard);
@@ -91,7 +84,7 @@ class API extends \Piwik\Plugin\API
foreach ($columns as $column) {
foreach ($column as $widget) {
- if ($this->widgetIsNotHidden($widget) && $this->widgetExists($widget)) {
+ if ($this->widgetIsNotHidden($widget) && !empty($widget->parameters->module)) {
$module = $widget->parameters->module;
$action = $widget->parameters->action;
@@ -105,39 +98,24 @@ class API extends \Piwik\Plugin\API
private function getColumnsFromDashboard($dashboard)
{
- if (is_array($dashboard['layout'])) {
-
- return $dashboard['layout'];
+ if (empty($dashboard['layout'])) {
+ return array();
}
- return $dashboard['layout']->columns;
- }
-
- private function hasDashboardColumns($dashboard)
- {
if (is_array($dashboard['layout'])) {
+ return $dashboard['layout'];
+ }
- return !empty($dashboard['layout']);
+ if (!empty($dashboard['layout']->columns)) {
+ return $dashboard['layout']->columns;
}
- return !empty($dashboard['layout']->columns);
+ return array();
}
private function buildDashboard($dashboard, $widgets)
{
- return array('name' => $dashboard['name'], 'widgets' => $widgets);
- }
-
- private function widgetExists($widget)
- {
- if (empty($widget->parameters->module)) {
- return false;
- }
-
- $module = $widget->parameters->module;
- $action = $widget->parameters->action;
-
- return WidgetsList::isDefined($module, $action);
+ return array('name' => $dashboard['name'], 'id' => $dashboard['iddashboard'], 'widgets' => $widgets);
}
private function widgetIsNotHidden($widget)
diff --git a/plugins/Dashboard/Categories/DashboardCategory.php b/plugins/Dashboard/Categories/DashboardCategory.php
new file mode 100644
index 0000000000..99a3785c84
--- /dev/null
+++ b/plugins/Dashboard/Categories/DashboardCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Dashboard\Categories;
+
+use Piwik\Category\Category;
+
+class DashboardCategory extends Category
+{
+ protected $id = 'Dashboard_Dashboard';
+ protected $order = 0;
+}
diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php
index d77c283273..bef5a89237 100644
--- a/plugins/Dashboard/Controller.php
+++ b/plugins/Dashboard/Controller.php
@@ -13,8 +13,6 @@ use Piwik\Db;
use Piwik\Piwik;
use Piwik\Session\SessionNamespace;
use Piwik\View;
-use Piwik\WidgetsList;
-use Piwik\FrontController;
/**
* Dashboard Controller
@@ -39,24 +37,21 @@ class Controller extends \Piwik\Plugin\Controller
$view = new View($template);
$this->setGeneralVariablesView($view);
- $view->availableWidgets = json_encode(WidgetsList::get());
$view->availableLayouts = $this->getAvailableLayouts();
$view->dashboardId = Common::getRequestVar('idDashboard', 1, 'int');
- // get the layout via FrontController so controller events are posted
- $view->dashboardLayout = FrontController::getInstance()->dispatch('Dashboard', 'getDashboardLayout',
- array($checkToken = false));
-
return $view;
}
+ // this
public function embeddedIndex()
{
$view = $this->_getDashboardView('@Dashboard/embeddedIndex');
return $view->render();
}
+ // this is the exported widget
public function index()
{
$view = $this->_getDashboardView('@Dashboard/index');
@@ -70,14 +65,6 @@ class Controller extends \Piwik\Plugin\Controller
return $view->render();
}
- public function getAvailableWidgets()
- {
- $this->checkTokenInUrl();
-
- Json::sendHeaderJSON();
- return json_encode(WidgetsList::get());
- }
-
public function getDashboardLayout($checkToken = true)
{
if ($checkToken) {
diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php
index 9ccbb822e4..5a0a7cc0ec 100644
--- a/plugins/Dashboard/Dashboard.php
+++ b/plugins/Dashboard/Dashboard.php
@@ -11,7 +11,8 @@ namespace Piwik\Plugins\Dashboard;
use Piwik\Common;
use Piwik\Db;
use Piwik\Piwik;
-use Piwik\WidgetsList;
+use Piwik\Category\Subcategory;
+use Piwik\Widget\WidgetConfig;
/**
*/
@@ -26,10 +27,43 @@ class Dashboard extends \Piwik\Plugin
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'UsersManager.deleteUser' => 'deleteDashboardLayout',
- 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys'
+ 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
+ 'Widget.addWidgetConfigs' => 'addWidgetConfigs',
+ 'Category.addSubcategories' => 'addSubcategories'
);
}
+ public function addWidgetConfigs(&$widgets)
+ {
+ $dashboards = API::getInstance()->getDashboards();
+
+ foreach ($dashboards as $dashboard) {
+ $config = new WidgetConfig();
+ $config->setIsNotWidgetizable();
+ $config->setModule('Dashboard');
+ $config->setAction('embeddedIndex');
+ $config->setCategoryId('Dashboard_Dashboard');
+ $config->setSubcategoryId($dashboard['id']);
+ $config->setParameters(array('idDashboard' => $dashboard['id']));
+ $widgets[] = $config;
+ }
+ }
+
+ public function addSubcategories(&$subcategories)
+ {
+ $dashboards = API::getInstance()->getDashboards();
+
+ $order = 0;
+ foreach ($dashboards as $dashboard) {
+ $subcategory = new Subcategory();
+ $subcategory->setName($dashboard['name']);
+ $subcategory->setCategoryId('Dashboard_Dashboard');
+ $subcategory->setId($dashboard['id']);
+ $subcategory->setOrder($order++);
+ $subcategories[] = $subcategory;
+ }
+ }
+
/**
* Returns the layout in the DB for the given user, or false if the layout has not been set yet.
* Parameters must be checked BEFORE this function call
@@ -70,14 +104,14 @@ class Dashboard extends \Piwik\Plugin
$defaultLayout = '[
[
- {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}},
+ {"uniqueId":"widgetVisitsSummarygetEvolutionGraphforceView1viewDataTablegraphEvolution","parameters":{"forceView":"1","viewDataTable":"graphEvolution","module":"VisitsSummary","action":"getEvolutionGraph"}},
{"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}},
- {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}}
+ {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDurationviewDataTablecloud","parameters":{"viewDataTable":"cloud","module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}}
],
[
' . $topWidget . '
{"uniqueId":"widgetReferrersgetWebsites","parameters":{"module":"Referrers","action":"getWebsites"}},
- {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}}
+ {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTimeviewDataTablegraphVerticalBar","parameters":{"viewDataTable": "graphVerticalBar","module":"VisitTime","action":"getVisitInformationPerServerTime"}}
],
[
{"uniqueId":"widgetUserCountryMapvisitorMap","parameters":{"module":"UserCountryMap","action":"visitorMap"}},
@@ -160,24 +194,6 @@ class Dashboard extends \Piwik\Plugin
);
}
- foreach ($layoutObject->columns as &$row) {
- if (!is_array($row)) {
- $row = array();
- continue;
- }
-
- foreach ($row as $widgetId => $widget) {
- if (isset($widget->parameters->module)) {
- $controllerName = $widget->parameters->module;
- $controllerAction = $widget->parameters->action;
- if (!WidgetsList::isDefined($controllerName, $controllerAction)) {
- unset($row[$widgetId]);
- }
- } else {
- unset($row[$widgetId]);
- }
- }
- }
$layout = $this->encodeLayout($layoutObject);
return $layout;
}
@@ -202,11 +218,13 @@ class Dashboard extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
+ $jsFiles[] = "plugins/Dashboard/angularjs/common/services/dashboards-model.js";
$jsFiles[] = "plugins/Dashboard/javascripts/widgetMenu.js";
$jsFiles[] = "libs/javascript/json2.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboardObject.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboardWidget.js";
$jsFiles[] = "plugins/Dashboard/javascripts/dashboard.js";
+ $jsFiles[] = "plugins/Dashboard/angularjs/dashboard/dashboard.directive.js";
}
public function getStylesheetFiles(&$stylesheets)
diff --git a/plugins/Dashboard/Menu.php b/plugins/Dashboard/Menu.php
index f90c117e10..7967635f97 100644
--- a/plugins/Dashboard/Menu.php
+++ b/plugins/Dashboard/Menu.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Dashboard;
use Piwik\Db;
-use Piwik\Menu\MenuReporting;
use Piwik\Menu\MenuTop;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\UserPreferences;
@@ -19,24 +18,6 @@ use Piwik\Site;
*/
class Menu extends \Piwik\Plugin\Menu
{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addItem('Dashboard_Dashboard', '', $this->urlForAction('embeddedIndex', array('idDashboard' => 1)), 5);
-
- if (!Piwik::isUserIsAnonymous()) {
- $login = Piwik::getCurrentUserLogin();
-
- $dashboard = new Dashboard();
- $dashboards = $dashboard->getAllDashboards($login);
-
- $pos = 0;
- foreach ($dashboards as $dashboard) {
- $menu->addItem('Dashboard_Dashboard', $dashboard['name'], $this->urlForAction('embeddedIndex', array('idDashboard' => $dashboard['iddashboard'])), $pos);
- $pos++;
- }
- }
- }
-
public function configureTopMenu(MenuTop $menu)
{
$userPreferences = new UserPreferences();
diff --git a/plugins/Dashboard/Model.php b/plugins/Dashboard/Model.php
index 790076c1a9..0ef02aeea9 100644
--- a/plugins/Dashboard/Model.php
+++ b/plugins/Dashboard/Model.php
@@ -10,7 +10,7 @@ namespace Piwik\Plugins\Dashboard;
use Piwik\Common;
use Piwik\Db;
use Piwik\DbHelper;
-use Piwik\WidgetsList;
+use Piwik\Widget\WidgetsList;
class Model
{
@@ -189,7 +189,11 @@ class Model
if ($widget->uniqueId == $oldWidgetId) {
- $newWidgetId = WidgetsList::getWidgetUniqueId($newWidget['module'], $newWidget['action'], $newWidget['params']);
+ if (!empty($newWidget['uniqueId'])) {
+ $newWidgetId = $newWidget['uniqueId'];
+ } else {
+ $newWidgetId = WidgetsList::getWidgetUniqueId($newWidget['module'], $newWidget['action'], $newWidget['params']);
+ }
// is new widget already is on dashboard just remove the old one
if (self::layoutContainsWidget($dashboardLayout, $newWidgetId)) {
diff --git a/plugins/Dashboard/angularjs/common/services/dashboards-model.js b/plugins/Dashboard/angularjs/common/services/dashboards-model.js
new file mode 100644
index 0000000000..e0d861c2ba
--- /dev/null
+++ b/plugins/Dashboard/angularjs/common/services/dashboards-model.js
@@ -0,0 +1,68 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+(function () {
+ angular.module('piwikApp.service').factory('dashboardsModel', dashboardsModel);
+
+ dashboardsModel.$inject = ['piwikApi'];
+
+ function dashboardsModel (piwikApi) {
+
+ var dashboardsPromise = null;
+
+ var model = {
+ dashboards: [],
+ getAllDashboards: getAllDashboards,
+ reloadAllDashboards: reloadAllDashboards,
+ getDashboard: getDashboard,
+ getDashboardLayout: getDashboardLayout
+ };
+
+ return model;
+
+ function getDashboard(dashboardId)
+ {
+ return getAllDashboards().then(function (dashboards) {
+ var dashboard = null;
+ angular.forEach(dashboards, function (board) {
+ if (parseInt(board.id, 10) === parseInt(dashboardId, 10)) {
+ dashboard = board;
+ }
+ });
+ return dashboard;
+ });
+ }
+
+ function getDashboardLayout(dashboardId)
+ {
+ return piwikApi.fetch({module: 'Dashboard', action: 'getDashboardLayout', idDashboard: dashboardId});
+ }
+
+ function reloadAllDashboards()
+ {
+ if (dashboardsPromise) {
+ dashboardsPromise = null;
+ }
+
+ return getAllDashboards();
+ }
+
+ function getAllDashboards()
+ {
+ if (!dashboardsPromise) {
+ dashboardsPromise = piwikApi.fetch({method: 'Dashboard.getDashboards'}).then(function (response) {
+ if (response) {
+ model.dashboards = response;
+ }
+
+ return response;
+ });
+ }
+
+ return dashboardsPromise;
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js b/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js
new file mode 100644
index 0000000000..578737940c
--- /dev/null
+++ b/plugins/Dashboard/angularjs/dashboard/dashboard.directive.js
@@ -0,0 +1,103 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * <div piwik-dashboard dashboardId="5" layout="10"></div>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikDashboard', piwikDashboard);
+
+ piwikDashboard.$inject = ['dashboardsModel', '$rootScope', '$q'];
+
+ function piwikDashboard(dashboardsModel, $rootScope, $q) {
+
+ function renderDashboard(dashboardId, dashboard, layout)
+ {
+ $('.dashboardSettings').show();
+ initTopControls();
+
+ // Embed dashboard
+ if (!$('#topBars').length) {
+ $('.dashboardSettings').after($('#Dashboard'));
+ $('#Dashboard_embeddedIndex_' + dashboardId).addClass('sfHover');
+ }
+
+ widgetsHelper.getAvailableWidgets();
+
+ $('#dashboardWidgetsArea')
+ .on('dashboardempty', showEmptyDashboardNotification)
+ .dashboard({
+ idDashboard: dashboardId,
+ layout: layout,
+ name: dashboard ? dashboard.name : ''
+ });
+
+ $('#columnPreview').find('>div').each(function () {
+ var width = [];
+ $('div', this).each(function () {
+ width.push(this.className.replace(/width-/, ''));
+ });
+ $(this).attr('layout', width.join('-'));
+ });
+
+ $('#columnPreview').find('>div').on('click', function () {
+ $('#columnPreview').find('>div').removeClass('choosen');
+ $(this).addClass('choosen');
+ });
+ }
+
+ function fetchDashboard(dashboardId) {
+ $('#dashboardWidgetsArea').innerHTML ='';
+
+ var getDashboard = dashboardsModel.getDashboard(dashboardId);
+ var getLayout = dashboardsModel.getDashboardLayout(dashboardId);
+
+ $q.all([getDashboard, getLayout]).then(function (response) {
+ var dashboard = response[0];
+ var layout = response[1];
+
+ $(function() {
+ renderDashboard(dashboardId, dashboard, layout);
+ });
+ });
+ }
+
+ function clearDashboard () {
+ $('.top_controls .dashboard-manager').hide();
+ $('#dashboardWidgetsArea').dashboard('destroy');
+ }
+
+ return {
+ restrict: 'A',
+ scope: {
+ dashboardid: '=',
+ layout: '='
+ },
+ link: function (scope, element, attrs) {
+
+ scope.$parent.fetchDashboard = function (dashboardId) {
+ scope.dashboardId = dashboardId;
+ fetchDashboard(dashboardId)
+ };
+
+ fetchDashboard(scope.dashboardid);
+
+ function onLocationChange(event, url1, url2)
+ {
+ if (url1 !== url2) {
+ clearDashboard();
+ }
+ }
+
+ // should be rather handled in route or so.
+ var unbind = $rootScope.$on('$locationChangeSuccess', onLocationChange);
+ scope.$on('$destroy', onLocationChange);
+ scope.$on('$destroy', unbind);
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/Dashboard/javascripts/dashboard.js b/plugins/Dashboard/javascripts/dashboard.js
index 238aca5197..f78814cdbb 100644
--- a/plugins/Dashboard/javascripts/dashboard.js
+++ b/plugins/Dashboard/javascripts/dashboard.js
@@ -5,45 +5,12 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-function initDashboard(dashboardId, dashboardLayout) {
-
- $('.dashboardSettings').show();
- initTopControls();
-
- // Embed dashboard
- if (!$('#topBars').length) {
- $('.dashboardSettings').after($('#Dashboard'));
- $('#Dashboard_embeddedIndex_' + dashboardId).addClass('sfHover');
- }
-
- widgetsHelper.getAvailableWidgets();
-
- $('#dashboardWidgetsArea')
- .on('dashboardempty', showEmptyDashboardNotification)
- .dashboard({
- idDashboard: dashboardId,
- layout: dashboardLayout
- });
-
- $('#columnPreview').find('>div').each(function () {
- var width = [];
- $('div', this).each(function () {
- width.push(this.className.replace(/width-/, ''));
- });
- $(this).attr('layout', width.join('-'));
- });
-
- $('#columnPreview').find('>div').on('click', function () {
- $('#columnPreview').find('>div').removeClass('choosen');
- $(this).addClass('choosen');
- });
-}
-
function createDashboard() {
- $('#createDashboardName').val('');
- piwikHelper.modalConfirm('#createDashboardConfirm', {yes: function () {
- var dashboardName = $('#createDashboardName').val();
- var type = ($('#dashboard_type_empty:checked').length > 0) ? 'empty' : 'default';
+ $(makeSelectorLastId('createDashboardName')).val('');
+
+ piwikHelper.modalConfirm(makeSelectorLastId('createDashboardConfirm'), {yes: function () {
+ var dashboardName = $(makeSelectorLastId('createDashboardName')).val();
+ var type = ($('[id=dashboard_type_empty]:last:checked').length > 0) ? 'empty' : 'default';
var ajaxRequest = new ajaxHelper();
ajaxRequest.setLoadingElement();
@@ -57,50 +24,74 @@ function createDashboard() {
}, 'post');
ajaxRequest.setCallback(
function (id) {
- $('#dashboardWidgetsArea').dashboard('loadDashboard', id);
+ angular.element(document).injector().invoke(function ($location, reportingMenuModel, dashboardsModel) {
+ dashboardsModel.reloadAllDashboards().then(function () {
+ $('#dashboardWidgetsArea').dashboard('loadDashboard', id);
+ $('#dashboardWidgetsArea').dashboard('rebuildMenu');
+ });
+ });
}
);
ajaxRequest.send(true);
}});
}
+function makeSelectorLastId(domElementId)
+{
+ // there can be many elements with this id, we prefer the last one
+ return '[id=' + domElementId + ']:last';
+}
+
function resetDashboard() {
- piwikHelper.modalConfirm('#resetDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('resetLayout'); }});
+ piwikHelper.modalConfirm(makeSelectorLastId('resetDashboardConfirm'), {yes:
+ function () { $('#dashboardWidgetsArea').dashboard('resetLayout');
+ }});
}
function renameDashboard() {
- $('#newDashboardName').val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
- piwikHelper.modalConfirm('#renameDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('setDashboardName', $('#newDashboardName').val()); }});
+ $(makeSelectorLastId('newDashboardName')).val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+
+ piwikHelper.modalConfirm(makeSelectorLastId('renameDashboardConfirm'), {yes: function () {
+ var newDashboardName = $(makeSelectorLastId('newDashboardName')).val();
+ $('#dashboardWidgetsArea').dashboard('setDashboardName', newDashboardName);
+ }});
}
function removeDashboard() {
- $('#removeDashboardConfirm').find('h2 span').text($('#dashboardWidgetsArea').dashboard('getDashboardName'));
- piwikHelper.modalConfirm('#removeDashboardConfirm', {yes: function () { $('#dashboardWidgetsArea').dashboard('removeDashboard'); }});
+ $(makeSelectorLastId('removeDashboardConfirm')).find('h2 span').text($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+
+ piwikHelper.modalConfirm(makeSelectorLastId('removeDashboardConfirm'), {yes: function () {
+ $('#dashboardWidgetsArea').dashboard('removeDashboard');
+ }});
}
function showChangeDashboardLayoutDialog() {
$('#columnPreview').find('>div').removeClass('choosen');
$('#columnPreview').find('>div[layout=' + $('#dashboardWidgetsArea').dashboard('getColumnLayout') + ']').addClass('choosen');
- piwikHelper.modalConfirm('#changeDashboardLayout', {yes: function () {
- $('#dashboardWidgetsArea').dashboard('setColumnLayout', $('#changeDashboardLayout').find('.choosen').attr('layout'));
+
+ var id = makeSelectorLastId('changeDashboardLayout');
+ piwikHelper.modalConfirm(id, {yes: function () {
+ $('#dashboardWidgetsArea').dashboard('setColumnLayout', $(id).find('.choosen').attr('layout'));
}});
}
function showEmptyDashboardNotification() {
- piwikHelper.modalConfirm('#dashboardEmptyNotification', {
+ piwikHelper.modalConfirm(makeSelectorLastId('dashboardEmptyNotification'), {
resetDashboard: function () { $('#dashboardWidgetsArea').dashboard('resetLayout'); },
addWidget: function () { $('.dashboardSettings').trigger('click'); }
});
}
function setAsDefaultWidgets() {
- piwikHelper.modalConfirm('#setAsDefaultWidgetsConfirm', {
- yes: function () { $('#dashboardWidgetsArea').dashboard('saveLayoutAsDefaultWidgetLayout'); }
+ piwikHelper.modalConfirm(makeSelectorLastId('setAsDefaultWidgetsConfirm'), {
+ yes: function () {
+ $('#dashboardWidgetsArea').dashboard('saveLayoutAsDefaultWidgetLayout');
+ }
});
}
function copyDashboardToUser() {
- $('#copyDashboardName').val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
+ $(makeSelectorLastId('copyDashboardName')).val($('#dashboardWidgetsArea').dashboard('getDashboardName'));
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams({
module: 'API',
@@ -109,13 +100,13 @@ function copyDashboardToUser() {
}, 'get');
ajaxRequest.setCallback(
function (availableUsers) {
- $('#copyDashboardUser').empty();
- $('#copyDashboardUser').append(
+ $(makeSelectorLastId('copyDashboardUser')).empty();
+ $(makeSelectorLastId('copyDashboardUser')).append(
$('<option></option>').val(piwik.userLogin).text(piwik.userLogin)
);
$.each(availableUsers, function (index, user) {
if (user.login != 'anonymous' && user.login != piwik.userLogin) {
- $('#copyDashboardUser').append(
+ $(makeSelectorLastId('copyDashboardUser')).append(
$('<option></option>').val(user.login).text(user.login + ' (' + user.alias + ')')
);
}
@@ -124,10 +115,10 @@ function copyDashboardToUser() {
);
ajaxRequest.send(true);
- piwikHelper.modalConfirm('#copyDashboardToUserConfirm', {
+ piwikHelper.modalConfirm(makeSelectorLastId('copyDashboardToUserConfirm'), {
yes: function () {
- var copyDashboardName = $('#copyDashboardName').val();
- var copyDashboardUser = $('#copyDashboardUser').val();
+ var copyDashboardName = $(makeSelectorLastId('copyDashboardName')).val();
+ var copyDashboardUser = $(makeSelectorLastId('copyDashboardUser')).val();
var ajaxRequest = new ajaxHelper();
ajaxRequest.addParams({
@@ -291,7 +282,7 @@ function copyDashboardToUser() {
},
isWidgetAvailable: function (widgetUniqueId) {
- return !$('#dashboardWidgetsArea').find('[widgetId=' + widgetUniqueId + ']').length;
+ return !$('#dashboardWidgetsArea').find('[widgetId="' + widgetUniqueId + '"]').length;
},
widgetSelected: function (widget) {
@@ -301,6 +292,7 @@ function copyDashboardToUser() {
DashboardManagerControl.initElements = function () {
UIControl.initElements(this, '.dashboard-manager');
+ $('.top_controls .dashboard-manager').hide(); // initially hide the manager
};
exports.DashboardManagerControl = DashboardManagerControl;
diff --git a/plugins/Dashboard/javascripts/dashboardObject.js b/plugins/Dashboard/javascripts/dashboardObject.js
index 7808d22c11..08bb36dd79 100644
--- a/plugins/Dashboard/javascripts/dashboardObject.js
+++ b/plugins/Dashboard/javascripts/dashboardObject.js
@@ -57,9 +57,6 @@
if (options.layout) {
generateLayout(options.layout);
- buildMenu();
- } else {
- methods.loadDashboard.apply(this, [dashboardId]);
}
return this;
@@ -89,11 +86,11 @@
dashboardName = '';
dashboardLayout = null;
dashboardId = dashboardIdToLoad;
- piwikHelper.showAjaxLoading();
- broadcast.updateHashOnly = true;
- broadcast.propagateAjax('?idDashboard=' + dashboardIdToLoad);
- fetchLayout(generateLayout);
- buildMenu();
+
+ var element = $('[piwik-dashboard]');
+ var scope = angular.element(element).scope();
+ scope.fetchDashboard(dashboardIdToLoad);
+
return this;
},
@@ -179,6 +176,8 @@
ajaxRequest.send(true);
},
+ rebuildMenu: rebuildMenu,
+
/**
* Removes the current dashboard
*/
@@ -201,6 +200,39 @@
}
};
+ function removeNonExistingWidgets(availableWidgets, layout)
+ {
+ var existingModuleAction = {};
+ $.each(availableWidgets, function (category, widgets) {
+ $.each(widgets, function (index, widget) {
+ existingModuleAction[widget.module + '.' + widget.action] = true;
+ });
+ });
+
+ var columns = [];
+ $.each(layout.columns, function (i, column) {
+ var widgets = [];
+
+ $.each(column, function (j, widget) {
+ if (!widget.parameters || !widget.parameters.module) {
+ return;
+ }
+
+ var method = widget.parameters.module + '.' + widget.parameters.action
+ if (existingModuleAction[method]) {
+ widgets.push(widget);
+ }
+
+ });
+
+ columns[i] = widgets;
+ });
+
+ layout.columns = columns;
+
+ return layout;
+ }
+
/**
* Generates the dashboard out of the given layout
*
@@ -209,46 +241,33 @@
function generateLayout(layout) {
dashboardLayout = parseLayout(layout);
- piwikHelper.hideAjaxLoading();
- adjustDashboardColumns(dashboardLayout.config.layout);
-
- var dashboardContainsWidgets = false;
- for (var column = 0; column < dashboardLayout.columns.length; column++) {
- for (var i in dashboardLayout.columns[column]) {
- if (typeof dashboardLayout.columns[column][i] != 'object') {
- // Fix IE8 bug: the "i in" loop contains i="indexOf", which would yield type function.
- // If we would continue with i="indexOf", an invalid widget would be created.
- continue;
+
+ widgetsHelper.getAvailableWidgets(function (availableWidgets) {
+ dashboardLayout = removeNonExistingWidgets(availableWidgets, dashboardLayout);
+
+ piwikHelper.hideAjaxLoading();
+ adjustDashboardColumns(dashboardLayout.config.layout);
+
+ var dashboardContainsWidgets = false;
+ for (var column = 0; column < dashboardLayout.columns.length; column++) {
+ for (var i in dashboardLayout.columns[column]) {
+ if (typeof dashboardLayout.columns[column][i] != 'object') {
+ // Fix IE8 bug: the "i in" loop contains i="indexOf", which would yield type function.
+ // If we would continue with i="indexOf", an invalid widget would be created.
+ continue;
+ }
+ var widget = dashboardLayout.columns[column][i];
+ dashboardContainsWidgets = true;
+ addWidgetTemplate(widget.uniqueId, column + 1, widget.parameters, false, widget.isHidden)
}
- var widget = dashboardLayout.columns[column][i];
- dashboardContainsWidgets = true;
- addWidgetTemplate(widget.uniqueId, column + 1, widget.parameters, false, widget.isHidden)
}
- }
-
- if (!dashboardContainsWidgets) {
- $(dashboardElement).trigger('dashboardempty');
- }
- makeWidgetsSortable();
- }
+ if (!dashboardContainsWidgets) {
+ $(dashboardElement).trigger('dashboardempty');
+ }
- /**
- * Fetches the layout for the currently set dashboard id
- * and passes the response to given callback function
- *
- * @param {function} callback
- */
- function fetchLayout(callback) {
- globalAjaxQueue.abort();
- var ajaxRequest = new ajaxHelper();
- ajaxRequest.addParams({
- module: 'Dashboard',
- action: 'getDashboardLayout',
- idDashboard: dashboardId
- }, 'get');
- ajaxRequest.setCallback(callback);
- ajaxRequest.send(false);
+ makeWidgetsSortable();
+ });
}
/**
@@ -388,7 +407,7 @@
* @param {String} uniqueId
*/
function reloadWidget(uniqueId) {
- $('[widgetId=' + uniqueId + ']', dashboardElement).dashboardWidget('reload', false, true);
+ $('[widgetId="' + uniqueId + '"]', dashboardElement).dashboardWidget('reload', false, true);
}
/**
@@ -417,7 +436,7 @@
$('.col:nth-child(' + columnNumber + ')', dashboardElement).append(widgetContent);
}
- $('[widgetId=' + uniqueId + ']', dashboardElement).dashboardWidget({
+ $('[widgetId="' + uniqueId + '"]', dashboardElement).dashboardWidget({
uniqueId: uniqueId,
widgetParameters: widgetParameters,
onChange: function () {
@@ -468,7 +487,19 @@
/**
* Handle clicks for menu items for choosing between available dashboards
*/
- function buildMenu() {
+ function rebuildMenu() {
+
+ if ($('[piwik-reporting-menu]').length) {
+ // dashboard in reporting page (regular Piwik UI)
+ angular.element(document).injector().invoke(function (reportingMenuModel) {
+ reportingMenuModel.reloadMenuItems();
+ });
+ return;
+ }
+
+ var _self = this;
+
+ // widgetized
var success = function (dashboards) {
var dashboardMenuList = $('#Dashboard').find('> ul');
var dashboardMenuListItems = dashboardMenuList.find('>li');
@@ -484,7 +515,7 @@
for (var i = 0; i < dashboards.length; i++) {
var $link = $('<a/>').attr('data-idDashboard', dashboards[i].iddashboard).text(dashboards[i].name);
var $li = $('<li/>').attr('id', 'Dashboard_embeddedIndex_' + dashboards[i].iddashboard)
- .addClass('dashboardMenuItem').append($link);
+ .addClass('dashboardMenuItem').append($link);
items.push($li);
if (dashboards[i].iddashboard == dashboardId) {
@@ -502,15 +533,10 @@
var idDashboard = $(this).attr('data-idDashboard');
- if (typeof piwikMenu != 'undefined') {
- piwikMenu.activateMenu('Dashboard', 'embeddedIndex');
- }
$('#Dashboard ul li').removeClass('sfHover');
- if ($(dashboardElement).length) {
- $(dashboardElement).dashboard('loadDashboard', idDashboard);
- } else {
- broadcast.propagateAjax('module=Dashboard&action=embeddedIndex&idDashboard=' + idDashboard);
- }
+
+ methods.loadDashboard.apply(_self, [idDashboard]);
+
$(this).closest('li').addClass('sfHover');
});
};
@@ -521,7 +547,7 @@
action: 'getAllDashboards'
}, 'get');
ajaxRequest.setCallback(success);
- ajaxRequest.send(false);
+ ajaxRequest.send();
}
/**
@@ -568,7 +594,7 @@
function () {
if (dashboardChanged) {
dashboardChanged = false;
- buildMenu();
+ rebuildMenu();
}
}
);
@@ -594,6 +620,7 @@
}, 'get');
ajaxRequest.setCallback(
function () {
+ rebuildMenu();
methods.loadDashboard.apply(this, [1]);
}
);
diff --git a/plugins/Dashboard/javascripts/dashboardWidget.js b/plugins/Dashboard/javascripts/dashboardWidget.js
index accd0aa2c2..969ed9db28 100755
--- a/plugins/Dashboard/javascripts/dashboardWidget.js
+++ b/plugins/Dashboard/javascripts/dashboardWidget.js
@@ -70,7 +70,7 @@
*/
destroy: function () {
if (this.isMaximised) {
- $('[widgetId=' + this.uniqueId + ']').dialog('destroy');
+ $('[widgetId="' + this.uniqueId + '"]').dialog('destroy');
}
$('*', this.element).off('.dashboardWidget'); // unbind all events
$('.widgetContent', this.element).trigger('widget:destroy');
@@ -197,7 +197,7 @@
var emptyWidgetContent = require('piwik/UI/Dashboard').WidgetFactory.make(uniqueId, title);
this.element.html(emptyWidgetContent);
- var widgetElement = $('#' + uniqueId, this.element);
+ var widgetElement = $('[id="' + uniqueId + '"]', this.element);
var self = this;
widgetElement
.on('mouseenter.dashboardWidget', function () {
@@ -312,7 +312,7 @@
}
$('body').off('.dashboardWidget');
$(this).dialog("destroy");
- $('#' + self.uniqueId + '-placeholder').replaceWith(this);
+ $('[id="' + self.uniqueId + '-placeholder"]').replaceWith(this);
$(this).removeAttr('style');
self.options.onChange();
$(this).find('div.piwik-graph').trigger('resizeGraph');
@@ -339,6 +339,9 @@
*/
detachWidget: function () {
this.element.before('<div id="' + this.uniqueId + '-placeholder" class="widgetPlaceholder widget"> </div>');
+ var placeholder = $('[id="' + self.uniqueId + '-placeholder"]')
+
+
$('#' + this.uniqueId + '-placeholder').height(this.element.height());
$('#' + this.uniqueId + '-placeholder').width(this.element.width() - 16);
diff --git a/plugins/Dashboard/javascripts/widgetMenu.js b/plugins/Dashboard/javascripts/widgetMenu.js
index 6d58415cb9..169768eb03 100644
--- a/plugins/Dashboard/javascripts/widgetMenu.js
+++ b/plugins/Dashboard/javascripts/widgetMenu.js
@@ -13,21 +13,82 @@ function widgetsHelper() {
*
* @return {object} object containing available widgets
*/
-widgetsHelper.getAvailableWidgets = function () {
+widgetsHelper.getAvailableWidgets = function (callback) {
+
+ function mergeCategoriesAndSubCategories(availableWidgets)
+ {
+ var categorized = {};
+
+ $.each(availableWidgets, function (index, widget) {
+ var category = widget.category.name;
+
+ if (!categorized[category]) {
+ categorized[category] = {'-': []};
+ }
+
+ var subcategory = '-';
+ if (widget.subcategory && widget.subcategory.name) {
+ subcategory = widget.subcategory.name;
+ }
+
+ if (!categorized[category][subcategory]) {
+ categorized[category][subcategory] = [];
+ }
+
+ categorized[category][subcategory].push(widget);
+ });
+
+ var moved = {};
+
+ $.each(categorized, function (category, widgets) {
+ $.each(widgets, function (subcategory, subwidgets) {
+
+ var categoryToUse = category;
+ if (subwidgets.length >= 3 && subcategory !== '-') {
+ categoryToUse = category + ' - ' + subcategory;
+ }
+
+ if (!moved[categoryToUse]) {
+ moved[categoryToUse] = [];
+ }
+
+ $.each(subwidgets, function (index, widget) {
+ moved[categoryToUse].push(widget);
+ });
+ });
+ });
+
+ return moved;
+ }
+
if (!widgetsHelper.availableWidgets) {
var ajaxRequest = new ajaxHelper();
+ ajaxRequest._mixinDefaultGetParams = function (params) {
+ return params;
+ };
ajaxRequest.addParams({
- module: 'Dashboard',
- action: 'getAvailableWidgets'
+ module: 'API',
+ method: 'API.getWidgetMetadata',
+ format: 'JSON',
+ deep: '1',
+ idSite: piwik.idSite || broadcast.getValueFromUrl('idSite')
}, 'get');
ajaxRequest.setCallback(
function (data) {
- widgetsHelper.availableWidgets = data;
+ widgetsHelper.availableWidgets = mergeCategoriesAndSubCategories(data);
+
+ if (callback) {
+ callback(widgetsHelper.availableWidgets);
+ }
}
);
ajaxRequest.send(true);
}
+ if (callback) {
+ callback(widgetsHelper.availableWidgets);
+ }
+
return widgetsHelper.availableWidgets;
};
@@ -191,6 +252,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
* @return {$} category list element
*/
function createWidgetCategoryList(widgetPreview, availableWidgets) {
+
var settings = widgetPreview.settings;
if (!$('.' + settings.categorylistClass, widgetPreview).length) {
@@ -200,7 +262,6 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
}
for (var widgetCategory in availableWidgets) {
-
$('.' + settings.categorylistClass, widgetPreview).append('<li>' + widgetCategory + '</li>');
}
@@ -257,6 +318,8 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
widgetClass += ' ' + settings.unavailableClass;
}
+ widgetName = piwikHelper.escape(piwikHelper.htmlEntities(widgetName));
+
widgetList.append('<li class="' + widgetClass + '" uniqueid="' + widgetUniqueId + '">' + widgetName + '</li>');
}
@@ -278,7 +341,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
clearTimeout(widgetPreview);
});
- $('li:not(.' + settings.unavailableClass + ')', widgetList).on('click', function () {
+ $('li', widgetList).on('click', function () {
if (!$('.widgetLoading', widgetPreview).length) {
settings.onSelect($(this).attr('uniqueid'));
if (settings.resetOnSelect) {
@@ -317,7 +380,7 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
*/
function showPreview(widgetUniqueId, widgetPreview) {
// do not reload id widget already displayed
- if ($('#' + widgetUniqueId, widgetPreview).length) return;
+ if ($('[id="' + widgetUniqueId + '"]', widgetPreview).length) return;
var settings = widgetPreview.settings;
@@ -335,7 +398,8 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
previewElement.html(emptyWidgetHtml);
var onWidgetLoadedCallback = function (response) {
- var widgetElement = $('#' + widgetUniqueId);
+ var widgetElement = $(document.getElementById(widgetUniqueId));
+ // document.getElementById needed for widgets with uniqueid like widgetOpens+Contact+Form
$('.widgetContent', widgetElement).html($(response));
$('.widgetContent', widgetElement).trigger('widget:create');
settings.onPreviewLoaded(widgetUniqueId, widgetElement);
@@ -398,19 +462,21 @@ widgetsHelper.loadWidgetAjax = function (widgetUniqueId, widgetParameters, onWid
this.onPreviewLoaded = this.settings.onPreviewLoaded;
}
- availableWidgets = widgetsHelper.getAvailableWidgets();
+ var self = this;
+ widgetsHelper.getAvailableWidgets(function (availableWidgets) {
- var categoryList = createWidgetCategoryList(this, availableWidgets);
+ var categoryList = createWidgetCategoryList(self, availableWidgets);
- var self = this;
- $('li', categoryList).on('mouseover', function () {
- var category = $(this).text();
- var widgets = availableWidgets[category];
- $('li', categoryList).removeClass(self.settings.choosenClass);
- $(this).addClass(self.settings.choosenClass);
- showWidgetList(widgets, self);
- createPreviewElement(self); // empty preview
+ $('li', categoryList).on('mouseover', function () {
+ var category = $(this).text();
+ var widgets = availableWidgets[category];
+ $('li', categoryList).removeClass(self.settings.choosenClass);
+ $(this).addClass(self.settings.choosenClass);
+ showWidgetList(widgets, self);
+ createPreviewElement(self); // empty preview
+ });
});
+
};
}
});
diff --git a/plugins/Dashboard/templates/embeddedIndex.twig b/plugins/Dashboard/templates/embeddedIndex.twig
index af1dbeb887..a7633ca193 100644
--- a/plugins/Dashboard/templates/embeddedIndex.twig
+++ b/plugins/Dashboard/templates/embeddedIndex.twig
@@ -1,10 +1,4 @@
-<script type="text/javascript">
- widgetsHelper.availableWidgets = {{ availableWidgets|raw }};
- $(function() {
- initDashboard({{ dashboardId }}, {{ dashboardLayout|raw }});
- });
-</script>
-<div id="dashboard">
+<div id="dashboard" piwik-dashboard dashboardid="{{ dashboardId }}">
<div class="ui-confirm" id="confirm">
<h2>{{ 'Dashboard_DeleteWidgetConfirm'|translate }}</h2>
<input role="yes" type="button" value="{{ 'General_Yes'|translate }}"/>
diff --git a/plugins/DevicePlugins/Reports/Base.php b/plugins/DevicePlugins/Reports/Base.php
index 81116f4d1d..b6f8755b13 100644
--- a/plugins/DevicePlugins/Reports/Base.php
+++ b/plugins/DevicePlugins/Reports/Base.php
@@ -15,7 +15,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_VisitorSettings';
+ $this->categoryId = 'General_Visitors';
}
protected function getBasicDevicePluginsDisplayProperties(ViewDataTable $view)
diff --git a/plugins/DevicePlugins/Reports/GetPlugin.php b/plugins/DevicePlugins/Reports/GetPlugin.php
index 151bf3e1a6..42fef1cb89 100644
--- a/plugins/DevicePlugins/Reports/GetPlugin.php
+++ b/plugins/DevicePlugins/Reports/GetPlugin.php
@@ -23,8 +23,9 @@ class GetPlugin extends Base
$this->metrics = array('nb_visits');
$this->constantRowsCount = true;
$this->processedMetrics = array('nb_visits_percentage');
- $this->order = 4;
- $this->widgetTitle = 'DevicePlugins_WidgetPlugins';
+ $this->order = 13;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/DevicesDetection/Controller.php b/plugins/DevicesDetection/Controller.php
index 10c55a8a96..d19d0cf403 100644
--- a/plugins/DevicesDetection/Controller.php
+++ b/plugins/DevicesDetection/Controller.php
@@ -13,52 +13,11 @@ use Piwik\Common;
use Piwik\Db;
use Piwik\Piwik;
use Piwik\Plugin\ControllerAdmin;
-use Piwik\Plugin\Manager AS PluginManager;
use Piwik\Plugin\Report;
use Piwik\View;
class Controller extends \Piwik\Plugin\Controller
{
- public function index()
- {
- return $this->devices();
- }
-
- public function devices()
- {
- $view = new View('@DevicesDetection/devices');
- $view->deviceTypes = $this->renderReport('getType');
- $view->deviceBrands = $this->renderReport('getBrand');
- $view->deviceModels = $this->renderReport('getModel');
-
- $isResolutionEnabled = PluginManager::getInstance()->isPluginActivated('Resolution');
- if ($isResolutionEnabled) {
- $view->resolutions = $this->renderReport(Report::factory('Resolution', 'getResolution'));
- }
-
- return $view->render();
- }
-
- public function software()
- {
- $view = new View('@DevicesDetection/software');
- $view->osReport = $this->renderReport('getOsVersions');
- $view->browserReport = $this->renderReport('getBrowsers');
- $view->browserEngineReport = $this->renderReport('getBrowserEngines');
-
- $isResolutionEnabled = PluginManager::getInstance()->isPluginActivated('Resolution');
- if ($isResolutionEnabled) {
- $view->configurations = $this->renderReport(Report::factory('Resolution', 'getConfiguration'));
- }
-
- $isDevicePluginsEnabled = PluginManager::getInstance()->isPluginActivated('DevicePlugins');
- if ($isDevicePluginsEnabled) {
- $view->browserPlugins = $this->renderReport(Report::factory('DevicePlugins', 'getPlugin'));
- }
-
- return $view->render();
- }
-
public function detection()
{
Piwik::checkUserHasSomeAdminAccess();
diff --git a/plugins/DevicesDetection/Menu.php b/plugins/DevicesDetection/Menu.php
index 7ddb1dc668..067f8b9afa 100644
--- a/plugins/DevicesDetection/Menu.php
+++ b/plugins/DevicesDetection/Menu.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\DevicesDetection;
use Piwik\Menu\MenuAdmin;
-use Piwik\Menu\MenuReporting;
use Piwik\Piwik;
/**
@@ -24,10 +23,4 @@ class Menu extends \Piwik\Plugin\Menu
$order = 40);
}
}
-
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addVisitorsItem('DevicesDetection_Devices', $this->urlForAction('devices'));
- $menu->addVisitorsItem('DevicesDetection_Software', $this->urlForAction('software'));
- }
}
diff --git a/plugins/DevicesDetection/Reports/Base.php b/plugins/DevicesDetection/Reports/Base.php
index 15eac96a4a..cb24a376e4 100644
--- a/plugins/DevicesDetection/Reports/Base.php
+++ b/plugins/DevicesDetection/Reports/Base.php
@@ -14,6 +14,6 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'DevicesDetection_DevicesDetection';
+ $this->categoryId = 'General_Visitors';
}
}
diff --git a/plugins/DevicesDetection/Reports/GetBrand.php b/plugins/DevicesDetection/Reports/GetBrand.php
index 070b2d8918..41b9fd5366 100644
--- a/plugins/DevicesDetection/Reports/GetBrand.php
+++ b/plugins/DevicesDetection/Reports/GetBrand.php
@@ -20,8 +20,9 @@ class GetBrand extends Base
$this->dimension = new DeviceBrand();
$this->name = Piwik::translate('DevicesDetection_DeviceBrand');
$this->documentation = ''; // TODO
- $this->order = 1;
- $this->widgetTitle = 'DevicesDetection_DeviceBrand';
+ $this->order = 4;
+
+ $this->subcategoryId = 'DevicesDetection_Devices';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/DevicesDetection/Reports/GetBrowserEngines.php b/plugins/DevicesDetection/Reports/GetBrowserEngines.php
index 7c47ffca63..403955c66c 100644
--- a/plugins/DevicesDetection/Reports/GetBrowserEngines.php
+++ b/plugins/DevicesDetection/Reports/GetBrowserEngines.php
@@ -21,8 +21,9 @@ class GetBrowserEngines extends Base
$this->dimension = new BrowserEngine();
$this->name = Piwik::translate('DevicesDetection_BrowserEngines');
$this->documentation = Piwik::translate('DevicesDetection_BrowserEngineDocumentation', '<br />');
- $this->order = 7;
- $this->widgetTitle = 'DevicesDetection_BrowserEngines';
+ $this->order = 10;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/DevicesDetection/Reports/GetBrowserVersions.php b/plugins/DevicesDetection/Reports/GetBrowserVersions.php
index 4f5875199a..66c7f91f55 100644
--- a/plugins/DevicesDetection/Reports/GetBrowserVersions.php
+++ b/plugins/DevicesDetection/Reports/GetBrowserVersions.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DevicesDetection\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\DevicesDetection\Columns\BrowserVersion;
+use Piwik\Plugin\Reports;
class GetBrowserVersions extends Base
{
@@ -20,8 +21,9 @@ class GetBrowserVersions extends Base
$this->dimension = new BrowserVersion();
$this->name = Piwik::translate('DevicesDetection_BrowserVersion');
$this->documentation = ''; // TODO
- $this->order = 2;
- $this->widgetTitle = 'DevicesDetection_BrowserVersion';
+ $this->order = 6;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
@@ -34,7 +36,7 @@ class GetBrowserVersions extends Base
public function getRelatedReports()
{
return array(
- self::factory('DevicesDetection', 'getBrowsers'),
+ Reports::factory('DevicesDetection', 'getBrowsers'),
);
}
}
diff --git a/plugins/DevicesDetection/Reports/GetBrowsers.php b/plugins/DevicesDetection/Reports/GetBrowsers.php
index 7d08a51ce5..5c39a275ee 100644
--- a/plugins/DevicesDetection/Reports/GetBrowsers.php
+++ b/plugins/DevicesDetection/Reports/GetBrowsers.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DevicesDetection\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\DevicesDetection\Columns\BrowserName;
+use Piwik\Plugin\Reports;
class GetBrowsers extends Base
{
@@ -18,10 +19,11 @@ class GetBrowsers extends Base
{
parent::init();
$this->dimension = new BrowserName();
- $this->name = Piwik::translate('DevicesDetection_WidgetBrowsers');
+ $this->name = Piwik::translate('DevicesDetection_Browsers');
$this->documentation = Piwik::translate('DevicesDetection_WidgetBrowsersDocumentation', '<br />');
- $this->order = 1;
- $this->widgetTitle = 'DevicesDetection_WidgetBrowsers';
+ $this->order = 5;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
@@ -35,7 +37,7 @@ class GetBrowsers extends Base
public function getRelatedReports()
{
return array(
- self::factory('DevicesDetection', 'getBrowserVersions'),
+ Reports::factory('DevicesDetection', 'getBrowserVersions'),
);
}
}
diff --git a/plugins/DevicesDetection/Reports/GetModel.php b/plugins/DevicesDetection/Reports/GetModel.php
index e2241e1ad4..154464691c 100644
--- a/plugins/DevicesDetection/Reports/GetModel.php
+++ b/plugins/DevicesDetection/Reports/GetModel.php
@@ -21,7 +21,8 @@ class GetModel extends Base
$this->name = Piwik::translate('DevicesDetection_DeviceModel');
$this->documentation = ''; // TODO
$this->order = 2;
- $this->widgetTitle = 'DevicesDetection_DeviceModel';
+
+ $this->subcategoryId = 'DevicesDetection_Devices';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/DevicesDetection/Reports/GetOsFamilies.php b/plugins/DevicesDetection/Reports/GetOsFamilies.php
index 61b393cb44..a283a83f7b 100644
--- a/plugins/DevicesDetection/Reports/GetOsFamilies.php
+++ b/plugins/DevicesDetection/Reports/GetOsFamilies.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DevicesDetection\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\DevicesDetection\Columns\Os;
+use Piwik\Plugin\Reports;
class GetOsFamilies extends Base
{
@@ -20,8 +21,9 @@ class GetOsFamilies extends Base
$this->dimension = new Os();
$this->name = Piwik::translate('DevicesDetection_OperatingSystemFamilies');
$this->documentation = ''; // TODO
- $this->order = 3;
- $this->widgetTitle = 'DevicesDetection_OperatingSystemFamilies';
+ $this->order = 8;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
@@ -35,7 +37,7 @@ class GetOsFamilies extends Base
public function getRelatedReports()
{
return array(
- self::factory('DevicesDetection', 'getOsVersions'),
+ Reports::factory('DevicesDetection', 'getOsVersions'),
);
}
diff --git a/plugins/DevicesDetection/Reports/GetOsVersions.php b/plugins/DevicesDetection/Reports/GetOsVersions.php
index 8676f38776..b330054c6f 100644
--- a/plugins/DevicesDetection/Reports/GetOsVersions.php
+++ b/plugins/DevicesDetection/Reports/GetOsVersions.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\DevicesDetection\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\DevicesDetection\Columns\OsVersion;
+use Piwik\Plugin\Reports;
class GetOsVersions extends Base
{
@@ -20,8 +21,9 @@ class GetOsVersions extends Base
$this->dimension = new OsVersion();
$this->name = Piwik::translate('DevicesDetection_OperatingSystemVersions');
$this->documentation = ''; // TODO
- $this->order = 4;
- $this->widgetTitle = 'DevicesDetection_OperatingSystemVersions';
+ $this->order = 2;
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
@@ -35,7 +37,7 @@ class GetOsVersions extends Base
public function getRelatedReports()
{
return array(
- self::factory('DevicesDetection', 'getOsFamilies'),
+ Reports::factory('DevicesDetection', 'getOsFamilies'),
);
}
}
diff --git a/plugins/DevicesDetection/Reports/GetType.php b/plugins/DevicesDetection/Reports/GetType.php
index cbfa69db3d..b12f19f319 100644
--- a/plugins/DevicesDetection/Reports/GetType.php
+++ b/plugins/DevicesDetection/Reports/GetType.php
@@ -22,7 +22,8 @@ class GetType extends Base
$this->name = Piwik::translate('DevicesDetection_DeviceType');
$this->documentation = ''; // TODO
$this->order = 0;
- $this->widgetTitle = 'DevicesDetection_DeviceType';
+
+ $this->subcategoryId = 'DevicesDetection_Devices';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/DevicesDetection/templates/devices.twig b/plugins/DevicesDetection/templates/devices.twig
deleted file mode 100644
index a37079c9fd..0000000000
--- a/plugins/DevicesDetection/templates/devices.twig
+++ /dev/null
@@ -1,19 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceType"|translate }}</h2>
- {{ deviceTypes | raw}}
- <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceBrand"|translate }}</h2>
- {{ deviceBrands | raw }}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ "DevicesDetection_DeviceModel"|translate }}</h2>
- {{ deviceModels | raw }}
- {% if resolutions|default is not empty %}
- <h2 piwik-enriched-headline>{{ 'Resolution_Resolutions'|translate }}</h2>
- {{ resolutions|raw }}
- {% endif %}
- </div>
-
-</div>
diff --git a/plugins/DevicesDetection/templates/software.twig b/plugins/DevicesDetection/templates/software.twig
deleted file mode 100644
index 8b0dab0631..0000000000
--- a/plugins/DevicesDetection/templates/software.twig
+++ /dev/null
@@ -1,23 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ "DevicesDetection_OperatingSystems"|translate }}</h2>
- {{ osReport | raw}}
- {% if configurations|default is not empty %}
- <h2 piwik-enriched-headline>{{ 'Resolution_Configurations'|translate }}</h2>
- {{ configurations|raw }}
- {% endif %}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ "DevicesDetection_Browsers"|translate }}</h2>
- {{ browserReport | raw }}
- <h2 piwik-enriched-headline>{{ "DevicesDetection_BrowserEngines"|translate }}</h2>
- {{ browserEngineReport | raw }}
- {% if browserPlugins|default is not empty %}
- <h2 piwik-enriched-headline>{{ 'General_Plugins'|translate }}</h2>
- {{ browserPlugins|raw }}
- {% endif %}
- </div>
-
-</div>
diff --git a/plugins/Ecommerce/Categories/EcommerceCategory.php b/plugins/Ecommerce/Categories/EcommerceCategory.php
new file mode 100644
index 0000000000..39cd5bb3ea
--- /dev/null
+++ b/plugins/Ecommerce/Categories/EcommerceCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Categories;
+
+use Piwik\Category\Category;
+
+class EcommerceCategory extends Category
+{
+ protected $id = 'Goals_Ecommerce';
+ protected $order = 20;
+}
diff --git a/plugins/Ecommerce/Categories/EcommerceLogSubcategory.php b/plugins/Ecommerce/Categories/EcommerceLogSubcategory.php
new file mode 100644
index 0000000000..f3999fda02
--- /dev/null
+++ b/plugins/Ecommerce/Categories/EcommerceLogSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Categories;
+
+use Piwik\Category\Subcategory;
+
+class EcommerceLogSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Ecommerce';
+ protected $id = 'Goals_EcommerceLog';
+ protected $order = 5;
+
+}
diff --git a/plugins/Ecommerce/Categories/EcommerceOverviewSubcategory.php b/plugins/Ecommerce/Categories/EcommerceOverviewSubcategory.php
new file mode 100644
index 0000000000..b8560a8072
--- /dev/null
+++ b/plugins/Ecommerce/Categories/EcommerceOverviewSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Categories;
+
+use Piwik\Category\Subcategory;
+
+class EcommerceOverviewSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Ecommerce';
+ protected $id = 'General_Overview';
+ protected $order = 2;
+
+}
diff --git a/plugins/Ecommerce/Categories/ProductSubcategory.php b/plugins/Ecommerce/Categories/ProductSubcategory.php
new file mode 100644
index 0000000000..d7d8e9a810
--- /dev/null
+++ b/plugins/Ecommerce/Categories/ProductSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Categories;
+
+use Piwik\Category\Subcategory;
+
+class ProductSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Ecommerce';
+ protected $id = 'Goals_Products';
+ protected $order = 10;
+
+}
diff --git a/plugins/Ecommerce/Categories/SalesSubcategory.php b/plugins/Ecommerce/Categories/SalesSubcategory.php
new file mode 100644
index 0000000000..0cb68d3d1c
--- /dev/null
+++ b/plugins/Ecommerce/Categories/SalesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Categories;
+
+use Piwik\Category\Subcategory;
+
+class SalesSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Ecommerce';
+ protected $id = 'Ecommerce_Sales';
+ protected $order = 15;
+
+}
diff --git a/plugins/Ecommerce/Controller.php b/plugins/Ecommerce/Controller.php
index 7cfb955184..780c905c7c 100644
--- a/plugins/Ecommerce/Controller.php
+++ b/plugins/Ecommerce/Controller.php
@@ -8,7 +8,8 @@
*/
namespace Piwik\Plugins\Ecommerce;
-use Exception;
+use Piwik\API\Request;
+use Piwik\Common;
use Piwik\DataTable;
use Piwik\FrontController;
use Piwik\Piwik;
@@ -30,95 +31,75 @@ class Controller extends \Piwik\Plugins\Goals\Controller
parent::__construct($translator, $translationHelper);
}
- public function ecommerceReport()
+ public function getSparklines()
{
- if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('CustomVariables')) {
- throw new Exception("Ecommerce Tracking requires that the plugin Custom Variables is enabled. Please enable the plugin CustomVariables (or ask your admin).");
- }
+ $idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER;
- $view = $this->getGoalReportView($idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER);
- $view->displayFullReport = false;
- $view->headline = $this->translator->translate('General_EvolutionOverPeriod');
+ $view = new View('@Ecommerce/getSparklines');
+ $view->onlyConversionOverview = false;
+ $view->conversionsOverViewEnabled = true;
- return $view->render();
- }
+ if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+ $goalDefinition['name'] = $this->translator->translate('Goals_Ecommerce');
+ $goalDefinition['allow_multiple'] = true;
+ } else {
+ if (!isset($this->goals[$idGoal])) {
+ Piwik::redirectToModule('Goals', 'index', array('idGoal' => null));
+ }
+ $goalDefinition = $this->goals[$idGoal];
+ }
- public function ecommerceLogReport($fetch = false)
- {
- $view = new View('@Ecommerce/ecommerceLog');
$this->setGeneralVariablesView($view);
- $view->ecommerceLog = $this->getEcommerceLog($fetch);
-
- return $view->render();
- }
+ $goal = $this->getMetricsForGoal($idGoal);
+ foreach ($goal as $name => $value) {
+ $view->$name = $value;
+ }
- public function getEcommerceLog($fetch = false)
- {
- $saveGET = $_GET;
- $_GET['segment'] = urlencode('visitEcommerceStatus!=none');
- $_GET['widget'] = 1;
- $output = FrontController::getInstance()->dispatch('Live', 'getVisitorLog', array($fetch));
- $_GET = $saveGET;
+ if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+ $goal = $this->getMetricsForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART);
+ foreach ($goal as $name => $value) {
+ $name = 'cart_' . $name;
+ $view->$name = $value;
+ }
+ }
- return $output;
- }
+ $view->idGoal = $idGoal;
+ $view->goalAllowMultipleConversionsPerVisit = $goalDefinition['allow_multiple'];
- public function index()
- {
- return $this->ecommerceReport();
+ return $view->render();
}
- public function products()
+ public function getConversionsOverview()
{
- $goal = $this->getMetricsForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER);
- $conversions = 0;
- if (!empty($goal['nb_conversions'])) {
- $conversions = $goal['nb_conversions'];
- }
-
- $goal = $this->getMetricsForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART);
-
- $cartNbConversions = 0;
- if (!empty($goal) && array_key_exists('nb_conversions', $goal)) {
- $cartNbConversions = $goal['nb_conversions'];
- }
+ $view = new View('@Ecommerce/conversionOverview');
+ $idGoal = Common::getRequestVar('idGoal', null, 'string');
- $preloadAbandonedCart = $cartNbConversions !== false && $conversions == 0;
+ $goalMetrics = Request::processRequest('Goals.get', array('idGoal' => $idGoal));
+ $dataRow = $goalMetrics->getFirstRow();
- $goalReportsByDimension = new View\ReportsByDimension('Goals');
+ $view->idSite = Common::getRequestVar('idSite', null, 'int');
- $ecommerceCustomParams = array();
- if ($preloadAbandonedCart) {
- $ecommerceCustomParams['abandonedCarts'] = '1';
- } else {
- $ecommerceCustomParams['abandonedCarts'] = '0';
+ if ($dataRow) {
+ $view->revenue = $dataRow->getColumn('revenue');
+ $view->revenue_subtotal = $dataRow->getColumn('revenue_subtotal');
+ $view->revenue_tax = $dataRow->getColumn('revenue_tax');
+ $view->revenue_shipping = $dataRow->getColumn('revenue_shipping');
+ $view->revenue_discount = $dataRow->getColumn('revenue_discount');
}
- $goalReportsByDimension->addReport(
- 'Goals_Products', 'Goals_ProductSKU', 'Goals.getItemsSku', $ecommerceCustomParams);
- $goalReportsByDimension->addReport(
- 'Goals_Products', 'Goals_ProductName', 'Goals.getItemsName', $ecommerceCustomParams);
- $goalReportsByDimension->addReport(
- 'Goals_Products', 'Goals_ProductCategory', 'Goals.getItemsCategory', $ecommerceCustomParams);
-
- $view = new View('@Ecommerce/products');
- $this->setGeneralVariablesView($view);
-
- $view->productsByDimension = $goalReportsByDimension->render();
return $view->render();
}
- public function sales()
+ public function getEcommerceLog($fetch = false)
{
- $viewOverview = $this->getGoalReportView(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER);
- $reportsByDimension = $viewOverview->goalReportsByDimension;
-
- $view = new View('@Ecommerce/sales');
- $this->setGeneralVariablesView($view);
+ $saveGET = $_GET;
+ $_GET['segment'] = urlencode('visitEcommerceStatus!=none');
+ $_GET['widget'] = 1;
+ $output = FrontController::getInstance()->dispatch('Live', 'getVisitorLog', array($fetch));
+ $_GET = $saveGET;
- $view->goalReportsByDimension = $reportsByDimension;
- return $view->render();
+ return $output;
}
}
diff --git a/plugins/Ecommerce/Menu.php b/plugins/Ecommerce/Menu.php
deleted file mode 100644
index 331715be4f..0000000000
--- a/plugins/Ecommerce/Menu.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Ecommerce;
-
-use Piwik\Common;
-use Piwik\Menu\MenuReporting;
-use Piwik\Menu\MenuUser;
-use Piwik\Piwik;
-use Piwik\Site;
-use Piwik\Url;
-
-/**
- */
-class Menu extends \Piwik\Plugin\Menu
-{
-
- public function configureReportingMenu(MenuReporting $menu)
- {
- $idSite = Common::getRequestVar('idSite', null, 'int');
-
- $site = new Site($idSite);
-
- if ($site->isEcommerceEnabled()) {
- $ecommerceParams = array('idGoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER);
- $ecommerceUrl = $this->urlForAction('ecommerceReport', $ecommerceParams);
-
- $menu->addItem('Goals_Ecommerce', '', $ecommerceUrl, 24);
- $menu->addItem('Goals_Ecommerce', 'General_Overview', $ecommerceUrl, 1);
- $menu->addItem('Goals_Ecommerce', 'Goals_EcommerceLog', $this->urlForAction('ecommerceLogReport'), 2);
- $menu->addItem('Goals_Ecommerce', 'Goals_Products', $this->urlForAction('products', $ecommerceParams), 3);
- $menu->addItem('Goals_Ecommerce', 'Ecommerce_Sales', $this->urlForAction('sales', $ecommerceParams), 4);
- }
-
- }
-}
diff --git a/plugins/Ecommerce/Reports/Base.php b/plugins/Ecommerce/Reports/Base.php
index 08a766792a..28a3a4a36f 100644
--- a/plugins/Ecommerce/Reports/Base.php
+++ b/plugins/Ecommerce/Reports/Base.php
@@ -8,20 +8,17 @@
*/
namespace Piwik\Plugins\Ecommerce\Reports;
-use Piwik\API\Proxy;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Site;
-use Piwik\ViewDataTable\Factory as ViewDataTableFactory;
-use Piwik\WidgetsList;
abstract class Base extends Report
{
protected function init()
{
$this->module = 'Goals';
- $this->category = 'Goals_Ecommerce';
+ $this->categoryId = 'Goals_Ecommerce';
}
public function isEnabled()
diff --git a/plugins/Ecommerce/Reports/BaseItem.php b/plugins/Ecommerce/Reports/BaseItem.php
index 5caf770a6b..5896710dc2 100644
--- a/plugins/Ecommerce/Reports/BaseItem.php
+++ b/plugins/Ecommerce/Reports/BaseItem.php
@@ -9,15 +9,18 @@
namespace Piwik\Plugins\Ecommerce\Reports;
use Piwik\Common;
+use Piwik\DataTable;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
-use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
-use Piwik\Plugins\Goals\Goals;
use Piwik\Plugins\Goals\Columns\Metrics\AveragePrice;
use Piwik\Plugins\Goals\Columns\Metrics\AverageQuantity;
use Piwik\Plugins\Goals\Columns\Metrics\ProductConversionRate;
+use Piwik\Plugins\Goals\Conversions;
+use Piwik\Plugins\Goals\Model;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
abstract class BaseItem extends Base
{
@@ -46,7 +49,8 @@ abstract class BaseItem extends Base
public function getMetricsDocumentation()
{
- if ($this->isAbandonedCart()) {
+ // we do not check whether it is abondon carts if not set re performance improvements
+ if ($this->isAbandonedCart($fetchIfNotSet = false)) {
return array(
'revenue' => Piwik::translate('Goals_ColumnRevenueDocumentation',
Piwik::translate('Goals_DocumentationRevenueGeneratedByProductSales')),
@@ -62,6 +66,11 @@ abstract class BaseItem extends Base
return array();
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addToContainerWidget('Products', $factory->createWidget());
+ }
+
public function configureView(ViewDataTable $view)
{
$idSite = Common::getRequestVar('idSite');
@@ -100,7 +109,7 @@ abstract class BaseItem extends Base
$view->config->custom_parameters['viewDataTable'] = 'table';
$abandonedCart = true;
} else {
- $abandonedCart = $this->isAbandonedCart();
+ $abandonedCart = $this->isAbandonedCart($fetchIfNotSet = true);
}
if ($abandonedCart) {
@@ -127,8 +136,32 @@ abstract class BaseItem extends Base
$view->config->columns_to_display = $columnsOrdered;
}
- private function isAbandonedCart()
+ private function isAbandonedCart($fetchIfNotSet)
{
- return Common::getRequestVar('abandonedCarts', '0', 'string') == 1;
+ $abandonedCarts = Common::getRequestVar('abandonedCarts', '', 'string');
+
+ if ($abandonedCarts === '') {
+ if ($fetchIfNotSet) {
+
+ $idSite = Common::getRequestVar('idSite', 0, 'int');
+ $period = Common::getRequestVar('period', '', 'string');
+ $date = Common::getRequestVar('date', '', 'string');
+
+ $conversion = new Conversions();
+ $conversions = $conversion->getConversionForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER, $idSite, $period, $date);
+ $cartNbConversions = $conversion->getConversionForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART, $idSite, $period, $date);
+ $preloadAbandonedCart = $cartNbConversions !== false && $conversions == 0;
+
+ if ($preloadAbandonedCart) {
+ $abandonedCarts = '1';
+ } else {
+ $abandonedCarts = '0';
+ }
+ } else {
+ $abandonedCarts = '0';
+ }
+ }
+
+ return $abandonedCarts == '1';
}
}
diff --git a/plugins/Ecommerce/Reports/GetItemsCategory.php b/plugins/Ecommerce/Reports/GetItemsCategory.php
index bf652ca10d..efd4a9489a 100644
--- a/plugins/Ecommerce/Reports/GetItemsCategory.php
+++ b/plugins/Ecommerce/Reports/GetItemsCategory.php
@@ -20,6 +20,7 @@ class GetItemsCategory extends BaseItem
$this->name = Piwik::translate('Goals_ProductCategory');
$this->dimension = new ProductCategory();
$this->order = 32;
- $this->widgetTitle = 'Goals_ProductCategory';
+
+ $this->subcategoryId = 'Goals_Products';
}
}
diff --git a/plugins/Ecommerce/Reports/GetItemsName.php b/plugins/Ecommerce/Reports/GetItemsName.php
index a320b760e4..db8c7f5d3d 100644
--- a/plugins/Ecommerce/Reports/GetItemsName.php
+++ b/plugins/Ecommerce/Reports/GetItemsName.php
@@ -20,6 +20,7 @@ class GetItemsName extends BaseItem
$this->name = Piwik::translate('Goals_ProductName');
$this->dimension = new ProductName();
$this->order = 31;
- $this->widgetTitle = 'Goals_ProductName';
+
+ $this->subcategoryId = 'Goals_Products';
}
}
diff --git a/plugins/Ecommerce/Reports/GetItemsSku.php b/plugins/Ecommerce/Reports/GetItemsSku.php
index a2b20eb3f9..9056b2ff6c 100644
--- a/plugins/Ecommerce/Reports/GetItemsSku.php
+++ b/plugins/Ecommerce/Reports/GetItemsSku.php
@@ -21,7 +21,8 @@ class GetItemsSku extends BaseItem
$this->name = Piwik::translate('Goals_ProductSKU');
$this->dimension = new ProductSku();
$this->order = 30;
- $this->widgetTitle = 'Goals_ProductSKU';
+
+ $this->subcategoryId = 'Goals_Products';
}
}
diff --git a/plugins/Ecommerce/Widgets.php b/plugins/Ecommerce/Widgets.php
deleted file mode 100644
index e20a73850e..0000000000
--- a/plugins/Ecommerce/Widgets.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Ecommerce;
-
-use Piwik\Common;
-use Piwik\Site;
-use Piwik\Piwik;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'Goals_Ecommerce';
-
- protected function init()
- {
- $idSite = $this->getIdSite();
-
- $site = new Site($idSite);
- if ($site->isEcommerceEnabled()) {
- $this->addWidget('General_Overview', 'widgetGoalReport', array('idGoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER));
- $this->addWidget('Goals_EcommerceLog', 'getEcommerceLog');
- }
- }
-
- private function getIdSite()
- {
- return Common::getRequestVar('idSite', null, 'int');
- }
-
-}
diff --git a/plugins/Ecommerce/Widgets/GetEcommerceLog.php b/plugins/Ecommerce/Widgets/GetEcommerceLog.php
new file mode 100644
index 0000000000..d1a68a435a
--- /dev/null
+++ b/plugins/Ecommerce/Widgets/GetEcommerceLog.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Widgets;
+
+use Piwik\Common;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Site;
+
+class GetEcommerceLog extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Goals_Ecommerce');
+ $config->setSubcategoryId('Goals_EcommerceLog');
+ $config->setName('Goals_EcommerceLog');
+
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $site = new Site($idSite);
+ $config->setIsEnabled($site->isEcommerceEnabled());
+ }
+
+}
diff --git a/plugins/Ecommerce/Widgets/ProductsByDimension.php b/plugins/Ecommerce/Widgets/ProductsByDimension.php
new file mode 100644
index 0000000000..2f25e23b76
--- /dev/null
+++ b/plugins/Ecommerce/Widgets/ProductsByDimension.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Ecommerce\Widgets;
+
+use Piwik\Common;
+use Piwik\Plugins\CoreHome\CoreHome;
+use Piwik\Site;
+use Piwik\Widget\WidgetContainerConfig;
+
+class ProductsByDimension extends WidgetContainerConfig
+{
+ protected $layout = CoreHome::WIDGET_CONTAINER_LAYOUT_BY_DIMENSION;
+ protected $id = 'Products';
+ protected $categoryId = 'Goals_Ecommerce';
+ protected $subcategoryId = 'Goals_Products';
+
+ public function isEnabled()
+ {
+ $idSite = Common::getRequestVar('idSite', false, 'int');
+
+ if (empty($idSite)) {
+ return false;
+ }
+
+ $site = new Site($idSite);
+ return $site->isEcommerceEnabled();
+ }
+}
diff --git a/plugins/Ecommerce/templates/conversionOverview.twig b/plugins/Ecommerce/templates/conversionOverview.twig
new file mode 100644
index 0000000000..9b6864c03c
--- /dev/null
+++ b/plugins/Ecommerce/templates/conversionOverview.twig
@@ -0,0 +1,15 @@
+<ul class="ulGoalTopElements">
+ {{ 'General_ColumnRevenue'|translate }}: {{ revenue|money(idSite)|raw -}}
+ {% if revenue_subtotal is not empty %},
+ {{ 'General_Subtotal'|translate }}: {{ revenue_subtotal|money(idSite)|raw -}}
+ {% endif %}
+ {%- if revenue_tax is not empty -%},
+ {{ 'General_Tax'|translate }}: {{ revenue_tax|money(idSite)|raw -}}
+ {% endif %}
+ {%- if revenue_shipping is not empty -%},
+ {{ 'General_Shipping'|translate }}: {{ revenue_shipping|money(idSite)|raw -}}
+ {% endif %}
+ {%- if revenue_discount is not empty -%},
+ {{ 'General_Discount'|translate }}: {{ revenue_discount|money(idSite)|raw -}}
+ {% endif %}
+</ul><br/> \ No newline at end of file
diff --git a/plugins/Ecommerce/templates/ecommerceLog.twig b/plugins/Ecommerce/templates/ecommerceLog.twig
deleted file mode 100644
index 4c40a94d99..0000000000
--- a/plugins/Ecommerce/templates/ecommerceLog.twig
+++ /dev/null
@@ -1,3 +0,0 @@
-<h2 piwik-enriched-headline>{{ 'Goals_EcommerceLog'|translate }}</h2>
-
-{{ ecommerceLog|raw }}
diff --git a/plugins/Ecommerce/templates/getSparklines.twig b/plugins/Ecommerce/templates/getSparklines.twig
new file mode 100644
index 0000000000..0952c081a5
--- /dev/null
+++ b/plugins/Ecommerce/templates/getSparklines.twig
@@ -0,0 +1,55 @@
+<div id='leftcolumn' style="clear:both;{% if not isWidget %}width:33%;'{% endif %}">
+ <div class="sparkline">{{ sparkline(urlSparklineConversions) }}
+ <strong>{{ nb_conversions }}</strong>
+ {{ 'General_EcommerceOrders'|translate }}
+ <img src='plugins/Morpheus/images/ecommerceOrder.gif'>
+
+ {% if goalAllowMultipleConversionsPerVisit is defined and goalAllowMultipleConversionsPerVisit %}
+ ({{ 'General_NVisits'|translate("<strong>"~nb_visits_converted~"</strong>")|raw }})
+ {% endif %}
+ </div>
+
+ <div class="sparkline">
+ {{ sparkline(urlSparklineRevenue) }}
+ {% set revenue=revenue|money(idSite) %}
+ <strong>{{ revenue|raw }}</strong> {{ 'General_TotalRevenue'|translate }}
+ </div>
+
+ <div class="sparkline">{{ sparkline(urlSparklineAverageOrderValue) }}
+ <strong>{{ avg_order_revenue|money(idSite)|raw }}</strong>
+ {{ 'General_AverageOrderValue'|translate }}
+ </div>
+</div>
+<div id='leftcolumn' {% if not isWidget %}style='width:33%;'{% endif %}>
+ <div class="sparkline">{{ sparkline(urlSparklineConversionRate) }}
+ {% set ecommerceOrdersText %}{{ 'General_EcommerceOrders'|translate }}{% endset %}
+ {{ 'Goals_ConversionRate'|translate("<strong>"~conversion_rate~"</strong> "~ecommerceOrdersText)|raw }}
+ </div>
+ <div class="sparkline">{{ sparkline(urlSparklinePurchasedProducts) }}
+ <strong>{{ items }}</strong> {{ 'General_PurchasedProducts'|translate }}</div>
+</div>
+<div id='rightcolumn' {% if not isWidget %}style='width:30%;'{% endif %}>
+ <div>
+ <img src='plugins/Morpheus/images/ecommerceAbandonedCart.gif'> <em>{{ 'General_AbandonedCarts'|translate }}</em>
+ </div>
+
+ <div class="sparkline">
+ {{ sparkline(cart_urlSparklineConversions) }}
+ {% set ecommerceAbandonedCartsText %}{{ 'Goals_AbandonedCart'|translate }}{% endset %}
+ <strong>{{ cart_nb_conversions }}</strong> {{ 'General_VisitsWith'|translate(ecommerceAbandonedCartsText) }}
+ </div>
+
+ <div class="sparkline">
+ {{ sparkline(cart_urlSparklineRevenue) }}
+ {% set revenue %}{{ cart_revenue|money(idSite)|raw }}{% endset %}
+ {% set revenueText %}{{ 'General_ColumnRevenue'|translate }}{% endset %}
+ <strong>{{ revenue }}</strong> {{ 'Goals_LeftInCart'|translate(revenueText) }}
+ </div>
+
+ <div class="sparkline">
+ {{ sparkline(cart_urlSparklineConversionRate) }}
+ <strong>{{ cart_conversion_rate }}</strong>
+ {{ 'General_VisitsWith'|translate(ecommerceAbandonedCartsText) }}
+ </div>
+</div>
+{% include "_sparklineFooter.twig" %}
diff --git a/plugins/Events/Categories/EventsSubcategory.php b/plugins/Events/Categories/EventsSubcategory.php
new file mode 100644
index 0000000000..e969029e13
--- /dev/null
+++ b/plugins/Events/Categories/EventsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Events\Categories;
+
+use Piwik\Category\Subcategory;
+
+class EventsSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Actions';
+ protected $id = 'Events_Events';
+ protected $order = 40;
+
+}
diff --git a/plugins/Events/Controller.php b/plugins/Events/Controller.php
deleted file mode 100644
index 3429443b88..0000000000
--- a/plugins/Events/Controller.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Events;
-
-use Piwik\View;
-
-/**
- * Events controller
- *
- */
-class Controller extends \Piwik\Plugin\Controller
-{
- public function index()
- {
- $view = new View('@Events/index');
- $view->leftMenuReports = $this->getLeftMenuReports();
- return $view->render();
- }
-
- private function getLeftMenuReports()
- {
- $reports = new View\ReportsByDimension('Events');
- foreach(Events::getLabelTranslations() as $apiAction => $translations) {
- // 'getCategory' is the API method, but we are loading 'indexCategory' which displays <h2>
- $count = 1;
- $controllerAction = str_replace("get", "index", $apiAction, $count);
- $params = array(
- 'secondaryDimension' => API::getInstance()->getDefaultSecondaryDimension($apiAction)
- );
- $reports->addReport('Events_TopEvents', $translations[0], 'Events.' . $controllerAction, $params);
- }
- return $reports->render();
- }
-
- public function indexCategory()
- {
- return $this->indexEvent(__FUNCTION__);
- }
-
- public function indexAction()
- {
- return $this->indexEvent(__FUNCTION__);
- }
-
- public function indexName()
- {
- return $this->indexEvent(__FUNCTION__);
- }
-
- public function getActionFromCategoryId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- public function getNameFromCategoryId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- public function getCategoryFromActionId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- public function getNameFromActionId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- public function getActionFromNameId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- public function getCategoryFromNameId()
- {
- return $this->renderReport(__FUNCTION__);
- }
-
- protected function indexEvent($controllerMethod)
- {
- $count = 1;
- $apiMethod = str_replace('index', 'get', $controllerMethod, $count);
- $events = new Events;
- $title = $events->getReportTitleTranslation($apiMethod);
-
- if (method_exists($this, $apiMethod)) {
- $content = $this->$apiMethod();
- } else {
- $content = $this->renderReport($apiMethod);
- }
-
- return View::singleReport(
- $title,
- $content
- );
- }
-}
diff --git a/plugins/Events/Events.php b/plugins/Events/Events.php
index ba3e96465d..f09e1a9925 100644
--- a/plugins/Events/Events.php
+++ b/plugins/Events/Events.php
@@ -12,6 +12,7 @@ use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugin\Reports;
class Events extends \Piwik\Plugin
{
@@ -154,7 +155,7 @@ class Events extends \Piwik\Plugin
$this->addRelatedReports($view, $secondaryDimension);
$this->addTooltipEventValue($view);
- $subtableReport = Report::factory('Events', $view->config->subtable_controller_action);
+ $subtableReport = Reports::factory('Events', $view->config->subtable_controller_action);
$view->config->pivot_by_dimension = $subtableReport->getDimension()->getId();
$view->config->pivot_by_column = 'nb_events';
}
diff --git a/plugins/Events/Menu.php b/plugins/Events/Menu.php
deleted file mode 100644
index 440a35978e..0000000000
--- a/plugins/Events/Menu.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Events;
-
-use Piwik\Menu\MenuReporting;
-
-/**
- */
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addActionsItem('Events_Events', $this->urlForAction('index'), 30);
- }
-}
diff --git a/plugins/Events/Reports/Base.php b/plugins/Events/Reports/Base.php
index 4430b31407..a43ba0dbfa 100644
--- a/plugins/Events/Reports/Base.php
+++ b/plugins/Events/Reports/Base.php
@@ -10,19 +10,31 @@ namespace Piwik\Plugins\Events\Reports;
use Piwik\Plugins\Events\API;
use Piwik\Plugins\Events\Columns\Metrics\AverageEventValue;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'General_Actions';
+ $this->subcategoryId = 'Events_Events';
+
$this->processedMetrics = array(
new AverageEventValue()
);
+ }
- $this->widgetParams = array(
- 'secondaryDimension' => API::getInstance()->getDefaultSecondaryDimension($this->action)
- );
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ if (!$this->isSubtableReport) {
+ $widget = $factory->createWidget()->setParameters(array(
+ 'secondaryDimension' => API::getInstance()->getDefaultSecondaryDimension($this->action)
+ ));
+
+ $widgetsList->addToContainerWidget('Events', $widget);
+ }
}
+
}
diff --git a/plugins/Events/Reports/GetAction.php b/plugins/Events/Reports/GetAction.php
index 84f750e264..bbdadd7ed4 100644
--- a/plugins/Events/Reports/GetAction.php
+++ b/plugins/Events/Reports/GetAction.php
@@ -27,6 +27,5 @@ class GetAction extends Base
$this->actionToLoadSubTables = 'getNameFromActionId';
}
$this->order = 1;
- $this->widgetTitle = 'Events_EventActions';
}
}
diff --git a/plugins/Events/Reports/GetActionFromCategoryId.php b/plugins/Events/Reports/GetActionFromCategoryId.php
index e5de6af9ca..9c355d4de1 100644
--- a/plugins/Events/Reports/GetActionFromCategoryId.php
+++ b/plugins/Events/Reports/GetActionFromCategoryId.php
@@ -19,7 +19,7 @@ class GetActionFromCategoryId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventAction();
$this->name = Piwik::translate('Events_EventActions');
diff --git a/plugins/Events/Reports/GetActionFromNameId.php b/plugins/Events/Reports/GetActionFromNameId.php
index 55bd628459..1da175e47b 100644
--- a/plugins/Events/Reports/GetActionFromNameId.php
+++ b/plugins/Events/Reports/GetActionFromNameId.php
@@ -19,7 +19,7 @@ class GetActionFromNameId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventAction();
$this->name = Piwik::translate('Events_EventActions');
diff --git a/plugins/Events/Reports/GetCategory.php b/plugins/Events/Reports/GetCategory.php
index be867705ea..2049868e7c 100644
--- a/plugins/Events/Reports/GetCategory.php
+++ b/plugins/Events/Reports/GetCategory.php
@@ -27,6 +27,5 @@ class GetCategory extends Base
$this->actionToLoadSubTables = 'getActionFromCategoryId';
}
$this->order = 0;
- $this->widgetTitle = 'Events_EventCategories';
}
}
diff --git a/plugins/Events/Reports/GetCategoryFromActionId.php b/plugins/Events/Reports/GetCategoryFromActionId.php
index 51f5f6918d..47e62c9260 100644
--- a/plugins/Events/Reports/GetCategoryFromActionId.php
+++ b/plugins/Events/Reports/GetCategoryFromActionId.php
@@ -19,7 +19,7 @@ class GetCategoryFromActionId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventCategory();
$this->name = Piwik::translate('Events_EventCategories');
diff --git a/plugins/Events/Reports/GetCategoryFromNameId.php b/plugins/Events/Reports/GetCategoryFromNameId.php
index 4806c97d0f..0eef6b5f32 100644
--- a/plugins/Events/Reports/GetCategoryFromNameId.php
+++ b/plugins/Events/Reports/GetCategoryFromNameId.php
@@ -19,7 +19,7 @@ class GetCategoryFromNameId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventCategory();
$this->name = Piwik::translate('Events_EventCategories');
diff --git a/plugins/Events/Reports/GetName.php b/plugins/Events/Reports/GetName.php
index aa21f968be..08d97b6ac4 100644
--- a/plugins/Events/Reports/GetName.php
+++ b/plugins/Events/Reports/GetName.php
@@ -27,6 +27,5 @@ class GetName extends Base
$this->actionToLoadSubTables = 'getActionFromNameId';
}
$this->order = 2;
- $this->widgetTitle = 'Events_EventNames';
}
}
diff --git a/plugins/Events/Reports/GetNameFromActionId.php b/plugins/Events/Reports/GetNameFromActionId.php
index 7b4899b672..4c0325a706 100644
--- a/plugins/Events/Reports/GetNameFromActionId.php
+++ b/plugins/Events/Reports/GetNameFromActionId.php
@@ -19,7 +19,7 @@ class GetNameFromActionId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventName();
$this->name = Piwik::translate('Events_Names');
diff --git a/plugins/Events/Reports/GetNameFromCategoryId.php b/plugins/Events/Reports/GetNameFromCategoryId.php
index d1f43f7931..6e28ccf1e9 100644
--- a/plugins/Events/Reports/GetNameFromCategoryId.php
+++ b/plugins/Events/Reports/GetNameFromCategoryId.php
@@ -19,7 +19,7 @@ class GetNameFromCategoryId extends Report
{
protected function init()
{
- $this->category = 'Events_Events';
+ $this->categoryId = 'Events_Events';
$this->processedMetrics = false;
$this->dimension = new EventName();
$this->name = Piwik::translate('Events_EventNames');
diff --git a/plugins/Events/Widgets/EventsByDimension.php b/plugins/Events/Widgets/EventsByDimension.php
new file mode 100644
index 0000000000..ef04e0d761
--- /dev/null
+++ b/plugins/Events/Widgets/EventsByDimension.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Events\Widgets;
+
+use Piwik\Plugins\CoreHome\CoreHome;
+use Piwik\Translation\Translator;
+use Piwik\Widget\WidgetContainerConfig;
+
+class EventsByDimension extends WidgetContainerConfig
+{
+ protected $layout = CoreHome::WIDGET_CONTAINER_LAYOUT_BY_DIMENSION;
+ protected $id = 'Events';
+ protected $categoryId = 'General_Actions';
+ protected $subcategoryId = 'Events_Events';
+
+}
diff --git a/plugins/Events/templates/index.twig b/plugins/Events/templates/index.twig
deleted file mode 100644
index a12afb651a..0000000000
--- a/plugins/Events/templates/index.twig
+++ /dev/null
@@ -1,2 +0,0 @@
-{{ leftMenuReports|raw }}
-
diff --git a/plugins/ExamplePlugin/Menu.php b/plugins/ExamplePlugin/Menu.php
index f890587fea..7c9acb90f6 100644
--- a/plugins/ExamplePlugin/Menu.php
+++ b/plugins/ExamplePlugin/Menu.php
@@ -9,27 +9,16 @@
namespace Piwik\Plugins\ExamplePlugin;
use Piwik\Menu\MenuAdmin;
-use Piwik\Menu\MenuReporting;
use Piwik\Menu\MenuTop;
use Piwik\Menu\MenuUser;
/**
* This class allows you to add, remove or rename menu items.
- * To configure a menu (such as Admin Menu, Reporting Menu, User Menu...) simply call the corresponding methods as
+ * To configure a menu (such as Admin Menu, Top Menu, User Menu...) simply call the corresponding methods as
* described in the API-Reference http://developer.piwik.org/api-reference/Piwik/Menu/MenuAbstract
*/
class Menu extends \Piwik\Plugin\Menu
{
- public function configureReportingMenu(MenuReporting $menu)
- {
- // reuse an existing category. Execute the showList() method within the controller when menu item was clicked
- // $menu->addVisitorsItem('Report 1', $this->urlForAction('showList'), $orderId = 30);
- // $menu->addActionsItem('Report 1', $this->urlForAction('showList'), $orderId = 30);
-
- // or create a custom category 'UI Framework'
- // $menu->addItem('UI Framework', '', $this->urlForDefaultAction(), $orderId = 30);
- // $menu->addItem('UI Framework', 'Report 1', $this->urlForAction('showList'), $orderId = 30);
- }
public function configureAdminMenu(MenuAdmin $menu)
{
diff --git a/plugins/ExamplePlugin/Widgets.php b/plugins/ExamplePlugin/Widgets.php
deleted file mode 100644
index a5670902ef..0000000000
--- a/plugins/ExamplePlugin/Widgets.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-
-namespace Piwik\Plugins\ExamplePlugin;
-
-use Piwik\View;
-use Piwik\WidgetsList;
-
-/**
- * This class allows you to add your own widgets to the Piwik platform. In case you want to remove widgets from another
- * plugin please have a look at the "configureWidgetsList()" method.
- * To configure a widget simply call the corresponding methods as described in the API-Reference:
- * http://developer.piwik.org/api-reference/Piwik/Plugin\Widgets
- */
-class Widgets extends \Piwik\Plugin\Widgets
-{
- /**
- * Here you can define the category the widget belongs to. You can reuse any existing widget category or define
- * your own category.
- * @var string
- */
- protected $category = 'Example Category';
-
- /**
- * Here you can add one or multiple widgets. You can add a widget by calling the method "addWidget()" and pass the
- * name of the widget as well as a method name that should be called to render the widget. The method can be
- * defined either directly here in this widget class or in the controller in case you want to reuse the same action
- * for instance in the menu etc.
- */
- protected function init()
- {
- // $this->addWidget('Example Widget Name', $method = 'myExampleWidget');
- // $this->addWidget('Example Widget 2', $method = 'myExampleWidget', $params = array('myparam' => 'myvalue'));
- }
-
- /**
- * This method renders a widget as defined in "init()". It's on you how to generate the content of the
- * widget. As long as you return a string everything is fine. You can use for instance a "Piwik\View" to render a
- * twig template. In such a case don't forget to create a twig template (eg. myViewTemplate.twig) in the
- * "templates" directory of your plugin.
- *
- * @return string
- */
- public function myExampleWidget()
- {
- // $view = new View('@ExamplePlugin/myViewTemplate');
- // return $view->render();
-
- return 'My Widget Text';
- }
-
- /**
- * Here you can remove any widgets defined by any plugin.
- *
- * @param WidgetsList $widgetsList
- */
- public function configureWidgetsList(WidgetsList $widgetsList)
- {
- // $widgetsList->remove('NameOfWidgetCategory'); // will remove all widgets having this category
- // $widgetsList->remove('NameOfWidgetCategory', 'Widget name'); // will only remove a specific widget
- }
-}
diff --git a/plugins/ExamplePlugin/Widgets/MyExampleWidget.php b/plugins/ExamplePlugin/Widgets/MyExampleWidget.php
new file mode 100644
index 0000000000..687ee6df67
--- /dev/null
+++ b/plugins/ExamplePlugin/Widgets/MyExampleWidget.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExamplePlugin\Widgets;
+
+use Piwik\Widget\Widget;
+use Piwik\Widget\WidgetConfig;
+use Piwik\View;
+
+/**
+ * This class allows you to add your own widget to the Piwik platform. In case you want to remove widgets from another
+ * plugin please have a look at the "configureWidgetsList()" method.
+ * To configure a widget simply call the corresponding methods as described in the API-Reference:
+ * http://developer.piwik.org/api-reference/Piwik/Plugin\Widget
+ */
+class MyExampleWidget extends Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ /**
+ * Set the category the widget belongs to. You can reuse any existing widget category or define
+ * your own category.
+ */
+ $config->setCategoryId('Example Widgets');
+
+ /**
+ * Set the subcategory the widget belongs to. If a subcategory is set, the widget will be shown in the UI.
+ */
+ // $config->setSubcategoryId('General_Overview');
+
+ /**
+ * Set the name of the widget belongs to.
+ */
+ $config->setName('Example Widget Name');
+
+ /**
+ * Set the order of the widget. The lower the number, the earlier the widget will be listed within a category.
+ */
+ $config->setOrder(99);
+
+ /**
+ * Optionally set URL parameters that will be used when this widget is requested.
+ * $config->setParameters(array('myparam' => 'myvalue'));
+ */
+
+ /**
+ * Define whether a widget is enabled or not. For instance some widgets might not be available to every user or
+ * might depend on a setting (such as Ecommerce) of a site. In such a case you can perform any checks and then
+ * set `true` or `false`. If your widget is only available to users having super user access you can do the
+ * following:
+ *
+ * $config->setIsEnabled(\Piwik\Piwik::hasUserSuperUserAccess());
+ * or
+ * if (!\Piwik\Piwik::hasUserSuperUserAccess())
+ * $config->disable();
+ */
+ }
+
+ /**
+ * This method renders the widget. It's on you how to generate the content of the widget.
+ * As long as you return a string everything is fine. You can use for instance a "Piwik\View" to render a
+ * twig template. In such a case don't forget to create a twig template (eg. myViewTemplate.twig) in the
+ * "templates" directory of your plugin.
+ *
+ * @return string
+ */
+ public function render()
+ {
+ // $view = new View('@ExamplePlugin/myViewTemplate');
+ // return $view->render();
+
+ return '<div>My Widget Text</div>';
+ }
+
+} \ No newline at end of file
diff --git a/plugins/ExampleReport/Reports/Base.php b/plugins/ExampleReport/Reports/Base.php
index c09da78e4b..35af935d9e 100644
--- a/plugins/ExampleReport/Reports/Base.php
+++ b/plugins/ExampleReport/Reports/Base.php
@@ -14,6 +14,6 @@ abstract class Base extends Report
{
protected function init()
{
- $this->category = 'ExampleCategory';
+ $this->categoryId = 'ExampleCategory';
}
}
diff --git a/plugins/ExampleReport/Reports/GetExampleReport.php b/plugins/ExampleReport/Reports/GetExampleReport.php
index 42af54d04a..9e0980f050 100644
--- a/plugins/ExampleReport/Reports/GetExampleReport.php
+++ b/plugins/ExampleReport/Reports/GetExampleReport.php
@@ -49,12 +49,8 @@ class GetExampleReport extends Base
// 24 rows for 1-24hours
// $this->constantRowsCount = true;
- // If a menu title is specified, the report will be displayed in the menu
- // $this->menuTitle = 'ExampleReportName';
-
- // If a widget title is specified, the report will be displayed in the list of widgets and the report can be
- // exported as a widget
- // $this->widgetTitle = 'ExampleReportName';
+ // If a subcategory is specified, the report will be displayed in the menu under this menu item
+ // $this->subCategory = 'ExampleReportName';
}
/**
diff --git a/plugins/ExampleRssWidget/Widgets.php b/plugins/ExampleRssWidget/Widgets/RssChangelog.php
index 5fc0667fa8..70ba5eb0c0 100644
--- a/plugins/ExampleRssWidget/Widgets.php
+++ b/plugins/ExampleRssWidget/Widgets/RssChangelog.php
@@ -6,35 +6,21 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
-namespace Piwik\Plugins\ExampleRssWidget;
+namespace Piwik\Plugins\ExampleRssWidget\Widgets;
use Piwik\Piwik;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Plugins\ExampleRssWidget\RssRenderer;
-class Widgets extends \Piwik\Plugin\Widgets
+class RssChangelog extends \Piwik\Widget\Widget
{
- protected $category = 'Example Widgets';
-
- protected function init()
- {
- $this->addWidget('Piwik.org Blog', 'rssPiwik');
- $this->addWidget('Piwik Changelog', 'rssChangelog');
- }
-
- public function rssPiwik()
+ public static function configure(WidgetConfig $config)
{
- try {
- $rss = new RssRenderer('http://feeds.feedburner.com/Piwik');
- $rss->showDescription(true);
-
- return $rss->get();
-
- } catch (\Exception $e) {
-
- return $this->error($e);
- }
+ $config->setCategoryId('Example Widgets');
+ $config->setName('Piwik Changelog');
}
- public function rssChangelog()
+ public function render()
{
try {
$rss = new RssRenderer('http://feeds.feedburner.com/PiwikReleases');
diff --git a/plugins/ExampleRssWidget/Widgets/RssPiwik.php b/plugins/ExampleRssWidget/Widgets/RssPiwik.php
new file mode 100644
index 0000000000..c3c7c76a16
--- /dev/null
+++ b/plugins/ExampleRssWidget/Widgets/RssPiwik.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleRssWidget\Widgets;
+
+use Piwik\Piwik;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Plugins\ExampleRssWidget\RssRenderer;
+
+class RssPiwik extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Example Widgets');
+ $config->setName('Piwik.org Blog');
+ }
+
+ public function render()
+ {
+ try {
+ $rss = new RssRenderer('http://feeds.feedburner.com/Piwik');
+ $rss->showDescription(true);
+
+ return $rss->get();
+
+ } catch (\Exception $e) {
+
+ return $this->error($e);
+ }
+ }
+
+ /**
+ * @param \Exception $e
+ * @return string
+ */
+ private function error($e)
+ {
+ return '<div class="pk-emptyDataTable">'
+ . Piwik::translate('General_ErrorRequest', array('', ''))
+ . ' - ' . $e->getMessage() . '</div>';
+ }
+}
diff --git a/plugins/ExampleUI/API.php b/plugins/ExampleUI/API.php
index 7b6e0c508a..ae9beae05f 100644
--- a/plugins/ExampleUI/API.php
+++ b/plugins/ExampleUI/API.php
@@ -99,4 +99,5 @@ class API extends \Piwik\Plugin\API
return $planetsDataTable;
}
+
}
diff --git a/plugins/ExampleUI/Categories/ExampleUiCategory.php b/plugins/ExampleUI/Categories/ExampleUiCategory.php
new file mode 100644
index 0000000000..cc7d2fd219
--- /dev/null
+++ b/plugins/ExampleUI/Categories/ExampleUiCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleUI\Categories;
+
+use Piwik\Category\Category;
+
+class ExampleUiCategory extends Category
+{
+ protected $id = 'ExampleUI_UiFramework';
+ protected $order = 90;
+}
diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php
index 210093c8b5..c032d449fa 100644
--- a/plugins/ExampleUI/Controller.php
+++ b/plugins/ExampleUI/Controller.php
@@ -18,38 +18,6 @@ use Piwik\ViewDataTable\Factory as ViewDataTableFactory;
*/
class Controller extends \Piwik\Plugin\Controller
{
- public function dataTables()
- {
- $controllerAction = $this->pluginName . '.' . __FUNCTION__;
- $apiAction = 'ExampleUI.getTemperatures';
-
- $view = ViewDataTableFactory::build('table', $apiAction, $controllerAction);
-
- $view->config->translations['value'] = 'Temperature in °C';
- $view->config->translations['label'] = 'Hour of day';
- $view->requestConfig->filter_sort_column = 'label';
- $view->requestConfig->filter_sort_order = 'asc';
- $view->requestConfig->filter_limit = 24;
- $view->config->columns_to_display = array('label', 'value');
- $view->config->y_axis_unit = '°C'; // useful if the user requests the bar graph
- $view->config->show_exclude_low_population = false;
- $view->config->show_table_all_columns = false;
- $view->config->disable_row_evolution = true;
- $view->config->max_graph_elements = 24;
- $view->config->metrics_documentation = array('value' => 'Documentation for temperature metric');
-
- return $view->render();
- }
-
- public function evolutionGraph()
- {
- $view = new View('@ExampleUI/evolutiongraph');
-
- $this->setPeriodVariablesView($view);
- $view->evolutionGraph = $this->getEvolutionGraph(array(), array('server1', 'server2'));
-
- return $view->render();
- }
public function notifications()
{
@@ -78,126 +46,4 @@ class Controller extends \Piwik\Plugin\Controller
return $view->render();
}
- public function getEvolutionGraph(array $columns = array(), array $defaultColumns = array())
- {
- if (empty($columns)) {
- $columns = Common::getRequestVar('columns', false);
- if (false !== $columns) {
- $columns = Piwik::getArrayFromApiParameter($columns);
- }
- }
-
- $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns,
- $selectableColumns = array('server1', 'server2'), 'My documentation', 'ExampleUI.getTemperaturesEvolution');
- $view->requestConfig->filter_sort_column = 'label';
- $view->requestConfig->filter_sort_order = 'asc';
-
- if (empty($view->config->columns_to_display) && !empty($defaultColumns)) {
- $view->config->columns_to_display = $defaultColumns;
- }
-
- return $this->renderView($view);
- }
-
- public function barGraph()
- {
- $view = ViewDataTableFactory::build(
- 'graphVerticalBar', 'ExampleUI.getTemperatures', $controllerAction = 'ExampleUI.barGraph');
-
- $view->config->y_axis_unit = '°C';
- $view->config->show_footer = false;
- $view->config->translations['value'] = "Temperature";
- $view->config->selectable_columns = array("value");
- $view->config->max_graph_elements = 24;
-
- return $view->render();
- }
-
- public function pieGraph()
- {
- $view = ViewDataTableFactory::build(
- 'graphPie', 'ExampleUI.getPlanetRatios', $controllerAction = 'ExampleUI.pieGraph');
-
- $view->config->columns_to_display = array('value');
- $view->config->translations['value'] = "times the diameter of Earth";
- $view->config->show_footer_icons = false;
- $view->config->selectable_columns = array("value");
- $view->config->max_graph_elements = 10;
-
- return $view->render();
- }
-
- public function tagClouds()
- {
- $output = "<h2>Simple tag cloud</h2>";
- $output .= $this->echoSimpleTagClouds();
-
- $output .= "<br /><br /><h2>Advanced tag cloud: with logos and links</h2>
- <ul style='list-style-type:disc;margin-left:50px'>
- <li>The logo size is proportional to the value returned by the API</li>
- <li>The logo is linked to a specific URL</li>
- </ul><br /><br />";
- $output .= $this->echoAdvancedTagClouds();
-
- return $output;
- }
-
- public function echoSimpleTagClouds()
- {
- $view = ViewDataTableFactory::build(
- 'cloud', 'ExampleUI.getPlanetRatios', $controllerAction = 'ExampleUI.echoSimpleTagClouds');
-
- $view->config->columns_to_display = array('label', 'value');
- $view->config->translations['value'] = "times the diameter of Earth";
- $view->config->show_footer = false;
-
- return $view->render();
- }
-
- public function echoAdvancedTagClouds()
- {
- $view = ViewDataTableFactory::build(
- 'cloud', 'ExampleUI.getPlanetRatiosWithLogos', $controllerAction = 'ExampleUI.echoAdvancedTagClouds');
-
- $view->config->display_logo_instead_of_label = true;
- $view->config->columns_to_display = array('label', 'value');
- $view->config->translations['value'] = "times the diameter of Earth";
-
- return $view->render();
- }
-
- public function sparklines()
- {
- $view = new View('@ExampleUI/sparklines');
- $view->urlSparkline1 = $this->getUrlSparkline('generateSparkline', array('server' => 'server1', 'rand' => mt_rand()));
- $view->urlSparkline2 = $this->getUrlSparkline('generateSparkline', array('server' => 'server2', 'rand' => mt_rand()));
-
- return $view->render();
- }
-
- public function generateSparkline()
- {
- $view = ViewDataTableFactory::build(
- 'sparkline', 'ExampleUI.getTemperaturesEvolution', $controllerAction = 'ExampleUI.generateSparkline');
-
- $serverRequested = Common::getRequestVar('server', false);
- if (false !== $serverRequested) {
- $view->config->columns_to_display = array($serverRequested);
- }
-
- return $view->render();
- }
-
- public function treemap()
- {
- $view = ViewDataTableFactory::build(
- 'infoviz-treemap', 'ExampleUI.getTemperatures', $controllerAction = 'ExampleUI.treemap');
-
- $view->config->translations['value'] = "Temperature";
- $view->config->columns_to_display = array("label", "value");
- $view->config->selectable_columns = array("value");
- $view->config->show_evolution_values = 0;
-
- return $view->render();
- }
}
diff --git a/plugins/ExampleUI/Menu.php b/plugins/ExampleUI/Menu.php
index e25bd10817..35cf0d70b5 100644
--- a/plugins/ExampleUI/Menu.php
+++ b/plugins/ExampleUI/Menu.php
@@ -8,37 +8,12 @@
*/
namespace Piwik\Plugins\ExampleUI;
-use Piwik\Menu\MenuReporting;
use Piwik\Menu\MenuUser;
-use Piwik\Plugin\Manager as PluginManager;
-/**
- */
class Menu extends \Piwik\Plugin\Menu
{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addItem('UI Framework', '', $this->urlForAction('dataTables'), 30);
-
- $this->addSubMenu($menu, 'Data tables', 'dataTables', 1);
- $this->addSubMenu($menu, 'Bar graph', 'barGraph', 2);
- $this->addSubMenu($menu, 'Pie graph', 'pieGraph', 3);
- $this->addSubMenu($menu, 'Tag clouds', 'tagClouds', 4);
- $this->addSubMenu($menu, 'Sparklines', 'sparklines', 5);
- $this->addSubMenu($menu, 'Evolution Graph', 'evolutionGraph', 6);
-
- if (PluginManager::getInstance()->isPluginActivated('TreemapVisualization')) {
- $this->addSubMenu($menu, 'Treemap', 'treemap', 7);
- }
- }
-
public function configureUserMenu(MenuUser $menu)
{
$menu->addPlatformItem('UI Notifications', $this->urlForAction('notifications'), $order = 10);
}
-
- private function addSubMenu(MenuReporting $menu, $subMenu, $action, $order)
- {
- $menu->addItem('UI Framework', $subMenu, $this->urlForAction($action), $order);
- }
}
diff --git a/plugins/ExampleUI/Reports/Base.php b/plugins/ExampleUI/Reports/Base.php
new file mode 100644
index 0000000000..88fa676754
--- /dev/null
+++ b/plugins/ExampleUI/Reports/Base.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleUI\Reports;
+
+use Piwik\Plugin\Report;
+
+abstract class Base extends Report
+{
+ protected function init()
+ {
+ $this->categoryId = 'ExampleUI_UiFramework';
+ }
+}
diff --git a/plugins/ExampleUI/Reports/GetPlanetRatios.php b/plugins/ExampleUI/Reports/GetPlanetRatios.php
new file mode 100644
index 0000000000..244e8f79c8
--- /dev/null
+++ b/plugins/ExampleUI/Reports/GetPlanetRatios.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\ExampleUI\Reports;
+
+use Piwik\Plugin\Report;
+use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
+
+/**
+ * This class defines a new report.
+ *
+ * See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
+ */
+class GetPlanetRatios extends Base
+{
+ protected function init()
+ {
+ parent::init();
+
+ $this->name = 'Pie graph';
+ $this->subcategoryId = $this->name;
+ $this->order = 112;
+ }
+
+ public function getDefaultTypeViewDataTable()
+ {
+ return PIE::ID;
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ // in this case it will render PIE as configured as default
+ $factory->createWidget()
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('Simple tag cloud')
+ ->setSubcategoryId('Tag clouds')
+ ->forceViewDataTable(Cloud::ID)
+ ->setOrder(5)
+ );
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ $view->config->addTranslation('value', 'times the diameter of Earth');
+
+ if ($view->isViewDataTableId(PIE::ID)) {
+
+ $view->config->columns_to_display = array('value');
+ $view->config->selectable_columns = array('value');
+ $view->config->show_footer_icons = false;
+ $view->config->max_graph_elements = 10;
+
+ } else if ($view->isViewDataTableId(Cloud::ID)) {
+
+ $view->config->columns_to_display = array('label', 'value');
+ $view->config->show_footer = false;
+
+ }
+ }
+
+}
diff --git a/plugins/ExampleUI/Reports/GetPlanetRatiosWithLogos.php b/plugins/ExampleUI/Reports/GetPlanetRatiosWithLogos.php
new file mode 100644
index 0000000000..d4d205e6c9
--- /dev/null
+++ b/plugins/ExampleUI/Reports/GetPlanetRatiosWithLogos.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\ExampleUI\Reports;
+
+use Piwik\Piwik;
+use Piwik\Plugin\Report;
+use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud;
+
+/**
+ * This class defines a new report.
+ *
+ * See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
+ */
+class GetPlanetRatiosWithLogos extends Base
+{
+ protected function init()
+ {
+ parent::init();
+
+ $this->name = Piwik::translate('Advanced tag cloud: with logos and links');
+ $this->subcategoryId = 'Tag clouds';
+ $this->order = 113;
+ }
+
+ public function getDefaultTypeViewDataTable()
+ {
+ return Cloud::ID;
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ $view->config->display_logo_instead_of_label = true;
+ $view->config->columns_to_display = array('label', 'value');
+ $view->config->addTranslation('value', 'times the diameter of Earth');
+ }
+
+}
diff --git a/plugins/ExampleUI/Reports/GetTemperatures.php b/plugins/ExampleUI/Reports/GetTemperatures.php
new file mode 100644
index 0000000000..0449e8b3e2
--- /dev/null
+++ b/plugins/ExampleUI/Reports/GetTemperatures.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\ExampleUI\Reports;
+
+use Piwik\Piwik;
+use Piwik\Plugin\Report;
+use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Bar;
+use Piwik\Plugin\Manager as PluginManager;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\View;
+use Piwik\Widget\WidgetsList;
+
+/**
+ * This class defines a new report.
+ *
+ * See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
+ */
+class GetTemperatures extends Base
+{
+ protected function init()
+ {
+ parent::init();
+
+ $this->name = Piwik::translate('ExampleUI_GetTemperaturesDataTable');
+ $this->subcategoryId = 'ExampleUI_GetTemperaturesDataTable';
+ $this->order = 110;
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ // this will render the default view, in this case an Html Table
+ $widgetsList->addWidgetConfig($factory->createWidget());
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->forceViewDataTable(Bar::ID)
+ ->setSubcategoryId('Bar graph')
+ );
+
+ if (PluginManager::getInstance()->isPluginActivated('TreemapVisualization')) {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('Treemap example')
+ ->setSubcategoryId('Treemap')
+ ->forceViewDataTable('infoviz-treemap')
+ );
+
+ }
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ if ($view->isViewDataTableId(BAR::ID)) {
+
+ $view->config->y_axis_unit = '°C';
+ $view->config->show_footer = false;
+ $view->config->translations['value'] = "Temperature";
+ $view->config->selectable_columns = array("value");
+ $view->config->max_graph_elements = 24;
+
+ } elseif ($view->isViewDataTableId('infoviz-treemap')) {
+
+ $view->config->translations['value'] = "Temperature";
+ $view->config->columns_to_display = array("label", "value");
+ $view->config->selectable_columns = array("value");
+ $view->config->show_evolution_values = 0;
+
+ } else {
+ // for default view datatable, eg HtmlTable
+
+ $view->config->translations['value'] = 'Temperature in °C';
+ $view->config->translations['label'] = 'Hour of day';
+ $view->requestConfig->filter_sort_column = 'label';
+ $view->requestConfig->filter_sort_order = 'asc';
+ $view->requestConfig->filter_limit = 24;
+ $view->config->columns_to_display = array('label', 'value');
+ $view->config->y_axis_unit = '°C'; // useful if the user requests the bar graph
+ $view->config->show_exclude_low_population = false;
+ $view->config->show_table_all_columns = false;
+ $view->config->disable_row_evolution = true;
+ $view->config->max_graph_elements = 24;
+ $view->config->metrics_documentation = array('value' => 'Documentation for temperature metric');
+ }
+ }
+
+}
diff --git a/plugins/ExampleUI/Reports/GetTemperaturesEvolution.php b/plugins/ExampleUI/Reports/GetTemperaturesEvolution.php
new file mode 100644
index 0000000000..ff8ea66e10
--- /dev/null
+++ b/plugins/ExampleUI/Reports/GetTemperaturesEvolution.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\ExampleUI\Reports;
+
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Plugin\Report;
+use Piwik\Plugin\ViewDataTable;
+
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Bar;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\View;
+use Piwik\Widget\WidgetsList;
+
+/**
+ * This class defines a new report.
+ *
+ * See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
+ */
+class GetTemperaturesEvolution extends Base
+{
+ protected function init()
+ {
+ parent::init();
+
+ $this->name = Piwik::translate('ExampleUI_GetTemperaturesEvolution');
+ $this->order = 111;
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setSubcategoryId('Sparklines')
+ ->forceViewDataTable(Sparklines::ID)
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('ExampleUI_TemperaturesEvolution')
+ ->setSubcategoryId('Evolution Graph')
+ ->forceViewDataTable(Evolution::ID)
+ ->setParameters(array('columns' => array('server1', 'server2')))
+ );
+
+ }
+
+ /**
+ * Here you can configure how your report should be displayed. For instance whether your report supports a search
+ * etc. You can also change the default request config. For instance change how many rows are displayed by default.
+ *
+ * @param ViewDataTable $view
+ */
+ public function configureView(ViewDataTable $view)
+ {
+ if ($view->isViewDataTableId(Sparklines::ID)) {
+
+ /** @var Sparklines $view */
+ $view->config->addSparklineMetric(array('server1'));
+ $view->config->addSparklineMetric(array('server2'));
+ $view->config->addTranslations(array('server1' => 'Evolution of temperature for server piwik.org'));
+ $view->config->addTranslations(array('server2' => 'Evolution of temperature for server dev.piwik.org'));
+
+ } elseif ($view->isViewDataTableId(Evolution::ID)) {
+
+ /** @var Evolution $view */
+ $selectableColumns = array('server1', 'server2');
+
+ $columns = Common::getRequestVar('columns', false);
+ if (!empty($columns)) {
+ $columns = Piwik::getArrayFromApiParameter($columns);
+ }
+
+ $columns = array_merge($columns ? $columns : array(), $selectableColumns);
+ $view->config->columns_to_display = $columns;
+
+ $view->config->addTranslations(array_combine($columns, $columns));
+ $view->config->selectable_columns = $selectableColumns;
+ $view->requestConfig->filter_sort_column = 'label';
+ $view->requestConfig->filter_sort_order = 'asc';
+ $view->config->documentation = 'My documentation';
+ $view->config->show_goals = false;
+ }
+ }
+
+}
diff --git a/plugins/ExampleUI/lang/en.json b/plugins/ExampleUI/lang/en.json
new file mode 100644
index 0000000000..e0c05c5411
--- /dev/null
+++ b/plugins/ExampleUI/lang/en.json
@@ -0,0 +1,8 @@
+{
+ "ExampleUI": {
+ "UiFramework": "UI Framework",
+ "GetTemperaturesDataTable": "Data tables",
+ "GetTemperaturesEvolution": "Temperatures evolution over time",
+ "TemperaturesEvolution": "Evolution of server temperatures over the last few days"
+ }
+} \ No newline at end of file
diff --git a/plugins/ExampleUI/plugin.json b/plugins/ExampleUI/plugin.json
index ec2fcfe025..8a39e0a2a2 100644
--- a/plugins/ExampleUI/plugin.json
+++ b/plugins/ExampleUI/plugin.json
@@ -2,14 +2,23 @@
"name": "ExampleUI",
"description": "Piwik Platform showcase: how to display data tables, graphs, and the UI framework.",
"version": "1.0.1",
- "keywords": ["example", "framework", "platform", "ui", "visualization"],
- "homepage": "http://piwik.org",
+ "keywords": [
+ "example",
+ "framework",
+ "platform",
+ "ui",
+ "visualization"
+ ],
+ "homepage": "http:\/\/piwik.org",
"license": "GPL v3+",
"authors": [
{
"name": "Piwik",
"email": "hello@piwik.org",
- "homepage": "http://piwik.org"
+ "homepage": "http:\/\/piwik.org"
}
- ]
+ ],
+ "require": {
+ "piwik": ">=2.13.1"
+ }
} \ No newline at end of file
diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php
index 80a898fe34..351e700782 100644
--- a/plugins/Goals/API.php
+++ b/plugins/Goals/API.php
@@ -22,6 +22,7 @@ use Piwik\Plugin\Report;
use Piwik\Plugins\API\DataTable\MergeDataTables;
use Piwik\Plugins\CoreHome\Columns\Metrics\ConversionRate;
use Piwik\Plugins\Goals\Columns\Metrics\AverageOrderRevenue;
+use Piwik\Plugin\Reports;
use Piwik\Segment\SegmentExpression;
use Piwik\Site;
use Piwik\Tracker\Cache;
@@ -414,7 +415,7 @@ class API extends \Piwik\Plugin\API
$requestedColumns = array_unique(array_merge($requestedColumns, $metricsToAdd));
}
- $report = Report::factory('Goals', 'getMetrics');
+ $report = Reports::factory('Goals', 'getMetrics');
$columnsToGet = $report->getMetricsRequiredForReport($allMetrics, $requestedColumns);
$inDbMetricNames = array_map(function ($name) use ($idGoal) {
diff --git a/plugins/Goals/Categories/AddANewGoalSubcategory.php b/plugins/Goals/Categories/AddANewGoalSubcategory.php
new file mode 100644
index 0000000000..9b613f2e55
--- /dev/null
+++ b/plugins/Goals/Categories/AddANewGoalSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Categories;
+
+use Piwik\Category\Subcategory;
+
+class AddANewGoalSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Goals';
+ protected $id = 'Goals_AddNewGoal';
+ protected $order = 9999;
+
+}
diff --git a/plugins/Goals/Categories/GoalsCategory.php b/plugins/Goals/Categories/GoalsCategory.php
new file mode 100644
index 0000000000..7ba4b4df58
--- /dev/null
+++ b/plugins/Goals/Categories/GoalsCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Categories;
+
+use Piwik\Category\Category;
+
+class GoalsCategory extends Category
+{
+ protected $id = 'Goals_Goals';
+ protected $order = 25;
+}
diff --git a/plugins/Goals/Categories/GoalsOverviewSubcategory.php b/plugins/Goals/Categories/GoalsOverviewSubcategory.php
new file mode 100644
index 0000000000..95f2d815c9
--- /dev/null
+++ b/plugins/Goals/Categories/GoalsOverviewSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Categories;
+
+use Piwik\Category\Subcategory;
+
+class GoalsOverviewSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Goals';
+ protected $id = 'General_Overview';
+ protected $order = 2;
+
+}
diff --git a/plugins/Goals/Categories/ManageGoalsSubcategory.php b/plugins/Goals/Categories/ManageGoalsSubcategory.php
new file mode 100644
index 0000000000..ef71697981
--- /dev/null
+++ b/plugins/Goals/Categories/ManageGoalsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Categories;
+
+use Piwik\Category\Subcategory;
+
+class ManageGoalsSubcategory extends Subcategory
+{
+ protected $categoryId = 'Goals_Goals';
+ protected $id = 'Goals_ManageGoals';
+ protected $order = 9999;
+
+}
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index 15f7b40aab..966005b690 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -8,16 +8,16 @@
*/
namespace Piwik\Plugins\Goals;
-use Exception;
use Piwik\API\Request;
use Piwik\Common;
use Piwik\DataTable;
+use Piwik\DataTable\Renderer\Json;
use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal;
+use Piwik\FrontController;
use Piwik\Piwik;
use Piwik\Plugins\Referrers\API as APIReferrers;
use Piwik\Translation\Translator;
use Piwik\View;
-use Piwik\View\ReportsByDimension;
/**
*
@@ -48,11 +48,6 @@ class Controller extends \Piwik\Plugin\Controller
*/
private $translator;
- /**
- * @var TranslationHelper
- */
- private $translationHelper;
-
private function formatConversionRate($conversionRate, $columnName = 'conversion_rate')
{
if ($conversionRate instanceof DataTable) {
@@ -70,89 +65,16 @@ class Controller extends \Piwik\Plugin\Controller
return $conversionRate;
}
- public function __construct(Translator $translator, TranslationHelper $translationHelper)
+ public function __construct(Translator $translator)
{
parent::__construct();
$this->translator = $translator;
- $this->translationHelper = $translationHelper;
$this->idSite = Common::getRequestVar('idSite', null, 'int');
$this->goals = API::getInstance()->getGoals($this->idSite);
}
- public function widgetGoalReport()
- {
- $view = $this->getGoalReportView($idGoal = Common::getRequestVar('idGoal', null, 'string'));
- $view->displayFullReport = false;
- return $view->render();
- }
-
- public function goalReport()
- {
- $view = $this->getGoalReportView($idGoal = Common::getRequestVar('idGoal', null, 'string'));
- $view->displayFullReport = true;
- return $view->render();
- }
-
- protected function getGoalReportView($idGoal = false)
- {
- $view = new View('@Goals/getGoalReportView');
- if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
- $goalDefinition['name'] = $this->translator->translate('Goals_Ecommerce');
- $goalDefinition['allow_multiple'] = true;
- $ecommerce = $view->ecommerce = true;
- } else {
- if (!isset($this->goals[$idGoal])) {
- Piwik::redirectToModule('Goals', 'index', array('idGoal' => null));
- }
- $goalDefinition = $this->goals[$idGoal];
- }
- $this->setGeneralVariablesView($view);
- $goal = $this->getMetricsForGoal($idGoal);
- foreach ($goal as $name => $value) {
- $view->$name = $value;
- }
- if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
- $goal = $this->getMetricsForGoal(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART);
- foreach ($goal as $name => $value) {
- $name = 'cart_' . $name;
- $view->$name = $value;
- }
- }
- $view->showHeadline = false;
- $view->idGoal = $idGoal;
- $view->goalName = $goalDefinition['name'];
- $view->goalAllowMultipleConversionsPerVisit = $goalDefinition['allow_multiple'];
- $view->graphEvolution = $this->getEvolutionGraph(array(), $idGoal, array('nb_conversions'));
- $view->nameGraphEvolution = 'Goals.getEvolutionGraph' . $idGoal;
- $view->topDimensions = $this->getTopDimensions($idGoal);
-
- $goalMetrics = Request::processRequest('Goals.get', array('idGoal' => $idGoal));
-
- // conversion rate for new and returning visitors
- $view->conversion_rate_returning = $this->formatConversionRate($goalMetrics, 'conversion_rate_returning_visit');
- $view->conversion_rate_new = $this->formatConversionRate($goalMetrics, 'conversion_rate_new_visit');
-
- $view->goalReportsByDimension = $this->getGoalReportsByDimensionTable(
- $view->nb_conversions, isset($ecommerce), !empty($view->cart_nb_conversions));
- return $view;
- }
-
- public function index()
- {
- $view = $this->getOverviewView();
-
- // unsanitize goal names and other text data (not done in API so as not to break
- // any other code/cause security issues)
- $goals = $this->goals;
- $view->goalsJSON = json_encode($goals);
-
- $view->ecommerceEnabled = $this->site->isEcommerceEnabled();
- $view->displayFullReport = true;
- return $view->render();
- }
-
public function manage()
{
Piwik::checkUserHasAdminAccess($this->idSite);
@@ -164,48 +86,20 @@ class Controller extends \Piwik\Plugin\Controller
return $view->render();
}
- public function widgetGoalsOverview()
+ public function goalConversionsOverview()
{
- $view = $this->getOverviewView();
- $view->displayFullReport = false;
- return $view->render();
- }
+ $view = new View('@Goals/conversionOverview');
+ $idGoal = Common::getRequestVar('idGoal', null, 'string');
- protected function getOverviewView()
- {
- $view = new View('@Goals/getOverviewView');
- $this->setGeneralVariablesView($view);
-
- $view->graphEvolution = $this->getEvolutionGraph(array(), false, array('nb_conversions'));
- $view->nameGraphEvolution = 'GoalsgetEvolutionGraph';
-
- // sparkline for the historical data of the above values
- $view->urlSparklineConversions = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_conversions'), 'idGoal' => ''));
- $view->urlSparklineConversionRate = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('conversion_rate'), 'idGoal' => ''));
- $view->urlSparklineRevenue = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('revenue'), 'idGoal' => ''));
-
- // Pass empty idGoal will return Goal overview
- $request = new Request("method=Goals.get&format=original&idGoal=");
- $datatable = $request->process();
- $dataRow = $datatable->getFirstRow();
+ $view->topDimensions = $this->getTopDimensions($idGoal);
- $view->nb_conversions = $dataRow->getColumn('nb_conversions');
- $view->nb_visits_converted = $dataRow->getColumn('nb_visits_converted');
- $view->conversion_rate = $this->formatConversionRate($dataRow->getColumn('conversion_rate'));
- $view->revenue = $dataRow->getColumn('revenue');
+ $goalMetrics = Request::processRequest('Goals.get', array('idGoal' => $idGoal));
- $goalMetrics = array();
- foreach ($this->goals as $idGoal => $goal) {
- $goalMetrics[$idGoal] = $this->getMetricsForGoal($idGoal);
- $goalMetrics[$idGoal]['name'] = $goal['name'];
- $goalMetrics[$idGoal]['goalAllowMultipleConversionsPerVisit'] = $goal['allow_multiple'];
- }
+ // conversion rate for new and returning visitors
+ $view->conversion_rate_returning = $this->formatConversionRate($goalMetrics, 'conversion_rate_returning_visit');
+ $view->conversion_rate_new = $this->formatConversionRate($goalMetrics, 'conversion_rate_new_visit');
- $view->goalMetrics = $goalMetrics;
- $view->goals = $this->goals;
- $view->goalReportsByDimension = $this->getGoalReportsByDimensionTable(
- $view->nb_conversions, $ecommerce = false, !empty($view->cart_nb_conversions));
- return $view;
+ return $view->render();
}
public function getLastNbConversionsGraph()
@@ -244,6 +138,26 @@ class Controller extends \Piwik\Plugin\Controller
return $view->render();
}
+ public function hasConversions()
+ {
+ $this->checkSitePermission();
+
+ $idGoal = Common::getRequestVar('idGoal', '', 'string');
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $period = Common::getRequestVar('period', null, 'string');
+ $date = Common::getRequestVar('date', null, 'string');
+
+ Piwik::checkUserHasViewAccess($idSite);
+
+ $conversions = new Conversions();
+
+ Json::sendHeaderJSON();
+
+ $numConversions = $conversions->getConversionForGoal($idGoal, $idSite, $period, $date);
+
+ return json_encode($numConversions > 0);
+ }
+
public function getEvolutionGraph(array $columns = array(), $idGoal = false, array $defaultColumns = array())
{
if (empty($columns)) {
@@ -334,11 +248,11 @@ class Controller extends \Piwik\Plugin\Controller
$topDimensions = array();
foreach ($topDimensionsToLoad as $dimensionName => $apiMethod) {
$request = new Request("method=$apiMethod
- &format=original
- &filter_update_columns_when_show_all_goals=1
- &idGoal=" . AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE . "
- &filter_sort_order=desc
- &filter_sort_column=$columnNbConversions" .
+ &format=original
+ &filter_update_columns_when_show_all_goals=1
+ &idGoal=" . AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE . "
+ &filter_sort_order=desc
+ &filter_sort_column=$columnNbConversions" .
// select a couple more in case some are not valid (ie. conversions==0 or they are "Keyword not defined")
"&filter_limit=" . (self::COUNT_TOP_ROWS_TO_DISPLAY + 2));
$datatable = $request->process();
@@ -402,72 +316,11 @@ class Controller extends \Piwik\Plugin\Controller
'avg_order_revenue' => $aov ? $aov : 0,
'urlSparklinePurchasedProducts' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('items'), 'idGoal' => $idGoal)),
'urlSparklineAverageOrderValue' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('avg_order_revenue'), 'idGoal' => $idGoal)),
- ));
+ ));
}
return $return;
}
- /**
- * Utility function that returns HTML that displays Goal information for reports. This
- * is the HTML that is at the bottom of every goals page.
- *
- * @param int $conversions The number of conversions for this goal (or all goals
- * in case of the overview).
- * @param bool $ecommerce Whether to show ecommerce reports or not.
- * @param bool $cartNbConversions Whether there are cart conversions or not for this
- * goal.
- * @return string
- */
- private function getGoalReportsByDimensionTable($conversions, $ecommerce = false, $cartNbConversions = false)
- {
- $preloadAbandonedCart = $cartNbConversions !== false && $conversions == 0;
-
- $goalReportsByDimension = new ReportsByDimension('Goals');
-
- // add ecommerce reports
- $ecommerceCustomParams = array();
- if ($ecommerce) {
- if ($preloadAbandonedCart) {
- $ecommerceCustomParams['abandonedCarts'] = '1';
- } else {
- $ecommerceCustomParams['abandonedCarts'] = '0';
- }
- }
-
- if ($conversions > 0 || $ecommerce) {
- // for non-Goals reports, we show the goals table
- $customParams = $ecommerceCustomParams + array('documentationForGoalsPage' => '1');
-
- if (Common::getRequestVar('idGoal', '') === '') // if no idGoal, use 0 for overview
- {
- $customParams['idGoal'] = '0'; // NOTE: Must be string! Otherwise Piwik_View_HtmlTable_Goals fails.
- }
-
- $allReports = Goals::getReportsWithGoalMetrics();
- foreach ($allReports as $category => $reports) {
- if ($ecommerce) {
- $categoryText = $this->translationHelper->translateEcommerceMetricCategory($category);
- } else {
- $categoryText = $this->translationHelper->translateGoalMetricCategory($category);
- }
-
- foreach ($reports as $report) {
- if (empty($report['viewDataTable'])
- && empty($report['abandonedCarts'])
- ) {
- $report['viewDataTable'] = 'tableGoals';
- }
- $customParams['viewDataTable'] = $report['viewDataTable'];
-
- $goalReportsByDimension->addReport(
- $categoryText, $report['name'], $report['module'] . '.' . $report['action'], $customParams);
- }
- }
- }
-
- return $goalReportsByDimension->render();
- }
-
private function setEditGoalsViewVariables($view)
{
$goals = $this->goals;
@@ -496,4 +349,32 @@ class Controller extends \Piwik\Plugin\Controller
{
$view->userCanEditGoals = Piwik::isUserHasAdminAccess($this->idSite);
}
+
+ /**
+ * @deprecated used to be a widgetized URL. There to not break widget URLs
+ */
+ public function widgetGoalReport()
+ {
+ $idGoal = Common::getRequestVar('idGoal', '', 'string');
+
+ if ($idGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+ $_GET['containerId'] = 'EcommerceOverview';
+ } elseif (!empty($idGoal)) {
+ $_GET['containerId'] = 'Goal_' . (int) $idGoal;
+ } else {
+ return '';
+ }
+
+ return FrontController::getInstance()->fetchDispatch('CoreHome', 'renderWidgetContainer');
+ }
+
+ /**
+ * @deprecated used to be a widgetized URL. There to not break widget URLs
+ */
+ public function widgetGoalsOverview()
+ {
+ $_GET['containerId'] = 'GoalsOverview';
+
+ return FrontController::getInstance()->fetchDispatch('CoreHome', 'renderWidgetContainer');
+ }
}
diff --git a/plugins/Goals/Conversions.php b/plugins/Goals/Conversions.php
new file mode 100644
index 0000000000..fbbbef0078
--- /dev/null
+++ b/plugins/Goals/Conversions.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals;
+
+use Piwik\API\Request;
+use Piwik\Cache;
+use Piwik\Common;
+use Piwik\Db;
+
+class Conversions
+{
+
+ public function getConversionForGoal($idGoal, $idSite, $period, $date)
+ {
+ if (!$period || !$date || !$idSite) {
+ return false;
+ }
+
+ $datatable = Request::processRequest('Goals.get', array(
+ 'idGoal' => $idGoal,
+ 'period' => $period,
+ 'date' => $date,
+ 'idSite' => $idSite,
+ 'serialize' => 0,
+ 'segment' => false
+ ));
+
+ // we ignore the segment even if there is one set. We still want to show conversion overview if there are conversions
+ // in general but not for this segment
+
+ $dataRow = $datatable->getFirstRow();
+
+ if (!$dataRow) {
+ return false;
+ }
+
+ return $dataRow->getColumn('nb_conversions');
+ }
+}
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
index d26e2cf77e..609d98c419 100644
--- a/plugins/Goals/Goals.php
+++ b/plugins/Goals/Goals.php
@@ -13,8 +13,9 @@ use Piwik\Common;
use Piwik\Db;
use Piwik\Piwik;
use Piwik\Plugin\Report;
+use Piwik\Plugin\Reports;
use Piwik\Tracker\GoalManager;
-use Piwik\Translate;
+use Piwik\Category\Subcategory;
/**
*
@@ -29,36 +30,17 @@ class Goals extends \Piwik\Plugin
foreach ($dimensions as $dimension) {
$group = $dimension['category'];
// move "Custom Variables" report to the "Goals/Sales by User attribute" category
- if ($dimension['module'] === 'CustomVariables') {
+ if ($dimension['module'] === 'CustomVariables'
+ || $dimension['action'] == 'getVisitInformationPerServerTime') {
$group = 'VisitsSummary_VisitsSummary';
}
unset($dimension['category']);
$dimensionsByGroup[$group][] = $dimension;
}
- uksort($dimensionsByGroup, array('self', 'sortGoalDimensionsByModule'));
return $dimensionsByGroup;
}
- public static function sortGoalDimensionsByModule($a, $b)
- {
- static $order = null;
-
- if (is_null($order)) {
- $order = array(
- 'Referrers_Referrers',
- 'General_Visit',
- 'General_Visitors',
- 'VisitsSummary_VisitsSummary',
- 'VisitTime_ColumnServerTime',
- );
- }
-
- $orderA = array_search($a, $order);
- $orderB = array_search($b, $order);
- return $orderA > $orderB;
- }
-
public static function getGoalColumns($idGoal)
{
$columns = array(
@@ -98,11 +80,34 @@ class Goals extends \Piwik\Plugin
'SitesManager.deleteSite.end' => 'deleteSiteGoals',
'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
- 'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations'
+ 'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
+ 'Category.addSubcategories' => 'addSubcategories'
);
return $hooks;
}
+ public function addSubcategories(&$subcategories)
+ {
+ $idSite = Common::getRequestVar('idSite', 0, 'int');
+
+ if (!$idSite) {
+ return;
+ }
+
+ $goals = API::getInstance()->getGoals($idSite);
+
+ $order = 900;
+ foreach ($goals as $goal) {
+ $category = new Subcategory();
+ $category->setName($goal['name']);
+ $category->setCategoryId('Goals_Goals');
+ $category->setId($goal['idgoal']);
+ $category->setOrder($order++);
+ $subcategories[] = $category;
+ }
+ }
+
+
public function addMetricTranslations(&$translations)
{
$metrics = array(
@@ -176,10 +181,12 @@ class Goals extends \Piwik\Plugin
{
$reportsWithGoals = array();
- foreach (Report::getAllReports() as $report) {
+ $reports = new Reports();
+
+ foreach ($reports->getAllReports() as $report) {
if ($report->hasGoalMetrics()) {
$reportsWithGoals[] = array(
- 'category' => $report->getCategoryKey(),
+ 'category' => $report->getCategoryId(),
'name' => $report->getName(),
'module' => $report->getModule(),
'action' => $report->getAction(),
@@ -271,5 +278,6 @@ class Goals extends \Piwik\Plugin
$translationKeys[] = 'Goals_DeleteGoalConfirm';
$translationKeys[] = 'Goals_Ecommerce';
$translationKeys[] = 'Goals_Optional';
+ $translationKeys[] = 'Goals_ChooseGoal';
}
}
diff --git a/plugins/Goals/Menu.php b/plugins/Goals/Menu.php
index 85db036797..503c7e0430 100644
--- a/plugins/Goals/Menu.php
+++ b/plugins/Goals/Menu.php
@@ -10,7 +10,6 @@ namespace Piwik\Plugins\Goals;
use Piwik\Common;
use Piwik\Menu\Group;
-use Piwik\Menu\MenuReporting;
use Piwik\Menu\MenuUser;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\UserPreferences;
@@ -18,48 +17,6 @@ use Piwik\Translate;
class Menu extends \Piwik\Plugin\Menu
{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $idSite = $this->getIdSite();
- $goals = API::getInstance()->getGoals($idSite);
- $mainGoalMenu = 'Goals_Goals';
-
- if (count($goals) == 0) {
- $linkToAddNewGoal = $this->urlForAction('addNewGoal', array(
- 'idGoal' => null,
- ));
- $menu->addItem($mainGoalMenu, '', $linkToAddNewGoal, 25);
- $menu->addItem($mainGoalMenu, 'Goals_AddNewGoal', $linkToAddNewGoal, 1);
- return;
- }
-
- $order = 1;
-
- $url = $this->urlForAction('index', array('idGoal' => null));
-
- $menu->addItem($mainGoalMenu, '', $url, 25);
- $menu->addItem($mainGoalMenu, 'General_Overview', $url, ++$order);
-
- $group = new Group();
- foreach ($goals as $goal) {
- $subMenuName = str_replace('%', '%%', Translate::clean($goal['name']));
- $params = $this->urlForAction('goalReport', array('idGoal' => $goal['idgoal']));
- $tooltip = sprintf('%s (id = %d)', $subMenuName, $goal['idgoal']);
-
- if (count($goals) > 3) {
- $group->add($subMenuName, $params, $tooltip);
- } else {
- $menu->addItem($mainGoalMenu, $subMenuName, $params, ++$order, $tooltip);
- }
- }
-
- if (count($goals) > 3) {
- $menu->addGroup($mainGoalMenu, 'Goals_ChooseGoal', $group, ++$order, $tooltip = false);
- }
-
- $menu->addItem($mainGoalMenu, 'Goals_ManageGoals', $this->urlForAction('editGoals'), ++$order);
- }
-
public function configureUserMenu(MenuUser $menu)
{
$userPreferences = new UserPreferences();
diff --git a/plugins/Goals/Pages.php b/plugins/Goals/Pages.php
new file mode 100644
index 0000000000..9ab7a96d66
--- /dev/null
+++ b/plugins/Goals/Pages.php
@@ -0,0 +1,339 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals;
+
+
+use Piwik\API\Request;
+use Piwik\Cache;
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Plugin\Report;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Plugin\Reports;
+use Piwik\Widget\WidgetContainerConfig;
+use Piwik\Widget\WidgetConfig;
+use Piwik\Report\ReportWidgetFactory;
+
+class Pages
+{
+ private $orderId = 0;
+ private $allReports = array();
+ private $factory = array();
+ private $conversions;
+
+ public function __construct(ReportWidgetFactory $reportFactory, $reportsWithGoalMetrics)
+ {
+ $this->factory = $reportFactory;
+ $this->allReports = $reportsWithGoalMetrics;
+ $this->conversions = new Conversions();
+ }
+
+ /**
+ * @param array $goals
+ * @return WidgetConfig[]
+ */
+ public function createGoalsOverviewPage($goals)
+ {
+ $subcategory = 'General_Overview';
+
+ $widgets = array();
+
+ $config = $this->factory->createWidget();
+ $config->forceViewDataTable(Evolution::ID);
+ $config->setSubcategoryId($subcategory);
+ $config->setAction('getEvolutionGraph');
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+
+ $config = $this->factory->createWidget();
+ $config->forceViewDataTable(Sparklines::ID);
+ $config->setSubcategoryId($subcategory);
+ $config->setName('');
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+
+ foreach ($goals as $goal) {
+ $name = Common::sanitizeInputValue($goal['name']);
+ $goalTranslated = Piwik::translate('Goals_GoalX', array($name));
+
+ $config = $this->factory->createWidget();
+ $config->setName($goalTranslated);
+ $config->setSubcategoryId($subcategory);
+ $config->forceViewDataTable(Sparklines::ID);
+ $config->setParameters(array('idGoal' => $goal['idgoal']));
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->addParameters(array('allow_multiple' => (int) $goal['allow_multiple'], 'only_summary' => '1'));
+ $widgets[] = $config;
+ }
+
+ $container = $this->createWidgetizableWidgetContainer('GoalsOverview', $subcategory, $widgets);
+
+ $config = $this->factory->createContainerWidget('Goals');
+ $config->setSubcategoryId($subcategory);
+ $config->setName('Goals_ConversionsOverviewBy');
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $this->buildGoalByDimensionView('', $config);
+ $config->setMiddlewareParameters(array(
+ 'module' => 'Goals',
+ 'action' => 'hasConversions'
+ ));
+
+ return array($container, $config);
+ }
+
+ /**
+ * @return WidgetConfig[]
+ */
+ public function createEcommerceOverviewPage()
+ {
+ $category = 'Goals_Ecommerce';
+ $subcategory = 'General_Overview';
+ $idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER;
+
+ $widgets = array();
+ $config = $this->factory->createWidget();
+ $config->forceViewDataTable(Evolution::ID);
+ $config->setCategoryId($category);
+ $config->setSubcategoryId($subcategory);
+ $config->setAction('getEvolutionGraph');
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->setParameters(array('idGoal' => $idGoal));
+ $widgets[] = $config;
+
+ $config = $this->factory->createWidget();
+ $config->setCategoryId($category);
+ $config->forceViewDataTable(Sparklines::ID);
+ $config->setSubcategoryId($subcategory);
+ $config->setName('');
+ $config->setModule('Ecommerce');
+ $config->setAction('getSparklines');
+ $config->setParameters(array('idGoal' => $idGoal));
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+
+ $config = $this->factory->createWidget();
+ $config->setModule('Ecommerce');
+ $config->setAction('getConversionsOverview');
+ $config->setSubcategoryId($idGoal);
+ $config->setName('Goals_ConversionsOverview');
+ $config->setParameters(array('idGoal' => $idGoal));
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->setMiddlewareParameters(array(
+ 'module' => 'Goals',
+ 'action' => 'hasConversions',
+ 'idGoal' => $idGoal
+ ));
+
+ $widgets[] = $config;
+
+ $container = $this->createWidgetizableWidgetContainer('EcommerceOverview', $subcategory, $widgets);
+ return array($container);
+ }
+
+ /**
+ * @return WidgetConfig[]
+ */
+ public function createEcommerceSalesPage()
+ {
+ $category = 'Goals_Ecommerce';
+ $subcategory = 'Ecommerce_Sales';
+
+ $config = $this->factory->createContainerWidget('GoalsOrder');
+ $config->setCategoryId($category);
+ $config->setSubcategoryId($subcategory);
+ $config->setName('');
+ $config->setParameters(array('idGoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER));
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $this->buildGoalByDimensionView(Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER, $config);
+
+ return array($config);
+ }
+
+ /**
+ * @param array $goal
+ * @return WidgetConfig[]
+ */
+ public function createGoalDetailPage($goal)
+ {
+ $widgets = array();
+
+ $idGoal = (int) $goal['idgoal'];
+ $name = Common::sanitizeInputValue($goal['name']);
+ $params = array('idGoal' => $idGoal);
+
+ $config = $this->factory->createWidget();
+ $config->setSubcategoryId($idGoal);
+ $config->forceViewDataTable(Evolution::ID);
+ $config->setAction('getEvolutionGraph');
+ $config->setParameters($params);
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+
+ $config = $this->factory->createWidget();
+ $config->setSubcategoryId($idGoal);
+ $config->setName('');
+ $config->forceViewDataTable(Sparklines::ID);
+ $config->setParameters($params);
+ $config->addParameters(array('allow_multiple' => (int) $goal['allow_multiple']));
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+
+ $config = $this->factory->createWidget();
+ $config->setAction('goalConversionsOverview');
+ $config->setSubcategoryId($idGoal);
+ $config->setName('Goals_ConversionsOverview');
+ $config->setParameters($params);
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->setMiddlewareParameters(array(
+ 'module' => 'Goals',
+ 'action' => 'hasConversions',
+ 'idGoal' => $idGoal
+ ));
+ $widgets[] = $config;
+
+ $container = $this->createWidgetizableWidgetContainer('Goal_' . $idGoal, $name, $widgets);
+
+ $configs = array($container);
+
+ $config = $this->factory->createContainerWidget('Goals' . $idGoal);
+ $config->setName(Piwik::translate('Goals_GoalConversionsBy', array($name)));
+ $config->setSubcategoryId($idGoal);
+ $config->setParameters(array());
+ $config->setOrder(++$this->orderId);
+ $config->setIsNotWidgetizable();
+ $config->setMiddlewareParameters(array(
+ 'module' => 'Goals',
+ 'action' => 'hasConversions',
+ 'idGoal' => $idGoal
+ ));
+ $this->buildGoalByDimensionView($idGoal, $config);
+
+ $configs[] = $config;
+
+ return $configs;
+ }
+
+ private function createWidgetizableWidgetContainer($containerId, $pageName, $widgets)
+ {
+ /** @var \Piwik\Widget\WidgetConfig[] $widgets */
+ $firstWidget = reset($widgets);
+ /** @var \Piwik\Report\ReportWidgetConfig $firstWidget */
+
+ if (!empty($pageName)) {
+ // make sure to not show two titles (one for this container and one for the first widget)
+ $firstWidget->setName('');
+ }
+
+ $config = $this->factory->createContainerWidget($containerId);
+ $config->setName($pageName);
+ $config->setCategoryId($firstWidget->getCategoryId());
+ $config->setSubcategoryId($firstWidget->getSubcategoryId());
+ $config->setIsWidgetizable();
+ $config->setOrder($this->orderId++);
+
+ foreach ($widgets as $widget) {
+ $config->addWidgetConfig($widget);
+ }
+
+ return $config;
+ }
+
+ private function buildGoalByDimensionView($idGoal, WidgetContainerConfig $container)
+ {
+ $container->setLayout('ByDimension');
+ $ecommerce = ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER);
+
+ // for non-Goals reports, we show the goals table
+ $customParams = array('documentationForGoalsPage' => '1');
+
+ if ($idGoal === '') {
+ // if no idGoal, use 0 for overview. Must be string! Otherwise Piwik_View_HtmlTable_Goals fails.
+ $customParams['idGoal'] = '0';
+ } else {
+ $customParams['idGoal'] = $idGoal;
+ }
+
+ $translationHelper = new TranslationHelper();
+
+ foreach ($this->allReports as $category => $reports) {
+ $order = ($this->getSortOrderOfCategory($category) * 100);
+
+ if ($ecommerce) {
+ $categoryText = $translationHelper->translateEcommerceMetricCategory($category);
+ } else {
+ $categoryText = $translationHelper->translateGoalMetricCategory($category);
+ }
+
+ foreach ($reports as $report) {
+ $order++;
+
+ if (empty($report['viewDataTable'])
+ && empty($report['abandonedCarts'])
+ ) {
+ $report['viewDataTable'] = 'tableGoals';
+ }
+
+ $widget = $this->createWidgetForReport($report['module'], $report['action']);
+ $widget->setParameters($customParams);
+ $widget->setCategoryId($categoryText);
+ $widget->setSubcategoryId($categoryText);
+ $widget->setOrder($order);
+ $widget->setIsNotWidgetizable();
+
+ if (!empty($report['viewDataTable'])) {
+ $widget->setDefaultViewDataTable($report['viewDataTable']);
+ }
+
+ $container->addWidgetConfig($widget);
+ }
+ }
+ }
+
+ private function getSortOrderOfCategory($category)
+ {
+ static $order = null;
+
+ if (is_null($order)) {
+ $order = array(
+ 'Referrers_Referrers',
+ 'General_Visit',
+ 'General_Visitors',
+ 'VisitsSummary_VisitsSummary',
+ );
+ }
+
+ $value = array_search($category, $order);
+
+ if (false === $value) {
+ $value = count($order) + 1;
+ }
+
+ return $value;
+ }
+
+ private function createWidgetForReport($module, $action)
+ {
+ $factory = new ReportWidgetFactory(Reports::factory($module, $action));
+ return $factory->createWidget();
+ }
+
+}
diff --git a/plugins/Goals/Reports/Base.php b/plugins/Goals/Reports/Base.php
index fd732035d3..3f9cb9c98a 100644
--- a/plugins/Goals/Reports/Base.php
+++ b/plugins/Goals/Reports/Base.php
@@ -18,7 +18,7 @@ abstract class Base extends \Piwik\Plugin\Report
protected function init()
{
- $this->category = 'Goals_Goals';
+ $this->categoryId = 'Goals_Goals';
}
protected function addReportMetadataForEachGoal(&$availableReports, $infos, $goalNameFormatter)
diff --git a/plugins/Goals/Reports/Get.php b/plugins/Goals/Reports/Get.php
index bccecda146..66f167fb24 100644
--- a/plugins/Goals/Reports/Get.php
+++ b/plugins/Goals/Reports/Get.php
@@ -8,7 +8,20 @@
*/
namespace Piwik\Plugins\Goals\Reports;
+use Piwik\Common;
+use Piwik\DataTable;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
+use Piwik\Plugin;
+use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Plugins\Goals\API;
+use Piwik\Plugins\Goals\Goals;
+use Piwik\Plugins\Goals\Pages;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Site;
+use Piwik\Widget\WidgetsList;
class Get extends Base
{
@@ -25,6 +38,104 @@ class Get extends Base
$this->parameters = null;
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $idSite = $this->getIdSite();
+ $goals = API::getInstance()->getGoals($idSite);
+ $reports = Goals::getReportsWithGoalMetrics();
+
+ $page = new Pages($factory, $reports);
+
+ $widgetsList->addWidgetConfigs($page->createGoalsOverviewPage($goals));
+
+ if ($this->isEcommerceEnabled($idSite)) {
+ $widgetsList->addWidgetConfigs($page->createEcommerceOverviewPage());
+ $widgetsList->addWidgetConfigs($page->createEcommerceSalesPage());
+ }
+
+ foreach ($goals as $goal) {
+ $widgetsList->addWidgetConfigs($page->createGoalDetailPage($goal));
+ }
+ }
+
+ private function getIdSite()
+ {
+ return Common::getRequestVar('idSite', null, 'int');
+ }
+
+ private function isEcommerceEnabled($idSite)
+ {
+ if (!Plugin\Manager::getInstance()->isPluginActivated('Ecommerce')) {
+ return false;
+ }
+
+ $site = new Site($idSite);
+ return $site->isEcommerceEnabled();
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ if ($view->isViewDataTableId(Sparklines::ID)) {
+ /** @var Sparklines $view */
+ $idSite = $this->getIdSite();
+ $isEcommerceEnabled = $this->isEcommerceEnabled($idSite);
+
+ $idGoal = Common::getRequestVar('idGoal', 0, 'int');
+
+ $formatter = new Formatter();
+ $view->config->filters[] = function (DataTable $table) use ($formatter, $idSite) {
+ $firstRow = $table->getFirstRow();
+ if ($firstRow) {
+ $revenue = $firstRow->getColumn('revenue');
+ $firstRow->setColumn('revenue', $formatter->getPrettyMoney($revenue, $idSite));
+ }
+ };
+
+ $view->config->addTranslations(array(
+ 'nb_visits' => Piwik::translate('VisitsSummary_NbVisitsDescription'),
+ 'nb_conversions' => Piwik::translate('Goals_ConversionsDescription'),
+ 'nb_visits_converted' => Piwik::translate('General_NVisits'),
+ 'conversion_rate' => Piwik::translate('Goals_OverallConversionRate'),
+ 'revenue' => Piwik::translate('Goals_OverallRevenue'),
+ ));
+
+ $allowMultiple = Common::getRequestVar('allow_multiple', 0, 'int');
+
+ if ($allowMultiple) {
+ $view->config->addSparklineMetric(array('nb_conversions', 'nb_visits_converted'), $order = 10);
+ } else {
+ $view->config->addSparklineMetric(array('nb_conversions'), $order = 10);
+ }
+
+ $view->config->addSparklineMetric(array('conversion_rate'), $order = 20);
+
+ if (empty($idGoal)) {
+ // goals overview sparklines below evolution graph
+
+ if ($isEcommerceEnabled) {
+ // this would be ideally done in Ecommerce plugin but then it is hard to keep same order
+ $view->config->addSparklineMetric(array('revenue'), $order = 30);
+ }
+
+ } else {
+ $onlySummary = Common::getRequestVar('only_summary', 0, 'int');
+
+ if ($onlySummary) {
+ // in Goals Overview we list an overview for each goal....
+ $view->config->addTranslation('conversion_rate', Piwik::translate('Goals_ConversionRate'));
+
+ } elseif ($isEcommerceEnabled) {
+ // in Goals detail page...
+ $view->config->addSparklineMetric(array('revenue'), $order = 30);
+ }
+ }
+ } else if ($view->isViewDataTableId(Evolution::ID)) {
+ if (empty($view->config->columns_to_display)) {
+ $view->config->columns_to_display = array('nb_conversions');
+ }
+ }
+ }
+
public function configureReportMetadata(&$availableReports, $infos)
{
if (!$this->isEnabled()) {
diff --git a/plugins/Goals/Widgets.php b/plugins/Goals/Widgets.php
deleted file mode 100644
index 94d91bda5c..0000000000
--- a/plugins/Goals/Widgets.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Goals;
-
-use Piwik\Common;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'Goals_Goals';
-
- protected function init()
- {
- $this->addWidget('Goals_GoalsOverview', 'widgetGoalsOverview');
-
- $idSite = $this->getIdSite();
- $goals = API::getInstance()->getGoals($idSite);
-
- if (count($goals) > 0) {
- foreach ($goals as $goal) {
- $name = Common::sanitizeInputValue($goal['name']);
- $params = array('idGoal' => $goal['idgoal']);
-
- $this->addWidget($name, 'widgetGoalReport', $params);
- }
- }
- }
-
- private function getIdSite()
- {
- return Common::getRequestVar('idSite', null, 'int');
- }
-
-}
diff --git a/plugins/Goals/Widgets/AddNewGoal.php b/plugins/Goals/Widgets/AddNewGoal.php
new file mode 100644
index 0000000000..b692309b9d
--- /dev/null
+++ b/plugins/Goals/Widgets/AddNewGoal.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Widgets;
+
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Plugins\Goals\API;
+use Piwik\Widget\WidgetConfig;
+
+class AddNewGoal extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $goals = API::getInstance()->getGoals($idSite);
+
+ $config->setCategoryId('Goals_Goals');
+ $config->setSubcategoryId('Goals_AddNewGoal');
+ $config->setParameters(array('idGoal' => ''));
+ $config->setIsNotWidgetizable();
+
+ if (Piwik::isUserHasAdminAccess($idSite)) {
+ $config->setName('Goals_AddNewGoal');
+ } else {
+ $config->setName('Goals_CreateNewGOal');
+ }
+
+ if (count($goals) !== 0) {
+ $config->disable();
+ }
+ }
+}
diff --git a/plugins/Goals/Widgets/EditGoals.php b/plugins/Goals/Widgets/EditGoals.php
new file mode 100644
index 0000000000..d0bb52667c
--- /dev/null
+++ b/plugins/Goals/Widgets/EditGoals.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Widgets;
+
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Plugins\Goals\API;
+use Piwik\Widget\WidgetConfig;
+
+class EditGoals extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $idSite = Common::getRequestVar('idSite', null, 'int');
+ $goals = API::getInstance()->getGoals($idSite);
+
+ $config->setCategoryId('Goals_Goals');
+ $config->setSubcategoryId('Goals_ManageGoals');
+ $config->setIsNotWidgetizable();
+
+ if (Piwik::isUserHasAdminAccess($idSite)) {
+ $config->setName('Goals_ManageGoals');
+ } else {
+ $config->setName('Goals_CreateNewGOal');
+ }
+
+ if (count($goals) === 0) {
+ $config->disable();
+ }
+ }
+}
diff --git a/plugins/Goals/lang/en.json b/plugins/Goals/lang/en.json
index 0545d0640f..8820b333e7 100644
--- a/plugins/Goals/lang/en.json
+++ b/plugins/Goals/lang/en.json
@@ -36,6 +36,7 @@
"ConversionByTypeReportDocumentation": "This report provides detailed information about the goal performance (conversions, conversion rates and revenue per visit) for each of the categories available in the left panel. %s Please click on one of the categories to view the report. %s For more information, read the %sTracking Goals documentation%s",
"ConversionRate": "%s conversion rate",
"Conversions": "%s conversions",
+ "ConversionsDescription": "conversions",
"ConversionsOverview": "Conversions Overview",
"ConversionsOverviewBy": "Conversions overview by type of visit",
"DaysToConv": "Days to Conversion",
@@ -79,8 +80,8 @@
"NoGoalsNeedAccess": "Only an Administrator or a user with Super User access can manage Goals for a given website. Please ask your Piwik administrator to set up a Goal for your website. <br>Tracking Goals is a great way to help understand and maximize your website performance!",
"NeedAccess": "Only an Administrator or a user with Super User access can manage Goals for a given website.",
"Optional": "(optional)",
- "OverallConversionRate": "%s overall conversion rate (visits with a completed goal)",
- "OverallRevenue": "%s overall revenue",
+ "OverallConversionRate": "overall conversion rate (visits with a completed goal)",
+ "OverallRevenue": "overall revenue",
"PageTitle": "Page Title",
"Pattern": "Pattern",
"PluginDescription": "Create Goals and see detailed reports about your goal conversions: evolution over time, revenue per visit, conversions per referrer, per keyword, and more.",
diff --git a/plugins/Goals/templates/_titleAndEvolutionGraph.twig b/plugins/Goals/templates/_titleAndEvolutionGraph.twig
deleted file mode 100644
index 0a2fdc1e31..0000000000
--- a/plugins/Goals/templates/_titleAndEvolutionGraph.twig
+++ /dev/null
@@ -1,86 +0,0 @@
-<span data-graph-id="{{ nameGraphEvolution }}"></span>
-
-{% if displayFullReport or headline is defined %}
- <h2 piwik-enriched-headline
- {% if idGoal is defined and idGoal and goalName is defined and not ecommerce is defined %}
- edit-url="{{ linkTo({'module': 'Goals', 'action': 'manage', 'idGoal': idGoal})|e('html_attr') }}"
- feature-name="{{ 'Goals_Details'|translate|e('html_attr') }}"
- {% endif %}
- >{% if headline is defined %}{{ headline }}{% elseif goalName is defined %}{{ 'Goals_GoalX'|translate(goalName) }}{% else %}{{ 'General_EvolutionOverPeriod'|translate }}{% endif %}</h2>
-{% endif %}
-{{ graphEvolution|raw }}
-
-<div id='leftcolumn' style="clear:both;{% if not isWidget and ecommerce is defined %}width:33%;'{% endif %}">
- <div class="sparkline">{{ sparkline(urlSparklineConversions) }}
- {% if ecommerce is defined %}
- <strong>{{ nb_conversions }}</strong>
- {{ 'General_EcommerceOrders'|translate }}
- <img src='plugins/Morpheus/images/ecommerceOrder.gif'>
- {% else %}
- {{ 'Goals_Conversions'|translate("<strong>"~nb_conversions~"</strong>")|raw }}
- {% endif %}
- {% if goalAllowMultipleConversionsPerVisit is defined and goalAllowMultipleConversionsPerVisit %}
- ({{ 'General_NVisits'|translate("<strong>"~nb_visits_converted~"</strong>")|raw }})
- {% endif %}
- </div>
- {% if revenue != 0 or ecommerce is defined %}
- <div class="sparkline">
- {{ sparkline(urlSparklineRevenue) }}
- {% set revenue=revenue|money(idSite) %}
- {% if ecommerce is defined %}
- <strong>{{ revenue|raw }}</strong> {{ 'General_TotalRevenue'|translate }}
- {% else %}
- {{ 'Goals_OverallRevenue'|translate("<strong>"~revenue~"</strong>")|raw }}
- {% endif %}
- </div>
- {% endif %}
- {% if ecommerce is defined %}
- <div class="sparkline">{{ sparkline(urlSparklineAverageOrderValue) }}
- <strong>{{ avg_order_revenue|money(idSite)|raw }}</strong>
- {{ 'General_AverageOrderValue'|translate }}
- </div>
- {% endif %}
-
-</div>
-<div id='leftcolumn' {% if not isWidget and ecommerce is defined %}style='width:33%;'{% endif %}>
- <div class="sparkline">{{ sparkline(urlSparklineConversionRate) }}
- {% if ecommerce is defined %}
- {% set ecommerceOrdersText %}{{ 'General_EcommerceOrders'|translate }}{% endset %}
- {{ 'Goals_ConversionRate'|translate("<strong>"~conversion_rate~"</strong> "~ecommerceOrdersText)|raw }}
- {% else %}
- {{ 'Goals_OverallConversionRate'|translate("<strong>"~conversion_rate~"</strong>")|raw }}
- {% endif %}
- </div>
- {% if ecommerce is defined %}
- <div class="sparkline">{{ sparkline(urlSparklinePurchasedProducts) }}
- <strong>{{ items }}</strong> {{ 'General_PurchasedProducts'|translate }}</div>
- {% endif %}
-</div>
-{% if ecommerce is defined %}
- <div id='rightcolumn' {% if not isWidget %}style='width:30%;'{% endif %}>
- <div>
- <img src='plugins/Morpheus/images/ecommerceAbandonedCart.gif'> <em>{{ 'General_AbandonedCarts'|translate }}</em>
- </div>
-
- <div class="sparkline">
- {{ sparkline(cart_urlSparklineConversions) }}
- {% set ecommerceAbandonedCartsText %}{{ 'Goals_AbandonedCart'|translate }}{% endset %}
- <strong>{{ cart_nb_conversions }}</strong> {{ 'General_VisitsWith'|translate(ecommerceAbandonedCartsText) }}
- </div>
-
- <div class="sparkline">
- {{ sparkline(cart_urlSparklineRevenue) }}
- {% set revenue %}{{ cart_revenue|money(idSite)|raw }}{% endset %}
- {% set revenueText %}{{ 'General_ColumnRevenue'|translate }}{% endset %}
- <strong>{{ revenue }}</strong> {{ 'Goals_LeftInCart'|translate(revenueText) }}
- </div>
-
- <div class="sparkline">
- {{ sparkline(cart_urlSparklineConversionRate) }}
- <strong>{{ cart_conversion_rate }}</strong>
- {{ 'General_VisitsWith'|translate(ecommerceAbandonedCartsText) }}
- </div>
- </div>
-{% endif %}
-{% include "_sparklineFooter.twig" %}
-
diff --git a/plugins/Goals/templates/addNewGoal.twig b/plugins/Goals/templates/addNewGoal.twig
index a2b44b88e9..844892ecbc 100644
--- a/plugins/Goals/templates/addNewGoal.twig
+++ b/plugins/Goals/templates/addNewGoal.twig
@@ -1,5 +1,4 @@
{% if userCanEditGoals %}
- <h2 piwik-enriched-headline>{{ 'Goals_AddNewGoal'|translate }}</h2>
<p>{{ 'Goals_NewGoalIntro'|translate }}</p>
<p>{{ 'Goals_LearnMoreAboutGoalTrackingDocumentation'|translate("<a href='?module=Proxy&action=redirect&url=http://piwik.org/docs/tracking-goals-web-analytics/' target='_blank'>","</a>")|raw }}
{{ 'Goals_ManageGoalsOrCreateANewGoal'|translate("<a href='#module=Goals&action=editGoals'>","</a>")|raw }}
diff --git a/plugins/Goals/templates/conversionOverview.twig b/plugins/Goals/templates/conversionOverview.twig
new file mode 100644
index 0000000000..2697527eb7
--- /dev/null
+++ b/plugins/Goals/templates/conversionOverview.twig
@@ -0,0 +1,15 @@
+<ul class="ulGoalTopElements">
+ {% if topDimensions.country is defined %}
+ <li>{{ 'Goals_BestCountries'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.country} %}</li>
+ {% endif %}
+ {% if topDimensions.keyword is defined and topDimensions.keyword|length > 0 %}
+ <li>{{ 'Goals_BestKeywords'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.keyword} %}</li>
+ {% endif %}
+ {% if topDimensions.website is defined and topDimensions.website|length > 0 %}
+ <li>{{ 'Goals_BestReferrers'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.website} %}</li>
+ {% endif %}
+ <li>
+ {{ 'Goals_ReturningVisitorsConversionRateIs'|translate("<strong>"~conversion_rate_returning~"</strong>")|raw }}
+ , {{ 'Goals_NewVisitorsConversionRateIs'|translate("<strong>"~conversion_rate_new~"</strong>")|raw }}
+ </li>
+</ul><br style="clear:left"/> \ No newline at end of file
diff --git a/plugins/Goals/templates/editGoals.twig b/plugins/Goals/templates/editGoals.twig
index 76b64b9918..1bc8956511 100644
--- a/plugins/Goals/templates/editGoals.twig
+++ b/plugins/Goals/templates/editGoals.twig
@@ -1,7 +1,5 @@
{% if userCanEditGoals %}
- <h2 piwik-enriched-headline>{{ 'Goals_ManageGoals'|translate }}</h2>
-
{% include "@Goals/_addEditGoal.twig" %}
{% else %}
diff --git a/plugins/Goals/templates/getGoalReportView.twig b/plugins/Goals/templates/getGoalReportView.twig
deleted file mode 100644
index 2cb3b7f4d0..0000000000
--- a/plugins/Goals/templates/getGoalReportView.twig
+++ /dev/null
@@ -1,66 +0,0 @@
-<link rel="stylesheet" type="text/css" href="plugins/Goals/stylesheets/goals.css"/>
-{% include "@Goals/_titleAndEvolutionGraph.twig" | raw %}
-
-<div class="clear"></div>
-{% if nb_conversions > 0 %}
- <h2>{{ 'Goals_ConversionsOverview'|translate }}</h2>
- <ul class="ulGoalTopElements">
- {% if ecommerce is not defined %}
- {% if topDimensions.country is defined %}
- <li>{{ 'Goals_BestCountries'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.country} %}</li>
- {% endif %}
- {% if topDimensions.keyword is defined and topDimensions.keyword|length > 0 %}
- <li>{{ 'Goals_BestKeywords'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.keyword} %}</li>
- {% endif %}
- {% if topDimensions.website is defined and topDimensions.website|length > 0 %}
- <li>{{ 'Goals_BestReferrers'|translate }} {% include '@Goals/_listTopDimension.twig' with {'topDimension':topDimensions.website} %}</li>
- {% endif %}
- <li>
- {{ 'Goals_ReturningVisitorsConversionRateIs'|translate("<strong>"~conversion_rate_returning~"</strong>")|raw }}
- , {{ 'Goals_NewVisitorsConversionRateIs'|translate("<strong>"~conversion_rate_new~"</strong>")|raw }}
- </li>
- {% else %}
- <li>
- {{ 'General_ColumnRevenue'|translate }}: {{ revenue|money(idSite)|raw -}}
- {% if revenue_subtotal is not empty %},
- {{ 'General_Subtotal'|translate }}: {{ revenue_subtotal|money(idSite)|raw -}}
- {% endif %}
- {%- if revenue_tax is not empty -%},
- {{ 'General_Tax'|translate }}: {{ revenue_tax|money(idSite)|raw -}}
- {% endif %}
- {%- if revenue_shipping is not empty -%},
- {{ 'General_Shipping'|translate }}: {{ revenue_shipping|money(idSite)|raw -}}
- {% endif %}
- {%- if revenue_discount is not empty -%},
- {{ 'General_Discount'|translate }}: {{ revenue_discount|money(idSite)|raw -}}
- {% endif %}
- </li>
- {% endif %}
- </ul>
-{% endif %}
-
-<script type="text/javascript">
- $(document).ready(function () {
- $('.goalTopElement').tooltip({
- track: true,
- content: function () {
- return $(this).attr("title");
- },
- show: false,
- hide: false
- });
- });
-</script>
-
-{% if displayFullReport %}
- {% if nb_conversions > 0 or cart_nb_conversions is defined %}
- <h2 id='titleGoalsByDimension'>
- {% if idGoal is defined %}
- {{ 'Goals_GoalConversionsBy'|translate(goalName) }}
- {% else %}
- {{ 'Goals_ConversionsOverviewBy'|translate }}
- {% endif %}
- </h2>
- {{ goalReportsByDimension|raw }}
- {% endif %}
-{% endif %}
diff --git a/plugins/Goals/templates/getOverviewView.twig b/plugins/Goals/templates/getOverviewView.twig
deleted file mode 100644
index 909fd01711..0000000000
--- a/plugins/Goals/templates/getOverviewView.twig
+++ /dev/null
@@ -1,58 +0,0 @@
-<link rel="stylesheet" type="text/css" href="plugins/Goals/stylesheets/goals.css"/>
-
-{% include "@Goals/_titleAndEvolutionGraph.twig" %}
-{% set sum_nb_conversions=nb_conversions %}
-
-{% for goal in goalMetrics %}
- {% set nb_conversions=goal.nb_conversions %}
- {% set nb_visits_converted=goal.nb_visits_converted %}
- {% set conversion_rate=goal.conversion_rate %}
- {% set name=goal.name %}
- <div class="goalEntry" style="clear:both">
- <h2>
- <a href="javascript:broadcast.propagateAjax('module=Goals&action=goalReport&idGoal={{ goal.id }}')">
- {{ 'Goals_GoalX'|translate("'"~name~"'") }}
- </a>
- </h2>
-
- {% if not isWidget %}
- <div class="row">
- <div class="col-md-6">
- {% endif %}
-
- <div class="sparkline">{{ sparkline(goal.urlSparklineConversions) }}
- {{ 'Goals_Conversions'|translate("<strong>"~nb_conversions~"</strong>")|raw }}
- {% if goal.goalAllowMultipleConversionsPerVisit %}
- ({{ 'General_NVisits'|translate("<strong>"~nb_visits_converted~"</strong>") | raw }})
- {% endif %}
- </div>
-
- {% if not isWidget %}
- </div>
- <div class="col-md-6">
- {% endif %}
-
- <div class="sparkline">{{ sparkline(goal.urlSparklineConversionRate) }}
- {{ 'Goals_ConversionRate'|translate("<strong>"~conversion_rate~"</strong>")|raw }}
- </div>
-
- {% if not isWidget %}
- </div>
- </div>
- {% endif %}
-
- </div>
-{% endfor %}
-
-{% if displayFullReport %}
- {% if sum_nb_conversions != 0 %}
- <h2 id='titleGoalsByDimension'>
- {% if idGoal is defined %}
- {{ 'Goals_GoalConversionsBy'|translate(goalName) }}
- {% else %}
- {{ 'Goals_ConversionsOverviewBy'|translate }}
- {% endif %}
- </h2>
- {{ goalReportsByDimension|raw }}
- {% endif %}
-{% endif %}
diff --git a/plugins/Insights/Widgets.php b/plugins/Insights/Widgets.php
deleted file mode 100644
index 799662deb5..0000000000
--- a/plugins/Insights/Widgets.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Insights;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'Insights_WidgetCategory';
-
- public function init()
- {
- $this->addWidget('Insights_OverviewWidgetTitle', 'getInsightsOverview');
- $this->addWidget('Insights_MoversAndShakersWidgetTitle', 'getOverallMoversAndShakers');
- }
-}
diff --git a/plugins/Insights/Widgets/GetInsightsOverview.php b/plugins/Insights/Widgets/GetInsightsOverview.php
new file mode 100644
index 0000000000..e715865a41
--- /dev/null
+++ b/plugins/Insights/Widgets/GetInsightsOverview.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Insights\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+
+class GetInsightsOverview extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Insights_WidgetCategory');
+ $config->setName('Insights_OverviewWidgetTitle');
+ }
+}
diff --git a/plugins/Insights/Widgets/GetOverallMoversAndShakers.php b/plugins/Insights/Widgets/GetOverallMoversAndShakers.php
new file mode 100644
index 0000000000..e175e76519
--- /dev/null
+++ b/plugins/Insights/Widgets/GetOverallMoversAndShakers.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Insights\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+
+class GetOverallMoversAndShakers extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Insights_WidgetCategory');
+ $config->setName('Insights_MoversAndShakersWidgetTitle');
+ }
+}
diff --git a/plugins/Live/Categories/LiveCategory.php b/plugins/Live/Categories/LiveCategory.php
new file mode 100644
index 0000000000..c3b1a52c91
--- /dev/null
+++ b/plugins/Live/Categories/LiveCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Live\Categories;
+
+use Piwik\Category\Category;
+
+class LiveCategory extends Category
+{
+ protected $id = 'Live!';
+ protected $order = 2;
+}
diff --git a/plugins/Live/Categories/VisitorLogSubcategory.php b/plugins/Live/Categories/VisitorLogSubcategory.php
new file mode 100644
index 0000000000..2ed65cc4ed
--- /dev/null
+++ b/plugins/Live/Categories/VisitorLogSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Live\Categories;
+
+use Piwik\Category\Subcategory;
+
+class VisitorLogSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'Live_VisitorLog';
+ protected $order = 5;
+
+}
diff --git a/plugins/Live/Reports/Base.php b/plugins/Live/Reports/Base.php
index e64ed55f96..3a9a00945a 100644
--- a/plugins/Live/Reports/Base.php
+++ b/plugins/Live/Reports/Base.php
@@ -12,7 +12,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'Live!';
+ $this->categoryId = 'Live!';
}
public function configureReportMetadata(&$availableReports, $infos)
diff --git a/plugins/Live/Reports/GetLastVisitsDetails.php b/plugins/Live/Reports/GetLastVisitsDetails.php
index 8cf2268d28..f714989b75 100644
--- a/plugins/Live/Reports/GetLastVisitsDetails.php
+++ b/plugins/Live/Reports/GetLastVisitsDetails.php
@@ -8,10 +8,10 @@
*/
namespace Piwik\Plugins\Live\Reports;
-use Piwik\Menu\MenuReporting;
use Piwik\Plugin\Report;
use Piwik\Plugins\Live\Visualizations\VisitorLog;
-use Piwik\WidgetsList;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetLastVisitsDetails extends Base
{
@@ -20,8 +20,9 @@ class GetLastVisitsDetails extends Base
protected function init()
{
parent::init();
- $this->widgetTitle = 'Live_VisitorLog';
$this->order = 2;
+ $this->categoryId = 'General_Visitors';
+ $this->subcategoryId = 'Live_VisitorLog';
}
public function getDefaultTypeViewDataTable()
@@ -34,17 +35,14 @@ class GetLastVisitsDetails extends Base
return true;
}
- public function configureReportingMenu(MenuReporting $menu)
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
{
- if ($this->isEnabled()) {
- $url = array('module' => $this->module, 'action' => 'indexVisitorLog');
- $menu->addVisitorsItem($this->widgetTitle, $url, $order = 5);
- }
- }
-
- public function configureWidget(WidgetsList $widget)
- {
- $widget->add($this->category, $this->widgetTitle, $this->module, 'getVisitorLog', array('small' => 1));
+ $widget = $factory->createWidget()
+ ->forceViewDataTable(VisitorLog::ID)
+ ->setName('Live_VisitorLog')
+ ->setOrder(10)
+ ->setParameters(array('small' => 1));
+ $widgetsList->addWidgetConfig($widget);
}
}
diff --git a/plugins/Live/Reports/GetSimpleLastVisitCount.php b/plugins/Live/Reports/GetSimpleLastVisitCount.php
index 9b0db30769..d2f535ff4e 100644
--- a/plugins/Live/Reports/GetSimpleLastVisitCount.php
+++ b/plugins/Live/Reports/GetSimpleLastVisitCount.php
@@ -14,17 +14,24 @@ use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugins\Live\Controller;
use Piwik\API\Request;
+use Piwik\Report\ReportWidgetFactory;
use Piwik\View;
+use Piwik\Widget\WidgetsList;
class GetSimpleLastVisitCount extends Base
{
protected function init()
{
parent::init();
- $this->widgetTitle = 'Live_RealTimeVisitorCount';
$this->order = 3;
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widget = $factory->createWidget()->setName('Live_RealTimeVisitorCount')->setOrder(15);
+ $widgetsList->addWidgetConfig($widget);
+ }
+
public function render()
{
$lastMinutes = Config::getInstance()->General[Controller::SIMPLE_VISIT_COUNT_WIDGET_LAST_MINUTES_CONFIG_KEY];
diff --git a/plugins/Live/Widgets.php b/plugins/Live/Widgets.php
deleted file mode 100644
index c4c96c53e9..0000000000
--- a/plugins/Live/Widgets.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Live;
-
-use Piwik\Piwik;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'Live!';
-
- public function init()
- {
- $this->addWidget('Live_VisitorsInRealTime', 'widget');
-
- // the visitor profile uses a segment that is not accessible to the anonymous user, so don't bother showing this widget
- if (!Piwik::isUserIsAnonymous()) {
- $this->addWidget('Live_VisitorProfile', 'getVisitorProfilePopup');
- }
- }
-
-}
diff --git a/plugins/Live/Widgets/GetVisitorProfilePopup.php b/plugins/Live/Widgets/GetVisitorProfilePopup.php
new file mode 100644
index 0000000000..0d01a7abca
--- /dev/null
+++ b/plugins/Live/Widgets/GetVisitorProfilePopup.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Live\Widgets;
+
+use Piwik\Piwik;
+use Piwik\Widget\WidgetConfig;
+
+class GetVisitorProfilePopup extends \Piwik\Widget\Widget
+{
+
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('General_Visitors');
+ $config->setName('Live_VisitorProfile');
+ $config->setOrder(25);
+
+ if (Piwik::isUserIsAnonymous()) {
+ $config->disable();
+ }
+ }
+
+ public function render()
+ {
+
+ }
+
+}
diff --git a/plugins/Live/Widgets/Widget.php b/plugins/Live/Widgets/Widget.php
new file mode 100644
index 0000000000..e058423b66
--- /dev/null
+++ b/plugins/Live/Widgets/Widget.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Live\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+
+class Widget extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('Live!');
+ $config->setName('Live_VisitorsInRealTime');
+ $config->setOrder(20);
+ }
+}
diff --git a/plugins/Live/templates/index.twig b/plugins/Live/templates/index.twig
index ced0699bb9..b0a9382b65 100644
--- a/plugins/Live/templates/index.twig
+++ b/plugins/Live/templates/index.twig
@@ -43,7 +43,7 @@
</a>
{% if not disableLink %}
&nbsp;
- <a class="rightLink" href="javascript:broadcast.propagateAjax('module=Live&action=getVisitorLog')">{{ 'Live_LinkVisitorLog'|translate }}</a>
+ <a class="rightLink" href="#" onclick="this.href=broadcast.buildReportingUrl('category=General_Visitors&subcategory=Live_VisitorLog')">{{ 'Live_LinkVisitorLog'|translate }}</a>
{% endif %}
</div>
{% endspaceless %}
diff --git a/plugins/Morpheus/javascripts/piwikHelper.js b/plugins/Morpheus/javascripts/piwikHelper.js
index 163ea90160..cc6ae5dde5 100644
--- a/plugins/Morpheus/javascripts/piwikHelper.js
+++ b/plugins/Morpheus/javascripts/piwikHelper.js
@@ -125,6 +125,10 @@ var piwikHelper = {
compileAngularComponents: function (selector) {
var $element = $(selector);
+ if (!$element || !$element.length) {
+ return;
+ }
+
angular.element(document).injector().invoke(function($compile) {
var scope = angular.element($element).scope();
$compile($element)(scope);
@@ -155,9 +159,9 @@ var piwikHelper = {
var button = {text: text};
if(typeof handles[role] == 'function') {
- button.click = function(){$(this).dialog("close"); handles[role].apply()};
+ button.click = function(){ $(this).dialog("close"); handles[role].apply()};
} else {
- button.click = function(){$(this).dialog("close");};
+ button.click = function(){ $(this).dialog("close");};
}
if (title) {
diff --git a/plugins/Morpheus/stylesheets/ui/_map.less b/plugins/Morpheus/stylesheets/ui/_map.less
index 0446610c2d..731f4e369b 100644
--- a/plugins/Morpheus/stylesheets/ui/_map.less
+++ b/plugins/Morpheus/stylesheets/ui/_map.less
@@ -56,6 +56,10 @@
font-size: 14px;
}
+.uiTest .realTimeMap_datetime {
+ visibility: hidden;
+}
+
.realtime-map[data-name=white-fill] {
color: #f2f2f2 !important;
}
diff --git a/plugins/Morpheus/templates/layout.twig b/plugins/Morpheus/templates/layout.twig
index 1e9f1f0d5c..87cb863356 100644
--- a/plugins/Morpheus/templates/layout.twig
+++ b/plugins/Morpheus/templates/layout.twig
@@ -47,6 +47,8 @@
{% endblock %}
</div>
+ <div piwik-popover-handler></div>
+
{% endblock %}
</body>
diff --git a/plugins/MultiSites/Categories/MultiSitesCategory.php b/plugins/MultiSites/Categories/MultiSitesCategory.php
new file mode 100644
index 0000000000..0e884d3cfb
--- /dev/null
+++ b/plugins/MultiSites/Categories/MultiSitesCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\MultiSites\Categories;
+
+use Piwik\Category\Category;
+
+class MultiSitesCategory extends Category
+{
+ protected $id = 'General_MultiSitesSummary';
+ protected $order = 3;
+}
diff --git a/plugins/MultiSites/Reports/Base.php b/plugins/MultiSites/Reports/Base.php
index 7b72df674b..fbc85200b3 100644
--- a/plugins/MultiSites/Reports/Base.php
+++ b/plugins/MultiSites/Reports/Base.php
@@ -15,7 +15,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_MultiSitesSummary';
+ $this->categoryId = 'General_MultiSitesSummary';
$allMetricsInfo = API::getApiMetrics($enhanced = true);
diff --git a/plugins/Provider/Reports/GetProvider.php b/plugins/Provider/Reports/GetProvider.php
index e7cfcfa753..adf03cd26f 100644
--- a/plugins/Provider/Reports/GetProvider.php
+++ b/plugins/Provider/Reports/GetProvider.php
@@ -13,17 +13,26 @@ use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Provider\Columns\Provider;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetProvider extends Report
{
protected function init()
{
- $this->category = 'General_Visitors';
+ $this->categoryId = 'General_Visitors';
$this->dimension = new Provider();
$this->name = Piwik::translate('Provider_ColumnProvider');
$this->documentation = Piwik::translate('Provider_ProviderReportDocumentation', '<br />');
$this->order = 50;
- $this->widgetTitle = 'Provider_WidgetProviders';
+
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widget = $factory->createWidget()->setName('Provider_WidgetProviders');
+ $widgetsList->addWidgetConfig($widget);
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/Referrers/Categories/AllReferrersSubcategory.php b/plugins/Referrers/Categories/AllReferrersSubcategory.php
new file mode 100644
index 0000000000..277fc762dd
--- /dev/null
+++ b/plugins/Referrers/Categories/AllReferrersSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Subcategory;
+
+class AllReferrersSubcategory extends Subcategory
+{
+ protected $categoryId = 'Referrers_Referrers';
+ protected $id = 'Referrers_WidgetGetAll';
+ protected $order = 5;
+
+}
diff --git a/plugins/Referrers/Categories/CampaignsSubcategory.php b/plugins/Referrers/Categories/CampaignsSubcategory.php
new file mode 100644
index 0000000000..5878a0a9e2
--- /dev/null
+++ b/plugins/Referrers/Categories/CampaignsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Subcategory;
+
+class CampaignsSubcategory extends Subcategory
+{
+ protected $categoryId = 'Referrers_Referrers';
+ protected $id = 'Referrers_Campaigns';
+ protected $order = 20;
+
+}
diff --git a/plugins/Referrers/Categories/ReferrersCategory.php b/plugins/Referrers/Categories/ReferrersCategory.php
new file mode 100644
index 0000000000..34c8f053ba
--- /dev/null
+++ b/plugins/Referrers/Categories/ReferrersCategory.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Category;
+
+class ReferrersCategory extends Category
+{
+ protected $id = 'Referrers_Referrers';
+ protected $order = 15;
+}
diff --git a/plugins/Referrers/Categories/ReferrersOverviewSubcategory.php b/plugins/Referrers/Categories/ReferrersOverviewSubcategory.php
new file mode 100644
index 0000000000..9cd6dafbdc
--- /dev/null
+++ b/plugins/Referrers/Categories/ReferrersOverviewSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Subcategory;
+
+class ReferrersOverviewSubcategory extends Subcategory
+{
+ protected $categoryId = 'Referrers_Referrers';
+ protected $id = 'General_Overview';
+ protected $order = 2;
+
+}
diff --git a/plugins/Referrers/Categories/SearchEnginesSubcategory.php b/plugins/Referrers/Categories/SearchEnginesSubcategory.php
new file mode 100644
index 0000000000..c8bfc478e6
--- /dev/null
+++ b/plugins/Referrers/Categories/SearchEnginesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Subcategory;
+
+class SearchEnginesSubcategory extends Subcategory
+{
+ protected $categoryId = 'Referrers_Referrers';
+ protected $id = 'Referrers_SubmenuSearchEngines';
+ protected $order = 10;
+
+}
diff --git a/plugins/Referrers/Categories/WebsitesSubcategory.php b/plugins/Referrers/Categories/WebsitesSubcategory.php
new file mode 100644
index 0000000000..8b045bd5d4
--- /dev/null
+++ b/plugins/Referrers/Categories/WebsitesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Categories;
+
+use Piwik\Category\Subcategory;
+
+class WebsitesSubcategory extends Subcategory
+{
+ protected $categoryId = 'Referrers_Referrers';
+ protected $id = 'Referrers_SubmenuWebsites';
+ protected $order = 15;
+
+}
diff --git a/plugins/Referrers/Controller.php b/plugins/Referrers/Controller.php
index c628af7a83..2e1deea6af 100644
--- a/plugins/Referrers/Controller.php
+++ b/plugins/Referrers/Controller.php
@@ -10,10 +10,13 @@ namespace Piwik\Plugins\Referrers;
use Piwik\API\Request;
use Piwik\Common;
+use Piwik\DataTable\Filter\CalculateEvolutionFilter;
use Piwik\DataTable\Map;
use Piwik\Metrics;
use Piwik\Period\Range;
use Piwik\Piwik;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\ViewDataTable;
use Piwik\SettingsPiwik;
use Piwik\Translation\Translator;
use Piwik\View;
@@ -35,34 +38,21 @@ class Controller extends \Piwik\Plugin\Controller
parent::__construct();
}
- public function index()
+ public function getSparklines()
{
- $view = new View('@Referrers/index');
-
- $view->graphEvolutionReferrers = $this->getEvolutionGraph(Common::REFERRER_TYPE_DIRECT_ENTRY, array(), array('nb_visits'));
- $view->nameGraphEvolutionReferrers = 'Referrers.getEvolutionGraph';
-
- $nameValues = $this->getReferrersVisitorsByType();
+ $metrics = $this->getReferrersVisitorsByType();
+ $distinctMetrics = $this->getDistinctReferrersMetrics();
- $totalVisits = array_sum($nameValues);
- foreach ($nameValues as $name => $value) {
- $view->$name = $value;
+ $totalVisits = array_sum($metrics);
+ foreach ($metrics as $name => $value) {
// calculate percent of total, if there were any visits
- if ($value != 0
- && $totalVisits != 0
- ) {
+ if ($value != 0 && $totalVisits != 0) {
$percentName = $name . 'Percent';
- $view->$percentName = round(($value / $totalVisits) * 100, 0);
+ $metrics[$percentName] = round(($value / $totalVisits) * 100, 0);
}
}
- // set distinct metrics
- $distinctMetrics = $this->getDistinctReferrersMetrics();
- foreach ($distinctMetrics as $name => $value) {
- $view->$name = $value;
- }
-
// calculate evolution for visit metrics & distinct metrics
list($lastPeriodDate, $ignore) = Range::getLastDate();
if ($lastPeriodDate !== false) {
@@ -74,71 +64,109 @@ class Controller extends \Piwik\Plugin\Controller
// visit metrics
$previousValues = $this->getReferrersVisitorsByType($lastPeriodDate);
- $this->addEvolutionPropertiesToView($view, $prettyDate, $nameValues, $prettyLastPeriodDate, $previousValues);
+ $metrics = $this->addEvolutionPropertiesToView($prettyDate, $metrics, $prettyLastPeriodDate, $previousValues);
// distinct metrics
$previousValues = $this->getDistinctReferrersMetrics($lastPeriodDate);
- $this->addEvolutionPropertiesToView($view, $prettyDate, $distinctMetrics, $prettyLastPeriodDate, $previousValues);
+ $distinctMetrics = $this->addEvolutionPropertiesToView($prettyDate, $distinctMetrics, $prettyLastPeriodDate, $previousValues);
}
- // sparkline for the historical data of the above values
- $view->urlSparklineSearchEngines = $this->getReferrerUrlSparkline(Common::REFERRER_TYPE_SEARCH_ENGINE);
- $view->urlSparklineDirectEntry = $this->getReferrerUrlSparkline(Common::REFERRER_TYPE_DIRECT_ENTRY);
- $view->urlSparklineWebsites = $this->getReferrerUrlSparkline(Common::REFERRER_TYPE_WEBSITE);
- $view->urlSparklineCampaigns = $this->getReferrerUrlSparkline(Common::REFERRER_TYPE_CAMPAIGN);
- // sparklines for the evolution of the distinct keywords count/websites count/ etc
- $view->urlSparklineDistinctSearchEngines = $this->getUrlSparkline('getLastDistinctSearchEnginesGraph');
- $view->urlSparklineDistinctKeywords = $this->getUrlSparkline('getLastDistinctKeywordsGraph');
- $view->urlSparklineDistinctWebsites = $this->getUrlSparkline('getLastDistinctWebsitesGraph');
- $view->urlSparklineDistinctCampaigns = $this->getUrlSparkline('getLastDistinctCampaignsGraph');
+ /** @var Sparklines $view */
+ $view = ViewDataTable\Factory::build(Sparklines::ID, $api = false, $controller = false, $force = true, $loadUserParams = false);
- return $view->render();
- }
+ // DIRECT ENTRY
+ $values = array($metrics['visitorsFromDirectEntry']);
+ $descriptions = array(Piwik::translate('Referrers_TypeDirectEntries'));
- public function allReferrers()
- {
- $view = new View('@Referrers/allReferrers');
+ if (!empty($metrics['visitorsFromDirectEntryPercent'])) {
+ $values[] = $metrics['visitorsFromDirectEntryPercent'];
+ $descriptions[] = Piwik::translate('Referrers_XPercentOfVisits');
+ }
- // building the referrers summary report
- $view->dataTableReferrerType = $this->renderReport('getReferrerType');
+ $directEntryParams = $this->getReferrerSparklineParams(Common::REFERRER_TYPE_DIRECT_ENTRY);
- $nameValues = $this->getReferrersVisitorsByType();
+ $view->config->addSparkline($directEntryParams, $values, $descriptions, @$metrics['visitorsFromDirectEntryEvolution']);
- $totalVisits = array_sum($nameValues);
- foreach ($nameValues as $name => $value) {
- $view->$name = $value;
- // calculate percent of total, if there were any visits
- if ($value != 0
- && $totalVisits != 0
- ) {
- $percentName = $name . 'Percent';
- $view->$percentName = round(($value / $totalVisits) * 100, 0);
- }
+ // WEBSITES
+ $values = array($metrics['visitorsFromWebsites']);
+ $descriptions = array(Piwik::translate('Referrers_TypeWebsites'));
+
+ if (!empty($metrics['visitorsFromWebsitesPercent'])) {
+ $values[] = $metrics['visitorsFromWebsitesPercent'];
+ $descriptions[] = Piwik::translate('Referrers_XPercentOfVisits');
}
- $view->totalVisits = $totalVisits;
- $view->referrersReportsByDimension = $this->renderReport('getAll');
+ $searchEngineParams = $this->getReferrerSparklineParams(Common::REFERRER_TYPE_WEBSITE);
- return $view->render();
- }
+ $view->config->addSparkline($searchEngineParams, $values, $descriptions, @$metrics['visitorsFromWebsitesEvolution']);
+
+
+ // SEARCH ENGINES
+ $values = array($metrics['visitorsFromSearchEngines']);
+ $descriptions = array(Piwik::translate('Referrers_TypeSearchEngines'));
+
+ if (!empty($metrics['visitorsFromSearchEnginesPercent'])) {
+ $values[] = $metrics['visitorsFromSearchEnginesPercent'];
+ $descriptions[] = Piwik::translate('Referrers_XPercentOfVisits');
+ }
+ $searchEngineParams = $this->getReferrerSparklineParams(Common::REFERRER_TYPE_SEARCH_ENGINE);
+
+ $view->config->addSparkline($searchEngineParams, $values, $descriptions, @$metrics['visitorsFromSearchEnginesEvolution']);
+
+
+ // CAMPAIGNS
+ $values = array($metrics['visitorsFromCampaigns']);
+ $descriptions = array(Piwik::translate('Referrers_TypeCampaigns'));
+
+ if (!empty($metrics['visitorsFromCampaignsPercent'])) {
+ $values[] = $metrics['visitorsFromCampaignsPercent'];
+ $descriptions[] = Piwik::translate('Referrers_XPercentOfVisits');
+ }
+
+ $searchEngineParams = $this->getReferrerSparklineParams(Common::REFERRER_TYPE_CAMPAIGN);
+
+ $view->config->addSparkline($searchEngineParams, $values, $descriptions, @$metrics['visitorsFromCampaignsEvolution']);
+
+
+ // DISTINCT SEARCH ENGINES
+ $sparklineParams = $this->getDistinctSparklineUrlParams('getLastDistinctSearchEnginesGraph');
+ $value = $distinctMetrics['numberDistinctSearchEngines'];
+ $description = Piwik::translate('Referrers_DistinctSearchEngines');
+
+ $view->config->addSparkline($sparklineParams, $value, $description, @$distinctMetrics['numberDistinctSearchEnginesEvolution']);
+
+
+ // DISTINCT WEBSITES
+ $sparklineParams = $this->getDistinctSparklineUrlParams('getLastDistinctWebsitesGraph');
+ $values = array($distinctMetrics['numberDistinctWebsites'], $distinctMetrics['numberDistinctWebsitesUrls']);
+ $descriptions = array(Piwik::translate('Referrers_DistinctWebsites'), Piwik::translate('Referrers_UsingNDistinctUrls'));
+
+ $view->config->addSparkline($sparklineParams, $values, $descriptions, @$distinctMetrics['numberDistinctWebsitesEvolution']);
+
+
+ // DISTINCT KEYWORDS
+ $sparklineParams = $this->getDistinctSparklineUrlParams('getLastDistinctKeywordsGraph');
+ $value = $distinctMetrics['numberDistinctKeywords'];
+ $description = Piwik::translate('Referrers_DistinctKeywords');
+
+ $view->config->addSparkline($sparklineParams, $value, $description, @$distinctMetrics['numberDistinctKeywordsEvolution']);
+
+
+ // DISTINCT CAMPAIGNS
+ $sparklineParams = $this->getDistinctSparklineUrlParams('getLastDistinctCampaignsGraph');
+ $value = $distinctMetrics['numberDistinctCampaigns'];
+ $description = Piwik::translate('Referrers_DistinctCampaigns');
+
+ $view->config->addSparkline($sparklineParams, $value, $description, @$distinctMetrics['numberDistinctCampaignsEvolution']);
- public function getSearchEnginesAndKeywords()
- {
- $view = new View('@Referrers/getSearchEnginesAndKeywords');
- $view->searchEngines = $this->renderReport('getSearchEngines');
- $view->keywords = $this->renderReport('getKeywords');
return $view->render();
}
- public function indexWebsites()
+ private function getDistinctSparklineUrlParams($action)
{
- $view = new View('@Referrers/indexWebsites');
- $view->websites = $this->renderReport('getWebsites');
- $view->socials = $this->renderReport('getSocials');
-
- return $view->render();
+ return array('module' => $this->pluginName, 'action' => $action);
}
protected function getReferrersVisitorsByType($date = false)
@@ -221,7 +249,7 @@ class Controller extends \Piwik\Plugin\Controller
} else {
// use $typeReferrer as default
if ($typeReferrer === false) {
- $typeReferrer = Common::getRequestVar('typeReferrer', false);
+ $typeReferrer = Common::getRequestVar('typeReferrer', Common::REFERRER_TYPE_DIRECT_ENTRY);
}
$label = self::getTranslatedReferrerTypeLabel($typeReferrer);
$total = $this->translator->translate('General_Total');
@@ -416,14 +444,16 @@ function DisplayTopKeywords($url = "")
* @param int $referrerType The referrer type. Referrer types are defined in Common class.
* @return string The URL that can be used to get a sparkline image.
*/
- private function getReferrerUrlSparkline($referrerType)
+ private function getReferrerSparklineParams($referrerType)
{
$totalRow = $this->translator->translate('General_Total');
- return $this->getUrlSparkline(
- 'getEvolutionGraph',
- array('columns' => array('nb_visits'),
- 'rows' => array(self::getTranslatedReferrerTypeLabel($referrerType), $totalRow),
- 'typeReferrer' => $referrerType)
+
+ return array(
+ 'columns' => array('nb_visits'),
+ 'rows' => array(self::getTranslatedReferrerTypeLabel($referrerType), $totalRow),
+ 'typeReferrer' => $referrerType,
+ 'module' => $this->pluginName,
+ 'action' => 'getReferrerType'
);
}
@@ -456,20 +486,32 @@ function DisplayTopKeywords($url = "")
* Utility method that calculates evolution values for a set of current & past values
* and sets properties on a View w/ HTML that displays the evolution percents.
*
- * @param View $view The view to set properties on.
* @param string $date The date of the current values.
* @param array $currentValues Array mapping view property names w/ present values.
* @param string $lastPeriodDate The date of the period in the past.
* @param array $previousValues Array mapping view property names w/ past values. Keys
* in this array should be the same as keys in $currentValues.
+ * @return array Added current values
*/
- private function addEvolutionPropertiesToView($view, $date, $currentValues, $lastPeriodDate, $previousValues)
+ private function addEvolutionPropertiesToView($date, $currentValues, $lastPeriodDate, $previousValues)
{
foreach ($previousValues as $name => $pastValue) {
$currentValue = $currentValues[$name];
$evolutionName = $name . 'Evolution';
- $view->$evolutionName = $this->getEvolutionHtml($date, $currentValue, $lastPeriodDate, $pastValue);
+ $currentValues[$evolutionName] = array(
+ 'currentValue' => $currentValue,
+ 'pastValue' => $pastValue,
+ 'tooltip' => Piwik::translate('General_EvolutionSummaryGeneric', array(
+ Piwik::translate('General_NVisits', $currentValue),
+ $date,
+ Piwik::translate('General_NVisits', $pastValue),
+ $lastPeriodDate,
+ CalculateEvolutionFilter::calculate($currentValue, $pastValue, $precision = 1)
+ ))
+ );
}
+
+ return $currentValues;
}
}
diff --git a/plugins/Referrers/Menu.php b/plugins/Referrers/Menu.php
deleted file mode 100644
index cb92a43db3..0000000000
--- a/plugins/Referrers/Menu.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Referrers;
-
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addReferrersItem('', $this->urlForAction('index'), 20);
- $menu->addReferrersItem('General_Overview', $this->urlForAction('index'), 1);
- $menu->addReferrersItem('Referrers_WidgetGetAll', $this->urlForAction('allReferrers'), 2);
- $menu->addReferrersItem('Referrers_SubmenuSearchEngines', $this->urlForAction('getSearchEnginesAndKeywords'), 3);
- $menu->addReferrersItem('Referrers_SubmenuWebsites', $this->urlForAction('indexWebsites'), 4);
- }
-}
diff --git a/plugins/Referrers/Reports/Base.php b/plugins/Referrers/Reports/Base.php
index e4a6394c00..2bd240d191 100644
--- a/plugins/Referrers/Reports/Base.php
+++ b/plugins/Referrers/Reports/Base.php
@@ -12,7 +12,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'Referrers_Referrers';
+ $this->categoryId = 'Referrers_Referrers';
}
}
diff --git a/plugins/Referrers/Reports/GetAll.php b/plugins/Referrers/Reports/GetAll.php
index 2079dd414d..cb5f17ee41 100644
--- a/plugins/Referrers/Reports/GetAll.php
+++ b/plugins/Referrers/Reports/GetAll.php
@@ -13,6 +13,8 @@ use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
use Piwik\Plugins\Referrers\Columns\Referrer;
use Piwik\Plugins\Referrers\Referrers;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetAll extends Base
{
@@ -23,7 +25,15 @@ class GetAll extends Base
$this->name = Piwik::translate('Referrers_WidgetGetAll');
$this->documentation = Piwik::translate('Referrers_AllReferrersReportDocumentation', '<br />');
$this->order = 2;
- $this->widgetTitle = 'Referrers_WidgetGetAll';
+
+ $this->subcategoryId = 'Referrers_WidgetGetAll';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()->setName('Referrers_Referrers')
+ );
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/Referrers/Reports/GetCampaigns.php b/plugins/Referrers/Reports/GetCampaigns.php
index a09affa70c..1d375423d8 100644
--- a/plugins/Referrers/Reports/GetCampaigns.php
+++ b/plugins/Referrers/Reports/GetCampaigns.php
@@ -24,8 +24,8 @@ class GetCampaigns extends Base
$this->actionToLoadSubTables = 'getKeywordsFromCampaignId';
$this->hasGoalMetrics = true;
$this->order = 9;
- $this->widgetTitle = 'Referrers_Campaigns';
- $this->menuTitle = 'Referrers_Campaigns';
+
+ $this->subcategoryId = 'Referrers_Campaigns';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/Referrers/Reports/GetKeywords.php b/plugins/Referrers/Reports/GetKeywords.php
index be8e8d3f4c..3239fefde0 100644
--- a/plugins/Referrers/Reports/GetKeywords.php
+++ b/plugins/Referrers/Reports/GetKeywords.php
@@ -11,7 +11,9 @@ namespace Piwik\Plugins\Referrers\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
use Piwik\Plugins\Referrers\Columns\Keyword;
+use Piwik\Tracker\Visit;
class GetKeywords extends Base
{
@@ -24,7 +26,7 @@ class GetKeywords extends Base
$this->actionToLoadSubTables = 'getSearchEnginesFromKeywordId';
$this->hasGoalMetrics = true;
$this->order = 3;
- $this->widgetTitle = 'Referrers_Keywords';
+ $this->subcategoryId = 'Referrers_SubmenuSearchEngines';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/Referrers/Reports/GetReferrerType.php b/plugins/Referrers/Reports/GetReferrerType.php
index f5656bfa7f..c09f8c6d17 100644
--- a/plugins/Referrers/Reports/GetReferrerType.php
+++ b/plugins/Referrers/Reports/GetReferrerType.php
@@ -12,7 +12,11 @@ use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Plugins\Referrers\Columns\ReferrerType;
+use Piwik\Widget\WidgetsList;
+use Piwik\Report\ReportWidgetFactory;
class GetReferrerType extends Base
{
@@ -32,7 +36,7 @@ class GetReferrerType extends Base
$this->constantRowsCount = true;
$this->hasGoalMetrics = true;
$this->order = 1;
- $this->widgetTitle = 'General_Overview';
+ $this->subcategoryId = 'Referrers_WidgetGetAll';
}
public function getDefaultTypeViewDataTable()
@@ -40,6 +44,36 @@ class GetReferrerType extends Base
return HtmlTable\AllColumns::ID;
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('Referrers_ReferrerTypes')
+ ->setSubcategoryId('Referrers_WidgetGetAll')
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('General_EvolutionOverPeriod')
+ ->setSubcategoryId('General_Overview')
+ ->setAction('getEvolutionGraph')
+ ->setIsNotWidgetizable()
+ ->forceViewDataTable(Evolution::ID)
+ ->addParameters(array(
+ 'columns' => $defaultColumns = array('nb_visits'),
+ ))
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createCustomWidget('getSparklines')
+ ->forceViewDataTable(Sparklines::ID)
+ ->setIsNotWidgetizable()
+ ->setName('Referrers_Type')
+ ->setSubcategoryId('General_Overview')
+ ->setOrder(10)
+ );
+ }
+
public function configureView(ViewDataTable $view)
{
$idSubtable = Common::getRequestVar('idSubtable', false);
diff --git a/plugins/Referrers/Reports/GetSearchEngines.php b/plugins/Referrers/Reports/GetSearchEngines.php
index 3b66cd0784..0a17cd132e 100644
--- a/plugins/Referrers/Reports/GetSearchEngines.php
+++ b/plugins/Referrers/Reports/GetSearchEngines.php
@@ -24,7 +24,8 @@ class GetSearchEngines extends Base
$this->actionToLoadSubTables = 'getKeywordsFromSearchEngineId';
$this->hasGoalMetrics = true;
$this->order = 7;
- $this->widgetTitle = 'Referrers_SearchEngines';
+
+ $this->subcategoryId = 'Referrers_SubmenuSearchEngines';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/Referrers/Reports/GetSocials.php b/plugins/Referrers/Reports/GetSocials.php
index b49fac623a..7429ddd48f 100644
--- a/plugins/Referrers/Reports/GetSocials.php
+++ b/plugins/Referrers/Reports/GetSocials.php
@@ -14,6 +14,8 @@ use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie;
use Piwik\Plugins\Referrers\Columns\SocialNetwork;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetSocials extends Base
{
@@ -25,7 +27,14 @@ class GetSocials extends Base
$this->documentation = Piwik::translate('Referrers_WebsitesReportDocumentation', '<br />');
$this->actionToLoadSubTables = 'getUrlsForSocial';
$this->order = 11;
- $this->widgetTitle = 'Referrers_WidgetSocials';
+
+ $this->subcategoryId = 'Referrers_SubmenuWebsites';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widget = $factory->createWidget()->setName('Referrers_Socials');
+ $widgetsList->addWidgetConfig($widget);
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/Referrers/Reports/GetWebsites.php b/plugins/Referrers/Reports/GetWebsites.php
index 18f9336a63..f5be3ca375 100644
--- a/plugins/Referrers/Reports/GetWebsites.php
+++ b/plugins/Referrers/Reports/GetWebsites.php
@@ -12,6 +12,8 @@ use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
use Piwik\Plugins\Referrers\Columns\Website;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetWebsites extends Base
{
@@ -25,7 +27,8 @@ class GetWebsites extends Base
$this->actionToLoadSubTables = 'getUrlsFromWebsiteId';
$this->hasGoalMetrics = true;
$this->order = 5;
- $this->widgetTitle = 'Referrers_WidgetExternalWebsites';
+
+ $this->subcategoryId = 'Referrers_SubmenuWebsites';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/Referrers/Widgets.php b/plugins/Referrers/Widgets.php
deleted file mode 100644
index 4e23c9f746..0000000000
--- a/plugins/Referrers/Widgets.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\Referrers;
-
-use Piwik\SettingsPiwik;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'SEO';
-
- public function init()
- {
- if (SettingsPiwik::isSegmentationEnabled()) {
- $this->addWidget('Referrers_WidgetTopKeywordsForPages', 'getKeywordsForPage');
- }
- }
-
-}
diff --git a/plugins/Referrers/Widgets/GetKeywordsForPage.php b/plugins/Referrers/Widgets/GetKeywordsForPage.php
new file mode 100644
index 0000000000..165bb18f68
--- /dev/null
+++ b/plugins/Referrers/Widgets/GetKeywordsForPage.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+use Piwik\SettingsPiwik;
+
+class GetKeywordsForPage extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('SEO');
+ $config->setName('Referrers_WidgetTopKeywordsForPages');
+ $config->setIsEnabled(SettingsPiwik::isSegmentationEnabled());
+ }
+
+}
diff --git a/plugins/Referrers/templates/allReferrers.twig b/plugins/Referrers/templates/allReferrers.twig
deleted file mode 100644
index bf8c7c431c..0000000000
--- a/plugins/Referrers/templates/allReferrers.twig
+++ /dev/null
@@ -1,11 +0,0 @@
-<h2 piwik-enriched-headline>{{ 'Referrers_ReferrerTypes'|translate }}</h2>
-{{ dataTableReferrerType|raw }}
-
-<div style="clear:both;"></div>
-
-{% if totalVisits > 0 %}
- <h2 piwik-enriched-headline>{{ 'Referrers_Referrers'|translate }}</h2>
- {{ referrersReportsByDimension|raw }}
-{% endif %}
-
-{% include "_sparklineFooter.twig" %}
diff --git a/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig b/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig
deleted file mode 100644
index 29b2b3f0af..0000000000
--- a/plugins/Referrers/templates/getSearchEnginesAndKeywords.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Referrers_Keywords'|translate }}</h2>
- {{ keywords|raw }}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Referrers_SearchEngines'|translate }}</h2>
- {{ searchEngines|raw }}
- </div>
-
-</div>
diff --git a/plugins/Referrers/templates/index.twig b/plugins/Referrers/templates/index.twig
deleted file mode 100644
index c629431210..0000000000
--- a/plugins/Referrers/templates/index.twig
+++ /dev/null
@@ -1,89 +0,0 @@
-<h2 piwik-enriched-headline
- data-graph-id="{{ nameGraphEvolutionReferrers }}">{{ 'General_EvolutionOverPeriod'|translate }}</h2>
-{{ graphEvolutionReferrers|raw }}
-
-<h2 piwik-enriched-headline>{{ 'Referrers_Type'|translate }}</h2>
-
-<div class="row">
- <div class="col-md-6">
- <div class="sparkline" style="padding-left: 12px;">{{ sparkline(urlSparklineDirectEntry) }}
- {{ 'Referrers_TypeDirectEntries'|translate("<strong>"~visitorsFromDirectEntry~"</strong>")|raw }}
- {% if visitorsFromDirectEntryPercent|default is not empty %},
- {{ 'Referrers_XPercentOfVisits'|translate("<strong>"~visitorsFromDirectEntryPercent~"</strong>")|raw }}
- {% endif %}
- {% if visitorsFromDirectEntryEvolution|default is not empty %}
- {{ visitorsFromDirectEntryEvolution|raw }}
- {% endif %}
- </div>
- <div class="sparkline" style="padding-left: 12px;">{{ sparkline(urlSparklineSearchEngines) }}
- {{ 'Referrers_TypeSearchEngines'|translate("<strong>"~visitorsFromSearchEngines~"</strong>")|raw }}
- {% if visitorsFromSearchEnginesPercent|default is not empty %},
- {{ 'Referrers_XPercentOfVisits'|translate("<strong>"~visitorsFromSearchEnginesPercent~"</strong>")|raw }}
- {% endif %}
- {% if visitorsFromSearchEnginesEvolution|default is not empty %}
- {{ visitorsFromSearchEnginesEvolution|raw }}
- {% endif %}
- </div>
- </div>
- <div class="col-md-6">
- <div class="sparkline">{{ sparkline(urlSparklineWebsites) }}
- {{ 'Referrers_TypeWebsites'|translate("<strong>"~visitorsFromWebsites~"</strong>")|raw }}
- {% if visitorsFromWebsitesPercent|default is not empty %},
- {{ 'Referrers_XPercentOfVisits'|translate("<strong>"~visitorsFromWebsitesPercent~"</strong>")|raw }}
- {% endif %}
- {% if visitorsFromWebsitesEvolution|default is not empty %}
- {{ visitorsFromWebsitesEvolution|raw }}
- {% endif %}
- </div>
- <div class="sparkline">{{ sparkline(urlSparklineCampaigns) }}
- {{ 'Referrers_TypeCampaigns'|translate("<strong>"~visitorsFromCampaigns~"</strong>")|raw }}
- {% if visitorsFromCampaignsPercent|default is not empty %},
- {{ 'Referrers_XPercentOfVisits'|translate("<strong>"~visitorsFromCampaignsPercent~"</strong>")|raw }}
- {% endif %}
- {% if visitorsFromCampaignsEvolution|default is not empty %}
- {{ visitorsFromCampaignsEvolution|raw }}
- {% endif %}
- </div>
- </div>
-</div>
-
-<div id="distinctReferrersByType" class="row">
- <div class="col-md-6">
- <div class="sparkline" style="padding-left: 12px;">{{ sparkline(urlSparklineDistinctSearchEngines) }}
- <strong>{{ numberDistinctSearchEngines }}</strong> {{ 'Referrers_DistinctSearchEngines'|translate }}
- {% if numberDistinctSearchEnginesEvolution|default is not empty %}
- {{ numberDistinctSearchEnginesEvolution|raw }}
- {% endif %}
- </div>
- <div class="sparkline" style="padding-left: 12px;">{{ sparkline(urlSparklineDistinctKeywords) }}
- <strong>{{ numberDistinctKeywords }}</strong> {{ 'Referrers_DistinctKeywords'|translate }}
- {% if numberDistinctKeywordsEvolution|default is not empty %}
- {{ numberDistinctKeywordsEvolution|raw }}
- {% endif %}
- </div>
- </div>
- <div class="col-md-6">
- <div class="sparkline">{{ sparkline(urlSparklineDistinctWebsites) }}
- <strong>{{ numberDistinctWebsites }}</strong> {{ 'Referrers_DistinctWebsites'|translate }}
- {{ 'Referrers_UsingNDistinctUrls'|translate("<strong>"~numberDistinctWebsitesUrls~"</strong>")|raw }}
- {% if numberDistinctWebsitesEvolution|default is not empty %}
- {{ numberDistinctWebsitesEvolution|raw }}
- {% endif %}
- </div>
- <div class="sparkline">{{ sparkline(urlSparklineDistinctCampaigns) }}
- <strong>{{ numberDistinctCampaigns }}</strong> {{ 'Referrers_DistinctCampaigns'|translate }}
- {% if numberDistinctCampaignsEvolution|default is not empty %}
- {{ numberDistinctCampaignsEvolution|raw }}
- {% endif %}
- </div>
- </div>
- <br/>
-</div>
-
-<div style="float:left;" class="relatedReferrerReports">{{ 'General_View'|translate }}
- <a href="javascript:broadcast.propagateAjax('module=Referrers&action=getSearchEnginesAndKeywords')">{{ 'Referrers_SubmenuSearchEngines'|translate }}</a>,
- <a href="javascript:broadcast.propagateAjax('module=Referrers&action=indexWebsites')">{{ 'Referrers_SubmenuWebsites'|translate }}</a>,
- <a href="javascript:broadcast.propagateAjax('module=Referrers&action=indexCampaigns')">{{ 'Referrers_Campaigns'|translate }}</a>.
-</div>
-
-{% include "_sparklineFooter.twig" %}
diff --git a/plugins/Referrers/templates/indexWebsites.twig b/plugins/Referrers/templates/indexWebsites.twig
deleted file mode 100644
index cdfa6efe01..0000000000
--- a/plugins/Referrers/templates/indexWebsites.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Referrers_Websites'|translate }}</h2>
- {{ websites|raw }}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'Referrers_Socials'|translate }}</h2>
- {{ socials|raw }}
- </div>
-
-</div>
diff --git a/plugins/Resolution/Reports/Base.php b/plugins/Resolution/Reports/Base.php
index 259a164113..0ef3f0d631 100644
--- a/plugins/Resolution/Reports/Base.php
+++ b/plugins/Resolution/Reports/Base.php
@@ -15,7 +15,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_VisitorSettings';
+ $this->categoryId = 'General_Visitors';
}
protected function getBasicResolutionDisplayProperties(ViewDataTable $view)
diff --git a/plugins/Resolution/Reports/GetConfiguration.php b/plugins/Resolution/Reports/GetConfiguration.php
index c01c4f3b07..600f07edd9 100644
--- a/plugins/Resolution/Reports/GetConfiguration.php
+++ b/plugins/Resolution/Reports/GetConfiguration.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\Resolution\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Resolution\Columns\Configuration;
+use Piwik\Plugin\Reports;
class GetConfiguration extends Base
{
@@ -18,10 +19,11 @@ class GetConfiguration extends Base
{
parent::init();
$this->dimension = new Configuration();
- $this->name = Piwik::translate('Resolution_WidgetGlobalVisitors');
+ $this->name = Piwik::translate('Resolution_Configurations');
$this->documentation = Piwik::translate('Resolution_WidgetGlobalVisitorsDocumentation', '<br />');
$this->order = 7;
- $this->widgetTitle = 'Resolution_WidgetGlobalVisitors';
+
+ $this->subcategoryId = 'DevicesDetection_Software';
}
public function configureView(ViewDataTable $view)
@@ -36,7 +38,7 @@ class GetConfiguration extends Base
public function getRelatedReports()
{
return array(
- self::factory('Resolution', 'getResolution'),
+ Reports::factory('Resolution', 'getResolution'),
);
}
}
diff --git a/plugins/Resolution/Reports/GetResolution.php b/plugins/Resolution/Reports/GetResolution.php
index f9066ce19c..3b27236a86 100644
--- a/plugins/Resolution/Reports/GetResolution.php
+++ b/plugins/Resolution/Reports/GetResolution.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\Resolution\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Resolution\Columns\Resolution;
+use Piwik\Plugin\Reports;
class GetResolution extends Base
{
@@ -20,8 +21,9 @@ class GetResolution extends Base
$this->dimension = new Resolution();
$this->name = Piwik::translate('Resolution_WidgetResolutions');
$this->documentation = ''; // TODO
- $this->order = 0;
- $this->widgetTitle = 'Resolution_WidgetResolutions';
+ $this->order = 8;
+
+ $this->subcategoryId = 'DevicesDetection_Devices';
}
public function configureView(ViewDataTable $view)
@@ -34,7 +36,7 @@ class GetResolution extends Base
public function getRelatedReports()
{
return array(
- self::factory('Resolution', 'getConfiguration'),
+ Reports::factory('Resolution', 'getConfiguration'),
);
}
}
diff --git a/plugins/SEO/Widgets.php b/plugins/SEO/Widgets/GetRank.php
index 1f06c2ec8b..521bf1859c 100644
--- a/plugins/SEO/Widgets.php
+++ b/plugins/SEO/Widgets/GetRank.php
@@ -6,25 +6,26 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
-namespace Piwik\Plugins\SEO;
+namespace Piwik\Plugins\SEO\Widgets;
use Piwik\Common;
use Piwik\DataTable\Renderer;
+use Piwik\Widget\WidgetConfig;
use Piwik\Site;
use Piwik\Url;
use Piwik\UrlHelper;
use Piwik\View;
+use Piwik\Plugins\SEO\API;
-class Widgets extends \Piwik\Plugin\Widgets
+class GetRank extends \Piwik\Widget\Widget
{
- protected $category = 'SEO';
-
- public function init()
+ public static function configure(WidgetConfig $config)
{
- $this->addWidget('SEO_SeoRankings', 'getRank');
+ $config->setCategoryId('SEO');
+ $config->setName('SEO_SeoRankings');
}
- public function getRank()
+ public function render()
{
$idSite = Common::getRequestVar('idSite');
$site = new Site($idSite);
diff --git a/plugins/Transitions/Controller.php b/plugins/Transitions/Controller.php
index dbd782f08c..fb7bb5de2b 100644
--- a/plugins/Transitions/Controller.php
+++ b/plugins/Transitions/Controller.php
@@ -22,7 +22,7 @@ class Controller extends \Piwik\Plugin\Controller
* translation keys.
*/
private static $metricTranslations = array(
- 'pageviewsInline' => 'VisitsSummary_NbPageviewsDescription',
+ 'pageviewsInline' => 'Transitions_NumPageviews',
'loopsInline' => 'Transitions_LoopsInline',
'fromPreviousPages' => 'Transitions_FromPreviousPages',
'fromPreviousPagesInline' => 'Transitions_FromPreviousPagesInline',
@@ -41,9 +41,9 @@ class Controller extends \Piwik\Plugin\Controller
'toFollowingSiteSearches' => 'Transitions_ToFollowingSiteSearches',
'toFollowingSiteSearchesInline' => 'Transitions_ToFollowingSiteSearchesInline',
'downloads' => 'General_Downloads',
- 'downloadsInline' => 'VisitsSummary_NbDownloadsDescription',
+ 'downloadsInline' => 'Transitions_NumDownloads',
'outlinks' => 'General_Outlinks',
- 'outlinksInline' => 'VisitsSummary_NbOutlinksDescription',
+ 'outlinksInline' => 'Transitions_NumOutlinks',
'exits' => 'General_ColumnExits',
'exitsInline' => 'Transitions_ExitsInline',
'bouncesInline' => 'Transitions_BouncesInline'
diff --git a/plugins/Transitions/lang/en.json b/plugins/Transitions/lang/en.json
index 4e76d5bc54..af45334071 100644
--- a/plugins/Transitions/lang/en.json
+++ b/plugins/Transitions/lang/en.json
@@ -4,6 +4,9 @@
"DirectEntries": "Direct Entries",
"ErrorBack": "Go back to the previous action",
"ExitsInline": "%s exits",
+ "NumPageviews": "%s pageviews",
+ "NumDownloads": "%s downloads",
+ "NumOutlinks": "%s outlinks",
"FromCampaigns": "From Campaigns",
"FromPreviousPages": "From Internal Pages",
"FromPreviousPagesInline": "%s from internal pages",
diff --git a/plugins/UserCountry/Categories/LocationsSubcategory.php b/plugins/UserCountry/Categories/LocationsSubcategory.php
new file mode 100644
index 0000000000..22be202abd
--- /dev/null
+++ b/plugins/UserCountry/Categories/LocationsSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\UserCountry\Categories;
+
+use Piwik\Category\Subcategory;
+
+class LocationsSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'UserCountry_SubmenuLocations';
+ protected $order = 25;
+
+}
diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php
index a241968cbd..0ed417e421 100644
--- a/plugins/UserCountry/Controller.php
+++ b/plugins/UserCountry/Controller.php
@@ -26,18 +26,13 @@ use Piwik\View;
*/
class Controller extends \Piwik\Plugin\ControllerAdmin
{
- public function index()
+ public function getDistinctCountries()
{
- $view = new View('@UserCountry/index');
+ $view = new View('@UserCountry/getDistinctCountries');
$view->urlSparklineCountries = $this->getUrlSparkline('getLastDistinctCountriesGraph');
$view->numberDistinctCountries = $this->getNumberOfDistinctCountries(true);
- $view->dataTableCountry = $this->renderReport('getCountry');
- $view->dataTableContinent = $this->renderReport('getContinent');
- $view->dataTableRegion = $this->renderReport('getRegion');
- $view->dataTableCity = $this->renderReport('getCity');
-
return $view->render();
}
diff --git a/plugins/UserCountry/Menu.php b/plugins/UserCountry/Menu.php
index fa90e258db..92f88a7f14 100644
--- a/plugins/UserCountry/Menu.php
+++ b/plugins/UserCountry/Menu.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\UserCountry;
use Piwik\Menu\MenuAdmin;
-use Piwik\Menu\MenuReporting;
use Piwik\Piwik;
class Menu extends \Piwik\Plugin\Menu
@@ -22,9 +21,4 @@ class Menu extends \Piwik\Plugin\Menu
$order = 9);
}
}
-
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addVisitorsItem('UserCountry_SubmenuLocations', $this->urlForAction('index'));
- }
}
diff --git a/plugins/UserCountry/Reports/Base.php b/plugins/UserCountry/Reports/Base.php
index f7a4f34203..c24ec82d24 100644
--- a/plugins/UserCountry/Reports/Base.php
+++ b/plugins/UserCountry/Reports/Base.php
@@ -17,7 +17,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_Visitors';
+ $this->categoryId = 'General_Visitors';
}
protected function getGeoIPReportDocSuffix()
diff --git a/plugins/UserCountry/Reports/GetCity.php b/plugins/UserCountry/Reports/GetCity.php
index ce087c3f3c..e492d12ee2 100644
--- a/plugins/UserCountry/Reports/GetCity.php
+++ b/plugins/UserCountry/Reports/GetCity.php
@@ -22,9 +22,8 @@ class GetCity extends Base
$this->documentation = Piwik::translate('UserCountry_getCityDocumentation') . '<br/>' . $this->getGeoIPReportDocSuffix();
$this->metrics = array('nb_visits', 'nb_uniq_visitors', 'nb_actions');
$this->hasGoalMetrics = true;
- $this->order = 8;
- $this->widgetTitle = Piwik::translate('UserCountry_WidgetLocation')
- . ' (' . Piwik::translate('UserCountry_City') . ')';
+ $this->order = 10;
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/UserCountry/Reports/GetContinent.php b/plugins/UserCountry/Reports/GetContinent.php
index 7ba6d2ca1c..b524c4f048 100644
--- a/plugins/UserCountry/Reports/GetContinent.php
+++ b/plugins/UserCountry/Reports/GetContinent.php
@@ -11,6 +11,9 @@ namespace Piwik\Plugins\UserCountry\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\UserCountry\Columns\Continent;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetContainerConfig;
+use Piwik\Widget\WidgetsList;
class GetContinent extends Base
{
@@ -23,8 +26,18 @@ class GetContinent extends Base
$this->metrics = array('nb_visits', 'nb_uniq_visitors', 'nb_actions');
$this->hasGoalMetrics = true;
$this->order = 6;
- $this->widgetTitle = Piwik::translate('UserCountry_WidgetLocation')
- . ' (' . Piwik::translate('UserCountry_Continent') . ')';
+
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig($factory->createContainerWidget('Continent'));
+
+ $widgetsList->addToContainerWidget('Continent', $factory->createWidget());
+
+ $widget = $factory->createWidget()->setAction('getDistinctCountries')->setName('');
+ $widgetsList->addToContainerWidget('Continent', $widget);
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/UserCountry/Reports/GetCountry.php b/plugins/UserCountry/Reports/GetCountry.php
index 88363e1efa..5b038f7e49 100644
--- a/plugins/UserCountry/Reports/GetCountry.php
+++ b/plugins/UserCountry/Reports/GetCountry.php
@@ -24,8 +24,7 @@ class GetCountry extends Base
$this->metrics = array('nb_visits', 'nb_uniq_visitors', 'nb_actions');
$this->hasGoalMetrics = true;
$this->order = 5;
- $this->widgetTitle = Piwik::translate('UserCountry_WidgetLocation')
- . ' (' . Piwik::translate('UserCountry_Country') . ')';
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/UserCountry/Reports/GetRegion.php b/plugins/UserCountry/Reports/GetRegion.php
index 648b78967b..7e418ebef2 100644
--- a/plugins/UserCountry/Reports/GetRegion.php
+++ b/plugins/UserCountry/Reports/GetRegion.php
@@ -23,8 +23,8 @@ class GetRegion extends Base
$this->metrics = array('nb_visits', 'nb_uniq_visitors', 'nb_actions');
$this->hasGoalMetrics = true;
$this->order = 7;
- $this->widgetTitle = Piwik::translate('UserCountry_WidgetLocation')
- . ' (' . Piwik::translate('UserCountry_Region') . ')';
+
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/UserCountry/templates/getDistinctCountries.twig b/plugins/UserCountry/templates/getDistinctCountries.twig
new file mode 100644
index 0000000000..7a2506f782
--- /dev/null
+++ b/plugins/UserCountry/templates/getDistinctCountries.twig
@@ -0,0 +1,5 @@
+<div class="sparkline">
+ {{ sparkline(urlSparklineCountries) }}
+ {{ 'UserCountry_DistinctCountries'|translate("<strong>"~numberDistinctCountries~"</strong>")|raw }}
+</div>
+<br style="clear:left"/> \ No newline at end of file
diff --git a/plugins/UserCountry/templates/index.twig b/plugins/UserCountry/templates/index.twig
deleted file mode 100644
index fe1a6735dd..0000000000
--- a/plugins/UserCountry/templates/index.twig
+++ /dev/null
@@ -1,29 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- {{ postEvent("Template.leftColumnUserCountry") }}
-
- <h2 piwik-enriched-headline>{{ 'UserCountry_Continent'|translate }}</h2>
- {{ dataTableContinent|raw }}
-
- <div class="sparkline">
- {{ sparkline(urlSparklineCountries) }}
- {{ 'UserCountry_DistinctCountries'|translate("<strong>"~numberDistinctCountries~"</strong>")|raw }}
- </div>
- <div style="clear:left"></div>
-
- {{ postEvent("Template.footerUserCountry") }}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'UserCountry_Country'|translate }}</h2>
- {{ dataTableCountry|raw }}
-
- <h2 piwik-enriched-headline>{{ 'UserCountry_Region'|translate }}</h2>
- {{ dataTableRegion|raw }}
-
- <h2 piwik-enriched-headline>{{ 'UserCountry_City'|translate }}</h2>
- {{ dataTableCity|raw }}
- </div>
-
-</div>
diff --git a/plugins/UserCountryMap/Categories/RealTimeMapSubcategory.php b/plugins/UserCountryMap/Categories/RealTimeMapSubcategory.php
new file mode 100644
index 0000000000..d8f482327f
--- /dev/null
+++ b/plugins/UserCountryMap/Categories/RealTimeMapSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\UserCountryMap\Categories;
+
+use Piwik\Category\Subcategory;
+
+class RealTimeMapSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'UserCountryMap_RealTimeMap';
+ protected $order = 40;
+
+}
diff --git a/plugins/UserCountryMap/Menu.php b/plugins/UserCountryMap/Menu.php
deleted file mode 100644
index 88108e3f4d..0000000000
--- a/plugins/UserCountryMap/Menu.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\UserCountryMap;
-
-use Piwik\Menu\MenuReporting;
-use Piwik\Plugin\Manager as PluginManager;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- if (PluginManager::getInstance()->isPluginActivated('UserCountry')) {
- $menu->addVisitorsItem('UserCountryMap_RealTimeMap',
- $this->urlForAction('realtimeWorldMap'),
- $order = 70);
- }
- }
-}
diff --git a/plugins/UserCountryMap/UserCountryMap.php b/plugins/UserCountryMap/UserCountryMap.php
index c7819f7f8c..6453cc7f29 100644
--- a/plugins/UserCountryMap/UserCountryMap.php
+++ b/plugins/UserCountryMap/UserCountryMap.php
@@ -10,8 +10,9 @@ namespace Piwik\Plugins\UserCountryMap;
use Piwik\FrontController;
use Piwik\Piwik;
+use Piwik\Widget\WidgetConfig;
use Piwik\Version;
-use Piwik\WidgetsList;
+use Piwik\Widget\WidgetsList;
use Piwik\Plugin\Manager as PluginManager;
/**
@@ -34,23 +35,11 @@ class UserCountryMap extends \Piwik\Plugin
$hooks = array(
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
- 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
- 'Platform.initialized' => array(
- 'after' => true,
- 'function' => 'registerWidgets'
- )
+ 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys'
);
return $hooks;
}
- public function registerWidgets()
- {
- if (PluginManager::getInstance()->isPluginActivated('UserCountry')) {
- WidgetsList::add('General_Visitors', Piwik::translate('UserCountryMap_VisitorMap'), 'UserCountryMap', 'visitorMap');
- WidgetsList::add('Live!', Piwik::translate('UserCountryMap_RealTimeMap'), 'UserCountryMap', 'realtimeMap');
- }
- }
-
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "libs/bower_components/visibilityjs/lib/visibility.core.js";
diff --git a/plugins/UserCountryMap/Widgets/GetRealtimeMap.php b/plugins/UserCountryMap/Widgets/GetRealtimeMap.php
new file mode 100644
index 0000000000..d6476bfe2d
--- /dev/null
+++ b/plugins/UserCountryMap/Widgets/GetRealtimeMap.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\UserCountryMap\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+use Piwik\Plugin\Manager as PluginManager;
+
+class GetRealtimeMap extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('General_Visitors');
+ $config->setSubcategoryId('UserCountryMap_RealTimeMap');
+ $config->setName('UserCountryMap_RealTimeMap');
+ $config->setModule('UserCountryMap');
+ $config->setAction('realtimeMap');
+ $config->setOrder(5);
+
+ if (!PluginManager::getInstance()->isPluginActivated('UserCountry')) {
+ $config->disable();
+ }
+ }
+}
diff --git a/plugins/UserCountryMap/Widgets/GetVisitorMap.php b/plugins/UserCountryMap/Widgets/GetVisitorMap.php
new file mode 100644
index 0000000000..930630df55
--- /dev/null
+++ b/plugins/UserCountryMap/Widgets/GetVisitorMap.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\UserCountryMap\Widgets;
+
+use Piwik\Widget\WidgetConfig;
+
+class GetVisitorMap extends \Piwik\Widget\Widget
+{
+ public static function configure(WidgetConfig $config)
+ {
+ $config->setCategoryId('General_Visitors');
+ $config->setSubcategoryId('UserCountry_SubmenuLocations');
+ $config->setName('UserCountryMap_VisitorMap');
+ $config->setAction('visitorMap');
+ $config->setOrder(1);
+ }
+}
diff --git a/plugins/UserCountryMap/templates/visitorMap.twig b/plugins/UserCountryMap/templates/visitorMap.twig
index 7873200c9f..b5445a2cc6 100644
--- a/plugins/UserCountryMap/templates/visitorMap.twig
+++ b/plugins/UserCountryMap/templates/visitorMap.twig
@@ -86,7 +86,7 @@
if ($('#dashboardWidgetsArea').length) {
// dashboard mode
- var $widgetContent = $('.UserCountryMap').parents('.widgetContent');
+ var $widgetContent = $('.UserCountryMap').parents('.widgetContent').first();
$widgetContent.on('widget:create',function (evt, widget) {
visitorMap = new UserCountryMap.VisitorMap(config, widget);
diff --git a/plugins/UserLanguage/Reports/Base.php b/plugins/UserLanguage/Reports/Base.php
index 366521b16a..68e8a91b4b 100644
--- a/plugins/UserLanguage/Reports/Base.php
+++ b/plugins/UserLanguage/Reports/Base.php
@@ -15,6 +15,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_VisitorSettings';
+ $this->categoryId = 'General_Visitors';
+ $this->subcategoryId = 'UserCountry_SubmenuLocations';
}
}
diff --git a/plugins/UserLanguage/Reports/GetLanguage.php b/plugins/UserLanguage/Reports/GetLanguage.php
index f5babd65b8..8db3629134 100644
--- a/plugins/UserLanguage/Reports/GetLanguage.php
+++ b/plugins/UserLanguage/Reports/GetLanguage.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\UserLanguage\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\UserLanguage\Columns\Language;
+use Piwik\Plugin\Reports;
class GetLanguage extends Base
{
@@ -20,8 +21,7 @@ class GetLanguage extends Base
$this->dimension = new Language();
$this->name = Piwik::translate('UserLanguage_BrowserLanguage');
$this->documentation = ''; // TODO
- $this->order = 10;
- $this->widgetTitle = 'UserLanguage_BrowserLanguage';
+ $this->order = 8;
}
public function configureView(ViewDataTable $view)
@@ -37,7 +37,7 @@ class GetLanguage extends Base
public function getRelatedReports() {
return array(
- self::factory('UserLanguage', 'getLanguageCode'),
+ Reports::factory('UserLanguage', 'getLanguageCode'),
);
}
diff --git a/plugins/UserLanguage/Reports/GetLanguageCode.php b/plugins/UserLanguage/Reports/GetLanguageCode.php
index 0ca2c64bb2..9d9a46f201 100644
--- a/plugins/UserLanguage/Reports/GetLanguageCode.php
+++ b/plugins/UserLanguage/Reports/GetLanguageCode.php
@@ -10,6 +10,7 @@ namespace Piwik\Plugins\UserLanguage\Reports;
use Piwik\Piwik;
use Piwik\Plugins\UserLanguage\Columns\Language;
+use Piwik\Plugin\Reports;
class GetLanguageCode extends GetLanguage
{
@@ -20,13 +21,12 @@ class GetLanguageCode extends GetLanguage
$this->name = Piwik::translate('UserLanguage_LanguageCode');
$this->documentation = '';
$this->order = 11;
- $this->widgetTitle = 'UserLanguage_LanguageCode';
}
public function getRelatedReports()
{
return array(
- self::factory('UserLanguage', 'getLanguage'),
+ Reports::factory('UserLanguage', 'getLanguage'),
);
}
diff --git a/plugins/VisitFrequency/Controller.php b/plugins/VisitFrequency/Controller.php
index e1279206fd..8e6af9cffd 100644
--- a/plugins/VisitFrequency/Controller.php
+++ b/plugins/VisitFrequency/Controller.php
@@ -8,9 +8,10 @@
*/
namespace Piwik\Plugins\VisitFrequency;
-use Piwik\API\Request;
use Piwik\Common;
+use Piwik\FrontController;
use Piwik\Piwik;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Translation\Translator;
use Piwik\View;
@@ -28,31 +29,22 @@ class Controller extends \Piwik\Plugin\Controller
parent::__construct();
}
- public function index()
- {
- $view = new View('@VisitFrequency/index');
- $this->setGeneralVariablesView($view);
-
- $view->graphEvolutionVisitFrequency = $this->getEvolutionGraph(array(), array('nb_visits_returning'));
- $this->setSparklinesAndNumbers($view);
-
- return $view->render();
- }
-
+ /**
+ * @deprecated used to be a widgetized URL. There to not break widget URLs
+ */
public function getSparklines()
{
- $view = new View('@VisitFrequency/getSparklines');
- $this->setSparklinesAndNumbers($view);
- return $view->render();
+ $_GET['forceView'] = '1';
+ $_GET['viewDataTable'] = Sparklines::ID;
+
+ return FrontController::getInstance()->fetchDispatch('VisitFrequency', 'get');
}
- public function getEvolutionGraph(array $columns = array(), array $defaultColumns = array())
+ public function getEvolutionGraph()
{
- if (empty($columns)) {
- $columns = Common::getRequestVar('columns', false);
- if (false !== $columns) {
- $columns = Piwik::getArrayFromApiParameter($columns);
- }
+ $columns = Common::getRequestVar('columns', false);
+ if (false !== $columns) {
+ $columns = Piwik::getArrayFromApiParameter($columns);
}
$documentation = $this->translator->translate('VisitFrequency_ReturningVisitsDocumentation') . '<br />'
@@ -89,35 +81,10 @@ class Controller extends \Piwik\Plugin\Controller
$view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns,
$selectableColumns, $documentation);
- if (empty($view->config->columns_to_display) && !empty($defaultColumns)) {
- $view->config->columns_to_display = $defaultColumns;
+ if (empty($view->config->columns_to_display)) {
+ $view->config->columns_to_display = array('nb_visits_returning');
}
return $this->renderView($view);
}
-
- protected function setSparklinesAndNumbers($view)
- {
- $view->urlSparklineNbVisitsReturning = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_visits_returning')));
- $view->urlSparklineNbActionsReturning = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_actions_returning')));
- $view->urlSparklineActionsPerVisitReturning = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_actions_per_visit_returning')));
- $view->urlSparklineAvgVisitDurationReturning = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('avg_time_on_site_returning')));
- $view->urlSparklineBounceRateReturning = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('bounce_rate_returning')));
-
- $dataTableFrequency = $this->getSummary();
- $dataRow = $dataTableFrequency->getFirstRow();
- $nbVisitsReturning = $dataRow->getColumn('nb_visits_returning');
- $view->nbVisitsReturning = $nbVisitsReturning;
- $view->nbActionsReturning = $dataRow->getColumn('nb_actions_returning');
- $view->nbActionsPerVisitReturning = $dataRow->getColumn('nb_actions_per_visit_returning');
- $view->avgVisitDurationReturning = $dataRow->getColumn('avg_time_on_site_returning');
- $view->bounceRateReturning = $dataRow->getColumn('bounce_rate_returning');
- }
-
- protected function getSummary()
- {
- $requestString = "method=VisitFrequency.get&format=original";
- $request = new Request($requestString);
- return $request->process();
- }
}
diff --git a/plugins/VisitFrequency/Menu.php b/plugins/VisitFrequency/Menu.php
deleted file mode 100644
index e858bd2f76..0000000000
--- a/plugins/VisitFrequency/Menu.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitFrequency;
-
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addVisitorsItem('VisitFrequency_SubmenuFrequency', $this->urlForAction('index'), $order = 55);
- }
-}
diff --git a/plugins/VisitFrequency/Reports/Get.php b/plugins/VisitFrequency/Reports/Get.php
index eb4c7ddfbe..735f1cbe0f 100644
--- a/plugins/VisitFrequency/Reports/Get.php
+++ b/plugins/VisitFrequency/Reports/Get.php
@@ -9,17 +9,22 @@
namespace Piwik\Plugins\VisitFrequency\Reports;
use Piwik\Piwik;
+use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreHome\Columns\Metrics\ActionsPerVisit;
use Piwik\Plugins\CoreHome\Columns\Metrics\AverageTimeOnSite;
use Piwik\Plugins\CoreHome\Columns\Metrics\BounceRate;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Plugins\VisitFrequency\Columns\Metrics\ReturningMetric;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class Get extends \Piwik\Plugin\Report
{
protected function init()
{
parent::init();
- $this->category = 'General_Visitors';
+ $this->categoryId = 'General_Visitors';
$this->name = Piwik::translate('VisitFrequency_ColumnReturningVisits');
$this->documentation = ''; // TODO
$this->processedMetrics = array(
@@ -35,5 +40,60 @@ class Get extends \Piwik\Plugin\Report
'max_actions_returning'
);
$this->order = 40;
+ $this->subcategoryId = 'VisitorInterest_Engagement';
}
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('VisitFrequency_WidgetGraphReturning')
+ ->forceViewDataTable(Evolution::ID)
+ ->setAction('getEvolutionGraph')
+ ->setOrder(1)
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->forceViewDataTable(Sparklines::ID)
+ ->setName('VisitFrequency_WidgetOverview')
+ ->setOrder(2)
+ );
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ if ($view->isViewDataTableId(Sparklines::ID)) {
+ $view->requestConfig->apiMethodToRequestDataTable = 'VisitFrequency.get';
+ $this->addSparklineColumns($view);
+ $view->config->addTranslations($this->getSparklineTranslations());
+ }
+ }
+
+ private function getSparklineTranslations()
+ {
+ $translations = array(
+ 'nb_visits_returning' => 'ReturnVisits',
+ 'nb_actions_returning' => 'ReturnActions',
+ 'nb_actions_per_visit_returning' => 'ReturnAvgActions',
+ 'avg_time_on_site_returning' => 'ReturnAverageVisitDuration',
+ 'bounce_rate_returning' => 'ReturnBounceRate',
+ );
+
+ foreach ($translations as $metric => $key) {
+ $translations[$metric] = Piwik::translate('VisitFrequency_' . $key);
+ }
+
+ return $translations;
+ }
+
+ private function addSparklineColumns(Sparklines $view)
+ {
+ $view->config->addSparklineMetric(array('nb_visits_returning'));
+ $view->config->addSparklineMetric(array('avg_time_on_site_returning'));
+ $view->config->addSparklineMetric(array('nb_actions_per_visit_returning'));
+ $view->config->addSparklineMetric(array('bounce_rate_returning'));
+ $view->config->addSparklineMetric(array('nb_actions_returning'));
+ }
+
}
diff --git a/plugins/VisitFrequency/Widgets.php b/plugins/VisitFrequency/Widgets.php
deleted file mode 100644
index 53a5ddcd47..0000000000
--- a/plugins/VisitFrequency/Widgets.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitFrequency;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'General_Visitors';
-
- public function init()
- {
- $this->addWidget('VisitFrequency_WidgetOverview', 'getSparklines');
- $this->addWidget('VisitFrequency_WidgetGraphReturning',
- 'getEvolutionGraph',
- array('columns' => array('nb_visits_returning')));
- }
-
-}
diff --git a/plugins/VisitFrequency/lang/en.json b/plugins/VisitFrequency/lang/en.json
index d157e0a88c..39b1879852 100644
--- a/plugins/VisitFrequency/lang/en.json
+++ b/plugins/VisitFrequency/lang/en.json
@@ -12,13 +12,13 @@
"ColumnUniqueReturningVisitors": "Unique returning visitors",
"ColumnReturningUsers": "Returning Users",
"PluginDescription": "Reports metrics about your first time new visitors and returning visitors.",
- "ReturnActions": "%s actions by the returning visits",
- "ReturnAverageVisitDuration": "%s average visit duration for returning visitors",
- "ReturnAvgActions": "%s actions per returning visit",
- "ReturnBounceRate": "%s returning visits have bounced (left the website after one page)",
+ "ReturnActions": "actions by the returning visits",
+ "ReturnAverageVisitDuration": "average visit duration for returning visitors",
+ "ReturnAvgActions": "actions per returning visit",
+ "ReturnBounceRate": "returning visits have bounced (left the website after one page)",
"ReturningVisitDocumentation": "A returning visit is (as opposed to a new visit) made by someone who has visited the website at least once before.",
"ReturningVisitsDocumentation": "This is an overview of the returning visits.",
- "ReturnVisits": "%s returning visits",
+ "ReturnVisits": "returning visits",
"SubmenuFrequency": "Frequency",
"WidgetGraphReturning": "Returning Visits Over Time",
"WidgetOverview": "Frequency Overview"
diff --git a/plugins/VisitFrequency/templates/_sparklines.twig b/plugins/VisitFrequency/templates/_sparklines.twig
deleted file mode 100644
index c6c123c5e2..0000000000
--- a/plugins/VisitFrequency/templates/_sparklines.twig
+++ /dev/null
@@ -1,39 +0,0 @@
-
-{% if not isWidget %}
-<div class="row">
- <div class="col-md-6">
-{% endif %}
-
- <div class="sparkline">
- {{ sparkline(urlSparklineNbVisitsReturning) }}
- {{ 'VisitFrequency_ReturnVisits'|translate("<strong>"~nbVisitsReturning~"</strong>")|raw }}
- </div>
- <div class="sparkline">
- {{ sparkline(urlSparklineNbActionsReturning) }}
- {{ 'VisitFrequency_ReturnActions'|translate("<strong>"~nbActionsReturning~"</strong>")|raw }}
- </div>
- <div class="sparkline">
- {{ sparkline(urlSparklineActionsPerVisitReturning) }}
- {{ 'VisitFrequency_ReturnAvgActions'|translate("<strong>"~nbActionsPerVisitReturning~"</strong>")|raw }}
- </div>
-
- {% if not isWidget %}
- </div>
- <div class="col-md-6">
- {% endif %}
-
- <div class="sparkline">
- {{ sparkline(urlSparklineAvgVisitDurationReturning) }}
- {% set avgVisitDurationReturning=avgVisitDurationReturning|sumtime %}
- {{ 'VisitFrequency_ReturnAverageVisitDuration'|translate("<strong>"~avgVisitDurationReturning~"</strong>")|raw }}
- </div>
- <div class="sparkline">
- {{ sparkline(urlSparklineBounceRateReturning) }}
- {{ 'VisitFrequency_ReturnBounceRate'|translate("<strong>"~bounceRateReturning~"</strong>")|raw }}
- </div>
- {% include "_sparklineFooter.twig" %}
-
-{% if not isWidget %}
- </div>
-</div>
-{% endif %}
diff --git a/plugins/VisitFrequency/templates/getSparklines.twig b/plugins/VisitFrequency/templates/getSparklines.twig
deleted file mode 100644
index fd158c8329..0000000000
--- a/plugins/VisitFrequency/templates/getSparklines.twig
+++ /dev/null
@@ -1 +0,0 @@
-{% include "@VisitFrequency/_sparklines.twig" %} \ No newline at end of file
diff --git a/plugins/VisitFrequency/templates/index.twig b/plugins/VisitFrequency/templates/index.twig
deleted file mode 100644
index 6abd255b17..0000000000
--- a/plugins/VisitFrequency/templates/index.twig
+++ /dev/null
@@ -1,9 +0,0 @@
-{{ postEvent("Template.headerVisitsFrequency") }}
-
-<h2 piwik-enriched-headline data-graph-id="VisitFrequency.getEvolutionGraph">{{ 'VisitFrequency_ColumnReturningVisits'|translate }}</h2>
- {{ graphEvolutionVisitFrequency|raw }}
-<br/>
-
-{% include "@VisitFrequency/_sparklines.twig" %}
-
-{{ postEvent("Template.footerVisitsFrequency") }}
diff --git a/plugins/VisitTime/Categories/TimesSubcategory.php b/plugins/VisitTime/Categories/TimesSubcategory.php
new file mode 100644
index 0000000000..220a568ad3
--- /dev/null
+++ b/plugins/VisitTime/Categories/TimesSubcategory.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\VisitTime\Categories;
+
+use Piwik\Category\Subcategory;
+
+class TimesSubcategory extends Subcategory
+{
+ protected $categoryId = 'General_Visitors';
+ protected $id = 'VisitTime_SubmenuTimes';
+ protected $order = 35;
+
+}
diff --git a/plugins/VisitTime/Controller.php b/plugins/VisitTime/Controller.php
deleted file mode 100644
index 08af238213..0000000000
--- a/plugins/VisitTime/Controller.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitTime;
-
-use Piwik\View;
-
-/**
- *
- */
-class Controller extends \Piwik\Plugin\Controller
-{
- public function index()
- {
- $view = new View('@VisitTime/index');
- $view->dataTableVisitInformationPerLocalTime = $this->renderReport('getVisitInformationPerLocalTime');
- $view->dataTableVisitInformationPerServerTime = $this->renderReport('getVisitInformationPerServerTime');
- return $view->render();
- }
-}
diff --git a/plugins/VisitTime/Menu.php b/plugins/VisitTime/Menu.php
deleted file mode 100644
index ffa3a5b015..0000000000
--- a/plugins/VisitTime/Menu.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitTime;
-
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addVisitorsItem('VisitTime_SubmenuTimes', $this->urlForAction('index'), $order = 65);
- }
-}
diff --git a/plugins/VisitTime/Reports/Base.php b/plugins/VisitTime/Reports/Base.php
index 89b553cd44..2dfbf0e169 100644
--- a/plugins/VisitTime/Reports/Base.php
+++ b/plugins/VisitTime/Reports/Base.php
@@ -15,7 +15,7 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'VisitsSummary_VisitsSummary';
+ $this->categoryId = 'General_Visitors';
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/VisitTime/Reports/GetByDayOfWeek.php b/plugins/VisitTime/Reports/GetByDayOfWeek.php
index d9a3a58ee8..a93c6f21ee 100644
--- a/plugins/VisitTime/Reports/GetByDayOfWeek.php
+++ b/plugins/VisitTime/Reports/GetByDayOfWeek.php
@@ -14,6 +14,7 @@ use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
use Piwik\Plugins\VisitTime\Columns\DayOfTheWeek;
use Piwik\Period;
+use Piwik\Plugin\Reports;
use Piwik\Site;
class GetByDayOfWeek extends Base
@@ -28,7 +29,7 @@ class GetByDayOfWeek extends Base
$this->documentation = Piwik::translate('VisitTime_WidgetByDayOfWeekDocumentation');
$this->constantRowsCount = true;
$this->order = 25;
- $this->widgetTitle = 'VisitTime_VisitsByDayOfWeek';
+ $this->subcategoryId = 'VisitTime_SubmenuTimes';
}
public function configureView(ViewDataTable $view)
@@ -73,4 +74,11 @@ class GetByDayOfWeek extends Base
}
return $dateRange;
}
+
+ public function getRelatedReports()
+ {
+ return array(
+ Reports::factory('VisitTime', 'getVisitInformationPerLocalTime')
+ );
+ }
}
diff --git a/plugins/VisitTime/Reports/GetVisitInformationPerLocalTime.php b/plugins/VisitTime/Reports/GetVisitInformationPerLocalTime.php
index 6546463cd1..9372875619 100644
--- a/plugins/VisitTime/Reports/GetVisitInformationPerLocalTime.php
+++ b/plugins/VisitTime/Reports/GetVisitInformationPerLocalTime.php
@@ -13,6 +13,7 @@ use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
use Piwik\Plugins\VisitTime\Columns\LocalTime;
+use Piwik\Plugin\Reports;
class GetVisitInformationPerLocalTime extends Base
{
@@ -23,11 +24,12 @@ class GetVisitInformationPerLocalTime extends Base
{
parent::init();
$this->dimension = new LocalTime();
- $this->name = Piwik::translate('VisitTime_WidgetLocalTime');
+ $this->name = Piwik::translate('VisitTime_LocalTime');
$this->documentation = Piwik::translate('VisitTime_WidgetLocalTimeDocumentation', array('<strong>', '</strong>'));
$this->constantRowsCount = true;
- $this->order = 20;
- $this->widgetTitle = 'VisitTime_WidgetLocalTime';
+ $this->order = 15;
+
+ $this->subcategoryId = 'VisitTime_SubmenuTimes';
}
public function configureView(ViewDataTable $view)
@@ -42,10 +44,12 @@ class GetVisitInformationPerLocalTime extends Base
if ($view->isViewDataTableId(Graph::ID)) {
$view->config->max_graph_elements = false;
}
+ }
- // add the visits by day of week as a related report, if the current period is not 'day'
- if (Common::getRequestVar('period', 'day') != 'day') {
- $view->config->addRelatedReport('VisitTime.getByDayOfWeek', Piwik::translate('VisitTime_VisitsByDayOfWeek'));
- }
+ public function getRelatedReports()
+ {
+ return array(
+ Reports::factory('VisitTime', 'getByDayOfWeek')
+ );
}
}
diff --git a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
index ce213fb211..871f760046 100644
--- a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
+++ b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
@@ -22,12 +22,13 @@ class GetVisitInformationPerServerTime extends Base
{
parent::init();
$this->dimension = new ServerTime();
- $this->name = Piwik::translate('VisitTime_WidgetServerTime');
+ $this->name = Piwik::translate('VisitTime_ServerTime');
$this->documentation = Piwik::translate('VisitTime_WidgetServerTimeDocumentation', array('<strong>', '</strong>'));
$this->constantRowsCount = true;
$this->hasGoalMetrics = true;
- $this->order = 15;
- $this->widgetTitle = 'VisitTime_WidgetServerTime';
+ $this->order = 20;
+
+ $this->subcategoryId = 'VisitTime_SubmenuTimes';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/VisitTime/templates/index.twig b/plugins/VisitTime/templates/index.twig
deleted file mode 100644
index 688cde0338..0000000000
--- a/plugins/VisitTime/templates/index.twig
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="row">
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitTime_LocalTime'|translate }}</h2>
- {{ dataTableVisitInformationPerLocalTime|raw }}
- </div>
-
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitTime_ServerTime'|translate }}</h2>
- {{ dataTableVisitInformationPerServerTime|raw }}
- </div>
-
-</div>
diff --git a/plugins/VisitorInterest/Controller.php b/plugins/VisitorInterest/Controller.php
deleted file mode 100644
index 8cb5200c4d..0000000000
--- a/plugins/VisitorInterest/Controller.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitorInterest;
-
-use Piwik\View;
-
-class Controller extends \Piwik\Plugin\Controller
-{
- public function index()
- {
- $view = new View('@VisitorInterest/index');
- $view->dataTableNumberOfVisitsPerVisitDuration = $this->renderReport('getNumberOfVisitsPerVisitDuration');
- $view->dataTableNumberOfVisitsPerPage = $this->renderReport('getNumberOfVisitsPerPage');
- $view->dataTableNumberOfVisitsByVisitNum = $this->renderReport('getNumberOfVisitsByVisitCount');
- $view->dataTableNumberOfVisitsByDaysSinceLast = $this->renderReport('getNumberOfVisitsByDaysSinceLast');
- return $view->render();
- }
-} \ No newline at end of file
diff --git a/plugins/VisitorInterest/Menu.php b/plugins/VisitorInterest/Menu.php
deleted file mode 100644
index 17de395000..0000000000
--- a/plugins/VisitorInterest/Menu.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitorInterest;
-
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->rename('General_Visitors', 'VisitFrequency_SubmenuFrequency',
- 'General_Visitors', 'VisitorInterest_Engagement');
- }
-}
diff --git a/plugins/VisitorInterest/Reports/Base.php b/plugins/VisitorInterest/Reports/Base.php
index fb3f0b4a42..3381a8e805 100644
--- a/plugins/VisitorInterest/Reports/Base.php
+++ b/plugins/VisitorInterest/Reports/Base.php
@@ -12,7 +12,8 @@ abstract class Base extends \Piwik\Plugin\Report
{
protected function init()
{
- $this->category = 'General_Visitors';
+ $this->categoryId = 'General_Visitors';
+ $this->subcategoryId = 'VisitorInterest_Engagement';
}
}
diff --git a/plugins/VisitorInterest/Reports/GetNumberOfVisitsByDaysSinceLast.php b/plugins/VisitorInterest/Reports/GetNumberOfVisitsByDaysSinceLast.php
index fd935d47c6..b7b7302842 100644
--- a/plugins/VisitorInterest/Reports/GetNumberOfVisitsByDaysSinceLast.php
+++ b/plugins/VisitorInterest/Reports/GetNumberOfVisitsByDaysSinceLast.php
@@ -11,6 +11,8 @@ namespace Piwik\Plugins\VisitorInterest\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\VisitorInterest\Columns\VisitsByDaysSinceLastVisit;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetNumberOfVisitsByDaysSinceLast extends Base
{
@@ -26,7 +28,14 @@ class GetNumberOfVisitsByDaysSinceLast extends Base
$this->processedMetrics = false;
$this->constantRowsCount = true;
$this->order = 30;
- $this->widgetTitle = 'VisitorInterest_WidgetVisitsByDaysSinceLast';
+
+ $this->subcategoryId = 'VisitorInterest_Engagement';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widget = $factory->createWidget()->setName('VisitorInterest_WidgetVisitsByDaysSinceLast');
+ $widgetsList->addWidgetConfig($widget);
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/VisitorInterest/Reports/GetNumberOfVisitsByVisitCount.php b/plugins/VisitorInterest/Reports/GetNumberOfVisitsByVisitCount.php
index 74dbf69c14..d7c2a7b7e8 100644
--- a/plugins/VisitorInterest/Reports/GetNumberOfVisitsByVisitCount.php
+++ b/plugins/VisitorInterest/Reports/GetNumberOfVisitsByVisitCount.php
@@ -31,7 +31,6 @@ class GetNumberOfVisitsByVisitCount extends Base
);
$this->constantRowsCount = true;
$this->order = 25;
- $this->widgetTitle = 'VisitorInterest_visitsByVisitCount';
}
public function configureView(ViewDataTable $view)
diff --git a/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerPage.php b/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerPage.php
index de15ed5f5f..395c70da2b 100644
--- a/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerPage.php
+++ b/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerPage.php
@@ -13,6 +13,8 @@ use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
use Piwik\Plugins\VisitorInterest\Columns\PagesPerVisit;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetNumberOfVisitsPerPage extends Base
{
@@ -29,7 +31,13 @@ class GetNumberOfVisitsPerPage extends Base
$this->processedMetrics = false;
$this->constantRowsCount = true;
$this->order = 20;
- $this->widgetTitle = 'VisitorInterest_WidgetPages';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()->setName('VisitorInterest_VisitsPerNbOfPages')
+ );
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerVisitDuration.php b/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerVisitDuration.php
index ead1849b7f..8ca31b560c 100644
--- a/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerVisitDuration.php
+++ b/plugins/VisitorInterest/Reports/GetNumberOfVisitsPerVisitDuration.php
@@ -13,6 +13,8 @@ use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
use Piwik\Plugins\VisitorInterest\Columns\VisitDuration;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
class GetNumberOfVisitsPerVisitDuration extends Base
{
@@ -29,7 +31,13 @@ class GetNumberOfVisitsPerVisitDuration extends Base
$this->processedMetrics = false;
$this->constantRowsCount = true;
$this->order = 15;
- $this->widgetTitle = 'VisitorInterest_WidgetLengths';
+ }
+
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()->setName('VisitorInterest_VisitsPerDuration')
+ );
}
public function getDefaultTypeViewDataTable()
diff --git a/plugins/VisitorInterest/templates/index.twig b/plugins/VisitorInterest/templates/index.twig
deleted file mode 100644
index 332289e106..0000000000
--- a/plugins/VisitorInterest/templates/index.twig
+++ /dev/null
@@ -1,21 +0,0 @@
-<div class="row">
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsPerDuration'|translate }}</h2>
- {{ dataTableNumberOfVisitsPerVisitDuration|raw }}
- </div>
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsPerNbOfPages'|translate }}</h2>
- {{ dataTableNumberOfVisitsPerPage|raw }}
- </div>
-</div>
-
-<div class="row">
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitorInterest_visitsByVisitCount'|translate }}</h2>
- {{ dataTableNumberOfVisitsByVisitNum|raw }}
- </div>
- <div class="col-md-6">
- <h2 piwik-enriched-headline>{{ 'VisitorInterest_VisitsByDaysSinceLast'|translate }}</h2>
- {{ dataTableNumberOfVisitsByDaysSinceLast|raw }}
- </div>
-</div>
diff --git a/plugins/VisitsSummary/API.php b/plugins/VisitsSummary/API.php
index b80c505fbb..c46bd93b7b 100644
--- a/plugins/VisitsSummary/API.php
+++ b/plugins/VisitsSummary/API.php
@@ -12,6 +12,7 @@ use Piwik\Archive;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\Report;
+use Piwik\Plugin\Reports;
use Piwik\SettingsPiwik;
/**
@@ -29,7 +30,7 @@ class API extends \Piwik\Plugin\API
$requestedColumns = Piwik::getArrayFromApiParameter($columns);
- $report = Report::factory("VisitsSummary", "get");
+ $report = Reports::factory("VisitsSummary", "get");
$columns = $report->getMetricsRequiredForReport($this->getCoreColumns($period), $requestedColumns);
$dataTable = $archive->getDataTableFromNumeric($columns);
diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php
index 336ee26937..ca141b7ed8 100644
--- a/plugins/VisitsSummary/Controller.php
+++ b/plugins/VisitsSummary/Controller.php
@@ -12,8 +12,9 @@ use Piwik\API\Request;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\DataTable\Row;
+use Piwik\FrontController;
use Piwik\Piwik;
-use Piwik\Plugins\Actions\API as APIActions;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Site;
use Piwik\Translation\Translator;
use Piwik\View;
@@ -35,38 +36,32 @@ class Controller extends \Piwik\Plugin\Controller
parent::__construct();
}
- public function index()
+ /**
+ * @deprecated used to be a widgetized URL. There to not break widget URLs
+ */
+ public function getSparklines()
{
- $view = new View('@VisitsSummary/index');
- $this->setPeriodVariablesView($view);
- $view->graphEvolutionVisitsSummary = $this->getEvolutionGraph(array(), array('nb_visits'), 'getIndexGraph');
- $this->setSparklinesAndNumbers($view);
- return $view->render();
- }
+ $_GET['forceView'] = '1';
+ $_GET['viewDataTable'] = Sparklines::ID;
- // sparkline.js:81 dataTable.trigger('reload', …); does not remove the old headline,
- // so when updating this graph (such as when selecting a different metric)
- // ONLY the graph should be returned
- public function getIndexGraph()
- {
- return $this->getEvolutionGraph(array(), array(), __FUNCTION__);
+ return FrontController::getInstance()->fetchDispatch('VisitsSummary', 'get');
}
- public function getSparklines()
+ /**
+ * @deprecated used to be a widgetized URL. There to not break widget URLs
+ */
+ public function index()
{
- $view = new View('@VisitsSummary/getSparklines');
- $this->setPeriodVariablesView($view);
- $this->setSparklinesAndNumbers($view);
- return $view->render();
+ $_GET['containerId'] = 'VisitOverviewWithGraph';
+
+ return FrontController::getInstance()->fetchDispatch('CoreHome', 'renderWidgetContainer');
}
- public function getEvolutionGraph(array $columns = array(), array $defaultColumns = array(), $callingAction = __FUNCTION__)
+ public function getEvolutionGraph()
{
- if (empty($columns)) {
- $columns = Common::getRequestVar('columns', false);
- if (false !== $columns) {
- $columns = Piwik::getArrayFromApiParameter($columns);
- }
+ $columns = Common::getRequestVar('columns', false);
+ if (false !== $columns) {
+ $columns = Piwik::getArrayFromApiParameter($columns);
}
$documentation = $this->translator->translate('VisitsSummary_VisitsSummaryDocumentation') . '<br />'
@@ -116,11 +111,11 @@ class Controller extends \Piwik\Plugin\Controller
}
// $callingAction may be specified to distinguish between
// "VisitsSummary_WidgetLastVisits" and "VisitsSummary_WidgetOverviewGraph"
- $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, $callingAction, $columns,
+ $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns,
$selectableColumns, $documentation);
- if (empty($view->config->columns_to_display) && !empty($defaultColumns)) {
- $view->config->columns_to_display = $defaultColumns;
+ if (empty($view->config->columns_to_display)) {
+ $view->config->columns_to_display = array('nb_visits');
}
return $this->renderView($view);
@@ -137,87 +132,4 @@ class Controller extends \Piwik\Plugin\Controller
return empty($result) ? new DataTable() : $result;
}
-
- public static function getVisits()
- {
- $requestString = "method=VisitsSummary.getVisits" .
- "&format=original" .
- "&disable_generic_filters=1";
- $request = new Request($requestString);
- return $request->process();
- }
-
- protected function setSparklinesAndNumbers($view)
- {
- $view->urlSparklineNbVisits = $this->getUrlSparkline('getEvolutionGraph', array('columns' => $view->displayUniqueVisitors ? array('nb_visits', 'nb_uniq_visitors') : array('nb_visits')));
- $view->urlSparklineNbUsers = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_users')));
- $view->urlSparklineNbPageviews = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_pageviews', 'nb_uniq_pageviews')));
- $view->urlSparklineNbDownloads = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_downloads', 'nb_uniq_downloads')));
- $view->urlSparklineNbOutlinks = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_outlinks', 'nb_uniq_outlinks')));
- $view->urlSparklineAvgVisitDuration = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('avg_time_on_site')));
- $view->urlSparklineMaxActions = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('max_actions')));
- $view->urlSparklineActionsPerVisit = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_actions_per_visit')));
- $view->urlSparklineBounceRate = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('bounce_rate')));
- $view->urlSparklineAvgGenerationTime = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('avg_time_generation')));
-
- $idSite = Common::getRequestVar('idSite');
- $displaySiteSearch = Site::isSiteSearchEnabledFor($idSite);
- if ($displaySiteSearch) {
- $view->urlSparklineNbSearches = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_searches', 'nb_keywords')));
- }
- $view->displaySiteSearch = $displaySiteSearch;
-
- $dataTableVisit = self::getVisitsSummary();
- $dataRow = $dataTableVisit->getRowsCount() == 0 ? new Row() : $dataTableVisit->getFirstRow();
- $view->nbUniqVisitors = (int)$dataRow->getColumn('nb_uniq_visitors');
- $view->nbUsers = (int)$dataRow->getColumn('nb_users');
- $nbVisits = (int)$dataRow->getColumn('nb_visits');
- $view->nbVisits = $nbVisits;
-
- $view->averageVisitDuration = $dataRow->getColumn('avg_time_on_site');
- $view->bounceRate = $dataRow->getColumn('bounce_rate');
- $view->maxActions = (int)$dataRow->getColumn('max_actions');
- $view->nbActionsPerVisit = $dataRow->getColumn('nb_actions_per_visit');
-
- if (Common::isActionsPluginEnabled()) {
- $view->showActionsPluginReports = true;
-
- $dataTableActions = Request::processRequest("Actions.get", array(
- 'idSite' => $idSite,
- 'period' => Common::getRequestVar('period'),
- 'date' => Common::getRequestVar('date'),
- 'segment' => Request::getRawSegmentFromRequest()
- ), $defaultParams = array());
-
- $dataActionsRow =
- $dataTableActions->getRowsCount() == 0 ? new Row() : $dataTableActions->getFirstRow();
-
- $view->nbPageviews = (int)$dataActionsRow->getColumn('nb_pageviews');
- $view->nbUniquePageviews = (int)$dataActionsRow->getColumn('nb_uniq_pageviews');
- $view->nbDownloads = (int)$dataActionsRow->getColumn('nb_downloads');
- $view->nbUniqueDownloads = (int)$dataActionsRow->getColumn('nb_uniq_downloads');
- $view->nbOutlinks = (int)$dataActionsRow->getColumn('nb_outlinks');
- $view->nbUniqueOutlinks = (int)$dataActionsRow->getColumn('nb_uniq_outlinks');
- $view->averageGenerationTime = $dataActionsRow->getColumn('avg_time_generation');
-
- if ($displaySiteSearch) {
- $view->nbSearches = (int)$dataActionsRow->getColumn('nb_searches');
- $view->nbKeywords = (int)$dataActionsRow->getColumn('nb_keywords');
- }
-
- // backward compatibility:
- // show actions if the finer metrics are not archived
- $view->showOnlyActions = false;
- if ($dataActionsRow->getColumn('nb_pageviews')
- + $dataActionsRow->getColumn('nb_downloads')
- + $dataActionsRow->getColumn('nb_outlinks') == 0
- && $dataRow->getColumn('nb_actions') > 0
- ) {
- $view->showOnlyActions = true;
- $view->nbActions = $dataRow->getColumn('nb_actions');
- $view->urlSparklineNbActions = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array('nb_actions')));
- }
- }
-
- }
}
diff --git a/plugins/VisitsSummary/Menu.php b/plugins/VisitsSummary/Menu.php
deleted file mode 100644
index 1b87e46be9..0000000000
--- a/plugins/VisitsSummary/Menu.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitsSummary;
-
-use Piwik\Menu\MenuReporting;
-
-class Menu extends \Piwik\Plugin\Menu
-{
- public function configureReportingMenu(MenuReporting $menu)
- {
- $menu->addVisitorsItem('', array('module' => 'VisitsSummary', 'action' => 'index'), 10);
- $menu->addVisitorsItem('General_Overview', array('module' => 'VisitsSummary', 'action' => 'index'), 1);
- }
-}
diff --git a/plugins/VisitsSummary/Reports/Get.php b/plugins/VisitsSummary/Reports/Get.php
index 55696873be..7fb95d2950 100644
--- a/plugins/VisitsSummary/Reports/Get.php
+++ b/plugins/VisitsSummary/Reports/Get.php
@@ -8,11 +8,23 @@
*/
namespace Piwik\Plugins\VisitsSummary\Reports;
+use Piwik\Common;
+use Piwik\Container\StaticContainer;
+use Piwik\DataTable;
use Piwik\DataTable\DataTableInterface;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
+use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreHome\Columns\Metrics\ActionsPerVisit;
use Piwik\Plugins\CoreHome\Columns\Metrics\AverageTimeOnSite;
use Piwik\Plugins\CoreHome\Columns\Metrics\BounceRate;
+use Piwik\Plugins\CoreHome\Columns\UserId;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\SettingsPiwik;
+use Piwik\Site;
+use Piwik\Widget\WidgetsList;
class Get extends \Piwik\Plugin\Report
{
@@ -21,7 +33,7 @@ class Get extends \Piwik\Plugin\Report
protected function init()
{
parent::init();
- $this->category = 'VisitsSummary_VisitsSummary';
+ $this->categoryId = 'General_Visitors';
$this->name = Piwik::translate('VisitsSummary_VisitsSummary');
$this->documentation = ''; // TODO
$this->processedMetrics = array(
@@ -36,12 +48,145 @@ class Get extends \Piwik\Plugin\Report
'nb_actions',
'max_actions'
);
+ $this->subcategoryId = 'General_Overview';
// Used to process metrics, not displayed/used directly
// 'sum_visit_length',
// 'nb_visits_converted',
$this->order = 1;
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('VisitsSummary_WidgetLastVisits')
+ ->forceViewDataTable(Evolution::ID)
+ ->setAction('getEvolutionGraph')
+ ->setOrder(5)
+ );
+
+ $widgetsList->addWidgetConfig(
+ $factory->createWidget()
+ ->setName('VisitsSummary_WidgetVisits')
+ ->forceViewDataTable(Sparklines::ID)
+ ->setOrder(10)
+ );
+ }
+
+ public function configureView(ViewDataTable $view)
+ {
+ if ($view->isViewDataTableId(Sparklines::ID)) {
+ /** @var Sparklines $view */
+ $view->requestConfig->apiMethodToRequestDataTable = 'API.get';
+ $this->addSparklineColumns($view);
+ $view->config->addTranslations($this->getSparklineTranslations());
+ $view->config->filters[] = function (DataTable $table) use ($view) {
+ $firstRow = $table->getFirstRow();
+
+ if (($firstRow->getColumn('nb_pageviews')
+ + $firstRow->getColumn('nb_downloads')
+ + $firstRow->getColumn('nb_outlinks')) == 0
+ && $firstRow->getColumn('nb_actions') > 0) {
+ $view->config->removeSparklineMetric(array('nb_downloads', 'nb_uniq_downloads'));
+ $view->config->removeSparklineMetric(array('nb_outlinks', 'nb_uniq_outlinks'));
+ $view->config->removeSparklineMetric(array('nb_pageviews', 'nb_uniq_pageviews'));
+ $view->config->removeSparklineMetric(array('nb_searches', 'nb_keywords'));
+ } else {
+ $view->config->removeSparklineMetric(array('nb_actions'));
+ }
+
+ $nbUsers = $firstRow->getColumn('nb_users');
+ if (!is_numeric($nbUsers) || 0 >= $nbUsers) {
+ $view->config->replaceSparklineMetric(array('nb_users'), '');
+ }
+
+ $avgGenerationTime = $firstRow->getColumn('avg_time_generation');
+ if (false === $avgGenerationTime) {
+ // fix avgGenerationTime is not formatted if value is false
+ /** @var Formatter $formatter */
+ $formatter = StaticContainer::get('Piwik\Metrics\Formatter');
+ $avgGenerationTime = $formatter->getPrettyTimeFromSeconds($avgGenerationTime, true);
+ $firstRow->setColumn('avg_time_generation', $avgGenerationTime);
+ }
+ };
+ }
+ }
+
+ private function getSparklineTranslations()
+ {
+ $translations = array(
+ 'nb_actions' => 'NbActionsDescription',
+ 'nb_visits' => 'NbVisitsDescription',
+ 'nb_users' => 'NbUsersDescription',
+ 'nb_uniq_visitors' => 'NbUniqueVisitors',
+ 'avg_time_generation' => 'AverageGenerationTime',
+ 'avg_time_on_site' => 'AverageVisitDuration',
+ 'max_actions' => 'MaxNbActions',
+ 'nb_actions_per_visit' => 'NbActionsPerVisit',
+ 'nb_downloads' => 'NbDownloadsDescription',
+ 'nb_uniq_downloads' => 'NbUniqueDownloadsDescription',
+ 'nb_outlinks' => 'NbOutlinksDescription',
+ 'nb_uniq_outlinks' => 'NbUniqueOutlinksDescription',
+ 'nb_keywords' => 'NbKeywordsDescription',
+ 'nb_searches' => 'NbSearchesDescription',
+ 'nb_pageviews' => 'NbPageviewsDescription',
+ 'nb_uniq_pageviews' => 'NbUniquePageviewsDescription',
+ 'bounce_rate' => 'NbVisitsBounced',
+ );
+
+ foreach ($translations as $metric => $key) {
+ $translations[$metric] = Piwik::translate('VisitsSummary_' . $key);
+ }
+
+ return $translations;
+ }
+
+ private function addSparklineColumns(Sparklines $view)
+ {
+ $currentPeriod = Common::getRequestVar('period');
+ $currentIdSite = Common::getRequestVar('idSite');
+ $currentDate = Common::getRequestVar('date');
+ $displayUniqueVisitors = SettingsPiwik::isUniqueVisitorsEnabled($currentPeriod);
+
+ $isActionPluginEnabled = Common::isActionsPluginEnabled();
+
+ $view->config->addSparklineMetric($displayUniqueVisitors ? array('nb_visits', 'nb_uniq_visitors') : array('nb_visits'), 5);
+
+ if ($isActionPluginEnabled) {
+ $view->config->addSparklineMetric(array('nb_actions'), 10); // either actions or pageviews will be displayed
+ $view->config->addSparklineMetric(array('nb_pageviews', 'nb_uniq_pageviews'), 20);
+ } else {
+ // make sure to still create a div on the right side for this, just leave it empty
+ $view->config->addPlaceholder(10);
+ }
+
+ $userId = new UserId();
+ if ($userId->isUsedInAtLeastOneSite($currentIdSite, $currentPeriod, $currentDate)) {
+ $view->config->addSparklineMetric(array('nb_users'), 30);
+ $view->config->addPlaceholder(31);
+ }
+
+ $view->config->addSparklineMetric(array('avg_time_on_site'), 40);
+
+ $idSite = Common::getRequestVar('idSite');
+ if ($isActionPluginEnabled && Site::isSiteSearchEnabledFor($idSite)) {
+ $view->config->addSparklineMetric(array('nb_searches', 'nb_keywords'), 50);
+ } else {
+ // make sure to still create a div on the right side for this, just leave it empty
+ $view->config->addPlaceholder(50);
+ }
+
+ $view->config->addSparklineMetric(array('bounce_rate'), 60);
+
+ if ($isActionPluginEnabled) {
+ $view->config->addSparklineMetric(array('nb_downloads', 'nb_uniq_downloads'), 70);
+ $view->config->addSparklineMetric(array('nb_actions_per_visit'), 71);
+ $view->config->addSparklineMetric(array('nb_outlinks', 'nb_uniq_outlinks'), 72);
+ $view->config->addSparklineMetric(array('avg_time_generation'), 73);
+ $view->config->addSparklineMetric(array('max_actions'), 74);
+ }
+ }
+
public function getMetrics()
{
$metrics = parent::getMetrics();
diff --git a/plugins/VisitsSummary/Widgets.php b/plugins/VisitsSummary/Widgets.php
deleted file mode 100644
index 5ec7eef56e..0000000000
--- a/plugins/VisitsSummary/Widgets.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Plugins\VisitsSummary;
-
-class Widgets extends \Piwik\Plugin\Widgets
-{
- protected $category = 'VisitsSummary_VisitsSummary';
-
- public function init()
- {
- $this->addWidget('VisitsSummary_WidgetLastVisits', 'getEvolutionGraph', array('columns' => array('nb_visits')));
- $this->addWidget('VisitsSummary_WidgetVisits', 'getSparklines');
- $this->addWidget('VisitsSummary_WidgetOverviewGraph', 'index');
- }
-
-}
diff --git a/plugins/VisitsSummary/Widgets/Index.php b/plugins/VisitsSummary/Widgets/Index.php
new file mode 100644
index 0000000000..1b39fad7c6
--- /dev/null
+++ b/plugins/VisitsSummary/Widgets/Index.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\VisitsSummary\Widgets;
+
+use Piwik\Plugin\Report;
+use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
+use Piwik\Plugin\Reports;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
+
+class Index extends \Piwik\Widget\WidgetContainerConfig
+{
+ protected $categoryId = 'General_Visitors';
+ protected $name = 'VisitsSummary_WidgetOverviewGraph';
+ protected $id = 'VisitOverviewWithGraph';
+ protected $isWidgetizable = true;
+
+ public function isEnabled()
+ {
+ return Reports::factory('VisitsSummary', 'get')->isEnabled();
+ }
+
+ public function getWidgetConfigs()
+ {
+ $report = Reports::factory('VisitsSummary', 'get');
+
+ $factory = new ReportWidgetFactory($report);
+ $widgets = array();
+
+ $list = new WidgetsList();
+ $report->configureWidgets($list, $factory);
+
+ foreach ($list->getWidgetConfigs() as $config) {
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
+ }
+
+ return $widgets;
+ }
+}
diff --git a/plugins/VisitsSummary/lang/en.json b/plugins/VisitsSummary/lang/en.json
index e4a46bc5ae..fc9d3c4777 100644
--- a/plugins/VisitsSummary/lang/en.json
+++ b/plugins/VisitsSummary/lang/en.json
@@ -1,22 +1,24 @@
{
"VisitsSummary": {
- "AverageGenerationTime": "%s average generation time",
- "AverageVisitDuration": "%s average visit duration",
+ "AverageGenerationTime": "average generation time",
+ "AverageVisitDuration": "average visit duration",
"GenerateQueries": "%s queries executed",
"GenerateTime": "%s seconds to generate the page",
- "MaxNbActions": "%s max actions in one visit",
+ "MaxNbActions": "max actions in one visit",
"NbActionsDescription": "%s actions",
- "NbActionsPerVisit": "%s actions (page views, downloads, outlinks and internal site searches) per visit",
- "NbDownloadsDescription": "%s downloads",
- "NbKeywordsDescription": "%s unique keywords",
- "NbOutlinksDescription": "%s outlinks",
- "NbPageviewsDescription": "%s pageviews",
- "NbSearchesDescription": "%s total searches on your website",
- "NbUniqueDownloadsDescription": "%s unique downloads",
- "NbUniqueOutlinksDescription": "%s unique outlinks",
- "NbUniquePageviewsDescription": "%s unique pageviews",
- "NbUniqueVisitors": "%s unique visitors",
- "NbVisitsBounced": "%s visits have bounced (left the website after one page)",
+ "NbActionsPerVisit": "actions (page views, downloads, outlinks and internal site searches) per visit",
+ "NbDownloadsDescription": "downloads",
+ "NbKeywordsDescription": "unique keywords",
+ "NbOutlinksDescription": "outlinks",
+ "NbPageviewsDescription": "pageviews",
+ "NbSearchesDescription": "total searches on your website",
+ "NbUniqueDownloadsDescription": "unique downloads",
+ "NbUniqueOutlinksDescription": "unique outlinks",
+ "NbUniquePageviewsDescription": "unique pageviews",
+ "NbUniqueVisitors": "unique visitors",
+ "NbUsersDescription": "users",
+ "NbVisitsDescription": "visits",
+ "NbVisitsBounced": "visits have bounced (left the website after one page)",
"PluginDescription": "Reports general analytics metrics: visits, unique visitors, number of actions, bounce rate, etc.",
"VisitsSummary": "Visits Summary",
"VisitsSummaryDocumentation": "This is an overview of the visit evolution.",
diff --git a/plugins/Widgetize/Controller.php b/plugins/Widgetize/Controller.php
index 2e2e5bf8cb..cf6cb5114a 100644
--- a/plugins/Widgetize/Controller.php
+++ b/plugins/Widgetize/Controller.php
@@ -12,7 +12,6 @@ use Piwik\API\Request;
use Piwik\Common;
use Piwik\FrontController;
use Piwik\View;
-use Piwik\WidgetsList;
/**
*
@@ -22,7 +21,6 @@ class Controller extends \Piwik\Plugin\Controller
public function index()
{
$view = new View('@Widgetize/index');
- $view->availableWidgets = json_encode(WidgetsList::get());
$this->setGeneralVariablesView($view);
return $view->render();
}
@@ -35,7 +33,7 @@ class Controller extends \Piwik\Plugin\Controller
$controllerName = Common::getRequestVar('moduleToWidgetize');
$actionName = Common::getRequestVar('actionToWidgetize');
- if($controllerName == 'API') {
+ if ($controllerName == 'API') {
throw new \Exception("Widgetizing API requests is not supported for security reasons. Please change query parameter 'moduleToWidgetize'.");
}
diff --git a/plugins/Widgetize/templates/iframe.twig b/plugins/Widgetize/templates/iframe.twig
index ce40bdb940..892960316a 100644
--- a/plugins/Widgetize/templates/iframe.twig
+++ b/plugins/Widgetize/templates/iframe.twig
@@ -17,6 +17,7 @@
<!--[if (gte IE 9)|!(IE)]><!-->
<body ng-app="app">
<![endif]-->
+ <div piwik-popover-handler></div>
<div class="widget">
{{ content|raw }}
</div>
diff --git a/plugins/Widgetize/templates/index.twig b/plugins/Widgetize/templates/index.twig
index 49a2b5f6c1..a798723928 100644
--- a/plugins/Widgetize/templates/index.twig
+++ b/plugins/Widgetize/templates/index.twig
@@ -24,7 +24,6 @@
$('#widgetPreview').widgetPreview({
onPreviewLoaded: widgetized.callbackAddExportButtonsUnderWidget
});
- broadcast.init();
});
</script>
diff --git a/plugins/Widgetize/tests/System/WidgetTest.php b/plugins/Widgetize/tests/System/WidgetTest.php
index d2d6ec3260..2425ed3c9a 100644
--- a/plugins/Widgetize/tests/System/WidgetTest.php
+++ b/plugins/Widgetize/tests/System/WidgetTest.php
@@ -11,10 +11,11 @@ namespace Piwik\Plugins\Widgetize\tests\Integration;
use Piwik\Container\StaticContainer;
use Piwik\Http\ControllerResolver;
use Piwik\Piwik;
+use Piwik\Plugins\API;
use Piwik\Plugins\Goals;
use Piwik\Plugins\Widgetize\tests\Fixtures\WidgetizeFixture;
use Piwik\Tests\Framework\TestCase\SystemTestCase;
-use Piwik\WidgetsList;
+use Piwik\Widget\WidgetsList;
/**
* @group Widgetize
@@ -35,7 +36,7 @@ class WidgetTest extends SystemTestCase
$_GET = array();
$_GET['idSite'] = self::$fixture->idSite;
$_GET['period'] = 'year';
- $_GET['date'] = 'today';
+ $_GET['date'] = '2013-01-23';
}
public function tearDown()
@@ -44,28 +45,35 @@ class WidgetTest extends SystemTestCase
parent::tearDown();
}
+ public function test_allWidgetUniqueIdsAreActuallyUnique()
+ {
+ $uniqueIds = array();
+ foreach (WidgetsList::get()->getWidgetConfigs() as $widget) {
+ $uniqueIds[] = $widget->getUniqueId();
+ }
+
+ $this->assertEquals(array_unique($uniqueIds), $uniqueIds);
+ }
+
public function test_AvailableWidgetListIsUpToDate()
{
- $namesOfWidgetsThatAreAPI = $this->getWidgetNames($this->getWidgetsThatAreAPI());
+ $namesOfWidgetsThatAreAPI = array_map(function ($widget) {
+ return $widget['uniqueId'];
+ }, $this->getWidgetsThatAreAPICurrently());
Piwik::postEvent('Platform.initialized'); // userCountryMap defines it's Widgets via this event currently
- $currentWidgetNames = array();
- foreach (WidgetsList::get() as $widgets) {
- $currentWidgetNames = array_merge($this->getWidgetNames($widgets), $currentWidgetNames);
- }
+ $widgets = API\API::getInstance()->getWidgetMetadata($_GET['idSite']);
- $allWidgetNames = array_merge($namesOfWidgetsThatAreAPI, $currentWidgetNames);
- $regressedWidgetNames = array_diff($allWidgetNames, $currentWidgetNames);
+ $currentUniqueIds = array();
+ foreach ($widgets as $widget) {
+ $currentUniqueIds[] = $widget['uniqueId'];
+ }
- $this->assertEmpty($regressedWidgetNames, 'The widgets list is no longer up to date. If you added, removed or renamed a widget please update `getAvailableWidgets()` otherwise you will need to fix it. Different names: ' . var_export($regressedWidgetNames, 1));
- }
+ $allWidgetNames = array_merge($namesOfWidgetsThatAreAPI, $currentUniqueIds);
+ $regressedWidgetIds = array_diff($allWidgetNames, $currentUniqueIds);
- private function getWidgetNames($widgets)
- {
- return array_map(function ($widget) {
- return $widget['name'];
- }, $widgets);
+ $this->assertEmpty($regressedWidgetIds, 'The widgets list is no longer up to date. If you added or changed a widget please update `getWidgetsThatAreAPICurrently()`, if you removed a widget please add it to `getWidgetsThatAreDeprecatedButStillAPI()`. If the uniqueId changed you might need to create an update for Dashboards and Scheduled Reports! Different names: ' . var_export($regressedWidgetIds, 1));
}
/**
@@ -78,7 +86,8 @@ class WidgetTest extends SystemTestCase
$params = $widget['parameters'];
$parameters = array();
- $resolver = new ControllerResolver(StaticContainer::getContainer());
+ /** @var ControllerResolver $resolver */
+ $resolver = StaticContainer::get('Piwik\Http\ControllerResolver');
$controller = $resolver->getController($params['module'], $params['action'], $parameters);
$this->assertNotEmpty($controller, $widget['name'] . ' is not renderable with following params: ' . json_encode($params) . '. This breaks the API, please make sure to keep the URL working');
@@ -86,11 +95,15 @@ class WidgetTest extends SystemTestCase
public function availableWidgetsProvider()
{
- $widgets = $this->getWidgetsThatAreAPI();
-
$data = array();
- foreach ($widgets as $widget) {
+ foreach ($this->getWidgetsThatAreAPICurrently() as $widget) {
+ if (!empty($widget)) {
+ $data[] = array($widget);
+ }
+ }
+
+ foreach ($this->getWidgetsThatAreDeprecatedButStillAPI() as $widget) {
if (!empty($widget)) {
$data[] = array($widget);
}
@@ -99,746 +112,1163 @@ class WidgetTest extends SystemTestCase
return $data;
}
+ public function getWidgetsThatAreAPICurrently()
+ {
+ return array(
+ array (
+ 'name' => 'Visits Overview (with graph)',
+ 'uniqueId' => 'widgetVisitOverviewWithGraph',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'VisitOverviewWithGraph',
+ ),
+ ),array (
+ 'name' => 'Support Piwik!',
+ 'uniqueId' => 'widgetCoreHomegetDonateForm',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'getDonateForm',
+ ),
+ ),array (
+ 'name' => 'Welcome!',
+ 'uniqueId' => 'widgetCoreHomegetPromoVideo',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'getPromoVideo',
+ ),
+ ),array (
+ 'name' => 'Example Widget Name',
+ 'uniqueId' => 'widgetExamplePluginmyExampleWidget',
+ 'parameters' =>
+ array (
+ 'module' => 'ExamplePlugin',
+ 'action' => 'myExampleWidget',
+ ),
+ ),array (
+ 'name' => 'Top Keywords for Page URL',
+ 'uniqueId' => 'widgetReferrersgetKeywordsForPage',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getKeywordsForPage',
+ ),
+ ),array (
+ 'name' => 'Ecommerce Log',
+ 'uniqueId' => 'widgetEcommercegetEcommerceLog',
+ 'parameters' =>
+ array (
+ 'module' => 'Ecommerce',
+ 'action' => 'getEcommerceLog',
+ ),
+ ),array (
+ 'name' => 'SEO Rankings',
+ 'uniqueId' => 'widgetSEOgetRank',
+ 'parameters' =>
+ array (
+ 'module' => 'SEO',
+ 'action' => 'getRank',
+ ),
+ ),array (
+ 'name' => 'Piwik Changelog',
+ 'uniqueId' => 'widgetExampleRssWidgetrssChangelog',
+ 'parameters' =>
+ array (
+ 'module' => 'ExampleRssWidget',
+ 'action' => 'rssChangelog',
+ ),
+ ),array (
+ 'name' => 'Piwik.org Blog',
+ 'uniqueId' => 'widgetExampleRssWidgetrssPiwik',
+ 'parameters' =>
+ array (
+ 'module' => 'ExampleRssWidget',
+ 'action' => 'rssPiwik',
+ ),
+ ),array (
+ 'name' => 'Real-time Map',
+ 'uniqueId' => 'widgetUserCountryMaprealtimeMap',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountryMap',
+ 'action' => 'realtimeMap',
+ ),
+ ),array (
+ 'name' => 'Visitor Map',
+ 'uniqueId' => 'widgetUserCountryMapvisitorMap',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountryMap',
+ 'action' => 'visitorMap',
+ ),
+ ),array (
+ 'name' => 'Visitor profile',
+ 'uniqueId' => 'widgetLivegetVisitorProfilePopup',
+ 'parameters' =>
+ array (
+ 'module' => 'Live',
+ 'action' => 'getVisitorProfilePopup',
+ ),
+ ),array (
+ 'name' => 'Visitors in Real-time',
+ 'uniqueId' => 'widgetLivewidget',
+ 'parameters' =>
+ array (
+ 'module' => 'Live',
+ 'action' => 'widget',
+ ),
+ ),array (
+ 'name' => 'Insights Overview',
+ 'uniqueId' => 'widgetInsightsgetInsightsOverview',
+ 'parameters' =>
+ array (
+ 'module' => 'Insights',
+ 'action' => 'getInsightsOverview',
+ ),
+ ),array (
+ 'name' => 'Movers and Shakers',
+ 'uniqueId' => 'widgetInsightsgetOverallMoversAndShakers',
+ 'parameters' =>
+ array (
+ 'module' => 'Insights',
+ 'action' => 'getOverallMoversAndShakers',
+ ),
+ ),array (
+ 'name' => 'Real Time Visitor Count',
+ 'uniqueId' => 'widgetLivegetSimpleLastVisitCount',
+ 'parameters' =>
+ array (
+ 'module' => 'Live',
+ 'action' => 'getSimpleLastVisitCount',
+ ),
+ ),array (
+ 'name' => 'Visits Over Time',
+ 'uniqueId' => 'widgetVisitsSummarygetEvolutionGraphforceView1viewDataTablegraphEvolution',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'graphEvolution',
+ 'module' => 'VisitsSummary',
+ 'action' => 'getEvolutionGraph',
+ ),
+ ),array (
+ 'name' => 'Visits Overview',
+ 'uniqueId' => 'widgetVisitsSummarygetforceView1viewDataTablesparklines',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'sparklines',
+ 'module' => 'VisitsSummary',
+ 'action' => 'get',
+ ),
+ ),array (
+ 'name' => 'Visitor Log',
+ 'uniqueId' => 'widgetLivegetLastVisitsDetailsforceView1viewDataTablePiwik%5CPlugins%5CLive%5CVisitorLogsmall1',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'Piwik\\Plugins\\Live\\VisitorLog',
+ 'module' => 'Live',
+ 'action' => 'getLastVisitsDetails',
+ 'small' => 1,
+ ),
+ ),array (
+ 'name' => 'Custom Variables',
+ 'uniqueId' => 'widgetCustomVariablesgetCustomVariables',
+ 'parameters' =>
+ array (
+ 'module' => 'CustomVariables',
+ 'action' => 'getCustomVariables',
+ ),
+ ),array (
+ 'name' => 'Device type',
+ 'uniqueId' => 'widgetDevicesDetectiongetType',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getType',
+ ),
+ ),array (
+ 'name' => 'Device model',
+ 'uniqueId' => 'widgetDevicesDetectiongetModel',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getModel',
+ ),
+ ),array (
+ 'name' => 'Device brand',
+ 'uniqueId' => 'widgetDevicesDetectiongetBrand',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getBrand',
+ ),
+ ),array (
+ 'name' => 'Screen Resolution',
+ 'uniqueId' => 'widgetResolutiongetResolution',
+ 'parameters' =>
+ array (
+ 'module' => 'Resolution',
+ 'action' => 'getResolution',
+ ),
+ ),array (
+ 'name' => 'Operating System versions',
+ 'uniqueId' => 'widgetDevicesDetectiongetOsVersions',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getOsVersions',
+ ),
+ ),array (
+ 'name' => 'Browsers',
+ 'uniqueId' => 'widgetDevicesDetectiongetBrowsers',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getBrowsers',
+ ),
+ ),array (
+ 'name' => 'Browser version',
+ 'uniqueId' => 'widgetDevicesDetectiongetBrowserVersions',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getBrowserVersions',
+ ),
+ ),array (
+ 'name' => 'Configurations',
+ 'uniqueId' => 'widgetResolutiongetConfiguration',
+ 'parameters' =>
+ array (
+ 'module' => 'Resolution',
+ 'action' => 'getConfiguration',
+ ),
+ ),array (
+ 'name' => 'Operating System families',
+ 'uniqueId' => 'widgetDevicesDetectiongetOsFamilies',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getOsFamilies',
+ ),
+ ),array (
+ 'name' => 'Browser engines',
+ 'uniqueId' => 'widgetDevicesDetectiongetBrowserEnginesviewDataTablegraphPie',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphPie',
+ 'module' => 'DevicesDetection',
+ 'action' => 'getBrowserEngines',
+ ),
+ ),array (
+ 'name' => 'Browser Plugins',
+ 'uniqueId' => 'widgetDevicePluginsgetPlugin',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicePlugins',
+ 'action' => 'getPlugin',
+ ),
+ ),array (
+ 'name' => 'Country',
+ 'uniqueId' => 'widgetUserCountrygetCountry',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountry',
+ 'action' => 'getCountry',
+ ),
+ ),array (
+ 'name' => 'Region',
+ 'uniqueId' => 'widgetUserCountrygetRegion',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountry',
+ 'action' => 'getRegion',
+ ),
+ ),array (
+ 'name' => 'Browser language',
+ 'uniqueId' => 'widgetUserLanguagegetLanguage',
+ 'parameters' =>
+ array (
+ 'module' => 'UserLanguage',
+ 'action' => 'getLanguage',
+ ),
+ ),array (
+ 'name' => 'City',
+ 'uniqueId' => 'widgetUserCountrygetCity',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountry',
+ 'action' => 'getCity',
+ ),
+ ),array (
+ 'name' => 'Language code',
+ 'uniqueId' => 'widgetUserLanguagegetLanguageCode',
+ 'parameters' =>
+ array (
+ 'module' => 'UserLanguage',
+ 'action' => 'getLanguageCode',
+ ),
+ ),array (
+ 'name' => 'Visits per visit duration',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerVisitDurationviewDataTablecloud',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'cloud',
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsPerVisitDuration',
+ ),
+ ),array (
+ 'name' => 'Visits per number of pages',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerPageviewDataTablecloud',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'cloud',
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsPerPage',
+ ),
+ ),array (
+ 'name' => 'Visits by Visit Number',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsByVisitCount',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsByVisitCount',
+ ),
+ ),array (
+ 'name' => 'Visits by Days Since Last Visit',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsByDaysSinceLast',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsByDaysSinceLast',
+ ),
+ ),array (
+ 'name' => 'Returning Visits Over Time',
+ 'uniqueId' => 'widgetVisitFrequencygetEvolutionGraphforceView1viewDataTablegraphEvolution',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'graphEvolution',
+ 'module' => 'VisitFrequency',
+ 'action' => 'getEvolutionGraph',
+ ),
+ ),array (
+ 'name' => 'Frequency Overview',
+ 'uniqueId' => 'widgetVisitFrequencygetforceView1viewDataTablesparklines',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'sparklines',
+ 'module' => 'VisitFrequency',
+ 'action' => 'get',
+ ),
+ ),array (
+ 'name' => 'Visits per local time',
+ 'uniqueId' => 'widgetVisitTimegetVisitInformationPerLocalTimeviewDataTablegraphVerticalBar',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphVerticalBar',
+ 'module' => 'VisitTime',
+ 'action' => 'getVisitInformationPerLocalTime',
+ ),
+ ),array (
+ 'name' => 'Visits per server time',
+ 'uniqueId' => 'widgetVisitTimegetVisitInformationPerServerTimeviewDataTablegraphVerticalBar',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphVerticalBar',
+ 'module' => 'VisitTime',
+ 'action' => 'getVisitInformationPerServerTime',
+ ),
+ ),array (
+ 'name' => 'Visits by Day of Week',
+ 'uniqueId' => 'widgetVisitTimegetByDayOfWeekviewDataTablegraphVerticalBar',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphVerticalBar',
+ 'module' => 'VisitTime',
+ 'action' => 'getByDayOfWeek',
+ ),
+ ),array (
+ 'name' => 'Pages',
+ 'uniqueId' => 'widgetActionsgetPageUrls',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getPageUrls',
+ ),
+ ),array (
+ 'name' => 'Entry pages',
+ 'uniqueId' => 'widgetActionsgetEntryPageUrls',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getEntryPageUrls',
+ ),
+ ),array (
+ 'name' => 'Exit pages',
+ 'uniqueId' => 'widgetActionsgetExitPageUrls',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getExitPageUrls',
+ ),
+ ),array (
+ 'name' => 'Page titles',
+ 'uniqueId' => 'widgetActionsgetPageTitles',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getPageTitles',
+ ),
+ ),array (
+ 'name' => 'Site Search Keywords',
+ 'uniqueId' => 'widgetActionsgetSiteSearchKeywords',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getSiteSearchKeywords',
+ ),
+ ),array (
+ 'name' => 'Pages Following a Site Search',
+ 'uniqueId' => 'widgetActionsgetPageUrlsFollowingSiteSearch',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getPageUrlsFollowingSiteSearch',
+ ),
+ ),array (
+ 'name' => 'Search Keywords with No Results',
+ 'uniqueId' => 'widgetActionsgetSiteSearchNoResultKeywords',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getSiteSearchNoResultKeywords',
+ ),
+ ),array (
+ 'name' => 'Page Titles Following a Site Search',
+ 'uniqueId' => 'widgetActionsgetPageTitlesFollowingSiteSearch',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getPageTitlesFollowingSiteSearch',
+ ),
+ ),array (
+ 'name' => 'Search Categories',
+ 'uniqueId' => 'widgetActionsgetSiteSearchCategories',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getSiteSearchCategories',
+ ),
+ ),array (
+ 'name' => 'Outlinks',
+ 'uniqueId' => 'widgetActionsgetOutlinks',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getOutlinks',
+ ),
+ ),array (
+ 'name' => 'Downloads',
+ 'uniqueId' => 'widgetActionsgetDownloads',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getDownloads',
+ ),
+ ),array (
+ 'name' => 'Entry Page Titles',
+ 'uniqueId' => 'widgetActionsgetEntryPageTitles',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getEntryPageTitles',
+ ),
+ ),array (
+ 'name' => 'Exit page titles',
+ 'uniqueId' => 'widgetActionsgetExitPageTitles',
+ 'parameters' =>
+ array (
+ 'module' => 'Actions',
+ 'action' => 'getExitPageTitles',
+ ),
+ ),array (
+ 'name' => 'Referrer Types',
+ 'uniqueId' => 'widgetReferrersgetReferrerTypeviewDataTabletableAllColumns',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'tableAllColumns',
+ 'module' => 'Referrers',
+ 'action' => 'getReferrerType',
+ ),
+ ),array (
+ 'name' => 'Referrers',
+ 'uniqueId' => 'widgetReferrersgetAllviewDataTabletableAllColumns',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'tableAllColumns',
+ 'module' => 'Referrers',
+ 'action' => 'getAll',
+ ),
+ ),array (
+ 'name' => 'Keywords',
+ 'uniqueId' => 'widgetReferrersgetKeywords',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getKeywords',
+ ),
+ ),array (
+ 'name' => 'Search Engines',
+ 'uniqueId' => 'widgetReferrersgetSearchEngines',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getSearchEngines',
+ ),
+ ),array (
+ 'name' => 'Websites',
+ 'uniqueId' => 'widgetReferrersgetWebsites',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getWebsites',
+ ),
+ ),array (
+ 'name' => 'Social Networks',
+ 'uniqueId' => 'widgetReferrersgetSocialsviewDataTablegraphPie',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphPie',
+ 'module' => 'Referrers',
+ 'action' => 'getSocials',
+ ),
+ ),array (
+ 'name' => 'Campaigns',
+ 'uniqueId' => 'widgetReferrersgetCampaigns',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getCampaigns',
+ ),
+ ),array (
+ 'name' => 'Overview',
+ 'uniqueId' => 'widgetGoalsOverview',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'GoalsOverview',
+ ),
+ ),array (
+ 'name' => 'Overview',
+ 'uniqueId' => 'widgetEcommerceOverview',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'EcommerceOverview',
+ ),
+ ),array (
+ 'name' => 'Download Software',
+ 'uniqueId' => 'widgetGoal_1',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'Goal_1',
+ ),
+ ),array (
+ 'name' => 'Download Software2',
+ 'uniqueId' => 'widgetGoal_2',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'Goal_2',
+ ),
+ ),array (
+ 'name' => 'Opens Contact Form',
+ 'uniqueId' => 'widgetGoal_3',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'Goal_3',
+ ),
+ ),array (
+ 'name' => 'Visit Docs',
+ 'uniqueId' => 'widgetGoal_4',
+ 'parameters' =>
+ array (
+ 'module' => 'CoreHome',
+ 'action' => 'renderWidgetContainer',
+ 'containerId' => 'Goal_4',
+ ),
+ ),array (
+ 'name' => 'Data tables',
+ 'uniqueId' => 'widgetExampleUIgetTemperatures',
+ 'parameters' =>
+ array (
+ 'module' => 'ExampleUI',
+ 'action' => 'getTemperatures',
+ ),
+ ),array (
+ 'name' => 'Data tables',
+ 'uniqueId' => 'widgetExampleUIgetTemperaturesforceView1viewDataTablegraphVerticalBar',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'graphVerticalBar',
+ 'module' => 'ExampleUI',
+ 'action' => 'getTemperatures',
+ ),
+ ),array (
+ 'name' => 'Treemap example',
+ 'uniqueId' => 'widgetExampleUIgetTemperaturesforceView1viewDataTableinfoviz-treemap',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'infoviz-treemap',
+ 'module' => 'ExampleUI',
+ 'action' => 'getTemperatures',
+ ),
+ ),array (
+ 'name' => 'Temperatures evolution over time',
+ 'uniqueId' => 'widgetExampleUIgetTemperaturesEvolutionforceView1viewDataTablesparklines',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'sparklines',
+ 'module' => 'ExampleUI',
+ 'action' => 'getTemperaturesEvolution',
+ ),
+ ),array (
+ 'name' => 'Evolution of server temperatures over the last few days',
+ 'uniqueId' => 'widgetExampleUIgetTemperaturesEvolutionforceView1viewDataTablegraphEvolutioncolumnsArray',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'graphEvolution',
+ 'module' => 'ExampleUI',
+ 'action' => 'getTemperaturesEvolution',
+ 'columns' =>
+ array (
+ 0 => 'server1',
+ 1 => 'server2',
+ ),
+ ),
+ ),array (
+ 'name' => 'Pie graph',
+ 'uniqueId' => 'widgetExampleUIgetPlanetRatiosviewDataTablegraphPie',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'graphPie',
+ 'module' => 'ExampleUI',
+ 'action' => 'getPlanetRatios',
+ ),
+ ),array (
+ 'name' => 'Simple tag cloud',
+ 'uniqueId' => 'widgetExampleUIgetPlanetRatiosforceView1viewDataTablecloud',
+ 'parameters' =>
+ array (
+ 'forceView' => 1,
+ 'viewDataTable' => 'cloud',
+ 'module' => 'ExampleUI',
+ 'action' => 'getPlanetRatios',
+ ),
+ ),array (
+ 'name' => 'Advanced tag cloud: with logos and links',
+ 'uniqueId' => 'widgetExampleUIgetPlanetRatiosWithLogosviewDataTablecloud',
+ 'parameters' =>
+ array (
+ 'viewDataTable' => 'cloud',
+ 'module' => 'ExampleUI',
+ 'action' => 'getPlanetRatiosWithLogos',
+ )
+ ),array (
+ 'name' => 'Continent',
+ 'uniqueId' => 'widgetUserCountrygetContinent',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountry',
+ 'action' => 'getContinent',
+ ),
+ ), array (
+ 'name' => 'Event Categories',
+ 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getCategory',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Categories',
+ 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getCategory',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Actions',
+ 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getAction',
+ 'secondaryDimension' => 'eventName',
+ ),
+ ), array (
+ 'name' => 'Event Actions',
+ 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getAction',
+ 'secondaryDimension' => 'eventName',
+ ),
+ ), array (
+ 'name' => 'Event Actions',
+ 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getAction',
+ 'secondaryDimension' => 'eventName',
+ ),
+ ), array (
+ 'name' => 'Event Actions',
+ 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getAction',
+ 'secondaryDimension' => 'eventName',
+ ),
+ ), array (
+ 'name' => 'Event Names',
+ 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getName',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Names',
+ 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getName',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Names',
+ 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getName',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Names',
+ 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getName',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Categories',
+ 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getCategory',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Categories',
+ 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getCategory',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Content Piece',
+ 'uniqueId' => 'widgetContentsgetContentPieces',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentPieces',
+ ),
+ ), array (
+ 'name' => 'Content Piece',
+ 'uniqueId' => 'widgetContentsgetContentPieces',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentPieces',
+ ),
+ ), array (
+ 'name' => 'Content Name',
+ 'uniqueId' => 'widgetContentsgetContentNames',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentNames',
+ ),
+ ), array (
+ 'name' => 'Content Name',
+ 'uniqueId' => 'widgetContentsgetContentNames',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentNames',
+ ),
+ ), array (
+ 'name' => 'Content Name',
+ 'uniqueId' => 'widgetContentsgetContentNames',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentNames',
+ ),
+ ), array (
+ 'name' => 'Content Name',
+ 'uniqueId' => 'widgetContentsgetContentNames',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentNames',
+ ),
+ ), array (
+ 'name' => 'Content Piece',
+ 'uniqueId' => 'widgetContentsgetContentPieces',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentPieces',
+ ),
+ ), array (
+ 'name' => 'Content Piece',
+ 'uniqueId' => 'widgetContentsgetContentPieces',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentPieces',
+ ),
+ ), array (
+ 'name' => 'Product SKU',
+ 'uniqueId' => 'widgetGoalsgetItemsSku',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsSku',
+ ),
+ ), array (
+ 'name' => 'Product SKU',
+ 'uniqueId' => 'widgetGoalsgetItemsSku',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsSku',
+ ),
+ ), array (
+ 'name' => 'Product Category',
+ 'uniqueId' => 'widgetGoalsgetItemsCategory',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsCategory',
+ ),
+ ),
+ );
+ }
+
/**
* This is a list of all widgets that we consider API. We need to make sure the widgets will be still renderable
* etc.
* @return array
*/
- public function getWidgetsThatAreAPI()
+ public function getWidgetsThatAreDeprecatedButStillAPI()
{
- return array (
- array (
- 'name' => 'Visits by Server Time',
- 'uniqueId' => 'widgetVisitTimegetVisitInformationPerServerTime',
- 'parameters' =>
- array (
- 'module' => 'VisitTime',
- 'action' => 'getVisitInformationPerServerTime',
- ),
- ),
- array (
- 'name' => 'Visits by Local Time',
- 'uniqueId' => 'widgetVisitTimegetVisitInformationPerLocalTime',
- 'parameters' =>
- array (
- 'module' => 'VisitTime',
- 'action' => 'getVisitInformationPerLocalTime',
- ),
- ),
- array (
- 'name' => 'Visits by Day of Week',
- 'uniqueId' => 'widgetVisitTimegetByDayOfWeek',
- 'parameters' =>
- array (
- 'module' => 'VisitTime',
- 'action' => 'getByDayOfWeek',
- ),
- ),
- array (
- 'name' => 'Visits Over Time',
- 'uniqueId' => 'widgetVisitsSummarygetEvolutionGraphcolumnsArray',
- 'parameters' =>
- array (
- 'module' => 'VisitsSummary',
- 'action' => 'getEvolutionGraph',
- 'columns' =>
- array (
- 0 => 'nb_visits',
- ),
- ),
- ),
- array (
- 'name' => 'Visits Overview',
- 'uniqueId' => 'widgetVisitsSummarygetSparklines',
- 'parameters' =>
- array (
- 'module' => 'VisitsSummary',
- 'action' => 'getSparklines',
- ),
- ),
- array (
- 'name' => 'Visits Overview (with graph)',
- 'uniqueId' => 'widgetVisitsSummaryindex',
- 'parameters' =>
- array (
- 'module' => 'VisitsSummary',
- 'action' => 'index',
- ),
- ),
- array (
- 'name' => 'Real-time Map',
- 'uniqueId' => 'widgetUserCountryMaprealtimeMap',
- 'parameters' =>
- array (
- 'module' => 'UserCountryMap',
- 'action' => 'realtimeMap',
- ),
- ),
- array (
- 'name' => 'Visitor Log',
- 'uniqueId' => 'widgetLivegetVisitorLogsmall1',
- 'parameters' =>
- array (
- 'module' => 'Live',
- 'action' => 'getVisitorLog',
- 'small' => 1,
- ),
- ),
- array (
- 'name' => 'Real Time Visitor Count',
- 'uniqueId' => 'widgetLivegetSimpleLastVisitCount',
- 'parameters' =>
- array (
- 'module' => 'Live',
- 'action' => 'getSimpleLastVisitCount',
- ),
- ),
- array (
- 'name' => 'Visitors in Real-time',
- 'uniqueId' => 'widgetLivewidget',
- 'parameters' =>
- array (
- 'module' => 'Live',
- 'action' => 'widget',
- ),
- ),
- array (
- 'name' => 'Visitor profile',
- 'uniqueId' => 'widgetLivegetVisitorProfilePopup',
- 'parameters' =>
- array (
- 'module' => 'Live',
- 'action' => 'getVisitorProfilePopup',
- ),
- ),
- array (
- 'name' => 'Visitor Map',
- 'uniqueId' => 'widgetUserCountryMapvisitorMap',
- 'parameters' =>
- array (
- 'module' => 'UserCountryMap',
- 'action' => 'visitorMap',
- ),
- ),
- array (
- 'name' => 'Visitor Location (Country)',
- 'uniqueId' => 'widgetUserCountrygetCountry',
- 'parameters' =>
- array (
- 'module' => 'UserCountry',
- 'action' => 'getCountry',
- ),
- ),
- array (
- 'name' => 'Visitor Location (Continent)',
- 'uniqueId' => 'widgetUserCountrygetContinent',
- 'parameters' =>
- array (
- 'module' => 'UserCountry',
- 'action' => 'getContinent',
- ),
- ),
- array (
- 'name' => 'Visitor Location (Region)',
- 'uniqueId' => 'widgetUserCountrygetRegion',
- 'parameters' =>
- array (
- 'module' => 'UserCountry',
- 'action' => 'getRegion',
- ),
- ),
- array (
- 'name' => 'Visitor Location (City)',
- 'uniqueId' => 'widgetUserCountrygetCity',
- 'parameters' =>
- array (
- 'module' => 'UserCountry',
- 'action' => 'getCity',
- ),
- ),
- array (
- 'name' => 'Custom Variables',
- 'uniqueId' => 'widgetCustomVariablesgetCustomVariables',
- 'parameters' =>
- array (
- 'module' => 'CustomVariables',
- 'action' => 'getCustomVariables',
- ),
- ),
- array (
- 'name' => 'Length of Visits',
- 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerVisitDuration',
- 'parameters' =>
- array (
- 'module' => 'VisitorInterest',
- 'action' => 'getNumberOfVisitsPerVisitDuration',
- ),
- ),
- array (
- 'name' => 'Pages per Visit',
- 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerPage',
- 'parameters' =>
- array (
- 'module' => 'VisitorInterest',
- 'action' => 'getNumberOfVisitsPerPage',
- ),
- ),
- array (
- 'name' => 'Visits by Visit Number',
- 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsByVisitCount',
- 'parameters' =>
- array (
- 'module' => 'VisitorInterest',
- 'action' => 'getNumberOfVisitsByVisitCount',
- ),
- ),
- array (
- 'name' => 'Visits by Days Since Last Visit',
- 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsByDaysSinceLast',
- 'parameters' =>
- array (
- 'module' => 'VisitorInterest',
- 'action' => 'getNumberOfVisitsByDaysSinceLast',
- ),
- ),
- array (
- 'name' => 'Frequency Overview',
- 'uniqueId' => 'widgetVisitFrequencygetSparklines',
- 'parameters' =>
- array (
- 'module' => 'VisitFrequency',
- 'action' => 'getSparklines',
- ),
- ),
- array (
- 'name' => 'Returning Visits Over Time',
- 'uniqueId' => 'widgetVisitFrequencygetEvolutionGraphcolumnsArray',
- 'parameters' =>
- array (
- 'module' => 'VisitFrequency',
- 'action' => 'getEvolutionGraph',
- 'columns' =>
- array (
- 0 => 'nb_visits_returning',
- ),
- ),
- ),
- array (
- 'name' => 'Screen Resolution',
- 'uniqueId' => 'widgetResolutiongetResolution',
- 'parameters' =>
- array (
- 'module' => 'Resolution',
- 'action' => 'getResolution',
- ),
- ),
- array (
- 'name' => 'Browser Plugins',
- 'uniqueId' => 'widgetDevicePluginsgetPlugin',
- 'parameters' =>
- array (
- 'module' => 'DevicePlugins',
- 'action' => 'getPlugin',
- ),
- ),
- array (
- 'name' => 'Visitor Configuration',
- 'uniqueId' => 'widgetResolutiongetConfiguration',
- 'parameters' =>
- array (
- 'module' => 'Resolution',
- 'action' => 'getConfiguration',
- ),
- ),
- array (
- 'name' => 'Browser language',
- 'uniqueId' => 'widgetUserLanguagegetLanguage',
- 'parameters' =>
- array (
- 'module' => 'UserLanguage',
- 'action' => 'getLanguage',
- ),
- ),
- array (
- 'name' => 'Language code',
- 'uniqueId' => 'widgetUserLanguagegetLanguageCode',
- 'parameters' =>
- array (
- 'module' => 'UserLanguage',
- 'action' => 'getLanguageCode',
- ),
- ),
- array (
- 'name' => 'Device type',
- 'uniqueId' => 'widgetDevicesDetectiongetType',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getType',
- ),
- ),
- array (
- 'name' => 'Device brand',
- 'uniqueId' => 'widgetDevicesDetectiongetBrand',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getBrand',
- ),
- ),
- array (
- 'name' => 'Visitor Browser',
- 'uniqueId' => 'widgetDevicesDetectiongetBrowsers',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getBrowsers',
- ),
- ),
- array (
- 'name' => 'Device model',
- 'uniqueId' => 'widgetDevicesDetectiongetModel',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getModel',
- ),
- ),
- array (
- 'name' => 'Browser version',
- 'uniqueId' => 'widgetDevicesDetectiongetBrowserVersions',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getBrowserVersions',
- ),
- ),
- array (
- 'name' => 'Operating System families',
- 'uniqueId' => 'widgetDevicesDetectiongetOsFamilies',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getOsFamilies',
- ),
- ),
- array (
- 'name' => 'Operating System versions',
- 'uniqueId' => 'widgetDevicesDetectiongetOsVersions',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getOsVersions',
- ),
- ),
- array (
- 'name' => 'Browser engines',
- 'uniqueId' => 'widgetDevicesDetectiongetBrowserEngines',
- 'parameters' =>
- array (
- 'module' => 'DevicesDetection',
- 'action' => 'getBrowserEngines',
- ),
- ),
- array (
- 'name' => 'Pages',
- 'uniqueId' => 'widgetActionsgetPageUrls',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getPageUrls',
- ),
- ),
- array (
- 'name' => 'Entry Pages',
- 'uniqueId' => 'widgetActionsgetEntryPageUrls',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getEntryPageUrls',
- ),
- ),
- array (
- 'name' => 'Exit Pages',
- 'uniqueId' => 'widgetActionsgetExitPageUrls',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getExitPageUrls',
- ),
- ),
- array (
- 'name' => 'Page Titles',
- 'uniqueId' => 'widgetActionsgetPageTitles',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getPageTitles',
- ),
- ),
- array (
- 'name' => 'Entry Page Titles',
- 'uniqueId' => 'widgetActionsgetEntryPageTitles',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getEntryPageTitles',
- ),
- ),
- array (
- 'name' => 'Exit Page Titles',
- 'uniqueId' => 'widgetActionsgetExitPageTitles',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getExitPageTitles',
- ),
- ),
- array (
- 'name' => 'Outlinks',
- 'uniqueId' => 'widgetActionsgetOutlinks',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getOutlinks',
- ),
- ),
- array (
- 'name' => 'Downloads',
- 'uniqueId' => 'widgetActionsgetDownloads',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getDownloads',
- ),
- ),
- array (
- 'name' => 'Content Name',
- 'uniqueId' => 'widgetContentsgetContentNames',
- 'parameters' =>
- array (
- 'module' => 'Contents',
- 'action' => 'getContentNames',
- ),
- ),
- array (
- 'name' => 'Content Piece',
- 'uniqueId' => 'widgetContentsgetContentPieces',
- 'parameters' =>
- array (
- 'module' => 'Contents',
- 'action' => 'getContentPieces',
- ),
- ),
- array (
- 'name' => 'Event Categories',
- 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
- 'parameters' =>
- array (
- 'module' => 'Events',
- 'action' => 'getCategory',
- 'secondaryDimension' => 'eventAction',
- ),
- ),
- array (
- 'name' => 'Event Actions',
- 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
- 'parameters' =>
- array (
- 'module' => 'Events',
- 'action' => 'getAction',
- 'secondaryDimension' => 'eventName',
- ),
- ),
- array (
- 'name' => 'Event Names',
- 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
- 'parameters' =>
- array (
- 'module' => 'Events',
- 'action' => 'getName',
- 'secondaryDimension' => 'eventAction',
- ),
- ),
- array (
- 'name' => 'Site Search Keywords',
- 'uniqueId' => 'widgetActionsgetSiteSearchKeywords',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getSiteSearchKeywords',
- ),
- ),
- array (
- 'name' => 'Search Keywords with No Results',
- 'uniqueId' => 'widgetActionsgetSiteSearchNoResultKeywords',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getSiteSearchNoResultKeywords',
- ),
- ),
- array (
- 'name' => 'Search Categories',
- 'uniqueId' => 'widgetActionsgetSiteSearchCategories',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getSiteSearchCategories',
- ),
- ),
- array (
- 'name' => 'Pages Following a Site Search',
- 'uniqueId' => 'widgetActionsgetPageUrlsFollowingSiteSearch',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getPageUrlsFollowingSiteSearch',
- ),
- ),
- array (
- 'name' => 'Page Titles Following a Site Search',
- 'uniqueId' => 'widgetActionsgetPageTitlesFollowingSiteSearch',
- 'parameters' =>
- array (
- 'module' => 'Actions',
- 'action' => 'getPageTitlesFollowingSiteSearch',
- ),
- ),
- array (
- 'name' => 'Overview',
- 'uniqueId' => 'widgetReferrersgetReferrerType',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getReferrerType',
- ),
- ),
- array (
- 'name' => 'All Referrers',
- 'uniqueId' => 'widgetReferrersgetAll',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getAll',
- ),
- ),
- array (
- 'name' => 'Keywords',
- 'uniqueId' => 'widgetReferrersgetKeywords',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getKeywords',
- ),
- ),
- array (
- 'name' => 'Referrer Websites',
- 'uniqueId' => 'widgetReferrersgetWebsites',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getWebsites',
- ),
- ),
- array (
- 'name' => 'Search Engines',
- 'uniqueId' => 'widgetReferrersgetSearchEngines',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getSearchEngines',
- ),
- ),
- array (
- 'name' => 'Campaigns',
- 'uniqueId' => 'widgetReferrersgetCampaigns',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getCampaigns',
- ),
- ),
- array (
- 'name' => 'List of social networks',
- 'uniqueId' => 'widgetReferrersgetSocials',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getSocials',
- ),
- ),
- array (
- 'name' => 'Goals Overview',
- 'uniqueId' => 'widgetGoalswidgetGoalsOverview',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'widgetGoalsOverview',
- ),
- ),
- array (
- 'name' => 'Download Software',
- 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal1',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'widgetGoalReport',
- 'idGoal' => '1',
- ),
- ),
- array (
- 'name' => 'Download Software2',
- 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal2',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'widgetGoalReport',
- 'idGoal' => '2',
- ),
- ),
- array (
- 'name' => 'Opens Contact Form',
- 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal3',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'widgetGoalReport',
- 'idGoal' => '3',
- ),
- ),
- array (
- 'name' => 'Visit Docs',
- 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal4',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'widgetGoalReport',
- 'idGoal' => '4',
- ),
- ),
- array (
- 'name' => 'Product SKU',
- 'uniqueId' => 'widgetGoalsgetItemsSku',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'getItemsSku',
- ),
- ),
- array (
- 'name' => 'Product Name',
- 'uniqueId' => 'widgetGoalsgetItemsName',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'getItemsName',
- ),
- ),
- array (
- 'name' => 'Product Category',
- 'uniqueId' => 'widgetGoalsgetItemsCategory',
- 'parameters' =>
- array (
- 'module' => 'Goals',
- 'action' => 'getItemsCategory',
- ),
- ),
- array (
- 'name' => 'Overview',
- 'uniqueId' => 'widgetEcommercewidgetGoalReportidGoalecommerceOrder',
- 'parameters' =>
- array (
- 'module' => 'Ecommerce',
- 'action' => 'widgetGoalReport',
- 'idGoal' => 'ecommerceOrder',
- ),
- ),
- array (
- 'name' => 'Ecommerce Log',
- 'uniqueId' => 'widgetEcommercegetEcommerceLog',
- 'parameters' =>
- array (
- 'module' => 'Ecommerce',
- 'action' => 'getEcommerceLog',
- ),
- ),
- array (
- 'name' => 'Insights Overview',
- 'uniqueId' => 'widgetInsightsgetInsightsOverview',
- 'parameters' =>
- array (
- 'module' => 'Insights',
- 'action' => 'getInsightsOverview',
- ),
- ),
- array (
- 'name' => 'Movers and Shakers',
- 'uniqueId' => 'widgetInsightsgetOverallMoversAndShakers',
- 'parameters' =>
- array (
- 'module' => 'Insights',
- 'action' => 'getOverallMoversAndShakers',
- ),
- ),
- array (
- 'name' => 'Top Keywords for Page URL',
- 'uniqueId' => 'widgetReferrersgetKeywordsForPage',
- 'parameters' =>
- array (
- 'module' => 'Referrers',
- 'action' => 'getKeywordsForPage',
- ),
- ),
- array (
- 'name' => 'SEO Rankings',
- 'uniqueId' => 'widgetSEOgetRank',
- 'parameters' =>
- array (
- 'module' => 'SEO',
- 'action' => 'getRank',
- ),
- ),
- array (
- 'name' => 'Support Piwik!',
- 'uniqueId' => 'widgetCoreHomegetDonateForm',
- 'parameters' =>
- array (
- 'module' => 'CoreHome',
- 'action' => 'getDonateForm',
- ),
- ),
- array (
- 'name' => 'Welcome!',
- 'uniqueId' => 'widgetCoreHomegetPromoVideo',
- 'parameters' =>
- array (
- 'module' => 'CoreHome',
- 'action' => 'getPromoVideo',
- ),
- ),
- array (
- 'name' => 'Piwik.org Blog',
- 'uniqueId' => 'widgetExampleRssWidgetrssPiwik',
- 'parameters' =>
- array (
- 'module' => 'ExampleRssWidget',
- 'action' => 'rssPiwik',
- ),
- ),
- array (
- 'name' => 'Piwik Changelog',
- 'uniqueId' => 'widgetExampleRssWidgetrssChangelog',
- 'parameters' =>
- array (
- 'module' => 'ExampleRssWidget',
- 'action' => 'rssChangelog',
- ),
- ),
+ return array(
+ array (
+ 'name' => 'Visits per server time',
+ 'uniqueId' => 'widgetVisitTimegetVisitInformationPerServerTime',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitTime',
+ 'action' => 'getVisitInformationPerServerTime',
+ ),
+ ), array (
+ 'name' => 'Visits per local time',
+ 'uniqueId' => 'widgetVisitTimegetVisitInformationPerLocalTime',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitTime',
+ 'action' => 'getVisitInformationPerLocalTime',
+ ),
+ ), array (
+ 'name' => 'Visits by Day of Week',
+ 'uniqueId' => 'widgetVisitTimegetByDayOfWeek',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitTime',
+ 'action' => 'getByDayOfWeek',
+ ),
+ ), array (
+ 'name' => 'Visits Over Time',
+ 'uniqueId' => 'widgetVisitsSummarygetEvolutionGraphcolumnsArray',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitsSummary',
+ 'action' => 'getEvolutionGraph',
+ 'columns' =>
+ array (
+ 0 => 'nb_visits',
+ ),
+ ),
+ ), array (
+ 'name' => 'Visits Overview',
+ 'uniqueId' => 'widgetVisitsSummarygetSparklines',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitsSummary',
+ 'action' => 'getSparklines',
+ ),
+ ), array (
+ 'name' => 'Visits Overview (with graph)',
+ 'uniqueId' => 'widgetVisitsSummaryindex',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitsSummary',
+ 'action' => 'index',
+ ),
+ ), array (
+ 'name' => 'Visitor Log',
+ 'uniqueId' => 'widgetLivegetVisitorLogsmall1',
+ 'parameters' =>
+ array (
+ 'module' => 'Live',
+ 'action' => 'getVisitorLog',
+ 'small' => 1,
+ ),
+ ), array (
+ 'name' => 'Continent',
+ 'uniqueId' => 'widgetUserCountrygetContinent',
+ 'parameters' =>
+ array (
+ 'module' => 'UserCountry',
+ 'action' => 'getContinent',
+ ),
+ ), array (
+ 'name' => 'Visits per visit duration',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerVisitDuration',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsPerVisitDuration',
+ ),
+ ), array (
+ 'name' => 'Pages per Visit',
+ 'uniqueId' => 'widgetVisitorInterestgetNumberOfVisitsPerPage',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitorInterest',
+ 'action' => 'getNumberOfVisitsPerPage',
+ ),
+ ), array (
+ 'name' => 'Frequency Overview',
+ 'uniqueId' => 'widgetVisitFrequencygetSparklines',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitFrequency',
+ 'action' => 'getSparklines',
+ ),
+ ), array (
+ 'name' => 'Returning Visits Over Time',
+ 'uniqueId' => 'widgetVisitFrequencygetEvolutionGraphcolumnsArray',
+ 'parameters' =>
+ array (
+ 'module' => 'VisitFrequency',
+ 'action' => 'getEvolutionGraph',
+ 'columns' =>
+ array (
+ 0 => 'nb_visits_returning',
+ ),
+ ),
+ ), array (
+ 'name' => 'Browser engines',
+ 'uniqueId' => 'widgetDevicesDetectiongetBrowserEngines',
+ 'parameters' =>
+ array (
+ 'module' => 'DevicesDetection',
+ 'action' => 'getBrowserEngines',
+ ),
+ ), array (
+ 'name' => 'Content Name',
+ 'uniqueId' => 'widgetContentsgetContentNames',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentNames',
+ ),
+ ), array (
+ 'name' => 'Content Piece',
+ 'uniqueId' => 'widgetContentsgetContentPieces',
+ 'parameters' =>
+ array (
+ 'module' => 'Contents',
+ 'action' => 'getContentPieces',
+ ),
+ ), array (
+ 'name' => 'Event Categories',
+ 'uniqueId' => 'widgetEventsgetCategorysecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getCategory',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Event Actions',
+ 'uniqueId' => 'widgetEventsgetActionsecondaryDimensioneventName',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getAction',
+ 'secondaryDimension' => 'eventName',
+ ),
+ ), array (
+ 'name' => 'Event Names',
+ 'uniqueId' => 'widgetEventsgetNamesecondaryDimensioneventAction',
+ 'parameters' =>
+ array (
+ 'module' => 'Events',
+ 'action' => 'getName',
+ 'secondaryDimension' => 'eventAction',
+ ),
+ ), array (
+ 'name' => 'Overview',
+ 'uniqueId' => 'widgetReferrersgetReferrerType',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getReferrerType',
+ ),
+ ), array (
+ 'name' => 'All Referrers',
+ 'uniqueId' => 'widgetReferrersgetAll',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getAll',
+ ),
+ ), array (
+ 'name' => 'List of social networks',
+ 'uniqueId' => 'widgetReferrersgetSocials',
+ 'parameters' =>
+ array (
+ 'module' => 'Referrers',
+ 'action' => 'getSocials',
+ ),
+ ), array (
+ 'name' => 'Goals Overview',
+ 'uniqueId' => 'widgetGoalswidgetGoalsOverview',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'widgetGoalsOverview',
+ ),
+ ), array (
+ 'name' => 'Download Software',
+ 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal1',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'widgetGoalReport',
+ 'idGoal' => '1',
+ ),
+ ), array (
+ 'name' => 'Download Software2',
+ 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal2',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'widgetGoalReport',
+ 'idGoal' => '2',
+ ),
+ ), array (
+ 'name' => 'Opens Contact Form',
+ 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal3',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'widgetGoalReport',
+ 'idGoal' => '3',
+ ),
+ ), array (
+ 'name' => 'Visit Docs',
+ 'uniqueId' => 'widgetGoalswidgetGoalReportidGoal4',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'widgetGoalReport',
+ 'idGoal' => '4',
+ ),
+ ), array (
+ 'name' => 'Product SKU',
+ 'uniqueId' => 'widgetGoalsgetItemsSku',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsSku',
+ ),
+ ), array (
+ 'name' => 'Product Name',
+ 'uniqueId' => 'widgetGoalsgetItemsName',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsName',
+ ),
+ ), array (
+ 'name' => 'Product Category',
+ 'uniqueId' => 'widgetGoalsgetItemsCategory',
+ 'parameters' =>
+ array (
+ 'module' => 'Goals',
+ 'action' => 'getItemsCategory',
+ ),
+ ), array (
+ 'name' => 'Overview',
+ 'uniqueId' => 'widgetEcommercewidgetGoalReportidGoalecommerceOrder',
+ 'parameters' =>
+ array (
+ 'module' => 'Ecommerce',
+ 'action' => 'widgetGoalReport',
+ 'idGoal' => 'ecommerceOrder',
+ ),
+ )
);
}
}
-WidgetTest::$fixture = new WidgetizeFixture(); \ No newline at end of file
+WidgetTest::$fixture = new WidgetizeFixture();
diff --git a/plugins/ZenMode/ZenMode.php b/plugins/ZenMode/ZenMode.php
index bbacb157c3..eee60c4603 100644
--- a/plugins/ZenMode/ZenMode.php
+++ b/plugins/ZenMode/ZenMode.php
@@ -40,6 +40,7 @@ class ZenMode extends \Piwik\Plugin
{
$jsFiles[] = "plugins/ZenMode/javascripts/zen-mode.js";
$jsFiles[] = "plugins/ZenMode/angularjs/quick-access/quick-access.directive.js";
+ $jsFiles[] = "plugins/ZenMode/angularjs/zen-mode/zen-mode-disabler.js";
$jsFiles[] = "plugins/ZenMode/angularjs/zen-mode/zen-mode-switcher.directive.js";
}
diff --git a/plugins/ZenMode/angularjs/zen-mode/zen-mode-disabler.js b/plugins/ZenMode/angularjs/zen-mode/zen-mode-disabler.js
new file mode 100644
index 0000000000..420020b75f
--- /dev/null
+++ b/plugins/ZenMode/angularjs/zen-mode/zen-mode-disabler.js
@@ -0,0 +1,35 @@
+/*!
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * Usage:
+ * <div piwik-zen-mode-switcher>...</div>
+ * Will toggle the zen mode on click on this element.
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikReportingMenu', piwikZenModeSwitcher);
+
+ piwikZenModeSwitcher.$inject = ['$rootElement', '$filter'];
+
+ function piwikZenModeSwitcher($rootElement, $filter) {
+
+ return {
+ restrict: 'A',
+ compile: function (element, attrs) {
+
+ element.find('.Menu--dashboard').prepend(
+ '<span piwik-zen-mode-switcher class="deactivateZenMode">'
+ + '<img src="plugins/CoreHome/images/navigation_collapse.png" >'
+ + '</span>');
+
+ return function () {
+ };
+ }
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/plugins/ZenMode/javascripts/zen-mode.js b/plugins/ZenMode/javascripts/zen-mode.js
index bc2a793942..e4e163db8b 100644
--- a/plugins/ZenMode/javascripts/zen-mode.js
+++ b/plugins/ZenMode/javascripts/zen-mode.js
@@ -19,13 +19,6 @@ $(document).ready(function () {
piwikHelper.compileAngularComponents(addedElement);
- addedElement = $('.Menu--dashboard').prepend(
- '<span piwik-zen-mode-switcher class="deactivateZenMode">'
- + '<img src="plugins/CoreHome/images/navigation_collapse.png" >'
- + '</span>');
-
- piwikHelper.compileAngularComponents(addedElement);
-
angular.element(document).injector().invoke(handleZenMode);
function handleZenMode ($rootElement, $cookies) {
@@ -77,7 +70,7 @@ $(document).ready(function () {
function isDashboard()
{
- return !!$('.Menu--dashboard').length;
+ return !!$('[piwik-reporting-menu]').length;
}
function initMenu () {
@@ -98,7 +91,6 @@ $(document).ready(function () {
$('#Searchmenu').off('keydown focus', '.quick-access input', showQuickAccessMenu);
$('#Searchmenu').off('blur', '.quick-access input', hideQuickAccessMenu);
- menu.prototype.adaptSubMenuHeight();
}
function overMainLI () {