public function test_pluginAware_shouldAppendLoadedPluginsAndLanguage() { $result = CacheId::pluginAware('myrandomkey'); $parts = explode('-', $result); $this->assertCount(3, $parts); $this->assertEquals('myrandomkey', $parts[0]); $this->assertEquals(32, strlen($parts[1]), $parts[1] . ' is not a MD5 hash'); $this->assertEquals('en', $parts[2]); }
/** * Returns a list of all available reports. Even not enabled reports will be returned. They will be already sorted * depending on the order and category of the report. * @return \Piwik\Plugin\Report[] * @api */ public function getAllReports() { $reports = $this->getAllReportClasses(); $cacheId = CacheId::languageAware('Reports' . md5(implode('', $reports))); $cache = PiwikCache::getTransientCache(); if (!$cache->contains($cacheId)) { $instances = array(); /** * Triggered to add new reports that cannot be picked up automatically by the platform. * This is useful if the plugin allows a user to create reports / dimensions dynamically. For example * CustomDimensions or CustomVariables. There are a variable number of dimensions in this case and it * wouldn't be really possible to create a report file for one of these dimensions as it is not known * how many Custom Dimensions will exist. * * **Example** * * public function addReport(&$reports) * { * $reports[] = new MyCustomReport(); * } * * @param Report[] $reports An array of reports */ Piwik::postEvent('Report.addReports', array(&$instances)); foreach ($reports as $report) { $instances[] = new $report(); } /** * Triggered to filter / restrict reports. * * **Example** * * public function filterReports(&$reports) * { * foreach ($reports as $index => $report) { * if ($report->getCategory() === 'Actions') {} * unset($reports[$index]); // remove all reports having this action * } * } * } * * @param Report[] $reports An array of reports */ Piwik::postEvent('Report.filterReports', array(&$instances)); usort($instances, array($this, 'sort')); $cache->save($cacheId, $instances); } return $cache->fetch($cacheId); }
public static function getDefaultMetricsDocumentation() { $cacheId = CacheId::pluginAware('DefaultMetricsDocumentation'); $cache = PiwikCache::getTransientCache(); if ($cache->contains($cacheId)) { return $cache->fetch($cacheId); } $translations = array('nb_visits' => 'General_ColumnNbVisitsDocumentation', 'nb_uniq_visitors' => 'General_ColumnNbUniqVisitorsDocumentation', 'nb_actions' => 'General_ColumnNbActionsDocumentation', 'nb_users' => 'General_ColumnNbUsersDocumentation', 'nb_actions_per_visit' => 'General_ColumnActionsPerVisitDocumentation', 'avg_time_on_site' => 'General_ColumnAvgTimeOnSiteDocumentation', 'bounce_rate' => 'General_ColumnBounceRateDocumentation', 'conversion_rate' => 'General_ColumnConversionRateDocumentation', 'avg_time_on_page' => 'General_ColumnAverageTimeOnPageDocumentation', 'nb_hits' => 'General_ColumnPageviewsDocumentation', 'exit_rate' => 'General_ColumnExitRateDocumentation'); /** * Use this event to register translations for metrics documentation processed by your plugin. * * @param string[] $translations The array mapping of column_name => Plugin_TranslationForColumnDocumentation */ Piwik::postEvent('Metrics.getDefaultMetricDocumentationTranslations', array(&$translations)); $translations = array_map(array('\\Piwik\\Piwik', 'translate'), $translations); $cache->save($cacheId, $translations); return $translations; }
/** * Triggers a hook to ask plugins for available Reports. * Returns metadata information about each report (category, name, dimension, metrics, etc.) * * @param string $idSites Comma separated list of website Ids * @param bool|string $period * @param bool|Date $date * @param bool $hideMetricsDoc * @param bool $showSubtableReports * @return array */ public function getReportMetadata($idSites, $period = false, $date = false, $hideMetricsDoc = false, $showSubtableReports = false) { $idSites = Site::getIdSitesFromIdSitesString($idSites); if (!empty($idSites)) { Piwik::checkUserHasViewAccess($idSites); } // as they cache key contains a lot of information there would be an even better cache result by caching parts of // this huge method separately but that makes it also more complicated. leaving it like this for now. $key = $this->buildReportMetadataCacheKey($idSites, $period, $date, $hideMetricsDoc, $showSubtableReports); $key = CacheId::pluginAware($key); $cache = PiwikCache::getTransientCache(); if ($cache->contains($key)) { return $cache->fetch($key); } $parameters = array('idSites' => $idSites, 'period' => $period, 'date' => $date); $availableReports = array(); foreach (Report::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) { 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(); } } } /** * Triggered after all available reports are collected. * * This event can be used to modify the report metadata of reports in other plugins. You * could, for example, add custom metrics to every report or remove reports from the list * of available reports. * * @param array &$availableReports List of all report metadata. Read the {@hook API.getReportMetadata} * docs to see what this array contains. * @param array $parameters Contains the values of the sites and period we are * getting reports for. Some report depend on this data. * For example, Goals reports depend on the site IDs being * request. 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'`. */ Piwik::postEvent('API.getReportMetadata.end', array(&$availableReports, $parameters)); // Sort results to ensure consistent order usort($availableReports, array('self', 'sortReports')); $knownMetrics = array_merge(Metrics::getDefaultMetrics(), Metrics::getDefaultProcessedMetrics()); $columnsToKeep = $this->getColumnsToKeep(); $columnsToRemove = $this->getColumnsToRemove(); foreach ($availableReports as &$availableReport) { // Ensure all metrics have a translation $metrics = $availableReport['metrics']; $cleanedMetrics = array(); // TODO we can remove this once we remove the getReportMetadata event, leaving it here for backwards compatibility foreach ($metrics as $metricId => $metricTranslation) { // When simply the column name was given, ie 'metric' => array( 'nb_visits' ) // $metricTranslation is in this case nb_visits. We look for a known translation. if (is_numeric($metricId) && isset($knownMetrics[$metricTranslation])) { $metricId = $metricTranslation; $metricTranslation = $knownMetrics[$metricTranslation]; } $cleanedMetrics[$metricId] = $metricTranslation; } $availableReport['metrics'] = $cleanedMetrics; // if hide/show columns specified, hide/show metrics & docs $availableReport['metrics'] = $this->hideShowMetricsWithParams($availableReport['metrics'], $columnsToRemove, $columnsToKeep); if (isset($availableReport['processedMetrics'])) { $availableReport['processedMetrics'] = $this->hideShowMetricsWithParams($availableReport['processedMetrics'], $columnsToRemove, $columnsToKeep); } if (isset($availableReport['metricsDocumentation'])) { $availableReport['metricsDocumentation'] = $this->hideShowMetricsWithParams($availableReport['metricsDocumentation'], $columnsToRemove, $columnsToKeep); } // Remove array elements that are false (to clean up API output) foreach ($availableReport as $attributeName => $attributeValue) { if (empty($attributeValue)) { unset($availableReport[$attributeName]); } } // when there are per goal metrics, don't display conversion_rate since it can differ from per goal sum // TODO we should remove this once we remove the getReportMetadata event, leaving it here for backwards compatibility if (isset($availableReport['metricsGoal'])) { unset($availableReport['processedMetrics']['conversion_rate']); unset($availableReport['metricsGoal']['conversion_rate']); } // Processing a uniqueId for each report, // can be used by UIs as a key to match a given report $uniqueId = $availableReport['module'] . '_' . $availableReport['action']; if (!empty($availableReport['parameters'])) { foreach ($availableReport['parameters'] as $key => $value) { $uniqueId .= '_' . $key . '--' . $value; } } $availableReport['uniqueId'] = $uniqueId; // Order is used to order reports internally, but not meant to be used outside unset($availableReport['order']); } // remove subtable reports if (!$showSubtableReports) { foreach ($availableReports as $idx => $report) { if (isset($report['isSubtableReport']) && $report['isSubtableReport']) { unset($availableReports[$idx]); } } } $actualReports = array_values($availableReports); $cache->save($key, $actualReports); return $actualReports; // make sure array has contiguous key values }
private function getCacheId($idSite) { return CacheId::pluginAware('Goals.getGoals.' . $idSite); }
/** * Get all conversion dimensions that are defined by all activated plugins. * @ignore */ public static function getAllDimensions() { $cacheId = CacheId::pluginAware('ConversionDimensions'); $cache = PiwikCache::getTransientCache(); if (!$cache->contains($cacheId)) { $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); $instances = array(); foreach ($plugins as $plugin) { foreach (self::getDimensions($plugin) as $instance) { $instances[] = $instance; } } $cache->save($cacheId, $instances); } return $cache->fetch($cacheId); }
/** * Returns all available user settings. A plugin has to specify a file named `UserSettings.php` containing a class * named `UserSettings` that extends `Piwik\Settings\Plugin\UserSettings` in order to be considered as a plugin * setting. Otherwise the settings for a plugin won't be available. * * @return UserSettings[] An array containing array([pluginName] => [setting instance]). */ public function getAllUserSettings() { $cacheId = CacheId::languageAware('AllUserSettings'); $cache = PiwikCache::getTransientCache(); if (!$cache->contains($cacheId)) { $pluginNames = $this->pluginManager->getActivatedPlugins(); $byPluginName = array(); foreach ($pluginNames as $plugin) { $component = $this->getUserSettings($plugin); if (!empty($component)) { $byPluginName[$plugin] = $component; } } $cache->save($cacheId, $byPluginName); } return $cache->fetch($cacheId); }
private static function getCacheId() { return CacheId::pluginAware('WidgetsList'); }
/** * Returns a list of all available reports. Even not enabled reports will be returned. They will be already sorted * depending on the order and category of the report. * @return \Piwik\Plugin\Report[] * @api */ public static function getAllReports() { $reports = self::getAllReportClasses(); $cacheId = CacheId::languageAware('Reports' . md5(implode('', $reports))); $cache = PiwikCache::getTransientCache(); if (!$cache->contains($cacheId)) { $instances = array(); foreach ($reports as $report) { $instances[] = new $report(); } usort($instances, array('self', 'sort')); $cache->save($cacheId, $instances); } return $cache->fetch($cacheId); }
/** * Gets an instance of all available visit, action and conversion dimension. * @return Dimension[] */ public static function getAllDimensions() { $cacheId = CacheId::pluginAware('AllDimensions'); $cache = PiwikCache::getTransientCache(); if (!$cache->contains($cacheId)) { $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); $instances = array(); /** * Triggered to add new dimensions that cannot be picked up automatically by the platform. * This is useful if the plugin allows a user to create reports / dimensions dynamically. For example * CustomDimensions or CustomVariables. There are a variable number of dimensions in this case and it * wouldn't be really possible to create a report file for one of these dimensions as it is not known * how many Custom Dimensions will exist. * * **Example** * * public function addDimension(&$dimensions) * { * $dimensions[] = new MyCustomDimension(); * } * * @param Dimension[] $reports An array of dimensions */ Piwik::postEvent('Dimension.addDimensions', array(&$instances)); foreach ($plugins as $plugin) { foreach (self::getDimensions($plugin) as $instance) { $instances[] = $instance; } } /** * Triggered to filter / restrict dimensions. * * **Example** * * public function filterDimensions(&$dimensions) * { * foreach ($dimensions as $index => $dimension) { * if ($dimension->getName() === 'Page URL') {} * unset($dimensions[$index]); // remove this dimension * } * } * } * * @param Dimension[] $dimensions An array of dimensions */ Piwik::postEvent('Dimension.filterDimensions', array(&$instances)); $cache->save($cacheId, $instances); } return $cache->fetch($cacheId); }
private function setDimensionsWithOnNewVisit($dimensionOnNewVisitResults) { $dimensions = array(); foreach ($dimensionOnNewVisitResults as $onNewVisitResult) { $dim = $this->getMock('Piwik\\Plugin\\Dimension', array('shouldForceNewVisit', 'getColumnName')); $dim->expects($this->any())->method('shouldForceNewVisit')->will($this->returnValue($onNewVisitResult)); $dimensions[] = $dim; } $cache = Cache::getTransientCache(); $cache->save(CacheId::pluginAware('VisitDimensions'), $dimensions); Visit::$dimensions = null; }
public function getSegmentsMetadata($idSites = array(), $_hideImplementationData = true) { if (empty($idSites)) { Piwik::checkUserHasSomeViewAccess(); } else { Piwik::checkUserHasViewAccess($idSites); } $isNotAnonymous = !Piwik::isUserIsAnonymous(); $sites = is_array($idSites) ? implode('.', $idSites) : (int) $idSites; $cache = Cache::getTransientCache(); $cachKey = 'API.getSegmentsMetadata' . $sites . '_' . (int) $_hideImplementationData . '_' . (int) $isNotAnonymous; $cachKey = CacheId::pluginAware($cachKey); if ($cache->contains($cachKey)) { return $cache->fetch($cachKey); } $metadata = new SegmentMetadata(); $segments = $metadata->getSegmentsMetadata($idSites, $_hideImplementationData, $isNotAnonymous); $cache->save($cachKey, $segments); return $segments; }
/** * Triggers a hook to ask plugins for available Reports. * Returns metadata information about each report (category, name, dimension, metrics, etc.) * * @param int $idSite * @param bool|string $period * @param bool|Date $date * @param bool $hideMetricsDoc * @param bool $showSubtableReports * @return array */ public function getReportMetadata($idSite, $period = false, $date = false, $hideMetricsDoc = false, $showSubtableReports = false) { Piwik::checkUserHasViewAccess($idSite); // as they cache key contains a lot of information there would be an even better cache result by caching parts of // this huge method separately but that makes it also more complicated. leaving it like this for now. $key = $this->buildReportMetadataCacheKey($idSite, $period, $date, $hideMetricsDoc, $showSubtableReports); $key = CacheId::pluginAware($key); $cache = PiwikCache::getTransientCache(); if ($cache->contains($key)) { return $cache->fetch($key); } $parameters = array('idSite' => $idSite, 'period' => $period, 'date' => $date); $availableReports = array(); foreach ($this->reportsProvider->getAllReports() as $report) { $report->configureReportMetadata($availableReports, $parameters); } foreach ($availableReports as &$availableReport) { if ($hideMetricsDoc) { unset($availableReport['metricsDocumentation']); } } /** * Triggered after all available reports are collected. * * This event can be used to modify the report metadata of reports in other plugins. You * could, for example, add custom metrics to every report or remove reports from the list * of available reports. * * @param array &$availableReports List of all report metadata. Read the {@hook API.getReportMetadata} * docs to see what this array contains. * @param array $parameters Contains the values of the sites and period we are * getting reports for. Some report depend on this data. * For example, Goals reports depend on the site IDs being * request. 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'`. */ Piwik::postEvent('API.getReportMetadata.end', array(&$availableReports, $parameters)); // Sort results to ensure consistent order usort($availableReports, array($this, 'sortReports')); $knownMetrics = array_merge(Metrics::getDefaultMetrics(), Metrics::getDefaultProcessedMetrics()); $columnsToKeep = $this->getColumnsToKeep(); $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(); // TODO we can remove this once we remove the getReportMetadata event, leaving it here for backwards compatibility foreach ($metrics as $metricId => $metricTranslation) { // When simply the column name was given, ie 'metric' => array( 'nb_visits' ) // $metricTranslation is in this case nb_visits. We look for a known translation. if (is_numeric($metricId) && isset($knownMetrics[$metricTranslation])) { $metricId = $metricTranslation; $metricTranslation = $knownMetrics[$metricTranslation]; } $cleanedMetrics[$metricId] = $metricTranslation; } $availableReport['metrics'] = $cleanedMetrics; // if hide/show columns specified, hide/show metrics & docs $availableReport['metrics'] = $this->hideShowMetricsWithParams($availableReport['metrics'], $columnsToRemove, $columnsToKeep); if (isset($availableReport['processedMetrics'])) { $availableReport['processedMetrics'] = $this->hideShowMetricsWithParams($availableReport['processedMetrics'], $columnsToRemove, $columnsToKeep); } if (isset($availableReport['metricsDocumentation'])) { $availableReport['metricsDocumentation'] = $this->hideShowMetricsWithParams($availableReport['metricsDocumentation'], $columnsToRemove, $columnsToKeep); } // Remove array elements that are false (to clean up API output) foreach ($availableReport as $attributeName => $attributeValue) { if (empty($attributeValue)) { unset($availableReport[$attributeName]); } } // when there are per goal metrics, don't display conversion_rate since it can differ from per goal sum // TODO we should remove this once we remove the getReportMetadata event, leaving it here for backwards compatibility if (isset($availableReport['metricsGoal'])) { unset($availableReport['processedMetrics']['conversion_rate']); unset($availableReport['metricsGoal']['conversion_rate']); } // Processing a uniqueId for each report, // can be used by UIs as a key to match a given report $uniqueId = $availableReport['module'] . '_' . $availableReport['action']; if (!empty($availableReport['parameters'])) { foreach ($availableReport['parameters'] as $key => $value) { $uniqueId .= '_' . $key . '--' . $value; } } $availableReport['uniqueId'] = $uniqueId; // Order is used to order reports internally, but not meant to be used outside unset($availableReport['order']); } // remove subtable reports if (!$showSubtableReports) { foreach ($availableReports as $idx => $report) { if (isset($report['isSubtableReport']) && $report['isSubtableReport']) { unset($availableReports[$idx]); } } } $actualReports = array_values($availableReports); $cache->save($key, $actualReports); return $actualReports; // make sure array has contiguous key values }