| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\API; |
|
|
| use Piwik\API\Proxy; |
| use Piwik\API\Request; |
| use Piwik\ArchiveProcessor\Rules; |
| use Piwik\Cache; |
| use Piwik\CacheId; |
| use Piwik\Category\CategoryList; |
| use Piwik\Common; |
| use Piwik\Config; |
| use Piwik\Container\StaticContainer; |
| use Piwik\DataTable; |
| use Piwik\DataTable\Filter\ColumnDelete; |
| use Piwik\Date; |
| use Piwik\Http\BadRequestException; |
| use Piwik\IP; |
| use Piwik\Period; |
| use Piwik\Piwik; |
| use Piwik\Plugin\SettingsProvider; |
| use Piwik\Plugins\API\DataTable\MergeDataTables; |
| use Piwik\Plugins\CorePluginsAdmin\SettingsMetadata; |
| use Piwik\Request\AuthenticationToken; |
| use Piwik\Segment; |
| use Piwik\Site; |
| use Piwik\Translation\Translator; |
| use Piwik\Measurable\Type\TypeManager; |
| use Piwik\Version; |
| use Piwik\Widget\WidgetsList; |
|
|
| require_once PIWIK_INCLUDE_PATH . '/core/Config.php'; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| class API extends \Piwik\Plugin\API |
| { |
| |
| |
| |
| private $settingsProvider; |
|
|
| |
| |
| |
| private $processedReport; |
|
|
| |
| |
| |
| |
| public static $_autoSuggestLookBack = 60; |
|
|
| public function __construct(SettingsProvider $settingsProvider, ProcessedReport $processedReport) |
| { |
| $this->settingsProvider = $settingsProvider; |
| $this->processedReport = $processedReport; |
| } |
|
|
| |
| |
| |
| |
| |
| public function getMatomoVersion(): string |
| { |
| Piwik::checkUserHasSomeViewAccess(); |
| return Version::VERSION; |
| } |
|
|
| |
| |
| |
| |
| |
| public function getPhpVersion(): array |
| { |
| Piwik::checkUserHasSuperUserAccess(); |
| return [ |
| 'version' => PHP_VERSION, |
| 'major' => PHP_MAJOR_VERSION, |
| 'minor' => PHP_MINOR_VERSION, |
| 'release' => PHP_RELEASE_VERSION, |
| 'versionId' => PHP_VERSION_ID, |
| 'extra' => PHP_EXTRA_VERSION, |
| ]; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getPiwikVersion(): string |
| { |
| return $this->getMatomoVersion(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getIpFromHeader(): string |
| { |
| Piwik::checkUserHasSomeViewAccess(); |
| return IP::getIpFromHeader(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getSettings() |
| { |
| return Config::getInstance()->APISettings; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getAvailableMeasurableTypes() |
| { |
| Piwik::checkUserHasSomeViewAccess(); |
|
|
| $typeManager = new TypeManager(); |
| $types = $typeManager->getAllTypes(); |
|
|
| $available = array(); |
| foreach ($types as $type) { |
| $measurableSettings = $this->settingsProvider->getAllMeasurableSettings($idSite = 0, $type->getId()); |
|
|
| $settingsMetadata = new SettingsMetadata(); |
|
|
| $available[] = array( |
| 'id' => $type->getId(), |
| 'name' => Piwik::translate($type->getName()), |
| 'description' => Piwik::translate($type->getDescription()), |
| 'longDescription' => Piwik::translate($type->getLongDescription()), |
| 'howToSetupUrl' => $type->getHowToSetupUrl(), |
| 'settings' => $settingsMetadata->formatSettings($measurableSettings), |
| ); |
| } |
|
|
| return $available; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public function getSegmentsMetadata($idSites = array(), $_hideImplementationData = true, $_showAllSegments = false): array |
| { |
| if (empty($idSites)) { |
| Piwik::checkUserHasSomeViewAccess(); |
| } else { |
| $idSites = Site::getIdSitesFromIdSitesString($idSites, false, true); |
| Piwik::checkUserHasViewAccess($idSites); |
| } |
|
|
| $isNotAnonymous = !Piwik::isUserIsAnonymous(); |
|
|
| $sites = (is_array($idSites) ? implode('.', $idSites) : (int) $idSites); |
| $cache = Cache::getTransientCache(); |
| $cacheKey = 'API.getSegmentsMetadata' . $sites . '_' . (int) $_hideImplementationData . '_' . (int) $isNotAnonymous . '_' . (int) $_showAllSegments; |
| $cacheKey = CacheId::pluginAware($cacheKey); |
|
|
| if ($cache->contains($cacheKey)) { |
| return $cache->fetch($cacheKey); |
| } |
|
|
| $metadata = new SegmentMetadata(); |
| $segments = $metadata->getSegmentsMetadata($idSites, $_hideImplementationData, $isNotAnonymous, $_showAllSegments); |
|
|
| $cache->save($cacheKey, $segments); |
|
|
| return $segments; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| protected function getSegmentValuesFromVisitorLog($segmentName, $table) |
| { |
| |
| $values = $table->getColumn($segmentName); |
|
|
| |
| $valuesBis = $table->getColumnsStartingWith($segmentName . ColumnDelete::APPEND_TO_COLUMN_NAME_TO_KEEP); |
| $values = array_merge($values, $valuesBis); |
|
|
| |
| if (empty(array_filter($values)) && $this->doesSegmentNeedActionsData($segmentName)) { |
| foreach ($table->getRows() as $row) { |
| foreach ($row->getColumn('actionDetails') as $actionRow) { |
| if (isset($actionRow[$segmentName])) { |
| $values[] = $actionRow[$segmentName]; |
| } |
| } |
| } |
| } |
|
|
| return $values; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getMetadata( |
| $idSite, |
| string $apiModule, |
| string $apiAction, |
| $apiParameters = [], |
| $language = false, |
| $period = false, |
| $date = false, |
| $hideMetricsDoc = false, |
| $showSubtableReports = false |
| ) { |
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| if ($language) { |
| |
| $translator = StaticContainer::get('Piwik\Translation\Translator'); |
| $translator->setCurrentLanguage($language); |
| } |
|
|
| return $this->processedReport->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language, $period, $date, $hideMetricsDoc, $showSubtableReports); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getReportMetadata( |
| $idSites = '', |
| $period = false, |
| $date = false, |
| $hideMetricsDoc = false, |
| $showSubtableReports = false, |
| $idSite = false |
| ) { |
| if (empty($idSite) && !empty($idSites)) { |
| if (is_array($idSites)) { |
| $idSite = array_shift($idSites); |
| } else { |
| $idSite = $idSites; |
| } |
| } elseif (empty($idSite) && empty($idSites)) { |
| throw new \Exception('Calling API.getReportMetadata without any idSite is no longer supported since Matomo 3.0.0. Please specify at least one idSite via the "idSite" parameter.'); |
| } |
|
|
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $metadata = $this->processedReport->getReportMetadata($idSite, $period, $date, $hideMetricsDoc, $showSubtableReports); |
| return $metadata; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getProcessedReport( |
| $idSite, |
| $period, |
| $date, |
| $apiModule, |
| $apiAction, |
| $segment = false, |
| $apiParameters = false, |
| $idGoal = false, |
| $language = false, |
| $showTimer = true, |
| $hideMetricsDoc = false, |
| $idSubtable = false, |
| $showRawMetrics = false, |
| $format_metrics = null, |
| $idDimension = false |
| ) { |
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $processed = $this->processedReport->getProcessedReport( |
| $idSite, |
| $period, |
| $date, |
| $apiModule, |
| $apiAction, |
| $segment, |
| $apiParameters, |
| $idGoal, |
| $language, |
| $showTimer, |
| $hideMetricsDoc, |
| $idSubtable, |
| $showRawMetrics, |
| $format_metrics, |
| $idDimension |
| ); |
|
|
| return $processed; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getReportPagesMetadata($idSite) |
| { |
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $widgetsList = WidgetsList::get(); |
| $categoryList = CategoryList::get(); |
| $metadata = new WidgetMetadata(); |
|
|
| return $metadata->getPagesMetadata($categoryList, $widgetsList); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getWidgetMetadata($idSite) |
| { |
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $widgetsList = WidgetsList::get(); |
| $categoryList = CategoryList::get(); |
| $metadata = new WidgetMetadata(); |
|
|
| return $metadata->getWidgetMetadata($categoryList, $widgetsList); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function get($idSite, $period, $date, $segment = false, $columns = false) |
| { |
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $columns = Piwik::getArrayFromApiParameter($columns); |
|
|
| |
| $columnsMap = array(); |
| foreach ($columns as $column) { |
| $columnsMap[$column] = true; |
| } |
|
|
| |
| $columnsByPlugin = array(); |
| $meta = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite, $period, $date); |
| foreach ($meta as $reportMeta) { |
| |
| if ( |
| $reportMeta['action'] == 'get' |
| && !isset($reportMeta['parameters']) |
| && $reportMeta['module'] != 'API' |
| && !empty($reportMeta['metrics']) |
| ) { |
| $plugin = $reportMeta['module']; |
| $allMetrics = array_merge($reportMeta['metrics'], (@$reportMeta['processedMetrics'] ?: [])); |
| foreach ($allMetrics as $column => $columnTranslation) { |
| |
| if ( |
| isset($columnsMap[$column]) |
| |
| || empty($columnsMap) |
| ) { |
| $columnsByPlugin[$plugin][] = $column; |
| } |
| } |
| } |
| } |
| krsort($columnsByPlugin); |
|
|
| $mergedDataTable = null; |
| $params = compact('idSite', 'period', 'date', 'segment'); |
| foreach ($columnsByPlugin as $plugin => $columns) { |
| |
| $className = Request::getClassNameAPI($plugin); |
| $params['columns'] = implode(',', $columns); |
| $dataTable = Proxy::getInstance()->call($className, 'get', $params); |
|
|
| $dataTable->filter(function (DataTable $table) { |
| $table->clearQueuedFilters(); |
| }); |
|
|
| |
| if ($mergedDataTable === null) { |
| $mergedDataTable = $dataTable; |
| } else { |
| $merger = new MergeDataTables(true); |
| $merger->mergeDataTables($mergedDataTable, $dataTable); |
| } |
| } |
|
|
| if ( |
| !empty($columnsMap) |
| && !empty($mergedDataTable) |
| ) { |
| $mergedDataTable->queueFilter('ColumnDelete', array(false, array_keys($columnsMap))); |
| } |
|
|
| return $mergedDataTable ?? new DataTable(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false, $labelSeries = false, $showGoalMetricsForGoal = false) |
| { |
| |
| $idSite = (int) $idSite; |
| $site = new Site($idSite); |
|
|
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $apiParameters = array(); |
| $entityNames = StaticContainer::get('entities.idNames'); |
| foreach ($entityNames as $entityName) { |
| if ($entityName === 'idGoal' && is_numeric($idGoal)) { |
| $apiParameters['idGoal'] = $idGoal; |
| } elseif ($entityName === 'idDimension' && $idDimension) { |
| $apiParameters['idDimension'] = $idDimension; |
| } else { |
| |
| |
| |
| $idEntity = Common::getRequestVar($entityName, 0, 'int'); |
| if ($idEntity > 0) { |
| $apiParameters[$entityName] = $idEntity; |
| } |
| } |
| } |
|
|
| $rowEvolution = new RowEvolution(); |
| return $rowEvolution->getRowEvolution( |
| $idSite, |
| $period, |
| $date, |
| $apiModule, |
| $apiAction, |
| $label, |
| $segment, |
| $column, |
| $language, |
| $apiParameters, |
| $legendAppendMetric, |
| $labelUseAbsoluteUrl, |
| $labelSeries, |
| $showGoalMetricsForGoal |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function getBulkRequest($urls) |
| { |
| if (empty($urls) || !is_array($urls)) { |
| return []; |
| } |
|
|
| $limit = BulkRequestLimit::getCurrentLimit(); |
| if ($limit > -1 && count($urls) > $limit) { |
| throw new BadRequestException(Piwik::translate('General_MaximumNumberOfBulkRequestUrlsIs', [$limit])); |
| } |
|
|
| $request = \Piwik\Request::fromRequest(); |
| $queryParameters = $request->getParameters(); |
| unset($queryParameters['urls']); |
|
|
| $authToken = StaticContainer::get(AuthenticationToken::class); |
| $rootIsSessionToken = $authToken->isSessionToken(); |
| $rootTokenAuth = $authToken->getAuthToken(); |
|
|
| $result = []; |
| foreach ($urls as $url) { |
| $nestedRequest = \Piwik\Request::fromQueryString($url); |
|
|
| $this->checkNestedRequestAuthMatchesRoot($nestedRequest, $rootIsSessionToken, $rootTokenAuth); |
|
|
| $params = $nestedRequest->getParameters(); |
| $params['format'] = 'json'; |
|
|
| $params += $queryParameters; |
|
|
| $method = $params['method'] ?? ''; |
|
|
| if ( |
| !empty($method) && is_string($method) && |
| preg_replace('/[^\w\.]+/', '', Common::sanitizeInputValue($method)) === 'API.getBulkRequest' |
| ) { |
| continue; |
| } |
|
|
| $req = new Request($params); |
| $result[] = json_decode($req->process(), true); |
| } |
| return $result; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function checkNestedRequestAuthMatchesRoot( |
| \Piwik\Request $nestedRequest, |
| bool $rootIsSessionToken, |
| #[\SensitiveParameter] |
| string $rootTokenAuth |
| ): void { |
| $params = $nestedRequest->getParameters(); |
|
|
| if ( |
| array_key_exists('force_api_session', $params) |
| && $nestedRequest->getBoolParameter('force_api_session', false) !== $rootIsSessionToken |
| ) { |
| throw new BadRequestException(Piwik::translate('General_ConflictingAuthenticationParametersProvided')); |
| } |
|
|
| if ( |
| $rootIsSessionToken |
| && array_key_exists('token_auth', $params) |
| && $nestedRequest->getStringParameter('token_auth', '') !== $rootTokenAuth |
| ) { |
| throw new BadRequestException(Piwik::translate('General_ConflictingAuthenticationParametersProvided')); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| public function isPluginActivated($pluginName): bool |
| { |
| Piwik::checkUserHasSomeViewAccess(); |
| return \Piwik\Plugin\Manager::getInstance()->isPluginActivated($pluginName); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function getSuggestedValuesForSegment($segmentName, $idSite) |
| { |
| if (empty(Config::getInstance()->General['enable_segment_suggested_values'])) { |
| return array(); |
| } |
|
|
| Piwik::checkUserHasViewAccess($idSite); |
|
|
| $maxSuggestionsToReturn = 30; |
| $segment = $this->findSegment($segmentName, $idSite); |
|
|
| |
| $suggestedValuesCallbackRequiresTable = false; |
|
|
| if (!empty($segment['suggestedValuesApi']) && is_string($segment['suggestedValuesApi']) && !Rules::isBrowserTriggerEnabled()) { |
| if ($idSite === 'all') { |
| $now = Date::now()->setTimezone(\Piwik\Plugins\SitesManager\API::getInstance()->getDefaultTimezone()); |
| } else { |
| $now = Date::now()->setTimezone(Site::getTimezoneFor($idSite)); |
| } |
| if (self::$_autoSuggestLookBack != 60) { |
| |
| |
| $now = $now->subDay(self::$_autoSuggestLookBack - 20); |
| } |
| |
| |
| $period = 'year'; |
| $date = $now->toString(); |
| if ($now->toString('m') == '01') { |
| if (Rules::isArchivingDisabledFor([$idSite], new Segment('', [$idSite]), 'range')) { |
| $date = $now->subYear(1)->toString(); |
| } else { |
| $period = 'range'; |
| $date = $now->subMonth(1)->toString() . ',' . $now->addDay(1)->toString(); |
| } |
| } |
|
|
| $apiParts = explode('.', $segment['suggestedValuesApi']); |
| $meta = $this->getMetadata($idSite, $apiParts[0], $apiParts[1]); |
| $flat = !empty($meta[0]['actionToLoadSubTables']) && $meta[0]['actionToLoadSubTables'] == $apiParts[1]; |
|
|
| $table = Request::processRequest($segment['suggestedValuesApi'], [ |
| 'idSite' => $idSite, |
| 'period' => $period, |
| 'date' => $date, |
| 'segment' => '', |
| 'filter_offset' => 0, |
| 'flat' => (int) $flat, |
| 'filter_limit' => $maxSuggestionsToReturn, |
| ]); |
|
|
| if ($table && $table instanceof DataTable && $table->getRowsCount()) { |
| $values = []; |
| foreach ($table->getRowsWithoutSummaryRow() as $row) { |
| |
| $segment = $row->getMetadata('segment'); |
| $remove = [ |
| $segmentName . Segment\SegmentExpression::MATCH_EQUAL, |
| $segmentName . Segment\SegmentExpression::MATCH_STARTS_WITH, |
| ]; |
| |
| |
| if (!empty($segment) && preg_match('/^' . implode('|', $remove) . '/', $segment)) { |
| $values[] = urldecode(urldecode(str_replace($remove, '', $segment))); |
| } |
| } |
|
|
| $values = array_slice($values, 0, $maxSuggestionsToReturn); |
| $values = array_map(['Piwik\Common', 'unsanitizeInputValue'], $values); |
| return $values; |
| } |
| } |
|
|
| if (isset($segment['suggestedValuesCallback'])) { |
| $suggestedValuesCallbackRequiresTable = $this->doesSuggestedValuesCallbackNeedData( |
| $segment['suggestedValuesCallback'] |
| ); |
|
|
| if (!$suggestedValuesCallbackRequiresTable) { |
| return call_user_func($segment['suggestedValuesCallback'], $idSite, $maxSuggestionsToReturn); |
| } |
| } |
|
|
| |
| if (!Period\Factory::isPeriodEnabledForAPI('range')) { |
| return []; |
| } |
|
|
| if (!empty($segment['unionOfSegments'])) { |
| $values = []; |
| foreach ($segment['unionOfSegments'] as $unionSegmentName) { |
| $unionSegment = $this->findSegment($unionSegmentName, $idSite, $_showAllSegments = true); |
|
|
| try { |
| $result = $this->getSuggestedValuesForSegmentName($idSite, $unionSegment, $maxSuggestionsToReturn); |
| if (!empty($result)) { |
| $values = array_merge($result, $values); |
| } |
| } catch (\Exception $e) { |
| |
| } |
| } |
|
|
| if (empty($values)) { |
| throw new \Exception("There was no data to suggest for $segmentName"); |
| } |
| } else { |
| $values = $this->getSuggestedValuesForSegmentName($idSite, $segment, $maxSuggestionsToReturn); |
| } |
|
|
| if ($segment['needsMostFrequentValues']) { |
| $values = $this->getMostFrequentValues($values); |
| } |
| $values = array_slice($values, 0, $maxSuggestionsToReturn); |
| $values = array_map(['Piwik\Common', 'unsanitizeInputValue'], $values); |
|
|
| return $values; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getPagesComparisonsDisabledFor() |
| { |
| $pages = []; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Piwik::postEvent('API.getPagesComparisonsDisabledFor', [&$pages]); |
|
|
| return $pages; |
| } |
|
|
| |
| |
| |
| |
| |
| private function findSegment($segmentName, $idSite, bool $_showAllSegments = false) |
| { |
| $segmentsMetadata = $this->getSegmentsMetadata($idSite, $_hideImplementationData = false, $_showAllSegments); |
|
|
| foreach ($segmentsMetadata as $segmentMetadata) { |
| if ($segmentMetadata['segment'] == $segmentName) { |
| return $segmentMetadata; |
| } |
| } |
|
|
| throw new \Exception("Requested segment $segmentName not found."); |
| } |
|
|
| |
| |
| |
| |
| |
| private function getSuggestedValuesForSegmentName($idSite, $segment, $maxSuggestionsToReturn) |
| { |
| $startDate = Date::now()->subDay(self::$_autoSuggestLookBack)->toString(); |
| $requestLastVisits = [ |
| 'method' => 'Live.getLastVisitsDetails', |
| 'idSite' => $idSite, |
| 'period' => 'range', |
| 'date' => $startDate . ',today', |
| 'format' => 'original', |
| 'serialize' => 0, |
| 'flat' => 1, |
| ]; |
|
|
| $segmentName = $segment['segment']; |
|
|
| |
| |
| $requestLastVisits['segment'] = $segmentName . urlencode('!='); |
|
|
| |
| if ($this->doesSegmentNeedActionsData($segmentName)) { |
| $requestLastVisits['filter_limit'] = 400; |
| } else { |
| $requestLastVisits['doNotFetchActions'] = 1; |
| $requestLastVisits['filter_limit'] = 800; |
| } |
|
|
| $request = new Request($requestLastVisits); |
| $table = $request->process(); |
|
|
| if (empty($table)) { |
| throw new \Exception("There was no data to suggest for $segmentName"); |
| } |
|
|
| if ( |
| isset($segment['suggestedValuesCallback']) && |
| $this->doesSuggestedValuesCallbackNeedData($segment['suggestedValuesCallback']) |
| ) { |
| $values = call_user_func($segment['suggestedValuesCallback'], $idSite, $maxSuggestionsToReturn, $table); |
| } else { |
| $values = $this->getSegmentValuesFromVisitorLog($segmentName, $table); |
| } |
|
|
| return $values; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getGlossaryReports($idSite) |
| { |
| $glossary = StaticContainer::get('Piwik\Plugins\API\Glossary'); |
| return $glossary->reportsGlossary($idSite); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getGlossaryMetrics($idSite) |
| { |
| $glossary = StaticContainer::get('Piwik\Plugins\API\Glossary'); |
| return $glossary->metricsGlossary($idSite); |
| } |
|
|
| |
| |
| |
| protected function doesSegmentNeedActionsData(string $segmentName): bool |
| { |
| |
| $segmentsNeedActionsInfo = array('visitConvertedGoalId', 'visitConvertedGoalName', |
| 'pageUrl', 'pageTitle', 'siteSearchKeyword', 'siteSearchCategory', 'siteSearchCount', |
| 'entryPageTitle', 'entryPageUrl', 'exitPageTitle', 'exitPageUrl', |
| 'outlinkUrl', 'downloadUrl', 'eventUrl', 'orderId', 'revenueOrder', 'revenueAbandonedCart', 'productViewName', 'productViewSku', 'productViewPrice', |
| 'productViewCategory1', 'productViewCategory2', 'productViewCategory3', 'productViewCategory4', 'productViewCategory5', |
| ); |
| $isCustomVariablePage = stripos($segmentName, 'customVariablePage') !== false; |
| $isEventSegment = stripos($segmentName, 'event') !== false; |
| $isContentSegment = stripos($segmentName, 'content') !== false; |
| $doesSegmentNeedActionsInfo = in_array($segmentName, $segmentsNeedActionsInfo) || $isCustomVariablePage || $isEventSegment || $isContentSegment; |
| return $doesSegmentNeedActionsInfo; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| private function getMostFrequentValues($values) |
| { |
| |
| $values = array_filter($values, 'strlen'); |
|
|
| |
| foreach ($values as &$value) { |
| if (is_numeric($value)) { |
| $value = (string)round($value, 3); |
| } |
| } |
| |
| $values = array_count_values($values); |
|
|
| |
| $sortArray = []; |
|
|
| foreach ($values as $val => $count) { |
| $sortArray[] = [ |
| 'value' => $val, |
| 'count' => $count, |
| ]; |
| } |
|
|
| usort($sortArray, function ($a, $b) { |
| if ($a['count'] == $b['count']) { |
| return strcmp($a['value'], $b['value']); |
| } |
|
|
| return $a['count'] > $b['count'] ? -1 : 1; |
| }); |
|
|
| return array_column($sortArray, 'value'); |
| } |
|
|
| |
| |
| |
| private function doesSuggestedValuesCallbackNeedData($suggestedValuesCallback): bool |
| { |
| if ( |
| is_string($suggestedValuesCallback) |
| && strpos($suggestedValuesCallback, '::') !== false |
| ) { |
| $suggestedValuesCallback = explode('::', $suggestedValuesCallback); |
| } |
|
|
| if (is_array($suggestedValuesCallback)) { |
| $methodMetadata = new \ReflectionMethod($suggestedValuesCallback[0], $suggestedValuesCallback[1]); |
| } else { |
| $methodMetadata = new \ReflectionFunction($suggestedValuesCallback); |
| } |
|
|
| return $methodMetadata->getNumberOfParameters() >= 3; |
| } |
| } |
|
|
|
|
| |
| class Plugin extends \Piwik\Plugin |
| { |
| public function __construct() |
| { |
| |
| parent::__construct($pluginName = 'API'); |
| } |
|
|
| |
| |
| |
| public function registerEvents() |
| { |
| return array( |
| 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', |
| 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', |
| 'Template.jsGlobalVariables' => 'getJsGlobalVariables', |
| 'Platform.initialized' => 'detectIsApiRequest', |
| ); |
| } |
|
|
| public function detectIsApiRequest(): void |
| { |
| Request::setIsRootRequestApiRequest(Request::getMethodIfApiRequest($request = null)); |
| } |
|
|
| |
| |
| |
| public function getStylesheetFiles(&$stylesheets): void |
| { |
| $stylesheets[] = "plugins/API/stylesheets/listAllAPI.less"; |
| $stylesheets[] = "plugins/API/stylesheets/glossary.less"; |
| } |
|
|
| |
| |
| |
| public function getJsGlobalVariables(&$out): void |
| { |
| $bulkRequestLimit = BulkRequestLimit::getCurrentLimit(); |
| $out .= "piwik.apiBulkRequestLimit = $bulkRequestLimit;\n"; |
|
|
| |
| |
| |
| if (Piwik::getModule() === 'API' && Piwik::getAction() === 'glossary' && \Piwik\Request::fromRequest()->getBoolParameter('widget', false)) { |
| $out .= "piwik.isPagesComparisonApiDisabled = true;\n"; |
| } |
| } |
|
|
| |
| |
| |
| public function getClientSideTranslationKeys(&$translations): void |
| { |
| $translations[] = 'API_Glossary'; |
| $translations[] = 'API_LearnAboutCommonlyUsedTerms2'; |
| } |
| } |
|
|