diff --git a/bundles/AdminBundle/Controller/Reports/PiwikController.php b/bundles/AdminBundle/Controller/Reports/PiwikController.php deleted file mode 100644 index 95b67de986a..00000000000 --- a/bundles/AdminBundle/Controller/Reports/PiwikController.php +++ /dev/null @@ -1,230 +0,0 @@ -checkPermission('piwik_reports'); - - $reports = $reportBroker->getReports(); - - return $this->json($reports); - } - - /** - * @Route("/reports/{report}", name="pimcore_admin_reports_piwik_report", methods={"GET"}) - * - * @param ReportBroker $reportBroker - * - * @return JsonResponse - */ - public function reportAction(ReportBroker $reportBroker, $report) - { - $this->checkPermission('piwik_reports'); - - try { - $report = $reportBroker->getReport((string)$report); - - return $this->json($report); - } catch (\InvalidArgumentException $e) { - throw $this->createNotFoundException($e->getMessage()); - } - } - - /** - * @Route("/iframe-integration", name="pimcore_admin_reports_piwik_iframeintegration", methods={"GET"}) - * - * @param ConfigProvider $configProvider - * - * @return JsonResponse - */ - public function iframeIntegrationAction(ConfigProvider $configProvider) - { - $this->checkPermission('piwik_reports'); - - $config = $configProvider->getConfig(); - - $data = [ - 'configured' => false, - ]; - - if ($config->isIframeIntegrationConfigured()) { - $data = [ - 'configured' => true, - 'url' => $config->generateIframeUrl(), - ]; - } - - return $this->json($data); - } - - /** - * @Route("/config/configured-sites", name="pimcore_admin_reports_piwik_sites", methods={"GET"}) - * - * @param SiteIdProvider $siteConfigProvider - * @param ConfigProvider $configProvider - * @param TranslatorInterface $translator - * - * @return JsonResponse - */ - public function sitesAction( - SiteIdProvider $siteConfigProvider, - ConfigProvider $configProvider, - TranslatorInterface $translator - ) { - $this->checkPermission('piwik_reports'); - - $siteConfigs = $siteConfigProvider->getSiteIds(); - $config = $configProvider->getConfig(); - - $sites = []; - foreach ($siteConfigs as $siteConfig) { - if (!$config->isSiteConfigured($siteConfig->getConfigKey())) { - continue; - } - - $sites[] = [ - 'id' => $siteConfig->getConfigKey(), - 'title' => $siteConfig->getTitle($translator), - ]; - } - - return $this->json(['data' => $sites]); - } - - /** - * @Route("/portal-widgets/{configKey}", name="pimcore_admin_reports_piwik_portalwidgets", methods={"GET"}) - * - * @param WidgetBroker $widgetBroker - * @param string $configKey - * - * @return JsonResponse - */ - public function portalWidgetsAction(WidgetBroker $widgetBroker, string $configKey) - { - $this->checkPermission('piwik_reports'); - - $widgetReferences = $widgetBroker->getWidgetReferences($configKey); - - return $this->json(['data' => $widgetReferences]); - } - - /** - * @Route("/portal-widgets/{configKey}/{widgetId}", name="pimcore_admin_reports_piwik_portalwidget", methods={"GET"}) - * - * @param Request $request - * @param WidgetBroker $widgetBroker - * @param string $configKey - * @param string $widgetId - * - * @return JsonResponse - */ - public function portalWidgetAction(Request $request, WidgetBroker $widgetBroker, string $configKey, string $widgetId) - { - $this->checkPermission('piwik_reports'); - - $params = []; - foreach (['date', 'period'] as $param) { - if ($request->get($param)) { - $params[$param] = urlencode($request->get($param)); - } - } - - try { - $widgetConfig = $widgetBroker->getWidgetConfig($widgetId, $configKey, null, $params); - } catch (\InvalidArgumentException $e) { - return $this->json([ - 'success' => false, - 'message' => $e->getMessage(), - ], JsonResponse::HTTP_NOT_FOUND); - } - - return $this->json($widgetConfig); - } - - /** - * @Route("/api/site/{configKey}", name="pimcore_admin_reports_piwik_apisitecreate", methods={"POST"}) - * - * @param string $configKey - * @param SiteIdProvider $siteConfigProvider - * @param SitesManager $sitesManager - * - * @return JsonResponse - */ - public function apiSiteCreateAction( - string $configKey, - SiteIdProvider $siteConfigProvider, - SitesManager $sitesManager - ) { - $this->checkPermission('piwik_settings'); - - $siteConfig = $siteConfigProvider->getSiteId($configKey); - $siteId = $sitesManager->addSite($siteConfig); - - return $this->json([ - 'site_id' => $siteId, - ]); - } - - /** - * @Route("/api/site/{configKey}", name="pimcore_admin_reports_piwik_apisiteupdate", methods={"PUT"}) - * - * @param string $configKey - * @param SiteIdProvider $siteConfigProvider - * @param SitesManager $sitesManager - * - * @return JsonResponse - */ - public function apiSiteUpdateAction( - string $configKey, - SiteIdProvider $siteConfigProvider, - SitesManager $sitesManager - ) { - $this->checkPermission('piwik_settings'); - - $siteConfig = $siteConfigProvider->getSiteId($configKey); - $siteId = $sitesManager->updateSite($siteConfig); - - return $this->json([ - 'site_id' => $siteId, - ]); - } -} diff --git a/bundles/AdminBundle/Resources/public/css/icons.css b/bundles/AdminBundle/Resources/public/css/icons.css index 8bfa503052e..231ce75552c 100644 --- a/bundles/AdminBundle/Resources/public/css/icons.css +++ b/bundles/AdminBundle/Resources/public/css/icons.css @@ -315,16 +315,6 @@ background: url(/bundles/pimcoreadmin/img/flat-white-icons/settings.svg) center center no-repeat !important; } -.pimcore_nav_icon_matomo { - background: url(/bundles/pimcoreadmin/img/flat-white-icons/matomo.svg) center center no-repeat !important; - color: #d4291f; -} - -.pimcore_icon_matomo { - background: url(/bundles/pimcoreadmin/img/matomo.svg) center center no-repeat !important; - color: #d4291f; -} - .pimcore_nav_icon_doctypes { background: url(/bundles/pimcoreadmin/img/flat-white-icons/file-types.svg) center center no-repeat !important; } @@ -1587,19 +1577,6 @@ background: url(/bundles/pimcoreadmin/img/flat-color-icons/genealogy.svg) center center no-repeat !important; } -.pimcore_icon_piwik { - background: url(/bundles/pimcoreadmin/img/matomo.svg) center center no-repeat !important; - color: #d4291f; -} - -.pimcore_icon_piwik_api_create { - background: url(/bundles/pimcoreadmin/img/flat-color-icons/external.svg) center center no-repeat !important; -} - -.pimcore_icon_piwik_api_update { - background: url(/bundles/pimcoreadmin/img/flat-color-icons/synchronize.svg) center center no-repeat !important; -} - .pimcore_icon_operator_ignore { background: url(/bundles/pimcoreadmin/img/flat-color-icons/cancel.svg) center center no-repeat !important; } diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/analytics/piwik/widget_store_provider.js b/bundles/AdminBundle/Resources/public/js/pimcore/analytics/piwik/widget_store_provider.js deleted file mode 100644 index 803f83581c6..00000000000 --- a/bundles/AdminBundle/Resources/public/js/pimcore/analytics/piwik/widget_store_provider.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Pimcore - * - * This source file is available under two different licenses: - * - GNU General Public License version 3 (GPLv3) - * - Pimcore Enterprise License (PEL) - * Full copyright and license information is available in - * LICENSE.md which is distributed with this source code. - * - * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) - * @license http://www.pimcore.org/license GPLv3 and PEL - */ - -/** - * @deprecated - */ -pimcore.registerNS("pimcore.analytics.piwik.WidgetStoreProvider"); - -(function() { - 'use strict'; - - var stores = {}; - - pimcore.analytics.piwik.WidgetStoreProvider = { - /** - * @returns {Ext.data.Store} - */ - getConfiguredSitesStore: function() { - if ('undefined' !== typeof stores.configuredSites) { - return stores.configuredSites; - } - - stores.configuredSites = new Ext.data.Store({ - autoDestroy: false, - autoLoad: true, - proxy: { - type: 'ajax', - url: Routing.generate('pimcore_admin_reports_piwik_sites'), - reader: { - type: 'json', - rootProperty: 'data' - } - } - }); - - return stores.configuredSites; - }, - - /** - * @param {String} siteConfigKey - * @returns {Ext.data.Store} - */ - getPortalWidgetsStore: function(siteConfigKey) { - if ('undefined' === typeof stores.portalWidgets) { - stores.portalWidgets = {}; - } - - if ('undefined' !== typeof stores.portalWidgets[siteConfigKey]) { - return stores.portalWidgets[siteConfigKey]; - } - - stores.portalWidgets[siteConfigKey] = new Ext.data.Store({ - autoDestroy: false, - autoLoad: true, - proxy: { - type: 'ajax', - url: Routing.generate('pimcore_admin_reports_piwik_portalwidgets', {configKey: siteConfigKey}), - reader: { - type: 'json', - rootProperty: 'data' - } - } - }); - - return stores.portalWidgets[siteConfigKey]; - } - }; -}()); diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/layout/portlets/piwik.js b/bundles/AdminBundle/Resources/public/js/pimcore/layout/portlets/piwik.js deleted file mode 100644 index 1152f8a86d1..00000000000 --- a/bundles/AdminBundle/Resources/public/js/pimcore/layout/portlets/piwik.js +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Pimcore - * - * This source file is available under two different licenses: - * - GNU General Public License version 3 (GPLv3) - * - Pimcore Enterprise License (PEL) - * Full copyright and license information is available in - * LICENSE.md which is distributed with this source code. - * - * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) - * @license http://www.pimcore.org/license GPLv3 and PEL - */ - -/** - * @deprecated - */ -pimcore.registerNS("pimcore.layout.portlets.piwik"); -pimcore.layout.portlets.piwik = Class.create(pimcore.layout.portlets.abstract, { - - isAvailable: function() { - return pimcore.globalmanager.get("user").isAllowed("piwik_reports"); - }, - - setConfig: function (config) { - var parsed = { - site: null, - widget: null, - period: null, - date: null - }; - - try { - if (config) { - parsed = JSON.parse(config); - } - } catch (e) { - console.error('Failed to parse Matomo/Piwik widget config: ', e); - } - - this.config = parsed; - }, - - getType: function () { - return "pimcore.layout.portlets.piwik"; - }, - - getName: function () { - return "Piwik"; - }, - - getIcon: function () { - return "pimcore_icon_piwik"; - }, - - getLayout: function (portletId) { - var that = this; - - var defaultConf = this.getDefaultConfig(); - defaultConf.tools = [ - { - type: 'gear', - handler: this.editSettings.bind(this) - }, - { - type: 'close', - handler: this.remove.bind(this) - } - ]; - - this.layout = Ext.create('Portal.view.Portlet', Object.assign(defaultConf, { - title: this.getName(), - iconCls: this.getIcon(), - height: 275, - layout: "fit", - items: [] - })); - - this.loadMask = new Ext.LoadMask({ - target: this.layout, - msg: t("please_wait") - }); - - this.layout.on("afterrender", function () { - that.loadMask.show(); - that.renderIframe(); - }); - - this.layout.on("destroy", function() { - that.loadMask.destroy(); - }); - - this.layout.portletId = portletId; - - return this.layout; - }, - - editSettings: function () { - var config = this.config || {}; - - var siteCombo = new Ext.form.ComboBox({ - name: "site", - xtype: "combo", - width: 500, - autoSelect: true, - valueField: "id", - displayField: "title", - value: config.site, - fieldLabel: t("piwik_widget_site"), - fields: ['id', 'title'], - mode: "local", - triggerAction: "all", - store: pimcore.analytics.piwik.WidgetStoreProvider.getConfiguredSitesStore() - }); - - var widgetCombo = new Ext.form.ComboBox({ - name: "widget", - xtype: "combo", - width: 500, - autoSelect: true, - valueField: "id", - displayField: "title", - value: config.widget, - fieldLabel: t("piwik_widget_widget"), - fields: ['id', 'title'], - mode: "local", - triggerAction: "all", - disabled: true - }); - - var siteValueListener = function () { - var value = siteCombo.getValue(); - - if (value) { - widgetCombo.setStore(pimcore.analytics.piwik.WidgetStoreProvider.getPortalWidgetsStore(value)); - widgetCombo.enable(); - } else { - widgetCombo.setValue(null); - widgetCombo.setStore(null); - widgetCombo.disable(); - } - }; - - siteCombo.on('select', siteValueListener); - siteCombo.on('change', siteValueListener); - siteValueListener(); - - var win = new Ext.Window({ - width: 550, - height: 280, - modal: true, - title: t('portlet_piwik_widget'), - closeAction: "destroy", - items: [ - { - xtype: "form", - bodyStyle: "padding: 10px", - items: [ - siteCombo, - widgetCombo, - { - name: 'period', - fieldLabel: t("piwik_widget_period"), - xtype: 'combo', - store: [ - ['day', t('piwik_period_day')], - ['week', t('piwik_period_week')], - ['month', t('piwik_period_month')], - ['year', t('piwik_period_year')] - ], - mode: 'local', - width: 500, - value: ('undefined' !== typeof config.period) ? config.period : 'day', - editable: false, - triggerAction: 'all' - }, - { - name: 'date', - fieldLabel: t("piwik_widget_date"), - xtype: 'combo', - store: [ - ['yesterday', t('piwik_date_yesterday')], - ['today', t('piwik_date_today')] - ], - mode: 'local', - width: 500, - value: ('undefined' !== typeof config.date) ? config.date : 'yesterday', - editable: true, - triggerAction: 'all' - }, - { - xtype: "button", - text: t("save"), - handler: function (button) { - var form = button.up('form').getForm(); - this.updateSettings(form.getValues()); - - win.close(); - }.bind(this) - } - ] - } - ] - }); - - win.show(); - }, - - updateSettings: function (data) { - this.config = data; - this.loadMask.show(); - - Ext.Ajax.request({ - url: Routing.generate('pimcore_admin_portal_updateportletconfig'), - method: 'PUT', - params: { - key: this.portal.key, - id: this.layout.portletId, - config: JSON.stringify(this.config) - }, - success: function () { - this.renderIframe(); - }.bind(this), - - failure: function() { - this.loadMask.hide(); - }.bind(this) - }); - }, - - renderIframe: function () { - var that = this; - var config = this.config; - var layout = this.layout; - - if (!config || !config.site || !config.widget) { - layout.removeAll(); - layout.add(new Ext.Component({ - html: t('portlet_piwik_unconfigured'), - padding: 20 - })); - - that.loadMask.hide(); - - return; - } - - var params = { - period: 'day', - date: 'yesterday' - }; - - if (config.period) { - params.period = config.period; - } - - if (config.date) { - params.date = config.date; - } - - Ext.Ajax.request({ - url: Routing.generate('pimcore_admin_reports_piwik_portalwidget', {configKey: config.site, widgetId: config.widget}), - params: params, - method: "GET", - ignoreErrors: true, // do not pop up error window on failure - success: function (response) { - var widget = Ext.decode(response.responseText); - var iframe = new Ext.Component({ - autoEl: { - tag: 'iframe', - src: widget.url, - frameborder: 0 - } - }); - - var title = 'Matomo/Piwik: ' + widget.title; - title += ' (period: ' + params.period + ', date: ' + params.date + ')'; - - layout.removeAll(); - layout.add(iframe); - layout.setTitle(title); - - iframe.el.dom.onload = function() { - that.loadMask.hide(); - }; - }, - failure: function (response) { - var message = t('portlet_piwik_error'); - - try { - var json = Ext.decode(response.responseText); - if (json && json.message) { - message += ' ' + json.message; - } - } catch (e) {} - - layout.removeAll(); - layout.add(new Ext.Component({ - html: message, - padding: 20, - style: "color: #ff0000" - })); - - that.loadMask.hide(); - } - }); - } -}); diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/layout/toolbar.js b/bundles/AdminBundle/Resources/public/js/pimcore/layout/toolbar.js index 5e2d8727aa3..b4eedb31ec9 100644 --- a/bundles/AdminBundle/Resources/public/js/pimcore/layout/toolbar.js +++ b/bundles/AdminBundle/Resources/public/js/pimcore/layout/toolbar.js @@ -578,70 +578,6 @@ pimcore.layout.toolbar = Class.create({ } } - if (user.isAllowed("piwik_reports") && 'undefined' !== typeof pimcore.settings.piwik && pimcore.settings.piwik.iframe_configured) { - marketingItems.push({ - text: "Matomo / Piwik", - iconCls: "pimcore_nav_icon_matomo", - handler: (function() { - // create a promise which is resolved if the request succeeds - var promise = new Ext.Promise(function (resolve, reject) { - Ext.Ajax.request({ - url: Routing.generate('pimcore_admin_reports_piwik_iframeintegration'), - ignoreErrors: true, // do not pop up error window on failure - success: function (response) { - var data = {}; - - try { - data = Ext.decode(response.responseText); - } catch (e) { - reject(e); - return; - } - - if (data && data.configured && data.url) { - resolve(data.url); - } - - reject('Matomo iframe integration is not configured.'); - }, - - failure: function(response) { - try { - var data = Ext.decode(response.responseText); - if (data && data.message) { - reject(data.message); - return; - } - } catch (e) {} - - reject(response.responseText); - } - }); - }); - - // the actual handler - return function () { - promise.then( - function (url) { - // only open window after promise was resolved - pimcore.helpers.openGenericIframeWindow( - "piwik_iframe_integration", - url, - "pimcore_icon_matomo", - "Matomo / Piwik" - ); - }, - function (message) { - if (message) { - console.error(message); - } - } - ); - }; - }()) - }); - } - if (marketingItems.length > 0) { this.marketingMenu = new Ext.menu.Menu({ items: marketingItems, diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/dashboard_iframe.js b/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/dashboard_iframe.js deleted file mode 100644 index 0799b295ae5..00000000000 --- a/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/dashboard_iframe.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Pimcore - * - * This source file is available under two different licenses: - * - GNU General Public License version 3 (GPLv3) - * - Pimcore Enterprise License (PEL) - * Full copyright and license information is available in - * LICENSE.md which is distributed with this source code. - * - * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) - * @license http://www.pimcore.org/license GPLv3 and PEL - */ - -/** - * @deprecated - */ -pimcore.registerNS("pimcore.report.piwik.dashboard_iframe"); -pimcore.report.piwik.dashboard_iframe = Class.create(pimcore.report.abstract, { - matchType: function (type) { - return !!pimcore.report.abstract.prototype.matchTypeValidate(type, ["global"]); - }, - - getName: function () { - return "pimcore_report_piwik_dashboard_iframe"; - }, - - getIconCls: function () { - return "pimcore_icon_analytics_explorer"; - }, - - getPanel: function () { - var that = this; - - this.panelId = 'report_piwik_dashboard_' + this.config.id; - this.iframeId = this.panelId + '_iframe'; - this.toolbarId = this.panelId + '_toolbar'; - - var panel = new Ext.Panel({ - title: this.config.title, - id: this.panelId, - layout: "fit", - border: false, - bodyStyle: 'padding: 5px; 10px', - items: [], - tbar: Ext.create('Ext.Toolbar', { - id: this.toolbarId, - cls: 'pimcore_main_toolbar', - items: [{ - text: t("reload"), - iconCls: "pimcore_icon_reload", - handler: this.reloadFrame.bind(this) - }, { - text: t("open"), - iconCls: "pimcore_icon_open", - handler: this.openWindow.bind(this) - }] - }) - }); - - this.loadMask = new Ext.LoadMask({ - target: panel, - msg: t("please_wait") - }); - - panel.on("afterrender", function (panel) { - that.loadMask.show(); - }.bind(this)); - - this.getReportConfig().then(function(config) { - var iframe = new Ext.Component({ - id: that.iframeId, - autoEl: { - tag: 'iframe', - src: config.url, - frameborder: 0 - } - }); - - panel.add(iframe); - - iframe.el.dom.onload = function() { - that.loadMask.hide(); - }; - }); - - return panel; - }, - - reloadFrame: function() { - var that = this; - - this.loadMask.show(); - - this.getReportConfig().then(function(config) { - Ext.get(that.iframeId).dom.src = config.url; - }); - }, - - openWindow: function() { - this.getReportConfig().then(function(config) { - window.open(config.url); - }); - }, - - /** - * @returns {Ext.Promise} - */ - getReportConfig: function() { - var that = this; - - if (!this.configPromise) { - this.configPromise = new Ext.Promise(function (resolve, reject) { - Ext.Ajax.request({ - url: Routing.generate('pimcore_admin_reports_piwik_report', {report: that.config.id}), - success: function (response) { - resolve(Ext.decode(response.responseText)); - } - }); - }); - } - - return this.configPromise; - } -}); - -pimcore.layout.treepanelmanager.addOnReadyCallback(function() { - 'use strict'; - - var user = pimcore.globalmanager.get("user"); - if (!user || !user.isAllowed("piwik_reports")) { - return; - } - - if ('undefined' === typeof pimcore.settings.piwik || 'undefined' === typeof pimcore.settings.piwik.reports) { - return; - } - - Ext.Object.each(pimcore.settings.piwik.reports, function (reportId, reportConfig) { - reportConfig.text = reportConfig.title; - - // add to report broker - pimcore.report.broker.addGroup("piwik", "Piwik", "pimcore_icon_piwik"); - pimcore.report.broker.addReport(pimcore.report.piwik.dashboard_iframe, "piwik", reportConfig); - }); -}); diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/settings.js b/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/settings.js deleted file mode 100644 index 3941be0ab5f..00000000000 --- a/bundles/AdminBundle/Resources/public/js/pimcore/report/piwik/settings.js +++ /dev/null @@ -1,426 +0,0 @@ -/** - * Pimcore - * - * This source file is available under two different licenses: - * - GNU General Public License version 3 (GPLv3) - * - Pimcore Enterprise License (PEL) - * Full copyright and license information is available in - * LICENSE.md which is distributed with this source code. - * - * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) - * @license http://www.pimcore.org/license GPLv3 and PEL - */ - -/** - * @deprecated - */ -pimcore.registerNS("pimcore.report.piwik.settings"); -pimcore.report.piwik.settings = Class.create({ - - initialize: function (parent) { - this.parent = parent; - }, - - getKey: function () { - return "piwik"; - }, - - getLayout: function () { - this.panel = new Ext.FormPanel({ - title: "Matomo/Piwik (Deprecated)", - bodyStyle: "padding: 10px;", - autoScroll: true, - items: [ - { - xtype: 'container', - html: "DEPRECATED! Will be removed in Pimcore 10
" - }, - { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_config_notice"), - cls: "pimcore_extra_label", - fieldStyle: { - color: "#ff0000" - } - }, - { - xtype: "fieldset", - defaults: { - labelWidth: 200 - }, - title: t("general_settings"), - items: [ - { - xtype: "textfield", - fieldLabel: t("piwik_url"), - name: "piwik_url", - width: 670, - id: "report_settings_piwik_url", - value: this.parent.getValue("piwik.piwik_url"), - enableKeyEvents: true - } - ] - }, - { - xtype: "fieldset", - defaults: { - labelWidth: 200 - }, - title: t("piwik_api_settings"), - collapsible: true, - collapsed: true, - items: [ - { - xtype: "textarea", - fieldLabel: t("piwik_api_client_options"), - name: "api_client_options", - height: 100, - width: 650, - id: "report_settings_piwik_api_client_options", - value: this.parent.getValue("piwik.api_client_options"), - style: "font-family: Consolas, 'Courier New', Courier, monospace;" - }, { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_api_client_options_description", null, - { guzzleLink: 'http://docs.guzzlephp.org/en/stable/request-options.html'}), - cls: "pimcore_extra_label" - } - ] - }, - { - xtype: "fieldset", - defaults: { - labelWidth: 200 - }, - title: t("piwik_tokens"), - collapsible: true, - collapsed: true, - items: [ - { - xtype: "textfield", - inputType: "password", - fieldLabel: t("piwik_api_token"), - name: "api_token", - width: 670, - id: "report_settings_piwik_api_token", - value: this.parent.getValue("piwik.api_token") - }, { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_api_token_info"), - cls: "pimcore_extra_label" - }, { - xtype: "textfield", - inputType: "password", - fieldLabel: t("piwik_report_token"), - name: "report_token", - width: 670, - id: "report_settings_piwik_report_token", - value: this.parent.getValue("piwik.report_token") - }, { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_report_token_info"), - cls: "pimcore_extra_label" - } - ] - }, - { - xtype: "fieldset", - defaults: { - labelWidth: 200 - }, - title: t("piwik_iframe_integration"), - collapsible: true, - collapsed: true, - items: [ - { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_iframe_integration_info", null , - { matomoLink: 'https://matomo.org/faq/troubleshooting/#faq_147'}), - cls: "pimcore_extra_label" - }, { - xtype: "textfield", - fieldLabel: t("piwik_iframe_username"), - name: "iframe_username", - width: 670, - id: "report_settings_piwik_iframe_username", - value: this.parent.getValue("piwik.iframe_username") - }, { - xtype: "textfield", - inputType: "password", - fieldLabel: t("piwik_iframe_password"), - name: "iframe_password", - width: 670, - id: "report_settings_piwik_iframe_password", - value: this.parent.getValue("piwik.iframe_password") - }, { - xtype: "displayfield", - width: 670, - hideLabel: true, - value: t("piwik_iframe_password_info"), - cls: "pimcore_extra_label" - } - ] - }, - { - xtype: "panel", - border: false, - items: this.getConfigurations() - } - ] - }); - - this.loadMask = new Ext.LoadMask({ - target: this.panel, - msg: t("please_wait") - }); - - this.loadMask.hide(); - - return this.panel; - }, - - getConfigurations: function () { - var configs = []; - var sites = pimcore.globalmanager.get("sites"); - - sites.each(function (record) { - var id = record.data.id; - if ("default" === id) { - key = "default"; - } else { - key = "site_" + id; - } - - configs.push(this.getConfiguration(key, record.data.domain, id)); - }, this); - - return configs; - }, - - getConfiguration: function (key, name, id) { - return { - xtype: "fieldset", - defaults: { - labelWidth: 200 - }, - title: name, - items: [ - this.buildSiteIdContainer(key, name, id), - { - xtype: "fieldset", - collapsible: true, - collapsed: true, - title: t("code_settings"), - defaults: { - labelWidth: 200 - }, - items: [{ - xtype: "textarea", - fieldLabel: t("code_before_init"), - name: "code_before_init_" + id, - height: 100, - width: 650, - id: "report_settings_piwik_code_before_init_" + id, - value: this.parent.getValue("piwik.sites." + key + ".code_before_init"), - style: "font-family: Consolas, 'Courier New', Courier, monospace;" - }, { - xtype: "textarea", - fieldLabel: t("code_before_pageview"), - name: "code_before_track_" + id, - height: 100, - width: 650, - id: "report_settings_piwik_code_before_track_" + id, - value: this.parent.getValue("piwik.sites." + key + ".code_before_track"), - style: "font-family: Consolas, 'Courier New', Courier, monospace;" - }, { - xtype: "textarea", - fieldLabel: t("code_after_pageview"), - name: "code_after_track_" + id, - height: 100, - width: 650, - id: "report_settings_piwik_code_after_track_" + id, - value: this.parent.getValue("piwik.sites." + key + ".code_after_track"), - style: "font-family: Consolas, 'Courier New', Courier, monospace;" - }] - } - ] - }; - }, - - buildSiteIdContainer: function(key, name, id) { - var that = this; - - // initial site id state when loading the panel - var siteId = this.parent.getValue("piwik.sites." + key + ".site_id"); - - var siteIdInput = new Ext.form.field.Number({ - fieldLabel: t("piwik_site_id"), - name: "site_id_" + id, - width: 300, - id: "report_settings_piwik_site_id_" + id, - value: siteId - }); - - var container = new Ext.form.FieldContainer({ - layout: 'hbox', - items: [ - siteIdInput - ] - }); - - // do not show create/update buttons if api token is not configured - if (!this.parent.getValue("piwik.api_token")) { - return container; - } - - var createHandler = function(url, method, successMessage, errorMessage) { - return function () { - that.loadMask.show(); - - Ext.Ajax.request({ - url: url, - method: method, - ignoreErrors: true, // do not pop up error window on failure - callback: function () { - that.loadMask.hide(); - }, - - success: function (response) { - var json = Ext.decode(response.responseText); - - var message = successMessage; - if (json.message) { - message += ': ' + json.message; - } - - if (json.site_id) { - siteIdInput.setValue(json.site_id); - } - - pimcore.helpers.showNotification(t("success"), message, "success"); - }, - - failure: function (response) { - var message = errorMessage; - - try { - var json = Ext.decode(response.responseText); - if (json.message) { - message += ': ' + json.message; - } - } catch (e) {} - - pimcore.helpers.showNotification(t("error"), message, "error"); - } - }); - }; - }; - - var createButton = new Ext.button.Button({ - text: t('piwik_api_create_site'), - tooltip: t('piwik_api_create_site_tooltip'), - iconCls: "pimcore_icon_piwik_api_create", - hidden: true, - style: "margin-left: 5px" - }); - - var updateButton = new Ext.button.Button({ - text: t('piwik_api_update_site'), - tooltip: t('piwik_api_update_site_tooltip'), - iconCls: "pimcore_icon_piwik_api_update", - hidden: true, - style: "margin-left: 5px" - }); - - var buttonStateHandler = function() { - var val = siteIdInput.getValue(); - - if (val && val > 0) { - createButton.hide(); - updateButton.show(); - } else { - // only show create button if there was no site ID configured - // when the panel was loaded to avoid having the create button - // showing up as soon as the value is cleared while the backend - // config still holds the site id - if (!siteId) { - createButton.show(); - } - - updateButton.hide(); - } - }; - - siteIdInput.on('change', buttonStateHandler); - buttonStateHandler(); // trigger initial state - - createButton.setHandler(createHandler( - Routing.generate('pimcore_admin_reports_piwik_apisiteupdate', {configKey: key}), - 'POST', - t("piwik_api_create_site_success"), - t("piwik_api_create_site_failure") - )); - - updateButton.setHandler(createHandler( - Routing.generate('pimcore_admin_reports_piwik_apisiteupdate', {configKey: key}), - 'PUT', - t("piwik_api_update_site_success"), - t("piwik_api_update_site_failure") - )); - - container.add(createButton); - container.add(updateButton); - - return container; - }, - - getValues: function () { - var sites = pimcore.globalmanager.get("sites"); - var sitesData = {}; - - sites.each(function (record) { - var id = record.get("id"); - if ("default" === id) { - key = "default"; - } else { - key = "site_" + id; - } - - sitesData[key] = { - site_id: Ext.getCmp("report_settings_piwik_site_id_" + id).getValue(), - code_before_init: Ext.getCmp("report_settings_piwik_code_before_init_" + id).getValue(), - code_before_track: Ext.getCmp("report_settings_piwik_code_before_track_" + id).getValue(), - code_after_track: Ext.getCmp("report_settings_piwik_code_after_track_" + id).getValue() - }; - }, this); - - return { - piwik_url: Ext.getCmp("report_settings_piwik_url").getValue(), - api_token: Ext.getCmp("report_settings_piwik_api_token").getValue(), - report_token: Ext.getCmp("report_settings_piwik_report_token").getValue(), - api_client_options: Ext.getCmp("report_settings_piwik_api_client_options").getValue(), - iframe_username: Ext.getCmp("report_settings_piwik_iframe_username").getValue(), - iframe_password: Ext.getCmp("report_settings_piwik_iframe_password").getValue(), - sites: sitesData - }; - } -}); - -pimcore.layout.treepanelmanager.addOnReadyCallback(function() { - 'use strict'; - - var user = pimcore.globalmanager.get("user"); - if (user.isAllowed("piwik_settings")) { - pimcore.report.settings.broker.push("pimcore.report.piwik.settings"); - } -}); diff --git a/bundles/CoreBundle/DependencyInjection/Compiler/DebugStopwatchPass.php b/bundles/CoreBundle/DependencyInjection/Compiler/DebugStopwatchPass.php index 5977e1c402b..67776e17d9c 100644 --- a/bundles/CoreBundle/DependencyInjection/Compiler/DebugStopwatchPass.php +++ b/bundles/CoreBundle/DependencyInjection/Compiler/DebugStopwatchPass.php @@ -18,7 +18,6 @@ namespace Pimcore\Bundle\CoreBundle\DependencyInjection\Compiler; use Pimcore\Targeting\DataLoader; -use Pimcore\Targeting\DataProvider\Piwik; use Pimcore\Targeting\Debug\TargetingDataCollector; use Pimcore\Targeting\EventListener\TargetingListener; use Pimcore\Targeting\VisitorInfoResolver; @@ -49,7 +48,6 @@ public function process(ContainerBuilder $container) VisitorInfoResolver::class, TargetingListener::class, TargetingDataCollector::class, - Piwik::class, ]; foreach ($services as $service) { diff --git a/bundles/CoreBundle/Resources/config/pimcore/default.yml b/bundles/CoreBundle/Resources/config/pimcore/default.yml index 5a81e60601f..10cc136fa6a 100644 --- a/bundles/CoreBundle/Resources/config/pimcore/default.yml +++ b/bundles/CoreBundle/Resources/config/pimcore/default.yml @@ -187,7 +187,6 @@ pimcore: device: Pimcore\Targeting\DataProvider\Device geoip: Pimcore\Targeting\DataProvider\GeoIp geolocation: Pimcore\Targeting\DataProvider\GeoLocation - piwik: Pimcore\Targeting\DataProvider\Piwik targeting_storage: Pimcore\Targeting\DataProvider\TargetingStorage visited_pages_counter: Pimcore\Targeting\DataProvider\VisitedPagesCounter conditions: @@ -202,7 +201,6 @@ pimcore: target_group: Pimcore\Targeting\Condition\TargetGroup timeonsite: Pimcore\Targeting\Condition\TimeOnSite url: Pimcore\Targeting\Condition\Url - visitedpagebefore: Pimcore\Targeting\Condition\Piwik\VisitedPageBefore visitedpagesbefore: Pimcore\Targeting\Condition\VisitedPagesBefore action_handlers: assign_target_group: Pimcore\Targeting\ActionHandler\AssignTargetGroup diff --git a/bundles/CoreBundle/Resources/config/targeting.yml b/bundles/CoreBundle/Resources/config/targeting.yml index 1abff53c126..8ecc23e8443 100644 --- a/bundles/CoreBundle/Resources/config/targeting.yml +++ b/bundles/CoreBundle/Resources/config/targeting.yml @@ -82,7 +82,6 @@ services: - [setCache, ['@Pimcore\Cache\Core\CoreCacheHandler']] - [setCachePool, ['@pimcore.cache.pool']] - Pimcore\Targeting\DataProvider\Piwik: ~ Pimcore\Targeting\DataProvider\TargetingStorage: ~ Pimcore\Targeting\Service\VisitedPagesCounter: ~ diff --git a/bundles/CoreBundle/Resources/config/targeting/listeners.yml b/bundles/CoreBundle/Resources/config/targeting/listeners.yml index 8d7e9a25bc5..2f84b2c4879 100644 --- a/bundles/CoreBundle/Resources/config/targeting/listeners.yml +++ b/bundles/CoreBundle/Resources/config/targeting/listeners.yml @@ -5,7 +5,6 @@ services: public: false Pimcore\Targeting\EventListener\TargetingListener: ~ - Pimcore\Targeting\EventListener\PiwikVisitorIdListener: ~ Pimcore\Targeting\EventListener\DocumentTargetGroupListener: ~ Pimcore\Targeting\EventListener\FullPageCacheCookieCleanupListener: ~ Pimcore\Targeting\EventListener\VisitedPagesCountListener: ~ diff --git a/bundles/CoreBundle/Resources/translations/en.extended.json b/bundles/CoreBundle/Resources/translations/en.extended.json index 09d17a8de52..8b5ec34125f 100644 --- a/bundles/CoreBundle/Resources/translations/en.extended.json +++ b/bundles/CoreBundle/Resources/translations/en.extended.json @@ -540,29 +540,6 @@ "yes_label": "Yes Display Name", "no_label": "No Display Name", "empty_label": "Empty Display Name", - "piwik_config_notice": "Please read the documentation about the Matomo\/Piwik integration first as you may need to configure your Matomo\/Piwik installation to make use of all features.", - "piwik_url": "Matomo\/Piwik URL (including protocol)", - "piwik_api_settings": "API Integration", - "piwik_api_client_options": "API Client Options", - "piwik_api_client_options_description": "You can define custom Guzzle client options as JSON string which will be used when issuing API requests. Please see the Guzzle Documentation<\/a> for a list of available options.", - "piwik_tokens": "Authentication Tokens", - "piwik_api_token": "API Token", - "piwik_api_token_info": "Authentication token used send API requests (e.g. when updating site settings). If this token is not set, Matomo\/Piwik updates from within Pimcore will not be possible.", - "piwik_api_create_site": "Create via API", - "piwik_api_create_site_tooltip": "Create a new site in Matomo\/Piwik", - "piwik_api_create_site_success": "Successfully created site via Matomo\/Piwik API.", - "piwik_api_create_site_failure": "Failed to create site via Matomo\/Piwik API.", - "piwik_api_update_site": "Update via API", - "piwik_api_update_site_tooltip": "Update site config (list of domains) via Matomo\/Piwik API", - "piwik_api_update_site_success": "Successfully updated site config via Matomo\/Piwik API.", - "piwik_api_update_site_failure": "Failed to update site config via Matomo\/Piwik API.", - "piwik_report_token": "Report Token", - "piwik_report_token_info": "Authentication token used to integrate report widgets and dashboards. If this token is not set, reporting from within Pimcore will not be possible. It's recommended to use a token with read only rights here.", - "piwik_iframe_integration": "Iframe Integration", - "piwik_iframe_integration_info": "You can embed the whole Matomo\/Piwik application as iframe by letting Pimcore generate a 'logme' URL which automatically logs the selected user into Matomo\/Piwik. To authenticate a user, Matomo\/Piwik expects a username and the user's password as MD5 hash. Please make sure to read the Matomo\/Piwik integration documentation as you need to update your Matomo\/Piwik settings for this feature (see Matomo FAQ<\/a>).", - "piwik_iframe_username": "Matomo\/Piwik Username", - "piwik_iframe_password": "Matomo\/Piwik Password (MD5)", - "piwik_iframe_password_info": "The password needs to be an MD5 hash of the actual Matomo\/Piwik password.", "gdpr_dataSource_sentMail_only_email": "Search only based on E-Mail", "imageGallery": "Image Gallery", "column_type": "Column Type", diff --git a/bundles/CoreBundle/Resources/translations/en.json b/bundles/CoreBundle/Resources/translations/en.json index bd27b216e14..913ef894b92 100644 --- a/bundles/CoreBundle/Resources/translations/en.json +++ b/bundles/CoreBundle/Resources/translations/en.json @@ -674,20 +674,6 @@ "lower": "Lower", "disabled": "Disabled", "capitalization": "Capitalization", - "piwik_all_websites_dashboard": "All Websites", - "piwik_widget_widget": "Widget", - "piwik_widget_period": "Period", - "piwik_settings": "Matomo\/Piwik Settings", - "piwik_reports": "Matomo\/Piwik Reports", - "piwik_period_day": "Day", - "piwik_period_week": "Week", - "piwik_period_month": "Month", - "piwik_period_year": "Year", - "piwik_date_yesterday": "Yesterday", - "piwik_date_today": "Today", - "portlet_piwik_widget": "Matomo\/Piwik Widget", - "portlet_piwik_unconfigured": "Please use the gear icon to configure the widget.", - "portlet_piwik_error": "Failed to load widget.", "restrict_to_locales": "Restrict to locales", "predefined": "Predefined", "save_as_copy": "Save as copy", diff --git a/bundles/CoreBundle/Resources/views/Analytics/Tracking/Piwik/trackingCode.html.twig b/bundles/CoreBundle/Resources/views/Analytics/Tracking/Piwik/trackingCode.html.twig deleted file mode 100644 index 3bfb74607d5..00000000000 --- a/bundles/CoreBundle/Resources/views/Analytics/Tracking/Piwik/trackingCode.html.twig +++ /dev/null @@ -1,34 +0,0 @@ -{% block beforeScriptTag %}{{ blocks.beforeScriptTag|raw }}{% endblock %} - - - -{% block afterScriptTag %}{{ blocks.afterScriptTag|raw }}{% endblock %} diff --git a/bundles/EcommerceFrameworkBundle/Resources/config/services.yml b/bundles/EcommerceFrameworkBundle/Resources/config/services.yml index 26f8e9f25fb..e51a27e5cc7 100644 --- a/bundles/EcommerceFrameworkBundle/Resources/config/services.yml +++ b/bundles/EcommerceFrameworkBundle/Resources/config/services.yml @@ -32,9 +32,3 @@ services: public: true tags: ['controller.service_arguments'] - - # - # REPORTS - # - - Pimcore\Bundle\EcommerceFrameworkBundle\Reports\Piwik\PiwikReportsProvider: ~ diff --git a/bundles/InstallBundle/Installer.php b/bundles/InstallBundle/Installer.php index 4e34045ff2a..14363bd0d3d 100644 --- a/bundles/InstallBundle/Installer.php +++ b/bundles/InstallBundle/Installer.php @@ -759,8 +759,6 @@ protected function insertDatabaseContents() ['key' => 'http_errors'], ['key' => 'notes_events'], ['key' => 'objects'], - ['key' => 'piwik_settings'], - ['key' => 'piwik_reports'], ['key' => 'plugins'], ['key' => 'predefined_properties'], ['key' => 'asset_metadata'], diff --git a/doc/Development_Documentation/10_E-Commerce_Framework/19_Tracking_Manager.md b/doc/Development_Documentation/10_E-Commerce_Framework/19_Tracking_Manager.md index ec77c3f2e2b..317cae16594 100644 --- a/doc/Development_Documentation/10_E-Commerce_Framework/19_Tracking_Manager.md +++ b/doc/Development_Documentation/10_E-Commerce_Framework/19_Tracking_Manager.md @@ -9,7 +9,6 @@ Current implementations of trackers are * **Google Analytics Classic**: `\Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker\Analytics\Ecommerce` * **Google Analytics Universal**: `\Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker\Analytics\UniversalEcommerce` * **Google Analytics Enhanced E-Commerce**: `\Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker\Analytics\EnhancedEcommerce` -* **Matomo**: `\Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker\Piwik` ## Supported Tracking Actions @@ -33,8 +32,7 @@ trackers. * `$trackingManager->trackProductActionRemove($cart, $product, $quantity)` * Cart Update * Tracks a generic cart update for trackers not supporting add/remove. This can be sent on every cart list or cart - change (see [Piwik Docs](https://piwik.org/docs/ecommerce-analytics/#tracking-add-to-cart-items-added-to-the-cart-optional) - for an example) + change. * `$trackingManager->trackProductActionRemove($cart, $product, $quantity)` * Checkout * Tracks start of checkout with first step diff --git a/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/07_Piwik.md b/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/07_Piwik.md deleted file mode 100644 index 9b00d152135..00000000000 --- a/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/07_Piwik.md +++ /dev/null @@ -1,187 +0,0 @@ -# [Deprecated] Matomo (formerly known as Piwik) - -Similar to Google Analytics, a Matomo tracking code can be automatically injected into each response. For a basic tracking -integration you need to know the following: - -* The URL to the Matomo installation you want to use -* The Matomo Site ID where you want to track your site - -The Matomo URL needs to be the full URL to your piwik installation including protocol and an optional path on the -server if Matomo is not installed into the document root. Valid examples: - -* `https://matomo.example.com` -* `https://analytics.example.com/matomo` - -Wrong: - -* `matomo.example.com` -* `//matomo.example.com` - -Similar to Google Analytics, you can configure the Site ID and optional code snippets which should be added to the tracking -code on a per-site level. All settings can be configured in the Matomo tab of the Marketing Settings panel. - -![Matomo Site Settings](../../img/piwik_site_settings.png) - - -## Integrating Matomo into the Admin UI - -Matomo reports can be integrated into the Admin UI at several places like the dashboard, the reports panel or as full iframe -integration of the whole Matomo app. To make those features available, you need to configure a **Report Token** in the -*Authentication Tokens* Section of the settings tab. This report token will be used for authentication when integrating -report iframes. - -The API token for a user can be found in Matomo's API settings panel (please see the [Matomo FAQ](https://matomo.org/faq/general/faq_114/) -for details). - -As soon as this token is configured, you can use Matomo's wigets in the Dashboard and the Reports panel: - -![Matomo Dashboard](../../img/piwik_dashboard.png) -![Matomo Reports Panel](../../img/piwik_reports.png) - -**Important:** It is recommended to create a dedicated reporting user with **view only** permissions and to use this token -as report token. As the token acts like a password and can be extracted from the iframe URL, users could potentially use -this token to change Matomo settings. - - -### Iframe Integration - -Additionally you can integrate the whole Matomo app as iframe by using Matomo's [logme()](https://piwik.org/faq/how-to/#faq_30) -functionality. To use this integration, you need to configure the Matomo username to access to iframe and the **MD5 hash** -of its password (not the plain text password itself!). Similar to the report token, you should use a user with **view only** -permissions here. - -Further more, you might need to enable the setting `enable_framed_pages` in the Matomo config (see -[Matomo FAQ](https://matomo.org/faq/troubleshooting/faq_147/)) to allow the iframe to be displayed. - -After the iframe integration is configured, you'll find a new menu entry in the marketing menu: - -![Matomo Iframe integration](../../img/piwik_iframe_integration.png) - - -### Updating site settings from the Pimcore Admin - -Certain site settings (currently only the list of valid domains) can be automatically exported from Pimcore to the Matomo -site configuration. To activate this feature, you need to configure an API token which will be used for API requests. - -> As you'll use this token to update Matomo's settings, this token (its user) needs to be configured with write access. - -With a configured API token, each site will show a button to either create a site or update a site's settings: - -![Matomo API Update Buttons](../../img/piwik_api_update_buttons.png) - -If you need to pass custom options to the Matomo API client, you can configure a list of Guzzle Request Options as JSON -string in the *API Integration* section: - -![Matomo API Client Options](../../img/piwik_api_client_options.png) - - -## Customizing the tracking code - -If you want to influence the generated tracking code, you have multiple possibilities to do so. The tracker code is divided -into multiple code blocks which can be expanded and altered individually. As reference, please see: - -* the definition of available blocks in the [Tracker implementation](https://github.com/pimcore/pimcore/blob/master/lib/Analytics/Piwik/Tracker.php#L63) -* the [template](https://github.com/pimcore/pimcore/blob/master/bundles/CoreBundle/Resources/views/Analytics/Tracking/Piwik/trackingCode.html.twig) - which defines where the content of each blocks is rendered - -### Adding code to a block - -The central part of the Matomo tracking is the `Pimcore\Analytics\Piwik\Tracker` class which is defined as service and which -provides a `addCodePart()` method which allows you to add custom code snippets to a specific block: - -```php -addCodePart('console.log("foo");'); - - // append a part to a specific block - $tracker->addCodePart('console.log("foo");', Tracker::BLOCK_BEFORE_TRACK); - - // prepend a part to a specific block - $tracker->addCodePart('console.log("foo");', Tracker::BLOCK_TRACK, true); - - // you can also add the code only for a specific site - // if you want to do so, you need to pass a SiteId object which identifies a tracking site - $tracker->addCodePart('console.log("foo");', Tracker::BLOCK_TRACK, true, SiteId::forMainDomain()); - } -} -``` - -### Influencing generated code through the `CODE_TRACKING_DATA` event - -Before the tracking code is generated, the `PiwikEvents::CODE_TRACKING_DATA` event is dispatched which gives you full control -over the generated code: - -```php - 'onTrackingData' - ]; - } - - public function onTrackingData(TrackingDataEvent $event) - { - // append data to a block - $event->getBlock(Tracker::BLOCK_TRACK)->append([ - 'console.log("foo");' - ]); - - // completely empty the track block - $event->getBlock(Tracker::BLOCK_TRACK)->setParts([]); - - // the data array is the data which will be passed to the template - $data = $event->getData(); - $data['foo'] = 'bar'; - $event->setData($data); - - // you can also completely replace the rendered template - $event->setTemplate('@App/Analytics/Tracking/Piwik/trackingCode.html.twig'); - } -} -``` - -### Overriding the rendered template - -As you can see in the sample event listener above, you can change the template which will be used for the tracking code. -If you set a custom template, you can extend the core one and just override the blocks you want: - -```twig -{# src/AppBundle/Resources/views/Analytics/Tracking/Piwik/trackingCode.html.twig #} -{% extends "@PimcoreCore/Analytics/Tracking/Piwik/trackingCode.html.twig" %} - -{% block asyncInit %} - {{ parent() }} - - console.log('hello world'); -{% endblock %} - -{% block afterScriptTag %} - {{ parent() }} - - -{% endblock %} -``` diff --git a/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/README.md b/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/README.md index 96e63e744d3..2cec4225215 100644 --- a/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/README.md +++ b/doc/Development_Documentation/18_Tools_and_Features/28_Marketing_Settings/README.md @@ -5,7 +5,6 @@ The `Marketing Settings` give you the possibility to configure marketing-specifi - [Google Analytics](./05_Analytics.md) - Google Search Console - Google Tag Manager -- [Matomo](./07_Piwik.md) ## Google Analytics @@ -22,9 +21,3 @@ possibilities through: * the `GoogleTagManagerEvents::CODE_HEAD` and `GoogleTagManagerEvents::CODE_BODY` events, each defining a set of customizable blocks * a dedicated template for both events which can be customized from an event listener - - -## Matomo - -Similar to Google Analytics, a Matomo tracking code can be automatically injected into each response. See [Matomo](./07_Piwik.md) -for details. diff --git a/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/01_Visitor_Info.md b/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/01_Visitor_Info.md index af5896cbdf0..5901809ddb3 100644 --- a/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/01_Visitor_Info.md +++ b/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/01_Visitor_Info.md @@ -10,12 +10,9 @@ request. To identify returning visitors, the engine needs some kind of unique identificator which will be assigned to each visitor. This identificator, internally referred to as `visitor ID`, is expected to be generated or set by the browser and to be stored as a cookie. When creating a `VisitorInfo` the targeting engine tries to load a visitor ID from the `_pc_vis` cookie. -This ID is (by default) generated by the frontend on 2 events: +This ID is (by default) generated by the frontend on event: * when loading a site with targeting enabled and no visitor ID was previously set, a random string is generated -* if Matomo integration is configured and the tracker is loaded, the unique Matomo visitor ID will be used. This has the - advantage that tracking for returining visitors or logged in users can be implemented based on Matomo's - [User ID](https://matomo.org/docs/user-id/) feature If you want to manually set the visitor ID in your frontend code you can do so with the following call which is exposed by the targeting JS implementation: diff --git a/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/11_Frontend_Javascript.md b/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/11_Frontend_Javascript.md index 6a441cb240f..3f393906ebe 100644 --- a/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/11_Frontend_Javascript.md +++ b/doc/Development_Documentation/18_Tools_and_Features/37_Targeting_and_Personalization/11_Frontend_Javascript.md @@ -83,10 +83,6 @@ The listener above sets a custom template which can either extend the core one o {% endblock %} ``` -As this makes use of the same extension/code block system as the [Matomo Tracking Integration](../28_Marketing_Settings/07_Piwik.md) -see its documentation page for further details. - - ## Frontend Data Providers Some conditions or data providers might need data from the frontend. To make this possible, a backend implementation can diff --git a/lib/Analytics/Piwik/Api/ApiClient.php b/lib/Analytics/Piwik/Api/ApiClient.php deleted file mode 100644 index 151d98eb261..00000000000 --- a/lib/Analytics/Piwik/Api/ApiClient.php +++ /dev/null @@ -1,144 +0,0 @@ -configProvider = $configProvider; - $this->clientFactory = $clientFactory; - $this->serializer = $serializer; - } - - /** - * Send a GET request - * - * @param array $query Query params - * @param array $options Valid options for Guzzle - * - * @return array - */ - public function get(array $query = [], array $options = []): array - { - $options['query'] = array_merge($options['query'] ?? [], $query); - - return $this->requestRaw('GET', $options); - } - - /** - * Send a request - * - * @param string $method Request method - * @param array $options Valid options for Guzzle - * - * @return array - */ - public function request(string $method, array $options = []): array - { - return $this->requestRaw($method, $options); - } - - /** - * @param string $method - * @param array $options - * - * @return array - */ - private function requestRaw(string $method, array $options): array - { - $client = $this->getClient(); - $response = $client->request($method, '', $options); - - if (200 !== $response->getStatusCode()) { - throw new ApiException($response->getReasonPhrase()); - } - - $json = $this->serializer->decode($response->getBody()->getContents(), 'json'); - - if (!is_array($json)) { - throw new ApiException('Unexpected response format'); - } - - if (isset($json['result']) && 'error' === $json['result']) { - throw ApiException::fromResponse($json['message'], $json); - } - - return $json; - } - - private function getClient(): Client - { - if (null !== $this->client) { - return $this->client; - } - - $config = $this->configProvider->getConfig(); - - $options = array_merge([ - 'base_uri' => $this->getBaseUri($config), - ], $config->getApiClientOptions()); - - $this->client = $this->clientFactory->createClient($options); - - return $this->client; - } - - private function getBaseUri(Config $config): string - { - if (!$config->isConfigured()) { - throw new \RuntimeException('Piwik is not configured'); - } - - return $config->getPiwikUrl(); - } -} diff --git a/lib/Analytics/Piwik/Api/Exception/ApiException.php b/lib/Analytics/Piwik/Api/Exception/ApiException.php deleted file mode 100644 index d544b0c1755..00000000000 --- a/lib/Analytics/Piwik/Api/Exception/ApiException.php +++ /dev/null @@ -1,54 +0,0 @@ -response = $response; - - return $ex; - } - - /** - * @return array|null - */ - public function getResponse() - { - return $this->response; - } -} diff --git a/lib/Analytics/Piwik/Api/SitesManager.php b/lib/Analytics/Piwik/Api/SitesManager.php deleted file mode 100644 index ee256aecbba..00000000000 --- a/lib/Analytics/Piwik/Api/SitesManager.php +++ /dev/null @@ -1,244 +0,0 @@ -config = $configProvider->getConfig(); - $this->apiClient = $apiClient; - $this->configWriter = $configWriter; - $this->translator = $translator; - $this->pimcoreConfig = $pimcoreConfig; - } - - public function addSite(SiteId $siteId, array $params = []): int - { - $piwikSiteId = $this->config->getPiwikSiteId($siteId->getConfigKey()); - if (null !== $piwikSiteId) { - throw new \LogicException(sprintf( - 'The site "%s" already defines a Piwik site ID. Please use updateSite instead.', - $siteId->getConfigKey() - )); - } - - $params = array_merge($this->buildParameters([ - 'method' => 'SitesManager.addSite', - 'siteName' => $siteId->getTitle($this->translator), - 'urls' => $this->buildSiteUrls($siteId), - ]), $params); - - $response = $this->apiClient->request('POST', [ - 'query' => $params, - ]); - - $piwikSiteId = $response['value'] ?? null; - if (!$piwikSiteId) { - throw new \RuntimeException('Failed to read Piwik site ID from API response'); - } - - $piwikSiteId = (int)$piwikSiteId; - if ($piwikSiteId < 1) { - throw new \RuntimeException('Returned Piwik site ID is invalid'); - } - - // save site ID to config - $this->savePiwikSiteId($siteId, $piwikSiteId); - - return $piwikSiteId; - } - - public function updateSite(SiteId $siteId, array $params = []): int - { - $piwikSiteId = $this->config->getPiwikSiteId($siteId->getConfigKey()); - - if (null === $piwikSiteId) { - throw new \LogicException(sprintf( - 'The site "%s" does not define a Piwik site ID. Please use createSite instead.', - $siteId->getConfigKey() - )); - } - - $currentUrls = $this->getSiteUrlsFromId($piwikSiteId); - - $params = array_merge($this->buildParameters([ - 'method' => 'SitesManager.updateSite', - 'idSite' => $piwikSiteId, - 'urls' => $this->buildSiteUrls($siteId, $currentUrls), - ]), $params); - - $response = $this->apiClient->request('POST', [ - 'query' => $params, - ]); - - if ('success' === $response['result'] && 'ok' === $response['message']) { - return $piwikSiteId; - } - - throw ApiException::fromResponse('SitesManager.updateSite() request failed', $response); - } - - public function getSiteFromId(int $piwikSiteId, array $params = []): array - { - $params = array_merge($this->buildParameters([ - 'method' => 'SitesManager.getSiteFromId', - 'idSite' => $piwikSiteId, - ]), $params); - - $response = $this->apiClient->get($params); - - if ($response && count($response) === 1) { - return $response[0]; - } - - throw ApiException::fromResponse( - 'Unexpected API response format. Expected array with a single entry for SitesManager.getSiteFromId.', - $response - ); - } - - public function getSiteUrlsFromId(int $piwikSiteId, array $params = []): array - { - $params = array_merge($this->buildParameters([ - 'method' => 'SitesManager.getSiteUrlsFromId', - 'idSite' => $piwikSiteId, - ]), $params); - - return $this->apiClient->get($params); - } - - private function buildParameters(array $parameters): array - { - return array_merge([ - 'module' => 'API', - 'format' => 'JSON', - 'token_auth' => $this->getApiToken(), - ], $parameters); - } - - private function buildSiteUrls(SiteId $siteId, array $urls = []): array - { - $siteUrls = []; - if ($site = $siteId->getSite()) { - if (!empty($site->getMainDomain())) { - $siteUrls[] = $site->getMainDomain(); - } - - foreach ($site->getDomains() as $domain) { - if (!empty($domain)) { - $siteUrls[] = $domain; - } - } - } elseif (SiteId::CONFIG_KEY_MAIN_DOMAIN === $siteId->getConfigKey()) { - if (!empty($this->pimcoreConfig['general']['domain'])) { - $siteUrls[] = $this->pimcoreConfig['general']['domain']; - } - } - - // only add urls which are not already in the list - foreach ($siteUrls as $siteUrl) { - if (!in_array($siteUrl, $urls)) { - $urls[] = $siteUrl; - } - } - - // API request could return empty URLs - if only sending those - // back the API will quit with an error expecting at least one URL - // while an empty array is fine - $urls = array_filter($urls, function ($url) { - return !empty($url); - }); - - return $urls; - } - - private function getApiToken(): string - { - $apiToken = $this->config->getApiToken(); - if (null === $apiToken) { - throw new \LogicException('Piwik API token is not configured'); - } - - return $apiToken; - } - - /** - * Save returned site ID back to the config - * - * @param SiteId $siteId - * @param int $piwikSiteId - */ - private function savePiwikSiteId(SiteId $siteId, int $piwikSiteId) - { - $configKey = $siteId->getConfigKey(); - - $this->configWriter->mergeArray([ - 'piwik' => [ - 'sites' => [ - $configKey => [ - 'site_id' => $piwikSiteId, - ], - ], - ], - ]); - } -} diff --git a/lib/Analytics/Piwik/Api/VisitorClient.php b/lib/Analytics/Piwik/Api/VisitorClient.php deleted file mode 100644 index c59bcb7cb4b..00000000000 --- a/lib/Analytics/Piwik/Api/VisitorClient.php +++ /dev/null @@ -1,67 +0,0 @@ -apiClient = $apiClient; - $this->config = $config; - } - - public function getVisitorProfile(int $piwikSiteId, string $visitorId): array - { - $result = $this->apiClient->get($this->buildParameters([ - 'method' => 'Live.getVisitorProfile', - 'idSite' => $piwikSiteId, - 'visitorId' => $visitorId, - ])); - - return $result; - } - - private function buildParameters(array $parameters): array - { - $token = $this->config->getReportToken(); - if (null === $token) { - throw new \LogicException('Piwik report token is not configured'); - } - - return array_merge([ - 'module' => 'API', - 'format' => 'JSON', - 'token_auth' => $token, - ], $parameters); - } -} diff --git a/lib/Analytics/Piwik/Config/Config.php b/lib/Analytics/Piwik/Config/Config.php deleted file mode 100644 index 67a8fc65483..00000000000 --- a/lib/Analytics/Piwik/Config/Config.php +++ /dev/null @@ -1,246 +0,0 @@ -config = $config; - } - - public static function fromReportConfig(ConfigObject $reportConfig): self - { - $config = null; - if ($reportConfig->get('piwik')) { - $config = $reportConfig->get('piwik'); - } else { - $config = new ConfigObject([]); - } - - return new self($config); - } - - public function isConfigured(): bool - { - if (null === $this->getPiwikUrl()) { - return false; - } - - return true; - } - - public function getConfig(): ConfigObject - { - return $this->config; - } - - public function isSiteConfigured(string $configKey): bool - { - $config = $this->getConfigForSite($configKey); - - if (null === $config) { - return false; - } - - $piwikSiteId = $this->normalizePiwikSiteId($config); - if (null === $piwikSiteId) { - return false; - } - - return true; - } - - /** - * @param string $configKey - * - * @return null|ConfigObject - */ - public function getConfigForSite(string $configKey) - { - if (!$this->config->get('sites') || !$this->config->get('sites')->$configKey) { - return null; - } - - return $this->config->get('sites')->$configKey; - } - - public function getConfiguredSites(): array - { - $sites = $this->config->get('sites'); - if ($sites && $sites instanceof ConfigObject) { - return array_keys($sites->toArray()); - } - - return []; - } - - /** - * @return string|null - */ - public function getPiwikUrl() - { - $url = $this->normalizeStringValue($this->config->get('piwik_url')); - - if (null !== $url && 0 !== strpos($url, 'http')) { - $url = null; - - @trigger_error( - 'Configured Piwik URL does not include a protocol (https:// or http://). Please update your settings to re-enable Piwik.', - E_USER_DEPRECATED - ); - } - - return $url; - } - - /** - * @return string|null - */ - public function getApiToken() - { - return $this->normalizeStringValue($this->config->get('api_token')); - } - - /** - * @return string|null - */ - public function getReportToken() - { - return $this->normalizeStringValue($this->config->get('report_token')); - } - - public function getApiClientOptions(): array - { - $value = $this->normalizeStringValue($this->config->get('api_client_options')); - if (empty($value)) { - return []; - } - - $options = @json_decode($value, true); - if (is_array($options)) { - return $options; - } - - return []; - } - - /** - * @param string $configKey - * - * @return int|null - */ - public function getPiwikSiteId(string $configKey) - { - $config = $this->getConfigForSite($configKey); - if (null !== $config) { - return $this->normalizePiwikSiteId($config); - } - - return null; - } - - public function isIframeIntegrationConfigured(): bool - { - return !empty($this->getIframeUsername()) && !empty($this->getIframePassword()); - } - - /** - * @return null|string - */ - public function getIframeUsername() - { - return $this->normalizeStringValue($this->config->get('iframe_username')); - } - - /** - * @return null|string - */ - public function getIframePassword() - { - return $this->normalizeStringValue($this->config->get('iframe_password')); - } - - public function generateIframeUrl(array $parameters = []): string - { - if (!$this->isIframeIntegrationConfigured()) { - throw new \RuntimeException('Iframe integration is not configured'); - } - - $parameters = array_merge([ - 'module' => 'Login', - 'action' => 'logme', - 'login' => $this->getIframeUsername(), - 'password' => $this->getIframePassword(), - ], $parameters); - - return sprintf( - '%s/index.php?%s', - rtrim($this->getPiwikUrl(), '/'), - http_build_query($parameters) - ); - } - - /** - * @param mixed $value - * - * @return string|null - */ - private function normalizeStringValue($value) - { - if (null === $value) { - return $value; - } - - $value = trim((string)$value); - if (empty($value)) { - return null; - } - - return $value; - } - - /** - * @param ConfigObject $config - * - * @return int|null - */ - private function normalizePiwikSiteId(ConfigObject $config) - { - if (!$config->get('site_id')) { - return null; - } - - $piwikSiteId = (int)$config->get('site_id'); - if ($piwikSiteId > 0) { - return $piwikSiteId; - } - - return null; - } -} diff --git a/lib/Analytics/Piwik/Config/ConfigProvider.php b/lib/Analytics/Piwik/Config/ConfigProvider.php deleted file mode 100644 index 0542e7cbf65..00000000000 --- a/lib/Analytics/Piwik/Config/ConfigProvider.php +++ /dev/null @@ -1,74 +0,0 @@ -configObject = $configObject; - } - - public function getConfig(): Config - { - if (null === $this->config) { - $this->config = new Config($this->getConfigObject()); - } - - return $this->config; - } - - private function getConfigObject(): ConfigObject - { - if (null === $this->configObject) { - $this->configObject = $this->loadDefaultConfigObject(); - } - - return $this->configObject; - } - - protected function loadDefaultConfigObject(): ConfigObject - { - $reportConfig = \Pimcore\Config::getReportConfig(); - - $config = $reportConfig->get('piwik'); - if (!$config instanceof ConfigObject) { - $config = new ConfigObject([]); - } - - return $config; - } -} diff --git a/lib/Analytics/Piwik/Dto/ReportConfig.php b/lib/Analytics/Piwik/Dto/ReportConfig.php deleted file mode 100644 index f0ee98f6079..00000000000 --- a/lib/Analytics/Piwik/Dto/ReportConfig.php +++ /dev/null @@ -1,61 +0,0 @@ -id = $id; - $this->title = $title; - $this->url = $url; - } - - public function getId(): string - { - return $this->id; - } - - public function getTitle(): string - { - return $this->title; - } - - public function getUrl(): string - { - return $this->url; - } -} diff --git a/lib/Analytics/Piwik/Dto/WidgetConfig.php b/lib/Analytics/Piwik/Dto/WidgetConfig.php deleted file mode 100644 index 03977dd8209..00000000000 --- a/lib/Analytics/Piwik/Dto/WidgetConfig.php +++ /dev/null @@ -1,83 +0,0 @@ -id = $id; - $this->name = $name; - $this->title = $title; - $this->url = $url; - $this->data = $data; - } - - public function getId(): string - { - return $this->id; - } - - public function getName(): string - { - return $this->name; - } - - public function getTitle(): string - { - return $this->title; - } - - public function getUrl(): string - { - return $this->url; - } - - public function getData(): array - { - return $this->data; - } -} diff --git a/lib/Analytics/Piwik/Dto/WidgetReference.php b/lib/Analytics/Piwik/Dto/WidgetReference.php deleted file mode 100644 index e4ecfa597a4..00000000000 --- a/lib/Analytics/Piwik/Dto/WidgetReference.php +++ /dev/null @@ -1,50 +0,0 @@ -id = $id; - $this->title = $title; - } - - public function getId(): string - { - return $this->id; - } - - public function getTitle(): string - { - return $this->title; - } -} diff --git a/lib/Analytics/Piwik/Event/ReportConfigEvent.php b/lib/Analytics/Piwik/Event/ReportConfigEvent.php deleted file mode 100644 index 3af7d676858..00000000000 --- a/lib/Analytics/Piwik/Event/ReportConfigEvent.php +++ /dev/null @@ -1,62 +0,0 @@ -setReports($reports); - } - - /** - * @return ReportConfig[] - */ - public function getReports(): array - { - return $this->reports; - } - - public function setReports(array $reports) - { - $this->reports = []; - - foreach ($reports as $report) { - $this->addReport($report); - } - } - - public function addReport(ReportConfig $report) - { - $this->reports[] = $report; - } -} diff --git a/lib/Analytics/Piwik/Event/TrackingDataEvent.php b/lib/Analytics/Piwik/Event/TrackingDataEvent.php deleted file mode 100644 index 1440c2f9810..00000000000 --- a/lib/Analytics/Piwik/Event/TrackingDataEvent.php +++ /dev/null @@ -1,115 +0,0 @@ -config = $config; - $this->siteId = $siteId; - $this->data = $data; - $this->blocks = $blocks; - $this->template = $template; - } - - public function getConfig(): Config - { - return $this->config; - } - - public function getSiteId(): SiteId - { - return $this->siteId; - } - - public function getData(): array - { - return $this->data; - } - - public function setData(array $data) - { - $this->data = $data; - } - - /** - * @return CodeBlock[] - */ - public function getBlocks(): array - { - return $this->blocks; - } - - public function getBlock(string $block): CodeBlock - { - if (!isset($this->blocks[$block])) { - throw new \InvalidArgumentException(sprintf('Invalid block "%s"', $block)); - } - - return $this->blocks[$block]; - } - - public function getTemplate(): string - { - return $this->template; - } - - public function setTemplate(string $template) - { - $this->template = $template; - } -} diff --git a/lib/Analytics/Piwik/EventListener/CacheListener.php b/lib/Analytics/Piwik/EventListener/CacheListener.php deleted file mode 100644 index 4e30df75275..00000000000 --- a/lib/Analytics/Piwik/EventListener/CacheListener.php +++ /dev/null @@ -1,56 +0,0 @@ -cache = $cache; - } - - public static function getSubscribedEvents() - { - return [ - ReportEvents::SAVE_SETTINGS => 'onSaveSettings', - ]; - } - - public function onSaveSettings(SettingsEvent $event) - { - // clear piwik cache tag when report settings are saved - // to make sure cached data (e.g. widgets) is refreshed - $this->cache->clearTag('piwik'); - } -} diff --git a/lib/Analytics/Piwik/EventListener/IndexSettingsListener.php b/lib/Analytics/Piwik/EventListener/IndexSettingsListener.php deleted file mode 100644 index f45bf5e09d8..00000000000 --- a/lib/Analytics/Piwik/EventListener/IndexSettingsListener.php +++ /dev/null @@ -1,104 +0,0 @@ -configProvider = $configProvider; - $this->reportBroker = $reportBroker; - $this->userResolver = $tokenStorageUserResolver; - } - - public static function getSubscribedEvents() - { - return [ - AdminEvents::INDEX_ACTION_SETTINGS => 'addIndexSettings', - ]; - } - - /** - * Handles INDEX_ACTION_SETTINGS event and adds piwik reports to settings - * - * @param IndexActionSettingsEvent $event - */ - public function addIndexSettings(IndexActionSettingsEvent $event) - { - $user = $this->userResolver->getUser(); - if (!$user || !$user->isAllowed('piwik_reports')) { - return; - } - - $config = $this->configProvider->getConfig(); - - $settings = [ - 'configured' => $config->isConfigured(), - 'iframe_configured' => $config->isIframeIntegrationConfigured(), - 'report_token_configured' => !empty($config->getReportToken()), - 'api_token_configured' => !empty($config->getApiToken()), - ]; - - $settings = $this->addReportSettings($settings); - - $event->addSetting('piwik', $settings); - } - - private function addReportSettings(array $settings): array - { - $reports = []; - foreach ($this->reportBroker->getReports() as $report) { - $reports[$report->getId()] = [ - 'id' => $report->getId(), - 'title' => $report->getTitle(), - ]; - } - - $settings['reports'] = $reports; - - return $settings; - } -} diff --git a/lib/Analytics/Piwik/EventListener/TrackingCodeListener.php b/lib/Analytics/Piwik/EventListener/TrackingCodeListener.php deleted file mode 100644 index 1a679485b8c..00000000000 --- a/lib/Analytics/Piwik/EventListener/TrackingCodeListener.php +++ /dev/null @@ -1,113 +0,0 @@ -tracker = $tracker; - } - - public static function getSubscribedEvents() - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -110], - ]; - } - - public function enable() - { - $this->enabled = true; - } - - public function disable() - { - $this->enabled = false; - } - - public function isEnabled(): bool - { - return $this->enabled; - } - - public function onKernelResponse(ResponseEvent $event) - { - if (!$this->enabled) { - return; - } - - $request = $event->getRequest(); - if (!$event->isMasterRequest()) { - return; - } - - // only inject analytics code on non-admin requests - if (!$this->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_DEFAULT)) { - return; - } - - if ($this->isPreviewRequest($request)) { - return; - } - - // output filters are disabled - if (!Tool::useFrontendOutputFilters($event->getRequest())) { - return; - } - - $response = $event->getResponse(); - if (!$this->isHtmlResponse($response)) { - return; - } - - $code = $this->tracker->generateCode(); - if (empty($code)) { - return; - } - - $this->injectBeforeHeadEnd($response, $code); - } -} diff --git a/lib/Analytics/Piwik/ReportBroker.php b/lib/Analytics/Piwik/ReportBroker.php deleted file mode 100644 index e32f715e352..00000000000 --- a/lib/Analytics/Piwik/ReportBroker.php +++ /dev/null @@ -1,191 +0,0 @@ -configProvider = $configProvider; - $this->siteIdProvider = $siteIdProvider; - $this->eventDispatcher = $eventDispatcher; - $this->translator = $translator; - } - - /** - * @return ReportConfig[] - */ - public function getReports(): array - { - if (null !== $this->reports) { - return $this->reports; - } - - $reports = $this->buildReports(); - - $event = new Event\ReportConfigEvent($reports); - $this->eventDispatcher->dispatch($event, PiwikEvents::GENERATE_REPORTS); - - $this->reports = []; - foreach ($event->getReports() as $report) { - $this->reports[$report->getId()] = $report; - } - - return $this->reports; - } - - public function getReport(string $id): ReportConfig - { - $reports = $this->getReports(); - - if (!isset($reports[$id])) { - throw new \InvalidArgumentException(sprintf('Report "%s" was not found', $id)); - } - - return $reports[$id]; - } - - private function buildReports(): array - { - $config = $this->configProvider->getConfig(); - - /** @var ReportConfig[] $reports */ - $reports = []; - if (!$config->isConfigured()) { - return $reports; - } - - $reportToken = $config->getReportToken(); - if (empty($reportToken)) { - return $reports; - } - - $siteIds = $this->siteIdProvider->getSiteIds(); - $firstConfigKey = null; - - foreach ($siteIds as $siteId) { - $configKey = $siteId->getConfigKey(); - - if (!$config->isSiteConfigured($configKey)) { - continue; - } - - $reports[] = new ReportConfig( - $configKey, - $siteId->getTitle($this->translator), - $this->generateSiteDashboardUrl($config, $configKey) - ); - - if (null === $firstConfigKey) { - $firstConfigKey = $configKey; - } - } - - // add an "all websites report" if any reports were configured - if (null !== $firstConfigKey) { - array_unshift($reports, new ReportConfig( - 'all_sites', - $this->translator->trans('piwik_all_websites_dashboard', [], 'admin'), - $this->generateAllWebsitesDashboardUrl($config, $firstConfigKey) - )); - } - - return $reports; - } - - private function generateAllWebsitesDashboardUrl(Config $config, string $configKey): string - { - $params = [ - 'moduleToWidgetize' => 'MultiSites', - 'actionToWidgetize' => 'standalone', - ]; - - return $this->generateDashboardUrl($config, $configKey, $params); - } - - private function generateSiteDashboardUrl(Config $config, string $configKey): string - { - $params = [ - 'moduleToWidgetize' => 'Dashboard', - 'actionToWidgetize' => 'index', - ]; - - return $this->generateDashboardUrl($config, $configKey, $params); - } - - private function generateDashboardUrl(Config $config, string $configKey, array $parameters) - { - $parameters = array_merge([ - 'module' => 'Widgetize', - 'action' => 'iframe', - 'period' => 'week', - 'date' => 'yesterday', - 'idSite' => $config->getPiwikSiteId($configKey), - 'token_auth' => $config->getReportToken(), - ], $parameters); - - return sprintf( - '%s/index.php?%s', - rtrim($config->getPiwikUrl(), '/'), - http_build_query($parameters) - ); - } -} diff --git a/lib/Analytics/Piwik/Tracker.php b/lib/Analytics/Piwik/Tracker.php deleted file mode 100644 index 24d31e5f1fe..00000000000 --- a/lib/Analytics/Piwik/Tracker.php +++ /dev/null @@ -1,194 +0,0 @@ -configProvider = $configProvider; - $this->eventDispatcher = $eventDispatcher; - $this->twig = $twig; - } - - protected function buildCodeCollector(): CodeCollector - { - return new CodeCollector($this->blocks, self::BLOCK_TRACK); - } - - protected function buildCode(SiteId $siteId) - { - $config = $this->configProvider->getConfig(); - if (!$config->isConfigured()) { - return null; - } - - $configKey = $siteId->getConfigKey(); - if (!$config->isSiteConfigured($configKey)) { - return null; - } - - $data = [ - 'siteId' => $siteId, - 'config' => $config, - 'piwikSiteId' => $config->getPiwikSiteId($siteId->getConfigKey()), - 'piwikUrl' => $config->getPiwikUrl(), - ]; - - $blocks = $this->buildCodeBlocks($config, $siteId); - - $template = '@PimcoreCore/Analytics/Tracking/Piwik/trackingCode.html.twig'; - - $event = new TrackingDataEvent($config, $siteId, $data, $blocks, $template); - $this->eventDispatcher->dispatch($event, PiwikEvents::CODE_TRACKING_DATA); - - return $this->renderTemplate($event); - } - - private function renderTemplate(TrackingDataEvent $event): string - { - $data = $event->getData(); - $data['blocks'] = $event->getBlocks(); - - $code = $this->twig->render( - $event->getTemplate(), - $data - ); - - $code = trim($code); - - return $code; - } - - private function buildCodeBlocks(Config $config, SiteId $siteId): array - { - $configKey = $siteId->getConfigKey(); - $trackerConfig = $config->getConfigForSite($configKey); - $blockData = $this->buildBlockData($trackerConfig, $config, $siteId); - - $blocks = []; - foreach ($this->blocks as $block) { - $codeBlock = new CodeBlock(); - - if (isset($blockData[$block])) { - $codeBlock->append($blockData[$block]); - } - - $this->getCodeCollector()->enrichCodeBlock($siteId, $codeBlock, $block); - - $blocks[$block] = $codeBlock; - } - - return $blocks; - } - - private function buildBlockData(ConfigObject $trackerConfig, Config $config, SiteId $siteId): array - { - $blockData = []; - - if (!empty($trackerConfig->code_before_init)) { - $blockData[self::BLOCK_BEFORE_SCRIPT] = $trackerConfig->code_before_init; - } - - if (!empty($trackerConfig->code_before_track)) { - $blockData[self::BLOCK_BEFORE_TRACK] = $trackerConfig->code_before_track; - } - - $blockData[self::BLOCK_TRACK] = [ - "_paq.push(['trackPageView']);", - "_paq.push(['enableLinkTracking']);", - ]; - - if (!empty($trackerConfig->code_after_track)) { - $blockData[self::BLOCK_AFTER_TRACK] = $trackerConfig->code_after_track; - } - - $blockData[self::BLOCK_BEFORE_ASYNC] = [ - "_paq.push(['setTrackerUrl', u+'piwik.php']);", - sprintf("_paq.push(['setSiteId', '%d']);", $config->getPiwikSiteId($siteId->getConfigKey())), - ]; - - return $blockData; - } -} diff --git a/lib/Analytics/Piwik/WidgetBroker.php b/lib/Analytics/Piwik/WidgetBroker.php deleted file mode 100644 index 16e0c6a4969..00000000000 --- a/lib/Analytics/Piwik/WidgetBroker.php +++ /dev/null @@ -1,372 +0,0 @@ -configProvider = $configProvider; - $this->apiClient = $apiClient; - $this->cache = $cache; - $this->userLoader = $userLoader; - $this->logger = $logger; - - $optionsResolver = new OptionsResolver(); - $this->configureOptions($optionsResolver); - - $this->options = $optionsResolver->resolve($options); - } - - protected function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'cache' => true, - 'cache_interval' => 'PT3H', - 'exclude_categories' => [ - 'About Piwik', - ], - 'exclude_subcategories' => [], - ]); - - $resolver->setAllowedTypes('exclude_categories', 'array'); - $resolver->setAllowedTypes('exclude_subcategories', 'array'); - $resolver->setAllowedTypes('cache', 'bool'); - $resolver->setAllowedTypes('cache_interval', ['string', 'null']); - } - - /** - * @param string $configKey - * @param string|null $locale - * - * @return array - */ - public function getWidgetReferences(string $configKey, string $locale = null): array - { - $references = []; - foreach ($this->getWidgetData($configKey, $locale) as $widgetId => $widget) { - $references[] = new WidgetReference($widgetId, $this->generateTitle($widget)); - } - - return $references; - } - - public function getWidgetConfig(string $widgetId, string $configKey, string $locale = null, array $urlParams = []): WidgetConfig - { - $config = $this->loadConfig(); - $locale = $this->resolveLocale($locale); - $widgets = $this->getWidgetData($configKey, $locale); - - if (!isset($widgets[$widgetId])) { - throw new \InvalidArgumentException(sprintf('Widget "%s" was not found.', $widgetId)); - } - - $widget = $widgets[$widgetId]; - $url = $this->generateWidgetUrl($config, $configKey, $widget, $locale, $urlParams); - - return new WidgetConfig($widgetId, $widget['name'], $this->generateTitle($widget), $url, $widget); - } - - public function getWidgetData(string $configKey, string $locale = null): array - { - $config = $this->loadConfig(); - if (!$config->isSiteConfigured($configKey)) { - throw new \InvalidArgumentException(sprintf('Site "%s" is not configured', $configKey)); - } - - $locale = $this->resolveLocale($locale); - $cacheKey = $this->generateCacheKey($config->getPiwikSiteId($configKey), $locale); - - if (isset($this->widgets[$cacheKey])) { - return $this->widgets[$cacheKey]; - } - - if ($this->options['cache']) { - if ($widgets = $this->cache->load($cacheKey)) { - $this->widgets[$cacheKey] = $widgets; - - return $widgets; - } - } - - $widgets = $this->loadWidgets($config, $configKey, $locale); - - $this->widgets[$cacheKey] = $widgets; - - if ($this->options['cache']) { - // cache for 3h - $this->cache->save( - $cacheKey, - $widgets, - ['piwik.widgets'], - new \DateInterval($this->options['cache_interval']), - 0, - true - ); - } - - return $widgets; - } - - private function loadConfig(): Config - { - $config = $this->configProvider->getConfig(); - if (!$config->isConfigured()) { - throw new \RuntimeException('Piwik is not configured'); - } - - if (null === $config->getReportToken()) { - throw new \RuntimeException('The report token is not configured'); - } - - return $config; - } - - private function resolveLocale(string $locale = null) - { - if (null !== $user = $this->userLoader->getUser()) { - $locale = $user->getLanguage(); - } - - return $locale; - } - - private function generateCacheKey(int $siteId, string $locale = null) - { - $parts = [(string)$siteId]; - if (!empty($locale)) { - $parts[] = $locale; - } - - return implode('_', $parts); - } - - private function loadWidgets(Config $config, string $configKey, string $locale = null): array - { - $data = $this->loadFromApi($config, $configKey, $locale); - - $categorizedTree = $this->categorizeWidgets($data); - $widgets = $this->flattenCategorizedWidgetTree($categorizedTree); - - return $widgets; - } - - /** - * Categorizes widgets into a category/subcategory tree ordered by respective order - * - * @param array $data - * - * @return array - */ - private function categorizeWidgets(array $data): array - { - $excludeCategories = $this->options['exclude_categories'] ?? []; - $excludeSubCategories = $this->options['exclude_subcategories'] ?? []; - - $tree = []; - foreach ($data as $entry) { - $categoryId = $entry['category'] ? $entry['category']['id'] : '_uncategorized'; - $subcategoryId = $entry['subcategory'] ? $entry['subcategory']['id'] : '_uncategorized'; - - if (in_array($categoryId, $excludeCategories)) { - continue; - } - - if (in_array($subcategoryId, $excludeSubCategories)) { - continue; - } - - $categoryOrder = $entry['category'] ? ($entry['category']['order'] ?? 0) : 0; - $subcategoryOrder = $entry['subcategory'] ? ($entry['subcategory']['order'] ?? 0) : 0; - - if (!isset($tree[$categoryOrder])) { - $tree[$categoryOrder] = []; - } - - if (!isset($tree[$categoryOrder][$subcategoryOrder])) { - $tree[$categoryOrder][$subcategoryOrder] = []; - } - - $tree[$categoryOrder][$subcategoryOrder][] = $entry; - } - - return $tree; - } - - /** - * Flattens category tree into a plain widget list indexed by widget ID - * - * @param array $tree - * - * @return array - */ - private function flattenCategorizedWidgetTree(array $tree): array - { - $categoryOrder = array_keys($tree); - sort($categoryOrder); - - $widgets = []; - foreach ($categoryOrder as $categoryIndex) { - $subcategoryOrder = array_keys($tree[$categoryIndex]); - sort($subcategoryOrder); - - foreach ($subcategoryOrder as $subcategoryIndex) { - foreach ($tree[$categoryIndex][$subcategoryIndex] as $widget) { - $widgets[$widget['uniqueId']] = $widget; - } - } - } - - return $widgets; - } - - private function loadFromApi(Config $config, string $configKey, string $locale = null): array - { - $params = [ - 'module' => 'API', - 'method' => 'API.getWidgetMetadata', - 'format' => 'JSON', - 'idSite' => $config->getPiwikSiteId($configKey), - 'token_auth' => $config->getReportToken(), - ]; - - if (null !== $locale) { - $params['language'] = $locale; - } - - return $this->apiClient->get($params); - } - - private function generateWidgetUrl(Config $config, string $configKey, array $widget, string $locale = null, array $urlParams = []): string - { - $params = array_merge([ - 'module' => 'Widgetize', - 'action' => 'iframe', - 'widget' => 1, - 'period' => 'day', - 'date' => 'yesterday', - 'disableLink' => 1, - 'idSite' => $config->getPiwikSiteId($configKey), - 'token_auth' => $config->getReportToken(), - ], $urlParams); - - $params['moduleToWidgetize'] = $widget['module']; - $params['actionToWidgetize'] = $widget['action']; - - $moduleParams = ['module', 'action']; - foreach ($widget['parameters'] as $key => $value) { - if (in_array($key, $moduleParams)) { - continue; - } - - $params[$key] = $value; - } - - if (null !== $locale) { - $params['language'] = $locale; - } - - $url = sprintf( - '%s?%s', - $config->getPiwikUrl(), - http_build_query($params) - ); - - return $url; - } - - private function generateTitle(array $widget) - { - $title = []; - $category = []; - - if ($widget['category'] && !empty($widget['category']['name'])) { - $category[] = $widget['category']['name']; - } - - if ($widget['subcategory'] && !empty($widget['subcategory']['name'])) { - $category[] = $widget['subcategory']['name']; - } - - if (!empty($category)) { - $title[] = implode(' - ', $category); - } - - $title[] = $widget['name']; - - return implode(' / ', $title); - } -} diff --git a/lib/Event/Analytics/PiwikEvents.php b/lib/Event/Analytics/PiwikEvents.php deleted file mode 100644 index 025037221b8..00000000000 --- a/lib/Event/Analytics/PiwikEvents.php +++ /dev/null @@ -1,41 +0,0 @@ -pattern = $pattern; - } - - /** - * @inheritDoc - */ - public static function fromConfig(array $config) - { - return new static($config['url'] ?? null); - } - - /** - * @inheritDoc - */ - public function getDataProviderKeys(): array - { - return [Piwik::PROVIDER_KEY]; - } - - /** - * @inheritDoc - */ - public function canMatch(): bool - { - return !empty($this->pattern); - } - - /** - * @inheritDoc - */ - public function match(VisitorInfo $visitorInfo): bool - { - $visitData = $visitorInfo->get(Piwik::PROVIDER_KEY); - - if (!$visitData || !is_array($visitData) || empty($visitData)) { - return false; - } - - if (0 === count($visitData['visitedPages'] ?? [])) { - return false; - } - - foreach ($visitData['visitedPages'] as $pageVisit) { - if (preg_match($this->pattern, $pageVisit['url'])) { - return true; - } - } - - return false; - } -} diff --git a/lib/Targeting/DataProvider/Piwik.php b/lib/Targeting/DataProvider/Piwik.php deleted file mode 100644 index 8065b58fcbb..00000000000 --- a/lib/Targeting/DataProvider/Piwik.php +++ /dev/null @@ -1,121 +0,0 @@ -config = $config; - $this->siteIdProvider = $siteIdProvider; - $this->visitorClient = $visitorClient; - $this->logger = $logger; - } - - /** - * @inheritDoc - */ - public function load(VisitorInfo $visitorInfo) - { - if ($visitorInfo->has(self::PROVIDER_KEY)) { - return; - } - - $result = null; - - try { - $this->startStopwatch('Targeting:piwikData', 'targeting'); - - $result = $this->loadData($visitorInfo); - - $this->stopStopwatch('Targeting:piwikData'); - } catch (\Exception $e) { - $this->logger->error($e); - } - - $visitorInfo->set( - self::PROVIDER_KEY, - $result - ); - } - - private function loadData(VisitorInfo $visitorInfo) - { - // no visitor ID - nothing to fetch - if (!$visitorInfo->hasVisitorId()) { - return null; - } - - // piwik is not configured properly - if (!$this->config->isConfigured() || empty($this->config->getReportToken())) { - return null; - } - - $siteId = $this->siteIdProvider->getForRequest($visitorInfo->getRequest()); - $piwikSiteId = $this->config->getPiwikSiteId($siteId->getConfigKey()); - - // piwik site is not configured -> we can't fetch data - if (null === $piwikSiteId) { - return null; - } - - $this->logger->debug('Fetching Piwik visitor profile for ID {visitorId}', [ - 'visitorId' => $visitorInfo->getVisitorId(), - ]); - - return $this->visitorClient->getVisitorProfile( - $piwikSiteId, - $visitorInfo->getVisitorId() - ); - } -} diff --git a/lib/Targeting/EventListener/PiwikVisitorIdListener.php b/lib/Targeting/EventListener/PiwikVisitorIdListener.php deleted file mode 100644 index 7ef4f39578c..00000000000 --- a/lib/Targeting/EventListener/PiwikVisitorIdListener.php +++ /dev/null @@ -1,60 +0,0 @@ -targetingListener = $targetingListener; - } - - public static function getSubscribedEvents(): array - { - return [ - PiwikEvents::CODE_TRACKING_DATA => 'onPiwikTrackingData', - ]; - } - - public function onPiwikTrackingData(TrackingDataEvent $event) - { - if (!$this->targetingListener->isEnabled()) { - return; - } - - $snippet = <<<'EOF' -_paq.push([function() { 'undefined' !== typeof window._ptg && _ptg.api.setVisitorId(this.getVisitorId()); }]); -EOF; - - // sets visitor ID to piwik's user ID - $event->getBlock(Tracker::BLOCK_AFTER_TRACK)->append($snippet); - } -}